summaryrefslogtreecommitdiff
path: root/indra/newview
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview')
-rwxr-xr-xindra/newview/CMakeLists.txt22
-rw-r--r--indra/newview/VIEWER_VERSION.txt2
-rwxr-xr-xindra/newview/app_settings/settings.xml35
-rwxr-xr-xindra/newview/app_settings/shaders/class1/avatar/objectSkinV.glsl3
-rwxr-xr-xindra/newview/app_settings/shaders/class1/deferred/bumpF.glsl24
-rwxr-xr-xindra/newview/installers/windows/installer_template.nsi4
-rwxr-xr-xindra/newview/llaccountingcostmanager.cpp87
-rwxr-xr-xindra/newview/llaccountingcostmanager.h7
-rwxr-xr-xindra/newview/llagent.cpp2
-rwxr-xr-xindra/newview/llagent.h3
-rwxr-xr-xindra/newview/llagentdata.cpp1
-rwxr-xr-xindra/newview/llagentdata.h1
-rwxr-xr-xindra/newview/llaisapi.cpp22
-rwxr-xr-xindra/newview/llaisapi.h2
-rwxr-xr-xindra/newview/llappcorehttp.cpp26
-rwxr-xr-xindra/newview/llappcorehttp.h2
-rwxr-xr-xindra/newview/llappearancemgr.cpp197
-rwxr-xr-xindra/newview/llappearancemgr.h8
-rwxr-xr-xindra/newview/llappviewer.cpp72
-rwxr-xr-xindra/newview/llappviewermacosx.cpp50
-rwxr-xr-xindra/newview/llavatariconctrl.cpp1
-rw-r--r--indra/newview/llavatarrenderinfoaccountant.cpp4
-rw-r--r--[-rwxr-xr-x]indra/newview/llcallbacklist.cpp0
-rwxr-xr-xindra/newview/llcallbacklist.h72
-rwxr-xr-xindra/newview/llcallingcard.cpp25
-rwxr-xr-xindra/newview/llcallingcard.h3
-rwxr-xr-xindra/newview/llchannelmanager.cpp3
-rwxr-xr-xindra/newview/llchathistory.cpp4
-rwxr-xr-xindra/newview/llchiclet.cpp8
-rwxr-xr-xindra/newview/llchicletbar.cpp3
-rwxr-xr-xindra/newview/llcommandhandler.cpp12
-rwxr-xr-xindra/newview/llcompilequeue.cpp5
-rwxr-xr-xindra/newview/llconversationlog.h3
-rwxr-xr-xindra/newview/llconversationmodel.cpp19
-rwxr-xr-xindra/newview/lldrawpoolavatar.cpp22
-rwxr-xr-xindra/newview/lldrawpoolbump.cpp1
-rwxr-xr-xindra/newview/llestateinfomodel.cpp2
-rwxr-xr-xindra/newview/lleventpoll.cpp18
-rwxr-xr-xindra/newview/lleventpoll.h1
-rw-r--r--indra/newview/llexperienceassociationresponder.cpp97
-rw-r--r--indra/newview/llexperienceassociationresponder.h58
-rwxr-xr-xindra/newview/llfacebookconnect.cpp32
-rwxr-xr-xindra/newview/llfavoritesbar.cpp384
-rwxr-xr-xindra/newview/llfavoritesbar.h26
-rwxr-xr-xindra/newview/llfeaturemanager.cpp6
-rwxr-xr-xindra/newview/llfilepicker.cpp4
-rw-r--r--indra/newview/llflickrconnect.cpp17
-rwxr-xr-xindra/newview/llfloaterabout.cpp94
-rwxr-xr-xindra/newview/llfloaterabout.h3
-rwxr-xr-xindra/newview/llfloateravatarpicker.cpp2
-rwxr-xr-xindra/newview/llfloaterbump.cpp32
-rwxr-xr-xindra/newview/llfloaterbump.h4
-rw-r--r--indra/newview/llfloaterexperienceprofile.cpp283
-rw-r--r--indra/newview/llfloaterexperienceprofile.h6
-rw-r--r--indra/newview/llfloaterexperiences.cpp5
-rw-r--r--indra/newview/llfloaterfacebook.cpp6
-rwxr-xr-xindra/newview/llfloaterimcontainer.cpp74
-rwxr-xr-xindra/newview/llfloaterimcontainer.h2
-rwxr-xr-xindra/newview/llfloaterjoystick.cpp14
-rwxr-xr-xindra/newview/llfloaterjoystick.h5
-rwxr-xr-xindra/newview/llfloaterland.cpp3
-rwxr-xr-xindra/newview/llfloatermarketplacelistings.cpp2
-rwxr-xr-xindra/newview/llfloatermodelpreview.cpp3053
-rwxr-xr-xindra/newview/llfloatermodelpreview.h132
-rwxr-xr-xindra/newview/llfloatermodeluploadbase.cpp2
-rw-r--r--indra/newview/llfloaternotificationstabbed.cpp575
-rw-r--r--indra/newview/llfloaternotificationstabbed.h174
-rwxr-xr-xindra/newview/llfloateroutbox.cpp623
-rwxr-xr-xindra/newview/llfloateroutbox.h116
-rwxr-xr-xindra/newview/llfloaterperms.cpp49
-rwxr-xr-xindra/newview/llfloaterpreference.cpp25
-rwxr-xr-xindra/newview/llfloaterpreference.h3
-rwxr-xr-xindra/newview/llfloaterregioninfo.cpp58
-rwxr-xr-xindra/newview/llfloaterregioninfo.h2
-rwxr-xr-xindra/newview/llfloaterreporter.cpp4
-rwxr-xr-xindra/newview/llfloaterscriptlimits.cpp8
-rwxr-xr-xindra/newview/llfloatersnapshot.cpp8
-rwxr-xr-xindra/newview/llfloatertos.cpp36
-rwxr-xr-xindra/newview/llfloatertos.h2
-rwxr-xr-xindra/newview/llfloatertranslationsettings.cpp64
-rwxr-xr-xindra/newview/llfloatertranslationsettings.h2
-rwxr-xr-xindra/newview/llfloaterurlentry.cpp2
-rwxr-xr-xindra/newview/llfloaterworldmap.cpp6
-rwxr-xr-xindra/newview/llfolderviewmodelinventory.cpp23
-rwxr-xr-xindra/newview/llfolderviewmodelinventory.h1
-rwxr-xr-xindra/newview/llgroupmgr.cpp93
-rwxr-xr-xindra/newview/llgroupmgr.h7
-rwxr-xr-xindra/newview/llhttpretrypolicy.cpp47
-rwxr-xr-xindra/newview/llhttpretrypolicy.h2
-rwxr-xr-xindra/newview/llimview.cpp4
-rwxr-xr-xindra/newview/llinventorybridge.cpp291
-rwxr-xr-xindra/newview/llinventorybridge.h12
-rwxr-xr-xindra/newview/llinventoryfunctions.cpp160
-rwxr-xr-xindra/newview/llinventoryfunctions.h10
-rwxr-xr-xindra/newview/llinventorymodel.cpp8
-rwxr-xr-xindra/newview/llinventorymodel.h6
-rwxr-xr-xindra/newview/llinventorymodelbackgroundfetch.cpp11
-rwxr-xr-xindra/newview/llinventoryobserver.cpp2
-rwxr-xr-xindra/newview/llinventorypanel.cpp24
-rwxr-xr-xindra/newview/lllocalbitmaps.cpp2
-rwxr-xr-xindra/newview/lllocationinputctrl.cpp5
-rwxr-xr-xindra/newview/lllogchat.cpp16
-rwxr-xr-xindra/newview/lllogchat.h1
-rwxr-xr-xindra/newview/llmanipscale.cpp16
-rwxr-xr-xindra/newview/llmaniptranslate.cpp8
-rwxr-xr-xindra/newview/llmarketplacefunctions.cpp1388
-rwxr-xr-xindra/newview/llmarketplacefunctions.h22
-rwxr-xr-xindra/newview/llmaterialmgr.cpp362
-rw-r--r--indra/newview/llmaterialmgr.h7
-rwxr-xr-xindra/newview/llmediactrl.cpp23
-rwxr-xr-xindra/newview/llmediactrl.h3
-rwxr-xr-xindra/newview/llmediadataclient.cpp26
-rwxr-xr-xindra/newview/llmediadataclient.h8
-rwxr-xr-xindra/newview/llmeshrepository.cpp426
-rwxr-xr-xindra/newview/llmeshrepository.h55
-rwxr-xr-xindra/newview/llmoveview.cpp10
-rwxr-xr-xindra/newview/llnamelistctrl.cpp15
-rwxr-xr-xindra/newview/llnamelistctrl.h17
-rwxr-xr-xindra/newview/llnotificationhandler.h16
-rw-r--r--indra/newview/llnotificationlistitem.cpp645
-rw-r--r--indra/newview/llnotificationlistitem.h250
-rw-r--r--[-rwxr-xr-x]indra/newview/llnotificationlistview.cpp (renamed from indra/newview/lltexturestatsuploader.cpp)35
-rw-r--r--[-rwxr-xr-x]indra/newview/llnotificationlistview.h (renamed from indra/newview/lltexturestatsuploader.h)33
-rwxr-xr-xindra/newview/llnotificationmanager.cpp7
-rwxr-xr-xindra/newview/llpaneleditwearable.cpp3
-rw-r--r--indra/newview/llpanelexperiencelisteditor.cpp6
-rw-r--r--indra/newview/llpanelexperiencelisteditor.h3
-rw-r--r--indra/newview/llpanelexperiencelog.cpp4
-rw-r--r--indra/newview/llpanelexperiencepicker.cpp108
-rw-r--r--indra/newview/llpanelexperiencepicker.h3
-rwxr-xr-xindra/newview/llpanelface.h2
-rwxr-xr-xindra/newview/llpanelgroup.cpp4
-rw-r--r--indra/newview/llpanelgroupexperiences.cpp57
-rw-r--r--indra/newview/llpanelgroupexperiences.h3
-rwxr-xr-xindra/newview/llpanelgroupgeneral.cpp5
-rwxr-xr-xindra/newview/llpanelgroupinvite.cpp92
-rwxr-xr-xindra/newview/llpanelgrouproles.cpp136
-rwxr-xr-xindra/newview/llpanelgrouproles.h3
-rwxr-xr-xindra/newview/llpanellandmarkinfo.cpp1
-rwxr-xr-xindra/newview/llpanellogin.cpp16
-rwxr-xr-xindra/newview/llpanelmaininventory.cpp2
-rwxr-xr-xindra/newview/llpanelmediasettingsgeneral.cpp4
-rwxr-xr-xindra/newview/llpanelobject.cpp11
-rwxr-xr-xindra/newview/llpanelpeople.cpp18
-rwxr-xr-xindra/newview/llpanelpeople.h1
-rwxr-xr-xindra/newview/llpanelpicks.cpp2
-rwxr-xr-xindra/newview/llpanelplaces.cpp16
-rwxr-xr-xindra/newview/llpaneltopinfobar.cpp5
-rwxr-xr-xindra/newview/llpathfindingmanager.cpp18
-rwxr-xr-xindra/newview/llpreviewscript.cpp22
-rwxr-xr-xindra/newview/llpreviewtexture.cpp1
-rwxr-xr-xindra/newview/llproductinforequest.cpp2
-rwxr-xr-xindra/newview/llprogressview.cpp4
-rwxr-xr-xindra/newview/llremoteparcelrequest.cpp2
-rwxr-xr-xindra/newview/llsecapi.cpp41
-rwxr-xr-xindra/newview/llsecapi.h3
-rwxr-xr-xindra/newview/llselectmgr.cpp27
-rwxr-xr-xindra/newview/llsidepanelinventory.cpp1
-rwxr-xr-xindra/newview/llsidepaneliteminfo.cpp5
-rwxr-xr-xindra/newview/llsidepaneltaskinfo.cpp24
-rwxr-xr-xindra/newview/llslurl.cpp7
-rw-r--r--indra/newview/llsnapshotlivepreview.cpp109
-rw-r--r--indra/newview/llsnapshotlivepreview.h2
-rwxr-xr-xindra/newview/llspeakers.cpp19
-rwxr-xr-xindra/newview/llstartup.cpp56
-rw-r--r--indra/newview/llsyntaxid.cpp2
-rwxr-xr-xindra/newview/llsyswellwindow.cpp152
-rwxr-xr-xindra/newview/llsyswellwindow.h51
-rwxr-xr-xindra/newview/lltexturecache.cpp9
-rwxr-xr-xindra/newview/lltexturefetch.cpp57
-rwxr-xr-xindra/newview/lltexturefetch.h1
-rwxr-xr-xindra/newview/lltexturestats.cpp14
-rwxr-xr-xindra/newview/lltoastgroupnotifypanel.cpp2
-rwxr-xr-xindra/newview/lltooldraganddrop.cpp18
-rwxr-xr-xindra/newview/lltranslate.cpp409
-rwxr-xr-xindra/newview/lltranslate.h217
-rw-r--r--indra/newview/lltwitterconnect.cpp28
-rwxr-xr-xindra/newview/lluploadfloaterobservers.h1
-rwxr-xr-xindra/newview/llurllineeditorctrl.cpp2
-rw-r--r--indra/newview/llviewerassetupload.cpp16
-rwxr-xr-xindra/newview/llviewerfloaterreg.cpp6
-rw-r--r--indra/newview/llviewerfoldertype.cpp2
-rwxr-xr-xindra/newview/llviewerinventory.cpp2
-rwxr-xr-xindra/newview/llviewermedia.cpp65
-rwxr-xr-xindra/newview/llviewermedia.h1
-rwxr-xr-xindra/newview/llviewermenu.cpp66
-rwxr-xr-xindra/newview/llviewermenufile.cpp1
-rwxr-xr-xindra/newview/llviewermessage.cpp119
-rwxr-xr-xindra/newview/llviewerobject.cpp32
-rwxr-xr-xindra/newview/llviewerobject.h2
-rwxr-xr-xindra/newview/llviewerobjectlist.cpp73
-rwxr-xr-xindra/newview/llviewerobjectlist.h10
-rwxr-xr-xindra/newview/llviewerregion.cpp21
-rwxr-xr-xindra/newview/llviewerstats.cpp5
-rwxr-xr-xindra/newview/llvoavatar.cpp22
-rwxr-xr-xindra/newview/llvoavatar.h2
-rwxr-xr-xindra/newview/llvoavatarself.cpp2
-rwxr-xr-xindra/newview/llvoicechannel.cpp2
-rwxr-xr-xindra/newview/llvoicevivox.cpp4
-rwxr-xr-xindra/newview/llvovolume.cpp165
-rwxr-xr-xindra/newview/llvovolume.h6
-rwxr-xr-xindra/newview/llwebprofile.cpp6
-rwxr-xr-xindra/newview/llwlhandlers.cpp6
-rwxr-xr-xindra/newview/llworldmap.cpp1
-rwxr-xr-xindra/newview/llxmlrpctransaction.cpp6
-rwxr-xr-xindra/newview/pipeline.cpp1
-rwxr-xr-xindra/newview/skins/default/colors.xml7
-rw-r--r--indra/newview/skins/default/textures/icons/Icon_Attachment_Large.pngbin0 -> 4182 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Icon_Attachment_Small.pngbin0 -> 3774 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Icon_Notification_Condense.pngbin0 -> 262 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Icon_Notification_Expand.pngbin0 -> 239 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/System_Notification_Large.pngbin0 -> 1804 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/System_Notification_Small.pngbin0 -> 661 bytes
-rwxr-xr-xindra/newview/skins/default/textures/textures.xml5
-rwxr-xr-xindra/newview/skins/default/xui/da/menu_viewer.xml2
-rwxr-xr-xindra/newview/skins/default/xui/da/notifications.xml3
-rwxr-xr-xindra/newview/skins/default/xui/de/menu_viewer.xml4
-rwxr-xr-xindra/newview/skins/default/xui/de/notifications.xml3
-rwxr-xr-xindra/newview/skins/default/xui/en/floater_about.xml8
-rwxr-xr-xindra/newview/skins/default/xui/en/floater_about_land.xml4
-rwxr-xr-xindra/newview/skins/default/xui/en/floater_bumps.xml6
-rw-r--r--indra/newview/skins/default/xui/en/floater_experiences.xml2
-rwxr-xr-xindra/newview/skins/default/xui/en/floater_model_preview.xml38
-rw-r--r--indra/newview/skins/default/xui/en/floater_notifications_tabbed.xml154
-rwxr-xr-xindra/newview/skins/default/xui/en/floater_sys_well.xml4
-rwxr-xr-xindra/newview/skins/default/xui/en/menu_inventory.xml16
-rwxr-xr-xindra/newview/skins/default/xui/en/menu_login.xml6
-rw-r--r--indra/newview/skins/default/xui/en/menu_url_email.xml21
-rwxr-xr-xindra/newview/skins/default/xui/en/menu_viewer.xml19
-rwxr-xr-xindra/newview/skins/default/xui/en/notifications.xml120
-rw-r--r--indra/newview/skins/default/xui/en/panel_experience_list_editor.xml6
-rwxr-xr-xindra/newview/skins/default/xui/en/panel_main_inventory.xml2
-rw-r--r--indra/newview/skins/default/xui/en/panel_notification_list_item.xml144
-rwxr-xr-xindra/newview/skins/default/xui/en/panel_people.xml2
-rwxr-xr-xindra/newview/skins/default/xui/en/panel_preferences_advanced.xml2
-rwxr-xr-xindra/newview/skins/default/xui/en/panel_preferences_setup.xml2
-rwxr-xr-xindra/newview/skins/default/xui/en/strings.xml2
-rw-r--r--indra/newview/skins/default/xui/en/widgets/notification_list_view.xml18
-rwxr-xr-xindra/newview/skins/default/xui/es/menu_viewer.xml4
-rwxr-xr-xindra/newview/skins/default/xui/es/notifications.xml3
-rwxr-xr-xindra/newview/skins/default/xui/fr/menu_viewer.xml4
-rwxr-xr-xindra/newview/skins/default/xui/fr/notifications.xml3
-rwxr-xr-xindra/newview/skins/default/xui/fr/panel_login.xml3
-rwxr-xr-xindra/newview/skins/default/xui/it/menu_viewer.xml4
-rwxr-xr-xindra/newview/skins/default/xui/it/notifications.xml3
-rwxr-xr-xindra/newview/skins/default/xui/ja/menu_viewer.xml4
-rwxr-xr-xindra/newview/skins/default/xui/ja/notifications.xml3
-rwxr-xr-xindra/newview/skins/default/xui/pl/menu_viewer.xml2
-rwxr-xr-xindra/newview/skins/default/xui/pl/notifications.xml3
-rwxr-xr-xindra/newview/skins/default/xui/pt/menu_viewer.xml4
-rwxr-xr-xindra/newview/skins/default/xui/pt/notifications.xml3
-rwxr-xr-xindra/newview/skins/default/xui/ru/menu_viewer.xml4
-rwxr-xr-xindra/newview/skins/default/xui/ru/notifications.xml3
-rwxr-xr-xindra/newview/skins/default/xui/tr/menu_viewer.xml4
-rwxr-xr-xindra/newview/skins/default/xui/tr/notifications.xml3
-rwxr-xr-xindra/newview/skins/default/xui/zh/menu_viewer.xml4
-rwxr-xr-xindra/newview/skins/default/xui/zh/notifications.xml3
-rwxr-xr-xindra/newview/tests/llhttpretrypolicy_test.cpp6
-rwxr-xr-xindra/newview/tests/lltranslate_test.cpp340
259 files changed, 6766 insertions, 7675 deletions
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 090879e372..feb2e207fe 100755
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -138,7 +138,6 @@ set(viewer_SOURCE_FILES
llbreadcrumbview.cpp
llbrowsernotification.cpp
llbuycurrencyhtml.cpp
- llcallbacklist.cpp
llcallingcard.cpp
llchannelmanager.cpp
llchatbar.cpp
@@ -192,7 +191,6 @@ set(viewer_SOURCE_FILES
lleventnotifier.cpp
lleventpoll.cpp
llexpandabletextbox.cpp
- llexperienceassociationresponder.cpp
llexperiencelog.cpp
llexternaleditor.cpp
llface.cpp
@@ -269,9 +267,9 @@ set(viewer_SOURCE_FILES
llfloatermodeluploadbase.cpp
llfloaternamedesc.cpp
llfloaternotificationsconsole.cpp
+ llfloaternotificationstabbed.cpp
llfloaterobjectweights.cpp
llfloateropenobject.cpp
- llfloateroutbox.cpp
llfloaterpathfindingcharacters.cpp
llfloaterpathfindingconsole.cpp
llfloaterpathfindinglinksets.cpp
@@ -402,6 +400,8 @@ set(viewer_SOURCE_FILES
llnotificationgrouphandler.cpp
llnotificationhandlerutil.cpp
llnotificationhinthandler.cpp
+ llnotificationlistitem.cpp
+ llnotificationlistview.cpp
llnotificationmanager.cpp
llnotificationofferhandler.cpp
llnotificationscripthandler.cpp
@@ -562,7 +562,6 @@ set(viewer_SOURCE_FILES
lltextureinfo.cpp
lltextureinfodetails.cpp
lltexturestats.cpp
- lltexturestatsuploader.cpp
lltextureview.cpp
lltoast.cpp
lltoastalertpanel.cpp
@@ -746,7 +745,6 @@ set(viewer_HEADER_FILES
llbox.h
llbreadcrumbview.h
llbuycurrencyhtml.h
- llcallbacklist.h
llcallingcard.h
llcapabilityprovider.h
llchannelmanager.h
@@ -801,7 +799,6 @@ set(viewer_HEADER_FILES
lleventnotifier.h
lleventpoll.h
llexpandabletextbox.h
- llexperienceassociationresponder.h
llexperiencelog.h
llexternaleditor.h
llface.h
@@ -881,9 +878,9 @@ set(viewer_HEADER_FILES
llfloatermodeluploadbase.h
llfloaternamedesc.h
llfloaternotificationsconsole.h
+ llfloaternotificationstabbed.h
llfloaterobjectweights.h
llfloateropenobject.h
- llfloateroutbox.h
llfloaterpathfindingcharacters.h
llfloaterpathfindingconsole.h
llfloaterpathfindinglinksets.h
@@ -1007,6 +1004,8 @@ set(viewer_HEADER_FILES
llnavigationbar.h
llnetmap.h
llnotificationhandler.h
+ llnotificationlistitem.h
+ llnotificationlistview.h
llnotificationmanager.h
llnotificationstorage.h
lloutfitslist.h
@@ -1162,7 +1161,6 @@ set(viewer_HEADER_FILES
lltextureinfo.h
lltextureinfodetails.h
lltexturestats.h
- lltexturestatsuploader.h
lltextureview.h
lltoast.h
lltoastalertpanel.h
@@ -2228,7 +2226,6 @@ if (LL_TESTS)
# llmediadataclient.cpp
lllogininstance.cpp
# llremoteparcelrequest.cpp
- lltranslate.cpp
llviewerhelputil.cpp
llversioninfo.cpp
llworldmap.cpp
@@ -2250,12 +2247,6 @@ if (LL_TESTS)
)
set_source_files_properties(
- lltranslate.cpp
- PROPERTIES
- LL_TEST_ADDITIONAL_LIBRARIES "${test_libs}"
- )
-
- set_source_files_properties(
llmediadataclient.cpp
PROPERTIES
LL_TEST_ADDITIONAL_LIBRARIES "${test_libs}"
@@ -2388,7 +2379,6 @@ if (LL_TESTS)
#ADD_VIEWER_BUILD_TEST(llagentaccess viewer)
#ADD_VIEWER_BUILD_TEST(lltextureinfo viewer)
#ADD_VIEWER_BUILD_TEST(lltextureinfodetails viewer)
- #ADD_VIEWER_BUILD_TEST(lltexturestatsuploader viewer)
include(LLAddBuildTest)
SET(viewer_TEST_SOURCE_FILES
diff --git a/indra/newview/VIEWER_VERSION.txt b/indra/newview/VIEWER_VERSION.txt
index ff313b8c21..4351a7e3a3 100644
--- a/indra/newview/VIEWER_VERSION.txt
+++ b/indra/newview/VIEWER_VERSION.txt
@@ -1 +1 @@
-3.8.4
+3.8.7
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index ee1d491073..2ca090b179 100755
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -2,6 +2,39 @@
<llsd xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="llsd.xsd">
<map>
+ <key>ImporterDebug</key>
+ <map>
+ <key>Comment</key>
+ <string>Enable debug output to more precisely identify sources of import errors. Warning: the output can slow down import on many machines.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
+ <key>ImporterLegacyMatching</key>
+ <map>
+ <key>Comment</key>
+ <string>Enable index based model matching.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
+ <key>ImporterModelLimit</key>
+ <map>
+ <key>Comment</key>
+ <string>Limits amount of importer generated models for dae files</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>U32</string>
+ <key>Value</key>
+ <integer>768</integer>
+ </map>
<key>IMShowTime</key>
<map>
<key>Comment</key>
@@ -14189,7 +14222,7 @@
<key>MaxFPS</key>
<map>
<key>Comment</key>
- <string>Yield some time to the local host if we reach a threshold framerate.</string>
+ <string>OBSOLETE UNUSED setting.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
diff --git a/indra/newview/app_settings/shaders/class1/avatar/objectSkinV.glsl b/indra/newview/app_settings/shaders/class1/avatar/objectSkinV.glsl
index 6cd38d8ef5..3060307b21 100755
--- a/indra/newview/app_settings/shaders/class1/avatar/objectSkinV.glsl
+++ b/indra/newview/app_settings/shaders/class1/avatar/objectSkinV.glsl
@@ -37,8 +37,7 @@ mat4 getObjectSkinnedTransform()
index = min(index, vec4(51.0));
index = max(index, vec4( 0.0));
- float scale = 1.0/(w.x+w.y+w.z+w.w);
- w *= scale;
+ w *= 1.0/(w.x+w.y+w.z+w.w);
int i1 = int(index.x);
int i2 = int(index.y);
diff --git a/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl b/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl
index 595c11fae2..58fb01d200 100755
--- a/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl
@@ -29,6 +29,7 @@ out vec4 frag_data[3];
#define frag_data gl_FragData
#endif
+uniform float minimum_alpha;
uniform sampler2D diffuseMap;
uniform sampler2D bumpMap;
@@ -47,16 +48,23 @@ vec2 encode_normal(vec3 n)
void main()
{
- vec3 col = vertex_color.rgb * texture2D(diffuseMap, vary_texcoord0.xy).rgb;
- vec3 norm = texture2D(bumpMap, vary_texcoord0.xy).rgb * 2.0 - 1.0;
+ vec4 col = texture2D(diffuseMap, vary_texcoord0.xy);
+
+ if(col.a < minimum_alpha)
+ {
+ discard;
+ }
+ col *= vertex_color;
+
+ vec3 norm = texture2D(bumpMap, vary_texcoord0.xy).rgb * 2.0 - 1.0;
- vec3 tnorm = vec3(dot(norm,vary_mat0),
+ vec3 tnorm = vec3(dot(norm,vary_mat0),
dot(norm,vary_mat1),
dot(norm,vary_mat2));
- frag_data[0] = vec4(col, 0.0);
- frag_data[1] = vertex_color.aaaa; // spec
- //frag_data[1] = vec4(vec3(vertex_color.a), vertex_color.a+(1.0-vertex_color.a)*vertex_color.a); // spec - from former class3 - maybe better, but not so well tested
- vec3 nvn = normalize(tnorm);
- frag_data[2] = vec4(encode_normal(nvn.xyz), vertex_color.a, 0.0);
+ frag_data[0] = vec4(col.rgb, 0.0);
+ frag_data[1] = vertex_color.aaaa; // spec
+ //frag_data[1] = vec4(vec3(vertex_color.a), vertex_color.a+(1.0-vertex_color.a)*vertex_color.a); // spec - from former class3 - maybe better, but not so well tested
+ vec3 nvn = normalize(tnorm);
+ frag_data[2] = vec4(encode_normal(nvn), vertex_color.a, 0.0);
}
diff --git a/indra/newview/installers/windows/installer_template.nsi b/indra/newview/installers/windows/installer_template.nsi
index 95cdf90e99..b8677fd9e4 100755
--- a/indra/newview/installers/windows/installer_template.nsi
+++ b/indra/newview/installers/windows/installer_template.nsi
@@ -165,7 +165,9 @@ lbl_configure_default_lang:
StrCpy $LANGUAGE $0
# For silent installs, no language prompt, use default
- IfSilent lbl_return
+ IfSilent 0 +3
+ StrCpy $SKIP_AUTORUN "true"
+ Goto lbl_return
StrCmp $SKIP_DIALOGS "true" lbl_return
lbl_build_menu:
diff --git a/indra/newview/llaccountingcostmanager.cpp b/indra/newview/llaccountingcostmanager.cpp
index cd9146ea16..92a5413adb 100755
--- a/indra/newview/llaccountingcostmanager.cpp
+++ b/indra/newview/llaccountingcostmanager.cpp
@@ -31,14 +31,12 @@
#include "llcoros.h"
#include "lleventcoro.h"
#include "llcorehttputil.h"
+#include <algorithm>
+#include <iterator>
//===============================================================================
-LLAccountingCostManager::LLAccountingCostManager():
- mHttpRequest(),
- mHttpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID)
+LLAccountingCostManager::LLAccountingCostManager()
{
- mHttpRequest = LLCore::HttpRequest::ptr_t(new LLCore::HttpRequest());
- //mHttpPolicy = LLCore::HttpRequest::DEFAULT_POLICY_ID;
}
@@ -51,30 +49,24 @@ void LLAccountingCostManager::accountingCostCoro(std::string url,
LL_DEBUGS("LLAccountingCostManager") << "Entering coroutine " << LLCoros::instance().getName()
<< " with url '" << url << LL_ENDL;
+ LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+ LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+ httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("AccountingCost", httpPolicy));
+ LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+
try
{
- LLSD objectList;
- U32 objectIndex = 0;
+ uuid_set_t diffSet;
- IDIt IDIter = mObjectList.begin();
- IDIt IDIterEnd = mObjectList.end();
+ std::set_difference(mObjectList.begin(), mObjectList.end(),
+ mPendingObjectQuota.begin(), mPendingObjectQuota.end(),
+ std::inserter(diffSet, diffSet.begin()));
- for (; IDIter != IDIterEnd; ++IDIter)
- {
- // Check to see if a request for this object has already been made.
- if (mPendingObjectQuota.find(*IDIter) == mPendingObjectQuota.end())
- {
- mPendingObjectQuota.insert(*IDIter);
- objectList[objectIndex++] = *IDIter;
- }
- }
+ if (diffSet.empty())
+ return;
mObjectList.clear();
- //Post results
- if (objectList.size() == 0)
- return;
-
std::string keystr;
if (selectionType == Roots)
{
@@ -87,11 +79,18 @@ void LLAccountingCostManager::accountingCostCoro(std::string url,
else
{
LL_INFOS() << "Invalid selection type " << LL_ENDL;
- mObjectList.clear();
- mPendingObjectQuota.clear();
return;
}
+ LLSD objectList(LLSD::emptyMap());
+
+ for (uuid_set_t::iterator it = diffSet.begin(); it != diffSet.end(); ++it)
+ {
+ objectList.append(*it);
+ }
+
+ mPendingObjectQuota.insert(diffSet.begin(), diffSet.end());
+
LLSD dataToPost = LLSD::emptyMap();
dataToPost[keystr.c_str()] = objectList;
@@ -99,27 +98,27 @@ void LLAccountingCostManager::accountingCostCoro(std::string url,
LLUUID transactionId = observer->getTransactionID();
observer = NULL;
- LLCoreHttpUtil::HttpCoroutineAdapter httpAdapter("AccountingCost", mHttpPolicy);
- LLSD results = httpAdapter.postAndYield(mHttpRequest, url, dataToPost);
- LLSD httpResults;
- httpResults = results["http_result"];
+ LLSD results = httpAdapter->postAndSuspend(httpRequest, url, dataToPost);
+
+ LLSD httpResults = results["http_result"];
+ LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
// do/while(false) allows error conditions to break out of following
// block while normal flow goes forward once.
do
{
observer = observerHandle.get();
- if ((!observer) || (observer->getTransactionID() != transactionId))
- { // *TODO: Rider: I've noticed that getTransactionID() does not
- // always match transactionId (the new transaction Id does not show a
- // corresponding request.) (ask Vir)
- if (!observer)
- break;
- LL_WARNS() << "Request transaction Id(" << transactionId
- << ") does not match observer's transaction Id("
- << observer->getTransactionID() << ")." << LL_ENDL;
+
+ if (!status || results.has("error"))
+ {
+ LL_WARNS() << "Error on fetched data" << LL_ENDL;
+ if (!status)
+ observer->setErrorStatus(status.getType(), status.toString());
+ else
+ observer->setErrorStatus(499, "Error on fetched data");
+
break;
}
@@ -134,22 +133,18 @@ void LLAccountingCostManager::accountingCostCoro(std::string url,
break;
}
- if (!results.isMap() || results.has("error"))
- {
- LL_WARNS() << "Error on fetched data" << LL_ENDL;
- observer->setErrorStatus(499, "Error on fetched data");
- break;
- }
if (results.has("selected"))
{
+ LLSD selected = results["selected"];
+
F32 physicsCost = 0.0f;
F32 networkCost = 0.0f;
F32 simulationCost = 0.0f;
- physicsCost = results["selected"]["physics"].asReal();
- networkCost = results["selected"]["streaming"].asReal();
- simulationCost = results["selected"]["simulation"].asReal();
+ physicsCost = selected["physics"].asReal();
+ networkCost = selected["streaming"].asReal();
+ simulationCost = selected["simulation"].asReal();
SelectionCost selectionCost( physicsCost, networkCost, simulationCost);
diff --git a/indra/newview/llaccountingcostmanager.h b/indra/newview/llaccountingcostmanager.h
index d5a94f6fda..f251ceffd4 100755
--- a/indra/newview/llaccountingcostmanager.h
+++ b/indra/newview/llaccountingcostmanager.h
@@ -71,16 +71,13 @@ public:
private:
//Set of objects that will be used to generate a cost
- std::set<LLUUID> mObjectList;
+ uuid_set_t mObjectList;
//During fetchCosts we move object into a the pending set to signify that
//a fetch has been instigated.
- std::set<LLUUID> mPendingObjectQuota;
- typedef std::set<LLUUID>::iterator IDIt;
+ uuid_set_t mPendingObjectQuota;
void accountingCostCoro(std::string url, eSelectionType selectionType, const LLHandle<LLAccountingCostObserver> observerHandle);
- LLCore::HttpRequest::ptr_t mHttpRequest;
- LLCore::HttpRequest::policy_t mHttpPolicy;
};
//===============================================================================
diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp
index 3316f1e654..e33d34ebc7 100755
--- a/indra/newview/llagent.cpp
+++ b/indra/newview/llagent.cpp
@@ -2829,7 +2829,7 @@ BOOL LLAgent::isInGroup(const LLUUID& group_id, BOOL ignore_god_mode /* FALSE */
// This implementation should mirror LLAgentInfo::hasPowerInGroup
BOOL LLAgent::hasPowerInGroup(const LLUUID& group_id, U64 power) const
{
- if (isGodlike())
+ if (isGodlikeWithoutAdminMenuFakery())
return true;
// GP_NO_POWERS can also mean no power is enough to grant an ability.
diff --git a/indra/newview/llagent.h b/indra/newview/llagent.h
index 5731f4db89..d46973ddee 100755
--- a/indra/newview/llagent.h
+++ b/indra/newview/llagent.h
@@ -36,6 +36,7 @@
#include "llpermissionsflags.h"
#include "llevents.h"
#include "v3dmath.h"
+#include "httprequest.h"
#include "llcorehttputil.h"
#include <boost/function.hpp>
@@ -935,6 +936,8 @@ public:
bool requestPostCapability(const std::string &capName, LLSD &postData, httpCallback_t cbSuccess = NULL, httpCallback_t cbFailure = NULL);
bool requestGetCapability(const std::string &capName, httpCallback_t cbSuccess = NULL, httpCallback_t cbFailure = NULL);
+ LLCore::HttpRequest::policy_t getAgentPolicy() const { return mHttpPolicy; }
+
/** Utility
** **
*******************************************************************************/
diff --git a/indra/newview/llagentdata.cpp b/indra/newview/llagentdata.cpp
index 5f6a082d75..d2c644a06f 100755
--- a/indra/newview/llagentdata.cpp
+++ b/indra/newview/llagentdata.cpp
@@ -31,3 +31,4 @@
LLUUID gAgentID;
LLUUID gAgentSessionID;
+std::string gAgentUsername;
diff --git a/indra/newview/llagentdata.h b/indra/newview/llagentdata.h
index 83d6a53d5e..efdd97f6c4 100755
--- a/indra/newview/llagentdata.h
+++ b/indra/newview/llagentdata.h
@@ -30,5 +30,6 @@
extern LLUUID gAgentID;
extern LLUUID gAgentSessionID;
+extern std::string gAgentUsername;
#endif
diff --git a/indra/newview/llaisapi.cpp b/indra/newview/llaisapi.cpp
index da2f69126a..afc6e208e6 100755
--- a/indra/newview/llaisapi.cpp
+++ b/indra/newview/llaisapi.cpp
@@ -99,7 +99,7 @@ void AISAPI::CreateInventory(const LLUUID& parentId, const LLSD& newInventory, c
LL_DEBUGS("Inventory") << "url: " << url << LL_ENDL;
// I may be suffering from golden hammer here, but the first part of this bind
- // is actually a static cast for &HttpCoroutineAdapter::postAndYield so that
+ // is actually a static cast for &HttpCoroutineAdapter::postAndSuspend so that
// the compiler can identify the correct signature to select.
//
// Reads as follows:
@@ -117,7 +117,7 @@ void AISAPI::CreateInventory(const LLUUID& parentId, const LLSD& newInventory, c
// _4 -> body
// _5 -> httpOptions
// _6 -> httpHeaders
- (&LLCoreHttpUtil::HttpCoroutineAdapter::postAndYield), _1, _2, _3, _4, _5, _6);
+ (&LLCoreHttpUtil::HttpCoroutineAdapter::postAndSuspend), _1, _2, _3, _4, _5, _6);
LLCoprocedureManager::CoProcedure_t proc(boost::bind(&AISAPI::InvokeAISCommandCoro,
_1, postFn, url, parentId, newInventory, callback, COPYINVENTORY));
@@ -150,7 +150,7 @@ void AISAPI::SlamFolder(const LLUUID& folderId, const LLSD& newInventory, comple
// _4 -> body
// _5 -> httpOptions
// _6 -> httpHeaders
- (&LLCoreHttpUtil::HttpCoroutineAdapter::putAndYield), _1, _2, _3, _4, _5, _6);
+ (&LLCoreHttpUtil::HttpCoroutineAdapter::putAndSuspend), _1, _2, _3, _4, _5, _6);
LLCoprocedureManager::CoProcedure_t proc(boost::bind(&AISAPI::InvokeAISCommandCoro,
_1, putFn, url, folderId, newInventory, callback, SLAMFOLDER));
@@ -182,7 +182,7 @@ void AISAPI::RemoveCategory(const LLUUID &categoryId, completion_t callback)
// _4 -> body
// _5 -> httpOptions
// _6 -> httpHeaders
- (&LLCoreHttpUtil::HttpCoroutineAdapter::deleteAndYield), _1, _2, _3, _5, _6);
+ (&LLCoreHttpUtil::HttpCoroutineAdapter::deleteAndSuspend), _1, _2, _3, _5, _6);
LLCoprocedureManager::CoProcedure_t proc(boost::bind(&AISAPI::InvokeAISCommandCoro,
_1, delFn, url, categoryId, LLSD(), callback, REMOVECATEGORY));
@@ -215,7 +215,7 @@ void AISAPI::RemoveItem(const LLUUID &itemId, completion_t callback)
// _4 -> body
// _5 -> httpOptions
// _6 -> httpHeaders
- (&LLCoreHttpUtil::HttpCoroutineAdapter::deleteAndYield), _1, _2, _3, _5, _6);
+ (&LLCoreHttpUtil::HttpCoroutineAdapter::deleteAndSuspend), _1, _2, _3, _5, _6);
LLCoprocedureManager::CoProcedure_t proc(boost::bind(&AISAPI::InvokeAISCommandCoro,
_1, delFn, url, itemId, LLSD(), callback, REMOVEITEM));
@@ -258,7 +258,7 @@ void AISAPI::CopyLibraryCategory(const LLUUID& sourceId, const LLUUID& destId, b
// _4 -> body
// _5 -> httpOptions
// _6 -> httpHeaders
- (&LLCoreHttpUtil::HttpCoroutineAdapter::copyAndYield), _1, _2, _3, destination, _5, _6);
+ (&LLCoreHttpUtil::HttpCoroutineAdapter::copyAndSuspend), _1, _2, _3, destination, _5, _6);
LLCoprocedureManager::CoProcedure_t proc(boost::bind(&AISAPI::InvokeAISCommandCoro,
_1, copyFn, url, destId, LLSD(), callback, COPYLIBRARYCATEGORY));
@@ -291,7 +291,7 @@ void AISAPI::PurgeDescendents(const LLUUID &categoryId, completion_t callback)
// _4 -> body
// _5 -> httpOptions
// _6 -> httpHeaders
- (&LLCoreHttpUtil::HttpCoroutineAdapter::deleteAndYield), _1, _2, _3, _5, _6);
+ (&LLCoreHttpUtil::HttpCoroutineAdapter::deleteAndSuspend), _1, _2, _3, _5, _6);
LLCoprocedureManager::CoProcedure_t proc(boost::bind(&AISAPI::InvokeAISCommandCoro,
_1, delFn, url, categoryId, LLSD(), callback, PURGEDESCENDENTS));
@@ -323,7 +323,7 @@ void AISAPI::UpdateCategory(const LLUUID &categoryId, const LLSD &updates, compl
// _4 -> body
// _5 -> httpOptions
// _6 -> httpHeaders
- (&LLCoreHttpUtil::HttpCoroutineAdapter::patchAndYield), _1, _2, _3, _4, _5, _6);
+ (&LLCoreHttpUtil::HttpCoroutineAdapter::patchAndSuspend), _1, _2, _3, _4, _5, _6);
LLCoprocedureManager::CoProcedure_t proc(boost::bind(&AISAPI::InvokeAISCommandCoro,
_1, patchFn, url, categoryId, updates, callback, UPDATECATEGORY));
@@ -355,7 +355,7 @@ void AISAPI::UpdateItem(const LLUUID &itemId, const LLSD &updates, completion_t
// _4 -> body
// _5 -> httpOptions
// _6 -> httpHeaders
- (&LLCoreHttpUtil::HttpCoroutineAdapter::patchAndYield), _1, _2, _3, _4, _5, _6);
+ (&LLCoreHttpUtil::HttpCoroutineAdapter::patchAndSuspend), _1, _2, _3, _4, _5, _6);
LLCoprocedureManager::CoProcedure_t proc(boost::bind(&AISAPI::InvokeAISCommandCoro,
_1, patchFn, url, itemId, updates, callback, UPDATEITEM));
@@ -367,7 +367,7 @@ void AISAPI::UpdateItem(const LLUUID &itemId, const LLSD &updates, completion_t
void AISAPI::EnqueueAISCommand(const std::string &procName, LLCoprocedureManager::CoProcedure_t proc)
{
std::string procFullName = "AIS(" + procName + ")";
- LLCoprocedureManager::getInstance()->enqueueCoprocedure("AIS", procFullName, proc);
+ LLCoprocedureManager::instance().enqueueCoprocedure("AIS", procFullName, proc);
}
@@ -380,7 +380,7 @@ void AISAPI::InvokeAISCommandCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t ht
LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest());
LLCore::HttpHeaders::ptr_t httpHeaders;
- httpOptions->setTimeout(HTTP_REQUEST_EXPIRY_SECS);
+ httpOptions->setTimeout(LLCoreHttpUtil::HTTP_REQUEST_EXPIRY_SECS);
LL_DEBUGS("Inventory") << "url: " << url << LL_ENDL;
diff --git a/indra/newview/llaisapi.h b/indra/newview/llaisapi.h
index 2de8003c2f..e97059014b 100755
--- a/indra/newview/llaisapi.h
+++ b/indra/newview/llaisapi.h
@@ -31,8 +31,6 @@
#include <map>
#include <set>
#include <string>
-#include "llcurl.h"
-#include "llhttpclient.h"
#include "llhttpretrypolicy.h"
#include "llviewerinventory.h"
#include "llcorehttputil.h"
diff --git a/indra/newview/llappcorehttp.cpp b/indra/newview/llappcorehttp.cpp
index 51cca273d8..8c276c0fe9 100755
--- a/indra/newview/llappcorehttp.cpp
+++ b/indra/newview/llappcorehttp.cpp
@@ -138,6 +138,9 @@ LLAppCoreHttp::~LLAppCoreHttp()
void LLAppCoreHttp::init()
{
+
+ LLCore::LLHttp::initialize();
+
LLCore::HttpStatus status = LLCore::HttpRequest::createService();
if (! status)
{
@@ -275,12 +278,25 @@ void setting_changed()
LLAppViewer::instance()->getAppCoreHttp().refreshSettings(false);
}
+namespace
+{
+ // The NoOpDeletor is used when wrapping LLAppCoreHttp in a smart pointer below for
+ // passage into the LLCore::Http libararies. When the smart pointer is destroyed,
+ // no action will be taken since we do not in this case want the entire LLAppCoreHttp object
+ // to be destroyed at the end of the call.
+ //
+ // *NOTE$: Yes! It is "Deletor"
+ // http://english.stackexchange.com/questions/4733/what-s-the-rule-for-adding-er-vs-or-when-nouning-a-verb
+ // "delete" derives from Latin "deletus"
+ void NoOpDeletor(LLCore::HttpHandler *)
+ { /*NoOp*/ }
+}
void LLAppCoreHttp::requestStop()
{
llassert_always(mRequest);
- mStopHandle = mRequest->requestStopThread(this);
+ mStopHandle = mRequest->requestStopThread(LLCore::HttpHandler::ptr_t(this, NoOpDeletor));
if (LLCORE_HTTP_HANDLE_INVALID != mStopHandle)
{
mStopRequested = LLTimer::getTotalSeconds();
@@ -393,7 +409,7 @@ void LLAppCoreHttp::refreshSettings(bool initial)
handle = mRequest->setPolicyOption(LLCore::HttpRequest::PO_PIPELINING_DEPTH,
mHttpClasses[app_policy].mPolicy,
new_depth,
- NULL);
+ LLCore::HttpHandler::ptr_t());
if (LLCORE_HTTP_HANDLE_INVALID == handle)
{
status = mRequest->getStatus();
@@ -443,7 +459,7 @@ void LLAppCoreHttp::refreshSettings(bool initial)
handle = mRequest->setPolicyOption(LLCore::HttpRequest::PO_CONNECTION_LIMIT,
mHttpClasses[app_policy].mPolicy,
(mHttpClasses[app_policy].mPipelined ? 2 * setting : setting),
- NULL);
+ LLCore::HttpHandler::ptr_t());
if (LLCORE_HTTP_HANDLE_INVALID == handle)
{
status = mRequest->getStatus();
@@ -456,7 +472,7 @@ void LLAppCoreHttp::refreshSettings(bool initial)
handle = mRequest->setPolicyOption(LLCore::HttpRequest::PO_PER_HOST_CONNECTION_LIMIT,
mHttpClasses[app_policy].mPolicy,
setting,
- NULL);
+ LLCore::HttpHandler::ptr_t());
if (LLCORE_HTTP_HANDLE_INVALID == handle)
{
status = mRequest->getStatus();
@@ -483,7 +499,7 @@ void LLAppCoreHttp::refreshSettings(bool initial)
}
LLCore::HttpStatus LLAppCoreHttp::sslVerify(const std::string &url,
- LLCore::HttpHandler const * const handler, void *appdata)
+ const LLCore::HttpHandler::ptr_t &handler, void *appdata)
{
X509_STORE_CTX *ctx = static_cast<X509_STORE_CTX *>(appdata);
LLCore::HttpStatus result;
diff --git a/indra/newview/llappcorehttp.h b/indra/newview/llappcorehttp.h
index 410d7c6b07..95c138d598 100755
--- a/indra/newview/llappcorehttp.h
+++ b/indra/newview/llappcorehttp.h
@@ -257,7 +257,7 @@ private:
bool mPipelined; // Global setting
boost::signals2::connection mPipelinedSignal; // Signal for 'HttpPipelining' setting
- static LLCore::HttpStatus sslVerify(const std::string &uri, LLCore::HttpHandler const * const handler, void *appdata);
+ static LLCore::HttpStatus sslVerify(const std::string &uri, const LLCore::HttpHandler::ptr_t &handler, void *appdata);
};
diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index eea585e998..d080dfb66e 100755
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -57,6 +57,8 @@
#include "llhttpsdhandler.h"
#include "llcorehttputil.h"
#include "llappviewer.h"
+#include "llcoros.h"
+#include "lleventcoro.h"
#if LL_MSVC
// disable boost::lexical_cast warning
@@ -1885,6 +1887,10 @@ bool LLAppearanceMgr::canAddWearables(const uuid_vec_t& item_ids)
{
++n_clothes;
}
+ else if (item->getType() == LLAssetType::AT_BODYPART)
+ {
+ return isAgentAvatarValid();
+ }
else
{
LL_WARNS() << "Unexpected wearable type" << LL_ENDL;
@@ -3348,84 +3354,123 @@ LLSD LLAppearanceMgr::dumpCOF() const
void LLAppearanceMgr::requestServerAppearanceUpdate()
{
+ LLCoros::instance().launch("LLAppearanceMgr::serverAppearanceUpdateCoro",
+ boost::bind(&LLAppearanceMgr::serverAppearanceUpdateCoro, this));
+}
- if (!testCOFRequestVersion())
- {
- // *TODO: LL_LOG message here
- return;
- }
+void LLAppearanceMgr::serverAppearanceUpdateCoro()
+{
+ // If we have already received an update for this or higher cof version, ignore.
+ S32 cofVersion = getCOFVersion();
+ S32 lastRcv = gAgentAvatarp->mLastUpdateReceivedCOFVersion;
+ S32 lastReq = gAgentAvatarp->mLastUpdateRequestCOFVersion;
- if ((mInFlightCounter > 0) && (mInFlightTimer.hasExpired()))
- {
- LL_WARNS("Avatar") << "in flight timer expired, resetting " << LL_ENDL;
- mInFlightCounter = 0;
- }
+ //----------------
+ // move out of coroutine
+ if (!gAgent.getRegion())
+ {
+ LL_WARNS("Avatar") << "Region not set, cannot request server appearance update" << LL_ENDL;
+ return;
+ }
+ if (gAgent.getRegion()->getCentralBakeVersion() == 0)
+ {
+ LL_WARNS("Avatar") << "Region does not support baking" << LL_ENDL;
+ }
- if (gAgentAvatarp->isEditingAppearance())
- {
- LL_WARNS("Avatar") << "Avatar editing appearance, not sending request." << LL_ENDL;
- // don't send out appearance updates if in appearance editing mode
- return;
- }
+ std::string url = gAgent.getRegion()->getCapability("UpdateAvatarAppearance");
+ if (url.empty())
+ {
+ LL_WARNS("Agent") << "Could not retrieve region capability \"UpdateAvatarAppearance\"" << LL_ENDL;
+ }
- if (!gAgent.getRegion())
- {
- LL_WARNS("Avatar") << "Region not set, cannot request server appearance update" << LL_ENDL;
- return;
- }
- if (gAgent.getRegion()->getCentralBakeVersion() == 0)
- {
- LL_WARNS("Avatar") << "Region does not support baking" << LL_ENDL;
- }
+ //----------------
+ if (gAgentAvatarp->isEditingAppearance())
+ {
+ LL_WARNS("Avatar") << "Avatar editing appearance, not sending request." << LL_ENDL;
+ // don't send out appearance updates if in appearance editing mode
+ return;
+ }
- LLSD postData;
- S32 cof_version = LLAppearanceMgr::instance().getCOFVersion();
- if (gSavedSettings.getBOOL("DebugAvatarExperimentalServerAppearanceUpdate"))
- {
- postData = LLAppearanceMgr::instance().dumpCOF();
- }
- else
- {
- postData["cof_version"] = cof_version;
- if (gSavedSettings.getBOOL("DebugForceAppearanceRequestFailure"))
- {
- postData["cof_version"] = cof_version + 999;
- }
- }
+ LL_DEBUGS("Avatar") << "COF version=" << cofVersion <<
+ " last_rcv=" << lastRcv <<
+ " last_req=" << lastReq << LL_ENDL;
+
+ if (cofVersion < lastRcv)
+ {
+ LL_WARNS("Avatar") << "Have already received update for cof version " << lastRcv
+ << " will not request for " << cofVersion << LL_ENDL;
+ return;
+ }
+ if (lastReq >= cofVersion)
+ {
+ LL_WARNS("Avatar") << "Request already in flight for cof version " << lastReq
+ << " will not request for " << cofVersion << LL_ENDL;
+ return;
+ }
- mInFlightCounter++;
- mInFlightTimer.setTimerExpirySec(60.0);
+ // Actually send the request.
+ LL_DEBUGS("Avatar") << "Will send request for cof_version " << cofVersion << LL_ENDL;
- llassert(cof_version >= gAgentAvatarp->mLastUpdateRequestCOFVersion);
- gAgentAvatarp->mLastUpdateRequestCOFVersion = cof_version;
+ LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter(
+ "UpdateAvatarAppearance", gAgent.getAgentPolicy()));
- if (!gAgent.requestPostCapability("UpdateAvatarAppearance", postData,
- static_cast<LLAgent::httpCallback_t>(boost::bind(&LLAppearanceMgr::serverAppearanceUpdateSuccess, this, _1)),
- static_cast<LLAgent::httpCallback_t>(boost::bind(&LLAppearanceMgr::decrementInFlightCounter, this))))
+ S32 reqCofVersion = cofVersion;
+ if (gSavedSettings.getBOOL("DebugForceAppearanceRequestFailure"))
{
- LL_WARNS("Avatar") << "Unable to access UpdateAvatarAppearance in this region." << LL_ENDL;
+ reqCofVersion += 999;
+ LL_WARNS("Avatar") << "Forcing version failure on COF Baking" << LL_ENDL;
}
-}
-void LLAppearanceMgr::serverAppearanceUpdateSuccess(const LLSD &result)
-{
- decrementInFlightCounter();
- if (result["success"].asBoolean())
+ do
{
- LL_DEBUGS("Avatar") << "succeeded" << LL_ENDL;
- if (gSavedSettings.getBOOL("DebugAvatarAppearanceMessage"))
+ LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest());
+
+ LLSD postData;
+ if (gSavedSettings.getBOOL("DebugAvatarExperimentalServerAppearanceUpdate"))
{
- dump_sequential_xml(gAgentAvatarp->getFullname() + "_appearance_request_ok", result);
+ postData = dumpCOF();
}
- }
- else
- {
- LL_WARNS("Avatar") << "Non success response for change appearance" << LL_ENDL;
+ else
+ {
+ postData["cof_version"] = reqCofVersion;
+ }
+
+ gAgentAvatarp->mLastUpdateRequestCOFVersion = reqCofVersion;
+
+ LLSD result = httpAdapter->postAndSuspend(httpRequest, url, postData);
+
+ LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+ LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+ if (!status || !result["success"].asBoolean())
+ {
+ std::string message = (result.has("error")) ? result["error"].asString() : status.toString();
+ LL_WARNS("Avatar") << "Appearance Failure. server responded with \"" << message << "\"" << LL_ENDL;
+
+ // We may have requested a bake for a stale COF (especially if the inventory
+ // is still updating. If that is the case re send the request with the
+ // corrected COF version. (This may also be the case if the viewer is running
+ // on multiple machines.
+ if (result.has("expected"))
+ {
+ reqCofVersion = result["expected"].asInteger();
+
+ LL_WARNS("Avatar") << "Will Retry with expected COF value of " << reqCofVersion << LL_ENDL;
+ continue;
+ }
+
+ break;
+ }
+
+ LL_DEBUGS("Avatar") << "succeeded" << LL_ENDL;
if (gSavedSettings.getBOOL("DebugAvatarAppearanceMessage"))
{
- debugAppearanceUpdateCOF(result);
+ dump_sequential_xml(gAgentAvatarp->getFullname() + "_appearance_request_ok", result);
}
- }
+
+ break;
+ } while (true);
+
}
/*static*/
@@ -3513,36 +3558,6 @@ void LLAppearanceMgr::debugAppearanceUpdateCOF(const LLSD& content)
}
-bool LLAppearanceMgr::testCOFRequestVersion() const
-{
- // If we have already received an update for this or higher cof version, ignore.
- S32 cof_version = getCOFVersion();
- S32 last_rcv = gAgentAvatarp->mLastUpdateReceivedCOFVersion;
- S32 last_req = gAgentAvatarp->mLastUpdateRequestCOFVersion;
-
- LL_DEBUGS("Avatar") << "cof_version " << cof_version
- << " last_rcv " << last_rcv
- << " last_req " << last_req
- << " in flight " << mInFlightCounter
- << LL_ENDL;
- if (cof_version < last_rcv)
- {
- LL_DEBUGS("Avatar") << "Have already received update for cof version " << last_rcv
- << " will not request for " << cof_version << LL_ENDL;
- return false;
- }
- if (/*mInFlightCounter > 0 &&*/ last_req >= cof_version)
- {
- LL_DEBUGS("Avatar") << "Request already in flight for cof version " << last_req
- << " will not request for " << cof_version << LL_ENDL;
- return false;
- }
-
- // Actually send the request.
- LL_DEBUGS("Avatar") << "Will send request for cof_version " << cof_version << LL_ENDL;
- return true;
-}
-
std::string LLAppearanceMgr::getAppearanceServiceURL() const
{
if (gSavedSettings.getString("DebugAvatarAppearanceServiceURLOverride").empty())
diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h
index 9b6ceb7d3e..118648b7c3 100755
--- a/indra/newview/llappearancemgr.h
+++ b/indra/newview/llappearancemgr.h
@@ -225,15 +225,9 @@ public:
std::string getAppearanceServiceURL() const;
- bool testCOFRequestVersion() const;
- void decrementInFlightCounter()
- {
- mInFlightCounter = llmax(mInFlightCounter - 1, 0);
- }
-
private:
- void serverAppearanceUpdateSuccess(const LLSD &result);
+ void serverAppearanceUpdateCoro();
static void debugAppearanceUpdateCOF(const LLSD& content);
std::string mAppearanceServiceURL;
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index e13a9d96c7..564e2450e8 100755
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -57,8 +57,6 @@
#include "llfocusmgr.h"
#include "llviewerjoystick.h"
#include "llallocator.h"
-#include "llares.h"
-#include "llcurl.h"
#include "llcalc.h"
#include "llconversationlog.h"
#include "lldxhardware.h"
@@ -828,12 +826,7 @@ bool LLAppViewer::init()
// before consumers (LLTextureFetch).
mAppCoreHttp.init();
- // *NOTE:Mani - LLCurl::initClass is not thread safe.
- // Called before threads are created.
- LLCurl::initClass(gSavedSettings.getF32("CurlRequestTimeOut"),
- gSavedSettings.getS32("CurlMaximumNumberOfHandles"),
- gSavedSettings.getBOOL("CurlUseMultipleThreads"));
- LL_INFOS("InitInfo") << "LLCurl initialized." << LL_ENDL ;
+ LL_INFOS("InitInfo") << "LLCore::Http initialized." << LL_ENDL ;
LLMachineID::init();
@@ -903,7 +896,7 @@ bool LLAppViewer::init()
// the libs involved in getting to a full login screen.
//
LL_INFOS("InitInfo") << "J2C Engine is: " << LLImageJ2C::getEngineInfo() << LL_ENDL;
- LL_INFOS("InitInfo") << "libcurl version is: " << LLCurl::getVersionString() << LL_ENDL;
+ LL_INFOS("InitInfo") << "libcurl version is: " << LLCore::LLHttp::getCURLVersion() << LL_ENDL;
/////////////////////////////////////////////////
// OS-specific login dialogs
@@ -1160,8 +1153,6 @@ bool LLAppViewer::init()
{
LLNotificationsUtil::add("CorruptedProtectedDataStore");
}
- LLHTTPClient::setCertVerifyCallback(secapiSSLCertVerifyCallback);
-
gGLActive = FALSE;
@@ -1291,7 +1282,6 @@ static LLTrace::BlockTimerStatHandle FTM_LFS("LFS Thread");
static LLTrace::BlockTimerStatHandle FTM_PAUSE_THREADS("Pause Threads");
static LLTrace::BlockTimerStatHandle FTM_IDLE("Idle");
static LLTrace::BlockTimerStatHandle FTM_PUMP("Pump");
-static LLTrace::BlockTimerStatHandle FTM_PUMP_ARES("Ares");
static LLTrace::BlockTimerStatHandle FTM_PUMP_SERVICE("Service");
static LLTrace::BlockTimerStatHandle FTM_SERVICE_CALLBACK("Callback");
static LLTrace::BlockTimerStatHandle FTM_AGENT_AUTOPILOT("Autopilot");
@@ -1315,8 +1305,6 @@ bool LLAppViewer::mainLoop()
// Create IO Pump to use for HTTP Requests.
gServicePump = new LLPumpIO(gAPRPoolp);
- LLHTTPClient::setPump(*gServicePump);
- LLCurl::setCAFile(gDirUtilp->getCAFile());
// Note: this is where gLocalSpeakerMgr and gActiveSpeakerMgr used to be instantiated.
@@ -1435,26 +1423,6 @@ bool LLAppViewer::mainLoop()
LL_RECORD_BLOCK_TIME(FTM_IDLE);
idle();
- if (gAres != NULL && gAres->isInitialized())
- {
- pingMainloopTimeout("Main:ServicePump");
- LL_RECORD_BLOCK_TIME(FTM_PUMP);
- {
- LL_RECORD_BLOCK_TIME(FTM_PUMP_ARES);
- gAres->process();
- }
- {
- LL_RECORD_BLOCK_TIME(FTM_PUMP_SERVICE);
- // this pump is necessary to make the login screen show up
- gServicePump->pump();
-
- {
- LL_RECORD_BLOCK_TIME(FTM_SERVICE_CALLBACK);
- gServicePump->callback();
- }
- }
- }
-
resumeMainloopTimeout();
}
@@ -1559,11 +1527,6 @@ bool LLAppViewer::mainLoop()
}
gMeshRepo.update() ;
- if(!LLCurl::getCurlThread()->update(1))
- {
- LLCurl::getCurlThread()->pause() ; //nothing in the curl thread.
- }
-
if(!total_work_pending) //pause texture fetching threads if nothing to process.
{
LLAppViewer::getTextureCache()->pause();
@@ -1801,13 +1764,14 @@ bool LLAppViewer::cleanup()
if (gAudiop)
{
- // shut down the streaming audio sub-subsystem first, in case it relies on not outliving the general audio subsystem.
-
- LLStreamingAudioInterface *sai = gAudiop->getStreamingAudioImpl();
+ // be sure to stop the internet stream cleanly BEFORE destroying the interface to stop it.
+ gAudiop->stopInternetStream();
+ // shut down the streaming audio sub-subsystem first, in case it relies on not outliving the general audio subsystem.
+ LLStreamingAudioInterface *sai = gAudiop->getStreamingAudioImpl();
delete sai;
gAudiop->setStreamingAudioImpl(NULL);
- // shut down the audio subsystem
+ // shut down the audio subsystem
gAudiop->shutdown();
delete gAudiop;
@@ -2001,7 +1965,6 @@ bool LLAppViewer::cleanup()
pending += LLAppViewer::getTextureFetch()->update(1); // unpauses the texture fetch thread
pending += LLVFSThread::updateClass(0);
pending += LLLFSThread::updateClass(0);
- pending += LLCurl::getCurlThread()->update(1) ;
F64 idle_time = idleTimer.getElapsedTimeF64();
if(!pending)
{
@@ -2013,7 +1976,6 @@ bool LLAppViewer::cleanup()
break;
}
}
- LLCurl::getCurlThread()->pause() ;
// Delete workers first
// shotdown all worker threads before deleting them in case of co-dependencies
@@ -2028,17 +1990,9 @@ bool LLAppViewer::cleanup()
LL_INFOS() << "Shutting down message system" << LL_ENDL;
end_messaging_system();
- // *NOTE:Mani - The following call is not thread safe.
- LL_CHECK_MEMORY
- LLCurl::cleanupClass();
- LL_CHECK_MEMORY
-
// Non-LLCurl libcurl library
mAppCoreHttp.cleanup();
- // NOTE The following call is not thread safe.
- ll_cleanup_ares();
-
LLFilePickerThread::cleanupClass();
//MUST happen AFTER LLCurl::cleanupClass
@@ -2124,6 +2078,7 @@ bool LLAppViewer::cleanup()
}
LL_INFOS() << "Cleaning up LLProxy." << LL_ENDL;
LLProxy::cleanupClass();
+ LLCore::LLHttp::cleanup();
LLWearableType::cleanupClass();
@@ -2793,10 +2748,12 @@ bool LLAppViewer::initConfiguration()
//
gWindowTitle = LLTrans::getString("APP_NAME");
#if LL_DEBUG
- gWindowTitle += std::string(" [DEBUG] ") + gArgs;
-#else
- gWindowTitle += std::string(" ") + gArgs;
+ gWindowTitle += std::string(" [DEBUG]")
#endif
+ if (!gArgs.empty())
+ {
+ gWindowTitle += std::string(" ") + gArgs;
+ }
LLStringUtil::truncate(gWindowTitle, 255);
//RN: if we received a URL, hand it off to the existing instance.
@@ -3363,7 +3320,7 @@ LLSD LLAppViewer::getViewerInfo() const
#endif
info["OPENGL_VERSION"] = (const char*)(glGetString(GL_VERSION));
- info["LIBCURL_VERSION"] = LLCurl::getVersionString();
+ info["LIBCURL_VERSION"] = LLCore::LLHttp::getCURLVersion();
info["J2C_VERSION"] = LLImageJ2C::getEngineInfo();
bool want_fullname = true;
info["AUDIO_DRIVER_VERSION"] = gAudiop ? LLSD(gAudiop->getDriverName(want_fullname)) : LLSD();
@@ -4931,6 +4888,7 @@ void LLAppViewer::idle()
gIdleCallbacks.callFunctions();
gInventory.idleNotifyObservers();
+ LLAvatarTracker::instance().idleNotifyObservers();
}
// Metrics logging (LLViewerAssetStats, etc.)
diff --git a/indra/newview/llappviewermacosx.cpp b/indra/newview/llappviewermacosx.cpp
index 56154a2de3..09227806fd 100755
--- a/indra/newview/llappviewermacosx.cpp
+++ b/indra/newview/llappviewermacosx.cpp
@@ -62,9 +62,10 @@ namespace
// They are not used immediately by the app.
int gArgC;
char** gArgV;
- LLAppViewerMacOSX* gViewerAppPtr;
+ LLAppViewerMacOSX* gViewerAppPtr = NULL;
void (*gOldTerminateHandler)() = NULL;
+ std::string gHandleSLURL;
}
static void exceptionTerminateHandler()
@@ -107,7 +108,11 @@ bool initViewer()
{
LL_WARNS() << "Application init failed." << LL_ENDL;
}
-
+ else if (!gHandleSLURL.empty())
+ {
+ dispatchUrl(gHandleSLURL);
+ gHandleSLURL = "";
+ }
return ok;
}
@@ -393,22 +398,31 @@ bool LLAppViewerMacOSX::getMasterSystemAudioMute()
void handleUrl(const char* url_utf8)
{
- if (url_utf8)
+ if (url_utf8 && gViewerAppPtr)
{
- std::string url = url_utf8;
- // Safari 3.2 silently mangles secondlife:///app/ URLs into
- // secondlife:/app/ (only one leading slash).
- // Fix them up to meet the URL specification. JC
- const std::string prefix = "secondlife:/app/";
- std::string test_prefix = url.substr(0, prefix.length());
- LLStringUtil::toLower(test_prefix);
- if (test_prefix == prefix)
- {
- url.replace(0, prefix.length(), "secondlife:///app/");
- }
-
- LLMediaCtrl* web = NULL;
- const bool trusted_browser = false;
- LLURLDispatcher::dispatch(url, "", web, trusted_browser);
+ gHandleSLURL = "";
+ dispatchUrl(url_utf8);
}
+ else if (url_utf8)
+ {
+ gHandleSLURL = url_utf8;
+ }
+}
+
+void dispatchUrl(std::string url)
+{
+ // Safari 3.2 silently mangles secondlife:///app/ URLs into
+ // secondlife:/app/ (only one leading slash).
+ // Fix them up to meet the URL specification. JC
+ const std::string prefix = "secondlife:/app/";
+ std::string test_prefix = url.substr(0, prefix.length());
+ LLStringUtil::toLower(test_prefix);
+ if (test_prefix == prefix)
+ {
+ url.replace(0, prefix.length(), "secondlife:///app/");
+ }
+
+ LLMediaCtrl* web = NULL;
+ const bool trusted_browser = false;
+ LLURLDispatcher::dispatch(url, "", web, trusted_browser);
}
diff --git a/indra/newview/llavatariconctrl.cpp b/indra/newview/llavatariconctrl.cpp
index 281e591b48..25a5df9781 100755
--- a/indra/newview/llavatariconctrl.cpp
+++ b/indra/newview/llavatariconctrl.cpp
@@ -311,6 +311,7 @@ bool LLAvatarIconCtrl::updateFromCache()
else
{
LLIconCtrl::setValue(mDefaultIconName);
+ return false;
}
return true;
diff --git a/indra/newview/llavatarrenderinfoaccountant.cpp b/indra/newview/llavatarrenderinfoaccountant.cpp
index e260142254..470f516db2 100644
--- a/indra/newview/llavatarrenderinfoaccountant.cpp
+++ b/indra/newview/llavatarrenderinfoaccountant.cpp
@@ -67,7 +67,7 @@ void LLAvatarRenderInfoAccountant::avatarRenderInfoGetCoro(std::string url, U64
httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("AvatarRenderInfoAccountant", httpPolicy));
LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
- LLSD result = httpAdapter->getAndYield(httpRequest, url);
+ LLSD result = httpAdapter->getAndSuspend(httpRequest, url);
LLViewerRegion * regionp = LLWorld::getInstance()->getRegionFromHandle(regionHandle);
if (!regionp)
@@ -190,7 +190,7 @@ void LLAvatarRenderInfoAccountant::avatarRenderInfoReportCoro(std::string url, U
report[KEY_AGENTS] = agents;
regionp = NULL;
- LLSD result = httpAdapter->postAndYield(httpRequest, url, report);
+ LLSD result = httpAdapter->postAndSuspend(httpRequest, url, report);
regionp = LLWorld::getInstance()->getRegionFromHandle(regionHandle);
if (!regionp)
diff --git a/indra/newview/llcallbacklist.cpp b/indra/newview/llcallbacklist.cpp
index 59ecbdd0ea..59ecbdd0ea 100755..100644
--- a/indra/newview/llcallbacklist.cpp
+++ b/indra/newview/llcallbacklist.cpp
diff --git a/indra/newview/llcallbacklist.h b/indra/newview/llcallbacklist.h
deleted file mode 100755
index 0516c9cdb4..0000000000
--- a/indra/newview/llcallbacklist.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/**
- * @file llcallbacklist.h
- * @brief A simple list of callback functions to call.
- *
- * $LicenseInfo:firstyear=2001&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLCALLBACKLIST_H
-#define LL_LLCALLBACKLIST_H
-
-#include "llstl.h"
-
-class LLCallbackList
-{
-public:
- typedef void (*callback_t)(void*);
-
- LLCallbackList();
- ~LLCallbackList();
-
- void addFunction( callback_t func, void *data = NULL ); // register a callback, which will be called as func(data)
- BOOL containsFunction( callback_t func, void *data = NULL ); // true if list already contains the function/data pair
- BOOL deleteFunction( callback_t func, void *data = NULL ); // removes the first instance of this function/data pair from the list, false if not found
- void callFunctions(); // calls all functions
- void deleteAllFunctions();
-
- static void test();
-
-protected:
- // Use a list so that the callbacks are ordered in case that matters
- typedef std::pair<callback_t,void*> callback_pair_t;
- typedef std::list<callback_pair_t > callback_list_t;
- callback_list_t mCallbackList;
-};
-
-typedef boost::function<void ()> nullary_func_t;
-typedef boost::function<bool ()> bool_func_t;
-
-// Call a given callable once in idle loop.
-void doOnIdleOneTime(nullary_func_t callable);
-
-// Repeatedly call a callable in idle loop until it returns true.
-void doOnIdleRepeating(bool_func_t callable);
-
-// Call a given callable once after specified interval.
-void doAfterInterval(nullary_func_t callable, F32 seconds);
-
-// Call a given callable every specified number of seconds, until it returns true.
-void doPeriodically(bool_func_t callable, F32 seconds);
-
-extern LLCallbackList gIdleCallbacks;
-
-#endif
diff --git a/indra/newview/llcallingcard.cpp b/indra/newview/llcallingcard.cpp
index b6c5496c17..f79d1aa609 100755
--- a/indra/newview/llcallingcard.cpp
+++ b/indra/newview/llcallingcard.cpp
@@ -97,7 +97,8 @@ static void on_avatar_name_cache_notify(const LLUUID& agent_id,
LLAvatarTracker::LLAvatarTracker() :
mTrackingData(NULL),
mTrackedAgentValid(false),
- mModifyMask(0x0)
+ mModifyMask(0x0),
+ mIsNotifyObservers(FALSE)
{
}
@@ -272,7 +273,7 @@ S32 LLAvatarTracker::addBuddyList(const LLAvatarTracker::buddy_map_t& buds)
<< "]" << LL_ENDL;
}
}
- notifyObservers();
+ // do not notify observers here - list can be large so let it be done on idle.
return new_buddy_count;
}
@@ -473,8 +474,25 @@ void LLAvatarTracker::removeObserver(LLFriendObserver* observer)
mObservers.end());
}
+void LLAvatarTracker::idleNotifyObservers()
+{
+ if (mModifyMask == LLFriendObserver::NONE && mChangedBuddyIDs.size() == 0)
+ {
+ return;
+ }
+ notifyObservers();
+}
+
void LLAvatarTracker::notifyObservers()
{
+ if (mIsNotifyObservers)
+ {
+ // Don't allow multiple calls.
+ // new masks and ids will be processed later from idle.
+ return;
+ }
+ mIsNotifyObservers = TRUE;
+
observer_list_t observers(mObservers);
observer_list_t::iterator it = observers.begin();
observer_list_t::iterator end = observers.end();
@@ -490,6 +508,7 @@ void LLAvatarTracker::notifyObservers()
mModifyMask = LLFriendObserver::NONE;
mChangedBuddyIDs.clear();
+ mIsNotifyObservers = FALSE;
}
void LLAvatarTracker::addParticularFriendObserver(const LLUUID& buddy_id, LLFriendObserver* observer)
@@ -531,7 +550,7 @@ void LLAvatarTracker::notifyParticularFriendObservers(const LLUUID& buddy_id)
// store flag for change
// and id of object change applies to
void LLAvatarTracker::addChangedMask(U32 mask, const LLUUID& referent)
-{
+{
mModifyMask |= mask;
if (referent.notNull())
{
diff --git a/indra/newview/llcallingcard.h b/indra/newview/llcallingcard.h
index 6e5fc01cd8..1f819a42fd 100755
--- a/indra/newview/llcallingcard.h
+++ b/indra/newview/llcallingcard.h
@@ -143,6 +143,7 @@ public:
// observers left behind.
void addObserver(LLFriendObserver* observer);
void removeObserver(LLFriendObserver* observer);
+ void idleNotifyObservers();
void notifyObservers();
// Observers interested in updates of a particular avatar.
@@ -209,6 +210,8 @@ private:
LLAvatarTracker(const LLAvatarTracker&);
bool operator==(const LLAvatarTracker&);
+ BOOL mIsNotifyObservers;
+
public:
// don't you dare create or delete this object
LLAvatarTracker();
diff --git a/indra/newview/llchannelmanager.cpp b/indra/newview/llchannelmanager.cpp
index b0537a83f1..d6240838b6 100755
--- a/indra/newview/llchannelmanager.cpp
+++ b/indra/newview/llchannelmanager.cpp
@@ -35,6 +35,7 @@
#include "llviewerwindow.h"
#include "llrootview.h"
#include "llsyswellwindow.h"
+#include "llfloaternotificationstabbed.h"
#include "llfloaterreg.h"
#include <algorithm>
@@ -131,7 +132,7 @@ void LLChannelManager::onLoginCompleted()
S32 channel_right_bound = gViewerWindow->getWorldViewRectScaled().mRight - gSavedSettings.getS32("NotificationChannelRightMargin");
S32 channel_width = gSavedSettings.getS32("NotifyBoxWidth");
mStartUpChannel->init(channel_right_bound - channel_width, channel_right_bound);
- mStartUpChannel->setMouseDownCallback(boost::bind(&LLNotificationWellWindow::onStartUpToastClick, LLNotificationWellWindow::getInstance(), _2, _3, _4));
+ mStartUpChannel->setMouseDownCallback(boost::bind(&LLFloaterNotificationsTabbed::onStartUpToastClick, LLFloaterNotificationsTabbed::getInstance(), _2, _3, _4));
mStartUpChannel->setCommitCallback(boost::bind(&LLChannelManager::onStartUpToastClose, this));
mStartUpChannel->createStartUpToast(away_notifications, gSavedSettings.getS32("StartUpToastLifeTime"));
diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp
index b81b95462e..dc0835eb1c 100755
--- a/indra/newview/llchathistory.cpp
+++ b/indra/newview/llchathistory.cpp
@@ -376,6 +376,10 @@ public:
|| mSourceType == CHAT_SOURCE_SYSTEM)
{
mFrom = LLTrans::getString("SECOND_LIFE");
+ if(!chat.mFromName.empty() && (mFrom != chat.mFromName))
+ {
+ mFrom += " (" + chat.mFromName + ")";
+ }
user_name->setValue(mFrom);
updateMinUserNameWidth();
}
diff --git a/indra/newview/llchiclet.cpp b/indra/newview/llchiclet.cpp
index 46b7679915..dedb06c945 100755
--- a/indra/newview/llchiclet.cpp
+++ b/indra/newview/llchiclet.cpp
@@ -35,6 +35,7 @@
#include "llscriptfloater.h"
#include "llsingleton.h"
#include "llsyswellwindow.h"
+#include "llfloaternotificationstabbed.h"
static LLDefaultChildRegistry::Register<LLChicletPanel> t1("chiclet_panel");
static LLDefaultChildRegistry::Register<LLNotificationChiclet> t2("chiclet_notification");
@@ -165,7 +166,7 @@ LLNotificationChiclet::LLNotificationChiclet(const Params& p)
mNotificationChannel.reset(new ChicletNotificationChannel(this));
// ensure that notification well window exists, to synchronously
// handle toast add/delete events.
- LLNotificationWellWindow::getInstance()->setSysWellChiclet(this);
+ LLFloaterNotificationsTabbed::getInstance()->setSysWellChiclet(this);
}
void LLNotificationChiclet::onMenuItemClicked(const LLSD& user_data)
@@ -173,7 +174,7 @@ void LLNotificationChiclet::onMenuItemClicked(const LLSD& user_data)
std::string action = user_data.asString();
if("close all" == action)
{
- LLNotificationWellWindow::getInstance()->closeAll();
+ LLFloaterNotificationsTabbed::getInstance()->closeAll();
LLIMWellWindow::getInstance()->closeAll();
}
}
@@ -224,7 +225,8 @@ bool LLNotificationChiclet::ChicletNotificationChannel::filterNotification( LLNo
bool displayNotification;
if ( (notification->getName() == "ScriptDialog") // special case for scripts
// if there is no toast window for the notification, filter it
- || (!LLNotificationWellWindow::getInstance()->findItemByID(notification->getID()))
+ //|| (!LLNotificationWellWindow::getInstance()->findItemByID(notification->getID()))
+ || (!LLFloaterNotificationsTabbed::getInstance()->findItemByID(notification->getID(), notification->getName()))
)
{
displayNotification = false;
diff --git a/indra/newview/llchicletbar.cpp b/indra/newview/llchicletbar.cpp
index d8b04f7004..254e3f61a8 100755
--- a/indra/newview/llchicletbar.cpp
+++ b/indra/newview/llchicletbar.cpp
@@ -31,6 +31,7 @@
#include "lllayoutstack.h"
#include "llpaneltopinfobar.h"
#include "llsyswellwindow.h"
+#include "llfloaternotificationstabbed.h"
namespace
{
@@ -49,7 +50,7 @@ BOOL LLChicletBar::postBuild()
mToolbarStack = getChild<LLLayoutStack>("toolbar_stack");
mChicletPanel = getChild<LLChicletPanel>("chiclet_list");
- showWellButton("notification_well", !LLNotificationWellWindow::getInstance()->isWindowEmpty());
+ showWellButton("notification_well", !LLFloaterNotificationsTabbed::getInstance()->isWindowEmpty());
LLPanelTopInfoBar::instance().setResizeCallback(boost::bind(&LLChicletBar::fitWithTopInfoBar, this));
LLPanelTopInfoBar::instance().setVisibleCallback(boost::bind(&LLChicletBar::fitWithTopInfoBar, this));
diff --git a/indra/newview/llcommandhandler.cpp b/indra/newview/llcommandhandler.cpp
index 19dba3f917..5ea7efc045 100755
--- a/indra/newview/llcommandhandler.cpp
+++ b/indra/newview/llcommandhandler.cpp
@@ -30,6 +30,7 @@
#include "llcommandhandler.h"
#include "llnotificationsutil.h"
#include "llcommanddispatcherlistener.h"
+#include "llstartup.h"
#include "stringize.h"
// system includes
@@ -116,7 +117,11 @@ bool LLCommandHandlerRegistry::dispatch(const std::string& cmd,
LL_WARNS_ONCE("SLURL") << "Blocked SLURL command from untrusted browser" << LL_ENDL;
if (! slurl_blocked)
{
- LLNotificationsUtil::add("BlockedSLURL");
+ if (LLStartUp::getStartupState() >= STATE_BROWSER_INIT)
+ {
+ // Note: commands can arrive before we initialize everything we need for Notification.
+ LLNotificationsUtil::add("BlockedSLURL");
+ }
slurl_blocked = true;
}
return true;
@@ -138,7 +143,10 @@ bool LLCommandHandlerRegistry::dispatch(const std::string& cmd,
LL_WARNS_ONCE("SLURL") << "Throttled SLURL command from untrusted browser" << LL_ENDL;
if (! slurl_throttled)
{
- LLNotificationsUtil::add("ThrottledSLURL");
+ if (LLStartUp::getStartupState() >= STATE_BROWSER_INIT)
+ {
+ LLNotificationsUtil::add("ThrottledSLURL");
+ }
slurl_throttled = true;
}
return true;
diff --git a/indra/newview/llcompilequeue.cpp b/indra/newview/llcompilequeue.cpp
index 9545771c8d..219bcf0eb0 100755
--- a/indra/newview/llcompilequeue.cpp
+++ b/indra/newview/llcompilequeue.cpp
@@ -57,7 +57,6 @@
#include "lltrans.h"
#include "llselectmgr.h"
-#include "llexperienceassociationresponder.h"
#include "llexperiencecache.h"
#include "llviewerassetupload.h"
@@ -358,8 +357,8 @@ void LLFloaterCompileQueue::handleInventory(LLViewerObject *viewer_object,
LLScriptQueueData* datap = new LLScriptQueueData(getKey().asUUID(),
viewer_object->getID(), itemp);
- ExperienceAssociationResponder::fetchAssociatedExperience(itemp->getParentUUID(), itemp->getUUID(),
- boost::bind(LLFloaterCompileQueue::requestAsset, datap, _1));
+ LLExperienceCache::instance().fetchAssociatedExperience(itemp->getParentUUID(), itemp->getUUID(),
+ boost::bind(&LLFloaterCompileQueue::requestAsset, datap, _1));
}
}
}
diff --git a/indra/newview/llconversationlog.h b/indra/newview/llconversationlog.h
index b38d472156..62f08144b9 100755
--- a/indra/newview/llconversationlog.h
+++ b/indra/newview/llconversationlog.h
@@ -153,6 +153,7 @@ public:
* file name is conversation.log
*/
std::string getFileName();
+ LLConversation* findConversation(const LLIMModel::LLIMSession* session);
private:
@@ -184,7 +185,7 @@ private:
void updateConversationName(const LLIMModel::LLIMSession* session, const std::string& name);
void updateOfflineIMs(const LLIMModel::LLIMSession* session, BOOL new_messages);
- LLConversation* findConversation(const LLIMModel::LLIMSession* session);
+
typedef std::vector<LLConversation> conversations_vec_t;
std::vector<LLConversation> mConversations;
diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp
index 6e32ce60ec..328a638f2f 100755
--- a/indra/newview/llconversationmodel.cpp
+++ b/indra/newview/llconversationmodel.cpp
@@ -136,7 +136,24 @@ void LLConversationItem::buildParticipantMenuOptions(menuentry_vec_t& items, U32
items.push_back(std::string("im"));
items.push_back(std::string("offer_teleport"));
items.push_back(std::string("request_teleport"));
- items.push_back(std::string("voice_call"));
+
+ if (getType() != CONV_SESSION_1_ON_1)
+ {
+ items.push_back(std::string("voice_call"));
+ }
+ else
+ {
+ LLVoiceChannel* voice_channel = LLIMModel::getInstance() ? LLIMModel::getInstance()->getVoiceChannel(this->getUUID()) : NULL;
+ if(voice_channel != LLVoiceChannel::getCurrentVoiceChannel())
+ {
+ items.push_back(std::string("voice_call"));
+ }
+ else
+ {
+ items.push_back(std::string("disconnect_from_voice"));
+ }
+ }
+
items.push_back(std::string("chat_history"));
items.push_back(std::string("separator_chat_history"));
items.push_back(std::string("add_friend"));
diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp
index 821d58a9b2..8bbc529244 100755
--- a/indra/newview/lldrawpoolavatar.cpp
+++ b/indra/newview/lldrawpoolavatar.cpp
@@ -1553,7 +1553,8 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(LLVOAvatar* avatar, LLFace*
(drawable && drawable->isState(LLDrawable::REBUILD_ALL)))
{
if (drawable && drawable->isState(LLDrawable::REBUILD_ALL))
- { //rebuild EVERY face in the drawable, not just this one, to avoid missing drawable wide rebuild issues
+ {
+ //rebuild EVERY face in the drawable, not just this one, to avoid missing drawable wide rebuild issues
for (S32 i = 0; i < drawable->getNumFaces(); ++i)
{
LLFace* facep = drawable->getFace(i);
@@ -1570,13 +1571,15 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(LLVOAvatar* avatar, LLFace*
buffer = face->getVertexBuffer();
}
else
- { //just rebuild this face
+ {
+ //just rebuild this face
getRiggedGeometry(face, buffer, data_mask, skin, volume, vol_face);
}
}
if (sShaderLevel <= 0 && face->mLastSkinTime < avatar->getLastSkinTime())
- { //perform software vertex skinning for this face
+ {
+ //perform software vertex skinning for this face
LLStrider<LLVector3> position;
LLStrider<LLVector3> normal;
@@ -1600,6 +1603,10 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(LLVOAvatar* avatar, LLFace*
for (U32 j = 0; j < count; ++j)
{
LLJoint* joint = avatar->getJoint(skin->mJointNames[j]);
+ if (!joint)
+ {
+ joint = avatar->getJoint("mPelvis");
+ }
if (joint)
{
mat[j] = skin->mInvBindMatrix[j];
@@ -1624,12 +1631,13 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(LLVOAvatar* avatar, LLFace*
{
F32 w = weight[j][k];
- idx[k] = llclamp((S32) floorf(w), 0, JOINT_COUNT-1);
+ idx[k] = llclamp((S32) floorf(w), (S32)0, (S32)JOINT_COUNT-1);
wght[k] = w - floorf(w);
scale += wght[k];
}
-
+ // This is enforced in unpackVolumeFaces()
+ llassert(scale>0.f);
wght *= 1.f/scale;
for (U32 k = 0; k < 4; k++)
@@ -1729,6 +1737,10 @@ void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow)
for (U32 i = 0; i < count; ++i)
{
LLJoint* joint = avatar->getJoint(skin->mJointNames[i]);
+ if (!joint)
+ {
+ joint = avatar->getJoint("mPelvis");
+ }
if (joint)
{
mat[i] = skin->mInvBindMatrix[i];
diff --git a/indra/newview/lldrawpoolbump.cpp b/indra/newview/lldrawpoolbump.cpp
index 33f7bc305c..7b9fd5c6c6 100755
--- a/indra/newview/lldrawpoolbump.cpp
+++ b/indra/newview/lldrawpoolbump.cpp
@@ -864,6 +864,7 @@ void LLDrawPoolBump::renderDeferred(S32 pass)
{
LLDrawInfo& params = **i;
+ gDeferredBumpProgram.setMinimumAlpha(params.mAlphaMaskCutoff);
LLDrawPoolBump::bindBumpMap(params, bump_channel);
pushBatch(params, mask, TRUE);
}
diff --git a/indra/newview/llestateinfomodel.cpp b/indra/newview/llestateinfomodel.cpp
index 884d1579e6..8f2eb41307 100755
--- a/indra/newview/llestateinfomodel.cpp
+++ b/indra/newview/llestateinfomodel.cpp
@@ -153,7 +153,7 @@ void LLEstateInfoModel::commitEstateInfoCapsCoro(std::string url)
<< ", sun_hour = " << getSunHour() << LL_ENDL;
LL_DEBUGS() << body << LL_ENDL;
- LLSD result = httpAdapter->postAndYield(httpRequest, url, body);
+ LLSD result = httpAdapter->postAndSuspend(httpRequest, url, body);
LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
diff --git a/indra/newview/lleventpoll.cpp b/indra/newview/lleventpoll.cpp
index 0aad1d5ba9..40eaba2bac 100755
--- a/indra/newview/lleventpoll.cpp
+++ b/indra/newview/lleventpoll.cpp
@@ -120,14 +120,18 @@ namespace Details
void LLEventPollImpl::stop()
{
- LL_INFOS() << "requesting stop for event poll coroutine <" << mCounter << ">" << LL_ENDL;
mDone = true;
LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t adapter = mAdapter.lock();
if (adapter)
{
+ LL_INFOS() << "requesting stop for event poll coroutine <" << mCounter << ">" << LL_ENDL;
// cancel the yielding operation if any.
- adapter->cancelYieldingOperation();
+ adapter->cancelSuspendedOperation();
+ }
+ else
+ {
+ LL_INFOS() << "Coroutine for poll <" << mCounter << "> previously stopped. No action taken." << LL_ENDL;
}
}
@@ -154,7 +158,7 @@ namespace Details
// << LLSDXMLStreamer(request) << LL_ENDL;
LL_DEBUGS("LLEventPollImpl") << " <" << counter << "> posting and yielding." << LL_ENDL;
- LLSD result = httpAdapter->postAndYield(mHttpRequest, url, request);
+ LLSD result = httpAdapter->postAndSuspend(mHttpRequest, url, request);
// LL_DEBUGS("LLEventPollImpl::eventPollCoro") << "<" << counter << "> result = "
// << LLSDXMLStreamer(result) << LL_ENDL;
@@ -179,6 +183,12 @@ namespace Details
LL_WARNS() << "Canceling coroutine" << LL_ENDL;
break;
}
+ else if (!status.isHttpStatus())
+ {
+ /// Some LLCore or LIBCurl error was returned. This is unlikely to be recoverable
+ LL_WARNS("LLEventPollImpl") << "Critical error from poll request returned from libraries. Canceling coroutine." << LL_ENDL;
+ break;
+ }
LL_WARNS("LLEventPollImpl") << "<" << counter << "> Error result from LLCoreHttpUtil::HttpCoroHandler. Code "
<< status.toTerseString() << ": '" << httpResults["message"] << "'" << LL_ENDL;
@@ -197,7 +207,7 @@ namespace Details
" seconds, error count is now " << errorCount << LL_ENDL;
timeout.eventAfter(waitToRetry, LLSD());
- llcoro::waitForEventOn(timeout);
+ llcoro::suspendUntilEventOn(timeout);
if (mDone)
break;
diff --git a/indra/newview/lleventpoll.h b/indra/newview/lleventpoll.h
index e32b4ed322..e2afd9226b 100755
--- a/indra/newview/lleventpoll.h
+++ b/indra/newview/lleventpoll.h
@@ -27,7 +27,6 @@
#ifndef LL_LLEVENTPOLL_H
#define LL_LLEVENTPOLL_H
-#include "llhttpclient.h"
#include "boost/move/unique_ptr.hpp"
namespace boost
diff --git a/indra/newview/llexperienceassociationresponder.cpp b/indra/newview/llexperienceassociationresponder.cpp
deleted file mode 100644
index cd4a7516b1..0000000000
--- a/indra/newview/llexperienceassociationresponder.cpp
+++ /dev/null
@@ -1,97 +0,0 @@
-/**
- * @file llexperienceassociationresponder.cpp
- * @brief llexperienceassociationresponder implementation. This class combines
- * a lookup for a script association and an experience details request. The first
- * is always async, but the second may be cached locally.
- *
- * $LicenseInfo:firstyear=2013&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2013, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#include "llviewerprecompiledheaders.h"
-#include "llexperienceassociationresponder.h"
-#include "llexperiencecache.h"
-#include "llviewerregion.h"
-#include "llagent.h"
-
-ExperienceAssociationResponder::ExperienceAssociationResponder(ExperienceAssociationResponder::callback_t callback):mCallback(callback)
-{
- ref();
-}
-
-void ExperienceAssociationResponder::fetchAssociatedExperience( const LLUUID& object_id, const LLUUID& item_id, callback_t callback )
-{
- LLSD request;
- request["object-id"]=object_id;
- request["item-id"]=item_id;
- fetchAssociatedExperience(request, callback);
-}
-
-void ExperienceAssociationResponder::fetchAssociatedExperience(LLSD& request, callback_t callback)
-{
- LLViewerRegion* region = gAgent.getRegion();
- if (region)
- {
- std::string lookup_url=region->getCapability("GetMetadata");
- if(!lookup_url.empty())
- {
- LLSD fields;
- fields.append("experience");
- request["fields"] = fields;
- LLHTTPClient::post(lookup_url, request, new ExperienceAssociationResponder(callback));
- }
- }
-}
-
-void ExperienceAssociationResponder::httpFailure()
-{
- LLSD msg;
- msg["error"]=(LLSD::Integer)getStatus();
- msg["message"]=getReason();
- LL_INFOS("ExperienceAssociation") << "Failed to look up associated experience: " << getStatus() << ": " << getReason() << LL_ENDL;
-
- sendResult(msg);
-
-}
-void ExperienceAssociationResponder::httpSuccess()
-{
- if(!getContent().has("experience"))
- {
-
- LLSD msg;
- msg["message"]="no experience";
- msg["error"]=-1;
- sendResult(msg);
- return;
- }
-
- LLExperienceCache::getInstance()->get(getContent()["experience"].asUUID(), boost::bind(&ExperienceAssociationResponder::sendResult, this, _1));
-
-}
-
-void ExperienceAssociationResponder::sendResult( const LLSD& experience )
-{
- mCallback(experience);
- unref();
-}
-
-
-
diff --git a/indra/newview/llexperienceassociationresponder.h b/indra/newview/llexperienceassociationresponder.h
deleted file mode 100644
index 2bdc3d251b..0000000000
--- a/indra/newview/llexperienceassociationresponder.h
+++ /dev/null
@@ -1,58 +0,0 @@
-#include "llhttpclient.h"
-#include "llsd.h"
-/**
- * @file llexperienceassociationresponder.h
- * @brief llexperienceassociationresponder and related class definitions
- *
- * $LicenseInfo:firstyear=2013&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2013, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-
-
-#ifndef LL_LLEXPERIENCEASSOCIATIONRESPONDER_H
-#define LL_LLEXPERIENCEASSOCIATIONRESPONDER_H
-
-#include "llhttpclient.h"
-#include "llsd.h"
-
-class ExperienceAssociationResponder : public LLHTTPClient::Responder
-{
-public:
- typedef boost::function<void(const LLSD& experience)> callback_t;
-
- ExperienceAssociationResponder(callback_t callback);
-
- /*virtual*/ void httpSuccess();
- /*virtual*/ void httpFailure();
-
- static void fetchAssociatedExperience(const LLUUID& object_it, const LLUUID& item_id, callback_t callback);
-
-private:
- static void fetchAssociatedExperience(LLSD& request, callback_t callback);
-
- void sendResult(const LLSD& experience);
-
- callback_t mCallback;
-
-};
-
-#endif // LL_LLEXPERIENCEASSOCIATIONRESPONDER_H
diff --git a/indra/newview/llfacebookconnect.cpp b/indra/newview/llfacebookconnect.cpp
index 136e02953c..1de4102dba 100755
--- a/indra/newview/llfacebookconnect.cpp
+++ b/indra/newview/llfacebookconnect.cpp
@@ -165,9 +165,7 @@ void LLFacebookConnect::facebookConnectCoro(std::string authCode, std::string au
httpOpts->setWantHeaders(true);
httpOpts->setFollowRedirects(false);
- setConnectionState(LLFacebookConnect::FB_CONNECTION_IN_PROGRESS);
-
- LLSD result = httpAdapter->putAndYield(httpRequest, getFacebookConnectURL("/connection"), putData, httpOpts, get_headers());
+ LLSD result = httpAdapter->putAndSuspend(httpRequest, getFacebookConnectURL("/connection"), putData, httpOpts, get_headers());
LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
@@ -242,9 +240,7 @@ void LLFacebookConnect::facebookShareCoro(std::string route, LLSD share)
httpOpts->setWantHeaders(true);
httpOpts->setFollowRedirects(false);
- setConnectionState(LLFacebookConnect::FB_POSTING);
-
- LLSD result = httpAdapter->postAndYield(httpRequest, getFacebookConnectURL(route, true), share, httpOpts, get_headers());
+ LLSD result = httpAdapter->postAndSuspend(httpRequest, getFacebookConnectURL(route, true), share, httpOpts, get_headers());
if (testShareStatus(result))
{
@@ -311,7 +307,7 @@ void LLFacebookConnect::facebookShareImageCoro(std::string route, LLPointer<LLIm
setConnectionState(LLFacebookConnect::FB_POSTING);
- LLSD result = httpAdapter->postAndYield(httpRequest, getFacebookConnectURL(route, true), raw, httpOpts, httpHeaders);
+ LLSD result = httpAdapter->postAndSuspend(httpRequest, getFacebookConnectURL(route, true), raw, httpOpts, httpHeaders);
if (testShareStatus(result))
{
@@ -331,10 +327,9 @@ void LLFacebookConnect::facebookDisconnectCoro()
LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions);
- setConnectionState(LLFacebookConnect::FB_DISCONNECTING);
httpOpts->setFollowRedirects(false);
- LLSD result = httpAdapter->deleteAndYield(httpRequest, getFacebookConnectURL("/connection"), httpOpts, get_headers());
+ LLSD result = httpAdapter->deleteAndSuspend(httpRequest, getFacebookConnectURL("/connection"), httpOpts, get_headers());
LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
@@ -370,7 +365,7 @@ void LLFacebookConnect::facebookConnectedCheckCoro(bool autoConnect)
httpOpts->setFollowRedirects(false);
- LLSD result = httpAdapter->getAndYield(httpRequest, getFacebookConnectURL("/connection", true), httpOpts, get_headers());
+ LLSD result = httpAdapter->getAndSuspend(httpRequest, getFacebookConnectURL("/connection", true), httpOpts, get_headers());
LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
@@ -418,7 +413,7 @@ void LLFacebookConnect::facebookConnectInfoCoro()
httpOpts->setWantHeaders(true);
httpOpts->setFollowRedirects(false);
- LLSD result = httpAdapter->getAndYield(httpRequest, getFacebookConnectURL("/info", true), httpOpts, get_headers());
+ LLSD result = httpAdapter->getAndSuspend(httpRequest, getFacebookConnectURL("/info", true), httpOpts, get_headers());
LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
@@ -461,7 +456,7 @@ void LLFacebookConnect::facebookConnectFriendsCoro()
httpOpts->setFollowRedirects(false);
- LLSD result = httpAdapter->getAndYield(httpRequest, getFacebookConnectURL("/friends", true), httpOpts, get_headers());
+ LLSD result = httpAdapter->getAndSuspend(httpRequest, getFacebookConnectURL("/friends", true), httpOpts, get_headers());
LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
@@ -546,6 +541,8 @@ std::string LLFacebookConnect::getFacebookConnectURL(const std::string& route, b
void LLFacebookConnect::connectToFacebook(const std::string& auth_code, const std::string& auth_state)
{
+ setConnectionState(LLFacebookConnect::FB_CONNECTION_IN_PROGRESS);
+
LLCoros::instance().launch("LLFacebookConnect::facebookConnectCoro",
boost::bind(&LLFacebookConnect::facebookConnectCoro, this, auth_code, auth_state));
}
@@ -558,6 +555,8 @@ void LLFacebookConnect::disconnectFromFacebook()
void LLFacebookConnect::checkConnectionToFacebook(bool auto_connect)
{
+ setConnectionState(LLFacebookConnect::FB_DISCONNECTING);
+
LLCoros::instance().launch("LLFacebookConnect::facebookConnectedCheckCoro",
boost::bind(&LLFacebookConnect::facebookConnectedCheckCoro, this, auto_connect));
}
@@ -583,6 +582,8 @@ void LLFacebookConnect::loadFacebookFriends()
void LLFacebookConnect::postCheckin(const std::string& location, const std::string& name,
const std::string& description, const std::string& image, const std::string& message)
{
+ setConnectionState(LLFacebookConnect::FB_POSTING);
+
LLSD body;
if (!location.empty())
{
@@ -611,7 +612,8 @@ void LLFacebookConnect::postCheckin(const std::string& location, const std::stri
void LLFacebookConnect::sharePhoto(const std::string& image_url, const std::string& caption)
{
- // *TODO: I could not find an instace where this method is used. Remove?
+ setConnectionState(LLFacebookConnect::FB_POSTING);
+
LLSD body;
body["image"] = image_url;
body["caption"] = caption;
@@ -622,6 +624,8 @@ void LLFacebookConnect::sharePhoto(const std::string& image_url, const std::stri
void LLFacebookConnect::sharePhoto(LLPointer<LLImageFormatted> image, const std::string& caption)
{
+ setConnectionState(LLFacebookConnect::FB_POSTING);
+
LLCoros::instance().launch("LLFacebookConnect::facebookShareImageCoro",
boost::bind(&LLFacebookConnect::facebookShareImageCoro, this, "/share/photo", image, caption));
}
@@ -631,6 +635,8 @@ void LLFacebookConnect::updateStatus(const std::string& message)
LLSD body;
body["message"] = message;
+ setConnectionState(LLFacebookConnect::FB_POSTING);
+
LLCoros::instance().launch("LLFacebookConnect::facebookShareCoro",
boost::bind(&LLFacebookConnect::facebookShareCoro, this, "/share/wall", body));
}
diff --git a/indra/newview/llfavoritesbar.cpp b/indra/newview/llfavoritesbar.cpp
index f2b369a9ad..8f3eaaa207 100755
--- a/indra/newview/llfavoritesbar.cpp
+++ b/indra/newview/llfavoritesbar.cpp
@@ -380,9 +380,11 @@ LLFavoritesBarCtrl::LLFavoritesBarCtrl(const LLFavoritesBarCtrl::Params& p)
mShowDragMarker(FALSE),
mLandingTab(NULL),
mLastTab(NULL),
- mTabsHighlightEnabled(TRUE)
- , mUpdateDropDownItems(true)
-, mRestoreOverflowMenu(false)
+ mTabsHighlightEnabled(TRUE),
+ mUpdateDropDownItems(true),
+ mRestoreOverflowMenu(false),
+ mGetPrevItems(true),
+ mItemsChangedTimer()
{
// Register callback for menus with current registrar (will be parent panel's registrar)
LLUICtrl::CommitCallbackRegistry::currentRegistrar().add("Favorites.DoToSelected",
@@ -659,6 +661,15 @@ void LLFavoritesBarCtrl::changed(U32 mask)
LLFavoritesOrderStorage::instance().getSLURL((*i)->getAssetUUID());
}
updateButtons();
+ if (!mItemsChangedTimer.getStarted())
+ {
+ mItemsChangedTimer.start();
+ }
+ else
+ {
+ mItemsChangedTimer.reset();
+ }
+
}
}
@@ -693,6 +704,21 @@ void LLFavoritesBarCtrl::draw()
// Once drawn, mark this false so we won't draw it again (unless we hit the favorite bar again)
mShowDragMarker = FALSE;
}
+ if (mItemsChangedTimer.getStarted())
+ {
+ if (mItemsChangedTimer.getElapsedTimeF32() > 1.f)
+ {
+ LLFavoritesOrderStorage::instance().saveFavoritesRecord();
+ mItemsChangedTimer.stop();
+ }
+ }
+
+ if(!mItemsChangedTimer.getStarted() && LLFavoritesOrderStorage::instance().mUpdateRequired)
+ {
+ LLFavoritesOrderStorage::instance().mUpdateRequired = false;
+ mItemsChangedTimer.start();
+ }
+
}
const LLButton::Params& LLFavoritesBarCtrl::getButtonParams()
@@ -723,6 +749,12 @@ void LLFavoritesBarCtrl::updateButtons()
return;
}
+ if(mGetPrevItems)
+ {
+ LLFavoritesOrderStorage::instance().mPrevFavorites = mItems;
+ mGetPrevItems = false;
+ }
+
const LLButton::Params& button_params = getButtonParams();
if(mItems.empty())
@@ -844,6 +876,7 @@ void LLFavoritesBarCtrl::updateButtons()
{
mUpdateDropDownItems = false;
}
+
}
LLButton* LLFavoritesBarCtrl::createButton(const LLPointer<LLViewerInventoryItem> item, const LLButton::Params& button_params, S32 x_offset)
@@ -912,9 +945,11 @@ BOOL LLFavoritesBarCtrl::postBuild()
BOOL LLFavoritesBarCtrl::collectFavoriteItems(LLInventoryModel::item_array_t &items)
{
+
if (mFavoriteFolderId.isNull())
return FALSE;
+
LLInventoryModel::cat_array_t cats;
LLIsType is_type(LLAssetType::AT_LANDMARK);
@@ -1411,6 +1446,7 @@ void LLFavoritesBarCtrl::insertItem(LLInventoryModel::item_array_t& items, const
const std::string LLFavoritesOrderStorage::SORTING_DATA_FILE_NAME = "landmarks_sorting.xml";
const S32 LLFavoritesOrderStorage::NO_INDEX = -1;
+bool LLFavoritesOrderStorage::mSaveOnExit = false;
void LLFavoritesOrderStorage::setSortIndex(const LLViewerInventoryItem* inv_item, S32 sort_index)
{
@@ -1447,6 +1483,7 @@ void LLFavoritesOrderStorage::getSLURL(const LLUUID& asset_id)
LL_DEBUGS("FavoritesBar") << "landmark for " << asset_id << " already loaded" << LL_ENDL;
onLandmarkLoaded(asset_id, lm);
}
+ return;
}
// static
@@ -1482,13 +1519,16 @@ void LLFavoritesOrderStorage::destroyClass()
LLFile::remove(old_filename);
}
- if (gSavedPerAccountSettings.getBOOL("ShowFavoritesOnLogin"))
- {
- LLFavoritesOrderStorage::instance().saveFavoritesSLURLs();
- }
- else
+ std::string filename = getSavedOrderFileName();
+ file.open(filename.c_str());
+ if (file.is_open())
{
- LLFavoritesOrderStorage::instance().removeFavoritesRecordOfUser();
+ file.close();
+ LLFile::remove(filename);
+ if(mSaveOnExit)
+ {
+ LLFavoritesOrderStorage::instance().saveFavoritesRecord(true);
+ }
}
}
@@ -1503,108 +1543,57 @@ std::string LLFavoritesOrderStorage::getSavedOrderFileName()
void LLFavoritesOrderStorage::load()
{
- // load per-resident sorting information
std::string filename = getSavedOrderFileName();
-
LLSD settings_llsd;
llifstream file;
file.open(filename.c_str());
if (file.is_open())
{
LLSDSerialize::fromXML(settings_llsd, file);
- LL_INFOS("FavoritesBar") << "loaded favorites order from '" << filename << "' "
- << (settings_llsd.isMap() ? "" : "un") << "successfully"
- << LL_ENDL;
- file.close();
- }
- else
- {
- LL_WARNS("FavoritesBar") << "unable to open favorites order file at '" << filename << "'" << LL_ENDL;
- }
-
- for (LLSD::map_const_iterator iter = settings_llsd.beginMap();
- iter != settings_llsd.endMap(); ++iter)
- {
- mSortIndexes.insert(std::make_pair(LLUUID(iter->first), (S32)iter->second.asInteger()));
+ LL_INFOS("FavoritesBar") << "loaded favorites order from '" << filename << "' "
+ << (settings_llsd.isMap() ? "" : "un") << "successfully"
+ << LL_ENDL;
+ file.close();
+ mSaveOnExit = true;
+
+ for (LLSD::map_const_iterator iter = settings_llsd.beginMap();
+ iter != settings_llsd.endMap(); ++iter)
+ {
+ mSortIndexes.insert(std::make_pair(LLUUID(iter->first), (S32)iter->second.asInteger()));
+ }
}
-}
-
-void LLFavoritesOrderStorage::saveFavoritesSLURLs()
-{
- // Do not change the file if we are not logged in yet.
- if (!LLLoginInstance::getInstance()->authSuccess())
+ else
{
- LL_WARNS("FavoritesBar") << "Cannot save favorites: not logged in" << LL_ENDL;
- return;
+ filename = getStoredFavoritesFilename();
+ if (!filename.empty())
+ {
+ llifstream in_file;
+ in_file.open(filename.c_str());
+ LLSD fav_llsd;
+ LLSD user_llsd;
+ if (in_file.is_open())
+ {
+ LLSDSerialize::fromXML(fav_llsd, in_file);
+ LL_INFOS("FavoritesBar") << "loaded favorites from '" << filename << "' "
+ << (fav_llsd.isMap() ? "" : "un") << "successfully"
+ << LL_ENDL;
+ in_file.close();
+ user_llsd = fav_llsd[gAgentUsername];
+
+ S32 index = 0;
+ for (LLSD::array_iterator iter = user_llsd.beginArray();
+ iter != user_llsd.endArray(); ++iter)
+ {
+ mSortIndexes.insert(std::make_pair(iter->get("id").asUUID(), index));
+ index++;
+ }
+ }
+ else
+ {
+ LL_WARNS("FavoritesBar") << "unable to open favorites from '" << filename << "'" << LL_ENDL;
+ }
+ }
}
-
- std::string filename = getStoredFavoritesFilename();
- if (!filename.empty())
- {
- llifstream in_file;
- in_file.open(filename.c_str());
- LLSD fav_llsd;
- if (in_file.is_open())
- {
- LLSDSerialize::fromXML(fav_llsd, in_file);
- LL_INFOS("FavoritesBar") << "loaded favorites from '" << filename << "' "
- << (fav_llsd.isMap() ? "" : "un") << "successfully"
- << LL_ENDL;
- in_file.close();
- }
- else
- {
- LL_WARNS("FavoritesBar") << "unable to open favorites from '" << filename << "'" << LL_ENDL;
- }
-
- const LLUUID fav_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE);
- LLInventoryModel::cat_array_t cats;
- LLInventoryModel::item_array_t items;
- gInventory.collectDescendents(fav_id, cats, items, LLInventoryModel::EXCLUDE_TRASH);
-
- LLSD user_llsd;
- for (LLInventoryModel::item_array_t::iterator it = items.begin(); it != items.end(); it++)
- {
- LLSD value;
- value["name"] = (*it)->getName();
- value["asset_id"] = (*it)->getAssetUUID();
-
- slurls_map_t::iterator slurl_iter = mSLURLs.find(value["asset_id"]);
- if (slurl_iter != mSLURLs.end())
- {
- LL_DEBUGS("FavoritesBar") << "Saving favorite: idx=" << LLFavoritesOrderStorage::instance().getSortIndex((*it)->getUUID()) << ", SLURL=" << slurl_iter->second << ", value=" << value << LL_ENDL;
- value["slurl"] = slurl_iter->second;
- user_llsd[LLFavoritesOrderStorage::instance().getSortIndex((*it)->getUUID())] = value;
- }
- else
- {
- LL_WARNS("FavoritesBar") << "Not saving favorite " << value["name"] << ": no matching SLURL" << LL_ENDL;
- }
- }
-
- LLAvatarName av_name;
- LLAvatarNameCache::get( gAgentID, &av_name );
- // Note : use the "John Doe" and not the "john.doe" version of the name
- // as we'll compare it with the stored credentials in the login panel.
- fav_llsd[av_name.getUserName()] = user_llsd;
-
- llofstream file;
- file.open(filename.c_str());
- if ( file.is_open() )
- {
- LLSDSerialize::toPrettyXML(fav_llsd, file);
- LL_INFOS("FavoritesBar") << "saved favorites for '" << av_name.getUserName()
- << "' to '" << filename << "' "
- << LL_ENDL;
- file.close();
- }
- else
- {
- LL_WARNS("FavoritesBar") << "unable to open favorites storage for '" << av_name.getUserName()
- << "' at '" << filename << "' "
- << LL_ENDL;
- }
- }
}
void LLFavoritesOrderStorage::removeFavoritesRecordOfUser()
@@ -1626,8 +1615,30 @@ void LLFavoritesOrderStorage::removeFavoritesRecordOfUser()
// See saveFavoritesSLURLs() here above for the reason why.
if (fav_llsd.has(av_name.getUserName()))
{
- LL_INFOS("FavoritesBar") << "Removed favorites for " << av_name.getUserName() << LL_ENDL;
- fav_llsd.erase(av_name.getUserName());
+ LLSD user_llsd = fav_llsd[av_name.getUserName()];
+
+ if (user_llsd.beginArray()->has("id"))
+ {
+ for (LLSD::array_iterator iter = user_llsd.beginArray();iter != user_llsd.endArray(); ++iter)
+ {
+ LLSD value;
+ value["id"]= iter->get("id").asUUID();
+ iter->assign(value);
+ }
+ fav_llsd[av_name.getUserName()] = user_llsd;
+ llofstream file;
+ file.open(filename.c_str());
+ if ( file.is_open() )
+ {
+ LLSDSerialize::toPrettyXML(fav_llsd, file);
+ file.close();
+ }
+ }
+ else
+ {
+ LL_INFOS("FavoritesBar") << "Removed favorites for " << av_name.getUserName() << LL_ENDL;
+ fav_llsd.erase(av_name.getUserName());
+ }
}
llofstream out_file;
@@ -1648,20 +1659,20 @@ void LLFavoritesOrderStorage::onLandmarkLoaded(const LLUUID& asset_id, LLLandmar
if (landmark)
{
LL_DEBUGS("FavoritesBar") << "landmark for " << asset_id << " loaded" << LL_ENDL;
- LLVector3d pos_global;
- if (!landmark->getGlobalPos(pos_global))
- {
- // If global position was unknown on first getGlobalPos() call
- // it should be set for the subsequent calls.
- landmark->getGlobalPos(pos_global);
- }
+ LLVector3d pos_global;
+ if (!landmark->getGlobalPos(pos_global))
+ {
+ // If global position was unknown on first getGlobalPos() call
+ // it should be set for the subsequent calls.
+ landmark->getGlobalPos(pos_global);
+ }
- if (!pos_global.isExactlyZero())
- {
- LL_DEBUGS("FavoritesBar") << "requesting slurl for landmark " << asset_id << LL_ENDL;
- LLLandmarkActions::getSLURLfromPosGlobal(pos_global,
+ if (!pos_global.isExactlyZero())
+ {
+ LL_DEBUGS("FavoritesBar") << "requesting slurl for landmark " << asset_id << LL_ENDL;
+ LLLandmarkActions::getSLURLfromPosGlobal(pos_global,
boost::bind(&LLFavoritesOrderStorage::storeFavoriteSLURL, this, asset_id, _1));
- }
+ }
}
}
@@ -1671,41 +1682,6 @@ void LLFavoritesOrderStorage::storeFavoriteSLURL(const LLUUID& asset_id, std::st
mSLURLs[asset_id] = slurl;
}
-void LLFavoritesOrderStorage::save()
-{
- if (mIsDirty)
- {
- // something changed, so save it
- std::string filename = LLFavoritesOrderStorage::getInstance()->getSavedOrderFileName();
- if (!filename.empty())
- {
- LLSD settings_llsd;
-
- for(sort_index_map_t::const_iterator iter = mSortIndexes.begin(); iter != mSortIndexes.end(); ++iter)
- {
- settings_llsd[iter->first.asString()] = iter->second;
- }
-
- llofstream file;
- file.open(filename.c_str());
- if ( file.is_open() )
- {
- LLSDSerialize::toPrettyXML(settings_llsd, file);
- LL_INFOS("FavoritesBar") << "saved favorites order to '" << filename << "' " << LL_ENDL;
- }
- else
- {
- LL_WARNS("FavoritesBar") << "failed to open favorites order file '" << filename << "' " << LL_ENDL;
- }
- }
- else
- {
- LL_DEBUGS("FavoritesBar") << "no user directory available to store favorites order file" << LL_ENDL;
- }
- }
-}
-
-
void LLFavoritesOrderStorage::cleanup()
{
// nothing to clean
@@ -1720,7 +1696,7 @@ void LLFavoritesOrderStorage::cleanup()
sort_index_map_t aTempMap;
//copy unremoved values from mSortIndexes to aTempMap
- std::remove_copy_if(mSortIndexes.begin(), mSortIndexes.end(),
+ std::remove_copy_if(mSortIndexes.begin(), mSortIndexes.end(),
inserter(aTempMap, aTempMap.begin()),
is_not_in_fav);
@@ -1752,8 +1728,8 @@ void LLFavoritesOrderStorage::saveOrder()
void LLFavoritesOrderStorage::saveItemsOrder( const LLInventoryModel::item_array_t& items )
{
- int sortField = 0;
+ int sortField = 0;
// current order is saved by setting incremental values (1, 2, 3, ...) for the sort field
for (LLInventoryModel::item_array_t::const_iterator i = items.begin(); i != items.end(); ++i)
{
@@ -1793,6 +1769,110 @@ void LLFavoritesOrderStorage::rearrangeFavoriteLandmarks(const LLUUID& source_it
saveItemsOrder(items);
}
+BOOL LLFavoritesOrderStorage::saveFavoritesRecord(bool pref_changed)
+{
+
+ LLUUID favorite_folder= gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE);
+ if (favorite_folder.isNull())
+ return FALSE;
+
+ LLInventoryModel::item_array_t items;
+ LLInventoryModel::cat_array_t cats;
+
+ LLIsType is_type(LLAssetType::AT_LANDMARK);
+ gInventory.collectDescendentsIf(favorite_folder, cats, items, LLInventoryModel::EXCLUDE_TRASH, is_type);
+
+ std::sort(items.begin(), items.end(), LLFavoritesSort());
+
+ if((items != mPrevFavorites) || pref_changed)
+ {
+ std::string filename = getStoredFavoritesFilename();
+ if (!filename.empty())
+ {
+ llifstream in_file;
+ in_file.open(filename.c_str());
+ LLSD fav_llsd;
+ if (in_file.is_open())
+ {
+ LLSDSerialize::fromXML(fav_llsd, in_file);
+ in_file.close();
+ }
+ else
+ {
+ LL_WARNS("FavoritesBar") << "unable to open favorites from '" << filename << "'" << LL_ENDL;
+ }
+
+ LLSD user_llsd;
+ S32 fav_iter = 0;
+ for (LLInventoryModel::item_array_t::iterator it = items.begin(); it != items.end(); it++)
+ {
+ LLSD value;
+ if (gSavedPerAccountSettings.getBOOL("ShowFavoritesOnLogin"))
+ {
+ value["name"] = (*it)->getName();
+ value["asset_id"] = (*it)->getAssetUUID();
+ value["id"] = (*it)->getUUID();
+ slurls_map_t::iterator slurl_iter = mSLURLs.find(value["asset_id"]);
+ if (slurl_iter != mSLURLs.end())
+ {
+ value["slurl"] = slurl_iter->second;
+ user_llsd[fav_iter] = value;
+ }
+ else
+ {
+ getSLURL((*it)->getAssetUUID());
+ mUpdateRequired = true;
+ return FALSE;
+ }
+ }
+ else
+ {
+ value["id"] = (*it)->getUUID();
+ user_llsd[fav_iter] = value;
+ }
+
+ fav_iter ++;
+ }
+
+ LLAvatarName av_name;
+ LLAvatarNameCache::get( gAgentID, &av_name );
+ // Note : use the "John Doe" and not the "john.doe" version of the name
+ // as we'll compare it with the stored credentials in the login panel.
+ fav_llsd[av_name.getUserName()] = user_llsd;
+ llofstream file;
+ file.open(filename.c_str());
+ if ( file.is_open() )
+ {
+ LLSDSerialize::toPrettyXML(fav_llsd, file);
+ file.close();
+ mSaveOnExit = false;
+ }
+ else
+ {
+ LL_WARNS("FavoritesBar") << "unable to open favorites storage for '" << av_name.getUserName()
+ << "' at '" << filename << "' " << LL_ENDL;
+ }
+ }
+
+ mPrevFavorites = items;
+ }
+
+ return TRUE;
+
+}
+
+void LLFavoritesOrderStorage::showFavoritesOnLoginChanged(BOOL show)
+{
+ if (show)
+ {
+ saveFavoritesRecord(true);
+ }
+ else
+ {
+ removeFavoritesRecordOfUser();
+ }
+}
+
void AddFavoriteLandmarkCallback::fire(const LLUUID& inv_item_id)
{
if (mTargetLandmarkId.isNull()) return;
diff --git a/indra/newview/llfavoritesbar.h b/indra/newview/llfavoritesbar.h
index a370724947..66fc8b2ae7 100755
--- a/indra/newview/llfavoritesbar.h
+++ b/indra/newview/llfavoritesbar.h
@@ -105,8 +105,10 @@ protected:
bool mUpdateDropDownItems;
bool mRestoreOverflowMenu;
- LLUUID mSelectedItemID;
+ bool mGetPrevItems;
+ LLUUID mSelectedItemID;
+ LLFrameTimer mItemsChangedTimer;
LLUIImage* mImageDragIndication;
private:
@@ -204,12 +206,23 @@ public:
* @see cleanup()
*/
static void destroyClass();
+ static std::string getStoredFavoritesFilename();
+ static std::string getSavedOrderFileName();
+
+ BOOL saveFavoritesRecord(bool pref_changed = false);
+ void showFavoritesOnLoginChanged(BOOL show);
+
+ LLInventoryModel::item_array_t mPrevFavorites;
+
const static S32 NO_INDEX;
+ static bool mSaveOnExit;
+ bool mUpdateRequired;
+
private:
friend class LLSingleton<LLFavoritesOrderStorage>;
- LLFavoritesOrderStorage() : mIsDirty(false) { load(); }
- ~LLFavoritesOrderStorage() { save(); }
+ LLFavoritesOrderStorage() : mIsDirty(false), mUpdateRequired(false){ load(); }
+ ~LLFavoritesOrderStorage() {}
/**
* Removes sort indexes for items which are not in Favorites bar for now.
@@ -217,13 +230,8 @@ private:
void cleanup();
const static std::string SORTING_DATA_FILE_NAME;
- std::string getSavedOrderFileName();
- static std::string getStoredFavoritesFilename();
-
- void load();
- void save();
- void saveFavoritesSLURLs();
+ void load();
// Remove record of current user's favorites from file on disk.
void removeFavoritesRecordOfUser();
diff --git a/indra/newview/llfeaturemanager.cpp b/indra/newview/llfeaturemanager.cpp
index 0b76ca16a9..f08064d9b5 100755
--- a/indra/newview/llfeaturemanager.cpp
+++ b/indra/newview/llfeaturemanager.cpp
@@ -526,7 +526,7 @@ void LLFeatureManager::fetchFeatureTableCoro(std::string tableName)
LL_INFOS() << "LLFeatureManager fetching " << url << " into " << path << LL_ENDL;
- LLSD result = httpAdapter->getRawAndYield(httpRequest, url);
+ LLSD result = httpAdapter->getRawAndSuspend(httpRequest, url);
LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
@@ -536,13 +536,13 @@ void LLFeatureManager::fetchFeatureTableCoro(std::string tableName)
// write to file
const LLSD::Binary &raw = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS_RAW].asBinary();
- LL_INFOS() << "writing feature table to " << filename << LL_ENDL;
+ LL_INFOS() << "writing feature table to " << path << LL_ENDL;
S32 size = raw.size();
if (size > 0)
{
// write to file
- LLAPRFile out(filename, LL_APR_WB);
+ LLAPRFile out(path, LL_APR_WB);
out.write(raw.data(), size);
out.close();
}
diff --git a/indra/newview/llfilepicker.cpp b/indra/newview/llfilepicker.cpp
index ef50594feb..a7236d1778 100755
--- a/indra/newview/llfilepicker.cpp
+++ b/indra/newview/llfilepicker.cpp
@@ -40,6 +40,10 @@
#include "llwindowsdl.h" // for some X/GTK utils to help with filepickers
#endif // LL_SDL
+#if LL_LINUX || LL_SOLARIS
+#include "llhttpconstants.h" // file picker uses some of thes constants on Linux
+#endif
+
//
// Globals
//
diff --git a/indra/newview/llflickrconnect.cpp b/indra/newview/llflickrconnect.cpp
index 83e4f19191..c0ca5b8cf8 100644
--- a/indra/newview/llflickrconnect.cpp
+++ b/indra/newview/llflickrconnect.cpp
@@ -86,7 +86,7 @@ void LLFlickrConnect::flickrConnectCoro(std::string requestToken, std::string oa
setConnectionState(LLFlickrConnect::FLICKR_CONNECTION_IN_PROGRESS);
- LLSD result = httpAdapter->putAndYield(httpRequest, getFlickrConnectURL("/connection"), body, httpOpts);
+ LLSD result = httpAdapter->putAndSuspend(httpRequest, getFlickrConnectURL("/connection"), body, httpOpts);
LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
@@ -168,9 +168,7 @@ void LLFlickrConnect::flickrShareCoro(LLSD share)
httpOpts->setWantHeaders(true);
httpOpts->setFollowRedirects(false);
- setConnectionState(LLFlickrConnect::FLICKR_POSTING);
-
- LLSD result = httpAdapter->postAndYield(httpRequest, getFlickrConnectURL("/share/photo", true), share, httpOpts);
+ LLSD result = httpAdapter->postAndSuspend(httpRequest, getFlickrConnectURL("/share/photo", true), share, httpOpts);
if (testShareStatus(result))
{
@@ -248,7 +246,7 @@ void LLFlickrConnect::flickrShareImageCoro(LLPointer<LLImageFormatted> image, st
body << "\r\n--" << boundary << "--\r\n";
- LLSD result = httpAdapter->postAndYield(httpRequest, getFlickrConnectURL("/share/photo", true), raw, httpOpts, httpHeaders);
+ LLSD result = httpAdapter->postAndSuspend(httpRequest, getFlickrConnectURL("/share/photo", true), raw, httpOpts, httpHeaders);
if (testShareStatus(result))
{
@@ -271,7 +269,7 @@ void LLFlickrConnect::flickrDisconnectCoro()
setConnectionState(LLFlickrConnect::FLICKR_DISCONNECTING);
httpOpts->setFollowRedirects(false);
- LLSD result = httpAdapter->deleteAndYield(httpRequest, getFlickrConnectURL("/connection"), httpOpts);
+ LLSD result = httpAdapter->deleteAndSuspend(httpRequest, getFlickrConnectURL("/connection"), httpOpts);
LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
@@ -306,7 +304,7 @@ void LLFlickrConnect::flickrConnectedCoro(bool autoConnect)
httpOpts->setFollowRedirects(false);
- LLSD result = httpAdapter->getAndYield(httpRequest, getFlickrConnectURL("/connection", true), httpOpts);
+ LLSD result = httpAdapter->getAndSuspend(httpRequest, getFlickrConnectURL("/connection", true), httpOpts);
LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
@@ -355,7 +353,7 @@ void LLFlickrConnect::flickrInfoCoro()
httpOpts->setWantHeaders(true);
httpOpts->setFollowRedirects(false);
- LLSD result = httpAdapter->getAndYield(httpRequest, getFlickrConnectURL("/info", true), httpOpts);
+ LLSD result = httpAdapter->getAndSuspend(httpRequest, getFlickrConnectURL("/info", true), httpOpts);
LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
@@ -471,12 +469,15 @@ void LLFlickrConnect::uploadPhoto(const std::string& image_url, const std::strin
body["tags"] = tags;
body["safety_level"] = safety_level;
+ setConnectionState(LLFlickrConnect::FLICKR_POSTING);
+
LLCoros::instance().launch("LLFlickrConnect::flickrShareCoro",
boost::bind(&LLFlickrConnect::flickrShareCoro, this, body));
}
void LLFlickrConnect::uploadPhoto(LLPointer<LLImageFormatted> image, const std::string& title, const std::string& description, const std::string& tags, int safety_level)
{
+ setConnectionState(LLFlickrConnect::FLICKR_POSTING);
LLCoros::instance().launch("LLFlickrConnect::flickrShareImageCoro",
boost::bind(&LLFlickrConnect::flickrShareImageCoro, this, image,
diff --git a/indra/newview/llfloaterabout.cpp b/indra/newview/llfloaterabout.cpp
index 01c9416973..bababca652 100755
--- a/indra/newview/llfloaterabout.cpp
+++ b/indra/newview/llfloaterabout.cpp
@@ -34,10 +34,12 @@
// Viewer includes
#include "llagent.h"
#include "llagentui.h"
-#include "llappviewer.h"
+#include "llappviewer.h"
+#include "llnotificationsutil.h"
#include "llslurl.h"
#include "llvoiceclient.h"
#include "lluictrlfactory.h"
+#include "llupdaterservice.h"
#include "llviewertexteditor.h"
#include "llviewercontrol.h"
#include "llviewerstats.h"
@@ -48,7 +50,6 @@
// Linden library includes
#include "llaudioengine.h"
#include "llbutton.h"
-#include "llcurl.h"
#include "llglheaders.h"
#include "llfloater.h"
#include "llfloaterreg.h"
@@ -88,10 +89,24 @@ public:
/// separated so that we can programmatically access the same info.
static LLSD getInfo();
void onClickCopyToClipboard();
+ void onClickUpdateCheck();
+
+ // checks state of updater service and starts a check outside of schedule.
+ // subscribes callback for closest state update
+ static void setUpdateListener();
private:
void setSupportText(const std::string& server_release_notes_url);
+ // notifications for user requested checks
+ static void showCheckUpdateNotification(S32 state);
+
+ // callback method for manual checks
+ static bool callbackCheckUpdate(LLSD const & event);
+
+ // listener name for update checks
+ static const std::string sCheckUpdateListenerName;
+
static void startFetchServerReleaseNotes();
static void handleServerReleaseNotes(LLSD results);
};
@@ -124,6 +139,9 @@ BOOL LLFloaterAbout::postBuild()
getChild<LLUICtrl>("copy_btn")->setCommitCallback(
boost::bind(&LLFloaterAbout::onClickCopyToClipboard, this));
+ getChild<LLUICtrl>("update_btn")->setCommitCallback(
+ boost::bind(&LLFloaterAbout::onClickUpdateCheck, this));
+
static const LLUIColor about_color = LLUIColorTable::instance().getColor("TextFgReadOnlyColor");
if (gAgent.getRegion())
@@ -271,6 +289,11 @@ void LLFloaterAbout::onClickCopyToClipboard()
support_widget->deselect();
}
+void LLFloaterAbout::onClickUpdateCheck()
+{
+ setUpdateListener();
+}
+
void LLFloaterAbout::setSupportText(const std::string& server_release_notes_url)
{
#if LL_WINDOWS
@@ -292,6 +315,68 @@ void LLFloaterAbout::setSupportText(const std::string& server_release_notes_url)
}
///----------------------------------------------------------------------------
+/// Floater About Update-check related functions
+///----------------------------------------------------------------------------
+
+const std::string LLFloaterAbout::sCheckUpdateListenerName = "LLUpdateNotificationListener";
+
+void LLFloaterAbout::showCheckUpdateNotification(S32 state)
+{
+ switch (state)
+ {
+ case LLUpdaterService::UP_TO_DATE:
+ LLNotificationsUtil::add("UpdateViewerUpToDate");
+ break;
+ case LLUpdaterService::DOWNLOADING:
+ case LLUpdaterService::INSTALLING:
+ LLNotificationsUtil::add("UpdateDownloadInProgress");
+ break;
+ case LLUpdaterService::TERMINAL:
+ // download complete, user triggered check after download pop-up appeared
+ LLNotificationsUtil::add("UpdateDownloadComplete");
+ break;
+ default:
+ LLNotificationsUtil::add("UpdateCheckError");
+ break;
+ }
+}
+
+bool LLFloaterAbout::callbackCheckUpdate(LLSD const & event)
+{
+ if (!event.has("payload"))
+ {
+ return false;
+ }
+
+ LLSD payload = event["payload"];
+ if (payload.has("type") && payload["type"].asInteger() == LLUpdaterService::STATE_CHANGE)
+ {
+ LLEventPumps::instance().obtain("mainlooprepeater").stopListening(sCheckUpdateListenerName);
+ showCheckUpdateNotification(payload["state"].asInteger());
+ }
+ return false;
+}
+
+void LLFloaterAbout::setUpdateListener()
+{
+ LLUpdaterService update_service;
+ S32 service_state = update_service.getState();
+ // Note: Do not set state listener before forceCheck() since it set's new state
+ if (update_service.forceCheck() || service_state == LLUpdaterService::CHECKING_FOR_UPDATE)
+ {
+ LLEventPump& mainloop(LLEventPumps::instance().obtain("mainlooprepeater"));
+ if (mainloop.getListener(sCheckUpdateListenerName) == LLBoundListener()) // dummy listener
+ {
+ mainloop.listen(sCheckUpdateListenerName, boost::bind(&callbackCheckUpdate, _1));
+ }
+ }
+ else
+ {
+ showCheckUpdateNotification(service_state);
+ }
+}
+
+///----------------------------------------------------------------------------
/// LLFloaterAboutUtil
///----------------------------------------------------------------------------
void LLFloaterAboutUtil::registerFloater()
@@ -301,3 +386,8 @@ void LLFloaterAboutUtil::registerFloater()
}
+void LLFloaterAboutUtil::checkUpdatesAndNotify()
+{
+ LLFloaterAbout::setUpdateListener();
+}
+
diff --git a/indra/newview/llfloaterabout.h b/indra/newview/llfloaterabout.h
index 8fc1aa4f29..be34b631cc 100755
--- a/indra/newview/llfloaterabout.h
+++ b/indra/newview/llfloaterabout.h
@@ -30,6 +30,9 @@
namespace LLFloaterAboutUtil
{
void registerFloater();
+
+ // Support for user initialized update/state checks
+ void checkUpdatesAndNotify();
}
#endif // LL_LLFLOATERABOUT_H
diff --git a/indra/newview/llfloateravatarpicker.cpp b/indra/newview/llfloateravatarpicker.cpp
index 2824038f77..72892b47a4 100755
--- a/indra/newview/llfloateravatarpicker.cpp
+++ b/indra/newview/llfloateravatarpicker.cpp
@@ -466,7 +466,7 @@ void LLFloaterAvatarPicker::findCoro(std::string url, LLUUID queryID, std::strin
LL_INFOS("HttpCoroutineAdapter", "genericPostCoro") << "Generic POST for " << url << LL_ENDL;
- LLSD result = httpAdapter->getAndYield(httpRequest, url);
+ LLSD result = httpAdapter->getAndSuspend(httpRequest, url);
LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
diff --git a/indra/newview/llfloaterbump.cpp b/indra/newview/llfloaterbump.cpp
index 34904cf7ed..957c91b226 100755
--- a/indra/newview/llfloaterbump.cpp
+++ b/indra/newview/llfloaterbump.cpp
@@ -32,6 +32,7 @@
#include "llavataractions.h"
#include "llfloaterbump.h"
+#include "llfloaterreg.h"
#include "llfloaterreporter.h"
#include "llmutelist.h"
#include "llpanelblockedlist.h"
@@ -87,11 +88,11 @@ BOOL LLFloaterBump::postBuild()
// virtual
void LLFloaterBump::onOpen(const LLSD& key)
{
- mNames.clear();
- mList->deleteAllItems();
-
if (gMeanCollisionList.empty())
{
+ mNames.clear();
+ mList->deleteAllItems();
+
std::string none_detected = getString("none_detected");
LLSD row;
row["columns"][0]["value"] = none_detected;
@@ -100,12 +101,20 @@ void LLFloaterBump::onOpen(const LLSD& key)
}
else
{
- for (mean_collision_list_t::iterator iter = gMeanCollisionList.begin();
- iter != gMeanCollisionList.end(); ++iter)
- {
- LLMeanCollisionData *mcd = *iter;
- add(mList, mcd);
- }
+ populateCollisionList();
+ }
+}
+
+void LLFloaterBump::populateCollisionList()
+{
+ mNames.clear();
+ mList->deleteAllItems();
+
+ for (mean_collision_list_t::iterator iter = gMeanCollisionList.begin();
+ iter != gMeanCollisionList.end(); ++iter)
+ {
+ LLMeanCollisionData *mcd = *iter;
+ add(mList, mcd);
}
}
@@ -247,3 +256,8 @@ void LLFloaterBump::inviteToGroup()
{
LLAvatarActions::inviteToGroup(mItemUUID);
}
+
+LLFloaterBump* LLFloaterBump::getInstance()
+{
+ return LLFloaterReg::getTypedInstance<LLFloaterBump>("bumps");
+}
diff --git a/indra/newview/llfloaterbump.h b/indra/newview/llfloaterbump.h
index 11b7db9fee..ce52c75255 100755
--- a/indra/newview/llfloaterbump.h
+++ b/indra/newview/llfloaterbump.h
@@ -46,6 +46,10 @@ public:
/*virtual*/ BOOL postBuild();
/*virtual*/ void onOpen(const LLSD& key);
+ static LLFloaterBump* getInstance();
+
+ void populateCollisionList();
+
void startIM();
void startCall();
void reportAbuse();
diff --git a/indra/newview/llfloaterexperienceprofile.cpp b/indra/newview/llfloaterexperienceprofile.cpp
index 8a04f9e4cc..d44eb4310d 100644
--- a/indra/newview/llfloaterexperienceprofile.cpp
+++ b/indra/newview/llfloaterexperienceprofile.cpp
@@ -36,7 +36,6 @@
#include "llexpandabletextbox.h"
#include "llexperiencecache.h"
#include "llfloaterreg.h"
-#include "llhttpclient.h"
#include "lllayoutstack.h"
#include "lllineeditor.h"
#include "llnotificationsutil.h"
@@ -99,7 +98,7 @@ public:
if(params.size() != 2 || params[1].asString() != "profile")
return false;
- LLExperienceCache::getInstance()->get(params[0].asUUID(), boost::bind(&LLExperienceHandler::experienceCallback, this, _1));
+ LLExperienceCache::instance().get(params[0].asUUID(), boost::bind(&LLExperienceHandler::experienceCallback, this, _1));
return true;
}
@@ -131,175 +130,20 @@ LLFloaterExperienceProfile::~LLFloaterExperienceProfile()
}
-template<class T>
-class HandleResponder : public LLHTTPClient::Responder
-{
-public:
- HandleResponder(const LLHandle<T>& parent):mParent(parent){}
- LLHandle<T> mParent;
-
- virtual void httpFailure()
- {
- LL_WARNS() << "HandleResponder failed with code: " << getStatus() << ", reason: " << getReason() << LL_ENDL;
- }
-};
-
-class ExperienceUpdateResponder : public HandleResponder<LLFloaterExperienceProfile>
-{
-public:
- ExperienceUpdateResponder(const LLHandle<LLFloaterExperienceProfile>& parent):HandleResponder<LLFloaterExperienceProfile>(parent)
- {
- }
-
- virtual void httpSuccess()
- {
- LLFloaterExperienceProfile* parent=mParent.get();
- if(parent)
- {
- parent->onSaveComplete(getContent());
- }
- }
-};
-
-
-
-class ExperiencePreferencesResponder : public LLHTTPClient::Responder
-{
-public:
- ExperiencePreferencesResponder(const LLUUID& single = LLUUID::null):mId(single)
- {
- }
-
- bool sendSingle(const LLSD& content, const LLSD& permission, const char* name)
- {
- if(!content.has(name))
- return false;
-
- LLEventPump& pump = LLEventPumps::instance().obtain("experience_permission");
- const LLSD& list = content[name];
- LLSD::array_const_iterator it = list.beginArray();
- while(it != list.endArray())
- {
- if(it->asUUID() == mId)
- {
- LLSD message;
- message[it->asString()] = permission;
- message["experience"] = mId;
- pump.post(message);
- return true;
- }
- ++it;
- }
- return false;
- }
-
- bool hasPermission(const LLSD& content, const char* name)
- {
- if(!content.has(name))
- return false;
-
- const LLSD& list = content[name];
- LLSD::array_const_iterator it = list.beginArray();
- while(it != list.endArray())
- {
- if(it->asUUID() == mId)
- {
- return true;
- }
- ++it;
- }
- return false;
- }
-
- const char* getPermission(const LLSD& content)
- {
- if(hasPermission(content, "experiences"))
- {
- return "Allow";
- }
- else if(hasPermission(content, "blocked"))
- {
- return "Block";
- }
- return "Forget";
- }
-
-
- virtual void httpSuccess()
- {
- if(mId.notNull())
- {
- post(getPermission(getContent()));
- return;
- }
- LLEventPumps::instance().obtain("experience_permission").post(getContent());
- }
-
- void post( const char* perm )
- {
- LLSD experience;
- LLSD message;
- experience["permission"]=perm;
- message["experience"] = mId;
- message[mId.asString()] = experience;
- LLEventPumps::instance().obtain("experience_permission").post(message);
- }
-
-private:
- LLUUID mId;
-};
-
-
-class IsAdminResponder : public HandleResponder<LLFloaterExperienceProfile>
-{
-public:
- IsAdminResponder(const LLHandle<LLFloaterExperienceProfile>& parent):HandleResponder<LLFloaterExperienceProfile>(parent)
- {
- }
-
- virtual void httpSuccess()
- {
- LLFloaterExperienceProfile* parent = mParent.get();
- if(!parent)
- return;
-
- bool enabled = true;
- LLViewerRegion* region = gAgent.getRegion();
- if (!region)
- {
- enabled = false;
- }
- else
- {
- std::string url=region->getCapability("UpdateExperience");
- if(url.empty())
- enabled = false;
- }
- if(enabled && getContent()["status"].asBoolean())
- {
- parent->getChild<LLLayoutPanel>(PNL_TOP)->setVisible(TRUE);
- parent->getChild<LLButton>(BTN_EDIT)->setVisible(TRUE);
- }
- }
-};
-
BOOL LLFloaterExperienceProfile::postBuild()
{
if (mExperienceId.notNull())
{
- LLExperienceCache::getInstance()->fetch(mExperienceId, true);
- LLExperienceCache::getInstance()->get(mExperienceId, boost::bind(&LLFloaterExperienceProfile::experienceCallback,
+ LLExperienceCache::instance().fetch(mExperienceId, true);
+ LLExperienceCache::instance().get(mExperienceId, boost::bind(&LLFloaterExperienceProfile::experienceCallback,
getDerivedHandle<LLFloaterExperienceProfile>(), _1));
LLViewerRegion* region = gAgent.getRegion();
if (region)
{
- std::string lookup_url=region->getCapability("IsExperienceAdmin");
- if(!lookup_url.empty())
- {
- LLHTTPClient::get(lookup_url+"?experience_id="+mExperienceId.asString(), new IsAdminResponder(getDerivedHandle<LLFloaterExperienceProfile>()));
- }
+ LLExperienceCache::instance().getExperienceAdmin(mExperienceId, boost::bind(
+ &LLFloaterExperienceProfile::experienceIsAdmin, getDerivedHandle<LLFloaterExperienceProfile>(), _1));
}
}
@@ -372,23 +216,13 @@ void LLFloaterExperienceProfile::onClickSave()
doSave(NOTHING);
}
-
void LLFloaterExperienceProfile::onClickPermission(const char* perm)
{
LLViewerRegion* region = gAgent.getRegion();
if (!region)
return;
-
- std::string lookup_url=region->getCapability("ExperiencePreferences");
- if(lookup_url.empty())
- return;
- LLSD permission;
- LLSD data;
- permission["permission"]=perm;
-
- data[mExperienceId.asString()]=permission;
- LLHTTPClient::put(lookup_url, data, new ExperiencePreferencesResponder(mExperienceId));
-
+ LLExperienceCache::instance().setExperiencePermission(mExperienceId, perm, boost::bind(
+ &LLFloaterExperienceProfile::experiencePermissionResults, mExperienceId, _1));
}
@@ -398,11 +232,8 @@ void LLFloaterExperienceProfile::onClickForget()
if (!region)
return;
- std::string lookup_url=region->getCapability("ExperiencePreferences");
- if(lookup_url.empty())
- return;
-
- LLHTTPClient::del(lookup_url+"?"+mExperienceId.asString(), new ExperiencePreferencesResponder(mExperienceId));
+ LLExperienceCache::instance().forgetExperiencePermission(mExperienceId, boost::bind(
+ &LLFloaterExperienceProfile::experiencePermissionResults, mExperienceId, _1));
}
bool LLFloaterExperienceProfile::setMaturityString( U8 maturity, LLTextBox* child, LLComboBox* combo )
@@ -549,11 +380,8 @@ void LLFloaterExperienceProfile::refreshExperience( const LLSD& experience )
LLViewerRegion* region = gAgent.getRegion();
if (region)
{
- std::string lookup_url=region->getCapability("ExperiencePreferences");
- if(!lookup_url.empty())
- {
- LLHTTPClient::get(lookup_url+"?"+mExperienceId.asString(), new ExperiencePreferencesResponder(mExperienceId));
- }
+ LLExperienceCache::instance().getExperiencePermission(mExperienceId, boost::bind(
+ &LLFloaterExperienceProfile::experiencePermissionResults, mExperienceId, _1));
}
}
@@ -733,15 +561,9 @@ void LLFloaterExperienceProfile::doSave( int success_action )
if (!region)
return;
- std::string url=region->getCapability("UpdateExperience");
- if(url.empty())
- return;
-
- mPackage.erase(LLExperienceCache::QUOTA);
- mPackage.erase(LLExperienceCache::EXPIRES);
- mPackage.erase(LLExperienceCache::AGENT_ID);
-
- LLHTTPClient::post(url, mPackage, new ExperienceUpdateResponder(getDerivedHandle<LLFloaterExperienceProfile>()));
+ LLExperienceCache::instance().updateExperience(mPackage, boost::bind(
+ &LLFloaterExperienceProfile::experienceUpdateResult,
+ getDerivedHandle<LLFloaterExperienceProfile>(), _1));
}
void LLFloaterExperienceProfile::onSaveComplete( const LLSD& content )
@@ -799,8 +621,8 @@ void LLFloaterExperienceProfile::onSaveComplete( const LLSD& content )
}
refreshExperience(*it);
- LLExperienceCache::getInstance()->insert(*it);
- LLExperienceCache::getInstance()->fetch(id, true);
+ LLExperienceCache::instance().insert(*it);
+ LLExperienceCache::instance().fetch(id, true);
if(mSaveCompleteAction==VIEW)
{
@@ -1002,3 +824,76 @@ void LLFloaterExperienceProfile::onReportExperience()
{
LLFloaterReporter::showFromExperience(mExperienceId);
}
+
+/*static*/
+bool LLFloaterExperienceProfile::hasPermission(const LLSD& content, const std::string &name, const LLUUID &test)
+{
+ if (!content.has(name))
+ return false;
+
+ const LLSD& list = content[name];
+ LLSD::array_const_iterator it = list.beginArray();
+ while (it != list.endArray())
+ {
+ if (it->asUUID() == test)
+ {
+ return true;
+ }
+ ++it;
+ }
+ return false;
+}
+
+/*static*/
+void LLFloaterExperienceProfile::experiencePermissionResults(LLUUID exprienceId, LLSD result)
+{
+ std::string permission("Forget");
+ if (hasPermission(result, "experiences", exprienceId))
+ permission = "Allow";
+ else if (hasPermission(result, "blocked", exprienceId))
+ permission = "Block";
+
+ LLSD experience;
+ LLSD message;
+ experience["permission"] = permission;
+ message["experience"] = exprienceId;
+ message[exprienceId.asString()] = experience;
+
+ LLEventPumps::instance().obtain("experience_permission").post(message);
+}
+
+/*static*/
+void LLFloaterExperienceProfile::experienceIsAdmin(LLHandle<LLFloaterExperienceProfile> handle, const LLSD &result)
+{
+ LLFloaterExperienceProfile* parent = handle.get();
+ if (!parent)
+ return;
+
+ bool enabled = true;
+ LLViewerRegion* region = gAgent.getRegion();
+ if (!region)
+ {
+ enabled = false;
+ }
+ else
+ {
+ std::string url = region->getCapability("UpdateExperience");
+ if (url.empty())
+ enabled = false;
+ }
+ if (enabled && result["status"].asBoolean())
+ {
+ parent->getChild<LLLayoutPanel>(PNL_TOP)->setVisible(TRUE);
+ parent->getChild<LLButton>(BTN_EDIT)->setVisible(TRUE);
+ }
+}
+
+/*static*/
+void LLFloaterExperienceProfile::experienceUpdateResult(LLHandle<LLFloaterExperienceProfile> handle, const LLSD &result)
+{
+ LLFloaterExperienceProfile* parent = handle.get();
+ if (parent)
+ {
+ parent->onSaveComplete(result);
+ }
+}
diff --git a/indra/newview/llfloaterexperienceprofile.h b/indra/newview/llfloaterexperienceprofile.h
index 78d54eb447..7a5ced546b 100644
--- a/indra/newview/llfloaterexperienceprofile.h
+++ b/indra/newview/llfloaterexperienceprofile.h
@@ -99,6 +99,12 @@ protected:
int mSaveCompleteAction;
bool mDirty;
bool mForceClose;
+
+private:
+ static bool hasPermission(const LLSD& content, const std::string &name, const LLUUID &test);
+ static void experiencePermissionResults(LLUUID exprienceId, LLSD result);
+ static void experienceIsAdmin(LLHandle<LLFloaterExperienceProfile> handle, const LLSD &result);
+ static void experienceUpdateResult(LLHandle<LLFloaterExperienceProfile> handle, const LLSD &result);
};
#endif // LL_LLFLOATEREXPERIENCEPROFILE_H
diff --git a/indra/newview/llfloaterexperiences.cpp b/indra/newview/llfloaterexperiences.cpp
index 14fbdb3a8f..fbe00beddd 100644
--- a/indra/newview/llfloaterexperiences.cpp
+++ b/indra/newview/llfloaterexperiences.cpp
@@ -32,7 +32,6 @@
#include "llevents.h"
#include "llexperiencecache.h"
#include "llfloaterregioninfo.h"
-#include "llhttpclient.h"
#include "llnotificationsutil.h"
#include "llpanelexperiencelog.h"
#include "llpanelexperiencepicker.h"
@@ -294,7 +293,7 @@ void LLFloaterExperiences::retrieveExperienceList(const std::string &url,
// _3 -> url
// _4 -> httpOptions
// _5 -> httpHeaders
- (&LLCoreHttpUtil::HttpCoroutineAdapter::getAndYield), _1, _2, _3, _4, _5);
+ (&LLCoreHttpUtil::HttpCoroutineAdapter::getAndSuspend), _1, _2, _3, _4, _5);
LLCoros::instance().launch("LLFloaterExperiences::retrieveExperienceList",
boost::bind(&LLFloaterExperiences::retrieveExperienceListCoro,
@@ -315,7 +314,7 @@ void LLFloaterExperiences::requestNewExperience(const std::string &url,
// _3 -> url
// _4 -> httpOptions
// _5 -> httpHeaders
- (&LLCoreHttpUtil::HttpCoroutineAdapter::postAndYield), _1, _2, _3, LLSD(), _4, _5);
+ (&LLCoreHttpUtil::HttpCoroutineAdapter::postAndSuspend), _1, _2, _3, LLSD(), _4, _5);
LLCoros::instance().launch("LLFloaterExperiences::requestNewExperience",
boost::bind(&LLFloaterExperiences::retrieveExperienceListCoro,
diff --git a/indra/newview/llfloaterfacebook.cpp b/indra/newview/llfloaterfacebook.cpp
index 3a2047cfef..da85d378b2 100644
--- a/indra/newview/llfloaterfacebook.cpp
+++ b/indra/newview/llfloaterfacebook.cpp
@@ -64,9 +64,9 @@ const std::string DEFAULT_CHECKIN_ICON_URL = "http://map.secondlife.com.s3.amazo
const std::string DEFAULT_CHECKIN_QUERY_PARAMETERS = "?sourceid=slshare_checkin&utm_source=facebook&utm_medium=checkin&utm_campaign=slshare";
const std::string DEFAULT_PHOTO_QUERY_PARAMETERS = "?sourceid=slshare_photo&utm_source=facebook&utm_medium=photo&utm_campaign=slshare";
-const S32 MAX_QUALITY = 100; // Max quality value for jpeg images
-const S32 MIN_QUALITY = 0; // Min quality value for jpeg images
-const S32 TARGET_DATA_SIZE = 95000; // Size of the image (compressed) we're trying to send to Facebook
+const S32 MAX_QUALITY = 100; // Max quality value for jpeg images
+const S32 MIN_QUALITY = 0; // Min quality value for jpeg images
+const S32 TARGET_DATA_SIZE = 950000; // Size of the image (compressed) we're trying to send to Facebook
std::string get_map_url()
{
diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp
index ab57e8c170..f1a6ef78a6 100755
--- a/indra/newview/llfloaterimcontainer.cpp
+++ b/indra/newview/llfloaterimcontainer.cpp
@@ -261,6 +261,8 @@ BOOL LLFloaterIMContainer::postBuild()
mInitialized = true;
+ mIsFirstOpen = true;
+
// Add callbacks:
// We'll take care of view updates on idle
gIdleCallbacks.addFunction(idle, this);
@@ -636,14 +638,16 @@ void LLFloaterIMContainer::setVisible(BOOL visible)
{
// Make sure we have the Nearby Chat present when showing the conversation container
nearby_chat = LLFloaterReg::findTypedInstance<LLFloaterIMNearbyChat>("nearby_chat");
- if (nearby_chat == NULL)
+ if ((nearby_chat == NULL) || mIsFirstOpen)
{
+ mIsFirstOpen = false;
// If not found, force the creation of the nearby chat conversation panel
// *TODO: find a way to move this to XML as a default panel or something like that
LLSD name("nearby_chat");
LLFloaterReg::toggleInstanceOrBringToFront(name);
selectConversationPair(LLUUID(NULL), false, false);
}
+
flashConversationItemWidget(mSelectedSession,false);
LLFloaterIMSessionTab* session_floater = LLFloaterIMSessionTab::findConversation(mSelectedSession);
@@ -1216,7 +1220,22 @@ void LLFloaterIMContainer::doToSelectedConversation(const std::string& command,
{
if (selectedIDS.size() > 0)
{
- LLAvatarActions::viewChatHistory(selectedIDS.front());
+ if(conversationItem->getType() == LLConversationItem::CONV_SESSION_GROUP)
+ {
+ LLFloaterReg::showInstance("preview_conversation", conversationItem->getUUID(), true);
+ }
+ else if(conversationItem->getType() == LLConversationItem::CONV_SESSION_AD_HOC)
+ {
+ LLConversation* conv = LLConversationLog::instance().findConversation(LLIMModel::getInstance()->findIMSession(conversationItem->getUUID()));
+ if(conv)
+ {
+ LLFloaterReg::showInstance("preview_conversation", conv->getSessionID(), true);
+ }
+ }
+ else
+ {
+ LLAvatarActions::viewChatHistory(selectedIDS.front());
+ }
}
}
else
@@ -1316,6 +1335,15 @@ bool LLFloaterIMContainer::enableContextMenuItem(const LLSD& userdata)
{
return LLLogChat::isNearbyTranscriptExist();
}
+ else if (getCurSelectedViewModelItem()->getType() == LLConversationItem::CONV_SESSION_AD_HOC)
+ {
+ const LLConversation* conv = LLConversationLog::instance().findConversation(LLIMModel::getInstance()->findIMSession(uuids.front()));
+ if(conv)
+ {
+ return LLLogChat::isAdHocTranscriptExist(conv->getHistoryFileName());
+ }
+ return false;
+ }
else
{
bool is_group = (getCurSelectedViewModelItem()->getType() == LLConversationItem::CONV_SESSION_GROUP);
@@ -1881,22 +1909,28 @@ bool LLFloaterIMContainer::canBanSelectedMember(const LLUUID& participant_uuid)
return false;
}
- if (!gdatap->mMembers.size())
+ if (gdatap->mPendingBanRequest)
{
return false;
}
- LLGroupMgrGroupData::member_list_t::iterator mi = gdatap->mMembers.find((participant_uuid));
- if (mi == gdatap->mMembers.end())
+ if (gdatap->isRoleMemberDataComplete())
{
- return false;
- }
+ if (!gdatap->mMembers.size())
+ {
+ return false;
+ }
- LLGroupMemberData* member_data = (*mi).second;
- // Is the member an owner?
- if ( member_data && member_data->isInRole(gdatap->mOwnerRole) )
- {
- return false;
+ LLGroupMgrGroupData::member_list_t::iterator mi = gdatap->mMembers.find((participant_uuid));
+ if (mi != gdatap->mMembers.end())
+ {
+ LLGroupMemberData* member_data = (*mi).second;
+ // Is the member an owner?
+ if (member_data && member_data->isInRole(gdatap->mOwnerRole))
+ {
+ return false;
+ }
+ }
}
if( gAgent.hasPowerInGroup(group_uuid, GP_ROLE_REMOVE_MEMBER) &&
@@ -1924,20 +1958,8 @@ void LLFloaterIMContainer::banSelectedMember(const LLUUID& participant_uuid)
LL_WARNS("Groups") << "Unable to get group data for group " << group_uuid << LL_ENDL;
return;
}
- std::vector<LLUUID> ids;
- ids.push_back(participant_uuid);
-
- LLGroupBanData ban_data;
- gdatap->createBanEntry(participant_uuid, ban_data);
- LLGroupMgr::getInstance()->sendGroupBanRequest(LLGroupMgr::REQUEST_POST, group_uuid, LLGroupMgr::BAN_CREATE, ids);
- LLGroupMgr::getInstance()->sendGroupMemberEjects(group_uuid, ids);
- LLGroupMgr::getInstance()->sendGroupMembersRequest(group_uuid);
- LLSD args;
- std::string name;
- gCacheName->getFullName(participant_uuid, name);
- args["AVATAR_NAME"] = name;
- args["GROUP_NAME"] = gdatap->mName;
- LLNotifications::instance().add(LLNotification::Params("EjectAvatarFromGroup").substitutions(args));
+
+ gdatap->banMemberById(participant_uuid);
}
diff --git a/indra/newview/llfloaterimcontainer.h b/indra/newview/llfloaterimcontainer.h
index f21c0b9947..60cef83d9a 100755
--- a/indra/newview/llfloaterimcontainer.h
+++ b/indra/newview/llfloaterimcontainer.h
@@ -193,6 +193,8 @@ private:
bool mInitialized;
bool mIsFirstLaunch;
+ bool mIsFirstOpen;
+
LLUUID mSelectedSession;
std::string mGeneralTitle;
diff --git a/indra/newview/llfloaterjoystick.cpp b/indra/newview/llfloaterjoystick.cpp
index b7fff6cae3..ee3d633dd0 100755
--- a/indra/newview/llfloaterjoystick.cpp
+++ b/indra/newview/llfloaterjoystick.cpp
@@ -326,7 +326,21 @@ void LLFloaterJoystick::onClickOK(void *joy_panel)
}
}
+void LLFloaterJoystick::onClickCloseBtn(bool app_quitting)
+{
+ cancel();
+ closeFloater(app_quitting);
+}
+
void LLFloaterJoystick::setSNDefaults()
{
LLViewerJoystick::getInstance()->setSNDefaults();
}
+
+void LLFloaterJoystick::onClose(bool app_quitting)
+{
+ if (app_quitting)
+ {
+ cancel();
+ }
+}
diff --git a/indra/newview/llfloaterjoystick.h b/indra/newview/llfloaterjoystick.h
index 9c3752540d..a1b5951389 100755
--- a/indra/newview/llfloaterjoystick.h
+++ b/indra/newview/llfloaterjoystick.h
@@ -45,6 +45,11 @@ public:
virtual void draw();
static void setSNDefaults();
+protected:
+
+ void onClose(bool app_quitting);
+ void onClickCloseBtn(bool app_quitting);
+
private:
LLFloaterJoystick(const LLSD& data);
diff --git a/indra/newview/llfloaterland.cpp b/indra/newview/llfloaterland.cpp
index ce32aeda94..f9fd5069af 100755
--- a/indra/newview/llfloaterland.cpp
+++ b/indra/newview/llfloaterland.cpp
@@ -2439,6 +2439,8 @@ void LLPanelLandAccess::refresh()
mListAccess->clearSortOrder();
mListAccess->deleteAllItems();
S32 count = parcel->mAccessList.size();
+ getChild<LLUICtrl>("AllowedText")->setTextArg("[COUNT]", llformat("%d",count));
+
getChild<LLUICtrl>("AccessList")->setToolTipArg(LLStringExplicit("[LISTED]"), llformat("%d",count));
getChild<LLUICtrl>("AccessList")->setToolTipArg(LLStringExplicit("[MAX]"), llformat("%d",PARCEL_MAX_ACCESS_LIST));
@@ -2484,6 +2486,7 @@ void LLPanelLandAccess::refresh()
mListBanned->clearSortOrder();
mListBanned->deleteAllItems();
S32 count = parcel->mBanList.size();
+ getChild<LLUICtrl>("BanCheck")->setTextArg("[COUNT]", llformat("%d",count));
getChild<LLUICtrl>("BannedList")->setToolTipArg(LLStringExplicit("[LISTED]"), llformat("%d",count));
getChild<LLUICtrl>("BannedList")->setToolTipArg(LLStringExplicit("[MAX]"), llformat("%d",PARCEL_MAX_ACCESS_LIST));
diff --git a/indra/newview/llfloatermarketplacelistings.cpp b/indra/newview/llfloatermarketplacelistings.cpp
index b2d36479cd..18f0bc4498 100755
--- a/indra/newview/llfloatermarketplacelistings.cpp
+++ b/indra/newview/llfloatermarketplacelistings.cpp
@@ -572,7 +572,7 @@ void LLFloaterMarketplaceListings::updateView()
std::string title;
std::string tooltip;
- const LLSD& subs = getMarketplaceStringSubstitutions();
+ const LLSD& subs = LLMarketplaceData::getMarketplaceStringSubstitutions();
// Update the top message or flip to the tabs and folders view
// *TODO : check those messages and create better appropriate ones in strings.xml
diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp
index 47130dbb43..05b4ecafe6 100755
--- a/indra/newview/llfloatermodelpreview.cpp
+++ b/indra/newview/llfloatermodelpreview.cpp
@@ -26,35 +26,8 @@
#include "llviewerprecompiledheaders.h"
-#if LL_MSVC
-#pragma warning (disable : 4263)
-#pragma warning (disable : 4264)
-#endif
-#include "dae.h"
-//#include "dom.h"
-#include "dom/domAsset.h"
-#include "dom/domBind_material.h"
-#include "dom/domCOLLADA.h"
-#include "dom/domConstants.h"
-#include "dom/domController.h"
-#include "dom/domEffect.h"
-#include "dom/domGeometry.h"
-#include "dom/domInstance_geometry.h"
-#include "dom/domInstance_material.h"
-#include "dom/domInstance_node.h"
-#include "dom/domInstance_effect.h"
-#include "dom/domMaterial.h"
-#include "dom/domMatrix.h"
-#include "dom/domNode.h"
-#include "dom/domProfile_COMMON.h"
-#include "dom/domRotate.h"
-#include "dom/domScale.h"
-#include "dom/domTranslate.h"
-#include "dom/domVisual_scene.h"
-#if LL_MSVC
-#pragma warning (default : 4263)
-#pragma warning (default : 4264)
-#endif
+#include "llmodelloader.h"
+#include "lldaeloader.h"
#include "llfloatermodelpreview.h"
@@ -112,14 +85,15 @@
#include "llanimationstates.h"
#include "llviewernetwork.h"
#include "llviewershadermgr.h"
-#include "glod/glod.h"
-const S32 SLM_SUPPORTED_VERSION = 3;
+#include "glod/glod.h"
+#include <boost/algorithm/string.hpp>
//static
S32 LLFloaterModelPreview::sUploadAmount = 10;
LLFloaterModelPreview* LLFloaterModelPreview::sInstance = NULL;
-std::list<LLModelLoader*> LLModelLoader::sActiveLoaderList;
+
+bool LLModelPreview::sIgnoreLoadedCallback = false;
// "Retain%" decomp parameter has values from 0.0 to 1.0 by 0.01
// But according to the UI spec for upload model floater, this parameter
@@ -199,190 +173,46 @@ std::string lod_label_name[NUM_LOD+1] =
"I went off the end of the lod_label_name array. Me so smart."
};
-std::string colladaVersion[VERSIONTYPE_COUNT+1] =
-{
- "1.4.0",
- "1.4.1",
- "Unsupported"
-};
-
-
-#define LL_DEGENERACY_TOLERANCE 1e-7f
-
-inline F32 dot3fpu(const LLVector4a& a, const LLVector4a& b)
-{
- volatile F32 p0 = a[0] * b[0];
- volatile F32 p1 = a[1] * b[1];
- volatile F32 p2 = a[2] * b[2];
- return p0 + p1 + p2;
-}
-
-bool ll_is_degenerate(const LLVector4a& a, const LLVector4a& b, const LLVector4a& c, F32 tolerance = LL_DEGENERACY_TOLERANCE)
-{
- // small area check
- {
- LLVector4a edge1; edge1.setSub( a, b );
- LLVector4a edge2; edge2.setSub( a, c );
- //////////////////////////////////////////////////////////////////////////
- /// Linden Modified
- //////////////////////////////////////////////////////////////////////////
-
- // If no one edge is more than 10x longer than any other edge, we weaken
- // the tolerance by a factor of 1e-4f.
-
- LLVector4a edge3; edge3.setSub( c, b );
- const F32 len1sq = edge1.dot3(edge1).getF32();
- const F32 len2sq = edge2.dot3(edge2).getF32();
- const F32 len3sq = edge3.dot3(edge3).getF32();
- bool abOK = (len1sq <= 100.f * len2sq) && (len1sq <= 100.f * len3sq);
- bool acOK = (len2sq <= 100.f * len1sq) && (len1sq <= 100.f * len3sq);
- bool cbOK = (len3sq <= 100.f * len1sq) && (len1sq <= 100.f * len2sq);
- if ( abOK && acOK && cbOK )
- {
- tolerance *= 1e-4f;
- }
-
- //////////////////////////////////////////////////////////////////////////
- /// End Modified
- //////////////////////////////////////////////////////////////////////////
-
- LLVector4a cross; cross.setCross3( edge1, edge2 );
-
- LLVector4a edge1b; edge1b.setSub( b, a );
- LLVector4a edge2b; edge2b.setSub( b, c );
- LLVector4a crossb; crossb.setCross3( edge1b, edge2b );
-
- if ( ( cross.dot3(cross).getF32() < tolerance ) || ( crossb.dot3(crossb).getF32() < tolerance ))
- {
- return true;
- }
- }
-
- // point triangle distance check
- {
- LLVector4a Q; Q.setSub(a, b);
- LLVector4a R; R.setSub(c, b);
-
- const F32 QQ = dot3fpu(Q, Q);
- const F32 RR = dot3fpu(R, R);
- const F32 QR = dot3fpu(R, Q);
-
- volatile F32 QQRR = QQ * RR;
- volatile F32 QRQR = QR * QR;
- F32 Det = (QQRR - QRQR);
-
- if( Det == 0.0f )
- {
- return true;
- }
- }
-
- return false;
-}
-
-bool validate_face(const LLVolumeFace& face)
+BOOL stop_gloderror()
{
+ GLuint error = glodGetError();
- for (U32 v = 0; v < face.mNumVertices; v++)
- {
- if(face.mPositions && !face.mPositions[v].isFinite3())
- {
- LL_WARNS() << "NaN position data in face found!" << LL_ENDL;
- return false;
- }
-
- if(face.mNormals && !face.mNormals[v].isFinite3())
- {
- LL_WARNS() << "NaN normal data in face found!" << LL_ENDL;
- return false;
- }
- }
-
- for (U32 i = 0; i < face.mNumIndices; ++i)
- {
- if (face.mIndices[i] >= face.mNumVertices)
- {
- LL_WARNS() << "Face has invalid index." << LL_ENDL;
- return false;
- }
- }
-
- if (face.mNumIndices % 3 != 0 || face.mNumIndices == 0)
+ if (error != GLOD_NO_ERROR)
{
- LL_WARNS() << "Face has invalid number of indices." << LL_ENDL;
- return false;
+ LL_WARNS() << "GLOD error detected, cannot generate LOD: " << std::hex << error << LL_ENDL;
+ return TRUE;
}
-
- /*const LLVector4a scale(0.5f);
-
-
- for (U32 i = 0; i < face.mNumIndices; i+=3)
- {
- U16 idx1 = face.mIndices[i];
- U16 idx2 = face.mIndices[i+1];
- U16 idx3 = face.mIndices[i+2];
-
- LLVector4a v1; v1.setMul(face.mPositions[idx1], scale);
- LLVector4a v2; v2.setMul(face.mPositions[idx2], scale);
- LLVector4a v3; v3.setMul(face.mPositions[idx3], scale);
-
- if (ll_is_degenerate(v1,v2,v3))
- {
- LL_WARNS() << "Degenerate face found!" << LL_ENDL;
- return false;
- }
- }*/
- return true;
+ return FALSE;
}
-bool validate_model(const LLModel* mdl)
+LLViewerFetchedTexture* bindMaterialDiffuseTexture(const LLImportMaterial& material)
{
- if (mdl->getNumVolumeFaces() == 0)
- {
- LL_WARNS() << "Model has no faces!" << LL_ENDL;
- return false;
- }
+ LLViewerFetchedTexture *texture = LLViewerTextureManager::getFetchedTexture(material.getDiffuseMap(), FTT_DEFAULT, TRUE, LLGLTexture::BOOST_PREVIEW);
- for (S32 i = 0; i < mdl->getNumVolumeFaces(); ++i)
+ if (texture)
{
- if (mdl->getVolumeFace(i).mNumVertices == 0)
- {
- LL_WARNS() << "Face has no vertices." << LL_ENDL;
- return false;
- }
-
- if (mdl->getVolumeFace(i).mNumIndices == 0)
+ if (texture->getDiscardLevel() > -1)
{
- LL_WARNS() << "Face has no indices." << LL_ENDL;
- return false;
- }
-
- if (!validate_face(mdl->getVolumeFace(i)))
- {
- return false;
+ gGL.getTexUnit(0)->bind(texture, true);
+ return texture;
}
}
- return true;
+ return NULL;
}
-BOOL stop_gloderror()
+std::string stripSuffix(std::string name)
{
- GLuint error = glodGetError();
-
- if (error != GLOD_NO_ERROR)
+ if ((name.find("_LOD") != -1) || (name.find("_PHYS") != -1))
{
- LL_WARNS() << "GLOD error detected, cannot generate LOD: " << std::hex << error << LL_ENDL;
- return TRUE;
+ return name.substr(0, name.rfind('_'));
}
-
- return FALSE;
+ return name;
}
-
LLMeshFilePicker::LLMeshFilePicker(LLModelPreview* mp, S32 lod)
- : LLFilePickerThread(LLFilePicker::FFLOAD_COLLADA)
+: LLFilePickerThread(LLFilePicker::FFLOAD_COLLADA)
{
mMP = mp;
mLOD = lod;
@@ -393,6 +223,29 @@ void LLMeshFilePicker::notify(const std::string& filename)
mMP->loadModel(mFile, mLOD);
}
+void FindModel(LLModelLoader::scene& scene, const std::string& name_to_match, LLModel*& baseModelOut, LLMatrix4& matOut)
+{
+ LLModelLoader::scene::iterator base_iter = scene.begin();
+ bool found = false;
+ while (!found && (base_iter != scene.end()))
+ {
+ matOut = base_iter->first;
+
+ LLModelLoader::model_instance_list::iterator base_instance_iter = base_iter->second.begin();
+ while (!found && (base_instance_iter != base_iter->second.end()))
+ {
+ LLModelInstance& base_instance = *base_instance_iter++;
+ LLModel* base_model = base_instance.mModel;
+
+ if (base_model && (base_model->mLabel == name_to_match))
+ {
+ baseModelOut = base_model;
+ return;
+ }
+ }
+ base_iter++;
+ }
+}
//-----------------------------------------------------------------------------
// LLFloaterModelPreview()
@@ -613,6 +466,11 @@ void LLFloaterModelPreview::disableViewOption(const std::string& option)
void LLFloaterModelPreview::loadModel(S32 lod)
{
mModelPreview->mLoading = true;
+ if (lod == LLModel::LOD_PHYSICS)
+ {
+ // loading physics from file
+ mModelPreview->mPhysicsSearchLOD = lod;
+ }
(new LLMeshFilePicker(mModelPreview, lod))->getFile();
}
@@ -791,9 +649,9 @@ void LLFloaterModelPreview::draw()
childSetTextArg("status", "[STATUS]", getString("status_material_mismatch"));
}
else
- if ( mModelPreview->getLoadState() > LLModelLoader::ERROR_PARSING )
- {
- childSetTextArg("status", "[STATUS]", getString(LLModel::getStatusString(mModelPreview->getLoadState() - LLModelLoader::ERROR_PARSING)));
+ if ( mModelPreview->getLoadState() > LLModelLoader::ERROR_MODEL )
+ {
+ childSetTextArg("status", "[STATUS]", getString(LLModel::getStatusString(mModelPreview->getLoadState() - LLModelLoader::ERROR_MODEL)));
}
else
if ( mModelPreview->getLoadState() == LLModelLoader::ERROR_PARSING )
@@ -945,9 +803,16 @@ BOOL LLFloaterModelPreview::handleScrollWheel(S32 x, S32 y, S32 clicks)
/*virtual*/
void LLFloaterModelPreview::onOpen(const LLSD& key)
{
+ LLModelPreview::sIgnoreLoadedCallback = false;
requestAgentUploadPermissions();
}
+/*virtual*/
+void LLFloaterModelPreview::onClose(bool app_quitting)
+{
+ LLModelPreview::sIgnoreLoadedCallback = true;
+}
+
//static
void LLFloaterModelPreview::onPhysicsParamCommit(LLUICtrl* ctrl, void* data)
{
@@ -1308,1815 +1173,6 @@ void LLFloaterModelPreview::onMouseCaptureLostModelPreview(LLMouseHandler* handl
}
//-----------------------------------------------------------------------------
-// LLModelLoader
-//-----------------------------------------------------------------------------
-LLModelLoader::LLModelLoader( std::string filename, S32 lod, LLModelPreview* preview, JointTransformMap& jointMap,
- std::deque<std::string>& jointsFromNodes )
-: mJointList( jointMap )
-, mJointsFromNode( jointsFromNodes )
-, LLThread("Model Loader"), mFilename(filename), mLod(lod), mPreview(preview), mFirstTransform(TRUE), mNumOfFetchingTextures(0)
-{
- mJointMap["mPelvis"] = "mPelvis";
- mJointMap["mTorso"] = "mTorso";
- mJointMap["mChest"] = "mChest";
- mJointMap["mNeck"] = "mNeck";
- mJointMap["mHead"] = "mHead";
- mJointMap["mSkull"] = "mSkull";
- mJointMap["mEyeRight"] = "mEyeRight";
- mJointMap["mEyeLeft"] = "mEyeLeft";
- mJointMap["mCollarLeft"] = "mCollarLeft";
- mJointMap["mShoulderLeft"] = "mShoulderLeft";
- mJointMap["mElbowLeft"] = "mElbowLeft";
- mJointMap["mWristLeft"] = "mWristLeft";
- mJointMap["mCollarRight"] = "mCollarRight";
- mJointMap["mShoulderRight"] = "mShoulderRight";
- mJointMap["mElbowRight"] = "mElbowRight";
- mJointMap["mWristRight"] = "mWristRight";
- mJointMap["mHipRight"] = "mHipRight";
- mJointMap["mKneeRight"] = "mKneeRight";
- mJointMap["mAnkleRight"] = "mAnkleRight";
- mJointMap["mFootRight"] = "mFootRight";
- mJointMap["mToeRight"] = "mToeRight";
- mJointMap["mHipLeft"] = "mHipLeft";
- mJointMap["mKneeLeft"] = "mKneeLeft";
- mJointMap["mAnkleLeft"] = "mAnkleLeft";
- mJointMap["mFootLeft"] = "mFootLeft";
- mJointMap["mToeLeft"] = "mToeLeft";
-
- mJointMap["avatar_mPelvis"] = "mPelvis";
- mJointMap["avatar_mTorso"] = "mTorso";
- mJointMap["avatar_mChest"] = "mChest";
- mJointMap["avatar_mNeck"] = "mNeck";
- mJointMap["avatar_mHead"] = "mHead";
- mJointMap["avatar_mSkull"] = "mSkull";
- mJointMap["avatar_mEyeRight"] = "mEyeRight";
- mJointMap["avatar_mEyeLeft"] = "mEyeLeft";
- mJointMap["avatar_mCollarLeft"] = "mCollarLeft";
- mJointMap["avatar_mShoulderLeft"] = "mShoulderLeft";
- mJointMap["avatar_mElbowLeft"] = "mElbowLeft";
- mJointMap["avatar_mWristLeft"] = "mWristLeft";
- mJointMap["avatar_mCollarRight"] = "mCollarRight";
- mJointMap["avatar_mShoulderRight"] = "mShoulderRight";
- mJointMap["avatar_mElbowRight"] = "mElbowRight";
- mJointMap["avatar_mWristRight"] = "mWristRight";
- mJointMap["avatar_mHipRight"] = "mHipRight";
- mJointMap["avatar_mKneeRight"] = "mKneeRight";
- mJointMap["avatar_mAnkleRight"] = "mAnkleRight";
- mJointMap["avatar_mFootRight"] = "mFootRight";
- mJointMap["avatar_mToeRight"] = "mToeRight";
- mJointMap["avatar_mHipLeft"] = "mHipLeft";
- mJointMap["avatar_mKneeLeft"] = "mKneeLeft";
- mJointMap["avatar_mAnkleLeft"] = "mAnkleLeft";
- mJointMap["avatar_mFootLeft"] = "mFootLeft";
- mJointMap["avatar_mToeLeft"] = "mToeLeft";
-
-
- mJointMap["hip"] = "mPelvis";
- mJointMap["abdomen"] = "mTorso";
- mJointMap["chest"] = "mChest";
- mJointMap["neck"] = "mNeck";
- mJointMap["head"] = "mHead";
- mJointMap["figureHair"] = "mSkull";
- mJointMap["lCollar"] = "mCollarLeft";
- mJointMap["lShldr"] = "mShoulderLeft";
- mJointMap["lForeArm"] = "mElbowLeft";
- mJointMap["lHand"] = "mWristLeft";
- mJointMap["rCollar"] = "mCollarRight";
- mJointMap["rShldr"] = "mShoulderRight";
- mJointMap["rForeArm"] = "mElbowRight";
- mJointMap["rHand"] = "mWristRight";
- mJointMap["rThigh"] = "mHipRight";
- mJointMap["rShin"] = "mKneeRight";
- mJointMap["rFoot"] = "mFootRight";
- mJointMap["lThigh"] = "mHipLeft";
- mJointMap["lShin"] = "mKneeLeft";
- mJointMap["lFoot"] = "mFootLeft";
-
- if (mPreview)
- {
- //only try to load from slm if viewer is configured to do so and this is the
- //initial model load (not an LoD or physics shape)
- mTrySLM = gSavedSettings.getBOOL("MeshImportUseSLM") && mPreview->mUploadData.empty();
- mPreview->setLoadState(STARTING);
- }
- else
- {
- mTrySLM = false;
- }
-
- assert_main_thread();
- sActiveLoaderList.push_back(this) ;
-}
-
-LLModelLoader::~LLModelLoader()
-{
- assert_main_thread();
- sActiveLoaderList.remove(this);
-}
-
-void stretch_extents(LLModel* model, LLMatrix4a& mat, LLVector4a& min, LLVector4a& max, BOOL& first_transform)
-{
- LLVector4a box[] =
- {
- LLVector4a(-1, 1,-1),
- LLVector4a(-1, 1, 1),
- LLVector4a(-1,-1,-1),
- LLVector4a(-1,-1, 1),
- LLVector4a( 1, 1,-1),
- LLVector4a( 1, 1, 1),
- LLVector4a( 1,-1,-1),
- LLVector4a( 1,-1, 1),
- };
-
- for (S32 j = 0; j < model->getNumVolumeFaces(); ++j)
- {
- const LLVolumeFace& face = model->getVolumeFace(j);
-
- LLVector4a center;
- center.setAdd(face.mExtents[0], face.mExtents[1]);
- center.mul(0.5f);
- LLVector4a size;
- size.setSub(face.mExtents[1],face.mExtents[0]);
- size.mul(0.5f);
-
- for (U32 i = 0; i < 8; i++)
- {
- LLVector4a t;
- t.setMul(size, box[i]);
- t.add(center);
-
- LLVector4a v;
-
- mat.affineTransform(t, v);
-
- if (first_transform)
- {
- first_transform = FALSE;
- min = max = v;
- }
- else
- {
- update_min_max(min, max, v);
- }
- }
- }
-}
-
-void stretch_extents(LLModel* model, LLMatrix4& mat, LLVector3& min, LLVector3& max, BOOL& first_transform)
-{
- LLVector4a mina, maxa;
- LLMatrix4a mata;
-
- mata.loadu(mat);
- mina.load3(min.mV);
- maxa.load3(max.mV);
-
- stretch_extents(model, mata, mina, maxa, first_transform);
-
- min.set(mina.getF32ptr());
- max.set(maxa.getF32ptr());
-}
-
-void LLModelLoader::run()
-{
- doLoadModel();
- doOnIdleOneTime(boost::bind(&LLModelLoader::loadModelCallback,this));
-}
-
-bool LLModelLoader::doLoadModel()
-{
- //first, look for a .slm file of the same name that was modified later
- //than the .dae
-
- if (mTrySLM)
- {
- std::string filename = mFilename;
-
- std::string::size_type i = filename.rfind(".");
- if (i != std::string::npos)
- {
- filename.replace(i, filename.size()-1, ".slm");
- llstat slm_status;
- if (LLFile::stat(filename, &slm_status) == 0)
- { //slm file exists
- llstat dae_status;
- if (LLFile::stat(mFilename, &dae_status) != 0 ||
- dae_status.st_mtime < slm_status.st_mtime)
- {
- if (loadFromSLM(filename))
- { //slm successfully loaded, if this fails, fall through and
- //try loading from dae
-
- mLod = -1; //successfully loading from an slm implicitly sets all
- //LoDs
- return true;
- }
- }
- }
- }
- }
-
- //no suitable slm exists, load from the .dae file
- DAE dae;
- domCOLLADA* dom = dae.open(mFilename);
-
- if (!dom)
- {
- LL_INFOS()<<" Error with dae - traditionally indicates a corrupt file."<<LL_ENDL;
- setLoadState( ERROR_PARSING );
- return false;
- }
- //Dom version
- daeString domVersion = dae.getDomVersion();
- std::string sldom(domVersion);
- LL_INFOS()<<"Collada Importer Version: "<<sldom<<LL_ENDL;
- //Dae version
- domVersionType docVersion = dom->getVersion();
- //0=1.4
- //1=1.4.1
- //2=Currently unsupported, however may work
- if (docVersion > 1 )
- {
- docVersion = VERSIONTYPE_COUNT;
- }
- LL_INFOS()<<"Dae version "<<colladaVersion[docVersion]<<LL_ENDL;
-
-
- daeDatabase* db = dae.getDatabase();
-
- daeInt count = db->getElementCount(NULL, COLLADA_TYPE_MESH);
-
- daeDocument* doc = dae.getDoc(mFilename);
- if (!doc)
- {
- LL_WARNS() << "can't find internal doc" << LL_ENDL;
- return false;
- }
-
- daeElement* root = doc->getDomRoot();
- if (!root)
- {
- LL_WARNS() << "document has no root" << LL_ENDL;
- return false;
- }
-
- //Verify some basic properties of the dae
- //1. Basic validity check on controller
- U32 controllerCount = (int) db->getElementCount( NULL, "controller" );
- bool result = false;
- for ( int i=0; i<controllerCount; ++i )
- {
- domController* pController = NULL;
- db->getElement( (daeElement**) &pController, i , NULL, "controller" );
- result = mPreview->verifyController( pController );
- if (!result)
- {
- setLoadState( ERROR_PARSING );
- return true;
- }
- }
-
-
- //get unit scale
- mTransform.setIdentity();
-
- domAsset::domUnit* unit = daeSafeCast<domAsset::domUnit>(root->getDescendant(daeElement::matchType(domAsset::domUnit::ID())));
-
- if (unit)
- {
- F32 meter = unit->getMeter();
- mTransform.mMatrix[0][0] = meter;
- mTransform.mMatrix[1][1] = meter;
- mTransform.mMatrix[2][2] = meter;
- }
-
- //get up axis rotation
- LLMatrix4 rotation;
-
- domUpAxisType up = UPAXISTYPE_Y_UP; // default is Y_UP
- domAsset::domUp_axis* up_axis =
- daeSafeCast<domAsset::domUp_axis>(root->getDescendant(daeElement::matchType(domAsset::domUp_axis::ID())));
-
- if (up_axis)
- {
- up = up_axis->getValue();
- }
-
- if (up == UPAXISTYPE_X_UP)
- {
- rotation.initRotation(0.0f, 90.0f * DEG_TO_RAD, 0.0f);
- }
- else if (up == UPAXISTYPE_Y_UP)
- {
- rotation.initRotation(90.0f * DEG_TO_RAD, 0.0f, 0.0f);
- }
-
- rotation *= mTransform;
- mTransform = rotation;
-
-
- for (daeInt idx = 0; idx < count; ++idx)
- { //build map of domEntities to LLModel
- domMesh* mesh = NULL;
- db->getElement((daeElement**) &mesh, idx, NULL, COLLADA_TYPE_MESH);
-
- if (mesh)
- {
- LLPointer<LLModel> model = LLModel::loadModelFromDomMesh(mesh);
-
- if(model->getStatus() != LLModel::NO_ERRORS)
- {
- setLoadState(ERROR_PARSING + model->getStatus()) ;
- return false; //abort
- }
-
- if (model.notNull() && validate_model(model))
- {
- mModelList.push_back(model);
- mModel[mesh] = model;
- }
- }
- }
-
- count = db->getElementCount(NULL, COLLADA_TYPE_SKIN);
- for (daeInt idx = 0; idx < count; ++idx)
- { //add skinned meshes as instances
- domSkin* skin = NULL;
- db->getElement((daeElement**) &skin, idx, NULL, COLLADA_TYPE_SKIN);
-
- if (skin)
- {
- domGeometry* geom = daeSafeCast<domGeometry>(skin->getSource().getElement());
-
- if (geom)
- {
- domMesh* mesh = geom->getMesh();
- if (mesh)
- {
- LLModel* model = mModel[mesh];
- if (model)
- {
- LLVector3 mesh_scale_vector;
- LLVector3 mesh_translation_vector;
- model->getNormalizedScaleTranslation(mesh_scale_vector, mesh_translation_vector);
-
- LLMatrix4 normalized_transformation;
- normalized_transformation.setTranslation(mesh_translation_vector);
-
- LLMatrix4 mesh_scale;
- mesh_scale.initScale(mesh_scale_vector);
- mesh_scale *= normalized_transformation;
- normalized_transformation = mesh_scale;
-
- glh::matrix4f inv_mat((F32*) normalized_transformation.mMatrix);
- inv_mat = inv_mat.inverse();
- LLMatrix4 inverse_normalized_transformation(inv_mat.m);
-
- domSkin::domBind_shape_matrix* bind_mat = skin->getBind_shape_matrix();
-
- if (bind_mat)
- { //get bind shape matrix
- domFloat4x4& dom_value = bind_mat->getValue();
-
- LLMeshSkinInfo& skin_info = model->mSkinInfo;
-
- for (int i = 0; i < 4; i++)
- {
- for(int j = 0; j < 4; j++)
- {
- skin_info.mBindShapeMatrix.mMatrix[i][j] = dom_value[i + j*4];
- }
- }
-
- LLMatrix4 trans = normalized_transformation;
- trans *= skin_info.mBindShapeMatrix;
- skin_info.mBindShapeMatrix = trans;
- }
-
-
- //Some collada setup for accessing the skeleton
- daeElement* pElement = 0;
- dae.getDatabase()->getElement( &pElement, 0, 0, "skeleton" );
-
- //Try to get at the skeletal instance controller
- domInstance_controller::domSkeleton* pSkeleton = daeSafeCast<domInstance_controller::domSkeleton>( pElement );
- bool missingSkeletonOrScene = false;
-
- //If no skeleton, do a breadth-first search to get at specific joints
- bool rootNode = false;
-
- //Need to test for a skeleton that does not have a root node
- //This occurs when your instance controller does not have an associated scene
- if ( pSkeleton )
- {
- daeElement* pSkeletonRootNode = pSkeleton->getValue().getElement();
- if ( pSkeletonRootNode )
- {
- rootNode = true;
- }
-
- }
- if ( !pSkeleton || !rootNode )
- {
- daeElement* pScene = root->getDescendant("visual_scene");
- if ( !pScene )
- {
- LL_WARNS()<<"No visual scene - unable to parse bone offsets "<<LL_ENDL;
- missingSkeletonOrScene = true;
- }
- else
- {
- //Get the children at this level
- daeTArray< daeSmartRef<daeElement> > children = pScene->getChildren();
- S32 childCount = children.getCount();
-
- //Process any children that are joints
- //Not all children are joints, some code be ambient lights, cameras, geometry etc..
- for (S32 i = 0; i < childCount; ++i)
- {
- domNode* pNode = daeSafeCast<domNode>(children[i]);
- if ( isNodeAJoint( pNode ) )
- {
- processJointNode( pNode, mJointList );
- }
- }
- }
- }
- else
- //Has Skeleton
- {
- //Get the root node of the skeleton
- daeElement* pSkeletonRootNode = pSkeleton->getValue().getElement();
- if ( pSkeletonRootNode )
- {
- //Once we have the root node - start acccessing it's joint components
- const int jointCnt = mJointMap.size();
- std::map<std::string, std::string> :: const_iterator jointIt = mJointMap.begin();
-
- //Loop over all the possible joints within the .dae - using the allowed joint list in the ctor.
- for ( int i=0; i<jointCnt; ++i, ++jointIt )
- {
- //Build a joint for the resolver to work with
- char str[64]={0};
- sprintf(str,"./%s",(*jointIt).first.c_str() );
- //LL_WARNS()<<"Joint "<< str <<LL_ENDL;
-
- //Setup the resolver
- daeSIDResolver resolver( pSkeletonRootNode, str );
-
- //Look for the joint
- domNode* pJoint = daeSafeCast<domNode>( resolver.getElement() );
- if ( pJoint )
- {
- //Pull out the translate id and store it in the jointTranslations map
- daeSIDResolver jointResolverA( pJoint, "./translate" );
- domTranslate* pTranslateA = daeSafeCast<domTranslate>( jointResolverA.getElement() );
- daeSIDResolver jointResolverB( pJoint, "./location" );
- domTranslate* pTranslateB = daeSafeCast<domTranslate>( jointResolverB.getElement() );
-
- LLMatrix4 workingTransform;
-
- //Translation via SID
- if ( pTranslateA )
- {
- extractTranslation( pTranslateA, workingTransform );
- }
- else
- if ( pTranslateB )
- {
- extractTranslation( pTranslateB, workingTransform );
- }
- else
- {
- //Translation via child from element
- daeElement* pTranslateElement = getChildFromElement( pJoint, "translate" );
- if ( pTranslateElement && pTranslateElement->typeID() != domTranslate::ID() )
- {
- LL_WARNS()<< "The found element is not a translate node" <<LL_ENDL;
- missingSkeletonOrScene = true;
- }
- else
- if ( pTranslateElement )
- {
- extractTranslationViaElement( pTranslateElement, workingTransform );
- }
- else
- {
- extractTranslationViaSID( pJoint, workingTransform );
- }
-
- }
-
- //Store the joint transform w/respect to it's name.
- mJointList[(*jointIt).second.c_str()] = workingTransform;
- }
- }
-
- //If anything failed in regards to extracting the skeleton, joints or translation id,
- //mention it
- if ( missingSkeletonOrScene )
- {
- LL_WARNS()<< "Partial jointmap found in asset - did you mean to just have a partial map?" << LL_ENDL;
- }
- }//got skeleton?
- }
-
-
- domSkin::domJoints* joints = skin->getJoints();
-
- domInputLocal_Array& joint_input = joints->getInput_array();
-
- for (size_t i = 0; i < joint_input.getCount(); ++i)
- {
- domInputLocal* input = joint_input.get(i);
- xsNMTOKEN semantic = input->getSemantic();
-
- if (strcmp(semantic, COMMON_PROFILE_INPUT_JOINT) == 0)
- { //found joint source, fill model->mJointMap and model->mSkinInfo.mJointNames
- daeElement* elem = input->getSource().getElement();
-
- domSource* source = daeSafeCast<domSource>(elem);
- if (source)
- {
-
-
- domName_array* names_source = source->getName_array();
-
- if (names_source)
- {
- domListOfNames &names = names_source->getValue();
-
- for (size_t j = 0; j < names.getCount(); ++j)
- {
- std::string name(names.get(j));
- if (mJointMap.find(name) != mJointMap.end())
- {
- name = mJointMap[name];
- }
- model->mSkinInfo.mJointNames.push_back(name);
- model->mSkinInfo.mJointMap[name] = j;
- }
- }
- else
- {
- domIDREF_array* names_source = source->getIDREF_array();
- if (names_source)
- {
- xsIDREFS& names = names_source->getValue();
-
- for (size_t j = 0; j < names.getCount(); ++j)
- {
- std::string name(names.get(j).getID());
- if (mJointMap.find(name) != mJointMap.end())
- {
- name = mJointMap[name];
- }
- model->mSkinInfo.mJointNames.push_back(name);
- model->mSkinInfo.mJointMap[name] = j;
- }
- }
- }
- }
- }
- else if (strcmp(semantic, COMMON_PROFILE_INPUT_INV_BIND_MATRIX) == 0)
- { //found inv_bind_matrix array, fill model->mInvBindMatrix
- domSource* source = daeSafeCast<domSource>(input->getSource().getElement());
- if (source)
- {
- domFloat_array* t = source->getFloat_array();
- if (t)
- {
- domListOfFloats& transform = t->getValue();
- S32 count = transform.getCount()/16;
-
- for (S32 k = 0; k < count; ++k)
- {
- LLMatrix4 mat;
-
- for (int i = 0; i < 4; i++)
- {
- for(int j = 0; j < 4; j++)
- {
- mat.mMatrix[i][j] = transform[k*16 + i + j*4];
- }
- }
-
- model->mSkinInfo.mInvBindMatrix.push_back(mat);
- }
- }
- }
- }
- }
-
- //Now that we've parsed the joint array, let's determine if we have a full rig
- //(which means we have all the joint sthat are required for an avatar versus
- //a skinned asset attached to a node in a file that contains an entire skeleton,
- //but does not use the skeleton).
- buildJointToNodeMappingFromScene( root );
- mPreview->critiqueRigForUploadApplicability( model->mSkinInfo.mJointNames );
-
- if ( !missingSkeletonOrScene )
- {
- //Set the joint translations on the avatar - if it's a full mapping
- //The joints are reset in the dtor
- if ( mPreview->getRigWithSceneParity() )
- {
- std::map<std::string, std::string> :: const_iterator masterJointIt = mJointMap.begin();
- std::map<std::string, std::string> :: const_iterator masterJointItEnd = mJointMap.end();
- for (;masterJointIt!=masterJointItEnd;++masterJointIt )
- {
- std::string lookingForJoint = (*masterJointIt).first.c_str();
-
- if ( mJointList.find( lookingForJoint ) != mJointList.end() )
- {
- //LL_INFOS()<<"joint "<<lookingForJoint.c_str()<<LL_ENDL;
- LLMatrix4 jointTransform = mJointList[lookingForJoint];
- LLJoint* pJoint = mPreview->getPreviewAvatar()->getJoint( lookingForJoint );
- if ( pJoint )
- {
- LLUUID fake_mesh_id;
- fake_mesh_id.generate();
- pJoint->addAttachmentPosOverride( jointTransform.getTranslation(), fake_mesh_id, gAgentAvatarp->avString());
- }
- else
- {
- //Most likely an error in the asset.
- LL_WARNS()<<"Tried to apply joint position from .dae, but it did not exist in the avatar rig." << LL_ENDL;
- }
- }
- }
- }
- } //missingSkeletonOrScene
-
-
- //We need to construct the alternate bind matrix (which contains the new joint positions)
- //in the same order as they were stored in the joint buffer. The joints associated
- //with the skeleton are not stored in the same order as they are in the exported joint buffer.
- //This remaps the skeletal joints to be in the same order as the joints stored in the model.
- std::vector<std::string> :: const_iterator jointIt = model->mSkinInfo.mJointNames.begin();
- const int jointCnt = model->mSkinInfo.mJointNames.size();
- for ( int i=0; i<jointCnt; ++i, ++jointIt )
- {
- std::string lookingForJoint = (*jointIt).c_str();
- //Look for the joint xform that we extracted from the skeleton, using the jointIt as the key
- //and store it in the alternate bind matrix
- if ( mJointList.find( lookingForJoint ) != mJointList.end() )
- {
- LLMatrix4 jointTransform = mJointList[lookingForJoint];
- LLMatrix4 newInverse = model->mSkinInfo.mInvBindMatrix[i];
- newInverse.setTranslation( mJointList[lookingForJoint].getTranslation() );
- model->mSkinInfo.mAlternateBindMatrix.push_back( newInverse );
- }
- else
- {
- LL_WARNS()<<"Possibly misnamed/missing joint [" <<lookingForJoint.c_str()<<" ] "<<LL_ENDL;
- }
- }
-
- //grab raw position array
-
- domVertices* verts = mesh->getVertices();
- if (verts)
- {
- domInputLocal_Array& inputs = verts->getInput_array();
- for (size_t i = 0; i < inputs.getCount() && model->mPosition.empty(); ++i)
- {
- if (strcmp(inputs[i]->getSemantic(), COMMON_PROFILE_INPUT_POSITION) == 0)
- {
- domSource* pos_source = daeSafeCast<domSource>(inputs[i]->getSource().getElement());
- if (pos_source)
- {
- domFloat_array* pos_array = pos_source->getFloat_array();
- if (pos_array)
- {
- domListOfFloats& pos = pos_array->getValue();
-
- for (size_t j = 0; j < pos.getCount(); j += 3)
- {
- if (pos.getCount() <= j+2)
- {
- LL_ERRS() << "Invalid position array size." << LL_ENDL;
- }
-
- LLVector3 v(pos[j], pos[j+1], pos[j+2]);
-
- //transform from COLLADA space to volume space
- v = v * inverse_normalized_transformation;
-
- model->mPosition.push_back(v);
- }
- }
- }
- }
- }
- }
-
- //grab skin weights array
- domSkin::domVertex_weights* weights = skin->getVertex_weights();
- if (weights)
- {
- domInputLocalOffset_Array& inputs = weights->getInput_array();
- domFloat_array* vertex_weights = NULL;
- for (size_t i = 0; i < inputs.getCount(); ++i)
- {
- if (strcmp(inputs[i]->getSemantic(), COMMON_PROFILE_INPUT_WEIGHT) == 0)
- {
- domSource* weight_source = daeSafeCast<domSource>(inputs[i]->getSource().getElement());
- if (weight_source)
- {
- vertex_weights = weight_source->getFloat_array();
- }
- }
- }
-
- if (vertex_weights)
- {
- domListOfFloats& w = vertex_weights->getValue();
- domListOfUInts& vcount = weights->getVcount()->getValue();
- domListOfInts& v = weights->getV()->getValue();
-
- U32 c_idx = 0;
- for (size_t vc_idx = 0; vc_idx < vcount.getCount(); ++vc_idx)
- { //for each vertex
- daeUInt count = vcount[vc_idx];
-
- //create list of weights that influence this vertex
- LLModel::weight_list weight_list;
-
- for (daeUInt i = 0; i < count; ++i)
- { //for each weight
- daeInt joint_idx = v[c_idx++];
- daeInt weight_idx = v[c_idx++];
-
- if (joint_idx == -1)
- {
- //ignore bindings to bind_shape_matrix
- continue;
- }
-
- F32 weight_value = w[weight_idx];
-
- weight_list.push_back(LLModel::JointWeight(joint_idx, weight_value));
- }
-
- //sort by joint weight
- std::sort(weight_list.begin(), weight_list.end(), LLModel::CompareWeightGreater());
-
- std::vector<LLModel::JointWeight> wght;
-
- F32 total = 0.f;
-
- for (U32 i = 0; i < llmin((U32) 4, (U32) weight_list.size()); ++i)
- { //take up to 4 most significant weights
- if (weight_list[i].mWeight > 0.f)
- {
- wght.push_back( weight_list[i] );
- total += weight_list[i].mWeight;
- }
- }
-
- F32 scale = 1.f/total;
- if (scale != 1.f)
- { //normalize weights
- for (U32 i = 0; i < wght.size(); ++i)
- {
- wght[i].mWeight *= scale;
- }
- }
-
- model->mSkinWeights[model->mPosition[vc_idx]] = wght;
- }
-
- //add instance to scene for this model
-
- LLMatrix4 transformation = mTransform;
- // adjust the transformation to compensate for mesh normalization
-
- LLMatrix4 mesh_translation;
- mesh_translation.setTranslation(mesh_translation_vector);
- mesh_translation *= transformation;
- transformation = mesh_translation;
-
- LLMatrix4 mesh_scale;
- mesh_scale.initScale(mesh_scale_vector);
- mesh_scale *= transformation;
- transformation = mesh_scale;
-
- std::map<std::string, LLImportMaterial> materials;
- for (U32 i = 0; i < model->mMaterialList.size(); ++i)
- {
- materials[model->mMaterialList[i]] = LLImportMaterial();
- }
- mScene[transformation].push_back(LLModelInstance(model, model->mLabel, transformation, materials));
- stretch_extents(model, transformation, mExtents[0], mExtents[1], mFirstTransform);
- }
- }
- }
- }
- }
- }
- }
-
- daeElement* scene = root->getDescendant("visual_scene");
-
- if (!scene)
- {
- LL_WARNS() << "document has no visual_scene" << LL_ENDL;
- setLoadState( ERROR_PARSING );
- return true;
- }
-
- setLoadState( DONE );
-
- bool badElement = false;
-
- processElement( scene, badElement );
-
- if ( badElement )
- {
- setLoadState( ERROR_PARSING );
- }
-
- return true;
-}
-
-void LLModelLoader::setLoadState(U32 state)
-{
- if (mPreview)
- {
- mPreview->setLoadState(state);
- }
-}
-
-bool LLModelLoader::loadFromSLM(const std::string& filename)
-{
- //only need to populate mScene with data from slm
- llstat stat;
-
- if (LLFile::stat(filename, &stat))
- { //file does not exist
- return false;
- }
-
- S32 file_size = (S32) stat.st_size;
-
- llifstream ifstream(filename.c_str(), std::ifstream::in | std::ifstream::binary);
- LLSD data;
- LLSDSerialize::fromBinary(data, ifstream, file_size);
- ifstream.close();
-
- //build model list for each LoD
- model_list model[LLModel::NUM_LODS];
-
- if (data["version"].asInteger() != SLM_SUPPORTED_VERSION)
- { //unsupported version
- return false;
- }
-
- LLSD& mesh = data["mesh"];
-
- LLVolumeParams volume_params;
- volume_params.setType(LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE);
-
- for (S32 lod = 0; lod < LLModel::NUM_LODS; ++lod)
- {
- for (U32 i = 0; i < mesh.size(); ++i)
- {
- std::stringstream str(mesh[i].asString());
- LLPointer<LLModel> loaded_model = new LLModel(volume_params, (F32) lod);
- if (loaded_model->loadModel(str))
- {
- loaded_model->mLocalID = i;
- model[lod].push_back(loaded_model);
-
- if (lod == LLModel::LOD_HIGH && !loaded_model->mSkinInfo.mJointNames.empty())
- {
- //check to see if rig is valid
- mPreview->critiqueRigForUploadApplicability( loaded_model->mSkinInfo.mJointNames );
- }
- }
- }
- }
-
- if (model[LLModel::LOD_HIGH].empty())
- { //failed to load high lod
- return false;
- }
-
- // Set name.
- std::string name = data["name"];
- if (!name.empty())
- {
- model[LLModel::LOD_HIGH][0]->mLabel = name;
- }
-
-
- //load instance list
- model_instance_list instance_list;
-
- LLSD& instance = data["instance"];
-
- for (U32 i = 0; i < instance.size(); ++i)
- {
- //deserialize instance list
- instance_list.push_back(LLModelInstance(instance[i]));
-
- //match up model instance pointers
- S32 idx = instance_list[i].mLocalMeshID;
-
- for (U32 lod = 0; lod < LLModel::NUM_LODS; ++lod)
- {
- if (!model[lod].empty())
- {
- instance_list[i].mLOD[lod] = model[lod][idx];
- }
- }
-
- instance_list[i].mModel = model[LLModel::LOD_HIGH][idx];
- }
-
-
- //convert instance_list to mScene
- mFirstTransform = TRUE;
- for (U32 i = 0; i < instance_list.size(); ++i)
- {
- LLModelInstance& cur_instance = instance_list[i];
- mScene[cur_instance.mTransform].push_back(cur_instance);
- stretch_extents(cur_instance.mModel, cur_instance.mTransform, mExtents[0], mExtents[1], mFirstTransform);
- }
-
- setLoadState( DONE );
-
- return true;
-}
-
-//static
-bool LLModelLoader::isAlive(LLModelLoader* loader)
-{
- if(!loader)
- {
- return false ;
- }
-
- std::list<LLModelLoader*>::iterator iter = sActiveLoaderList.begin() ;
- for(; iter != sActiveLoaderList.end() && (*iter) != loader; ++iter) ;
-
- return *iter == loader ;
-}
-
-void LLModelLoader::loadModelCallback()
-{
- assert_main_thread();
-
- if (mPreview)
- {
- mPreview->loadModelCallback(mLod);
- }
-
- while (!isStopped())
- { //wait until this thread is stopped before deleting self
- apr_sleep(100);
- }
-
- //doubel check if "this" is valid before deleting it, in case it is aborted during running.
- if(!isAlive(this))
- {
- return ;
- }
-
- //cleanup model loader
- if (mPreview)
- {
- mPreview->mModelLoader = NULL;
- }
-
- delete this;
-}
-//-----------------------------------------------------------------------------
-// buildJointToNodeMappingFromScene()
-//-----------------------------------------------------------------------------
-void LLModelLoader::buildJointToNodeMappingFromScene( daeElement* pRoot )
-{
- daeElement* pScene = pRoot->getDescendant("visual_scene");
- if ( pScene )
- {
- daeTArray< daeSmartRef<daeElement> > children = pScene->getChildren();
- S32 childCount = children.getCount();
- for (S32 i = 0; i < childCount; ++i)
- {
- domNode* pNode = daeSafeCast<domNode>(children[i]);
- processJointToNodeMapping( pNode );
- }
- }
-}
-//-----------------------------------------------------------------------------
-// processJointToNodeMapping()
-//-----------------------------------------------------------------------------
-void LLModelLoader::processJointToNodeMapping( domNode* pNode )
-{
- if ( isNodeAJoint( pNode ) )
- {
- //1.Store the parent
- std::string nodeName = pNode->getName();
- if ( !nodeName.empty() )
- {
- mJointsFromNode.push_front( pNode->getName() );
- }
- //2. Handle the kiddo's
- processChildJoints( pNode );
- }
- else
- {
- //Determine if the're any children wrt to this failed node.
- //This occurs when an armature is exported and ends up being what essentially amounts to
- //as the root for the visual_scene
- if ( pNode )
- {
- processChildJoints( pNode );
- }
- else
- {
- LL_INFOS()<<"Node is NULL"<<LL_ENDL;
- }
-
- }
-}
-//-----------------------------------------------------------------------------
-// processChildJoint()
-//-----------------------------------------------------------------------------
-void LLModelLoader::processChildJoints( domNode* pParentNode )
-{
- daeTArray< daeSmartRef<daeElement> > childOfChild = pParentNode->getChildren();
- S32 childOfChildCount = childOfChild.getCount();
- for (S32 i = 0; i < childOfChildCount; ++i)
- {
- domNode* pChildNode = daeSafeCast<domNode>( childOfChild[i] );
- if ( pChildNode )
- {
- processJointToNodeMapping( pChildNode );
- }
- }
-}
-
-//-----------------------------------------------------------------------------
-// critiqueRigForUploadApplicability()
-//-----------------------------------------------------------------------------
-void LLModelPreview::critiqueRigForUploadApplicability( const std::vector<std::string> &jointListFromAsset )
-{
- critiqueJointToNodeMappingFromScene();
-
- //Determines the following use cases for a rig:
- //1. It is suitable for upload with skin weights & joint positions, or
- //2. It is suitable for upload as standard av with just skin weights
-
- bool isJointPositionUploadOK = isRigSuitableForJointPositionUpload( jointListFromAsset );
- bool isRigLegacyOK = isRigLegacy( jointListFromAsset );
-
- //It's OK that both could end up being true, both default to false
- if ( isJointPositionUploadOK )
- {
- setRigValidForJointPositionUpload( true );
- }
-
- if ( isRigLegacyOK)
- {
- setLegacyRigValid( true );
- }
-
-}
-//-----------------------------------------------------------------------------
-// critiqueJointToNodeMappingFromScene()
-//-----------------------------------------------------------------------------
-void LLModelPreview::critiqueJointToNodeMappingFromScene( void )
-{
- //Do the actual nodes back the joint listing from the dae?
- //if yes then this is a fully rigged asset, otherwise it's just a partial rig
-
- std::deque<std::string>::iterator jointsFromNodeIt = mJointsFromNode.begin();
- std::deque<std::string>::iterator jointsFromNodeEndIt = mJointsFromNode.end();
- bool result = true;
-
- if ( !mJointsFromNode.empty() )
- {
- for ( ;jointsFromNodeIt!=jointsFromNodeEndIt;++jointsFromNodeIt )
- {
- std::string name = *jointsFromNodeIt;
- if ( mJointTransformMap.find( name ) != mJointTransformMap.end() )
- {
- continue;
- }
- else
- {
- LL_INFOS()<<"critiqueJointToNodeMappingFromScene is missing a: "<<name<<LL_ENDL;
- result = false;
- }
- }
- }
- else
- {
- result = false;
- }
-
- //Determines the following use cases for a rig:
- //1. Full av rig w/1-1 mapping from the scene and joint array
- //2. Partial rig but w/o parity between the scene and joint array
- if ( result )
- {
- setRigWithSceneParity( true );
- }
-}
-//-----------------------------------------------------------------------------
-// isRigLegacy()
-//-----------------------------------------------------------------------------
-bool LLModelPreview::isRigLegacy( const std::vector<std::string> &jointListFromAsset )
-{
- //No joints in asset
- if ( jointListFromAsset.size() == 0 )
- {
- return false;
- }
-
- bool result = false;
-
- std::deque<std::string> :: const_iterator masterJointIt = mMasterLegacyJointList.begin();
- std::deque<std::string> :: const_iterator masterJointEndIt = mMasterLegacyJointList.end();
-
- std::vector<std::string> :: const_iterator modelJointIt = jointListFromAsset.begin();
- std::vector<std::string> :: const_iterator modelJointItEnd = jointListFromAsset.end();
-
- for ( ;masterJointIt!=masterJointEndIt;++masterJointIt )
- {
- result = false;
- modelJointIt = jointListFromAsset.begin();
-
- for ( ;modelJointIt!=modelJointItEnd; ++modelJointIt )
- {
- if ( *masterJointIt == *modelJointIt )
- {
- result = true;
- break;
- }
- }
- if ( !result )
- {
- LL_INFOS()<<" Asset did not contain the joint (if you're u/l a fully rigged asset w/joint positions - it is required)." << *masterJointIt<< LL_ENDL;
- break;
- }
- }
- return result;
-}
-//-----------------------------------------------------------------------------
-// isRigSuitableForJointPositionUpload()
-//-----------------------------------------------------------------------------
-bool LLModelPreview::isRigSuitableForJointPositionUpload( const std::vector<std::string> &jointListFromAsset )
-{
- bool result = false;
-
- std::deque<std::string> :: const_iterator masterJointIt = mMasterJointList.begin();
- std::deque<std::string> :: const_iterator masterJointEndIt = mMasterJointList.end();
-
- std::vector<std::string> :: const_iterator modelJointIt = jointListFromAsset.begin();
- std::vector<std::string> :: const_iterator modelJointItEnd = jointListFromAsset.end();
-
- for ( ;masterJointIt!=masterJointEndIt;++masterJointIt )
- {
- result = false;
- modelJointIt = jointListFromAsset.begin();
-
- for ( ;modelJointIt!=modelJointItEnd; ++modelJointIt )
- {
- if ( *masterJointIt == *modelJointIt )
- {
- result = true;
- break;
- }
- }
- if ( !result )
- {
- LL_INFOS()<<" Asset did not contain the joint (if you're u/l a fully rigged asset w/joint positions - it is required)." << *masterJointIt<< LL_ENDL;
- break;
- }
- }
- return result;
-}
-
-
-//called in the main thread
-void LLModelLoader::loadTextures()
-{
- BOOL is_paused = isPaused() ;
- pause() ; //pause the loader
-
- for(scene::iterator iter = mScene.begin(); iter != mScene.end(); ++iter)
- {
- for(U32 i = 0 ; i < iter->second.size(); i++)
- {
- for(std::map<std::string, LLImportMaterial>::iterator j = iter->second[i].mMaterial.begin();
- j != iter->second[i].mMaterial.end(); ++j)
- {
- LLImportMaterial& material = j->second;
-
- if(!material.mDiffuseMapFilename.empty())
- {
- material.mDiffuseMap =
- LLViewerTextureManager::getFetchedTextureFromUrl("file://" + material.mDiffuseMapFilename, FTT_LOCAL_FILE, TRUE, LLGLTexture::BOOST_PREVIEW);
- material.mDiffuseMap->setLoadedCallback(LLModelPreview::textureLoadedCallback, 0, TRUE, FALSE, mPreview, NULL, FALSE);
- material.mDiffuseMap->forceToSaveRawImage(0, F32_MAX);
- mNumOfFetchingTextures++ ;
- }
- }
- }
- }
-
- if(!is_paused)
- {
- unpause() ;
- }
-}
-
-//-----------------------------------------------------------------------------
-// isNodeAJoint()
-//-----------------------------------------------------------------------------
-bool LLModelLoader::isNodeAJoint( domNode* pNode )
-{
- if ( !pNode )
- {
- LL_INFOS()<<"Created node is NULL"<<LL_ENDL;
- return false;
- }
-
- if ( pNode->getName() == NULL )
- {
- LL_INFOS()<<"Parsed node has no name "<<LL_ENDL;
- //Attempt to write the node id, if possible (aids in debugging the visual scene)
- if ( pNode->getId() )
- {
- LL_INFOS()<<"Parsed node ID: "<<pNode->getId()<<LL_ENDL;
- }
- return false;
- }
-
- if ( mJointMap.find( pNode->getName() ) != mJointMap.end() )
- {
- return true;
- }
-
- return false;
-}
-//-----------------------------------------------------------------------------
-// verifyCount
-//-----------------------------------------------------------------------------
-bool LLModelPreview::verifyCount( int expected, int result )
-{
- if ( expected != result )
- {
- LL_INFOS()<< "Error: (expected/got)"<<expected<<"/"<<result<<"verts"<<LL_ENDL;
- return false;
- }
- return true;
-}
-//-----------------------------------------------------------------------------
-// verifyController
-//-----------------------------------------------------------------------------
-bool LLModelPreview::verifyController( domController* pController )
-{
-
- bool result = true;
-
- domSkin* pSkin = pController->getSkin();
-
- if ( pSkin )
- {
- xsAnyURI & uri = pSkin->getSource();
- domElement* pElement = uri.getElement();
-
- if ( !pElement )
- {
- LL_INFOS()<<"Can't resolve skin source"<<LL_ENDL;
- return false;
- }
-
- daeString type_str = pElement->getTypeName();
- if ( stricmp(type_str, "geometry") == 0 )
- {
- //Skin is reference directly by geometry and get the vertex count from skin
- domSkin::domVertex_weights* pVertexWeights = pSkin->getVertex_weights();
- U32 vertexWeightsCount = pVertexWeights->getCount();
- domGeometry* pGeometry = (domGeometry*) (domElement*) uri.getElement();
- domMesh* pMesh = pGeometry->getMesh();
-
- if ( pMesh )
- {
- //Get vertex count from geometry
- domVertices* pVertices = pMesh->getVertices();
- if ( !pVertices )
- {
- LL_INFOS()<<"No vertices!"<<LL_ENDL;
- return false;
- }
-
- if ( pVertices )
- {
- xsAnyURI src = pVertices->getInput_array()[0]->getSource();
- domSource* pSource = (domSource*) (domElement*) src.getElement();
- U32 verticesCount = pSource->getTechnique_common()->getAccessor()->getCount();
- result = verifyCount( verticesCount, vertexWeightsCount );
- if ( !result )
- {
- return result;
- }
- }
- }
-
- U32 vcountCount = (U32) pVertexWeights->getVcount()->getValue().getCount();
- result = verifyCount( vcountCount, vertexWeightsCount );
- if ( !result )
- {
- return result;
- }
-
- domInputLocalOffset_Array& inputs = pVertexWeights->getInput_array();
- U32 sum = 0;
- for (size_t i=0; i<vcountCount; i++)
- {
- sum += pVertexWeights->getVcount()->getValue()[i];
- }
- result = verifyCount( sum * inputs.getCount(), (domInt) pVertexWeights->getV()->getValue().getCount() );
- }
- }
-
- return result;
-}
-
-//-----------------------------------------------------------------------------
-// extractTranslation()
-//-----------------------------------------------------------------------------
-void LLModelLoader::extractTranslation( domTranslate* pTranslate, LLMatrix4& transform )
-{
- domFloat3 jointTrans = pTranslate->getValue();
- LLVector3 singleJointTranslation( jointTrans[0], jointTrans[1], jointTrans[2] );
- transform.setTranslation( singleJointTranslation );
-}
-//-----------------------------------------------------------------------------
-// extractTranslationViaElement()
-//-----------------------------------------------------------------------------
-void LLModelLoader::extractTranslationViaElement( daeElement* pTranslateElement, LLMatrix4& transform )
-{
- if ( pTranslateElement )
- {
- domTranslate* pTranslateChild = dynamic_cast<domTranslate*>( pTranslateElement );
- domFloat3 translateChild = pTranslateChild->getValue();
- LLVector3 singleJointTranslation( translateChild[0], translateChild[1], translateChild[2] );
- transform.setTranslation( singleJointTranslation );
- }
-}
-//-----------------------------------------------------------------------------
-// extractTranslationViaSID()
-//-----------------------------------------------------------------------------
-void LLModelLoader::extractTranslationViaSID( daeElement* pElement, LLMatrix4& transform )
-{
- if ( pElement )
- {
- daeSIDResolver resolver( pElement, "./transform" );
- domMatrix* pMatrix = daeSafeCast<domMatrix>( resolver.getElement() );
- //We are only extracting out the translational component atm
- LLMatrix4 workingTransform;
- if ( pMatrix )
- {
- domFloat4x4 domArray = pMatrix->getValue();
- for ( int i = 0; i < 4; i++ )
- {
- for( int j = 0; j < 4; j++ )
- {
- workingTransform.mMatrix[i][j] = domArray[i + j*4];
- }
- }
- LLVector3 trans = workingTransform.getTranslation();
- transform.setTranslation( trans );
- }
- }
- else
- {
- LL_WARNS()<<"Element is nonexistent - empty/unsupported node."<<LL_ENDL;
- }
-}
-//-----------------------------------------------------------------------------
-// processJointNode()
-//-----------------------------------------------------------------------------
-void LLModelLoader::processJointNode( domNode* pNode, JointTransformMap& jointTransforms )
-{
- if (pNode->getName() == NULL)
- {
- LL_WARNS() << "nameless node, can't process" << LL_ENDL;
- return;
- }
-
- //LL_WARNS()<<"ProcessJointNode# Node:" <<pNode->getName()<<LL_ENDL;
-
- //1. handle the incoming node - extract out translation via SID or element
-
- LLMatrix4 workingTransform;
-
- //Pull out the translate id and store it in the jointTranslations map
- daeSIDResolver jointResolverA( pNode, "./translate" );
- domTranslate* pTranslateA = daeSafeCast<domTranslate>( jointResolverA.getElement() );
- daeSIDResolver jointResolverB( pNode, "./location" );
- domTranslate* pTranslateB = daeSafeCast<domTranslate>( jointResolverB.getElement() );
-
- //Translation via SID was successful
- if ( pTranslateA )
- {
- extractTranslation( pTranslateA, workingTransform );
- }
- else
- if ( pTranslateB )
- {
- extractTranslation( pTranslateB, workingTransform );
- }
- else
- {
- //Translation via child from element
- daeElement* pTranslateElement = getChildFromElement( pNode, "translate" );
- if ( !pTranslateElement || pTranslateElement->typeID() != domTranslate::ID() )
- {
- //LL_WARNS()<< "The found element is not a translate node" <<LL_ENDL;
- daeSIDResolver jointResolver( pNode, "./matrix" );
- domMatrix* pMatrix = daeSafeCast<domMatrix>( jointResolver.getElement() );
- if ( pMatrix )
- {
- //LL_INFOS()<<"A matrix SID was however found!"<<LL_ENDL;
- domFloat4x4 domArray = pMatrix->getValue();
- for ( int i = 0; i < 4; i++ )
- {
- for( int j = 0; j < 4; j++ )
- {
- workingTransform.mMatrix[i][j] = domArray[i + j*4];
- }
- }
- }
- else
- {
- LL_WARNS()<< "The found element is not translate or matrix node - most likely a corrupt export!" <<LL_ENDL;
- }
- }
- else
- {
- extractTranslationViaElement( pTranslateElement, workingTransform );
- }
- }
-
- //Store the working transform relative to the nodes name.
- jointTransforms[ pNode->getName() ] = workingTransform;
-
- //2. handle the nodes children
-
- //Gather and handle the incoming nodes children
- daeTArray< daeSmartRef<daeElement> > childOfChild = pNode->getChildren();
- S32 childOfChildCount = childOfChild.getCount();
-
- for (S32 i = 0; i < childOfChildCount; ++i)
- {
- domNode* pChildNode = daeSafeCast<domNode>( childOfChild[i] );
- if ( pChildNode )
- {
- processJointNode( pChildNode, jointTransforms );
- }
- }
-}
-//-----------------------------------------------------------------------------
-// getChildFromElement()
-//-----------------------------------------------------------------------------
-daeElement* LLModelLoader::getChildFromElement( daeElement* pElement, std::string const & name )
-{
- daeElement* pChildOfElement = pElement->getChild( name.c_str() );
- if ( pChildOfElement )
- {
- return pChildOfElement;
- }
- LL_WARNS()<< "Could not find a child [" << name << "] for the element: \"" << pElement->getAttribute("id") << "\"" << LL_ENDL;
- return NULL;
-}
-
-void LLModelLoader::processElement( daeElement* element, bool& badElement )
-{
- LLMatrix4 saved_transform = mTransform;
-
- domTranslate* translate = daeSafeCast<domTranslate>(element);
- if (translate)
- {
- domFloat3 dom_value = translate->getValue();
-
- LLMatrix4 translation;
- translation.setTranslation(LLVector3(dom_value[0], dom_value[1], dom_value[2]));
-
- translation *= mTransform;
- mTransform = translation;
- }
-
- domRotate* rotate = daeSafeCast<domRotate>(element);
- if (rotate)
- {
- domFloat4 dom_value = rotate->getValue();
-
- LLMatrix4 rotation;
- rotation.initRotTrans(dom_value[3] * DEG_TO_RAD, LLVector3(dom_value[0], dom_value[1], dom_value[2]), LLVector3(0, 0, 0));
-
- rotation *= mTransform;
- mTransform = rotation;
- }
-
- domScale* scale = daeSafeCast<domScale>(element);
- if (scale)
- {
- domFloat3 dom_value = scale->getValue();
-
-
- LLVector3 scale_vector = LLVector3(dom_value[0], dom_value[1], dom_value[2]);
- scale_vector.abs(); // Set all values positive, since we don't currently support mirrored meshes
- LLMatrix4 scaling;
- scaling.initScale(scale_vector);
-
- scaling *= mTransform;
- mTransform = scaling;
- }
-
- domMatrix* matrix = daeSafeCast<domMatrix>(element);
- if (matrix)
- {
- domFloat4x4 dom_value = matrix->getValue();
-
- LLMatrix4 matrix_transform;
-
- for (int i = 0; i < 4; i++)
- {
- for(int j = 0; j < 4; j++)
- {
- matrix_transform.mMatrix[i][j] = dom_value[i + j*4];
- }
- }
-
- matrix_transform *= mTransform;
- mTransform = matrix_transform;
- }
-
- domInstance_geometry* instance_geo = daeSafeCast<domInstance_geometry>(element);
- if (instance_geo)
- {
- domGeometry* geo = daeSafeCast<domGeometry>(instance_geo->getUrl().getElement());
- if (geo)
- {
- domMesh* mesh = daeSafeCast<domMesh>(geo->getDescendant(daeElement::matchType(domMesh::ID())));
- if (mesh)
- {
- LLModel* model = mModel[mesh];
- if (model)
- {
- LLMatrix4 transformation = mTransform;
-
- if (mTransform.determinant() < 0)
- { //negative scales are not supported
- LL_INFOS() << "Negative scale detected, unsupported transform. domInstance_geometry: " << LLModel::getElementLabel(instance_geo) << LL_ENDL;
- badElement = true;
- }
-
- std::map<std::string, LLImportMaterial> materials = getMaterials(model, instance_geo);
-
- // adjust the transformation to compensate for mesh normalization
- LLVector3 mesh_scale_vector;
- LLVector3 mesh_translation_vector;
- model->getNormalizedScaleTranslation(mesh_scale_vector, mesh_translation_vector);
-
- LLMatrix4 mesh_translation;
- mesh_translation.setTranslation(mesh_translation_vector);
- mesh_translation *= transformation;
- transformation = mesh_translation;
-
- LLMatrix4 mesh_scale;
- mesh_scale.initScale(mesh_scale_vector);
- mesh_scale *= transformation;
- transformation = mesh_scale;
-
- std::string label = getElementLabel(instance_geo);
- mScene[transformation].push_back(LLModelInstance(model, label, transformation, materials));
-
- stretch_extents(model, transformation, mExtents[0], mExtents[1], mFirstTransform);
- }
- }
- }
- else
- {
- LL_INFOS()<<"Unable to resolve geometry URL."<<LL_ENDL;
- badElement = true;
- }
-
- }
-
- domInstance_node* instance_node = daeSafeCast<domInstance_node>(element);
- if (instance_node)
- {
- daeElement* instance = instance_node->getUrl().getElement();
- if (instance)
- {
- processElement(instance,badElement);
- }
- }
-
- //process children
- daeTArray< daeSmartRef<daeElement> > children = element->getChildren();
- int childCount = children.getCount();
- for (S32 i = 0; i < childCount; i++)
- {
- processElement(children[i],badElement);
- }
-
- domNode* node = daeSafeCast<domNode>(element);
- if (node)
- { //this element was a node, restore transform before processiing siblings
- mTransform = saved_transform;
- }
-}
-
-std::map<std::string, LLImportMaterial> LLModelLoader::getMaterials(LLModel* model, domInstance_geometry* instance_geo)
-{
- std::map<std::string, LLImportMaterial> materials;
- for (int i = 0; i < model->mMaterialList.size(); i++)
- {
- LLImportMaterial import_material;
-
- domInstance_material* instance_mat = NULL;
-
- domBind_material::domTechnique_common* technique =
- daeSafeCast<domBind_material::domTechnique_common>(instance_geo->getDescendant(daeElement::matchType(domBind_material::domTechnique_common::ID())));
-
- if (technique)
- {
- daeTArray< daeSmartRef<domInstance_material> > inst_materials = technique->getChildrenByType<domInstance_material>();
- for (int j = 0; j < inst_materials.getCount(); j++)
- {
- std::string symbol(inst_materials[j]->getSymbol());
-
- if (symbol == model->mMaterialList[i]) // found the binding
- {
- instance_mat = inst_materials[j];
- }
- }
- }
-
- if (instance_mat)
- {
- domMaterial* material = daeSafeCast<domMaterial>(instance_mat->getTarget().getElement());
- if (material)
- {
- domInstance_effect* instance_effect =
- daeSafeCast<domInstance_effect>(material->getDescendant(daeElement::matchType(domInstance_effect::ID())));
- if (instance_effect)
- {
- domEffect* effect = daeSafeCast<domEffect>(instance_effect->getUrl().getElement());
- if (effect)
- {
- domProfile_COMMON* profile =
- daeSafeCast<domProfile_COMMON>(effect->getDescendant(daeElement::matchType(domProfile_COMMON::ID())));
- if (profile)
- {
- import_material = profileToMaterial(profile);
- }
- }
- }
- }
- }
-
- import_material.mBinding = model->mMaterialList[i];
- materials[model->mMaterialList[i]] = import_material;
- }
-
- return materials;
-}
-
-LLImportMaterial LLModelLoader::profileToMaterial(domProfile_COMMON* material)
-{
- LLImportMaterial mat;
- mat.mFullbright = FALSE;
-
- daeElement* diffuse = material->getDescendant("diffuse");
- if (diffuse)
- {
- domCommon_color_or_texture_type_complexType::domTexture* texture =
- daeSafeCast<domCommon_color_or_texture_type_complexType::domTexture>(diffuse->getDescendant("texture"));
- if (texture)
- {
- domCommon_newparam_type_Array newparams = material->getNewparam_array();
- for (S32 i = 0; i < newparams.getCount(); i++)
- {
- domFx_surface_common* surface = newparams[i]->getSurface();
- if (surface)
- {
- domFx_surface_init_common* init = surface->getFx_surface_init_common();
- if (init)
- {
- domFx_surface_init_from_common_Array init_from = init->getInit_from_array();
-
- if (init_from.getCount() > i)
- {
- domImage* image = daeSafeCast<domImage>(init_from[i]->getValue().getElement());
- if (image)
- {
- // we only support init_from now - embedded data will come later
- domImage::domInit_from* init = image->getInit_from();
- if (init)
- {
- mat.mDiffuseMapFilename = cdom::uriToNativePath(init->getValue().str());
- mat.mDiffuseMapLabel = getElementLabel(material);
- }
- }
- }
- }
- }
- }
- }
-
- domCommon_color_or_texture_type_complexType::domColor* color =
- daeSafeCast<domCommon_color_or_texture_type_complexType::domColor>(diffuse->getDescendant("color"));
- if (color)
- {
- domFx_color_common domfx_color = color->getValue();
- LLColor4 value = LLColor4(domfx_color[0], domfx_color[1], domfx_color[2], domfx_color[3]);
- mat.mDiffuseColor = value;
- }
- }
-
- daeElement* emission = material->getDescendant("emission");
- if (emission)
- {
- LLColor4 emission_color = getDaeColor(emission);
- if (((emission_color[0] + emission_color[1] + emission_color[2]) / 3.0) > 0.25)
- {
- mat.mFullbright = TRUE;
- }
- }
-
- return mat;
-}
-
-// try to get a decent label for this element
-std::string LLModelLoader::getElementLabel(daeElement *element)
-{
- // if we have a name attribute, use it
- std::string name = element->getAttribute("name");
- if (name.length())
- {
- return name;
- }
-
- // if we have an ID attribute, use it
- if (element->getID())
- {
- return std::string(element->getID());
- }
-
- // if we have a parent, use it
- daeElement* parent = element->getParent();
- if (parent)
- {
- // if parent has a name, use it
- std::string name = parent->getAttribute("name");
- if (name.length())
- {
- return name;
- }
-
- // if parent has an ID, use it
- if (parent->getID())
- {
- return std::string(parent->getID());
- }
- }
-
- // try to use our type
- daeString element_name = element->getElementName();
- if (element_name)
- {
- return std::string(element_name);
- }
-
- // if all else fails, use "object"
- return std::string("object");
-}
-
-LLColor4 LLModelLoader::getDaeColor(daeElement* element)
-{
- LLColor4 value;
- domCommon_color_or_texture_type_complexType::domColor* color =
- daeSafeCast<domCommon_color_or_texture_type_complexType::domColor>(element->getDescendant("color"));
- if (color)
- {
- domFx_color_common domfx_color = color->getValue();
- value = LLColor4(domfx_color[0], domfx_color[1], domfx_color[2], domfx_color[3]);
- }
-
- return value;
-}
-
-//-----------------------------------------------------------------------------
// LLModelPreview
//-----------------------------------------------------------------------------
@@ -3125,7 +1181,9 @@ LLModelPreview::LLModelPreview(S32 width, S32 height, LLFloater* fmp)
, mPelvisZOffset( 0.0f )
, mLegacyRigValid( false )
, mRigValidJointUpload( false )
+, mPhysicsSearchLOD( LLModel::LOD_PHYSICS )
, mResetJoints( false )
+, mModelNoErrors( true )
, mRigParityWithScene( false )
, mLastJointUpdate( false )
{
@@ -3170,51 +1228,20 @@ LLModelPreview::LLModelPreview(S32 width, S32 height, LLFloater* fmp)
glodInit();
- //move into joint mapper class
- //1. joints for joint offset verification
- mMasterJointList.push_front("mPelvis");
- mMasterJointList.push_front("mTorso");
- mMasterJointList.push_front("mChest");
- mMasterJointList.push_front("mNeck");
- mMasterJointList.push_front("mHead");
- mMasterJointList.push_front("mCollarLeft");
- mMasterJointList.push_front("mShoulderLeft");
- mMasterJointList.push_front("mElbowLeft");
- mMasterJointList.push_front("mWristLeft");
- mMasterJointList.push_front("mCollarRight");
- mMasterJointList.push_front("mShoulderRight");
- mMasterJointList.push_front("mElbowRight");
- mMasterJointList.push_front("mWristRight");
- mMasterJointList.push_front("mHipRight");
- mMasterJointList.push_front("mKneeRight");
- mMasterJointList.push_front("mFootRight");
- mMasterJointList.push_front("mHipLeft");
- mMasterJointList.push_front("mKneeLeft");
- mMasterJointList.push_front("mFootLeft");
- //2. legacy joint list - used to verify rigs that will not be using joint offsets
- mMasterLegacyJointList.push_front("mPelvis");
- mMasterLegacyJointList.push_front("mTorso");
- mMasterLegacyJointList.push_front("mChest");
- mMasterLegacyJointList.push_front("mNeck");
- mMasterLegacyJointList.push_front("mHead");
- mMasterLegacyJointList.push_front("mHipRight");
- mMasterLegacyJointList.push_front("mKneeRight");
- mMasterLegacyJointList.push_front("mFootRight");
- mMasterLegacyJointList.push_front("mHipLeft");
- mMasterLegacyJointList.push_front("mKneeLeft");
- mMasterLegacyJointList.push_front("mFootLeft");
-
createPreviewAvatar();
}
LLModelPreview::~LLModelPreview()
{
- if (mModelLoader)
- {
- mModelLoader->mPreview = NULL;
- mModelLoader = NULL;
- }
- //*HACK : *TODO : turn this back on when we understand why this crashes
+ // glod apparently has internal mem alignment issues that are angering
+ // the heap-check code in windows, these should be hunted down in that
+ // TP code, if possible
+ //
+ // kernel32.dll!HeapFree() + 0x14 bytes
+ // msvcr100.dll!free(void * pBlock) Line 51 C
+ // glod.dll!glodGetGroupParameteriv() + 0x119 bytes
+ // glod.dll!glodShutdown() + 0x77 bytes
+ //
//glodShutdown();
}
@@ -3284,7 +1311,9 @@ U32 LLModelPreview::calcResourceCost()
decomp,
mFMP->childGetValue("upload_skin").asBoolean(),
mFMP->childGetValue("upload_joints").asBoolean(),
- TRUE);
+ TRUE,
+ FALSE,
+ instance.mModel->mSubmodelID);
num_hulls += decomp.mHull.size();
for (U32 i = 0; i < decomp.mHull.size(); ++i)
@@ -3351,29 +1380,12 @@ void LLModelPreview::rebuildUploadData()
F32 max_scale = 0.f;
- //reorder materials to match mBaseModel
- for (U32 i = 0; i < LLModel::NUM_LODS-1; i++)
- {
- if (mBaseModel.size() == mModel[i].size())
- {
- for (U32 j = 0; j < mBaseModel.size(); ++j)
- {
-
- int refFaceCnt = 0;
- int modelFaceCnt = 0;
-
- if ( !mModel[i][j]->matchMaterialOrder(mBaseModel[j], refFaceCnt, modelFaceCnt ) )
- {
- setLoadState( LLModelLoader::ERROR_MATERIALS );
- mFMP->childDisable( "calculate_btn" );
- }
- }
- }
- }
+ BOOL importerDebug = gSavedSettings.getBOOL("ImporterDebug");
+ BOOL legacyMatching = gSavedSettings.getBOOL("ImporterLegacyMatching");
for (LLModelLoader::scene::iterator iter = mBaseScene.begin(); iter != mBaseScene.end(); ++iter)
{ //for each transform in scene
- LLMatrix4 mat = iter->first;
+ LLMatrix4 mat = iter->first;
// compute position
LLVector3 position = LLVector3(0, 0, 0) * mat;
@@ -3390,38 +1402,171 @@ void LLModelPreview::rebuildUploadData()
mat *= scale_mat;
- for (LLModelLoader::model_instance_list::iterator model_iter = iter->second.begin(); model_iter != iter->second.end(); ++model_iter)
- { //for each instance with said transform applied
- LLModelInstance instance = *model_iter;
+ for (LLModelLoader::model_instance_list::iterator model_iter = iter->second.begin(); model_iter != iter->second.end();)
+ { //for each instance with said transform applied
+ LLModelInstance instance = *model_iter++;
LLModel* base_model = instance.mModel;
- if (base_model)
+ if (base_model && !requested_name.empty())
{
base_model->mRequestedLabel = requested_name;
base_model->mMetric = metric;
}
- S32 idx = 0;
- for (idx = 0; idx < mBaseModel.size(); ++idx)
- { //find reference instance for this model
- if (mBaseModel[idx] == base_model)
+ for (int i = LLModel::NUM_LODS - 1; i >= LLModel::LOD_IMPOSTOR; i--)
+ {
+ LLModel* lod_model = NULL;
+ if (!legacyMatching)
{
- break;
+ // Fill LOD slots by finding matching meshes by label with name extensions
+ // in the appropriate scene for each LOD. This fixes all kinds of issues
+ // where the indexed method below fails in spectacular fashion.
+ // If you don't take the time to name your LOD and PHYS meshes
+ // with the name of their corresponding mesh in the HIGH LOD,
+ // then the indexed method will be attempted below.
+
+ LLMatrix4 transform;
+
+ std::string name_to_match = instance.mLabel;
+ llassert(!name_to_match.empty());
+
+ int extensionLOD;
+ if (i != LLModel::LOD_PHYSICS || mModel[LLModel::LOD_PHYSICS].empty())
+ {
+ extensionLOD = i;
+ }
+ else
+ {
+ //Physics can be inherited from other LODs or loaded, so we need to adjust what extension we are searching for
+ extensionLOD = mPhysicsSearchLOD;
+ }
+
+ std::string toAdd;
+ switch (extensionLOD)
+ {
+ case LLModel::LOD_IMPOSTOR: toAdd = "_LOD0"; break;
+ case LLModel::LOD_LOW: toAdd = "_LOD1"; break;
+ case LLModel::LOD_MEDIUM: toAdd = "_LOD2"; break;
+ case LLModel::LOD_PHYSICS: toAdd = "_PHYS"; break;
+ case LLModel::LOD_HIGH: break;
+ }
+
+ if (name_to_match.find(toAdd) == -1)
+ {
+ name_to_match += toAdd;
+ }
+
+ FindModel(mScene[i], name_to_match, lod_model, transform);
+
+ if (!lod_model && i != LLModel::LOD_PHYSICS)
+ {
+ if (importerDebug)
+ {
+ LL_INFOS() << "Search of" << name_to_match << " in LOD" << i << " list failed. Searching for alternative among LOD lists." << LL_ENDL;
+ }
+
+ int searchLOD = (i > LLModel::LOD_HIGH) ? LLModel::LOD_HIGH : i;
+ while ((searchLOD <= LLModel::LOD_HIGH) && !lod_model)
+ {
+ std::string name_to_match = instance.mLabel;
+ llassert(!name_to_match.empty());
+
+ std::string toAdd;
+ switch (searchLOD)
+ {
+ case LLModel::LOD_IMPOSTOR: toAdd = "_LOD0"; break;
+ case LLModel::LOD_LOW: toAdd = "_LOD1"; break;
+ case LLModel::LOD_MEDIUM: toAdd = "_LOD2"; break;
+ case LLModel::LOD_PHYSICS: toAdd = "_PHYS"; break;
+ case LLModel::LOD_HIGH: break;
+ }
+
+ if (name_to_match.find(toAdd) == -1)
+ {
+ name_to_match += toAdd;
+ }
+
+ // See if we can find an appropriately named model in LOD 'searchLOD'
+ //
+ FindModel(mScene[searchLOD], name_to_match, lod_model, transform);
+ searchLOD++;
+ }
+ }
}
- }
+ else
+ {
+ // Use old method of index-based association
+ U32 idx = 0;
+ for (idx = 0; idx < mBaseModel.size(); ++idx)
+ {
+ // find reference instance for this model
+ if (mBaseModel[idx] == base_model)
+ {
+ if (importerDebug)
+ {
+ LL_INFOS() << "Attempting to use model index " << idx << " for LOD " << i << " of " << instance.mLabel << LL_ENDL;
+ }
+ break;
+ }
+ }
- if(idx < mBaseModel.size())
- {
- for (U32 i = 0; i < LLModel::NUM_LODS; i++)
- { //fill LOD slots based on reference model index
+ // If the model list for the current LOD includes that index...
+ //
if (mModel[i].size() > idx)
{
- instance.mLOD[i] = mModel[i][idx];
+ // Assign that index from the model list for our LOD as the LOD model for this instance
+ //
+ lod_model = mModel[i][idx];
+ if (importerDebug)
+ {
+ LL_INFOS() << "Indexed match of model index " << idx << " at LOD " << i << " to model named " << lod_model->mLabel << LL_ENDL;
+ }
}
- else
+ else if (importerDebug)
{
- instance.mLOD[i] = NULL;
+ LL_INFOS() << "List of models does not include index " << idx << LL_ENDL;
+ }
+ }
+
+ if (lod_model)
+ {
+ if (importerDebug)
+ {
+ if (i == LLModel::LOD_PHYSICS)
+ {
+ LL_INFOS() << "Assigning collision for " << instance.mLabel << " to match " << lod_model->mLabel << LL_ENDL;
+ }
+ else
+ {
+ LL_INFOS() << "Assigning LOD" << i << " for " << instance.mLabel << " to found match " << lod_model->mLabel << LL_ENDL;
+ }
+ }
+ instance.mLOD[i] = lod_model;
+ }
+ else if (importerDebug)
+ {
+ LL_INFOS() << "List of models does not include " << instance.mLabel << LL_ENDL;
+ }
+ }
+
+ LLModel* high_lod_model = instance.mLOD[LLModel::LOD_HIGH];
+ if (!high_lod_model)
+ {
+ setLoadState( LLModelLoader::ERROR_MATERIALS );
+ mFMP->childDisable( "calculate_btn" );
+ }
+ else
+ {
+ for (U32 i = 0; i < LLModel::NUM_LODS-1; i++)
+ {
+ int refFaceCnt = 0;
+ int modelFaceCnt = 0;
+ llassert(instance.mLOD[i]);
+ if (instance.mLOD[i] && !instance.mLOD[i]->matchMaterialOrder(high_lod_model, refFaceCnt, modelFaceCnt ) )
+ {
+ setLoadState( LLModelLoader::ERROR_MATERIALS );
+ mFMP->childDisable( "calculate_btn" );
}
}
}
@@ -3430,6 +1575,34 @@ void LLModelPreview::rebuildUploadData()
}
}
+ for (U32 lod = 0; lod < LLModel::NUM_LODS-1; lod++)
+ {
+ // Search for models that are not included into upload data
+ // If we found any, that means something we loaded is not a sub-model.
+ for (U32 model_ind = 0; model_ind < mModel[lod].size(); ++model_ind)
+ {
+ bool found_model = false;
+ for (LLMeshUploadThread::instance_list::iterator iter = mUploadData.begin(); iter != mUploadData.end(); ++iter)
+ {
+ LLModelInstance& instance = *iter;
+ if (instance.mLOD[lod] == mModel[lod][model_ind])
+ {
+ found_model = true;
+ break;
+ }
+ }
+ if (!found_model && mModel[lod][model_ind] && !mModel[lod][model_ind]->mSubmodelID)
+ {
+ if (importerDebug)
+ {
+ LL_INFOS() << "Model " << mModel[lod][model_ind]->mLabel << " was not used - mismatching lod models." << LL_ENDL;
+ }
+ setLoadState( LLModelLoader::ERROR_MATERIALS );
+ mFMP->childDisable( "calculate_btn" );
+ }
+ }
+ }
+
F32 max_import_scale = (DEFAULT_MAX_PRIM_SCALE-0.1f)/max_scale;
F32 max_axis = llmax(mPreviewScale.mV[0], mPreviewScale.mV[1]);
@@ -3496,7 +1669,6 @@ void LLModelPreview::saveUploadData(const std::string& filename, bool save_skinw
meshes.insert(instance.mModel);
std::stringstream str;
-
LLModel::Decomposition& decomp =
instance.mLOD[LLModel::LOD_PHYSICS].notNull() ?
instance.mLOD[LLModel::LOD_PHYSICS]->mPhysics :
@@ -3509,8 +1681,8 @@ void LLModelPreview::saveUploadData(const std::string& filename, bool save_skinw
instance.mLOD[LLModel::LOD_LOW],
instance.mLOD[LLModel::LOD_IMPOSTOR],
decomp,
- save_skinweights, save_joint_positions, FALSE, TRUE);
-
+ save_skinweights, save_joint_positions,
+ FALSE, TRUE, instance.mModel->mSubmodelID);
data["mesh"][instance.mModel->mLocalID] = str.str();
}
@@ -3578,13 +1750,28 @@ void LLModelPreview::loadModel(std::string filename, S32 lod, bool force_disable
clearGLODGroup();
}
- mModelLoader = new LLModelLoader(filename, lod, this, mJointTransformMap, mJointsFromNode );
+ mModelLoader = new LLDAELoader(
+ filename,
+ lod,
+ &LLModelPreview::loadedCallback,
+ &LLModelPreview::lookupJointByName,
+ &LLModelPreview::loadTextures,
+ &LLModelPreview::stateChangedCallback,
+ this,
+ mJointTransformMap,
+ mJointsFromNode,
+ gSavedSettings.getU32("ImporterModelLimit"));
if (force_disable_slm)
{
mModelLoader->mTrySLM = false;
}
-
+ else
+ {
+ //only try to load from slm if viewer is configured to do so and this is the
+ //initial model load (not an LoD or physics shape)
+ mModelLoader->mTrySLM = gSavedSettings.getBOOL("MeshImportUseSLM") && mUploadData.empty();
+ }
mModelLoader->start();
mFMP->childSetTextArg("status", "[STATUS]", mFMP->getString("status_reading_file"));
@@ -3615,6 +1802,7 @@ void LLModelPreview::setPhysicsFromLOD(S32 lod)
if (lod >= 0 && lod <= 3)
{
+ mPhysicsSearchLOD = lod;
mModel[LLModel::LOD_PHYSICS] = mModel[lod];
mScene[LLModel::LOD_PHYSICS] = mScene[lod];
mLODFile[LLModel::LOD_PHYSICS].clear();
@@ -3634,11 +1822,14 @@ void LLModelPreview::clearIncompatible(S32 lod)
return;
}
+ // at this point we don't care about sub-models,
+ // different amount of sub-models means face count mismatch, not incompatibility
+ U32 lod_size = countRootModels(mModel[lod]);
for (U32 i = 0; i <= LLModel::LOD_HIGH; i++)
{ //clear out any entries that aren't compatible with this model
if (i != lod)
{
- if (mModel[i].size() != mModel[lod].size())
+ if (countRootModels(mModel[i]) != lod_size)
{
mModel[i].clear();
mScene[i].clear();
@@ -3673,7 +1864,7 @@ void LLModelPreview::clearGLODGroup()
}
}
-void LLModelPreview::loadModelCallback(S32 lod)
+void LLModelPreview::loadModelCallback(S32 loaded_lod)
{
assert_main_thread();
@@ -3686,12 +1877,18 @@ void LLModelPreview::loadModelCallback(S32 lod)
if(getLoadState() >= LLModelLoader::ERROR_PARSING)
{
mLoading = false ;
+ mModelLoader = NULL;
return ;
}
+ // Copy determinations about rig so UI will reflect them
+ //
+ setRigValidForJointPositionUpload(mModelLoader->isRigValidForJointPositionUpload());
+ setLegacyRigValid(mModelLoader->isLegacyRigValid());
+
mModelLoader->loadTextures() ;
- if (lod == -1)
+ if (loaded_lod == -1)
{ //populate all LoDs from model loader scene
mBaseModel.clear();
mBaseScene.clear();
@@ -3723,6 +1920,11 @@ void LLModelPreview::loadModelCallback(S32 lod)
//override displayed model with current LoD
list_iter->mModel = list_iter->mLOD[lod];
+ if (!list_iter->mModel)
+ {
+ continue;
+ }
+
//add current model to current LoD's model list (LLModel::mLocalID makes a good vector index)
S32 idx = list_iter->mModel->mLocalID;
@@ -3731,7 +1933,7 @@ void LLModelPreview::loadModelCallback(S32 lod)
mModel[lod].resize(idx+1);
}
- mModel[lod][idx] = list_iter->mModel;
+ mModel[lod][idx] = list_iter->mModel;
if (!list_iter->mModel->mSkinWeights.empty())
{
skin_weights = true;
@@ -3774,31 +1976,108 @@ void LLModelPreview::loadModelCallback(S32 lod)
}
else
{ //only replace given LoD
- mModel[lod] = mModelLoader->mModelList;
- mScene[lod] = mModelLoader->mScene;
- mVertexBuffer[lod].clear();
+ mModel[loaded_lod] = mModelLoader->mModelList;
+ mScene[loaded_lod] = mModelLoader->mScene;
+ mVertexBuffer[loaded_lod].clear();
- setPreviewLOD(lod);
+ setPreviewLOD(loaded_lod);
- if (lod == LLModel::LOD_HIGH)
+ if (loaded_lod == LLModel::LOD_HIGH)
{ //save a copy of the highest LOD for automatic LOD manipulation
if (mBaseModel.empty())
{ //first time we've loaded a model, auto-gen LoD
mGenLOD = true;
}
- mBaseModel = mModel[lod];
+ mBaseModel = mModel[loaded_lod];
clearGLODGroup();
- mBaseScene = mScene[lod];
+ mBaseScene = mScene[loaded_lod];
mVertexBuffer[5].clear();
}
+ else
+ {
+ BOOL importerDebug = gSavedSettings.getBOOL("ImporterDebug");
+ BOOL legacyMatching = gSavedSettings.getBOOL("ImporterLegacyMatching");
+ if (!legacyMatching)
+ {
+ if (!mBaseModel.empty())
+ {
+ BOOL name_based = FALSE;
+ BOOL has_submodels = FALSE;
+ for (U32 idx = 0; idx < mBaseModel.size(); ++idx)
+ {
+ if (mBaseModel[idx]->mSubmodelID)
+ { // don't do index-based renaming when the base model has submodels
+ has_submodels = TRUE;
+ if (importerDebug)
+ {
+ LL_INFOS() << "High LOD has submodels" << LL_ENDL;
+ }
+ break;
+ }
+ }
- clearIncompatible(lod);
+ for (U32 idx = 0; idx < mModel[loaded_lod].size(); ++idx)
+ {
+ std::string loaded_name = stripSuffix(mModel[loaded_lod][idx]->mLabel);
+
+ LLModel* found_model = NULL;
+ LLMatrix4 transform;
+ FindModel(mBaseScene, loaded_name, found_model, transform);
+ if (found_model)
+ { // don't rename correctly named models (even if they are placed in a wrong order)
+ name_based = TRUE;
+ }
+
+ if (mModel[loaded_lod][idx]->mSubmodelID)
+ { // don't rename the models when loaded LOD model has submodels
+ has_submodels = TRUE;
+ }
+ }
+
+ if (importerDebug)
+ {
+ LL_INFOS() << "Loaded LOD " << loaded_lod << ": correct names" << (name_based ? "" : "NOT ") << "found; submodels " << (has_submodels ? "" : "NOT ") << "found" << LL_ENDL;
+ }
+
+ if (!name_based && !has_submodels)
+ { // replace the name of the model loaded for any non-HIGH LOD to match the others (MAINT-5601)
+ // this actually works like "ImporterLegacyMatching" for this particular LOD
+ for (U32 idx = 0; idx < mModel[loaded_lod].size() && idx < mBaseModel.size(); ++idx)
+ {
+ std::string name = mBaseModel[idx]->mLabel;
+ std::string loaded_name = stripSuffix(mModel[loaded_lod][idx]->mLabel);
+
+ if (loaded_name != name)
+ {
+ switch (loaded_lod)
+ {
+ case LLModel::LOD_IMPOSTOR: name += "_LOD0"; break;
+ case LLModel::LOD_LOW: name += "_LOD1"; break;
+ case LLModel::LOD_MEDIUM: name += "_LOD2"; break;
+ case LLModel::LOD_PHYSICS: name += "_PHYS"; break;
+ case LLModel::LOD_HIGH: break;
+ }
+
+ if (importerDebug)
+ {
+ LL_WARNS() << "Loded model name " << mModel[loaded_lod][idx]->mLabel << " for LOD " << loaded_lod << " doesn't match the base model. Renaming to " << name << LL_ENDL;
+ }
+
+ mModel[loaded_lod][idx]->mLabel = name;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ clearIncompatible(loaded_lod);
mDirty = true;
- if (lod == LLModel::LOD_HIGH)
+ if (loaded_lod == LLModel::LOD_HIGH)
{
resetPreviewTarget();
}
@@ -3817,6 +2096,8 @@ void LLModelPreview::loadModelCallback(S32 lod)
refresh();
mModelLoadedSignal();
+
+ mModelLoader = NULL;
}
void LLModelPreview::resetPreviewTarget()
@@ -4165,6 +2446,20 @@ void LLModelPreview::genLODs(S32 which_lod, U32 decimation, bool enforce_tri_lim
volume_params.setType(LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE);
mModel[lod][mdl_idx] = new LLModel(volume_params, 0.f);
+ std::string name = base->mLabel;
+
+ switch (lod)
+ {
+ case LLModel::LOD_IMPOSTOR: name += "_LOD0"; break;
+ case LLModel::LOD_LOW: name += "_LOD1"; break;
+ case LLModel::LOD_MEDIUM: name += "_LOD2"; break;
+ case LLModel::LOD_PHYSICS: name += "_PHYS"; break;
+ case LLModel::LOD_HIGH: break;
+ }
+
+ mModel[lod][mdl_idx]->mLabel = name;
+ mModel[lod][mdl_idx]->mSubmodelID = base->mSubmodelID;
+
GLint* sizes = new GLint[patch_count*2];
glodGetObjectParameteriv(mObject[base], GLOD_PATCH_SIZES, sizes);
stop_gloderror();
@@ -4277,17 +2572,6 @@ void LLModelPreview::genLODs(S32 which_lod, U32 decimation, bool enforce_tri_lim
{
shader->bind();
}
-
- /*if (which_lod == -1 && mScene[LLModel::LOD_PHYSICS].empty())
- { //build physics scene
- mScene[LLModel::LOD_PHYSICS] = mScene[LLModel::LOD_LOW];
- mModel[LLModel::LOD_PHYSICS] = mModel[LLModel::LOD_LOW];
-
- for (U32 i = 1; i < mModel[LLModel::LOD_PHYSICS].size(); ++i)
- {
- mPhysicsQ.push(mModel[LLModel::LOD_PHYSICS][i]);
- }
- }*/
}
void LLModelPreview::updateStatusMessages()
@@ -4304,43 +2588,89 @@ void LLModelPreview::updateStatusMessages()
S32 total_verts[LLModel::NUM_LODS];
S32 total_submeshes[LLModel::NUM_LODS];
- for (S32 lod = 0; lod < LLModel::NUM_LODS; ++lod)
+ for (U32 i = 0; i < LLModel::NUM_LODS-1; i++)
+ {
+ total_tris[i] = 0;
+ total_verts[i] = 0;
+ total_submeshes[i] = 0;
+ }
+
+ for (LLMeshUploadThread::instance_list::iterator iter = mUploadData.begin(); iter != mUploadData.end(); ++iter)
{
- //initialize total for this lod to 0
- total_tris[lod] = total_verts[lod] = total_submeshes[lod] = 0;
+ LLModelInstance& instance = *iter;
- for (LLModelLoader::scene::iterator iter = mScene[lod].begin(), endIter = mScene[lod].end(); iter != endIter; ++iter)
+ LLModel* model_high_lod = instance.mLOD[LLModel::LOD_HIGH];
+ if (!model_high_lod)
{
- for (LLModelLoader::model_instance_list::iterator instance = iter->second.begin(), end_instance = iter->second.end(); instance != end_instance; ++instance)
- {
- LLModel* model = instance->mModel;
- if (model)
- {
- //for each model in the lod
- S32 cur_tris = 0;
- S32 cur_verts = 0;
- S32 cur_submeshes = model->getNumVolumeFaces();
+ setLoadState( LLModelLoader::ERROR_MATERIALS );
+ mFMP->childDisable( "calculate_btn" );
+ continue;
+ }
- for (S32 j = 0; j < cur_submeshes; ++j)
- { //for each submesh (face), add triangles and vertices to current total
- const LLVolumeFace& face = model->getVolumeFace(j);
- cur_tris += face.mNumIndices/3;
- cur_verts += face.mNumVertices;
- }
+ for (U32 i = 0; i < LLModel::NUM_LODS-1; i++)
+ {
+ LLModel* lod_model = instance.mLOD[i];
+ if (!lod_model)
+ {
+ setLoadState( LLModelLoader::ERROR_MATERIALS );
+ mFMP->childDisable( "calculate_btn" );
+ }
+
+ int refFaceCnt = 0;
+ int modelFaceCnt = 0;
+
+ if (!lod_model->matchMaterialOrder(model_high_lod, refFaceCnt, modelFaceCnt ) )
+ {
+ setLoadState( LLModelLoader::ERROR_MATERIALS );
+ mFMP->childDisable( "calculate_btn" );
+ }
- //add this model to the lod total
- total_tris[lod] += cur_tris;
- total_verts[lod] += cur_verts;
- total_submeshes[lod] += cur_submeshes;
+ if (lod_model)
+ {
+ //for each model in the lod
+ S32 cur_tris = 0;
+ S32 cur_verts = 0;
+ S32 cur_submeshes = lod_model->getNumVolumeFaces();
- //store this model's counts to asset data
- tris[lod].push_back(cur_tris);
- verts[lod].push_back(cur_verts);
- submeshes[lod].push_back(cur_submeshes);
+ for (S32 j = 0; j < cur_submeshes; ++j)
+ { //for each submesh (face), add triangles and vertices to current total
+ const LLVolumeFace& face = lod_model->getVolumeFace(j);
+ cur_tris += face.mNumIndices/3;
+ cur_verts += face.mNumVertices;
}
+
+ std::string instance_name = instance.mLabel;
+
+ BOOL importerDebug = gSavedSettings.getBOOL("ImporterDebug");
+ if (importerDebug)
+ {
+ // Useful for debugging generalized complaints below about total submeshes which don't have enough
+ // context to address exactly what needs to be fixed to move towards compliance with the rules.
+ //
+ LL_INFOS() << "Instance " << lod_model->mLabel << " LOD " << i << " Verts: " << cur_verts << LL_ENDL;
+ LL_INFOS() << "Instance " << lod_model->mLabel << " LOD " << i << " Tris: " << cur_tris << LL_ENDL;
+ LL_INFOS() << "Instance " << lod_model->mLabel << " LOD " << i << " Faces: " << cur_submeshes << LL_ENDL;
+
+ LLModel::material_list::iterator mat_iter = lod_model->mMaterialList.begin();
+ while (mat_iter != lod_model->mMaterialList.end())
+ {
+ LL_INFOS() << "Instance " << lod_model->mLabel << " LOD " << i << " Material " << *(mat_iter) << LL_ENDL;
+ mat_iter++;
+ }
+ }
+
+ //add this model to the lod total
+ total_tris[i] += cur_tris;
+ total_verts[i] += cur_verts;
+ total_submeshes[i] += cur_submeshes;
+
+ //store this model's counts to asset data
+ tris[i].push_back(cur_tris);
+ verts[i].push_back(cur_verts);
+ submeshes[i].push_back(cur_submeshes);
}
}
- }
+ }
if (mMaxTriangleLimit == 0)
{
@@ -4354,37 +2684,48 @@ void LLModelPreview::updateStatusMessages()
const LLVector4a scale(0.5f);
for (U32 i = 0; i < mModel[lod].size() && !has_degenerate; ++i)
{ //for each model in the lod
- if (mModel[lod][i]->mPhysics.mHull.empty())
+ if (mModel[lod][i] && mModel[lod][i]->mPhysics.mHull.empty())
{ //no decomp exists
S32 cur_submeshes = mModel[lod][i]->getNumVolumeFaces();
for (S32 j = 0; j < cur_submeshes && !has_degenerate; ++j)
{ //for each submesh (face), add triangles and vertices to current total
- const LLVolumeFace& face = mModel[lod][i]->getVolumeFace(j);
- for (S32 k = 0; k < face.mNumIndices && !has_degenerate; )
+ LLVolumeFace& face = mModel[lod][i]->getVolumeFace(j);
+ for (S32 k = 0; (k < face.mNumIndices) && !has_degenerate; )
{
- LLVector4a v1; v1.setMul(face.mPositions[face.mIndices[k++]], scale);
- LLVector4a v2; v2.setMul(face.mPositions[face.mIndices[k++]], scale);
- LLVector4a v3; v3.setMul(face.mPositions[face.mIndices[k++]], scale);
+ U16 index_a = face.mIndices[k+0];
+ U16 index_b = face.mIndices[k+1];
+ U16 index_c = face.mIndices[k+2];
+
+ LLVector4a v1; v1.setMul(face.mPositions[index_a], scale);
+ LLVector4a v2; v2.setMul(face.mPositions[index_b], scale);
+ LLVector4a v3; v3.setMul(face.mPositions[index_c], scale);
if (ll_is_degenerate(v1,v2,v3))
{
has_degenerate = true;
}
+ else
+ {
+ k += 3;
+ }
}
}
}
}
}
-
+
mFMP->childSetTextArg("submeshes_info", "[SUBMESHES]", llformat("%d", total_submeshes[LLModel::LOD_HIGH]));
std::string mesh_status_na = mFMP->getString("mesh_status_na");
S32 upload_status[LLModel::LOD_HIGH+1];
- bool upload_ok = true;
+ mModelNoErrors = true;
- for (S32 lod = 0; lod <= LLModel::LOD_HIGH; ++lod)
+ const U32 lod_high = LLModel::LOD_HIGH;
+ U32 high_submodel_count = mModel[lod_high].size() - countRootModels(mModel[lod_high]);
+
+ for (S32 lod = 0; lod <= lod_high; ++lod)
{
upload_status[lod] = 0;
@@ -4397,7 +2738,7 @@ void LLModelPreview::updateStatusMessages()
}
else
{
- if (lod == LLModel::LOD_HIGH)
+ if (lod == lod_high)
{
upload_status[lod] = 2;
message = "mesh_status_missing_lod";
@@ -4418,8 +2759,6 @@ void LLModelPreview::updateStatusMessages()
mFMP->childSetValue(lod_vertices_name[lod], mesh_status_na);
}
- const U32 lod_high = LLModel::LOD_HIGH;
-
if (lod != lod_high)
{
if (total_submeshes[lod] && total_submeshes[lod] != total_submeshes[lod_high])
@@ -4427,6 +2766,13 @@ void LLModelPreview::updateStatusMessages()
message = "mesh_status_submesh_mismatch";
upload_status[lod] = 2;
}
+ else if (mModel[lod].size() - countRootModels(mModel[lod]) != high_submodel_count)
+ {//number of submodels is different, not all faces are matched correctly.
+ message = "mesh_status_submesh_mismatch";
+ upload_status[lod] = 2;
+ // Note: Submodels in instance were loaded from higher LOD and as result face count
+ // returns same value and total_submeshes[lod] is identical to high_lod one.
+ }
else if (!tris[lod].empty() && tris[lod].size() != tris[lod_high].size())
{ //number of meshes is different
message = "mesh_status_mesh_mismatch";
@@ -4447,7 +2793,7 @@ void LLModelPreview::updateStatusMessages()
{
//too many vertices in this lod
message = "mesh_status_too_many_vertices";
- upload_status[lod] = 2;
+ upload_status[lod] = 1;
}
}
}
@@ -4459,7 +2805,7 @@ void LLModelPreview::updateStatusMessages()
if (upload_status[lod] >= 2)
{
- upload_ok = false;
+ mModelNoErrors = false;
}
if (lod == mPreviewLOD)
@@ -4473,23 +2819,41 @@ void LLModelPreview::updateStatusMessages()
}
- //make sure no hulls have more than 256 points in them
- for (U32 i = 0; upload_ok && i < mModel[LLModel::LOD_PHYSICS].size(); ++i)
+ //warn if hulls have more than 256 points in them
+ BOOL physExceededVertexLimit = FALSE;
+ for (U32 i = 0; mModelNoErrors && i < mModel[LLModel::LOD_PHYSICS].size(); ++i)
{
LLModel* mdl = mModel[LLModel::LOD_PHYSICS][i];
- for (U32 j = 0; upload_ok && j < mdl->mPhysics.mHull.size(); ++j)
+ if (mdl)
{
- if (mdl->mPhysics.mHull[j].size() > 256)
+ for (U32 j = 0; j < mdl->mPhysics.mHull.size(); ++j)
{
- upload_ok = false;
+ if (mdl->mPhysics.mHull[j].size() > 256)
+ {
+ physExceededVertexLimit = TRUE;
+ LL_INFOS() << "Physical model " << mdl->mLabel << " exceeds vertex per hull limitations." << LL_ENDL;
+ break;
+ }
}
}
}
+ mFMP->childSetVisible("physics_status_message_text", physExceededVertexLimit);
+ LLIconCtrl* physStatusIcon = mFMP->getChild<LLIconCtrl>("physics_status_message_icon");
+ physStatusIcon->setVisible(physExceededVertexLimit);
+ if (physExceededVertexLimit)
+ {
+ mFMP->childSetValue("physics_status_message_text", mFMP->getString("phys_status_vertex_limit_exceeded"));
+ LLUIImagePtr img = LLUI::getUIImage("ModelImport_Status_Warning");
+ physStatusIcon->setImage(img);
+ }
- bool errorStateFromLoader = getLoadState() >= LLModelLoader::ERROR_PARSING ? true : false;
+ if (getLoadState() >= LLModelLoader::ERROR_PARSING)
+ {
+ mModelNoErrors = false;
+ LL_INFOS() << "Loader returned errors, model can't be uploaded" << LL_ENDL;
+ }
- bool skinAndRigOk = true;
bool uploadingSkin = mFMP->childGetValue("upload_skin").asBoolean();
bool uploadingJointPositions = mFMP->childGetValue("upload_joints").asBoolean();
@@ -4497,19 +2861,23 @@ void LLModelPreview::updateStatusMessages()
{
if ( uploadingJointPositions && !isRigValidForJointPositionUpload() )
{
- skinAndRigOk = false;
- }
+ mModelNoErrors = false;
+ LL_INFOS() << "Invalid rig, there might be issues with uploading Joint positions" << LL_ENDL;
+ }
}
-
- if(upload_ok && mModelLoader)
+
+ if(mModelNoErrors && mModelLoader)
{
if(!mModelLoader->areTexturesReady() && mFMP->childGetValue("upload_textures").asBoolean())
{
- upload_ok = false ;
+ // Some textures are still loading, prevent upload until they are done
+ mModelNoErrors = false;
}
}
- if (!upload_ok || errorStateFromLoader || !skinAndRigOk || has_degenerate)
+ // Todo: investigate use of has_degenerate and include into mModelNoErrors upload blocking mechanics
+ // current use of has_degenerate won't block upload permanently - later checks will restore the button
+ if (!mModelNoErrors || has_degenerate)
{
mFMP->childDisable("ok_btn");
}
@@ -4851,7 +3219,8 @@ void LLModelPreview::genBuffers(S32 lod, bool include_skin_weights)
LLModel* base_mdl = *base_iter;
base_iter++;
- for (S32 i = 0, e = mdl->getNumVolumeFaces(); i < e; ++i)
+ S32 num_faces = mdl->getNumVolumeFaces();
+ for (S32 i = 0; i < num_faces; ++i)
{
const LLVolumeFace &vf = mdl->getVolumeFace(i);
U32 num_vertices = vf.mNumVertices;
@@ -4946,23 +3315,23 @@ void LLModelPreview::genBuffers(S32 lod, bool include_skin_weights)
void LLModelPreview::update()
{
- if (mDirty)
+ if (mGenLOD)
{
- mDirty = false;
- mResourceCost = calcResourceCost();
+ mGenLOD = false;
+ genLODs();
refresh();
updateStatusMessages();
}
- if (mGenLOD)
+ if (mDirty)
{
- mGenLOD = false;
- genLODs();
+ mDirty = false;
+ mResourceCost = calcResourceCost();
refresh();
updateStatusMessages();
}
-
}
+
//-----------------------------------------------------------------------------
// getTranslationForJointOffset()
//-----------------------------------------------------------------------------
@@ -4996,10 +3365,79 @@ void LLModelPreview::createPreviewAvatar( void )
}
else
{
- LL_INFOS()<<"Failed to create preview avatar for upload model window"<<LL_ENDL;
+ LL_INFOS() << "Failed to create preview avatar for upload model window" << LL_ENDL;
}
}
+//static
+U32 LLModelPreview::countRootModels(LLModelLoader::model_list models)
+{
+ U32 root_models = 0;
+ model_list::iterator model_iter = models.begin();
+ while (model_iter != models.end())
+ {
+ LLModel* mdl = *model_iter;
+ if (mdl && mdl->mSubmodelID == 0)
+ {
+ root_models++;
+ }
+ model_iter++;
+ }
+ return root_models;
+}
+
+void LLModelPreview::loadedCallback(
+ LLModelLoader::scene& scene,
+ LLModelLoader::model_list& model_list,
+ S32 lod,
+ void* opaque)
+{
+ LLModelPreview* pPreview = static_cast< LLModelPreview* >(opaque);
+ if (pPreview && !LLModelPreview::sIgnoreLoadedCallback)
+ {
+ pPreview->loadModelCallback(lod);
+ }
+}
+
+void LLModelPreview::stateChangedCallback(U32 state,void* opaque)
+{
+ LLModelPreview* pPreview = static_cast< LLModelPreview* >(opaque);
+ if (pPreview)
+ {
+ pPreview->setLoadState(state);
+ }
+}
+
+LLJoint* LLModelPreview::lookupJointByName(const std::string& str, void* opaque)
+{
+ LLModelPreview* pPreview = static_cast< LLModelPreview* >(opaque);
+ if (pPreview)
+ {
+ return pPreview->getPreviewAvatar()->getJoint(str);
+ }
+ return NULL;
+}
+
+U32 LLModelPreview::loadTextures(LLImportMaterial& material,void* opaque)
+{
+ (void)opaque;
+
+ if (material.mDiffuseMapFilename.size())
+ {
+ material.mOpaqueData = new LLPointer< LLViewerFetchedTexture >;
+ LLPointer< LLViewerFetchedTexture >& tex = (*reinterpret_cast< LLPointer< LLViewerFetchedTexture > * >(material.mOpaqueData));
+
+ tex = LLViewerTextureManager::getFetchedTextureFromUrl("file://" + material.mDiffuseMapFilename, FTT_LOCAL_FILE, TRUE, LLGLTexture::BOOST_PREVIEW);
+ tex->setLoadedCallback(LLModelPreview::textureLoadedCallback, 0, TRUE, FALSE, opaque, NULL, FALSE);
+ tex->forceToSaveRawImage(0, F32_MAX);
+ material.setDiffuseMap(tex->getID()); // record tex ID
+ return 1;
+ }
+
+ material.mOpaqueData = NULL;
+ return 0;
+}
+
void LLModelPreview::addEmptyFace( LLModel* pTarget )
{
U32 type_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_TEXCOORD0;
@@ -5253,23 +3691,9 @@ BOOL LLModelPreview::render()
if (regen)
{
genBuffers(mPreviewLOD, skin_weight);
- }
-
- //make sure material lists all match
- for (U32 i = 0; i < LLModel::NUM_LODS-1; i++)
- {
- if (mBaseModel.size() == mModel[i].size())
{
- for (U32 j = 0; j < mBaseModel.size(); ++j)
- {
- int refFaceCnt = 0;
- int modelFaceCnt = 0;
-
- if ( !mModel[i][j]->matchMaterialOrder(mBaseModel[j], refFaceCnt, modelFaceCnt ) )
- {
- mFMP->childDisable( "calculate_btn" );
- }
- }
+ LL_INFOS() << "Vertex Buffer[" << mPreviewLOD << "]" << " is EMPTY!!!" << LL_ENDL;
+ regen = TRUE;
}
}
@@ -5281,62 +3705,63 @@ BOOL LLModelPreview::render()
LLModel* model = instance.mLOD[mPreviewLOD];
- if (!model)
- {
- continue;
- }
+ if (!model)
+ {
+ continue;
+ }
- gGL.pushMatrix();
- LLMatrix4 mat = instance.mTransform;
+ gGL.pushMatrix();
+ LLMatrix4 mat = instance.mTransform;
- gGL.multMatrix((GLfloat*) mat.mMatrix);
+ gGL.multMatrix((GLfloat*) mat.mMatrix);
- for (U32 i = 0, e = mVertexBuffer[mPreviewLOD][model].size(); i < e; ++i)
- {
- LLVertexBuffer* buffer = mVertexBuffer[mPreviewLOD][model][i];
-
- buffer->setBuffer(type_mask & buffer->getTypeMask());
- if (textures)
+ U32 num_models = mVertexBuffer[mPreviewLOD][model].size();
+ for (U32 i = 0; i < num_models; ++i)
{
- int materialCnt = instance.mModel->mMaterialList.size();
- if ( i < materialCnt )
+ LLVertexBuffer* buffer = mVertexBuffer[mPreviewLOD][model][i];
+
+ buffer->setBuffer(type_mask & buffer->getTypeMask());
+
+ if (textures)
{
- const std::string& binding = instance.mModel->mMaterialList[i];
- const LLImportMaterial& material = instance.mMaterial[binding];
+ int materialCnt = instance.mModel->mMaterialList.size();
+ if ( i < materialCnt )
+ {
+ const std::string& binding = instance.mModel->mMaterialList[i];
+ const LLImportMaterial& material = instance.mMaterial[binding];
- gGL.diffuseColor4fv(material.mDiffuseColor.mV);
+ gGL.diffuseColor4fv(material.mDiffuseColor.mV);
- if (material.mDiffuseMap.notNull())
- {
- if (material.mDiffuseMap->getDiscardLevel() > -1)
+ // Find the tex for this material, bind it, and add it to our set
+ //
+ LLViewerFetchedTexture* tex = bindMaterialDiffuseTexture(material);
+ if (tex)
{
- gGL.getTexUnit(0)->bind(material.mDiffuseMap, true);
- mTextureSet.insert(material.mDiffuseMap.get());
+ mTextureSet.insert(tex);
}
}
}
- }
- else
- {
- gGL.diffuseColor4f(1,1,1,1);
- }
-
- buffer->drawRange(LLRender::TRIANGLES, 0, buffer->getNumVerts()-1, buffer->getNumIndices(), 0);
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
- gGL.diffuseColor3f(0.4f, 0.4f, 0.4f);
+ else
+ {
+ gGL.diffuseColor4f(1,1,1,1);
+ }
- if (edges)
- {
- glLineWidth(3.f);
- glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
buffer->drawRange(LLRender::TRIANGLES, 0, buffer->getNumVerts()-1, buffer->getNumIndices(), 0);
- glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
- glLineWidth(1.f);
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+ gGL.diffuseColor3f(0.4f, 0.4f, 0.4f);
+
+ if (edges)
+ {
+ glLineWidth(3.f);
+ glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+ buffer->drawRange(LLRender::TRIANGLES, 0, buffer->getNumVerts()-1, buffer->getNumIndices(), 0);
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+ glLineWidth(1.f);
+ }
}
+ gGL.popMatrix();
}
- gGL.popMatrix();
- }
if (physics)
{
@@ -5364,97 +3789,99 @@ BOOL LLModelPreview::render()
LLModel* model = instance.mLOD[LLModel::LOD_PHYSICS];
- if (!model)
- {
- continue;
- }
+ if (!model)
+ {
+ continue;
+ }
- gGL.pushMatrix();
- LLMatrix4 mat = instance.mTransform;
+ gGL.pushMatrix();
+ LLMatrix4 mat = instance.mTransform;
gGL.multMatrix((GLfloat*) mat.mMatrix);
- bool render_mesh = true;
+ bool render_mesh = true;
- LLPhysicsDecomp* decomp = gMeshRepo.mDecompThread;
- if (decomp)
- {
- LLMutexLock(decomp->mMutex);
+ LLPhysicsDecomp* decomp = gMeshRepo.mDecompThread;
+ if (decomp)
+ {
+ LLMutexLock(decomp->mMutex);
- LLModel::Decomposition& physics = model->mPhysics;
+ LLModel::Decomposition& physics = model->mPhysics;
- if (!physics.mHull.empty())
- {
- render_mesh = false;
+ if (!physics.mHull.empty())
+ {
+ render_mesh = false;
- if (physics.mMesh.empty())
- { //build vertex buffer for physics mesh
- gMeshRepo.buildPhysicsMesh(physics);
- }
+ if (physics.mMesh.empty())
+ { //build vertex buffer for physics mesh
+ gMeshRepo.buildPhysicsMesh(physics);
+ }
- if (!physics.mMesh.empty())
- { //render hull instead of mesh
- for (U32 i = 0; i < physics.mMesh.size(); ++i)
- {
- if (explode > 0.f)
+ if (!physics.mMesh.empty())
+ { //render hull instead of mesh
+ for (U32 i = 0; i < physics.mMesh.size(); ++i)
{
- gGL.pushMatrix();
+ if (explode > 0.f)
+ {
+ gGL.pushMatrix();
- LLVector3 offset = model->mHullCenter[i]-model->mCenterOfHullCenters;
- offset *= explode;
+ LLVector3 offset = model->mHullCenter[i]-model->mCenterOfHullCenters;
+ offset *= explode;
- gGL.translatef(offset.mV[0], offset.mV[1], offset.mV[2]);
- }
+ gGL.translatef(offset.mV[0], offset.mV[1], offset.mV[2]);
+ }
- static std::vector<LLColor4U> hull_colors;
+ static std::vector<LLColor4U> hull_colors;
- if (i+1 >= hull_colors.size())
- {
- hull_colors.push_back(LLColor4U(rand()%128+127, rand()%128+127, rand()%128+127, 128));
- }
+ if (i+1 >= hull_colors.size())
+ {
+ hull_colors.push_back(LLColor4U(rand()%128+127, rand()%128+127, rand()%128+127, 128));
+ }
- gGL.diffuseColor4ubv(hull_colors[i].mV);
- LLVertexBuffer::drawArrays(LLRender::TRIANGLES, physics.mMesh[i].mPositions, physics.mMesh[i].mNormals);
+ gGL.diffuseColor4ubv(hull_colors[i].mV);
+ LLVertexBuffer::drawArrays(LLRender::TRIANGLES, physics.mMesh[i].mPositions, physics.mMesh[i].mNormals);
- if (explode > 0.f)
- {
- gGL.popMatrix();
+ if (explode > 0.f)
+ {
+ gGL.popMatrix();
+ }
}
}
}
}
- }
-
- if (render_mesh)
- {
- if (mVertexBuffer[LLModel::LOD_PHYSICS].empty())
- {
- genBuffers(LLModel::LOD_PHYSICS, false);
- }
- for (U32 i = 0; i < mVertexBuffer[LLModel::LOD_PHYSICS][model].size(); ++i)
+
+ if (render_mesh)
{
- LLVertexBuffer* buffer = mVertexBuffer[LLModel::LOD_PHYSICS][model][i];
+ if (mVertexBuffer[LLModel::LOD_PHYSICS].empty())
+ {
+ genBuffers(LLModel::LOD_PHYSICS, false);
+ }
+
+ U32 num_models = mVertexBuffer[LLModel::LOD_PHYSICS][model].size();
+ for (U32 i = 0; i < num_models; ++i)
+ {
+ LLVertexBuffer* buffer = mVertexBuffer[LLModel::LOD_PHYSICS][model][i];
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
- gGL.diffuseColor4f(0.4f, 0.4f, 0.0f, 0.4f);
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+ gGL.diffuseColor4f(0.4f, 0.4f, 0.0f, 0.4f);
- buffer->setBuffer(type_mask & buffer->getTypeMask());
- buffer->drawRange(LLRender::TRIANGLES, 0, buffer->getNumVerts()-1, buffer->getNumIndices(), 0);
+ buffer->setBuffer(type_mask & buffer->getTypeMask());
+ buffer->drawRange(LLRender::TRIANGLES, 0, buffer->getNumVerts()-1, buffer->getNumIndices(), 0);
- gGL.diffuseColor3f(1.f, 1.f, 0.f);
+ gGL.diffuseColor3f(1.f, 1.f, 0.f);
- glLineWidth(2.f);
- glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
- buffer->drawRange(LLRender::TRIANGLES, 0, buffer->getNumVerts()-1, buffer->getNumIndices(), 0);
+ glLineWidth(2.f);
+ glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+ buffer->drawRange(LLRender::TRIANGLES, 0, buffer->getNumVerts()-1, buffer->getNumIndices(), 0);
- glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
- glLineWidth(1.f);
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+ glLineWidth(1.f);
+ }
}
- }
- gGL.popMatrix();
- }
+ gGL.popMatrix();
+ }
glLineWidth(3.f);
glPointSize(8.f);
@@ -5635,20 +4062,20 @@ BOOL LLModelPreview::render()
position[j] = v;
}
- llassert(model->mMaterialList.size() > i);
+ llassert(model->mMaterialList.size() > i);
const std::string& binding = instance.mModel->mMaterialList[i];
const LLImportMaterial& material = instance.mMaterial[binding];
buffer->setBuffer(type_mask & buffer->getTypeMask());
gGL.diffuseColor4fv(material.mDiffuseColor.mV);
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
- if (material.mDiffuseMap.notNull())
+
+ // Find the tex for this material, bind it, and add it to our set
+ //
+ LLViewerFetchedTexture* tex = bindMaterialDiffuseTexture(material);
+ if (tex)
{
- if (material.mDiffuseMap->getDiscardLevel() > -1)
- {
- gGL.getTexUnit(0)->bind(material.mDiffuseMap, true);
- mTextureSet.insert(material.mDiffuseMap.get());
- }
+ mTextureSet.insert(tex);
}
buffer->draw(LLRender::TRIANGLES, buffer->getNumIndices(), 0);
@@ -5763,14 +4190,14 @@ void LLFloaterModelPreview::onReset(void* user_data)
LLFloaterModelPreview* fmp = (LLFloaterModelPreview*) user_data;
fmp->childDisable("reset_btn");
LLModelPreview* mp = fmp->mModelPreview;
- std::string filename = mp->mLODFile[3];
+ std::string filename = mp->mLODFile[LLModel::LOD_HIGH];
fmp->resetDisplayOptions();
//reset model preview
fmp->initModelPreview();
mp = fmp->mModelPreview;
- mp->loadModel(filename,3,true);
+ mp->loadModel(filename,LLModel::LOD_HIGH,true);
}
//static
@@ -5864,7 +4291,7 @@ void LLFloaterModelPreview::toggleCalculateButton(bool visible)
}
mUploadBtn->setVisible(!visible);
- mUploadBtn->setEnabled(mHasUploadPerm && !mUploadModelUrl.empty());
+ mUploadBtn->setEnabled(isModelUploadAllowed());
if (visible)
{
@@ -5930,7 +4357,7 @@ void LLFloaterModelPreview::handleModelPhysicsFeeReceived()
childSetTextArg("price_breakdown", "[MODEL]", llformat("%d", result["upload_price_breakdown"]["model"].asInteger()));
childSetVisible("upload_fee", true);
childSetVisible("price_breakdown", true);
- mUploadBtn->setEnabled(mHasUploadPerm && !mUploadModelUrl.empty());
+ mUploadBtn->setEnabled(isModelUploadAllowed());
}
void LLFloaterModelPreview::setModelPhysicsFeeErrorStatus(S32 status, const std::string& reason)
@@ -5954,6 +4381,16 @@ void LLFloaterModelPreview::onModelUploadFailure()
mUploadBtn->setEnabled(true);
}
+bool LLFloaterModelPreview::isModelUploadAllowed()
+{
+ bool allow_upload = mHasUploadPerm && !mUploadModelUrl.empty();
+ if (mModelPreview)
+ {
+ allow_upload &= mModelPreview->mModelNoErrors;
+ }
+ return allow_upload;
+}
+
S32 LLFloaterModelPreview::DecompRequest::statusCallback(const char* status, S32 p1, S32 p2)
{
if (mContinue)
@@ -6012,8 +4449,8 @@ void LLFloaterModelPreview::onPermissionsReceived(const LLSD& result)
LL_WARNS() << "Upload permission set to true but uploadModelUrl is empty!" << LL_ENDL;
}
- //mUploadBtn->setEnabled(mHasUploadPerm);
- mUploadBtn->setEnabled(mHasUploadPerm && !mUploadModelUrl.empty());
+ // isModelUploadAllowed() includes mHasUploadPerm
+ mUploadBtn->setEnabled(isModelUploadAllowed());
getChild<LLTextBox>("warning_title")->setVisible(!mHasUploadPerm);
getChild<LLTextBox>("warning_message")->setVisible(!mHasUploadPerm);
}
diff --git a/indra/newview/llfloatermodelpreview.h b/indra/newview/llfloatermodelpreview.h
index 618748bd4e..7a518c798b 100755
--- a/indra/newview/llfloatermodelpreview.h
+++ b/indra/newview/llfloatermodelpreview.h
@@ -37,6 +37,8 @@
#include "llviewermenufile.h"
#include "llfloatermodeluploadbase.h"
+#include "lldaeloader.h"
+
class LLComboBox;
class LLJoint;
class LLViewerJointMesh;
@@ -45,103 +47,18 @@ class LLTextBox;
class LLVertexBuffer;
class LLModelPreview;
class LLFloaterModelPreview;
+class DAE;
class daeElement;
class domProfile_COMMON;
class domInstance_geometry;
class domNode;
class domTranslate;
class domController;
+class domSkin;
+class domMesh;
class LLMenuButton;
class LLToggleableMenu;
-typedef std::map<std::string, LLMatrix4> JointTransformMap;
-typedef std::map<std::string, LLMatrix4>:: iterator JointTransformMapIt;
-
-const S32 NUM_LOD = 4;
-
-class LLModelLoader : public LLThread
-{
-public:
- typedef enum
- {
- STARTING = 0,
- READING_FILE,
- CREATING_FACES,
- GENERATING_VERTEX_BUFFERS,
- GENERATING_LOD,
- DONE,
- ERROR_PARSING, //basically loading failed
- ERROR_MATERIALS,
- } eLoadState;
-
- U32 mState;
- std::string mFilename;
- S32 mLod;
- LLModelPreview* mPreview;
- LLMatrix4 mTransform;
- BOOL mFirstTransform;
- LLVector3 mExtents[2];
- bool mTrySLM;
-
- std::map<daeElement*, LLPointer<LLModel> > mModel;
-
- typedef std::vector<LLPointer<LLModel> > model_list;
- model_list mModelList;
-
- typedef std::vector<LLModelInstance> model_instance_list;
-
- typedef std::map<LLMatrix4, model_instance_list > scene;
-
- scene mScene;
-
- typedef std::queue<LLPointer<LLModel> > model_queue;
-
- //queue of models that need a physics rep
- model_queue mPhysicsQ;
-
- LLModelLoader( std::string filename, S32 lod, LLModelPreview* preview, JointTransformMap& jointMap,
- std::deque<std::string>& jointsFromNodes );
- ~LLModelLoader() ;
-
- virtual void run();
- bool doLoadModel();
- bool loadFromSLM(const std::string& filename);
- void loadModelCallback();
-
- void loadTextures() ; //called in the main thread.
- void processElement(daeElement* element, bool& badElement);
- std::map<std::string, LLImportMaterial> getMaterials(LLModel* model, domInstance_geometry* instance_geo);
- LLImportMaterial profileToMaterial(domProfile_COMMON* material);
- std::string getElementLabel(daeElement *element);
- LLColor4 getDaeColor(daeElement* element);
-
- daeElement* getChildFromElement( daeElement* pElement, std::string const & name );
-
- bool isNodeAJoint( domNode* pNode );
- void processJointNode( domNode* pNode, std::map<std::string,LLMatrix4>& jointTransforms );
- void extractTranslation( domTranslate* pTranslate, LLMatrix4& transform );
- void extractTranslationViaElement( daeElement* pTranslateElement, LLMatrix4& transform );
- void extractTranslationViaSID( daeElement* pElement, LLMatrix4& transform );
-
- void setLoadState(U32 state);
-
- void buildJointToNodeMappingFromScene( daeElement* pRoot );
- void processJointToNodeMapping( domNode* pNode );
- void processChildJoints( domNode* pParentNode );
-
- //map of avatar joints as named in COLLADA assets to internal joint names
- std::map<std::string, std::string> mJointMap;
- JointTransformMap& mJointList;
- std::deque<std::string>& mJointsFromNode;
-
- S32 mNumOfFetchingTextures ; //updated in the main thread
- bool areTexturesReady() { return !mNumOfFetchingTextures; } //called in the main thread.
-
-private:
- static std::list<LLModelLoader*> sActiveLoaderList;
- static bool isAlive(LLModelLoader* loader) ;
-};
-
class LLFloaterModelPreview : public LLFloaterModelUploadBase
{
public:
@@ -172,6 +89,7 @@ public:
BOOL handleScrollWheel(S32 x, S32 y, S32 clicks);
/*virtual*/ void onOpen(const LLSD& key);
+ /*virtual*/ void onClose(bool app_quitting);
static void onMouseCaptureLostModelPreview(LLMouseHandler*);
static void setUploadAmount(S32 amount) { sUploadAmount = amount; }
@@ -210,6 +128,8 @@ public:
/*virtual*/ void onModelUploadFailure();
+ bool isModelUploadAllowed();
+
protected:
friend class LLModelPreview;
friend class LLMeshFilePicker;
@@ -359,21 +279,14 @@ public:
void setHasPivot( bool val ) { mHasPivot = val; }
void setModelPivot( const LLVector3& pivot ) { mModelPivot = pivot; }
- //Determines the viability of an asset to be used as an avatar rig (w or w/o joint upload caps)
- void critiqueRigForUploadApplicability( const std::vector<std::string> &jointListFromAsset );
- void critiqueJointToNodeMappingFromScene( void );
//Is a rig valid so that it can be used as a criteria for allowing for uploading of joint positions
//Accessors for joint position upload friendly rigs
const bool isRigValidForJointPositionUpload( void ) const { return mRigValidJointUpload; }
void setRigValidForJointPositionUpload( bool rigValid ) { mRigValidJointUpload = rigValid; }
- bool isRigSuitableForJointPositionUpload( const std::vector<std::string> &jointListFromAsset );
- //Determines if a rig is a legacy from the joint list
- bool isRigLegacy( const std::vector<std::string> &jointListFromAsset );
+
//Accessors for the legacy rigs
const bool isLegacyRigValid( void ) const { return mLegacyRigValid; }
- void setLegacyRigValid( bool rigValid ) { mLegacyRigValid = rigValid; }
- //Verify that a controller matches vertex counts
- bool verifyController( domController* pController );
+ void setLegacyRigValid( bool rigValid ) { mLegacyRigValid = rigValid; }
static void textureLoadedCallback( BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* src_aux, S32 discard_level, BOOL final, void* userdata );
@@ -388,6 +301,16 @@ public:
LLVector3 getTranslationForJointOffset( std::string joint );
+ static bool sIgnoreLoadedCallback;
+
+protected:
+
+ static void loadedCallback(LLModelLoader::scene& scene,LLModelLoader::model_list& model_list, S32 lod, void* opaque);
+ static void stateChangedCallback(U32 state, void* opaque);
+
+ static LLJoint* lookupJointByName(const std::string&, void* opaque);
+ static U32 loadTextures(LLImportMaterial& material, void* opaque);
+
private:
//Utility function for controller vertex compare
bool verifyCount( int expected, int result );
@@ -395,6 +318,8 @@ private:
void createPreviewAvatar( void );
//Accessor for the dummy avatar
LLVOAvatar* getPreviewAvatar( void ) { return mPreviewAvatar; }
+ // Count amount of original models, excluding sub-models
+ static U32 countRootModels(LLModelLoader::model_list models);
protected:
friend class LLModelLoader;
@@ -416,13 +341,15 @@ private:
LLVector3 mPreviewTarget;
LLVector3 mPreviewScale;
S32 mPreviewLOD;
+ S32 mPhysicsSearchLOD;
U32 mResourceCost;
std::string mLODFile[LLModel::NUM_LODS];
bool mLoading;
U32 mLoadState;
bool mResetJoints;
bool mRigParityWithScene;
-
+ bool mModelNoErrors;
+
std::map<std::string, bool> mViewOption;
//GLOD object parameters (must rebuild object if these change)
@@ -459,7 +386,7 @@ private:
U32 mMaxTriangleLimit;
LLMeshUploadThread::instance_list mUploadData;
- std::set<LLViewerFetchedTexture* > mTextureSet;
+ std::set<LLViewerFetchedTexture * > mTextureSet;
//map of vertex buffers to models (one vertex buffer in vector per face in model
std::map<LLModel*, std::vector<LLPointer<LLVertexBuffer> > > mVertexBuffer[LLModel::NUM_LODS+1];
@@ -478,10 +405,9 @@ private:
bool mLastJointUpdate;
- std::deque<std::string> mMasterJointList;
- std::deque<std::string> mMasterLegacyJointList;
- std::deque<std::string> mJointsFromNode;
- JointTransformMap mJointTransformMap;
+ JointSet mJointsFromNode;
+ JointTransformMap mJointTransformMap;
+
LLPointer<LLVOAvatar> mPreviewAvatar;
};
diff --git a/indra/newview/llfloatermodeluploadbase.cpp b/indra/newview/llfloatermodeluploadbase.cpp
index e2f84fd990..0fe97fd610 100755
--- a/indra/newview/llfloatermodeluploadbase.cpp
+++ b/indra/newview/llfloatermodeluploadbase.cpp
@@ -70,7 +70,7 @@ void LLFloaterModelUploadBase::requestAgentUploadPermissionsCoro(std::string url
LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
- LLSD result = httpAdapter->getAndYield(httpRequest, url);
+ LLSD result = httpAdapter->getAndSuspend(httpRequest, url);
LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
diff --git a/indra/newview/llfloaternotificationstabbed.cpp b/indra/newview/llfloaternotificationstabbed.cpp
new file mode 100644
index 0000000000..4b5fe4989a
--- /dev/null
+++ b/indra/newview/llfloaternotificationstabbed.cpp
@@ -0,0 +1,575 @@
+/**
+ * @file llfloaternotificationstabbed.cpp
+ * @brief
+ * $LicenseInfo:firstyear=2015&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2015, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h" // must be first include
+#include "llfloaternotificationstabbed.h"
+
+#include "llchiclet.h"
+#include "llchicletbar.h"
+#include "llflatlistview.h"
+#include "llfloaterreg.h"
+#include "llnotificationmanager.h"
+#include "llnotificationsutil.h"
+#include "llscriptfloater.h"
+#include "llspeakers.h"
+#include "lltoastpanel.h"
+#include "lltoastnotifypanel.h"
+
+//---------------------------------------------------------------------------------
+LLFloaterNotificationsTabbed::LLFloaterNotificationsTabbed(const LLSD& key) : LLTransientDockableFloater(NULL, true, key),
+ mChannel(NULL),
+ mSysWellChiclet(NULL),
+ mGroupInviteMessageList(NULL),
+ mGroupNoticeMessageList(NULL),
+ mTransactionMessageList(NULL),
+ mSystemMessageList(NULL),
+ mNotificationsSeparator(NULL),
+ mNotificationsTabContainer(NULL),
+ NOTIFICATION_TABBED_ANCHOR_NAME("notification_well_panel"),
+ IM_WELL_ANCHOR_NAME("im_well_panel"),
+ mIsReshapedByUser(false)
+
+{
+ setOverlapsScreenChannel(true);
+ mNotificationUpdates.reset(new NotificationTabbedChannel(this));
+ mNotificationsSeparator = new LLNotificationSeparator();
+}
+
+//---------------------------------------------------------------------------------
+BOOL LLFloaterNotificationsTabbed::postBuild()
+{
+ mGroupInviteMessageList = getChild<LLNotificationListView>("group_invite_notification_list");
+ mGroupNoticeMessageList = getChild<LLNotificationListView>("group_notice_notification_list");
+ mTransactionMessageList = getChild<LLNotificationListView>("transaction_notification_list");
+ mSystemMessageList = getChild<LLNotificationListView>("system_notification_list");
+ mNotificationsSeparator->initTaggedList(LLNotificationListItem::getGroupInviteTypes(), mGroupInviteMessageList);
+ mNotificationsSeparator->initTaggedList(LLNotificationListItem::getGroupNoticeTypes(), mGroupNoticeMessageList);
+ mNotificationsSeparator->initTaggedList(LLNotificationListItem::getTransactionTypes(), mTransactionMessageList);
+ mNotificationsSeparator->initUnTaggedList(mSystemMessageList);
+ mNotificationsTabContainer = getChild<LLTabContainer>("notifications_tab_container");
+
+ mDeleteAllBtn = getChild<LLButton>("delete_all_button");
+ mDeleteAllBtn->setClickedCallback(boost::bind(&LLFloaterNotificationsTabbed::onClickDeleteAllBtn,this));
+
+ mCollapseAllBtn = getChild<LLButton>("collapse_all_button");
+ mCollapseAllBtn->setClickedCallback(boost::bind(&LLFloaterNotificationsTabbed::onClickCollapseAllBtn,this));
+
+ // get a corresponding channel
+ initChannel();
+ BOOL rv = LLTransientDockableFloater::postBuild();
+
+ setTitle(getString("title_notification_tabbed_window"));
+ return rv;
+}
+
+//---------------------------------------------------------------------------------
+void LLFloaterNotificationsTabbed::setMinimized(BOOL minimize)
+{
+ LLTransientDockableFloater::setMinimized(minimize);
+}
+
+//---------------------------------------------------------------------------------
+void LLFloaterNotificationsTabbed::handleReshape(const LLRect& rect, bool by_user)
+{
+ mIsReshapedByUser |= by_user; // mark floater that it is reshaped by user
+ LLTransientDockableFloater::handleReshape(rect, by_user);
+}
+
+//---------------------------------------------------------------------------------
+void LLFloaterNotificationsTabbed::onStartUpToastClick(S32 x, S32 y, MASK mask)
+{
+ // just set floater visible. Screen channels will be cleared.
+ setVisible(TRUE);
+}
+
+//---------------------------------------------------------------------------------
+void LLFloaterNotificationsTabbed::setSysWellChiclet(LLSysWellChiclet* chiclet)
+{
+ mSysWellChiclet = chiclet;
+ if(NULL != mSysWellChiclet)
+ {
+ mSysWellChiclet->updateWidget(isWindowEmpty());
+ }
+}
+
+//---------------------------------------------------------------------------------
+LLFloaterNotificationsTabbed::~LLFloaterNotificationsTabbed()
+{
+}
+
+//---------------------------------------------------------------------------------
+void LLFloaterNotificationsTabbed::removeItemByID(const LLUUID& id, std::string type)
+{
+ if(mNotificationsSeparator->removeItemByID(type, id))
+ {
+ if (NULL != mSysWellChiclet)
+ {
+ mSysWellChiclet->updateWidget(isWindowEmpty());
+ }
+ reshapeWindow();
+ updateNotificationCounters();
+ }
+ else
+ {
+ LL_WARNS() << "Unable to remove notification from the list, ID: " << id
+ << LL_ENDL;
+ }
+
+ // hide chiclet window if there are no items left
+ if(isWindowEmpty())
+ {
+ setVisible(FALSE);
+ }
+}
+
+//---------------------------------------------------------------------------------
+LLPanel * LLFloaterNotificationsTabbed::findItemByID(const LLUUID& id, std::string type)
+{
+ return mNotificationsSeparator->findItemByID(type, id);
+}
+
+//---------------------------------------------------------------------------------
+void LLFloaterNotificationsTabbed::initChannel()
+{
+ LLNotificationsUI::LLScreenChannelBase* channel = LLNotificationsUI::LLChannelManager::getInstance()->findChannelByID(
+ LLUUID(gSavedSettings.getString("NotificationChannelUUID")));
+ mChannel = dynamic_cast<LLNotificationsUI::LLScreenChannel*>(channel);
+ if(NULL == mChannel)
+ {
+ LL_WARNS() << "LLSysWellWindow::initChannel() - could not get a requested screen channel" << LL_ENDL;
+ }
+
+ if(mChannel)
+ {
+ mChannel->addOnStoreToastCallback(boost::bind(&LLFloaterNotificationsTabbed::onStoreToast, this, _1, _2));
+ }
+}
+
+//---------------------------------------------------------------------------------
+void LLFloaterNotificationsTabbed::setVisible(BOOL visible)
+{
+ if (visible)
+ {
+ // when Notification channel is cleared, storable toasts will be added into the list.
+ clearScreenChannels();
+ }
+ if (visible)
+ {
+ if (NULL == getDockControl() && getDockTongue().notNull())
+ {
+ setDockControl(new LLDockControl(
+ LLChicletBar::getInstance()->getChild<LLView>(getAnchorViewName()), this,
+ getDockTongue(), LLDockControl::BOTTOM));
+ }
+ }
+
+ // do not show empty window
+ if (NULL == mNotificationsSeparator || isWindowEmpty()) visible = FALSE;
+
+ LLTransientDockableFloater::setVisible(visible);
+
+ // update notification channel state
+ initChannel(); // make sure the channel still exists
+ if(mChannel)
+ {
+ mChannel->updateShowToastsState();
+ mChannel->redrawToasts();
+ }
+}
+
+//---------------------------------------------------------------------------------
+void LLFloaterNotificationsTabbed::setDocked(bool docked, bool pop_on_undock)
+{
+ LLTransientDockableFloater::setDocked(docked, pop_on_undock);
+
+ // update notification channel state
+ if(mChannel)
+ {
+ mChannel->updateShowToastsState();
+ mChannel->redrawToasts();
+ }
+}
+
+//---------------------------------------------------------------------------------
+void LLFloaterNotificationsTabbed::reshapeWindow()
+{
+ // update notification channel state
+ // update on a window reshape is important only when a window is visible and docked
+ if(mChannel && getVisible() && isDocked())
+ {
+ mChannel->updateShowToastsState();
+ }
+}
+
+//---------------------------------------------------------------------------------
+bool LLFloaterNotificationsTabbed::isWindowEmpty()
+{
+ return mNotificationsSeparator->size() == 0;
+}
+
+//---------------------------------------------------------------------------------
+LLFloaterNotificationsTabbed::NotificationTabbedChannel::NotificationTabbedChannel(LLFloaterNotificationsTabbed* notifications_tabbed_window)
+ : LLNotificationChannel(LLNotificationChannel::Params().name(notifications_tabbed_window->getPathname())),
+ mNotificationsTabbedWindow(notifications_tabbed_window)
+{
+ connectToChannel("Notifications");
+ connectToChannel("Group Notifications");
+ connectToChannel("Offer");
+}
+
+// static
+//---------------------------------------------------------------------------------
+LLFloaterNotificationsTabbed* LLFloaterNotificationsTabbed::getInstance(const LLSD& key /*= LLSD()*/)
+{
+ return LLFloaterReg::getTypedInstance<LLFloaterNotificationsTabbed>("notification_well_window", key);
+}
+
+//---------------------------------------------------------------------------------
+void LLFloaterNotificationsTabbed::updateNotificationCounter(S32 panelIndex, S32 counterValue, std::string stringName)
+{
+ LLStringUtil::format_map_t string_args;
+ string_args["[COUNT]"] = llformat("%d", counterValue);
+ std::string label = getString(stringName, string_args);
+ mNotificationsTabContainer->setPanelTitle(panelIndex, label);
+}
+
+//---------------------------------------------------------------------------------
+void LLFloaterNotificationsTabbed::updateNotificationCounters()
+{
+ updateNotificationCounter(0, mSystemMessageList->size(), "system_tab_title");
+ updateNotificationCounter(1, mTransactionMessageList->size(), "transactions_tab_title");
+ updateNotificationCounter(2, mGroupInviteMessageList->size(), "group_invitations_tab_title");
+ updateNotificationCounter(3, mGroupNoticeMessageList->size(), "group_notices_tab_title");
+}
+
+//---------------------------------------------------------------------------------
+void LLFloaterNotificationsTabbed::addItem(LLNotificationListItem::Params p)
+{
+ // do not add clones
+ if (mNotificationsSeparator->findItemByID(p.notification_name, p.notification_id))
+ return;
+ LLNotificationListItem* new_item = LLNotificationListItem::create(p);
+ if (new_item == NULL)
+ {
+ return;
+ }
+ if (mNotificationsSeparator->addItem(new_item->getNotificationName(), new_item))
+ {
+ mSysWellChiclet->updateWidget(isWindowEmpty());
+ reshapeWindow();
+ updateNotificationCounters();
+ new_item->setOnItemCloseCallback(boost::bind(&LLFloaterNotificationsTabbed::onItemClose, this, _1));
+ new_item->setOnItemClickCallback(boost::bind(&LLFloaterNotificationsTabbed::onItemClick, this, _1));
+ }
+ else
+ {
+ LL_WARNS() << "Unable to add Notification into the list, notification ID: " << p.notification_id
+ << ", title: " << new_item->getTitle()
+ << LL_ENDL;
+
+ new_item->die();
+ }
+}
+
+//---------------------------------------------------------------------------------
+void LLFloaterNotificationsTabbed::closeAll()
+{
+ // Need to clear notification channel, to add storable toasts into the list.
+ clearScreenChannels();
+
+ std::vector<LLNotificationListItem*> items;
+ mNotificationsSeparator->getItems(items);
+ std::vector<LLNotificationListItem*>::iterator iter = items.begin();
+ for (; iter != items.end(); ++iter)
+ {
+ onItemClose(*iter);
+ }
+}
+
+//---------------------------------------------------------------------------------
+void LLFloaterNotificationsTabbed::getAllItemsOnCurrentTab(std::vector<LLPanel*>& items) const
+{
+ switch (mNotificationsTabContainer->getCurrentPanelIndex())
+ {
+ case 0:
+ mSystemMessageList->getItems(items);
+ break;
+ case 1:
+ mTransactionMessageList->getItems(items);
+ break;
+ case 2:
+ mGroupInviteMessageList->getItems(items);
+ break;
+ case 3:
+ mGroupNoticeMessageList->getItems(items);
+ break;
+ default:
+ break;
+ }
+}
+
+//---------------------------------------------------------------------------------
+void LLFloaterNotificationsTabbed::closeAllOnCurrentTab()
+{
+ // Need to clear notification channel, to add storable toasts into the list.
+ clearScreenChannels();
+ std::vector<LLPanel*> items;
+ getAllItemsOnCurrentTab(items);
+ std::vector<LLPanel*>::iterator iter = items.begin();
+ for (; iter != items.end(); ++iter)
+ {
+ LLNotificationListItem* notify_item = dynamic_cast<LLNotificationListItem*>(*iter);
+ if (notify_item)
+ onItemClose(notify_item);
+ }
+}
+
+//---------------------------------------------------------------------------------
+void LLFloaterNotificationsTabbed::collapseAllOnCurrentTab()
+{
+ std::vector<LLPanel*> items;
+ getAllItemsOnCurrentTab(items);
+ std::vector<LLPanel*>::iterator iter = items.begin();
+ for (; iter != items.end(); ++iter)
+ {
+ LLNotificationListItem* notify_item = dynamic_cast<LLNotificationListItem*>(*iter);
+ if (notify_item)
+ notify_item->setExpanded(FALSE);
+ }
+}
+
+//---------------------------------------------------------------------------------
+void LLFloaterNotificationsTabbed::clearScreenChannels()
+{
+ // 1 - remove StartUp toast and channel if present
+ if(!LLNotificationsUI::LLScreenChannel::getStartUpToastShown())
+ {
+ LLNotificationsUI::LLChannelManager::getInstance()->onStartUpToastClose();
+ }
+
+ // 2 - remove toasts in Notification channel
+ if(mChannel)
+ {
+ mChannel->removeAndStoreAllStorableToasts();
+ }
+}
+
+//---------------------------------------------------------------------------------
+void LLFloaterNotificationsTabbed::onStoreToast(LLPanel* info_panel, LLUUID id)
+{
+ LLNotificationListItem::Params p;
+ p.notification_id = id;
+ p.title = static_cast<LLToastPanel*>(info_panel)->getTitle();
+ LLNotificationPtr notify = mChannel->getToastByNotificationID(id)->getNotification();
+ LLSD payload = notify->getPayload();
+ p.notification_name = notify->getName();
+ p.transaction_id = payload["transaction_id"];
+ p.group_id = payload["group_id"];
+ p.fee = payload["fee"];
+ p.subject = payload["subject"].asString();
+ p.message = payload["message"].asString();
+ p.sender = payload["sender_name"].asString();
+ p.time_stamp = notify->getDate();
+ p.received_time = payload["received_time"].asDate();
+ p.paid_from_id = payload["from_id"];
+ p.paid_to_id = payload["dest_id"];
+ p.inventory_offer = payload["inventory_offer"];
+ p.notification_priority = notify->getPriority();
+ addItem(p);
+}
+
+//---------------------------------------------------------------------------------
+void LLFloaterNotificationsTabbed::onItemClick(LLNotificationListItem* item)
+{
+ LLUUID id = item->getID();
+ if (item->showPopup())
+ {
+ LLFloaterReg::showInstance("inspect_toast", id);
+ }
+ else
+ {
+ item->setExpanded(TRUE);
+ }
+}
+
+//---------------------------------------------------------------------------------
+void LLFloaterNotificationsTabbed::onItemClose(LLNotificationListItem* item)
+{
+ LLUUID id = item->getID();
+
+ if(mChannel)
+ {
+ // removeItemByID() is invoked from killToastByNotificationID() and item will removed;
+ mChannel->killToastByNotificationID(id);
+ }
+ else
+ {
+ // removeItemByID() should be called one time for each item to remove it from notification well
+ removeItemByID(id, item->getNotificationName());
+ }
+
+}
+
+//---------------------------------------------------------------------------------
+void LLFloaterNotificationsTabbed::onAdd( LLNotificationPtr notify )
+{
+ removeItemByID(notify->getID(), notify->getName());
+}
+
+//---------------------------------------------------------------------------------
+void LLFloaterNotificationsTabbed::onClickDeleteAllBtn()
+{
+ closeAllOnCurrentTab();
+}
+
+//---------------------------------------------------------------------------------
+void LLFloaterNotificationsTabbed::onClickCollapseAllBtn()
+{
+ collapseAllOnCurrentTab();
+}
+
+//---------------------------------------------------------------------------------
+void LLNotificationSeparator::initTaggedList(const std::string& tag, LLNotificationListView* list)
+{
+ mNotificationListMap.insert(notification_list_map_t::value_type(tag, list));
+ mNotificationLists.push_back(list);
+}
+
+//---------------------------------------------------------------------------------
+void LLNotificationSeparator::initTaggedList(const std::set<std::string>& tags, LLNotificationListView* list)
+{
+ std::set<std::string>::const_iterator it = tags.begin();
+ for(;it != tags.end();it++)
+ {
+ initTaggedList(*it, list);
+ }
+}
+
+//---------------------------------------------------------------------------------
+void LLNotificationSeparator::initUnTaggedList(LLNotificationListView* list)
+{
+ mUnTaggedList = list;
+}
+
+//---------------------------------------------------------------------------------
+bool LLNotificationSeparator::addItem(std::string& tag, LLNotificationListItem* item)
+{
+ notification_list_map_t::iterator it = mNotificationListMap.find(tag);
+ if (it != mNotificationListMap.end())
+ {
+ return it->second->addNotification(item);
+ }
+ else if (mUnTaggedList != NULL)
+ {
+ return mUnTaggedList->addNotification(item);
+ }
+ return false;
+}
+
+//---------------------------------------------------------------------------------
+bool LLNotificationSeparator::removeItemByID(std::string& tag, const LLUUID& id)
+{
+ notification_list_map_t::iterator it = mNotificationListMap.find(tag);
+ if (it != mNotificationListMap.end())
+ {
+ return it->second->removeItemByValue(id);
+ }
+ else if (mUnTaggedList != NULL)
+ {
+ return mUnTaggedList->removeItemByValue(id);
+ }
+ return false;
+}
+
+//---------------------------------------------------------------------------------
+U32 LLNotificationSeparator::size() const
+{
+ U32 size = 0;
+ notification_list_list_t::const_iterator it = mNotificationLists.begin();
+ for (; it != mNotificationLists.end(); it++)
+ {
+ size = size + (*it)->size();
+ }
+ if (mUnTaggedList != NULL)
+ {
+ size = size + mUnTaggedList->size();
+ }
+ return size;
+}
+
+//---------------------------------------------------------------------------------
+LLPanel* LLNotificationSeparator::findItemByID(std::string& tag, const LLUUID& id)
+{
+ notification_list_map_t::iterator it = mNotificationListMap.find(tag);
+ if (it != mNotificationListMap.end())
+ {
+ return it->second->getItemByValue(id);
+ }
+ else if (mUnTaggedList != NULL)
+ {
+ return mUnTaggedList->getItemByValue(id);
+ }
+
+ return NULL;
+}
+
+//static
+//---------------------------------------------------------------------------------
+void LLNotificationSeparator::getItemsFromList(std::vector<LLNotificationListItem*>& items, LLNotificationListView* list)
+{
+ std::vector<LLPanel*> list_items;
+ list->getItems(list_items);
+ std::vector<LLPanel*>::iterator it = list_items.begin();
+ for (; it != list_items.end(); ++it)
+ {
+ LLNotificationListItem* notify_item = dynamic_cast<LLNotificationListItem*>(*it);
+ if (notify_item)
+ items.push_back(notify_item);
+ }
+}
+
+//---------------------------------------------------------------------------------
+void LLNotificationSeparator::getItems(std::vector<LLNotificationListItem*>& items) const
+{
+ items.clear();
+ notification_list_list_t::const_iterator lists_it = mNotificationLists.begin();
+ for (; lists_it != mNotificationLists.end(); lists_it++)
+ {
+ getItemsFromList(items, *lists_it);
+ }
+ if (mUnTaggedList != NULL)
+ {
+ getItemsFromList(items, mUnTaggedList);
+ }
+}
+
+//---------------------------------------------------------------------------------
+LLNotificationSeparator::LLNotificationSeparator()
+ : mUnTaggedList(NULL)
+{}
+
+//---------------------------------------------------------------------------------
+LLNotificationSeparator::~LLNotificationSeparator()
+{}
diff --git a/indra/newview/llfloaternotificationstabbed.h b/indra/newview/llfloaternotificationstabbed.h
new file mode 100644
index 0000000000..8dd20b18c4
--- /dev/null
+++ b/indra/newview/llfloaternotificationstabbed.h
@@ -0,0 +1,174 @@
+/**
+ * @file llfloaternotificationstabbed.h
+ * @brief
+ *
+ * $LicenseInfo:firstyear=2015&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2015, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_FLOATERNOTIFICATIONSTABBED_H
+#define LL_FLOATERNOTIFICATIONSTABBED_H
+
+#include "llimview.h"
+#include "llnotifications.h"
+#include "llscreenchannel.h"
+#include "llsyswellitem.h"
+#include "lltransientdockablefloater.h"
+#include "llnotificationlistview.h"
+#include "lltabcontainer.h"
+
+class LLAvatarName;
+class LLChiclet;
+class LLFlatListView;
+class LLIMChiclet;
+class LLScriptChiclet;
+class LLSysWellChiclet;
+
+class LLNotificationSeparator
+{
+public:
+ LLNotificationSeparator();
+ ~LLNotificationSeparator();
+ void initTaggedList(const std::string& tag, LLNotificationListView* list);
+ void initTaggedList(const std::set<std::string>& tags, LLNotificationListView* list);
+ void initUnTaggedList(LLNotificationListView* list);
+ bool addItem(std::string& tag, LLNotificationListItem* item);
+ LLPanel* findItemByID(std::string& tag, const LLUUID& id);
+ bool removeItemByID(std::string& tag, const LLUUID& id);
+ void getItems(std::vector<LLNotificationListItem*>& items) const;
+ U32 size() const;
+private:
+ static void getItemsFromList(std::vector<LLNotificationListItem*>& items, LLNotificationListView* list);
+
+ typedef std::map<std::string, LLNotificationListView*> notification_list_map_t;
+ notification_list_map_t mNotificationListMap;
+ typedef std::list<LLNotificationListView*> notification_list_list_t;
+ notification_list_list_t mNotificationLists;
+ LLNotificationListView* mUnTaggedList;
+};
+
+class LLFloaterNotificationsTabbed : public LLTransientDockableFloater
+{
+public:
+ LOG_CLASS(LLFloaterNotificationsTabbed);
+
+ LLFloaterNotificationsTabbed(const LLSD& key);
+ virtual ~LLFloaterNotificationsTabbed();
+ BOOL postBuild();
+
+ // other interface functions
+ // check is window empty
+ bool isWindowEmpty();
+
+ // Operating with items
+ void removeItemByID(const LLUUID& id, std::string type);
+ LLPanel * findItemByID(const LLUUID& id, std::string type);
+ void updateNotificationCounters();
+ void updateNotificationCounter(S32 panelIndex, S32 counterValue, std::string stringName);
+
+ // Operating with outfit
+ virtual void setVisible(BOOL visible);
+
+ /*virtual*/ void setDocked(bool docked, bool pop_on_undock = true);
+ // override LLFloater's minimization according to EXT-1216
+ /*virtual*/ void setMinimized(BOOL minimize);
+ /*virtual*/ void handleReshape(const LLRect& rect, bool by_user);
+
+ void onStartUpToastClick(S32 x, S32 y, MASK mask);
+ /*virtual*/ void onAdd(LLNotificationPtr notify);
+
+ void setSysWellChiclet(LLSysWellChiclet* chiclet);
+ void closeAll();
+
+ static LLFloaterNotificationsTabbed* getInstance(const LLSD& key = LLSD());
+
+ // size constants for the window and for its elements
+ static const S32 MAX_WINDOW_HEIGHT = 200;
+ static const S32 MIN_WINDOW_WIDTH = 318;
+
+private:
+ // init Window's channel
+ virtual void initChannel();
+
+ const std::string NOTIFICATION_TABBED_ANCHOR_NAME;
+ const std::string IM_WELL_ANCHOR_NAME;
+ //virtual const std::string& getAnchorViewName() = 0;
+
+ void reshapeWindow();
+
+ // pointer to a corresponding channel's instance
+ LLNotificationsUI::LLScreenChannel* mChannel;
+
+ /**
+ * Reference to an appropriate Well chiclet to release "new message" state. EXT-3147
+ */
+ LLSysWellChiclet* mSysWellChiclet;
+
+ bool mIsReshapedByUser;
+
+ struct NotificationTabbedChannel : public LLNotificationChannel
+ {
+ NotificationTabbedChannel(LLFloaterNotificationsTabbed*);
+ void onDelete(LLNotificationPtr notify)
+ {
+ mNotificationsTabbedWindow->removeItemByID(notify->getID(), notify->getName());
+ }
+
+ LLFloaterNotificationsTabbed* mNotificationsTabbedWindow;
+ };
+
+ LLNotificationChannelPtr mNotificationUpdates;
+ virtual const std::string& getAnchorViewName() { return NOTIFICATION_TABBED_ANCHOR_NAME; }
+
+ // init Window's channel
+ // void initChannel();
+ void clearScreenChannels();
+ // Operating with items
+ void addItem(LLNotificationListItem::Params p);
+ void getAllItemsOnCurrentTab(std::vector<LLPanel*>& items) const;
+
+ // Closes all notifications and removes them from the Notification Well
+ void closeAllOnCurrentTab();
+ void collapseAllOnCurrentTab();
+
+ void onStoreToast(LLPanel* info_panel, LLUUID id);
+ void onClickDeleteAllBtn();
+ void onClickCollapseAllBtn();
+ // Handlers
+ void onItemClick(LLNotificationListItem* item);
+ void onItemClose(LLNotificationListItem* item);
+ // ID of a toast loaded by user (by clicking notification well item)
+ LLUUID mLoadedToastId;
+
+ LLNotificationListView* mGroupInviteMessageList;
+ LLNotificationListView* mGroupNoticeMessageList;
+ LLNotificationListView* mTransactionMessageList;
+ LLNotificationListView* mSystemMessageList;
+ LLNotificationSeparator* mNotificationsSeparator;
+ LLTabContainer* mNotificationsTabContainer;
+ LLButton* mDeleteAllBtn;
+ LLButton* mCollapseAllBtn;
+};
+
+#endif // LL_FLOATERNOTIFICATIONSTABBED_H
+
+
+
diff --git a/indra/newview/llfloateroutbox.cpp b/indra/newview/llfloateroutbox.cpp
deleted file mode 100755
index b7b1634a5f..0000000000
--- a/indra/newview/llfloateroutbox.cpp
+++ /dev/null
@@ -1,623 +0,0 @@
-/**
- * @file llfloateroutbox.cpp
- * @brief Implementation of the merchant outbox window
- *
- * $LicenseInfo:firstyear=2001&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#include "llviewerprecompiledheaders.h"
-
-#include "llfloateroutbox.h"
-
-#include "llfloaterreg.h"
-#include "llfolderview.h"
-#include "llinventorybridge.h"
-#include "llinventorymodelbackgroundfetch.h"
-#include "llinventoryobserver.h"
-#include "llinventorypanel.h"
-#include "llmarketplacefunctions.h"
-#include "llnotificationhandler.h"
-#include "llnotificationmanager.h"
-#include "llnotificationsutil.h"
-#include "lltextbox.h"
-#include "lltransientfloatermgr.h"
-#include "lltrans.h"
-#include "llviewernetwork.h"
-#include "llwindowshade.h"
-
-
-///----------------------------------------------------------------------------
-/// LLOutboxNotification class
-///----------------------------------------------------------------------------
-
-LLNotificationsUI::LLOutboxNotification::LLOutboxNotification()
- : LLSystemNotificationHandler("Outbox", "outbox")
-{
-}
-
-bool LLNotificationsUI::LLOutboxNotification::processNotification(const LLNotificationPtr& notify)
-{
- LLFloaterOutbox* outbox_floater = LLFloaterReg::getTypedInstance<LLFloaterOutbox>("outbox");
-
- outbox_floater->showNotification(notify);
-
- return false;
-}
-
-void LLNotificationsUI::LLOutboxNotification::onDelete(LLNotificationPtr p)
-{
- LLNotificationsUI::LLNotificationHandler * notification_handler = dynamic_cast<LLNotificationsUI::LLNotificationHandler*>(LLNotifications::instance().getChannel("AlertModal").get());
- if (notification_handler)
- {
- notification_handler->onDelete(p);
- }
-}
-
-///----------------------------------------------------------------------------
-/// LLOutboxAddedObserver helper class
-///----------------------------------------------------------------------------
-
-class LLOutboxAddedObserver : public LLInventoryCategoryAddedObserver
-{
-public:
- LLOutboxAddedObserver(LLFloaterOutbox * outboxFloater)
- : LLInventoryCategoryAddedObserver()
- , mOutboxFloater(outboxFloater)
- {
- }
-
- void done()
- {
- for (cat_vec_t::iterator it = mAddedCategories.begin(); it != mAddedCategories.end(); ++it)
- {
- LLViewerInventoryCategory* added_category = *it;
-
- LLFolderType::EType added_category_type = added_category->getPreferredType();
-
- if (added_category_type == LLFolderType::FT_OUTBOX)
- {
- mOutboxFloater->initializeMarketPlace();
- }
- }
- }
-
-private:
- LLFloaterOutbox * mOutboxFloater;
-};
-
-///----------------------------------------------------------------------------
-/// LLFloaterOutbox
-///----------------------------------------------------------------------------
-
-LLFloaterOutbox::LLFloaterOutbox(const LLSD& key)
- : LLFloater(key)
- , mCategoriesObserver(NULL)
- , mCategoryAddedObserver(NULL)
- , mImportBusy(false)
- , mImportButton(NULL)
- , mInventoryFolderCountText(NULL)
- , mInventoryImportInProgress(NULL)
- , mInventoryPlaceholder(NULL)
- , mInventoryText(NULL)
- , mInventoryTitle(NULL)
- , mOutboxId(LLUUID::null)
- , mOutboxItemCount(0)
- , mOutboxTopLevelDropZone(NULL)
- , mWindowShade(NULL)
-{
-}
-
-LLFloaterOutbox::~LLFloaterOutbox()
-{
- if (mCategoriesObserver && gInventory.containsObserver(mCategoriesObserver))
- {
- gInventory.removeObserver(mCategoriesObserver);
- }
- delete mCategoriesObserver;
-
- if (mCategoryAddedObserver && gInventory.containsObserver(mCategoryAddedObserver))
- {
- gInventory.removeObserver(mCategoryAddedObserver);
- }
- delete mCategoryAddedObserver;
-}
-
-BOOL LLFloaterOutbox::postBuild()
-{
- mInventoryFolderCountText = getChild<LLTextBox>("outbox_folder_count");
- mInventoryImportInProgress = getChild<LLView>("import_progress_indicator");
- mInventoryPlaceholder = getChild<LLView>("outbox_inventory_placeholder_panel");
- mInventoryText = mInventoryPlaceholder->getChild<LLTextBox>("outbox_inventory_placeholder_text");
- mInventoryTitle = mInventoryPlaceholder->getChild<LLTextBox>("outbox_inventory_placeholder_title");
-
- mImportButton = getChild<LLButton>("outbox_import_btn");
- mImportButton->setCommitCallback(boost::bind(&LLFloaterOutbox::onImportButtonClicked, this));
-
- mOutboxTopLevelDropZone = getChild<LLPanel>("outbox_generic_drag_target");
-
- LLFocusableElement::setFocusReceivedCallback(boost::bind(&LLFloaterOutbox::onFocusReceived, this));
-
- // Observe category creation to catch outbox creation (moot if already existing)
- mCategoryAddedObserver = new LLOutboxAddedObserver(this);
- gInventory.addObserver(mCategoryAddedObserver);
-
- // Setup callbacks for importer
- LLMarketplaceInventoryImporter& importer = LLMarketplaceInventoryImporter::instance();
- importer.setInitializationErrorCallback(boost::bind(&LLFloaterOutbox::initializationReportError, this, _1, _2));
- importer.setStatusChangedCallback(boost::bind(&LLFloaterOutbox::importStatusChanged, this, _1));
- importer.setStatusReportCallback(boost::bind(&LLFloaterOutbox::importReportResults, this, _1, _2));
-
- return TRUE;
-}
-
-void LLFloaterOutbox::cleanOutbox()
-{
- // Note: we cannot delete the mOutboxInventoryPanel as that point
- // as this is called through callback observers of the panel itself.
- // Doing so would crash rapidly.
-
- // Invalidate the outbox data
- mOutboxId.setNull();
- mOutboxItemCount = 0;
-}
-
-void LLFloaterOutbox::onClose(bool app_quitting)
-{
- if (mWindowShade)
- {
- delete mWindowShade;
-
- mWindowShade = NULL;
- }
-}
-
-void LLFloaterOutbox::onOpen(const LLSD& key)
-{
- //
- // Initialize the Market Place or go update the outbox
- //
- if (LLMarketplaceInventoryImporter::getInstance()->getMarketPlaceStatus() == MarketplaceStatusCodes::MARKET_PLACE_NOT_INITIALIZED)
- {
- initializeMarketPlace();
- }
- else
- {
- setupOutbox();
- }
-
- //
- // Update the floater view
- //
- updateView();
-
- //
- // Trigger fetch of outbox contents
- //
- fetchOutboxContents();
-}
-
-void LLFloaterOutbox::onFocusReceived()
-{
- fetchOutboxContents();
-}
-
-void LLFloaterOutbox::fetchOutboxContents()
-{
- if (mOutboxId.notNull())
- {
- LLInventoryModelBackgroundFetch::instance().start(mOutboxId);
- }
-}
-
-void LLFloaterOutbox::setupOutbox()
-{
- if (LLMarketplaceInventoryImporter::getInstance()->getMarketPlaceStatus() != MarketplaceStatusCodes::MARKET_PLACE_MERCHANT)
- {
- // If we are *not* a merchant or we have no market place connection established yet, do nothing
- return;
- }
-
- // We are a merchant. Get the outbox, create it if needs be.
- LLUUID outbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, true);
- if (outbox_id.isNull())
- {
- // We should never get there unless the inventory fails badly
- LL_ERRS() << "Inventory problem: failure to create the outbox for a merchant!" << LL_ENDL;
- return;
- }
-
- // Consolidate Merchant Outbox
- // We shouldn't have to do that but with a client/server system relying on a "well known folder" convention, things get messy and conventions get broken down eventually
- gInventory.consolidateForType(outbox_id, LLFolderType::FT_OUTBOX);
-
- if (outbox_id == mOutboxId)
- {
- LL_WARNS() << "Inventory warning: Merchant outbox already set" << LL_ENDL;
- return;
- }
- mOutboxId = outbox_id;
-
- // No longer need to observe new category creation
- if (mCategoryAddedObserver && gInventory.containsObserver(mCategoryAddedObserver))
- {
- gInventory.removeObserver(mCategoryAddedObserver);
- delete mCategoryAddedObserver;
- mCategoryAddedObserver = NULL;
- }
- llassert(!mCategoryAddedObserver);
-
- // Create observer for outbox modifications : clear the old one and create a new one
- if (mCategoriesObserver && gInventory.containsObserver(mCategoriesObserver))
- {
- gInventory.removeObserver(mCategoriesObserver);
- delete mCategoriesObserver;
- }
- mCategoriesObserver = new LLInventoryCategoriesObserver();
- gInventory.addObserver(mCategoriesObserver);
- mCategoriesObserver->addCategory(mOutboxId, boost::bind(&LLFloaterOutbox::onOutboxChanged, this));
- llassert(mCategoriesObserver);
-
- // Set up the outbox inventory view
- LLInventoryPanel* inventory_panel = mOutboxInventoryPanel.get();
- if (inventory_panel)
- {
- delete inventory_panel;
- }
- inventory_panel = LLUICtrlFactory::createFromFile<LLInventoryPanel>("panel_outbox_inventory.xml", mInventoryPlaceholder->getParent(), LLInventoryPanel::child_registry_t::instance());
- mOutboxInventoryPanel = inventory_panel->getInventoryPanelHandle();
- llassert(mOutboxInventoryPanel.get() != NULL);
-
- // Reshape the inventory to the proper size
- LLRect inventory_placeholder_rect = mInventoryPlaceholder->getRect();
- inventory_panel->setShape(inventory_placeholder_rect);
-
- // Set the sort order newest to oldest
- inventory_panel->getFolderViewModel()->setSorter(LLInventoryFilter::SO_FOLDERS_BY_NAME);
- inventory_panel->getFilter().markDefault();
-
- // Get the content of the outbox
- fetchOutboxContents();
-}
-
-void LLFloaterOutbox::initializeMarketPlace()
-{
- //
- // Initialize the marketplace import API
- //
- LLMarketplaceInventoryImporter& importer = LLMarketplaceInventoryImporter::instance();
- if (!importer.isInitialized())
- {
- importer.initialize();
- }
-}
-
-void LLFloaterOutbox::setStatusString(const std::string& statusString)
-{
- llassert(mInventoryFolderCountText != NULL);
-
- mInventoryFolderCountText->setText(statusString);
-}
-
-void LLFloaterOutbox::updateFolderCount()
-{
- if (mOutboxInventoryPanel.get() && mOutboxId.notNull())
- {
- U32 item_count = 0;
-
- if (mOutboxId.notNull())
- {
- LLInventoryModel::cat_array_t * cats;
- LLInventoryModel::item_array_t * items;
- gInventory.getDirectDescendentsOf(mOutboxId, cats, items);
-
- item_count = cats->size() + items->size();
- }
-
- mOutboxItemCount = item_count;
- }
- else
- {
- // If there's no outbox, the number of items in it should be set to 0 for consistency
- mOutboxItemCount = 0;
- }
-
- if (!mImportBusy)
- {
- updateFolderCountStatus();
- }
-}
-
-void LLFloaterOutbox::updateFolderCountStatus()
-{
- if (mOutboxInventoryPanel.get() && mOutboxId.notNull())
- {
- switch (mOutboxItemCount)
- {
- case 0: setStatusString(getString("OutboxFolderCount0")); break;
- case 1: setStatusString(getString("OutboxFolderCount1")); break;
- default:
- {
- std::string item_count_str = llformat("%d", mOutboxItemCount);
-
- LLStringUtil::format_map_t args;
- args["[NUM]"] = item_count_str;
-
- setStatusString(getString("OutboxFolderCountN", args));
- break;
- }
- }
- }
-
- mImportButton->setEnabled(mOutboxItemCount > 0);
-}
-
-void LLFloaterOutbox::updateView()
-{
- updateFolderCount();
- LLInventoryPanel* panel = mOutboxInventoryPanel.get();
-
- if (mOutboxItemCount > 0)
- {
- panel->setVisible(TRUE);
- mInventoryPlaceholder->setVisible(FALSE);
- mOutboxTopLevelDropZone->setVisible(TRUE);
- }
- else
- {
- if (panel)
- {
- panel->setVisible(FALSE);
- }
-
- // Show the drop zone if there is an outbox folder
- mOutboxTopLevelDropZone->setVisible(mOutboxId.notNull());
-
- mInventoryPlaceholder->setVisible(TRUE);
-
- std::string outbox_text;
- std::string outbox_title;
- std::string outbox_tooltip;
-
- const LLSD& subs = getMarketplaceStringSubstitutions();
- U32 mkt_status = LLMarketplaceInventoryImporter::getInstance()->getMarketPlaceStatus();
-
- if (mOutboxId.notNull())
- {
- // Does the outbox needs recreation?
- if ((mOutboxInventoryPanel.get() == NULL) || !gInventory.getCategory(mOutboxId))
- {
- setupOutbox();
- }
- // "Outbox is empty!" message strings
- outbox_text = LLTrans::getString("InventoryOutboxNoItems", subs);
- outbox_title = LLTrans::getString("InventoryOutboxNoItemsTitle");
- outbox_tooltip = LLTrans::getString("InventoryOutboxNoItemsTooltip");
- }
- else if (mkt_status <= MarketplaceStatusCodes::MARKET_PLACE_INITIALIZING)
- {
- // "Initializing!" message strings
- outbox_text = LLTrans::getString("InventoryOutboxInitializing", subs);
- outbox_title = LLTrans::getString("InventoryOutboxInitializingTitle");
- outbox_tooltip = LLTrans::getString("InventoryOutboxInitializingTooltip");
- }
- else if (mkt_status == MarketplaceStatusCodes::MARKET_PLACE_NOT_MERCHANT)
- {
- // "Not a merchant!" message strings
- outbox_text = LLTrans::getString("InventoryOutboxNotMerchant", subs);
- outbox_title = LLTrans::getString("InventoryOutboxNotMerchantTitle");
- outbox_tooltip = LLTrans::getString("InventoryOutboxNotMerchantTooltip");
- }
- else
- {
- // "Errors!" message strings
- outbox_text = LLTrans::getString("InventoryOutboxError", subs);
- outbox_title = LLTrans::getString("InventoryOutboxErrorTitle");
- outbox_tooltip = LLTrans::getString("InventoryOutboxErrorTooltip");
- }
-
- mInventoryText->setValue(outbox_text);
- mInventoryTitle->setValue(outbox_title);
- mInventoryPlaceholder->getParent()->setToolTip(outbox_tooltip);
- }
-}
-
-bool isAccepted(EAcceptance accept)
-{
- return (accept >= ACCEPT_YES_COPY_SINGLE);
-}
-
-BOOL LLFloaterOutbox::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
- EDragAndDropType cargo_type,
- void* cargo_data,
- EAcceptance* accept,
- std::string& tooltip_msg)
-{
- if ((mOutboxInventoryPanel.get() == NULL) ||
- (mWindowShade && mWindowShade->isShown()) ||
- LLMarketplaceInventoryImporter::getInstance()->isImportInProgress() ||
- mOutboxId.isNull())
- {
- return FALSE;
- }
-
- LLView * handled_view = childrenHandleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg);
- BOOL handled = (handled_view != NULL);
-
- // Determine if the mouse is inside the inventory panel itself or just within the floater
- bool pointInInventoryPanel = false;
- bool pointInInventoryPanelChild = false;
- LLInventoryPanel* panel = mOutboxInventoryPanel.get();
- LLFolderView* root_folder = panel->getRootFolder();
- if (panel->getVisible())
- {
- S32 inv_x, inv_y;
- localPointToOtherView(x, y, &inv_x, &inv_y, panel);
-
- pointInInventoryPanel = panel->getRect().pointInRect(inv_x, inv_y);
-
- LLView * inventory_panel_child_at_point = panel->childFromPoint(inv_x, inv_y, true);
- pointInInventoryPanelChild = (inventory_panel_child_at_point != root_folder);
- }
-
- // Pass all drag and drop for this floater to the outbox inventory control
- if (!handled || !isAccepted(*accept))
- {
- // Handle the drag and drop directly to the root of the outbox if we're not in the inventory panel
- // (otherwise the inventory panel itself will handle the drag and drop operation, without any override)
- if (!pointInInventoryPanel)
- {
- handled = root_folder->handleDragAndDropToThisFolder(mask, drop, cargo_type, cargo_data, accept, tooltip_msg);
- }
-
- mOutboxTopLevelDropZone->setBackgroundVisible(handled && !drop && isAccepted(*accept));
- }
- else
- {
- mOutboxTopLevelDropZone->setBackgroundVisible(!pointInInventoryPanelChild);
- }
-
- return handled;
-}
-
-BOOL LLFloaterOutbox::handleHover(S32 x, S32 y, MASK mask)
-{
- mOutboxTopLevelDropZone->setBackgroundVisible(FALSE);
-
- return LLFloater::handleHover(x, y, mask);
-}
-
-void LLFloaterOutbox::onMouseLeave(S32 x, S32 y, MASK mask)
-{
- mOutboxTopLevelDropZone->setBackgroundVisible(FALSE);
-
- LLFloater::onMouseLeave(x, y, mask);
-}
-
-void LLFloaterOutbox::onImportButtonClicked()
-{
- if (mOutboxInventoryPanel.get())
- {
- mOutboxInventoryPanel.get()->clearSelection();
- }
-
- mImportBusy = LLMarketplaceInventoryImporter::instance().triggerImport();
-}
-
-void LLFloaterOutbox::onOutboxChanged()
-{
- LLViewerInventoryCategory* category = gInventory.getCategory(mOutboxId);
- if (mOutboxId.notNull() && category)
- {
- fetchOutboxContents();
- updateView();
- }
- else
- {
- cleanOutbox();
- }
-}
-
-void LLFloaterOutbox::importReportResults(U32 status, const LLSD& content)
-{
- if (status == MarketplaceErrorCodes::IMPORT_DONE)
- {
- LLNotificationsUtil::add("OutboxImportComplete");
- }
- else if (status == MarketplaceErrorCodes::IMPORT_DONE_WITH_ERRORS)
- {
- const LLSD& subs = getMarketplaceStringSubstitutions();
-
- LLNotificationsUtil::add("OutboxImportHadErrors", subs);
- }
- else
- {
- char status_string[16];
- sprintf(status_string, "%d", status);
-
- LLSD subs;
- subs["[ERROR_CODE]"] = status_string;
-
- LLNotificationsUtil::add("OutboxImportFailed", subs);
- }
-
- updateView();
-}
-
-void LLFloaterOutbox::importStatusChanged(bool inProgress)
-{
- if (mOutboxId.isNull() && (LLMarketplaceInventoryImporter::getInstance()->getMarketPlaceStatus() == MarketplaceStatusCodes::MARKET_PLACE_MERCHANT))
- {
- setupOutbox();
- }
-
- if (inProgress)
- {
- if (mImportBusy)
- {
- setStatusString(getString("OutboxImporting"));
- }
- else
- {
- setStatusString(getString("OutboxInitializing"));
- }
-
- mImportBusy = true;
- mImportButton->setEnabled(false);
- mInventoryImportInProgress->setVisible(true);
- }
- else
- {
- setStatusString("");
- mImportBusy = false;
- mImportButton->setEnabled(mOutboxItemCount > 0);
- mInventoryImportInProgress->setVisible(false);
- }
-
- updateView();
-}
-
-void LLFloaterOutbox::initializationReportError(U32 status, const LLSD& content)
-{
- if (status >= MarketplaceErrorCodes::IMPORT_BAD_REQUEST)
- {
- char status_string[16];
- sprintf(status_string, "%d", status);
-
- LLSD subs;
- subs["[ERROR_CODE]"] = status_string;
-
- LLNotificationsUtil::add("OutboxInitFailed", subs);
- }
-
- updateView();
-}
-
-void LLFloaterOutbox::showNotification(const LLNotificationPtr& notification)
-{
- LLNotificationsUI::LLNotificationHandler * notification_handler = dynamic_cast<LLNotificationsUI::LLNotificationHandler*>(LLNotifications::instance().getChannel("AlertModal").get());
- llassert(notification_handler);
-
- notification_handler->processNotification(notification);
-}
-
-
-
diff --git a/indra/newview/llfloateroutbox.h b/indra/newview/llfloateroutbox.h
deleted file mode 100755
index 2cf69fc3cc..0000000000
--- a/indra/newview/llfloateroutbox.h
+++ /dev/null
@@ -1,116 +0,0 @@
-/**
- * @file llfloateroutbox.h
- * @brief Implementation of the merchant outbox window
- *
- * $LicenseInfo:firstyear=2001&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * ABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLFLOATEROUTBOX_H
-#define LL_LLFLOATEROUTBOX_H
-
-#include "llfloater.h"
-#include "llfoldertype.h"
-#include "llinventoryfilter.h"
-#include "llnotificationptr.h"
-
-
-class LLButton;
-class LLInventoryCategoriesObserver;
-class LLInventoryCategoryAddedObserver;
-class LLInventoryPanel;
-class LLLoadingIndicator;
-class LLNotification;
-class LLTextBox;
-class LLView;
-class LLWindowShade;
-
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// Class LLFloaterOutbox
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-class LLFloaterOutbox : public LLFloater
-{
-public:
- LLFloaterOutbox(const LLSD& key);
- ~LLFloaterOutbox();
-
- void initializeMarketPlace();
-
- // virtuals
- BOOL postBuild();
- BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
- EDragAndDropType cargo_type,
- void* cargo_data,
- EAcceptance* accept,
- std::string& tooltip_msg);
-
- void showNotification(const LLNotificationPtr& notification);
-
- BOOL handleHover(S32 x, S32 y, MASK mask);
- void onMouseLeave(S32 x, S32 y, MASK mask);
-
-protected:
- void setupOutbox();
- void cleanOutbox();
- void fetchOutboxContents();
-
- void importReportResults(U32 status, const LLSD& content);
- void importStatusChanged(bool inProgress);
- void initializationReportError(U32 status, const LLSD& content);
-
- void onClose(bool app_quitting);
- void onOpen(const LLSD& key);
-
- void onFocusReceived();
-
- void onImportButtonClicked();
- void onOutboxChanged();
-
- void setStatusString(const std::string& statusString);
-
- void updateFolderCount();
- void updateFolderCountStatus();
- void updateView();
-
-private:
- LLInventoryCategoriesObserver * mCategoriesObserver;
- LLInventoryCategoryAddedObserver * mCategoryAddedObserver;
-
- bool mImportBusy;
- LLButton * mImportButton;
-
- LLTextBox * mInventoryFolderCountText;
- LLView * mInventoryImportInProgress;
- LLView * mInventoryPlaceholder;
- LLTextBox * mInventoryText;
- LLTextBox * mInventoryTitle;
-
- LLUUID mOutboxId;
- LLHandle<LLInventoryPanel> mOutboxInventoryPanel;
- U32 mOutboxItemCount;
- LLPanel * mOutboxTopLevelDropZone;
-
- LLWindowShade * mWindowShade;
-};
-
-#endif // LL_LLFLOATEROUTBOX_H
diff --git a/indra/newview/llfloaterperms.cpp b/indra/newview/llfloaterperms.cpp
index 16bb449fdb..cb67787af3 100755
--- a/indra/newview/llfloaterperms.cpp
+++ b/indra/newview/llfloaterperms.cpp
@@ -38,6 +38,8 @@
#include "llsdserialize.h"
#include "llvoavatar.h"
#include "llcorehttputil.h"
+#include "lleventfilter.h"
+#include "lleventcoro.h"
LLFloaterPerms::LLFloaterPerms(const LLSD& seed)
: LLFloater(seed)
@@ -167,11 +169,15 @@ void LLFloaterPermsDefault::onCommitCopy(const LLSD& user_data)
xfer->setEnabled(copyable);
}
+const int MAX_HTTP_RETRIES = 5;
+const float RETRY_TIMEOUT = 5.0;
+
void LLFloaterPermsDefault::sendInitialPerms()
{
if(!mCapSent)
{
updateCap();
+ setCapSent(true);
}
}
@@ -193,7 +199,8 @@ void LLFloaterPermsDefault::updateCap()
/*static*/
void LLFloaterPermsDefault::updateCapCoro(std::string url)
{
- static std::string previousReason;
+ int retryCount = 0;
+ std::string previousReason;
LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("genericPostCoro", httpPolicy));
@@ -215,23 +222,37 @@ void LLFloaterPermsDefault::updateCapCoro(std::string url)
LL_CONT << sent_perms_log.str() << LL_ENDL;
}
- LLSD result = httpAdapter->postAndYield(httpRequest, url, postData);
+ while (true)
+ {
+ ++retryCount;
+ LLSD result = httpAdapter->postAndSuspend(httpRequest, url, postData);
- LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
- LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+ LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+ LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
- if (!status)
- {
- const std::string& reason = status.toString();
- // Do not display the same error more than once in a row
- if (reason != previousReason)
+ if (!status)
{
- previousReason = reason;
- LLSD args;
- args["REASON"] = reason;
- LLNotificationsUtil::add("DefaultObjectPermissions", args);
+ LLEventTimeout timeout;
+
+ const std::string& reason = status.toString();
+ // Do not display the same error more than once in a row
+ if (reason != previousReason)
+ {
+ previousReason = reason;
+ LLSD args;
+ args["REASON"] = reason;
+ LLNotificationsUtil::add("DefaultObjectPermissions", args);
+ }
+
+ timeout.eventAfter(RETRY_TIMEOUT, LLSD());
+ llcoro::suspendUntilEventOn(timeout);
+ if (retryCount < MAX_HTTP_RETRIES)
+ continue;
+
+ LL_WARNS("ObjectPermissionsFloater") << "Unable to send default permissions. Giving up for now." << LL_ENDL;
+ return;
}
- return;
+ break;
}
// Since we have had a successful POST call be sure to display the next error message
diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp
index ee4396758e..dac610eda1 100755
--- a/indra/newview/llfloaterpreference.cpp
+++ b/indra/newview/llfloaterpreference.cpp
@@ -49,6 +49,7 @@
//#include "llfirstuse.h"
#include "llfloaterreg.h"
#include "llfloaterabout.h"
+#include "llfavoritesbar.h"
#include "llfloaterhardwaresettings.h"
#include "llfloatersidepanelcontainer.h"
#include "llfloaterimsession.h"
@@ -1919,7 +1920,7 @@ BOOL LLPanelPreference::postBuild()
}
if (hasChild("favorites_on_login_check", TRUE))
{
- getChild<LLCheckBoxCtrl>("favorites_on_login_check")->setCommitCallback(boost::bind(&showFavoritesOnLoginWarning, _1, _2));
+ getChild<LLCheckBoxCtrl>("favorites_on_login_check")->setCommitCallback(boost::bind(&handleFavoritesOnLoginChanged, _1, _2));
bool show_favorites_at_login = LLPanelLogin::getShowFavorites();
getChild<LLCheckBoxCtrl>("favorites_on_login_check")->setValue(show_favorites_at_login);
}
@@ -2004,11 +2005,15 @@ void LLPanelPreference::showFriendsOnlyWarning(LLUICtrl* checkbox, const LLSD& v
}
}
-void LLPanelPreference::showFavoritesOnLoginWarning(LLUICtrl* checkbox, const LLSD& value)
+void LLPanelPreference::handleFavoritesOnLoginChanged(LLUICtrl* checkbox, const LLSD& value)
{
- if (checkbox && checkbox->getValue())
+ if (checkbox)
{
- LLNotificationsUtil::add("FavoritesOnLogin");
+ LLFavoritesOrderStorage::instance().showFavoritesOnLoginChanged(checkbox->getValue().asBoolean());
+ if(checkbox->getValue())
+ {
+ LLNotificationsUtil::add("FavoritesOnLogin");
+ }
}
}
@@ -2235,6 +2240,11 @@ void LLFloaterPreferenceProxy::onOpen(const LLSD& key)
void LLFloaterPreferenceProxy::onClose(bool app_quitting)
{
+ if(app_quitting)
+ {
+ cancel();
+ }
+
if (mSocksSettingsDirty)
{
@@ -2334,6 +2344,11 @@ void LLFloaterPreferenceProxy::onBtnCancel()
cancel();
}
+void LLFloaterPreferenceProxy::onClickCloseBtn(bool app_quitting)
+{
+ cancel();
+}
+
void LLFloaterPreferenceProxy::cancel()
{
@@ -2344,7 +2359,7 @@ void LLFloaterPreferenceProxy::cancel()
LLSD ctrl_value = iter->second;
control->set(ctrl_value);
}
-
+ mSocksSettingsDirty = false;
closeFloater();
}
diff --git a/indra/newview/llfloaterpreference.h b/indra/newview/llfloaterpreference.h
index 7bf6ae7d79..04e5e37731 100755
--- a/indra/newview/llfloaterpreference.h
+++ b/indra/newview/llfloaterpreference.h
@@ -229,7 +229,7 @@ private:
//for "Only friends and groups can call or IM me"
static void showFriendsOnlyWarning(LLUICtrl*, const LLSD&);
//for "Show my Favorite Landmarks at Login"
- static void showFavoritesOnLoginWarning(LLUICtrl* checkbox, const LLSD& value);
+ static void handleFavoritesOnLoginChanged(LLUICtrl* checkbox, const LLSD& value);
typedef std::map<std::string, LLColor4> string_color_map_t;
string_color_map_t mSavedColors;
@@ -269,6 +269,7 @@ protected:
void saveSettings();
void onBtnOk();
void onBtnCancel();
+ void onClickCloseBtn(bool app_quitting = false);
void onChangeSocksSettings();
diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp
index 37e934429f..94f3a45d88 100755
--- a/indra/newview/llfloaterregioninfo.cpp
+++ b/indra/newview/llfloaterregioninfo.cpp
@@ -3586,29 +3586,6 @@ void LLPanelRegionExperiences::processResponse( const LLSD& content )
}
-
-class LLRegionExperienceResponder : public LLHTTPClient::Responder
-{
-public:
- typedef boost::function<void (const LLSD&)> callback_t;
-
- callback_t mCallback;
-
- LLRegionExperienceResponder(callback_t callback) : mCallback(callback) { }
-
-protected:
- /*virtual*/ void httpSuccess()
- {
- mCallback(getContent());
- }
-
- /*virtual*/ void httpFailure()
- {
- LL_WARNS() << "experience responder failed [status:" << getStatus() << "]: " << getContent() << LL_ENDL;
- }
-};
-
-
// Used for both access add and remove operations, depending on the flag
// passed in (ESTATE_EXPERIENCE_ALLOWED_ADD, ESTATE_EXPERIENCE_ALLOWED_REMOVE, etc.)
// static
@@ -3691,6 +3668,13 @@ void LLPanelRegionExperiences::infoCallback(LLHandle<LLPanelRegionExperiences> h
}
}
+/*static*/
+std::string LLPanelRegionExperiences::regionCapabilityQuery(LLViewerRegion* region, const std::string &cap)
+{
+ // region->getHandle() How to get a region * from a handle?
+
+ return region->getCapability(cap);
+}
bool LLPanelRegionExperiences::refreshFromRegion(LLViewerRegion* region)
{
@@ -3715,13 +3699,10 @@ bool LLPanelRegionExperiences::refreshFromRegion(LLViewerRegion* region)
mTrusted->loading();
mTrusted->setReadonly(!allow_modify);
- std::string url = region->getCapability("RegionExperiences");
- if (!url.empty())
- {
- LLHTTPClient::get(url, new LLRegionExperienceResponder(boost::bind(&LLPanelRegionExperiences::infoCallback,
- getDerivedHandle<LLPanelRegionExperiences>(), _1)));
- }
- return LLPanelRegionInfo::refreshFromRegion(region);
+ LLExperienceCache::instance().getRegionExperiences(boost::bind(&LLPanelRegionExperiences::regionCapabilityQuery, region, _1),
+ boost::bind(&LLPanelRegionExperiences::infoCallback, getDerivedHandle<LLPanelRegionExperiences>(), _1));
+
+ return LLPanelRegionInfo::refreshFromRegion(region);
}
LLSD LLPanelRegionExperiences::addIds(LLPanelExperienceListEditor* panel)
@@ -3739,18 +3720,15 @@ LLSD LLPanelRegionExperiences::addIds(LLPanelExperienceListEditor* panel)
BOOL LLPanelRegionExperiences::sendUpdate()
{
LLViewerRegion* region = gAgent.getRegion();
- std::string url = region->getCapability("RegionExperiences");
- if (!url.empty())
- {
- LLSD content;
- content["allowed"]=addIds(mAllowed);
- content["blocked"]=addIds(mBlocked);
- content["trusted"]=addIds(mTrusted);
+ LLSD content;
- LLHTTPClient::post(url, content, new LLRegionExperienceResponder(boost::bind(&LLPanelRegionExperiences::infoCallback,
- getDerivedHandle<LLPanelRegionExperiences>(), _1)));
- }
+ content["allowed"]=addIds(mAllowed);
+ content["blocked"]=addIds(mBlocked);
+ content["trusted"]=addIds(mTrusted);
+
+ LLExperienceCache::instance().setRegionExperiences(boost::bind(&LLPanelRegionExperiences::regionCapabilityQuery, region, _1),
+ content, boost::bind(&LLPanelRegionExperiences::infoCallback, getDerivedHandle<LLPanelRegionExperiences>(), _1));
return TRUE;
}
diff --git a/indra/newview/llfloaterregioninfo.h b/indra/newview/llfloaterregioninfo.h
index 90f115faaf..3c74618fff 100755
--- a/indra/newview/llfloaterregioninfo.h
+++ b/indra/newview/llfloaterregioninfo.h
@@ -479,6 +479,8 @@ public:
private:
void refreshRegionExperiences();
+ static std::string regionCapabilityQuery(LLViewerRegion* region, const std::string &cap);
+
LLPanelExperienceListEditor* setupList(const char* control_name, U32 add_id, U32 remove_id);
static LLSD addIds( LLPanelExperienceListEditor* panel );
diff --git a/indra/newview/llfloaterreporter.cpp b/indra/newview/llfloaterreporter.cpp
index 714d8d0e8f..ed6f4ede9f 100755
--- a/indra/newview/llfloaterreporter.cpp
+++ b/indra/newview/llfloaterreporter.cpp
@@ -35,6 +35,7 @@
#include "llassetstorage.h"
#include "llavatarnamecache.h"
#include "llcachename.h"
+#include "llcheckboxctrl.h"
#include "llfontgl.h"
#include "llimagej2c.h"
#include "llinventory.h"
@@ -191,6 +192,7 @@ BOOL LLFloaterReporter::postBuild()
mOwnerName = LLStringUtil::null;
getChild<LLUICtrl>("summary_edit")->setFocus(TRUE);
+ getChild<LLCheckBoxCtrl>("screen_check")->set(TRUE);
mDefaultSummary = getChild<LLUICtrl>("details_edit")->getValue().asString();
@@ -268,7 +270,7 @@ void LLFloaterReporter::getExperienceInfo(const LLUUID& experience_id)
if (LLUUID::null != mExperienceID)
{
- const LLSD& experience = LLExperienceCache::getInstance()->get(mExperienceID);
+ const LLSD& experience = LLExperienceCache::instance().get(mExperienceID);
std::stringstream desc;
if(experience.isDefined())
diff --git a/indra/newview/llfloaterscriptlimits.cpp b/indra/newview/llfloaterscriptlimits.cpp
index 14719a77f9..7b8fc5b35b 100755
--- a/indra/newview/llfloaterscriptlimits.cpp
+++ b/indra/newview/llfloaterscriptlimits.cpp
@@ -220,7 +220,7 @@ void LLPanelScriptLimitsRegionMemory::getLandScriptResourcesCoro(std::string url
postData["parcel_id"] = mParcelId;
- LLSD result = httpAdapter->postAndYield(httpRequest, url, postData);
+ LLSD result = httpAdapter->postAndSuspend(httpRequest, url, postData);
LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
@@ -260,7 +260,7 @@ void LLPanelScriptLimitsRegionMemory::getLandScriptSummaryCoro(std::string url)
httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("getLandScriptSummaryCoro", httpPolicy));
LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
- LLSD result = httpAdapter->getAndYield(httpRequest, url);
+ LLSD result = httpAdapter->getAndSuspend(httpRequest, url);
LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
@@ -312,7 +312,7 @@ void LLPanelScriptLimitsRegionMemory::getLandScriptDetailsCoro(std::string url)
httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("getLandScriptDetailsCoro", httpPolicy));
LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
- LLSD result = httpAdapter->getAndYield(httpRequest, url);
+ LLSD result = httpAdapter->getAndSuspend(httpRequest, url);
LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
@@ -963,7 +963,7 @@ void LLPanelScriptLimitsAttachment::getAttachmentLimitsCoro(std::string url)
httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("getAttachmentLimitsCoro", httpPolicy));
LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
- LLSD result = httpAdapter->getAndYield(httpRequest, url);
+ LLSD result = httpAdapter->getAndSuspend(httpRequest, url);
LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
diff --git a/indra/newview/llfloatersnapshot.cpp b/indra/newview/llfloatersnapshot.cpp
index 16fa4684ab..afec981d56 100755
--- a/indra/newview/llfloatersnapshot.cpp
+++ b/indra/newview/llfloatersnapshot.cpp
@@ -663,14 +663,20 @@ void LLFloaterSnapshot::Impl::onCommitFreezeFrame(LLUICtrl* ctrl, void* data)
{
LLCheckBoxCtrl* check_box = (LLCheckBoxCtrl*)ctrl;
LLFloaterSnapshot *view = (LLFloaterSnapshot *)data;
+ LLSnapshotLivePreview* previewp = getPreviewView(view);
- if (!view || !check_box)
+ if (!view || !check_box || !previewp)
{
return;
}
gSavedSettings.setBOOL("UseFreezeFrame", check_box->get());
+ if (check_box->get())
+ {
+ previewp->prepareFreezeFrame();
+ }
+
updateLayout(view);
}
diff --git a/indra/newview/llfloatertos.cpp b/indra/newview/llfloatertos.cpp
index 6dc08417d7..5fa4441914 100755
--- a/indra/newview/llfloatertos.cpp
+++ b/indra/newview/llfloatertos.cpp
@@ -44,6 +44,7 @@
#include "message.h"
#include "llstartup.h" // login_alert_done
#include "llcorehttputil.h"
+#include "llfloaterreg.h"
LLFloaterTOS::LLFloaterTOS(const LLSD& data)
: LLModalDialog( data["message"].asString() ),
@@ -88,6 +89,12 @@ BOOL LLFloaterTOS::postBuild()
// Don't use the start_url parameter for this browser instance -- it may finish loading before we get to add our observer.
// Store the URL separately and navigate here instead.
web_browser->navigateTo( getString( "loading_url" ) );
+ LLPluginClassMedia* media_plugin = web_browser->getMediaPlugin();
+ if (media_plugin)
+ {
+ // All links from tos_html should be opened in external browser
+ media_plugin->setOverrideClickTarget("_external");
+ }
}
return TRUE;
@@ -189,8 +196,10 @@ void LLFloaterTOS::handleMediaEvent(LLPluginClassMedia* /*self*/, EMediaEvent ev
mLoadingScreenLoaded = true;
std::string url(getString("real_url"));
+ LLHandle<LLFloater> handle = getHandle();
+
LLCoros::instance().launch("LLFloaterTOS::testSiteIsAliveCoro",
- boost::bind(&LLFloaterTOS::testSiteIsAliveCoro, this, url));
+ boost::bind(&LLFloaterTOS::testSiteIsAliveCoro, handle, url));
}
else if(mRealNavigateBegun)
{
@@ -202,7 +211,7 @@ void LLFloaterTOS::handleMediaEvent(LLPluginClassMedia* /*self*/, EMediaEvent ev
}
}
-void LLFloaterTOS::testSiteIsAliveCoro(std::string url)
+void LLFloaterTOS::testSiteIsAliveCoro(LLHandle<LLFloater> handle, std::string url)
{
LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
@@ -210,18 +219,31 @@ void LLFloaterTOS::testSiteIsAliveCoro(std::string url)
LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
LLCore::HttpOptions::ptr_t httpOpts = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions);
+
httpOpts->setWantHeaders(true);
- LL_INFOS("HttpCoroutineAdapter", "genericPostCoro") << "Generic POST for " << url << LL_ENDL;
- LLSD result = httpAdapter->getAndYield(httpRequest, url);
+ LL_INFOS("testSiteIsAliveCoro") << "Generic POST for " << url << LL_ENDL;
+
+ LLSD result = httpAdapter->getAndSuspend(httpRequest, url);
LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
- // double not.
- // First ! returns a boolean error status, second ! is true if success result.
- setSiteIsAlive(!!status);
+ if (handle.isDead())
+ {
+ LL_WARNS("testSiteIsAliveCoro") << "Dialog canceled before response." << LL_ENDL;
+ return;
+ }
+
+ LLFloaterTOS *that = dynamic_cast<LLFloaterTOS *>(handle.get());
+
+ if (that)
+ that->setSiteIsAlive(static_cast<bool>(status));
+ else
+ {
+ LL_WARNS("testSiteIsAliveCoro") << "Handle was not a TOS floater." << LL_ENDL;
+ }
}
diff --git a/indra/newview/llfloatertos.h b/indra/newview/llfloatertos.h
index 2748b20513..e70c9f24af 100755
--- a/indra/newview/llfloatertos.h
+++ b/indra/newview/llfloatertos.h
@@ -62,7 +62,7 @@ public:
/*virtual*/ void handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event);
private:
- void testSiteIsAliveCoro(std::string url);
+ static void testSiteIsAliveCoro(LLHandle<LLFloater> handle, std::string url);
std::string mMessage;
bool mLoadingScreenLoaded;
diff --git a/indra/newview/llfloatertranslationsettings.cpp b/indra/newview/llfloatertranslationsettings.cpp
index 965d29b09c..b1316e386d 100755
--- a/indra/newview/llfloatertranslationsettings.cpp
+++ b/indra/newview/llfloatertranslationsettings.cpp
@@ -42,41 +42,6 @@
#include "llnotificationsutil.h"
#include "llradiogroup.h"
-class EnteredKeyVerifier : public LLTranslate::KeyVerificationReceiver
-{
-public:
- EnteredKeyVerifier(LLTranslate::EService service, bool alert)
- : LLTranslate::KeyVerificationReceiver(service)
- , mAlert(alert)
- {
- }
-
-private:
- /*virtual*/ void setVerificationStatus(bool ok)
- {
- LLFloaterTranslationSettings* floater =
- LLFloaterReg::getTypedInstance<LLFloaterTranslationSettings>("prefs_translation");
-
- if (!floater)
- {
- LL_WARNS() << "Cannot find translation settings floater" << LL_ENDL;
- return;
- }
-
- switch (getService())
- {
- case LLTranslate::SERVICE_BING:
- floater->setBingVerified(ok, mAlert);
- break;
- case LLTranslate::SERVICE_GOOGLE:
- floater->setGoogleVerified(ok, mAlert);
- break;
- }
- }
-
- bool mAlert;
-};
-
LLFloaterTranslationSettings::LLFloaterTranslationSettings(const LLSD& key)
: LLFloater(key)
, mMachineTranslationCB(NULL)
@@ -231,11 +196,34 @@ void LLFloaterTranslationSettings::updateControlsEnabledState()
mOKBtn->setEnabled(!on || service_verified);
}
+/*static*/
+void LLFloaterTranslationSettings::setVerificationStatus(int service, bool ok, bool alert)
+{
+ LLFloaterTranslationSettings* floater =
+ LLFloaterReg::getTypedInstance<LLFloaterTranslationSettings>("prefs_translation");
+
+ if (!floater)
+ {
+ LL_WARNS() << "Cannot find translation settings floater" << LL_ENDL;
+ return;
+ }
+
+ switch (service)
+ {
+ case LLTranslate::SERVICE_BING:
+ floater->setBingVerified(ok, alert);
+ break;
+ case LLTranslate::SERVICE_GOOGLE:
+ floater->setGoogleVerified(ok, alert);
+ break;
+ }
+}
+
+
void LLFloaterTranslationSettings::verifyKey(int service, const std::string& key, bool alert)
{
- LLTranslate::KeyVerificationReceiverPtr receiver =
- new EnteredKeyVerifier((LLTranslate::EService) service, alert);
- LLTranslate::verifyKey(receiver, key);
+ LLTranslate::verifyKey(static_cast<LLTranslate::EService>(service), key,
+ boost::bind(&LLFloaterTranslationSettings::setVerificationStatus, _1, _2, alert));
}
void LLFloaterTranslationSettings::onEditorFocused(LLFocusableElement* control)
diff --git a/indra/newview/llfloatertranslationsettings.h b/indra/newview/llfloatertranslationsettings.h
index b9bfd6265a..2a15eacded 100755
--- a/indra/newview/llfloatertranslationsettings.h
+++ b/indra/newview/llfloatertranslationsettings.h
@@ -61,6 +61,8 @@ private:
void onBtnGoogleVerify();
void onBtnOK();
+ static void setVerificationStatus(int service, bool alert, bool ok);
+
LLCheckBoxCtrl* mMachineTranslationCB;
LLComboBox* mLanguageCombo;
LLLineEditor* mBingAPIKeyEditor;
diff --git a/indra/newview/llfloaterurlentry.cpp b/indra/newview/llfloaterurlentry.cpp
index 6683a6e6e6..f2efef0c33 100755
--- a/indra/newview/llfloaterurlentry.cpp
+++ b/indra/newview/llfloaterurlentry.cpp
@@ -220,7 +220,7 @@ void LLFloaterURLEntry::getMediaTypeCoro(std::string url, LLHandle<LLFloater> pa
LL_INFOS("HttpCoroutineAdapter", "genericPostCoro") << "Generic POST for " << url << LL_ENDL;
- LLSD result = httpAdapter->getAndYield(httpRequest, url, httpOpts);
+ LLSD result = httpAdapter->getAndSuspend(httpRequest, url, httpOpts);
LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
diff --git a/indra/newview/llfloaterworldmap.cpp b/indra/newview/llfloaterworldmap.cpp
index 1b1c24b19a..ece3e10faa 100755
--- a/indra/newview/llfloaterworldmap.cpp
+++ b/indra/newview/llfloaterworldmap.cpp
@@ -284,12 +284,12 @@ BOOL LLFloaterWorldMap::postBuild()
LLComboBox *avatar_combo = getChild<LLComboBox>("friend combo");
avatar_combo->selectFirstItem();
avatar_combo->setPrearrangeCallback( boost::bind(&LLFloaterWorldMap::onAvatarComboPrearrange, this) );
- avatar_combo->setTextEntryCallback( boost::bind(&LLFloaterWorldMap::onComboTextEntry, this) );
+ avatar_combo->setTextChangedCallback( boost::bind(&LLFloaterWorldMap::onComboTextEntry, this) );
mListFriendCombo = dynamic_cast<LLCtrlListInterface *>(avatar_combo);
LLSearchEditor *location_editor = getChild<LLSearchEditor>("location");
location_editor->setFocusChangedCallback(boost::bind(&LLFloaterWorldMap::onLocationFocusChanged, this, _1));
- location_editor->setKeystrokeCallback( boost::bind(&LLFloaterWorldMap::onSearchTextEntry, this));
+ location_editor->setTextChangedCallback( boost::bind(&LLFloaterWorldMap::onSearchTextEntry, this));
getChild<LLScrollListCtrl>("search_results")->setDoubleClickCallback( boost::bind(&LLFloaterWorldMap::onClickTeleportBtn, this));
mListSearchResults = childGetListInterface("search_results");
@@ -297,7 +297,7 @@ BOOL LLFloaterWorldMap::postBuild()
LLComboBox *landmark_combo = getChild<LLComboBox>( "landmark combo");
landmark_combo->selectFirstItem();
landmark_combo->setPrearrangeCallback( boost::bind(&LLFloaterWorldMap::onLandmarkComboPrearrange, this) );
- landmark_combo->setTextEntryCallback( boost::bind(&LLFloaterWorldMap::onComboTextEntry, this) );
+ landmark_combo->setTextChangedCallback( boost::bind(&LLFloaterWorldMap::onComboTextEntry, this) );
mListLandmarkCombo = dynamic_cast<LLCtrlListInterface *>(landmark_combo);
mCurZoomVal = log(LLWorldMapView::sMapScale)/log(2.f);
diff --git a/indra/newview/llfolderviewmodelinventory.cpp b/indra/newview/llfolderviewmodelinventory.cpp
index 44eda4d6c0..e9f80b795a 100755
--- a/indra/newview/llfolderviewmodelinventory.cpp
+++ b/indra/newview/llfolderviewmodelinventory.cpp
@@ -109,6 +109,29 @@ bool LLFolderViewModelInventory::contentsReady()
return !LLInventoryModelBackgroundFetch::instance().folderFetchActive();
}
+bool LLFolderViewModelInventory::isFolderComplete(LLFolderViewFolder* folder)
+{
+ LLFolderViewModelItemInventory* modelp = static_cast<LLFolderViewModelItemInventory*>(folder->getViewModelItem());
+ LLUUID cat_id = modelp->getUUID();
+ if (cat_id.isNull())
+ {
+ return false;
+ }
+ LLViewerInventoryCategory* cat = gInventory.getCategory(cat_id);
+ if (cat)
+ {
+ // don't need to check version - descendents_server == -1 if we have no data
+ S32 descendents_server = cat->getDescendentCount();
+ S32 descendents_actual = cat->getViewerDescendentCount();
+ if (descendents_server == descendents_actual
+ || (descendents_actual > 0 && descendents_server == -1)) // content was loaded in previous session
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
void LLFolderViewModelItemInventory::requestSort()
{
LLFolderViewModelItemCommon::requestSort();
diff --git a/indra/newview/llfolderviewmodelinventory.h b/indra/newview/llfolderviewmodelinventory.h
index 0516fc3b4b..dea54cbe57 100755
--- a/indra/newview/llfolderviewmodelinventory.h
+++ b/indra/newview/llfolderviewmodelinventory.h
@@ -115,6 +115,7 @@ public:
void sort(LLFolderViewFolder* folder);
bool contentsReady();
+ bool isFolderComplete(LLFolderViewFolder* folder);
bool startDrag(std::vector<LLFolderViewModelItem*>& items);
private:
diff --git a/indra/newview/llgroupmgr.cpp b/indra/newview/llgroupmgr.cpp
index eda9e51d23..def0f72433 100755
--- a/indra/newview/llgroupmgr.cpp
+++ b/indra/newview/llgroupmgr.cpp
@@ -41,7 +41,6 @@
#include "llui.h"
#include "message.h"
#include "roles_constants.h"
-#include "llhttpclient.h"
#include "lltransactiontypes.h"
#include "llstatusbar.h"
#include "lleconomy.h"
@@ -240,7 +239,8 @@ LLGroupMgrGroupData::LLGroupMgrGroupData(const LLUUID& id) :
mRoleMemberDataComplete(false),
mGroupPropertiesDataComplete(false),
mPendingRoleMemberRequest(false),
- mAccessTime(0.0f)
+ mAccessTime(0.0f),
+ mPendingBanRequest(false)
{
mMemberVersion.generate();
}
@@ -762,8 +762,69 @@ void LLGroupMgrGroupData::removeBanEntry(const LLUUID& ban_id)
mBanList.erase(ban_id);
}
+void LLGroupMgrGroupData::banMemberById(const LLUUID& participant_uuid)
+{
+ if (!mMemberDataComplete ||
+ !mRoleDataComplete ||
+ !(mRoleMemberDataComplete && mMembers.size()))
+ {
+ LL_WARNS() << "No Role-Member data yet, setting ban request to pending." << LL_ENDL;
+ mPendingBanRequest = true;
+ mPendingBanMemberID = participant_uuid;
+ if (!mMemberDataComplete)
+ {
+ LLGroupMgr::getInstance()->sendCapGroupMembersRequest(mID);
+ }
+ if (!mRoleDataComplete)
+ {
+ LLGroupMgr::getInstance()->sendGroupRoleDataRequest(mID);
+ }
+
+ return;
+ }
+
+ LLGroupMgrGroupData::member_list_t::iterator mi = mMembers.find((participant_uuid));
+ if (mi == mMembers.end())
+ {
+ if (!mPendingBanRequest)
+ {
+ mPendingBanRequest = true;
+ mPendingBanMemberID = participant_uuid;
+ LLGroupMgr::getInstance()->sendCapGroupMembersRequest(mID); // member isn't in members list, request reloading
+ }
+ else
+ {
+ mPendingBanRequest = false;
+ }
+
+ return;
+ }
+
+ mPendingBanRequest = false;
+
+ LLGroupMemberData* member_data = (*mi).second;
+ if (member_data && member_data->isInRole(mOwnerRole))
+ {
+ return; // can't ban group owner
+ }
+
+ std::vector<LLUUID> ids;
+ ids.push_back(participant_uuid);
+
+ LLGroupBanData ban_data;
+ createBanEntry(participant_uuid, ban_data);
+ LLGroupMgr::getInstance()->sendGroupBanRequest(LLGroupMgr::REQUEST_POST, mID, LLGroupMgr::BAN_CREATE, ids);
+ LLGroupMgr::getInstance()->sendGroupMemberEjects(mID, ids);
+ LLGroupMgr::getInstance()->sendGroupMembersRequest(mID);
+ LLSD args;
+ std::string name;
+ gCacheName->getFullName(participant_uuid, name);
+ args["AVATAR_NAME"] = name;
+ args["GROUP_NAME"] = mName;
+ LLNotifications::instance().add(LLNotification::Params("EjectAvatarFromGroup").substitutions(args));
+}
//
// LLGroupMgr
@@ -1246,6 +1307,11 @@ void LLGroupMgr::processGroupRoleMembersReply(LLMessageSystem* msg, void** data)
group_datap->mChanged = TRUE;
LLGroupMgr::getInstance()->notifyObservers(GC_ROLE_MEMBER_DATA);
+
+ if (group_datap->mPendingBanRequest)
+ {
+ group_datap->banMemberById(group_datap->mPendingBanMemberID);
+ }
}
// static
@@ -1871,7 +1937,7 @@ void LLGroupMgr::getGroupBanRequestCoro(std::string url, LLUUID groupId)
std::string finalUrl = url + "?group_id=" + groupId.asString();
- LLSD result = httpAdapter->getAndYield(httpRequest, finalUrl);
+ LLSD result = httpAdapter->getAndSuspend(httpRequest, finalUrl);
LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
@@ -1922,7 +1988,7 @@ void LLGroupMgr::postGroupBanRequestCoro(std::string url, LLUUID groupId,
LL_WARNS() << "post: " << ll_pretty_print_sd(postData) << LL_ENDL;
- LLSD result = httpAdapter->postAndYield(httpRequest, finalUrl, postData, httpOptions, httpHeaders);
+ LLSD result = httpAdapter->postAndSuspend(httpRequest, finalUrl, postData, httpOptions, httpHeaders);
LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
@@ -2042,7 +2108,7 @@ void LLGroupMgr::groupMembersRequestCoro(std::string url, LLUUID groupId)
LLSD postData = LLSD::emptyMap();
postData["group_id"] = groupId;
- LLSD result = httpAdapter->postAndYield(httpRequest, url, postData, httpOpts);
+ LLSD result = httpAdapter->postAndSuspend(httpRequest, url, postData, httpOpts);
LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
@@ -2109,11 +2175,6 @@ void LLGroupMgr::processCapGroupMembersRequest(const LLSD& content)
return;
}
- // If we have no members, there's no reason to do anything else
- S32 num_members = content["member_count"];
- if(num_members < 1)
- return;
-
LLUUID group_id = content["group_id"].asUUID();
LLGroupMgrGroupData* group_datap = getGroupData(group_id);
@@ -2123,6 +2184,18 @@ void LLGroupMgr::processCapGroupMembersRequest(const LLSD& content)
return;
}
+ // If we have no members, there's no reason to do anything else
+ S32 num_members = content["member_count"];
+ if (num_members < 1)
+ {
+ LL_INFOS("GrpMgr") << "Received empty group members list for group id: " << group_id.asString() << LL_ENDL;
+ // Set mMemberDataComplete for correct handling of empty responses. See MAINT-5237
+ group_datap->mMemberDataComplete = true;
+ group_datap->mChanged = TRUE;
+ LLGroupMgr::getInstance()->notifyObservers(GC_MEMBER_DATA);
+ return;
+ }
+
group_datap->mMemberCount = num_members;
LLSD member_list = content["members"];
diff --git a/indra/newview/llgroupmgr.h b/indra/newview/llgroupmgr.h
index fd0c2de854..e5ce768035 100755
--- a/indra/newview/llgroupmgr.h
+++ b/indra/newview/llgroupmgr.h
@@ -151,7 +151,7 @@ public:
const uuid_vec_t& getRoleMembers() const { return mMemberIDs; }
S32 getMembersInRole(uuid_vec_t members, BOOL needs_sort = TRUE);
- S32 getTotalMembersInRole() { return mMemberIDs.size(); }
+ S32 getTotalMembersInRole() { return mMemberCount ? mMemberCount : mMemberIDs.size(); } //FIXME: Returns 0 for Everyone role when Member list isn't yet loaded, see MAINT-5225
LLRoleData getRoleData() const { return mRoleData; }
void setRoleData(LLRoleData data) { mRoleData = data; }
@@ -271,8 +271,8 @@ public:
void createBanEntry(const LLUUID& ban_id, const LLGroupBanData& ban_data = LLGroupBanData());
void removeBanEntry(const LLUUID& ban_id);
+ void banMemberById(const LLUUID& participant_uuid);
-
public:
typedef std::map<LLUUID,LLGroupMemberData*> member_list_t;
typedef std::map<LLUUID,LLGroupRoleData*> role_list_t;
@@ -304,6 +304,9 @@ public:
S32 mMemberCount;
S32 mRoleCount;
+ bool mPendingBanRequest;
+ LLUUID mPendingBanMemberID;
+
protected:
void sendRoleChanges();
void cancelRoleChanges();
diff --git a/indra/newview/llhttpretrypolicy.cpp b/indra/newview/llhttpretrypolicy.cpp
index e2e151eb63..6a2daeeb90 100755
--- a/indra/newview/llhttpretrypolicy.cpp
+++ b/indra/newview/llhttpretrypolicy.cpp
@@ -25,9 +25,23 @@
*/
#include "llviewerprecompiledheaders.h"
-
#include "llhttpretrypolicy.h"
+namespace
+{
+ // Moved from httpconstants.h... only used in this file.
+ bool isHttpServerErrorStatus(S32 status)
+ {
+ // Status 499 is sometimes used for re-interpreted status 2xx errors.
+ // Allow retry of these, since we don't have enough information in this
+ // context to know if this will always fail.
+ if (HTTP_INTERNAL_ERROR == status) return true;
+
+ // Check for status 5xx.
+ return((500 <= status) && (status < 600));
+ }
+}
+
LLAdaptiveRetryPolicy::LLAdaptiveRetryPolicy(F32 min_delay, F32 max_delay, F32 backoff_factor, U32 max_retries, bool retry_on_4xx):
mMinDelay(min_delay),
mMaxDelay(max_delay),
@@ -140,3 +154,34 @@ bool LLAdaptiveRetryPolicy::shouldRetry(F32& seconds_to_wait) const
seconds_to_wait = mShouldRetry ? (F32) mRetryTimer.getRemainingTimeF32() : F32_MAX;
return mShouldRetry;
}
+
+// Moved from httpconstants. Only used by this file.
+// Parses 'Retry-After' header contents and returns seconds until retry should occur.
+/*static*/
+bool LLAdaptiveRetryPolicy::getSecondsUntilRetryAfter(const std::string& retry_after, F32& seconds_to_wait)
+{
+ // *TODO: This needs testing! Not in use yet.
+ // Examples of Retry-After headers:
+ // Retry-After: Fri, 31 Dec 1999 23:59:59 GMT
+ // Retry-After: 120
+
+ // Check for number of seconds version, first:
+ char* end = 0;
+ // Parse as double
+ double seconds = std::strtod(retry_after.c_str(), &end);
+ if (end != 0 && *end == 0)
+ {
+ // Successful parse
+ seconds_to_wait = (F32)seconds;
+ return true;
+ }
+
+ // Parse rfc1123 date.
+ time_t date = curl_getdate(retry_after.c_str(), NULL);
+ if (-1 == date) return false;
+
+ seconds_to_wait = (F64)date - LLTimer::getTotalSeconds();
+
+ return true;
+}
+
diff --git a/indra/newview/llhttpretrypolicy.h b/indra/newview/llhttpretrypolicy.h
index c0cc263546..af07b4afec 100755
--- a/indra/newview/llhttpretrypolicy.h
+++ b/indra/newview/llhttpretrypolicy.h
@@ -76,6 +76,8 @@ public:
// virtual
bool shouldRetry(F32& seconds_to_wait) const;
+ static bool getSecondsUntilRetryAfter(const std::string& retry_after, F32& seconds_to_wait);
+
protected:
void init();
bool getRetryAfter(const LLSD& headers, F32& retry_header_time);
diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp
index 74f1cd0673..53b97a58c5 100755
--- a/indra/newview/llimview.cpp
+++ b/indra/newview/llimview.cpp
@@ -402,7 +402,7 @@ void startConfrenceCoro(std::string url,
postData["session-id"] = tempSessionId;
postData["params"] = agents;
- LLSD result = httpAdapter->postAndYield(httpRequest, url, postData);
+ LLSD result = httpAdapter->postAndSuspend(httpRequest, url, postData);
LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
@@ -441,7 +441,7 @@ void chatterBoxInvitationCoro(std::string url, LLUUID sessionId, LLIMMgr::EInvit
postData["method"] = "accept invitation";
postData["session-id"] = sessionId;
- LLSD result = httpAdapter->postAndYield(httpRequest, url, postData);
+ LLSD result = httpAdapter->postAndSuspend(httpRequest, url, postData);
LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index 605f71f412..58411af089 100755
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -121,12 +121,7 @@ bool isAddAction(const std::string& action)
bool isRemoveAction(const std::string& action)
{
- return ("take_off" == action || "detach" == action || "deactivate" == action);
-}
-
-bool isMarketplaceCopyAction(const std::string& action)
-{
- return (("copy_to_outbox" == action) || ("move_to_outbox" == action));
+ return ("take_off" == action || "detach" == action);
}
bool isMarketplaceSendAction(const std::string& action)
@@ -777,14 +772,6 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id,
{
items.push_back(std::string("Marketplace Separator"));
- if (gMenuHolder->getChild<LLView>("MerchantOutbox")->getVisible())
- {
- items.push_back(std::string("Merchant Copy"));
- if (!canListOnOutboxNow())
- {
- disabled_items.push_back(std::string("Merchant Copy"));
- }
- }
if (gMenuHolder->getChild<LLView>("MarketplaceListings")->getVisible())
{
items.push_back(std::string("Marketplace Copy"));
@@ -799,8 +786,8 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id,
}
}
- // Don't allow items to be pasted directly into the COF or the inbox/outbox
- if (!isCOFFolder() && !isInboxFolder() && !isOutboxFolder())
+ // Don't allow items to be pasted directly into the COF or the inbox
+ if (!isCOFFolder() && !isInboxFolder())
{
items.push_back(std::string("Paste"));
}
@@ -838,10 +825,6 @@ void LLInvFVBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
{
addTrashContextMenuOptions(items, disabled_items);
}
- else if(isOutboxFolder())
- {
- addOutboxContextMenuOptions(flags, items, disabled_items);
- }
else
{
items.push_back(std::string("Share"));
@@ -915,15 +898,7 @@ void LLInvFVBridge::addDeleteContextMenuOptions(menuentry_vec_t &items,
return;
}
- // "Remove link" and "Delete" are the same operation.
- if (obj && obj->getIsLinkType() && !get_is_item_worn(mUUID))
- {
- items.push_back(std::string("Remove Link"));
- }
- else
- {
- items.push_back(std::string("Delete"));
- }
+ items.push_back(std::string("Delete"));
if (!isItemRemovable())
{
@@ -942,19 +917,6 @@ void LLInvFVBridge::addOpenRightClickMenuOption(menuentry_vec_t &items)
items.push_back(std::string("Open"));
}
-void LLInvFVBridge::addOutboxContextMenuOptions(U32 flags,
- menuentry_vec_t &items,
- menuentry_vec_t &disabled_items)
-{
- items.push_back(std::string("Rename"));
- items.push_back(std::string("Delete"));
-
- if ((flags & FIRST_SELECTED_ITEM) == 0)
- {
- disabled_items.push_back(std::string("Rename"));
- }
-}
-
void LLInvFVBridge::addMarketplaceContextMenuOptions(U32 flags,
menuentry_vec_t &items,
menuentry_vec_t &disabled_items)
@@ -1204,41 +1166,6 @@ BOOL LLInvFVBridge::isMarketplaceListingsFolder() const
return gInventory.isObjectDescendentOf(mUUID, folder_id);
}
-BOOL LLInvFVBridge::isOutboxFolder() const
-{
- const LLUUID outbox_id = getOutboxFolder();
-
- if (outbox_id.isNull())
- {
- return FALSE;
- }
-
- return gInventory.isObjectDescendentOf(mUUID, outbox_id);
-}
-
-BOOL LLInvFVBridge::isOutboxFolderDirectParent() const
-{
- BOOL outbox_is_parent = FALSE;
-
- const LLInventoryCategory *cat = gInventory.getCategory(mUUID);
-
- if (cat)
- {
- const LLUUID outbox_id = getOutboxFolder();
-
- outbox_is_parent = (outbox_id.notNull() && (outbox_id == cat->getParentUUID()));
- }
-
- return outbox_is_parent;
-}
-
-const LLUUID LLInvFVBridge::getOutboxFolder() const
-{
- const LLUUID outbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false);
-
- return outbox_id;
-}
-
BOOL LLInvFVBridge::isItemPermissive() const
{
return FALSE;
@@ -1495,56 +1422,6 @@ bool LLInvFVBridge::canListOnMarketplace() const
return true;
}
-// *TODO : Suppress canListOnOutboxNow() once we deprecate Merchant Outbox completely
-bool LLInvFVBridge::canListOnOutboxNow() const
-{
- bool can_list = true;
-
- // Do not allow listing while import is in progress
- if (LLMarketplaceInventoryImporter::instanceExists())
- {
- can_list = !LLMarketplaceInventoryImporter::instance().isImportInProgress();
- }
-
- const LLInventoryObject* obj = getInventoryObject();
- can_list &= (obj != NULL);
-
- if (can_list)
- {
- const LLUUID& object_id = obj->getLinkedUUID();
- can_list = object_id.notNull();
-
- if (can_list)
- {
- LLFolderViewFolder * object_folderp = mInventoryPanel.get() ? mInventoryPanel.get()->getFolderByID(object_id) : NULL;
- if (object_folderp)
- {
- can_list = !static_cast<LLFolderBridge*>(object_folderp->getViewModelItem())->isLoading();
- }
- }
-
- if (can_list)
- {
- // Get outbox id
- const LLUUID & outbox_id = getInventoryModel()->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false);
- LLFolderViewItem * outbox_itemp = mInventoryPanel.get() ? mInventoryPanel.get()->getItemByID(outbox_id) : NULL;
-
- if (outbox_itemp)
- {
- MASK mask = 0x0;
- BOOL drop = FALSE;
- EDragAndDropType cargo_type = LLViewerAssetType::lookupDragAndDropType(obj->getActualType());
- void * cargo_data = (void *) obj;
- std::string tooltip_msg;
-
- can_list = outbox_itemp->getViewModelItem()->dragOrDrop(mask, drop, cargo_type, cargo_data, tooltip_msg);
- }
- }
- }
-
- return can_list;
-}
-
bool LLInvFVBridge::canListOnMarketplaceNow() const
{
bool can_list = true;
@@ -1714,16 +1591,6 @@ void LLItemBridge::performAction(LLInventoryModel* model, std::string action)
folder_view_itemp->getViewModelItem()->pasteLinkFromClipboard();
return;
}
- else if (isMarketplaceCopyAction(action))
- {
- LL_INFOS() << "Copy item to marketplace action!" << LL_ENDL;
-
- LLInventoryItem* itemp = model->getItem(mUUID);
- if (!itemp) return;
-
- const LLUUID outbox_id = getInventoryModel()->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false);
- copy_item_to_outbox(itemp, outbox_id, LLUUID::null, LLToolDragAndDrop::getOperationId());
- }
else if (("move_to_marketplace_listings" == action) || ("copy_to_marketplace_listings" == action) || ("copy_or_move_to_marketplace_listings" == action))
{
LLInventoryItem* itemp = model->getItem(mUUID);
@@ -1810,7 +1677,9 @@ void LLItemBridge::restoreItem()
if(item)
{
LLInventoryModel* model = getInventoryModel();
- const LLUUID new_parent = model->findCategoryUUIDForType(LLFolderType::assetTypeToFolderType(item->getType()));
+ bool is_snapshot = (item->getInventoryType() == LLInventoryType::IT_SNAPSHOT);
+
+ const LLUUID new_parent = model->findCategoryUUIDForType(is_snapshot? LLFolderType::FT_SNAPSHOT_CATEGORY : LLFolderType::assetTypeToFolderType(item->getType()));
// do not restamp on restore.
LLInvFVBridge::changeItemParent(model, item, new_parent, FALSE);
}
@@ -2437,7 +2306,8 @@ BOOL LLFolderBridge::isClipboardPasteableAsLink() const
BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
BOOL drop,
std::string& tooltip_msg,
- BOOL user_confirm)
+ BOOL is_link,
+ BOOL user_confirm)
{
LLInventoryModel* model = getInventoryModel();
@@ -2455,13 +2325,10 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
const LLUUID &cat_id = inv_cat->getUUID();
const LLUUID &current_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, false);
- const LLUUID &outbox_id = model->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false);
const LLUUID &marketplacelistings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false);
const LLUUID from_folder_uuid = inv_cat->getParentUUID();
const BOOL move_is_into_current_outfit = (mUUID == current_outfit_id);
- const BOOL move_is_into_outbox = model->isObjectDescendentOf(mUUID, outbox_id);
- const BOOL move_is_from_outbox = model->isObjectDescendentOf(cat_id, outbox_id);
const BOOL move_is_into_marketplacelistings = model->isObjectDescendentOf(mUUID, marketplacelistings_id);
const BOOL move_is_from_marketplacelistings = model->isObjectDescendentOf(cat_id, marketplacelistings_id);
@@ -2483,6 +2350,7 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
const BOOL move_is_into_trash = (mUUID == trash_id) || model->isObjectDescendentOf(mUUID, trash_id);
const BOOL move_is_into_my_outfits = (mUUID == my_outifts_id) || model->isObjectDescendentOf(mUUID, my_outifts_id);
const BOOL move_is_into_outfit = move_is_into_my_outfits || (getCategory() && getCategory()->getPreferredType()==LLFolderType::FT_OUTFIT);
+ const BOOL move_is_into_current_outfit = (getCategory() && getCategory()->getPreferredType()==LLFolderType::FT_CURRENT_OUTFIT);
const BOOL move_is_into_landmarks = (mUUID == landmarks_id) || model->isObjectDescendentOf(mUUID, landmarks_id);
//--------------------------------------------------------------------------------
@@ -2520,8 +2388,18 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
}
if (is_movable && move_is_into_outfit)
{
+ if((mUUID == my_outifts_id) || (getCategory() && getCategory()->getPreferredType() == LLFolderType::FT_NONE))
+ {
+ is_movable = ((inv_cat->getPreferredType() == LLFolderType::FT_NONE) || (inv_cat->getPreferredType() == LLFolderType::FT_OUTFIT));
+ }
+ else
+ {
+ is_movable = false;
+ }
+ }
+ if(is_movable && move_is_into_current_outfit && is_link)
+ {
is_movable = FALSE;
- // tooltip?
}
if (is_movable && (mUUID == model->findCategoryUUIDForType(LLFolderType::FT_FAVORITE)))
{
@@ -2602,9 +2480,9 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
}
}
- if (is_movable && (move_is_into_outbox || move_is_into_marketplacelistings))
+ if (is_movable && move_is_into_marketplacelistings)
{
- const LLViewerInventoryCategory * master_folder = (move_is_into_outbox ? model->getFirstDescendantOf(outbox_id, mUUID) : model->getFirstDescendantOf(marketplacelistings_id, mUUID));
+ const LLViewerInventoryCategory * master_folder = model->getFirstDescendantOf(marketplacelistings_id, mUUID);
LLViewerInventoryCategory * dest_folder = getCategory();
S32 bundle_size = (drop ? 1 : LLToolDragAndDrop::instance().getCargoCount());
is_movable = can_move_folder_to_marketplace(master_folder, dest_folder, inv_cat, tooltip_msg, bundle_size);
@@ -2705,18 +2583,16 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
}
}
}
+
// if target is current outfit folder we use link
if (move_is_into_current_outfit &&
- inv_cat->getPreferredType() == LLFolderType::FT_NONE)
+ (inv_cat->getPreferredType() == LLFolderType::FT_NONE ||
+ inv_cat->getPreferredType() == LLFolderType::FT_OUTFIT))
{
// traverse category and add all contents to currently worn.
BOOL append = true;
LLAppearanceMgr::instance().wearInventoryCategory(inv_cat, false, append);
}
- else if (move_is_into_outbox && !move_is_from_outbox)
- {
- copy_folder_to_outbox(inv_cat, mUUID, cat_id, LLToolDragAndDrop::getOperationId());
- }
else if (move_is_into_marketplacelistings)
{
move_folder_to_marketplacelistings(inv_cat, mUUID);
@@ -2767,7 +2643,7 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
}
else if (LLToolDragAndDrop::SOURCE_WORLD == source)
{
- if (move_is_into_outbox || move_is_into_marketplacelistings)
+ if (move_is_into_marketplacelistings)
{
tooltip_msg = LLTrans::getString("TooltipOutboxNotInInventory");
accept = FALSE;
@@ -2779,7 +2655,7 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
}
else if (LLToolDragAndDrop::SOURCE_LIBRARY == source)
{
- if (move_is_into_outbox || move_is_into_marketplacelistings)
+ if (move_is_into_marketplacelistings)
{
tooltip_msg = LLTrans::getString("TooltipOutboxNotInInventory");
accept = FALSE;
@@ -3296,16 +3172,6 @@ void LLFolderBridge::performAction(LLInventoryModel* model, std::string action)
removeSystemFolder();
}
#endif
- else if (isMarketplaceCopyAction(action))
- {
- LL_INFOS() << "Copy folder to marketplace action!" << LL_ENDL;
-
- LLInventoryCategory * cat = gInventory.getCategory(mUUID);
- if (!cat) return;
-
- const LLUUID outbox_id = getInventoryModel()->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false);
- copy_folder_to_outbox(cat, outbox_id, cat->getUUID(), LLToolDragAndDrop::getOperationId());
- }
else if (("move_to_marketplace_listings" == action) || ("copy_to_marketplace_listings" == action) || ("copy_or_move_to_marketplace_listings" == action))
{
LLInventoryCategory * cat = gInventory.getCategory(mUUID);
@@ -3546,7 +3412,6 @@ void LLFolderBridge::perform_pasteFromClipboard()
if (model && isClipboardPasteable())
{
const LLUUID &current_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, false);
- const LLUUID &outbox_id = model->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false);
const LLUUID &marketplacelistings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false);
const LLUUID &favorites_id = model->findCategoryUUIDForType(LLFolderType::FT_FAVORITE, false);
const LLUUID &my_outifts_id = model->findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS, false);
@@ -3554,7 +3419,6 @@ void LLFolderBridge::perform_pasteFromClipboard()
const BOOL move_is_into_current_outfit = (mUUID == current_outfit_id);
const BOOL move_is_into_my_outfits = (mUUID == my_outifts_id) || model->isObjectDescendentOf(mUUID, my_outifts_id);
const BOOL move_is_into_outfit = move_is_into_my_outfits || (getCategory() && getCategory()->getPreferredType()==LLFolderType::FT_OUTFIT);
- const BOOL move_is_into_outbox = model->isObjectDescendentOf(mUUID, outbox_id);
const BOOL move_is_into_marketplacelistings = model->isObjectDescendentOf(mUUID, marketplacelistings_id);
const BOOL move_is_into_favorites = (mUUID == favorites_id);
@@ -3562,10 +3426,10 @@ void LLFolderBridge::perform_pasteFromClipboard()
LLClipboard::instance().pasteFromClipboard(objects);
LLViewerInventoryCategory * dest_folder = getCategory();
- if (move_is_into_outbox || move_is_into_marketplacelistings)
+ if (move_is_into_marketplacelistings)
{
std::string error_msg;
- const LLViewerInventoryCategory * master_folder = (move_is_into_outbox ? model->getFirstDescendantOf(outbox_id, mUUID) : model->getFirstDescendantOf(marketplacelistings_id, mUUID));
+ const LLViewerInventoryCategory * master_folder = model->getFirstDescendantOf(marketplacelistings_id, mUUID);
int index = 0;
for (std::vector<LLUUID>::const_iterator iter = objects.begin(); iter != objects.end(); ++iter)
{
@@ -3744,17 +3608,15 @@ void LLFolderBridge::pasteLinkFromClipboard()
if(model)
{
const LLUUID &current_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, false);
- const LLUUID &outbox_id = model->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false);
const LLUUID &marketplacelistings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false);
const LLUUID &my_outifts_id = model->findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS, false);
const BOOL move_is_into_current_outfit = (mUUID == current_outfit_id);
const BOOL move_is_into_my_outfits = (mUUID == my_outifts_id) || model->isObjectDescendentOf(mUUID, my_outifts_id);
const BOOL move_is_into_outfit = move_is_into_my_outfits || (getCategory() && getCategory()->getPreferredType()==LLFolderType::FT_OUTFIT);
- const BOOL move_is_into_outbox = model->isObjectDescendentOf(mUUID, outbox_id);
const BOOL move_is_into_marketplacelistings = model->isObjectDescendentOf(mUUID, marketplacelistings_id);
- if (move_is_into_outbox || move_is_into_marketplacelistings)
+ if (move_is_into_marketplacelistings)
{
// Notify user of failure somehow -- play error sound? modal dialog?
return;
@@ -3875,10 +3737,6 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items
items.clear(); // clear any items that used to exist
addTrashContextMenuOptions(items, disabled_items);
}
- else if(isOutboxFolder())
- {
- addOutboxContextMenuOptions(flags, items, disabled_items);
- }
else if(isAgentInventory()) // do not allow creating in library
{
LLViewerInventoryCategory *cat = getCategory();
@@ -3886,7 +3744,7 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items
// Not sure what the right thing is to do here.
if (!isCOFFolder() && cat && (cat->getPreferredType() != LLFolderType::FT_OUTFIT))
{
- if (!isInboxFolder() && !isOutboxFolder()) // don't allow creation in inbox or outbox
+ if (!isInboxFolder()) // don't allow creation in inbox
{
// Do not allow to create 2-level subfolder in the Calling Card/Friends folder. EXT-694.
if (!LLFriendCardsManager::instance().isCategoryInFriendFolder(cat))
@@ -3948,7 +3806,7 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items
disabled_items.push_back(std::string("Delete System Folder"));
}
- if (!isOutboxFolder() && !isMarketplaceListingsFolder())
+ if (!isMarketplaceListingsFolder())
{
items.push_back(std::string("Share"));
if (!canShare())
@@ -3994,7 +3852,6 @@ void LLFolderBridge::buildContextMenuFolderOptions(U32 flags, menuentry_vec_t&
if (trash_id == mUUID) return;
if (isItemInTrash()) return;
if (!isAgentInventory()) return;
- if (isOutboxFolder()) return;
if (!isItemRemovable())
{
@@ -4141,7 +3998,7 @@ BOOL LLFolderBridge::dragOrDrop(MASK mask, BOOL drop,
LLInventoryCategory* linked_category = gInventory.getCategory(inv_item->getLinkedUUID());
if (linked_category)
{
- accept = dragCategoryIntoFolder((LLInventoryCategory*)linked_category, drop, tooltip_msg);
+ accept = dragCategoryIntoFolder((LLInventoryCategory*)linked_category, drop, tooltip_msg, TRUE);
}
}
else
@@ -4561,7 +4418,7 @@ void LLFolderBridge::callback_dropCategoryIntoFolder(const LLSD& notification, c
if (option == 0) // YES
{
std::string tooltip_msg;
- dragCategoryIntoFolder(inv_category, TRUE, tooltip_msg, FALSE);
+ dragCategoryIntoFolder(inv_category, TRUE, tooltip_msg, FALSE, FALSE);
}
}
@@ -4588,7 +4445,6 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
const LLUUID &current_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, false);
const LLUUID &favorites_id = model->findCategoryUUIDForType(LLFolderType::FT_FAVORITE, false);
const LLUUID &landmarks_id = model->findCategoryUUIDForType(LLFolderType::FT_LANDMARK, false);
- const LLUUID &outbox_id = model->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false);
const LLUUID &marketplacelistings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false);
const LLUUID &my_outifts_id = model->findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS, false);
const LLUUID from_folder_uuid = inv_item->getParentUUID();
@@ -4598,8 +4454,6 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
const BOOL move_is_into_my_outfits = (mUUID == my_outifts_id) || model->isObjectDescendentOf(mUUID, my_outifts_id);
const BOOL move_is_into_outfit = move_is_into_my_outfits || (getCategory() && getCategory()->getPreferredType()==LLFolderType::FT_OUTFIT);
const BOOL move_is_into_landmarks = (mUUID == landmarks_id) || model->isObjectDescendentOf(mUUID, landmarks_id);
- const BOOL move_is_into_outbox = model->isObjectDescendentOf(mUUID, outbox_id);
- const BOOL move_is_from_outbox = model->isObjectDescendentOf(inv_item->getUUID(), outbox_id);
const BOOL move_is_into_marketplacelistings = model->isObjectDescendentOf(mUUID, marketplacelistings_id);
const BOOL move_is_from_marketplacelistings = model->isObjectDescendentOf(inv_item->getUUID(), marketplacelistings_id);
@@ -4675,9 +4529,9 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
{
accept = can_move_to_landmarks(inv_item);
}
- else if (user_confirm && (move_is_into_outbox || move_is_into_marketplacelistings))
+ else if (user_confirm && move_is_into_marketplacelistings)
{
- const LLViewerInventoryCategory * master_folder = (move_is_into_outbox ? model->getFirstDescendantOf(outbox_id, mUUID) : model->getFirstDescendantOf(marketplacelistings_id, mUUID));
+ const LLViewerInventoryCategory * master_folder = model->getFirstDescendantOf(marketplacelistings_id, mUUID);
LLViewerInventoryCategory * dest_folder = getCategory();
accept = can_move_item_to_marketplace(master_folder, dest_folder, inv_item, tooltip_msg, LLToolDragAndDrop::instance().getCargoCount() - LLToolDragAndDrop::instance().getCargoIndex());
}
@@ -4762,19 +4616,6 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
{
dropToOutfit(inv_item, move_is_into_current_outfit);
}
- // MERCHANT OUTBOX folder
- // Move the item
- else if (move_is_into_outbox)
- {
- if (move_is_from_outbox)
- {
- move_item_within_outbox(inv_item, mUUID, LLToolDragAndDrop::getOperationId());
- }
- else
- {
- copy_item_to_outbox(inv_item, mUUID, LLUUID::null, LLToolDragAndDrop::getOperationId());
- }
- }
// MARKETPLACE LISTINGS folder
// Move the item
else if (move_is_into_marketplacelistings)
@@ -4861,7 +4702,7 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
{
accept = FALSE;
}
- else if (move_is_into_outbox || move_is_into_marketplacelistings)
+ else if (move_is_into_marketplacelistings)
{
tooltip_msg = LLTrans::getString("TooltipOutboxNotInInventory");
accept = FALSE;
@@ -4899,7 +4740,7 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
}
else if(LLToolDragAndDrop::SOURCE_NOTECARD == source)
{
- if (move_is_into_outbox || move_is_into_marketplacelistings)
+ if (move_is_into_marketplacelistings)
{
tooltip_msg = LLTrans::getString("TooltipOutboxNotInInventory");
accept = FALSE;
@@ -4933,7 +4774,7 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
{
accept = TRUE;
- if (move_is_into_outbox || move_is_into_marketplacelistings)
+ if (move_is_into_marketplacelistings)
{
tooltip_msg = LLTrans::getString("TooltipOutboxNotInInventory");
accept = FALSE;
@@ -5102,10 +4943,6 @@ void LLTextureBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
{
addTrashContextMenuOptions(items, disabled_items);
}
- else if(isOutboxFolder())
- {
- addOutboxContextMenuOptions(flags, items, disabled_items);
- }
else if (isMarketplaceListingsFolder())
{
addMarketplaceContextMenuOptions(flags, items, disabled_items);
@@ -5175,11 +5012,7 @@ void LLSoundBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
menuentry_vec_t items;
menuentry_vec_t disabled_items;
- if (isOutboxFolder())
- {
- addOutboxContextMenuOptions(flags, items, disabled_items);
- }
- else if (isMarketplaceListingsFolder())
+ if (isMarketplaceListingsFolder())
{
addMarketplaceContextMenuOptions(flags, items, disabled_items);
items.push_back(std::string("Properties"));
@@ -5256,11 +5089,7 @@ void LLLandmarkBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
menuentry_vec_t disabled_items;
LL_DEBUGS() << "LLLandmarkBridge::buildContextMenu()" << LL_ENDL;
- if(isOutboxFolder())
- {
- addOutboxContextMenuOptions(flags, items, disabled_items);
- }
- else if (isMarketplaceListingsFolder())
+ if (isMarketplaceListingsFolder())
{
addMarketplaceContextMenuOptions(flags, items, disabled_items);
items.push_back(std::string("Properties"));
@@ -5554,10 +5383,6 @@ void LLCallingCardBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
{
addTrashContextMenuOptions(items, disabled_items);
}
- else if(isOutboxFolder())
- {
- items.push_back(std::string("Delete"));
- }
else if (isMarketplaceListingsFolder())
{
addMarketplaceContextMenuOptions(flags, items, disabled_items);
@@ -5760,7 +5585,7 @@ void LLGestureBridge::performAction(LLInventoryModel* model, std::string action)
gInventory.updateItem(item);
gInventory.notifyObservers();
}
- else if (isRemoveAction(action))
+ else if ("deactivate" == action || isRemoveAction(action))
{
LLGestureMgr::instance().deactivateGesture(mUUID);
@@ -5846,10 +5671,6 @@ void LLGestureBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
{
addTrashContextMenuOptions(items, disabled_items);
}
- else if(isOutboxFolder())
- {
- items.push_back(std::string("Delete"));
- }
else if (isMarketplaceListingsFolder())
{
addMarketplaceContextMenuOptions(flags, items, disabled_items);
@@ -5906,11 +5727,7 @@ void LLAnimationBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
menuentry_vec_t disabled_items;
LL_DEBUGS() << "LLAnimationBridge::buildContextMenu()" << LL_ENDL;
- if(isOutboxFolder())
- {
- items.push_back(std::string("Delete"));
- }
- else if (isMarketplaceListingsFolder())
+ if (isMarketplaceListingsFolder())
{
addMarketplaceContextMenuOptions(flags, items, disabled_items);
items.push_back(std::string("Properties"));
@@ -6171,10 +5988,6 @@ void LLObjectBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
{
addTrashContextMenuOptions(items, disabled_items);
}
- else if(isOutboxFolder())
- {
- items.push_back(std::string("Delete"));
- }
else if (isMarketplaceListingsFolder())
{
addMarketplaceContextMenuOptions(flags, items, disabled_items);
@@ -6382,12 +6195,8 @@ void LLWearableBridge::performAction(LLInventoryModel* model, std::string action
void LLWearableBridge::openItem()
{
- LLViewerInventoryItem* item = getItem();
-
- if (item)
- {
- LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel());
- }
+ performAction(getInventoryModel(),
+ get_is_item_worn(mUUID) ? "take_off" : "wear");
}
void LLWearableBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
@@ -6399,10 +6208,6 @@ void LLWearableBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
{
addTrashContextMenuOptions(items, disabled_items);
}
- else if(isOutboxFolder())
- {
- items.push_back(std::string("Delete"));
- }
else if (isMarketplaceListingsFolder())
{
addMarketplaceContextMenuOptions(flags, items, disabled_items);
@@ -6705,10 +6510,6 @@ void LLMeshBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
items.push_back(std::string("Restore Item"));
}
- else if(isOutboxFolder())
- {
- addOutboxContextMenuOptions(flags, items, disabled_items);
- }
else if (isMarketplaceListingsFolder())
{
addMarketplaceContextMenuOptions(flags, items, disabled_items);
diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h
index 7e7cf9c7dd..9053c61171 100755
--- a/indra/newview/llinventorybridge.h
+++ b/indra/newview/llinventorybridge.h
@@ -77,7 +77,6 @@ public:
bool canShare() const;
bool canListOnMarketplace() const;
- bool canListOnOutboxNow() const;
bool canListOnMarketplaceNow() const;
//--------------------------------------------------------------------
@@ -145,9 +144,6 @@ protected:
virtual void addDeleteContextMenuOptions(menuentry_vec_t &items,
menuentry_vec_t &disabled_items);
virtual void addOpenRightClickMenuOption(menuentry_vec_t &items);
- virtual void addOutboxContextMenuOptions(U32 flags,
- menuentry_vec_t &items,
- menuentry_vec_t &disabled_items);
virtual void addMarketplaceContextMenuOptions(U32 flags,
menuentry_vec_t &items,
menuentry_vec_t &disabled_items);
@@ -164,9 +160,7 @@ protected:
BOOL isCOFFolder() const; // true if COF or descendant of
BOOL isInboxFolder() const; // true if COF or descendant of marketplace inbox
- BOOL isOutboxFolderDirectParent() const;
BOOL isMarketplaceListingsFolder() const; // true if descendant of Marketplace listings folder
- const LLUUID getOutboxFolder() const;
virtual BOOL isItemPermissive() const;
static void changeItemParent(LLInventoryModel* model,
@@ -182,10 +176,6 @@ protected:
BOOL callback_cutToClipboard(const LLSD& notification, const LLSD& response);
BOOL perform_cutToClipboard();
-public:
- BOOL isOutboxFolder() const; // true if COF or descendant of marketplace outbox
-
-protected:
LLHandle<LLInventoryPanel> mInventoryPanel;
LLFolderView* mRoot;
const LLUUID mUUID; // item id
@@ -274,7 +264,7 @@ public:
{}
BOOL dragItemIntoFolder(LLInventoryItem* inv_item, BOOL drop, std::string& tooltip_msg, BOOL user_confirm = TRUE);
- BOOL dragCategoryIntoFolder(LLInventoryCategory* inv_category, BOOL drop, std::string& tooltip_msg, BOOL user_confirm = TRUE);
+ BOOL dragCategoryIntoFolder(LLInventoryCategory* inv_category, BOOL drop, std::string& tooltip_msg, BOOL is_link = FALSE, BOOL user_confirm = TRUE);
void callback_dropItemIntoFolder(const LLSD& notification, const LLSD& response, LLInventoryItem* inv_item);
void callback_dropCategoryIntoFolder(const LLSD& notification, const LLSD& response, LLInventoryCategory* inv_category);
diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp
index 916e9ad8f3..e3cb4d57ef 100755
--- a/indra/newview/llinventoryfunctions.cpp
+++ b/indra/newview/llinventoryfunctions.cpp
@@ -782,11 +782,6 @@ void reset_inventory_filter()
}
}
-void open_outbox()
-{
- LLFloaterReg::showInstance("outbox");
-}
-
void open_marketplace_listings()
{
LLFloaterReg::showInstance("marketplace_listings");
@@ -808,157 +803,6 @@ LLUUID create_folder_for_item(LLInventoryItem* item, const LLUUID& destFolderId)
return created_folder_id;
}
-void move_to_outbox_cb_action(const LLSD& payload)
-{
- LLViewerInventoryItem * viitem = gInventory.getItem(payload["item_id"].asUUID());
- LLUUID dest_folder_id = payload["dest_folder_id"].asUUID();
-
- if (viitem)
- {
- // when moving item directly into outbox create folder with that name
- if (dest_folder_id == gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false))
- {
- dest_folder_id = create_folder_for_item(viitem, dest_folder_id);
- }
-
- LLUUID parent = viitem->getParentUUID();
-
- gInventory.changeItemParent(
- viitem,
- dest_folder_id,
- false);
-
- LLUUID top_level_folder = payload["top_level_folder"].asUUID();
-
- if (top_level_folder != LLUUID::null)
- {
- LLViewerInventoryCategory* category;
-
- while (parent.notNull())
- {
- LLInventoryModel::cat_array_t* cat_array;
- LLInventoryModel::item_array_t* item_array;
- gInventory.getDirectDescendentsOf(parent,cat_array,item_array);
-
- LLUUID next_parent;
-
- category = gInventory.getCategory(parent);
-
- if (!category) break;
-
- next_parent = category->getParentUUID();
-
- if (cat_array->empty() && item_array->empty())
- {
- gInventory.removeCategory(parent);
- }
-
- if (parent == top_level_folder)
- {
- break;
- }
-
- parent = next_parent;
- }
- }
-
- open_outbox();
- }
-}
-
-void copy_item_to_outbox(LLInventoryItem* inv_item, LLUUID dest_folder, const LLUUID& top_level_folder, S32 operation_id)
-{
- // Collapse links directly to items/folders
- LLViewerInventoryItem * viewer_inv_item = (LLViewerInventoryItem *) inv_item;
- LLViewerInventoryCategory * linked_category = viewer_inv_item->getLinkedCategory();
- if (linked_category != NULL)
- {
- copy_folder_to_outbox(linked_category, dest_folder, top_level_folder, operation_id);
- }
- else
- {
- LLViewerInventoryItem * linked_item = viewer_inv_item->getLinkedItem();
- if (linked_item != NULL)
- {
- inv_item = (LLInventoryItem *) linked_item;
- }
-
- // Check for copy permissions
- if (inv_item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID(), gAgent.getGroupID()))
- {
- // when moving item directly into outbox create folder with that name
- if (dest_folder == gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false))
- {
- dest_folder = create_folder_for_item(inv_item, dest_folder);
- }
-
- copy_inventory_item(gAgent.getID(),
- inv_item->getPermissions().getOwner(),
- inv_item->getUUID(),
- dest_folder,
- inv_item->getName(),
- LLPointer<LLInventoryCallback>(NULL));
-
- open_outbox();
- }
- else
- {
- LLSD payload;
- payload["item_id"] = inv_item->getUUID();
- payload["dest_folder_id"] = dest_folder;
- payload["top_level_folder"] = top_level_folder;
- payload["operation_id"] = operation_id;
-
- LLMarketplaceInventoryNotifications::addNoCopyNotification(payload, move_to_outbox_cb_action);
- }
- }
-}
-
-void move_item_within_outbox(LLInventoryItem* inv_item, LLUUID dest_folder, S32 operation_id)
-{
- // when moving item directly into outbox create folder with that name
- if (dest_folder == gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false))
- {
- dest_folder = create_folder_for_item(inv_item, dest_folder);
- }
-
- LLViewerInventoryItem * viewer_inv_item = (LLViewerInventoryItem *) inv_item;
-
- gInventory.changeItemParent(
- viewer_inv_item,
- dest_folder,
- false);
-}
-
-void copy_folder_to_outbox(LLInventoryCategory* inv_cat, const LLUUID& dest_folder, const LLUUID& top_level_folder, S32 operation_id)
-{
- LLUUID new_folder_id = gInventory.createNewCategory(dest_folder, LLFolderType::FT_NONE, inv_cat->getName());
- gInventory.notifyObservers();
-
- LLInventoryModel::cat_array_t* cat_array;
- LLInventoryModel::item_array_t* item_array;
- gInventory.getDirectDescendentsOf(inv_cat->getUUID(),cat_array,item_array);
-
- // copy the vector because otherwise the iterator won't be happy if we delete from it
- LLInventoryModel::item_array_t item_array_copy = *item_array;
-
- for (LLInventoryModel::item_array_t::iterator iter = item_array_copy.begin(); iter != item_array_copy.end(); iter++)
- {
- LLInventoryItem* item = *iter;
- copy_item_to_outbox(item, new_folder_id, top_level_folder, operation_id);
- }
-
- LLInventoryModel::cat_array_t cat_array_copy = *cat_array;
-
- for (LLInventoryModel::cat_array_t::iterator iter = cat_array_copy.begin(); iter != cat_array_copy.end(); iter++)
- {
- LLViewerInventoryCategory* category = *iter;
- copy_folder_to_outbox(category, new_folder_id, top_level_folder, operation_id);
- }
-
- open_outbox();
-}
-
///----------------------------------------------------------------------------
// Marketplace functions
//
@@ -975,7 +819,7 @@ S32 depth_nesting_in_marketplace(LLUUID cur_uuid)
{
return -1;
}
- // If not a descendent of the marketplace listings root, then the nesting depth is -1 by definition
+ // If not a descendant of the marketplace listings root, then the nesting depth is -1 by definition
if (!gInventory.isObjectDescendentOf(cur_uuid, marketplace_listings_uuid))
{
return -1;
@@ -2473,7 +2317,7 @@ void LLInventoryAction::doToSelected(LLInventoryModel* model, LLFolderView* root
{
LLSD args;
args["QUESTION"] = LLTrans::getString(root->getSelectedCount() > 1 ? "DeleteItems" : "DeleteItem");
- LLNotificationsUtil::add("DeleteItems", args, LLSD(), boost::bind(&onItemsRemovalConfirmation, _1, _2, root->getHandle()));
+ LLNotificationsUtil::add("DeleteItems", args, LLSD(), boost::bind(&LLInventoryAction::onItemsRemovalConfirmation, _1, _2, root->getHandle()));
// Note: marketplace listings will be updated in the callback if delete confirmed
return;
}
diff --git a/indra/newview/llinventoryfunctions.h b/indra/newview/llinventoryfunctions.h
index 6ae8fd0f13..649db4032d 100755
--- a/indra/newview/llinventoryfunctions.h
+++ b/indra/newview/llinventoryfunctions.h
@@ -75,10 +75,6 @@ void copy_inventory_category(LLInventoryModel* model, LLViewerInventoryCategory*
// Generates a string containing the path to the item specified by item_id.
void append_path(const LLUUID& id, std::string& path);
-void copy_item_to_outbox(LLInventoryItem* inv_item, LLUUID dest_folder, const LLUUID& top_level_folder, S32 operation_id);
-void move_item_within_outbox(LLInventoryItem* inv_item, LLUUID dest_folder, S32 operation_id);
-void copy_folder_to_outbox(LLInventoryCategory* inv_cat, const LLUUID& dest_folder, const LLUUID& top_level_folder, S32 operation_id);
-
typedef boost::function<void(std::string& validation_message, S32 depth, LLError::ELevel log_level)> validation_callback_t;
bool can_move_item_to_marketplace(const LLInventoryCategory* root_folder, LLInventoryCategory* dest_folder, LLInventoryItem* inv_item, std::string& tooltip_msg, S32 bundle_size = 1, bool from_paste = false);
@@ -465,9 +461,9 @@ struct LLInventoryAction
static void removeItemFromDND(LLFolderView* root);
private:
- static void buildMarketplaceFolders(LLFolderView* root);
- static void updateMarketplaceFolders();
- static std::list<LLUUID> sMarketplaceFolders; // Marketplace folders that will need update once the action is completed
+ static void buildMarketplaceFolders(LLFolderView* root);
+ static void updateMarketplaceFolders();
+ static std::list<LLUUID> sMarketplaceFolders; // Marketplace folders that will need update once the action is completed
};
diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp
index 175ea22aa0..ab0df33051 100755
--- a/indra/newview/llinventorymodel.cpp
+++ b/indra/newview/llinventorymodel.cpp
@@ -614,7 +614,7 @@ void LLInventoryModel::createNewCategoryCoro(std::string url, LLSD postData, inv
LL_INFOS("HttpCoroutineAdapter", "genericPostCoro") << "Generic POST for " << url << LL_ENDL;
- LLSD result = httpAdapter->postAndYield(httpRequest, url, postData, httpOpts);
+ LLSD result = httpAdapter->postAndSuspend(httpRequest, url, postData, httpOpts);
LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
@@ -2456,7 +2456,7 @@ void LLInventoryModel::handleResponses(bool foreground)
LLCore::HttpHandle LLInventoryModel::requestPost(bool foreground,
const std::string & url,
const LLSD & body,
- LLCore::HttpHandler * handler,
+ const LLCore::HttpHandler::ptr_t &handler,
const char * const message)
{
if (! mHttpRequestFG)
@@ -2485,7 +2485,6 @@ LLCore::HttpHandle LLInventoryModel::requestPost(bool foreground,
<< ", Status: " << status.toTerseString()
<< " Reason: '" << status.toString() << "'"
<< LL_ENDL;
- delete handler;
}
return handle;
}
@@ -4051,9 +4050,6 @@ void LLInventoryModel::FetchItemHttpHandler::onCompleted(LLCore::HttpHandle hand
processData(body_llsd, response);
}
while (false);
-
- // Must delete on completion.
- delete this;
}
void LLInventoryModel::FetchItemHttpHandler::processData(LLSD & content, LLCore::HttpResponse * response)
diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h
index e8977bc7d7..e1e6db19eb 100755
--- a/indra/newview/llinventorymodel.h
+++ b/indra/newview/llinventorymodel.h
@@ -35,7 +35,6 @@
#include "llassettype.h"
#include "llfoldertype.h"
#include "llframetimer.h"
-#include "llcurl.h"
#include "lluuid.h"
#include "llpermissionsflags.h"
#include "llviewerinventory.h"
@@ -81,6 +80,9 @@ public:
typedef std::vector<LLPointer<LLViewerInventoryItem> > item_array_t;
typedef std::set<LLUUID> changed_items_t;
+ // Rider: This is using the old responder patter. It should be refactored to
+ // take advantage of coroutines.
+
// HTTP handler for individual item requests (inventory or library).
// Background item requests are derived from this in the background
// inventory system. All folder requests are also located there
@@ -564,7 +566,7 @@ public:
LLCore::HttpHandle requestPost(bool foreground,
const std::string & url,
const LLSD & body,
- LLCore::HttpHandler * handler,
+ const LLCore::HttpHandler::ptr_t &handler,
const char * const message);
private:
diff --git a/indra/newview/llinventorymodelbackgroundfetch.cpp b/indra/newview/llinventorymodelbackgroundfetch.cpp
index 40edb13a80..4a77edc565 100755
--- a/indra/newview/llinventorymodelbackgroundfetch.cpp
+++ b/indra/newview/llinventorymodelbackgroundfetch.cpp
@@ -513,7 +513,7 @@ void LLInventoryModelBackgroundFetch::bulkFetch()
if (! url.empty())
{
- BGFolderHttpHandler * handler(new BGFolderHttpHandler(folder_request_body, recursive_cats));
+ LLCore::HttpHandler::ptr_t handler(new BGFolderHttpHandler(folder_request_body, recursive_cats));
gInventory.requestPost(false, url, folder_request_body, handler, "Inventory Folder");
}
}
@@ -524,7 +524,7 @@ void LLInventoryModelBackgroundFetch::bulkFetch()
if (! url.empty())
{
- BGFolderHttpHandler * handler(new BGFolderHttpHandler(folder_request_body_lib, recursive_cats));
+ LLCore::HttpHandler::ptr_t handler(new BGFolderHttpHandler(folder_request_body_lib, recursive_cats));
gInventory.requestPost(false, url, folder_request_body_lib, handler, "Library Folder");
}
}
@@ -540,7 +540,7 @@ void LLInventoryModelBackgroundFetch::bulkFetch()
{
LLSD body;
body["items"] = item_request_body;
- BGItemHttpHandler * handler(new BGItemHttpHandler(body));
+ LLCore::HttpHandler::ptr_t handler(new BGItemHttpHandler(body));
gInventory.requestPost(false, url, body, handler, "Inventory Item");
}
}
@@ -553,7 +553,7 @@ void LLInventoryModelBackgroundFetch::bulkFetch()
{
LLSD body;
body["items"] = item_request_body_lib;
- BGItemHttpHandler * handler(new BGItemHttpHandler(body));
+ LLCore::HttpHandler::ptr_t handler(new BGItemHttpHandler(body));
gInventory.requestPost(false, url, body, handler, "Library Item");
}
}
@@ -647,9 +647,6 @@ void BGFolderHttpHandler::onCompleted(LLCore::HttpHandle handle, LLCore::HttpRes
processData(body_llsd, response);
}
while (false);
-
- // Must delete on completion.
- delete this;
}
diff --git a/indra/newview/llinventoryobserver.cpp b/indra/newview/llinventoryobserver.cpp
index d81401b59b..6c81378622 100755
--- a/indra/newview/llinventoryobserver.cpp
+++ b/indra/newview/llinventoryobserver.cpp
@@ -237,7 +237,7 @@ void fetch_items_from_llsd(const LLSD& items_llsd)
if (!url.empty())
{
body[i]["agent_id"] = gAgent.getID();
- LLInventoryModel::FetchItemHttpHandler * handler(new LLInventoryModel::FetchItemHttpHandler(body[i]));
+ LLCore::HttpHandler::ptr_t handler(new LLInventoryModel::FetchItemHttpHandler(body[i]));
gInventory.requestPost(true, url, body[i], handler, (i ? "Library Item" : "Inventory Item"));
continue;
}
diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp
index 5194cba891..02d378bc51 100755
--- a/indra/newview/llinventorypanel.cpp
+++ b/indra/newview/llinventorypanel.cpp
@@ -1437,16 +1437,20 @@ BOOL LLInventoryPanel::handleKeyHere( KEY key, MASK mask )
// Open selected items if enter key hit on the inventory panel
if (mask == MASK_NONE)
{
- //Don't allow attaching or opening items from Merchant Outbox
- LLFolderViewItem* folder_item = mFolderRoot.get()->getCurSelectedItem();
- if(folder_item)
- {
- LLInvFVBridge* bridge = (LLInvFVBridge*)folder_item->getViewModelItem();
- if(bridge && bridge->isOutboxFolder() && (bridge->getInventoryType() != LLInventoryType::IT_CATEGORY))
- {
- return handled;
- }
- }
+
+// @TODO$: Rider: This code is dead with Outbox, however should something similar be
+// done for VMM?
+//
+// //Don't allow attaching or opening items from Merchant Outbox
+// LLFolderViewItem* folder_item = mFolderRoot.get()->getCurSelectedItem();
+// if(folder_item)
+// {
+// LLInvFVBridge* bridge = (LLInvFVBridge*)folder_item->getViewModelItem();
+// if(bridge && bridge->is() && (bridge->getInventoryType() != LLInventoryType::IT_CATEGORY))
+// {
+// return handled;
+// }
+// }
LLInventoryAction::doToSelected(mInventory, mFolderRoot.get(), "open");
handled = TRUE;
diff --git a/indra/newview/lllocalbitmaps.cpp b/indra/newview/lllocalbitmaps.cpp
index 4e9947fca0..46c1ffa789 100755
--- a/indra/newview/lllocalbitmaps.cpp
+++ b/indra/newview/lllocalbitmaps.cpp
@@ -515,7 +515,7 @@ void LLLocalBitmap::updateUserSculpts(LLUUID old_id, LLUUID new_id)
{
LLSculptParams* old_params = (LLSculptParams*)object->getParameterEntry(LLNetworkData::PARAMS_SCULPT);
LLSculptParams new_params(*old_params);
- new_params.setSculptTexture(new_id);
+ new_params.setSculptTexture(new_id, (*old_params).getSculptType());
object->setParameterEntry(LLNetworkData::PARAMS_SCULPT, new_params, TRUE);
}
}
diff --git a/indra/newview/lllocationinputctrl.cpp b/indra/newview/lllocationinputctrl.cpp
index cf04c5f7a5..8d21fda8f9 100755
--- a/indra/newview/lllocationinputctrl.cpp
+++ b/indra/newview/lllocationinputctrl.cpp
@@ -862,14 +862,11 @@ void LLLocationInputCtrl::refreshParcelIcons()
bool see_avs = current_parcel->getSeeAVs();
bool pathfinding_dynamic_enabled = agent_region->dynamicPathfindingEnabled();
- bool is_parcel_owner = (gAgent.getID() == current_parcel->getOwnerID());
- bool allow_group_modify = (gAgent.isInGroup(current_parcel->getGroupID()) && current_parcel->getAllowGroupModify());
-
// Most icons are "block this ability"
mParcelIcon[VOICE_ICON]->setVisible( !allow_voice );
mParcelIcon[FLY_ICON]->setVisible( !allow_fly );
mParcelIcon[PUSH_ICON]->setVisible( !allow_push );
- mParcelIcon[BUILD_ICON]->setVisible( !allow_build && !is_parcel_owner && !allow_group_modify );
+ mParcelIcon[BUILD_ICON]->setVisible( !allow_build );
mParcelIcon[SCRIPTS_ICON]->setVisible( !allow_scripts );
mParcelIcon[DAMAGE_ICON]->setVisible( allow_damage );
mParcelIcon[PATHFINDING_DIRTY_ICON]->setVisible(mIsNavMeshDirty);
diff --git a/indra/newview/lllogchat.cpp b/indra/newview/lllogchat.cpp
index 7ddacf3033..4116e38f11 100755
--- a/indra/newview/lllogchat.cpp
+++ b/indra/newview/lllogchat.cpp
@@ -804,6 +804,22 @@ bool LLLogChat::isNearbyTranscriptExist()
return false;
}
+bool LLLogChat::isAdHocTranscriptExist(std::string file_name)
+{
+ std::vector<std::string> list_of_transcriptions;
+ LLLogChat::getListOfTranscriptFiles(list_of_transcriptions);
+
+ file_name = makeLogFileName(file_name);
+ BOOST_FOREACH(std::string& transcript_file_name, list_of_transcriptions)
+ {
+ if (transcript_file_name == file_name)
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
//*TODO mark object's names in a special way so that they will be distinguishable form avatar name
//which are more strict by its nature (only firstname and secondname)
//Example, an object's name can be written like "Object <actual_object's_name>"
diff --git a/indra/newview/lllogchat.h b/indra/newview/lllogchat.h
index ca597599dd..6022e539a9 100755
--- a/indra/newview/lllogchat.h
+++ b/indra/newview/lllogchat.h
@@ -120,6 +120,7 @@ public:
static void deleteTranscripts();
static bool isTranscriptExist(const LLUUID& avatar_id, bool is_group=false);
static bool isNearbyTranscriptExist();
+ static bool isAdHocTranscriptExist(std::string file_name);
static bool historyThreadsFinished(LLUUID session_id);
static LLLoadHistoryThread* getLoadHistoryThread(LLUUID session_id);
diff --git a/indra/newview/llmanipscale.cpp b/indra/newview/llmanipscale.cpp
index 407613d32c..85faa70552 100755
--- a/indra/newview/llmanipscale.cpp
+++ b/indra/newview/llmanipscale.cpp
@@ -1677,12 +1677,12 @@ void LLManipScale::renderSnapGuides(const LLBBox& bbox)
F32 alpha = (1.f - (1.f * ((F32)llabs(i) / (F32)num_ticks_per_side1)));
LLVector3 tick_pos = mScaleCenter + (mScaleDir * (grid_multiple1 + i) * smallest_subdivision1);
- F32 cur_subdivisions = llclamp(getSubdivisionLevel(tick_pos, mScaleDir, mScaleSnapUnit1, mTickPixelSpacing1), sGridMinSubdivisionLevel, sGridMaxSubdivisionLevel);
-
- if (fmodf((F32)(i + sub_div_offset_1), (sGridMaxSubdivisionLevel / cur_subdivisions)) != 0.f)
+ //No need check this condition to prevent tick position scaling (FIX MAINT-5207/5208)
+ //F32 cur_subdivisions = llclamp(getSubdivisionLevel(tick_pos, mScaleDir, mScaleSnapUnit1, mTickPixelSpacing1), sGridMinSubdivisionLevel, sGridMaxSubdivisionLevel);
+ /*if (fmodf((F32)(i + sub_div_offset_1), (sGridMaxSubdivisionLevel / cur_subdivisions)) != 0.f)
{
continue;
- }
+ }*/
F32 tick_scale = 1.f;
for (F32 division_level = sGridMaxSubdivisionLevel; division_level >= sGridMinSubdivisionLevel; division_level /= 2.f)
@@ -1710,12 +1710,12 @@ void LLManipScale::renderSnapGuides(const LLBBox& bbox)
F32 alpha = (1.f - (1.f * ((F32)llabs(i) / (F32)num_ticks_per_side2)));
LLVector3 tick_pos = mScaleCenter + (mScaleDir * (grid_multiple2 + i) * smallest_subdivision2);
- F32 cur_subdivisions = llclamp(getSubdivisionLevel(tick_pos, mScaleDir, mScaleSnapUnit2, mTickPixelSpacing2), sGridMinSubdivisionLevel, sGridMaxSubdivisionLevel);
-
- if (fmodf((F32)(i + sub_div_offset_2), (sGridMaxSubdivisionLevel / cur_subdivisions)) != 0.f)
+ //No need check this condition to prevent tick position scaling (FIX MAINT-5207/5208)
+ //F32 cur_subdivisions = llclamp(getSubdivisionLevel(tick_pos, mScaleDir, mScaleSnapUnit2, mTickPixelSpacing2), sGridMinSubdivisionLevel, sGridMaxSubdivisionLevel);
+ /*if (fmodf((F32)(i + sub_div_offset_2), (sGridMaxSubdivisionLevel / cur_subdivisions)) != 0.f)
{
continue;
- }
+ }*/
F32 tick_scale = 1.f;
for (F32 division_level = sGridMaxSubdivisionLevel; division_level >= sGridMinSubdivisionLevel; division_level /= 2.f)
diff --git a/indra/newview/llmaniptranslate.cpp b/indra/newview/llmaniptranslate.cpp
index 394db71fb9..b4259a456c 100755
--- a/indra/newview/llmaniptranslate.cpp
+++ b/indra/newview/llmaniptranslate.cpp
@@ -1285,12 +1285,12 @@ void LLManipTranslate::renderSnapGuides()
{
tick_start = selection_center + (translate_axis * (smallest_grid_unit_scale * (F32)i - offset_nearest_grid_unit));
- F32 cur_subdivisions = getSubdivisionLevel(tick_start, translate_axis, getMinGridScale());
-
- if (fmodf((F32)(i + sub_div_offset), (max_subdivisions / cur_subdivisions)) != 0.f)
+ //No need check this condition to prevent tick position scaling (FIX MAINT-5207/5208)
+ //F32 cur_subdivisions = getSubdivisionLevel(tick_start, translate_axis, getMinGridScale());
+ /*if (fmodf((F32)(i + sub_div_offset), (max_subdivisions / cur_subdivisions)) != 0.f)
{
continue;
- }
+ }*/
// add in off-axis offset
tick_start += (mSnapOffsetAxis * mSnapOffsetMeters);
diff --git a/indra/newview/llmarketplacefunctions.cpp b/indra/newview/llmarketplacefunctions.cpp
index f11d0f16da..dfa33b37ef 100755
--- a/indra/newview/llmarketplacefunctions.cpp
+++ b/indra/newview/llmarketplacefunctions.cpp
@@ -30,7 +30,6 @@
#include "llagent.h"
#include "llbufferstream.h"
-#include "llhttpclient.h"
#include "llinventoryfunctions.h"
#include "llinventoryobserver.h"
#include "llnotificationsutil.h"
@@ -48,605 +47,127 @@
#include "llcoros.h"
#include "llcorehttputil.h"
+#include "llsdutil.h"
//
// Helpers
//
-static std::string getMarketplaceDomain()
-{
- std::string domain = "secondlife.com";
-
- if (!LLGridManager::getInstance()->isInProductionGrid())
- {
- const std::string& grid_id = LLGridManager::getInstance()->getGridId();
- const std::string& grid_id_lower = utf8str_tolower(grid_id);
-
- if (grid_id_lower == "damballah")
- {
- domain = "secondlife-staging.com";
- }
- else
- {
- domain = llformat("%s.lindenlab.com", grid_id_lower.c_str());
- }
- }
-
- return domain;
-}
+namespace {
-static std::string getMarketplaceURL(const std::string& urlStringName)
-{
- LLStringUtil::format_map_t domain_arg;
- domain_arg["[MARKETPLACE_DOMAIN_NAME]"] = getMarketplaceDomain();
-
- std::string marketplace_url = LLTrans::getString(urlStringName, domain_arg);
-
- return marketplace_url;
-}
-
-LLSD getMarketplaceStringSubstitutions()
-{
- std::string marketplace_url = getMarketplaceURL("MarketplaceURL");
- std::string marketplace_url_create = getMarketplaceURL("MarketplaceURL_CreateStore");
- std::string marketplace_url_dashboard = getMarketplaceURL("MarketplaceURL_Dashboard");
- std::string marketplace_url_imports = getMarketplaceURL("MarketplaceURL_Imports");
- std::string marketplace_url_info = getMarketplaceURL("MarketplaceURL_LearnMore");
-
- LLSD marketplace_sub_map;
-
- marketplace_sub_map["[MARKETPLACE_URL]"] = marketplace_url;
- marketplace_sub_map["[MARKETPLACE_CREATE_STORE_URL]"] = marketplace_url_create;
- marketplace_sub_map["[MARKETPLACE_LEARN_MORE_URL]"] = marketplace_url_info;
- marketplace_sub_map["[MARKETPLACE_DASHBOARD_URL]"] = marketplace_url_dashboard;
- marketplace_sub_map["[MARKETPLACE_IMPORTS_URL]"] = marketplace_url_imports;
-
- return marketplace_sub_map;
-}
-
-// Get the version folder: if there is only one subfolder, we will use it as a version folder
-LLUUID getVersionFolderIfUnique(const LLUUID& folder_id)
-{
- LLUUID version_id = LLUUID::null;
- LLInventoryModel::cat_array_t* categories;
- LLInventoryModel::item_array_t* items;
- gInventory.getDirectDescendentsOf(folder_id, categories, items);
- if (categories->size() == 1)
- {
- version_id = categories->begin()->get()->getUUID();
- }
- else
+ static std::string getMarketplaceDomain()
{
- LLNotificationsUtil::add("AlertMerchantListingActivateRequired");
- }
- return version_id;
-}
+ std::string domain = "secondlife.com";
-///////////////////////////////////////////////////////////////////////////////
-// SLM Responders
-void log_SLM_warning(const std::string& request, U32 status, const std::string& reason, const std::string& code, const std::string& description)
-{
- LL_WARNS("SLM") << "SLM API : Responder to " << request << ". status : " << status << ", reason : " << reason << ", code : " << code << ", description : " << description << LL_ENDL;
- if ((status == 422) && (description == "[\"You must have an English description to list the product\", \"You must choose a category for your product before it can be listed\", \"Listing could not change state.\", \"Price can't be blank\"]"))
- {
- // Unprocessable Entity : Special case that error as it is a frequent answer when trying to list an incomplete listing
- LLNotificationsUtil::add("MerchantUnprocessableEntity");
- }
- else
- {
- // Prompt the user with the warning (so they know why things are failing)
- LLSD subs;
- subs["[ERROR_REASON]"] = reason;
- // We do show long descriptions in the alert (unlikely to be readable). The description string will be in the log though.
- subs["[ERROR_DESCRIPTION]"] = (description.length() <= 512 ? description : "");
- LLNotificationsUtil::add("MerchantTransactionFailed", subs);
- }
-}
-void log_SLM_infos(const std::string& request, U32 status, const std::string& body)
-{
- if (gSavedSettings.getBOOL("MarketplaceListingsLogging"))
- {
- LL_INFOS("SLM") << "SLM API : Responder to " << request << ". status : " << status << ", body or description : " << body << LL_ENDL;
- }
-}
-void log_SLM_infos(const std::string& request, const std::string& url, const std::string& body)
-{
- if (gSavedSettings.getBOOL("MarketplaceListingsLogging"))
- {
- LL_INFOS("SLM") << "SLM API : Sending " << request << ". url : " << url << ", body : " << body << LL_ENDL;
- }
-}
-
-class LLSLMGetMerchantResponder : public LLHTTPClient::Responder
-{
- LOG_CLASS(LLSLMGetMerchantResponder);
-public:
-
- LLSLMGetMerchantResponder() {}
-
-protected:
- virtual void httpFailure()
- {
- if (HTTP_NOT_FOUND == getStatus())
- {
- log_SLM_infos("Get /merchant", getStatus(), "User is not a merchant");
- LLMarketplaceData::instance().setSLMStatus(MarketplaceStatusCodes::MARKET_PLACE_NOT_MERCHANT);
- }
- else if (HTTP_SERVICE_UNAVAILABLE == getStatus())
+ if (!LLGridManager::getInstance()->isInProductionGrid())
{
- log_SLM_infos("Get /merchant", getStatus(), "Merchant is not migrated");
- LLMarketplaceData::instance().setSLMStatus(MarketplaceStatusCodes::MARKET_PLACE_NOT_MIGRATED_MERCHANT);
- }
- else
- {
- log_SLM_warning("Get /merchant", getStatus(), getReason(), getContent().get("error_code"), getContent().get("error_description"));
- LLMarketplaceData::instance().setSLMStatus(MarketplaceStatusCodes::MARKET_PLACE_CONNECTION_FAILURE);
- }
- }
-
- virtual void httpSuccess()
- {
- log_SLM_infos("Get /merchant", getStatus(), "User is a merchant");
- LLMarketplaceData::instance().setSLMStatus(MarketplaceStatusCodes::MARKET_PLACE_MERCHANT);
- }
-
-};
-
-class LLSLMGetListingsResponder : public LLHTTPClient::Responder
-{
- LOG_CLASS(LLSLMGetListingsResponder);
-public:
-
- LLSLMGetListingsResponder(const LLUUID& folder_id)
- {
- mExpectedFolderId = folder_id;
- }
-
- virtual void completedRaw(const LLChannelDescriptors& channels,
- const LLIOPipe::buffer_ptr_t& buffer)
- {
- LLMarketplaceData::instance().setUpdating(mExpectedFolderId,false);
-
- LLBufferStream istr(channels, buffer.get());
- std::stringstream strstrm;
- strstrm << istr.rdbuf();
- const std::string body = strstrm.str();
-
- if (!isGoodStatus())
- {
- log_SLM_warning("Get /listings", getStatus(), getReason(), "", body);
- LLMarketplaceData::instance().setSLMDataFetched(MarketplaceFetchCodes::MARKET_FETCH_FAILED);
- update_marketplace_category(mExpectedFolderId, false);
- gInventory.notifyObservers();
- return;
- }
+ const std::string& grid_id = LLGridManager::getInstance()->getGridId();
+ const std::string& grid_id_lower = utf8str_tolower(grid_id);
- Json::Value root;
- Json::Reader reader;
- if (!reader.parse(body,root))
- {
- log_SLM_warning("Get /listings", getStatus(), "Json parsing failed", reader.getFormatedErrorMessages(), body);
- LLMarketplaceData::instance().setSLMDataFetched(MarketplaceFetchCodes::MARKET_FETCH_FAILED);
- update_marketplace_category(mExpectedFolderId, false);
- gInventory.notifyObservers();
- return;
- }
-
- log_SLM_infos("Get /listings", getStatus(), body);
-
- // Extract the info from the Json string
- Json::ValueIterator it = root["listings"].begin();
-
- while (it != root["listings"].end())
- {
- Json::Value listing = *it;
-
- int listing_id = listing["id"].asInt();
- bool is_listed = listing["is_listed"].asBool();
- std::string edit_url = listing["edit_url"].asString();
- std::string folder_uuid_string = listing["inventory_info"]["listing_folder_id"].asString();
- std::string version_uuid_string = listing["inventory_info"]["version_folder_id"].asString();
- int count = listing["inventory_info"]["count_on_hand"].asInt();
-
- LLUUID folder_id(folder_uuid_string);
- LLUUID version_id(version_uuid_string);
- if (folder_id.notNull())
+ if (grid_id_lower == "damballah")
+ {
+ domain = "secondlife-staging.com";
+ }
+ else
{
- LLMarketplaceData::instance().addListing(folder_id,listing_id,version_id,is_listed,edit_url,count);
+ domain = llformat("%s.lindenlab.com", grid_id_lower.c_str());
}
- it++;
}
-
- // Update all folders under the root
- LLMarketplaceData::instance().setSLMDataFetched(MarketplaceFetchCodes::MARKET_FETCH_DONE);
- update_marketplace_category(mExpectedFolderId, false);
- gInventory.notifyObservers();
- }
-private:
- LLUUID mExpectedFolderId;
-};
-class LLSLMCreateListingsResponder : public LLHTTPClient::Responder
-{
- LOG_CLASS(LLSLMCreateListingsResponder);
-public:
-
- LLSLMCreateListingsResponder(const LLUUID& folder_id)
- {
- mExpectedFolderId = folder_id;
+ return domain;
}
-
- virtual void completedRaw(const LLChannelDescriptors& channels,
- const LLIOPipe::buffer_ptr_t& buffer)
+
+ static std::string getMarketplaceURL(const std::string& urlStringName)
{
- LLMarketplaceData::instance().setUpdating(mExpectedFolderId,false);
-
- LLBufferStream istr(channels, buffer.get());
- std::stringstream strstrm;
- strstrm << istr.rdbuf();
- const std::string body = strstrm.str();
-
- if (!isGoodStatus())
- {
- log_SLM_warning("Post /listings", getStatus(), getReason(), "", body);
- update_marketplace_category(mExpectedFolderId, false);
- gInventory.notifyObservers();
- return;
- }
-
- Json::Value root;
- Json::Reader reader;
- if (!reader.parse(body,root))
- {
- log_SLM_warning("Post /listings", getStatus(), "Json parsing failed", reader.getFormatedErrorMessages(), body);
- update_marketplace_category(mExpectedFolderId, false);
- gInventory.notifyObservers();
- return;
- }
+ LLStringUtil::format_map_t domain_arg;
+ domain_arg["[MARKETPLACE_DOMAIN_NAME]"] = getMarketplaceDomain();
- log_SLM_infos("Post /listings", getStatus(), body);
+ std::string marketplace_url = LLTrans::getString(urlStringName, domain_arg);
- // Extract the info from the Json string
- Json::ValueIterator it = root["listings"].begin();
-
- while (it != root["listings"].end())
- {
- Json::Value listing = *it;
-
- int listing_id = listing["id"].asInt();
- bool is_listed = listing["is_listed"].asBool();
- std::string edit_url = listing["edit_url"].asString();
- std::string folder_uuid_string = listing["inventory_info"]["listing_folder_id"].asString();
- std::string version_uuid_string = listing["inventory_info"]["version_folder_id"].asString();
- int count = listing["inventory_info"]["count_on_hand"].asInt();
-
- LLUUID folder_id(folder_uuid_string);
- LLUUID version_id(version_uuid_string);
- LLMarketplaceData::instance().addListing(folder_id,listing_id,version_id,is_listed,edit_url,count);
- update_marketplace_category(folder_id, false);
- gInventory.notifyObservers();
- it++;
- }
+ return marketplace_url;
}
-private:
- LLUUID mExpectedFolderId;
-};
-class LLSLMGetListingResponder : public LLHTTPClient::Responder
-{
- LOG_CLASS(LLSLMGetListingResponder);
-public:
-
- LLSLMGetListingResponder(const LLUUID& folder_id)
+ // Get the version folder: if there is only one subfolder, we will use it as a version folder
+ LLUUID getVersionFolderIfUnique(const LLUUID& folder_id)
{
- mExpectedFolderId = folder_id;
- }
-
- virtual void completedRaw(const LLChannelDescriptors& channels,
- const LLIOPipe::buffer_ptr_t& buffer)
- {
- LLMarketplaceData::instance().setUpdating(mExpectedFolderId,false);
-
- LLBufferStream istr(channels, buffer.get());
- std::stringstream strstrm;
- strstrm << istr.rdbuf();
- const std::string body = strstrm.str();
-
- if (!isGoodStatus())
- {
- if (getStatus() == 404)
- {
- // That listing does not exist -> delete its record from the local SLM data store
- LLMarketplaceData::instance().deleteListing(mExpectedFolderId, false);
- }
- else
- {
- log_SLM_warning("Get /listing", getStatus(), getReason(), "", body);
- }
- update_marketplace_category(mExpectedFolderId, false);
- gInventory.notifyObservers();
- return;
- }
-
- Json::Value root;
- Json::Reader reader;
- if (!reader.parse(body,root))
+ LLUUID version_id = LLUUID::null;
+ LLInventoryModel::cat_array_t* categories;
+ LLInventoryModel::item_array_t* items;
+ gInventory.getDirectDescendentsOf(folder_id, categories, items);
+ if (categories->size() == 1)
{
- log_SLM_warning("Get /listing", getStatus(), "Json parsing failed", reader.getFormatedErrorMessages(), body);
- update_marketplace_category(mExpectedFolderId, false);
- gInventory.notifyObservers();
- return;
+ version_id = categories->begin()->get()->getUUID();
}
-
- log_SLM_infos("Get /listing", getStatus(), body);
-
- // Extract the info from the Json string
- Json::ValueIterator it = root["listings"].begin();
-
- while (it != root["listings"].end())
+ else
{
- Json::Value listing = *it;
-
- int listing_id = listing["id"].asInt();
- bool is_listed = listing["is_listed"].asBool();
- std::string edit_url = listing["edit_url"].asString();
- std::string folder_uuid_string = listing["inventory_info"]["listing_folder_id"].asString();
- std::string version_uuid_string = listing["inventory_info"]["version_folder_id"].asString();
- int count = listing["inventory_info"]["count_on_hand"].asInt();
-
- LLUUID folder_id(folder_uuid_string);
- LLUUID version_id(version_uuid_string);
-
- // Update that listing
- LLMarketplaceData::instance().setListingID(folder_id, listing_id, false);
- LLMarketplaceData::instance().setVersionFolderID(folder_id, version_id, false);
- LLMarketplaceData::instance().setActivationState(folder_id, is_listed, false);
- LLMarketplaceData::instance().setListingURL(folder_id, edit_url, false);
- LLMarketplaceData::instance().setCountOnHand(folder_id,count,false);
- update_marketplace_category(folder_id, false);
- gInventory.notifyObservers();
-
- it++;
+ LLNotificationsUtil::add("AlertMerchantListingActivateRequired");
}
+ return version_id;
}
-private:
- LLUUID mExpectedFolderId;
-};
-class LLSLMUpdateListingsResponder : public LLHTTPClient::Responder
-{
- LOG_CLASS(LLSLMUpdateListingsResponder);
-public:
-
- LLSLMUpdateListingsResponder(const LLUUID& folder_id, bool expected_listed_state, const LLUUID& expected_version_id)
+ ///////////////////////////////////////////////////////////////////////////////
+ // SLM Reporters
+ void log_SLM_warning(const std::string& request, U32 status, const std::string& reason, const std::string& code, const LLSD& result)
{
- mExpectedFolderId = folder_id;
- mExpectedListedState = expected_listed_state;
- mExpectedVersionUUID = expected_version_id;
- }
-
- virtual void completedRaw(const LLChannelDescriptors& channels,
- const LLIOPipe::buffer_ptr_t& buffer)
- {
- LLMarketplaceData::instance().setUpdating(mExpectedFolderId,false);
- LLBufferStream istr(channels, buffer.get());
- std::stringstream strstrm;
- strstrm << istr.rdbuf();
- const std::string body = strstrm.str();
-
- if (!isGoodStatus())
- {
- log_SLM_warning("Put /listing", getStatus(), getReason(), "", body);
- update_marketplace_category(mExpectedFolderId, false);
- gInventory.notifyObservers();
- return;
- }
-
- Json::Value root;
- Json::Reader reader;
- if (!reader.parse(body,root))
+ LL_WARNS("SLM") << "SLM API : Responder to " << request << ". status : " << status << ", reason : " << reason << ", code : " << code << ", description : " << ll_pretty_print_sd(result) << LL_ENDL;
+ if ((status == 422) && (result.has(LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS_CONTENT) &&
+ result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS_CONTENT].isArray() &&
+ result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS_CONTENT].size() > 4))
{
- log_SLM_warning("Put /listing", getStatus(), "Json parsing failed", reader.getFormatedErrorMessages(), body);
- update_marketplace_category(mExpectedFolderId, false);
- gInventory.notifyObservers();
- return;
+ // Unprocessable Entity : Special case that error as it is a frequent answer when trying to list an incomplete listing
+ LLNotificationsUtil::add("MerchantUnprocessableEntity");
}
-
- log_SLM_infos("Put /listing", getStatus(), body);
-
- // Extract the info from the Json string
- Json::ValueIterator it = root["listings"].begin();
-
- while (it != root["listings"].end())
+ else
{
- Json::Value listing = *it;
-
- int listing_id = listing["id"].asInt();
- bool is_listed = listing["is_listed"].asBool();
- std::string edit_url = listing["edit_url"].asString();
- std::string folder_uuid_string = listing["inventory_info"]["listing_folder_id"].asString();
- std::string version_uuid_string = listing["inventory_info"]["version_folder_id"].asString();
- int count = listing["inventory_info"]["count_on_hand"].asInt();
-
- LLUUID folder_id(folder_uuid_string);
- LLUUID version_id(version_uuid_string);
-
- // Update that listing
- LLMarketplaceData::instance().setListingID(folder_id, listing_id, false);
- LLMarketplaceData::instance().setVersionFolderID(folder_id, version_id, false);
- LLMarketplaceData::instance().setActivationState(folder_id, is_listed, false);
- LLMarketplaceData::instance().setListingURL(folder_id, edit_url, false);
- LLMarketplaceData::instance().setCountOnHand(folder_id,count,false);
- update_marketplace_category(folder_id, false);
- gInventory.notifyObservers();
-
- // Show a notification alert if what we got is not what we expected
- // (this actually doesn't result in an error status from the SLM API protocol)
- if ((mExpectedListedState != is_listed) || (mExpectedVersionUUID != version_id))
+ // Prompt the user with the warning (so they know why things are failing)
+ LLSD subs;
+ subs["[ERROR_REASON]"] = reason;
+ // We do show long descriptions in the alert (unlikely to be readable). The description string will be in the log though.
+ std::string description;
+ if (result.has(LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS_CONTENT))
{
- LLSD subs;
- subs["[URL]"] = edit_url;
- LLNotificationsUtil::add("AlertMerchantListingNotUpdated", subs);
+ LLSD content = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS_CONTENT];
+ if (content.isArray())
+ {
+ for (LLSD::array_iterator it = content.beginArray(); it != content.endArray(); ++it)
+ {
+ if (!description.empty())
+ description += "\n";
+ description += (*it).asString();
+ }
+ }
+ else
+ {
+ description = content.asString();
+ }
}
-
- it++;
+ else
+ {
+ description = result.asString();
+ }
+ subs["[ERROR_DESCRIPTION]"] = description;
+ LLNotificationsUtil::add("MerchantTransactionFailed", subs);
}
- }
-private:
- LLUUID mExpectedFolderId;
- bool mExpectedListedState;
- LLUUID mExpectedVersionUUID;
-};
-class LLSLMAssociateListingsResponder : public LLHTTPClient::Responder
-{
- LOG_CLASS(LLSLMAssociateListingsResponder);
-public:
-
- LLSLMAssociateListingsResponder(const LLUUID& folder_id, const LLUUID& source_folder_id)
- {
- mExpectedFolderId = folder_id;
- mSourceFolderId = source_folder_id;
}
-
- virtual void completedRaw(const LLChannelDescriptors& channels,
- const LLIOPipe::buffer_ptr_t& buffer)
+
+ void log_SLM_infos(const std::string& request, U32 status, const std::string& body)
{
- LLMarketplaceData::instance().setUpdating(mExpectedFolderId,false);
- LLMarketplaceData::instance().setUpdating(mSourceFolderId,false);
-
- LLBufferStream istr(channels, buffer.get());
- std::stringstream strstrm;
- strstrm << istr.rdbuf();
- const std::string body = strstrm.str();
-
- if (!isGoodStatus())
- {
- log_SLM_warning("Put /associate_inventory", getStatus(), getReason(), "", body);
- update_marketplace_category(mExpectedFolderId, false);
- update_marketplace_category(mSourceFolderId, false);
- gInventory.notifyObservers();
- return;
- }
-
- Json::Value root;
- Json::Reader reader;
- if (!reader.parse(body,root))
- {
- log_SLM_warning("Put /associate_inventory", getStatus(), "Json parsing failed", reader.getFormatedErrorMessages(), body);
- update_marketplace_category(mExpectedFolderId, false);
- update_marketplace_category(mSourceFolderId, false);
- gInventory.notifyObservers();
- return;
- }
-
- log_SLM_infos("Put /associate_inventory", getStatus(), body);
-
- // Extract the info from the Json string
- Json::ValueIterator it = root["listings"].begin();
-
- while (it != root["listings"].end())
+ if (gSavedSettings.getBOOL("MarketplaceListingsLogging"))
{
- Json::Value listing = *it;
-
- int listing_id = listing["id"].asInt();
- bool is_listed = listing["is_listed"].asBool();
- std::string edit_url = listing["edit_url"].asString();
- std::string folder_uuid_string = listing["inventory_info"]["listing_folder_id"].asString();
- std::string version_uuid_string = listing["inventory_info"]["version_folder_id"].asString();
- int count = listing["inventory_info"]["count_on_hand"].asInt();
-
- LLUUID folder_id(folder_uuid_string);
- LLUUID version_id(version_uuid_string);
-
- // Check that the listing ID is not already associated to some other record
- LLUUID old_listing = LLMarketplaceData::instance().getListingFolder(listing_id);
- if (old_listing.notNull())
- {
- // If it is already used, unlist the old record (we can't have 2 listings with the same listing ID)
- LLMarketplaceData::instance().deleteListing(old_listing);
- }
-
- // Add the new association
- LLMarketplaceData::instance().addListing(folder_id,listing_id,version_id,is_listed,edit_url,count);
- update_marketplace_category(folder_id, false);
- gInventory.notifyObservers();
-
- // The stock count needs to be updated with the new local count now
- LLMarketplaceData::instance().updateCountOnHand(folder_id,1);
-
- it++;
+ LL_INFOS("SLM") << "SLM API : Responder to " << request << ". status : " << status << ", body or description : " << body << LL_ENDL;
}
-
- // Always update the source folder so its widget updates
- update_marketplace_category(mSourceFolderId, false);
}
-private:
- LLUUID mExpectedFolderId; // This is the folder now associated with the id.
- LLUUID mSourceFolderId; // This is the folder initially associated with the id. Can be LLUUI::null
-};
-class LLSLMDeleteListingsResponder : public LLHTTPClient::Responder
-{
- LOG_CLASS(LLSLMDeleteListingsResponder);
-public:
-
- LLSLMDeleteListingsResponder(const LLUUID& folder_id)
- {
- mExpectedFolderId = folder_id;
- }
-
- virtual void completedRaw(const LLChannelDescriptors& channels,
- const LLIOPipe::buffer_ptr_t& buffer)
+ void log_SLM_infos(const std::string& request, U32 status, const LLSD& body)
{
- LLMarketplaceData::instance().setUpdating(mExpectedFolderId,false);
-
- LLBufferStream istr(channels, buffer.get());
- std::stringstream strstrm;
- strstrm << istr.rdbuf();
- const std::string body = strstrm.str();
-
- if (!isGoodStatus())
- {
- log_SLM_warning("Delete /listing", getStatus(), getReason(), "", body);
- update_marketplace_category(mExpectedFolderId, false);
- gInventory.notifyObservers();
- return;
- }
-
- Json::Value root;
- Json::Reader reader;
- if (!reader.parse(body,root))
- {
- log_SLM_warning("Delete /listing", getStatus(), "Json parsing failed", reader.getFormatedErrorMessages(), body);
- update_marketplace_category(mExpectedFolderId, false);
- gInventory.notifyObservers();
- return;
- }
-
- log_SLM_infos("Delete /listing", getStatus(), body);
-
- // Extract the info from the Json string
- Json::ValueIterator it = root["listings"].begin();
-
- while (it != root["listings"].end())
- {
- Json::Value listing = *it;
-
- int listing_id = listing["id"].asInt();
- LLUUID folder_id = LLMarketplaceData::instance().getListingFolder(listing_id);
- LLMarketplaceData::instance().deleteListing(folder_id);
-
- it++;
- }
+ log_SLM_infos(request, status, std::string(ll_pretty_print_sd(body)));
}
-private:
- LLUUID mExpectedFolderId;
-};
-// SLM Responders End
-///////////////////////////////////////////////////////////////////////////////
+}
+
+#if 1
namespace LLMarketplaceImport
{
// Basic interface for this namespace
@@ -671,13 +192,8 @@ namespace LLMarketplaceImport
static S32 sImportResultStatus = 0;
static LLSD sImportResults = LLSD::emptyMap();
-#if 0
- static LLTimer slmGetTimer;
- static LLTimer slmPostTimer;
-#endif
// Responders
-#if 1
void marketplacePostCoro(std::string url)
{
LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
@@ -696,7 +212,7 @@ namespace LLMarketplaceImport
httpHeaders->append(HTTP_OUT_HEADER_CONTENT_TYPE, HTTP_CONTENT_XML);
httpHeaders->append(HTTP_OUT_HEADER_USER_AGENT, LLViewerMedia::getCurrentUserAgent());
- LLSD result = httpAdapter->postAndYield(httpRequest, url, LLSD(), httpOpts, httpHeaders);
+ LLSD result = httpAdapter->postAndSuspend(httpRequest, url, LLSD(), httpOpts, httpHeaders);
LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
@@ -739,56 +255,6 @@ namespace LLMarketplaceImport
}
-
-#else
- class LLImportPostResponder : public LLHTTPClient::Responder
- {
- LOG_CLASS(LLImportPostResponder);
- public:
- LLImportPostResponder() : LLCurl::Responder() {}
-
- protected:
- /* virtual */ void httpCompleted()
- {
- slmPostTimer.stop();
-
- if (gSavedSettings.getBOOL("InventoryOutboxLogging"))
- {
- LL_INFOS() << " SLM [timer:" << slmPostTimer.getElapsedTimeF32() << "] "
- << dumpResponse() << LL_ENDL;
- }
-
- S32 status = getStatus();
- if ((status == MarketplaceErrorCodes::IMPORT_REDIRECT) ||
- (status == MarketplaceErrorCodes::IMPORT_AUTHENTICATION_ERROR) ||
- // MAINT-2301 : we determined we can safely ignore that error in that context
- (status == MarketplaceErrorCodes::IMPORT_JOB_TIMEOUT))
- {
- if (gSavedSettings.getBOOL("InventoryOutboxLogging"))
- {
- LL_INFOS() << " SLM POST : Ignoring time out status and treating it as success" << LL_ENDL;
- }
- status = MarketplaceErrorCodes::IMPORT_DONE;
- }
-
- if (status >= MarketplaceErrorCodes::IMPORT_BAD_REQUEST)
- {
- if (gSavedSettings.getBOOL("InventoryOutboxLogging"))
- {
- LL_INFOS() << " SLM POST : Clearing marketplace cookie due to client or server error" << LL_ENDL;
- }
- sMarketplaceCookie.clear();
- }
-
- sImportInProgress = (status == MarketplaceErrorCodes::IMPORT_DONE);
- sImportPostPending = false;
- sImportResultStatus = status;
- sImportId = getContent();
- }
- };
-#endif
-
-#if 1
void marketplaceGetCoro(std::string url, bool buildHeaders)
{
LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
@@ -815,7 +281,7 @@ namespace LLMarketplaceImport
httpHeaders = LLViewerMedia::getHttpHeaders();
}
- LLSD result = httpAdapter->getAndYield(httpRequest, url, httpOpts, httpHeaders);
+ LLSD result = httpAdapter->getAndSuspend(httpRequest, url, httpOpts, httpHeaders);
LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
@@ -854,57 +320,6 @@ namespace LLMarketplaceImport
}
-#else
- class LLImportGetResponder : public LLHTTPClient::Responder
- {
- LOG_CLASS(LLImportGetResponder);
- public:
- LLImportGetResponder() : LLCurl::Responder() {}
-
- protected:
- /* virtual */ void httpCompleted()
- {
- const std::string& set_cookie_string = getResponseHeader(HTTP_IN_HEADER_SET_COOKIE);
-
- if (!set_cookie_string.empty())
- {
- sMarketplaceCookie = set_cookie_string;
- }
-
- slmGetTimer.stop();
-
- if (gSavedSettings.getBOOL("InventoryOutboxLogging"))
- {
- LL_INFOS() << " SLM [timer:" << slmGetTimer.getElapsedTimeF32() << "] "
- << dumpResponse() << LL_ENDL;
- }
-
- // MAINT-2452 : Do not clear the cookie on IMPORT_DONE_WITH_ERRORS : Happens when trying to import objects with wrong permissions
- // ACME-1221 : Do not clear the cookie on IMPORT_NOT_FOUND : Happens for newly created Merchant accounts that are initially empty
- S32 status = getStatus();
- if ((status >= MarketplaceErrorCodes::IMPORT_BAD_REQUEST) &&
- (status != MarketplaceErrorCodes::IMPORT_DONE_WITH_ERRORS) &&
- (status != MarketplaceErrorCodes::IMPORT_NOT_FOUND))
- {
- if (gSavedSettings.getBOOL("InventoryOutboxLogging"))
- {
- LL_INFOS() << " SLM GET clearing marketplace cookie due to client or server error" << LL_ENDL;
- }
- sMarketplaceCookie.clear();
- }
- else if (gSavedSettings.getBOOL("InventoryOutboxLogging") && (status >= MarketplaceErrorCodes::IMPORT_BAD_REQUEST))
- {
- LL_INFOS() << " SLM GET : Got error status = " << status << ", but marketplace cookie not cleared." << LL_ENDL;
- }
-
- sImportInProgress = (status == MarketplaceErrorCodes::IMPORT_PROCESSING);
- sImportGetPending = false;
- sImportResultStatus = status;
- sImportResults = getContent();
- }
- };
-#endif
-
// Basic API
bool hasSessionCookie()
@@ -955,24 +370,9 @@ namespace LLMarketplaceImport
std::string url = getInventoryImportURL();
-#if 1
LLCoros::instance().launch("marketplaceGetCoro",
boost::bind(&marketplaceGetCoro, url, false));
-#else
- if (gSavedSettings.getBOOL("InventoryOutboxLogging"))
- {
- LL_INFOS() << " SLM GET: establishMarketplaceSessionCookie, LLHTTPClient::get, url = " << url << LL_ENDL;
- LLSD headers = LLViewerMedia::getHeaders();
- std::stringstream str;
- LLSDSerialize::toPrettyXML(headers, str);
- LL_INFOS() << " SLM GET: headers " << LL_ENDL;
- LL_INFOS() << str.str() << LL_ENDL;
- }
-
- slmGetTimer.start();
- LLHTTPClient::get(url, new LLImportGetResponder(), LLViewerMedia::getHeaders());
-#endif
return true;
}
@@ -989,31 +389,9 @@ namespace LLMarketplaceImport
url += sImportId.asString();
-#if 1
LLCoros::instance().launch("marketplaceGetCoro",
boost::bind(&marketplaceGetCoro, url, true));
-#else
- // Make the headers for the post
- LLSD headers = LLSD::emptyMap();
- headers[HTTP_OUT_HEADER_ACCEPT] = "*/*";
- headers[HTTP_OUT_HEADER_COOKIE] = sMarketplaceCookie;
- // *TODO: Why are we setting Content-Type for a GET request?
- headers[HTTP_OUT_HEADER_CONTENT_TYPE] = HTTP_CONTENT_LLSD_XML;
- headers[HTTP_OUT_HEADER_USER_AGENT] = LLViewerMedia::getCurrentUserAgent();
-
- if (gSavedSettings.getBOOL("InventoryOutboxLogging"))
- {
- LL_INFOS() << " SLM GET: pollStatus, LLHTTPClient::get, url = " << url << LL_ENDL;
- std::stringstream str;
- LLSDSerialize::toPrettyXML(headers, str);
- LL_INFOS() << " SLM GET: headers " << LL_ENDL;
- LL_INFOS() << str.str() << LL_ENDL;
- }
-
- slmGetTimer.start();
- LLHTTPClient::get(url, new LLImportGetResponder(), headers);
-#endif
return true;
}
@@ -1032,35 +410,13 @@ namespace LLMarketplaceImport
std::string url = getInventoryImportURL();
-#if 1
LLCoros::instance().launch("marketplacePostCoro",
boost::bind(&marketplacePostCoro, url));
-#else
- // Make the headers for the post
- LLSD headers = LLSD::emptyMap();
- headers[HTTP_OUT_HEADER_ACCEPT] = "*/*";
- headers[HTTP_OUT_HEADER_CONNECTION] = "Keep-Alive";
- headers[HTTP_OUT_HEADER_COOKIE] = sMarketplaceCookie;
- headers[HTTP_OUT_HEADER_CONTENT_TYPE] = HTTP_CONTENT_XML;
- headers[HTTP_OUT_HEADER_USER_AGENT] = LLViewerMedia::getCurrentUserAgent();
-
- if (gSavedSettings.getBOOL("InventoryOutboxLogging"))
- {
- LL_INFOS() << " SLM POST: triggerImport, LLHTTPClient::post, url = " << url << LL_ENDL;
- std::stringstream str;
- LLSDSerialize::toPrettyXML(headers, str);
- LL_INFOS() << " SLM POST: headers " << LL_ENDL;
- LL_INFOS() << str.str() << LL_ENDL;
- }
-
- slmPostTimer.start();
- LLHTTPClient::post(url, LLSD(), new LLImportPostResponder(), headers);
-#endif
return true;
}
}
-
+#endif
//
// Interface class
@@ -1362,6 +718,26 @@ LLMarketplaceData::~LLMarketplaceData()
gInventory.removeObserver(mInventoryObserver);
}
+
+LLSD LLMarketplaceData::getMarketplaceStringSubstitutions()
+{
+ std::string marketplace_url = getMarketplaceURL("MarketplaceURL");
+ std::string marketplace_url_create = getMarketplaceURL("MarketplaceURL_CreateStore");
+ std::string marketplace_url_dashboard = getMarketplaceURL("MarketplaceURL_Dashboard");
+ std::string marketplace_url_imports = getMarketplaceURL("MarketplaceURL_Imports");
+ std::string marketplace_url_info = getMarketplaceURL("MarketplaceURL_LearnMore");
+
+ LLSD marketplace_sub_map;
+
+ marketplace_sub_map["[MARKETPLACE_URL]"] = marketplace_url;
+ marketplace_sub_map["[MARKETPLACE_CREATE_STORE_URL]"] = marketplace_url_create;
+ marketplace_sub_map["[MARKETPLACE_LEARN_MORE_URL]"] = marketplace_url_info;
+ marketplace_sub_map["[MARKETPLACE_DASHBOARD_URL]"] = marketplace_url_dashboard;
+ marketplace_sub_map["[MARKETPLACE_IMPORTS_URL]"] = marketplace_url_imports;
+
+ return marketplace_sub_map;
+}
+
void LLMarketplaceData::initializeSLM(const status_updated_signal_t::slot_type& cb)
{
if (mStatusUpdatedSignal == NULL)
@@ -1377,15 +753,60 @@ void LLMarketplaceData::initializeSLM(const status_updated_signal_t::slot_type&
}
else
{
- // Initiate SLM connection and set responder
- std::string url = getSLMConnectURL("/merchant");
- if (url != "")
+ mMarketPlaceStatus = MarketplaceStatusCodes::MARKET_PLACE_INITIALIZING;
+
+ LLCoros::instance().launch("getMerchantStatus",
+ boost::bind(&LLMarketplaceData::getMerchantStatusCoro, this));
+ }
+}
+
+void LLMarketplaceData::getMerchantStatusCoro()
+{
+ LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+ LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+ httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("getMerchantStatusCoro", httpPolicy));
+ LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+ LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions);
+
+ httpOpts->setFollowRedirects(true);
+
+ std::string url = getSLMConnectURL("/merchant");
+ if (url.empty())
+ {
+ LL_INFOS("Marketplace") << "No marketplace capability on Sim" << LL_ENDL;
+ }
+
+ LLSD result = httpAdapter->getAndSuspend(httpRequest, url, httpOpts);
+
+ LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+ LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+ if (!status)
+ {
+ S32 httpCode = status.getType();
+
+ if (httpCode == HTTP_NOT_FOUND)
+ {
+ log_SLM_infos("Get /merchant", httpCode, std::string("User is not a merchant"));
+ setSLMStatus(MarketplaceStatusCodes::MARKET_PLACE_NOT_MERCHANT);
+ }
+ else if (httpCode == HTTP_SERVICE_UNAVAILABLE)
+ {
+ log_SLM_infos("Get /merchant", httpCode, std::string("Merchant is not migrated"));
+ setSLMStatus(MarketplaceStatusCodes::MARKET_PLACE_NOT_MIGRATED_MERCHANT);
+ }
+ else
{
- mMarketPlaceStatus = MarketplaceStatusCodes::MARKET_PLACE_INITIALIZING;
- log_SLM_infos("LLHTTPClient::get", url, "");
- LLHTTPClient::get(url, new LLSLMGetMerchantResponder(), LLSD());
+ std::string err_code = result["error_code"].asString();
+ //std::string err_description = result["error_description"].asString();
+ log_SLM_warning("Get /merchant", httpCode, status.toString(), err_code, result["error_description"]);
+ setSLMStatus(MarketplaceStatusCodes::MARKET_PLACE_CONNECTION_FAILURE);
}
+ return;
}
+
+ log_SLM_infos("Get /merchant", status.getType(), std::string("User is a merchant"));
+ setSLMStatus(MarketplaceStatusCodes::MARKET_PLACE_MERCHANT);
}
void LLMarketplaceData::setDataFetchedSignal(const status_updated_signal_t::slot_type& cb)
@@ -1400,151 +821,434 @@ void LLMarketplaceData::setDataFetchedSignal(const status_updated_signal_t::slot
// Get/Post/Put requests to the SLM Server using the SLM API
void LLMarketplaceData::getSLMListings()
{
- LLSD headers = LLSD::emptyMap();
- headers["Accept"] = "application/json";
- headers["Content-Type"] = "application/json";
-
- // Send request
+ const LLUUID marketplaceFolderId = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false);
+ setUpdating(marketplaceFolderId, true);
+
+ LLCoros::instance().launch("getSLMListings",
+ boost::bind(&LLMarketplaceData::getSLMListingsCoro, this, marketplaceFolderId));
+}
+
+void LLMarketplaceData::getSLMListingsCoro(LLUUID folderId)
+{
+ LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+ LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+ httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("getMerchantStatusCoro", httpPolicy));
+ LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+ LLCore::HttpHeaders::ptr_t httpHeaders(new LLCore::HttpHeaders);
+
+ httpHeaders->append("Accept", "application/json");
+ httpHeaders->append("Content-Type", "application/json");
+
std::string url = getSLMConnectURL("/listings");
- log_SLM_infos("LLHTTPClient::get", url, "");
- const LLUUID marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false);
- setUpdating(marketplacelistings_id,true);
- LLHTTPClient::get(url, new LLSLMGetListingsResponder(marketplacelistings_id), headers);
+
+ LLSD result = httpAdapter->getJsonAndSuspend(httpRequest, url, httpHeaders);
+
+ setUpdating(folderId, false);
+
+ LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+ LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+ if (!status)
+ {
+ log_SLM_warning("Get /listings", status.getType(), status.toString(), "", result);
+ setSLMDataFetched(MarketplaceFetchCodes::MARKET_FETCH_FAILED);
+ update_marketplace_category(folderId, false);
+ gInventory.notifyObservers();
+ return;
+ }
+
+ log_SLM_infos("Get /listings", static_cast<U32>(status.getType()), result);
+
+ // Extract the info from the results
+ for (LLSD::array_iterator it = result["listings"].beginArray();
+ it != result["listings"].endArray(); ++it)
+ {
+ LLSD listing = *it;
+
+ int listingId = listing["id"].asInteger();
+ bool isListed = listing["is_listed"].asBoolean();
+ std::string editUrl = listing["edit_url"].asString();
+ LLUUID folderUuid = listing["inventory_info"]["listing_folder_id"].asUUID();
+ LLUUID versionUuid = listing["inventory_info"]["version_folder_id"].asUUID();
+ int count = listing["inventory_info"]["count_on_hand"].asInteger();
+
+ if (folderUuid.notNull())
+ {
+ addListing(folderUuid, listingId, versionUuid, isListed, editUrl, count);
+ }
+ }
+
+ // Update all folders under the root
+ setSLMDataFetched(MarketplaceFetchCodes::MARKET_FETCH_DONE);
+ update_marketplace_category(folderId, false);
+ gInventory.notifyObservers();
}
-void LLMarketplaceData::getSLMListing(S32 listing_id)
+void LLMarketplaceData::getSLMListing(S32 listingId)
{
- LLSD headers = LLSD::emptyMap();
- headers["Accept"] = "application/json";
- headers["Content-Type"] = "application/json";
-
- // Send request
- std::string url = getSLMConnectURL("/listing/") + llformat("%d",listing_id);
- log_SLM_infos("LLHTTPClient::get", url, "");
- LLUUID folder_id = LLMarketplaceData::instance().getListingFolder(listing_id);
- setUpdating(folder_id,true);
- LLHTTPClient::get(url, new LLSLMGetListingResponder(folder_id), headers);
+ LLUUID folderId = getListingFolder(listingId);
+ setUpdating(folderId, true);
+
+ LLCoros::instance().launch("getSingleListingCoro",
+ boost::bind(&LLMarketplaceData::getSingleListingCoro, this, listingId, folderId));
+}
+
+void LLMarketplaceData::getSingleListingCoro(S32 listingId, LLUUID folderId)
+{
+ LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+ LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+ httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("getMerchantStatusCoro", httpPolicy));
+ LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+ LLCore::HttpHeaders::ptr_t httpHeaders(new LLCore::HttpHeaders);
+
+ httpHeaders->append("Accept", "application/json");
+ httpHeaders->append("Content-Type", "application/json");
+
+ std::string url = getSLMConnectURL("/listing/") + llformat("%d", listingId);
+
+ LLSD result = httpAdapter->getJsonAndSuspend(httpRequest, url, httpHeaders);
+
+ setUpdating(folderId, false);
+
+ LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+ LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+ if (!status)
+ {
+ if (status.getType() == HTTP_NOT_FOUND)
+ {
+ // That listing does not exist -> delete its record from the local SLM data store
+ deleteListing(folderId, false);
+ }
+ else
+ {
+ log_SLM_warning("Get /listing", status.getType(), status.toString(), "", result);
+ }
+
+ update_marketplace_category(folderId, false);
+ gInventory.notifyObservers();
+ return;
+ }
+
+ log_SLM_infos("Get /listings", static_cast<U32>(status.getType()), result);
+
+
+ // Extract the info from the results
+ for (LLSD::array_iterator it = result["listings"].beginArray();
+ it != result["listings"].endArray(); ++it)
+ {
+ LLSD listing = *it;
+
+ int resListingId = listing["id"].asInteger();
+ bool isListed = listing["is_listed"].asBoolean();
+ std::string editUrl = listing["edit_url"].asString();
+ LLUUID folderUuid = listing["inventory_info"]["listing_folder_id"].asUUID();
+ LLUUID versionUuid = listing["inventory_info"]["version_folder_id"].asUUID();
+ int count = listing["inventory_info"]["count_on_hand"].asInteger();
+
+ // Update that listing
+ setListingID(folderUuid, resListingId, false);
+ setVersionFolderID(folderUuid, versionUuid, false);
+ setActivationState(folderUuid, isListed, false);
+ setListingURL(folderUuid, editUrl, false);
+ setCountOnHand(folderUuid, count, false);
+ update_marketplace_category(folderUuid, false);
+ gInventory.notifyObservers();
+ }
}
void LLMarketplaceData::createSLMListing(const LLUUID& folder_id, const LLUUID& version_id, S32 count)
{
- LLSD headers = LLSD::emptyMap();
- headers["Accept"] = "application/json";
- headers["Content-Type"] = "application/json";
-
- // Build the json message
- Json::Value root;
- Json::FastWriter writer;
-
- LLViewerInventoryCategory* category = gInventory.getCategory(folder_id);
- root["listing"]["name"] = category->getName();
- root["listing"]["inventory_info"]["listing_folder_id"] = folder_id.asString();
- root["listing"]["inventory_info"]["version_folder_id"] = version_id.asString();
- root["listing"]["inventory_info"]["count_on_hand"] = count;
-
- std::string json_str = writer.write(root);
-
- // postRaw() takes ownership of the buffer and releases it later.
- size_t size = json_str.size();
- U8 *data = new U8[size];
- memcpy(data, (U8*)(json_str.c_str()), size);
-
- // Send request
- std::string url = getSLMConnectURL("/listings");
- log_SLM_infos("LLHTTPClient::postRaw", url, json_str);
- setUpdating(folder_id,true);
- LLHTTPClient::postRaw(url, data, size, new LLSLMCreateListingsResponder(folder_id), headers);
+ setUpdating(folder_id, true);
+ LLCoros::instance().launch("createSLMListingCoro",
+ boost::bind(&LLMarketplaceData::createSLMListingCoro, this, folder_id, version_id, count));
}
-void LLMarketplaceData::updateSLMListing(const LLUUID& folder_id, S32 listing_id, const LLUUID& version_id, bool is_listed, S32 count)
+void LLMarketplaceData::createSLMListingCoro(LLUUID folderId, LLUUID versionId, S32 count)
{
- LLSD headers = LLSD::emptyMap();
- headers["Accept"] = "application/json";
- headers["Content-Type"] = "application/json";
+ LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+ LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+ httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("getMerchantStatusCoro", httpPolicy));
+ LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+ LLCore::HttpHeaders::ptr_t httpHeaders(new LLCore::HttpHeaders);
- Json::Value root;
- Json::FastWriter writer;
+ httpHeaders->append("Accept", "application/json");
+ httpHeaders->append("Content-Type", "application/json");
- // Note : auto unlist if the count is 0 (out of stock)
- if (is_listed && (count == 0))
+ LLViewerInventoryCategory* category = gInventory.getCategory(folderId);
+ LLSD invInfo;
+ invInfo["listing_folder_id"] = folderId;
+ invInfo["version_folder_id"] = versionId;
+ invInfo["count_on_hand"] = count;
+ LLSD listing;
+ listing["name"] = category->getName();
+ listing["inventory_info"] = invInfo;
+ LLSD postData;
+ postData["listing"] = listing;
+
+ std::string url = getSLMConnectURL("/listings");
+
+ LLSD result = httpAdapter->postJsonAndSuspend(httpRequest, url, postData, httpHeaders);
+
+ setUpdating(folderId, false);
+
+ LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+ LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+ if (!status)
{
- is_listed = false;
- LLNotificationsUtil::add("AlertMerchantStockFolderEmpty");
+ log_SLM_warning("Post /listings", status.getType(), status.toString(), "", result);
+ update_marketplace_category(folderId, false);
+ gInventory.notifyObservers();
+ return;
}
- // Note : we're assuming that sending unchanged info won't break anything server side...
- root["listing"]["id"] = listing_id;
- root["listing"]["is_listed"] = is_listed;
- root["listing"]["inventory_info"]["listing_folder_id"] = folder_id.asString();
- root["listing"]["inventory_info"]["version_folder_id"] = version_id.asString();
- root["listing"]["inventory_info"]["count_on_hand"] = count;
-
- std::string json_str = writer.write(root);
-
- // postRaw() takes ownership of the buffer and releases it later.
- size_t size = json_str.size();
- U8 *data = new U8[size];
- memcpy(data, (U8*)(json_str.c_str()), size);
+ log_SLM_infos("Post /listings", status.getType(), result);
+
+ // Extract the info from the results
+ for (LLSD::array_iterator it = result["listings"].beginArray();
+ it != result["listings"].endArray(); ++it)
+ {
+ LLSD listing = *it;
+
+ int listingId = listing["id"].asInteger();
+ bool isListed = listing["is_listed"].asBoolean();
+ std::string editUrl = listing["edit_url"].asString();
+ LLUUID folderUuid = listing["inventory_info"]["listing_folder_id"].asUUID();
+ LLUUID versionUuid = listing["inventory_info"]["version_folder_id"].asUUID();
+ int count = listing["inventory_info"]["count_on_hand"].asInteger();
+
+ addListing(folderUuid, listingId, versionUuid, isListed, editUrl, count);
+ update_marketplace_category(folderUuid, false);
+ gInventory.notifyObservers();
+ }
+
+}
+
+void LLMarketplaceData::updateSLMListing(const LLUUID& folder_id, S32 listing_id, const LLUUID& version_id, bool is_listed, S32 count)
+{
+ setUpdating(folder_id, true);
+ LLCoros::instance().launch("updateSLMListingCoro",
+ boost::bind(&LLMarketplaceData::updateSLMListingCoro, this, folder_id, listing_id, version_id, is_listed, count));
+}
+
+void LLMarketplaceData::updateSLMListingCoro(LLUUID folderId, S32 listingId, LLUUID versionId, bool isListed, S32 count)
+{
+ LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+ LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+ httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("getMerchantStatusCoro", httpPolicy));
+ LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+ LLCore::HttpHeaders::ptr_t httpHeaders(new LLCore::HttpHeaders);
+
+ httpHeaders->append("Accept", "application/json");
+ httpHeaders->append("Content-Type", "application/json");
- // Send request
- std::string url = getSLMConnectURL("/listing/") + llformat("%d",listing_id);
- log_SLM_infos("LLHTTPClient::putRaw", url, json_str);
- setUpdating(folder_id,true);
- LLHTTPClient::putRaw(url, data, size, new LLSLMUpdateListingsResponder(folder_id, is_listed, version_id), headers);
+ LLSD invInfo;
+ invInfo["listing_folder_id"] = folderId;
+ invInfo["version_folder_id"] = versionId;
+ invInfo["count_on_hand"] = count;
+ LLSD listing;
+ listing["inventory_info"] = invInfo;
+ listing["id"] = listingId;
+ listing["is_listed"] = isListed;
+ LLSD postData;
+ postData["listing"] = listing;
+
+ std::string url = getSLMConnectURL("/listing/") + llformat("%d", listingId);
+ LLSD result = httpAdapter->putJsonAndSuspend(httpRequest, url, postData, httpHeaders);
+
+ setUpdating(folderId, false);
+
+ LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+ LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+ if (!status)
+ {
+ log_SLM_warning("Put /listing", status.getType(), status.toString(), "", result);
+ update_marketplace_category(folderId, false);
+ gInventory.notifyObservers();
+ return;
+ }
+
+ log_SLM_infos("Put /listing", status.getType(), result);
+
+ // Extract the info from the Json string
+ for (LLSD::array_iterator it = result["listings"].beginArray();
+ it != result["listings"].endArray(); ++it)
+ {
+ LLSD listing = *it;
+
+ int listing_id = listing["id"].asInteger();
+ bool is_listed = listing["is_listed"].asBoolean();
+ std::string edit_url = listing["edit_url"].asString();
+ LLUUID folderUuid = listing["inventory_info"]["listing_folder_id"].asUUID();
+ LLUUID versionUuid = listing["inventory_info"]["version_folder_id"].asUUID();
+ int onHand = listing["inventory_info"]["count_on_hand"].asInteger();
+
+ // Update that listing
+ setListingID(folderUuid, listing_id, false);
+ setVersionFolderID(folderUuid, versionUuid, false);
+ setActivationState(folderUuid, is_listed, false);
+ setListingURL(folderUuid, edit_url, false);
+ setCountOnHand(folderUuid, onHand, false);
+ update_marketplace_category(folderUuid, false);
+ gInventory.notifyObservers();
+
+ // Show a notification alert if what we got is not what we expected
+ // (this actually doesn't result in an error status from the SLM API protocol)
+ if ((isListed != is_listed) || (versionId != versionUuid))
+ {
+ LLSD subs;
+ subs["[URL]"] = edit_url;
+ LLNotificationsUtil::add("AlertMerchantListingNotUpdated", subs);
+ }
+ }
+
}
void LLMarketplaceData::associateSLMListing(const LLUUID& folder_id, S32 listing_id, const LLUUID& version_id, const LLUUID& source_folder_id)
{
- LLSD headers = LLSD::emptyMap();
- headers["Accept"] = "application/json";
- headers["Content-Type"] = "application/json";
-
- Json::Value root;
- Json::FastWriter writer;
-
- // Note : we're assuming that sending unchanged info won't break anything server side...
- root["listing"]["id"] = listing_id;
- root["listing"]["inventory_info"]["listing_folder_id"] = folder_id.asString();
- root["listing"]["inventory_info"]["version_folder_id"] = version_id.asString();
-
- std::string json_str = writer.write(root);
-
- // postRaw() takes ownership of the buffer and releases it later.
- size_t size = json_str.size();
- U8 *data = new U8[size];
- memcpy(data, (U8*)(json_str.c_str()), size);
-
- // Send request
- std::string url = getSLMConnectURL("/associate_inventory/") + llformat("%d",listing_id);
- log_SLM_infos("LLHTTPClient::putRaw", url, json_str);
- setUpdating(folder_id,true);
- setUpdating(source_folder_id,true);
- LLHTTPClient::putRaw(url, data, size, new LLSLMAssociateListingsResponder(folder_id,source_folder_id), headers);
+ setUpdating(folder_id, true);
+ setUpdating(source_folder_id, true);
+ LLCoros::instance().launch("associateSLMListingCoro",
+ boost::bind(&LLMarketplaceData::associateSLMListingCoro, this, folder_id, listing_id, version_id, source_folder_id));
}
-void LLMarketplaceData::deleteSLMListing(S32 listing_id)
+void LLMarketplaceData::associateSLMListingCoro(LLUUID folderId, S32 listingId, LLUUID versionId, LLUUID sourceFolderId)
{
- LLSD headers = LLSD::emptyMap();
- headers["Accept"] = "application/json";
- headers["Content-Type"] = "application/json";
-
- // Send request
- std::string url = getSLMConnectURL("/listing/") + llformat("%d",listing_id);
- log_SLM_infos("LLHTTPClient::del", url, "");
- LLUUID folder_id = LLMarketplaceData::instance().getListingFolder(listing_id);
- setUpdating(folder_id,true);
- LLHTTPClient::del(url, new LLSLMDeleteListingsResponder(folder_id), headers);
+ LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+ LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+ httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("getMerchantStatusCoro", httpPolicy));
+ LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+ LLCore::HttpHeaders::ptr_t httpHeaders(new LLCore::HttpHeaders);
+
+ httpHeaders->append("Accept", "application/json");
+ httpHeaders->append("Content-Type", "application/json");
+
+ LLSD invInfo;
+ invInfo["listing_folder_id"] = folderId;
+ invInfo["version_folder_id"] = versionId;
+ LLSD listing;
+ listing["id"] = listingId;
+ listing["inventory_info"] = invInfo;
+ LLSD postData;
+ postData["listing"] = listing;
+
+ // Send request
+ std::string url = getSLMConnectURL("/associate_inventory/") + llformat("%d", listingId);
+
+ LLSD result = httpAdapter->putJsonAndSuspend(httpRequest, url, postData, httpHeaders);
+
+ setUpdating(folderId, false);
+ setUpdating(sourceFolderId, false);
+
+ LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+ LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+ if (!status)
+ {
+ log_SLM_warning("Put /associate_inventory", status.getType(), status.toString(), "", result);
+ update_marketplace_category(folderId, false);
+ update_marketplace_category(sourceFolderId, false);
+ gInventory.notifyObservers();
+ return;
+ }
+
+ log_SLM_infos("Put /associate_inventory", status.getType(), result);
+
+ for (LLSD::array_iterator it = result["listings"].beginArray();
+ it != result["listings"].endArray(); ++it)
+ {
+ LLSD listing = *it;
+
+ int listing_id = listing["id"].asInteger();
+ bool is_listed = listing["is_listed"].asBoolean();
+ std::string edit_url = listing["edit_url"].asString();
+ LLUUID folder_uuid = listing["inventory_info"]["listing_folder_id"].asUUID();
+ LLUUID version_uuid = listing["inventory_info"]["version_folder_id"].asUUID();
+ int count = listing["inventory_info"]["count_on_hand"].asInteger();
+
+ // Check that the listing ID is not already associated to some other record
+ LLUUID old_listing = LLMarketplaceData::instance().getListingFolder(listing_id);
+ if (old_listing.notNull())
+ {
+ // If it is already used, unlist the old record (we can't have 2 listings with the same listing ID)
+ deleteListing(old_listing);
+ }
+
+ // Add the new association
+ addListing(folder_uuid, listing_id, version_uuid, is_listed, edit_url, count);
+ update_marketplace_category(folder_uuid, false);
+ gInventory.notifyObservers();
+
+ // The stock count needs to be updated with the new local count now
+ updateCountOnHand(folder_uuid, 1);
+ }
+
+ // Always update the source folder so its widget updates
+ update_marketplace_category(sourceFolderId, false);
+}
+
+void LLMarketplaceData::deleteSLMListing(S32 listingId)
+{
+ LLCoros::instance().launch("deleteSLMListingCoro",
+ boost::bind(&LLMarketplaceData::deleteSLMListingCoro, this, listingId));
+}
+
+void LLMarketplaceData::deleteSLMListingCoro(S32 listingId)
+{
+ LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+ LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+ httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("getMerchantStatusCoro", httpPolicy));
+ LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+ LLCore::HttpHeaders::ptr_t httpHeaders(new LLCore::HttpHeaders);
+
+ httpHeaders->append("Accept", "application/json");
+ httpHeaders->append("Content-Type", "application/json");
+
+ std::string url = getSLMConnectURL("/listing/") + llformat("%d", listingId);
+ LLUUID folderId = getListingFolder(listingId);
+
+ setUpdating(folderId, true);
+
+ LLSD result = httpAdapter->deleteJsonAndSuspend(httpRequest, url, httpHeaders);
+
+ setUpdating(folderId, false);
+
+ LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+ LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+ if (!status)
+ {
+ log_SLM_warning("Delete /listing", status.getType(), status.toString(), "", result);
+ update_marketplace_category(folderId, false);
+ gInventory.notifyObservers();
+ return;
+ }
+
+ log_SLM_infos("Delete /listing", status.getType(), result);
+
+ for (LLSD::array_iterator it = result["listings"].beginArray();
+ it != result["listings"].endArray(); ++it)
+ {
+ LLSD listing = *it;
+
+ int listing_id = listing["id"].asInteger();
+ LLUUID folder_id = LLMarketplaceData::instance().getListingFolder(listing_id);
+ deleteListing(folder_id);
+ }
+
}
std::string LLMarketplaceData::getSLMConnectURL(const std::string& route)
{
- std::string url("");
+ std::string url;
LLViewerRegion *regionp = gAgent.getRegion();
if (regionp)
{
// Get DirectDelivery cap
url = regionp->getCapability("DirectDelivery");
- if (url != "")
+ if (!url.empty())
{
url += route;
}
@@ -2133,5 +1837,3 @@ bool LLMarketplaceData::setListingURL(const LLUUID& folder_id, const std::string
return true;
}
-
-
diff --git a/indra/newview/llmarketplacefunctions.h b/indra/newview/llmarketplacefunctions.h
index f8e7ed4364..9d795c6ced 100755
--- a/indra/newview/llmarketplacefunctions.h
+++ b/indra/newview/llmarketplacefunctions.h
@@ -37,8 +37,6 @@
#include "llstring.h"
-LLSD getMarketplaceStringSubstitutions();
-
namespace MarketplaceErrorCodes
{
@@ -183,6 +181,8 @@ class LLSLMDeleteListingsResponder;
class LLMarketplaceData
: public LLSingleton<LLMarketplaceData>
{
+ friend class LLSingleton < LLMarketplaceData > ;
+
public:
friend class LLSLMGetMerchantResponder;
friend class LLSLMGetListingsResponder;
@@ -192,9 +192,8 @@ public:
friend class LLSLMAssociateListingsResponder;
friend class LLSLMDeleteListingsResponder;
- LLMarketplaceData();
- virtual ~LLMarketplaceData();
-
+ static LLSD getMarketplaceStringSubstitutions();
+
// Public SLM API : Initialization and status
typedef boost::signals2::signal<void ()> status_updated_signal_t;
void initializeSLM(const status_updated_signal_t::slot_type& cb);
@@ -241,8 +240,11 @@ public:
// Used to decide when to run a validation on listing folders
void setValidationWaiting(const LLUUID& folder_id, S32 count);
void decrementValidationWaiting(const LLUUID& folder_id, S32 count = 1);
-
+
private:
+ LLMarketplaceData();
+ virtual ~LLMarketplaceData();
+
// Modify Marketplace data set : each method returns true if the function succeeds, false if error
// Used internally only by SLM Responders when data are received from the SLM Server
bool addListing(const LLUUID& folder_id, S32 listing_id, const LLUUID& version_id, bool is_listed, const std::string& edit_url, S32 count);
@@ -261,6 +263,14 @@ private:
void deleteSLMListing(S32 listing_id);
std::string getSLMConnectURL(const std::string& route);
+ void getMerchantStatusCoro();
+ void getSLMListingsCoro(LLUUID folderId);
+ void getSingleListingCoro(S32 listingId, LLUUID folderId);
+ void createSLMListingCoro(LLUUID folderId, LLUUID versionId, S32 count);
+ void updateSLMListingCoro(LLUUID folderId, S32 listingId, LLUUID versionId, bool isListed, S32 count);
+ void associateSLMListingCoro(LLUUID folderId, S32 listingId, LLUUID versionId, LLUUID sourceFolderId);
+ void deleteSLMListingCoro(S32 listingId);
+
// Handling Marketplace connection and inventory connection
U32 mMarketPlaceStatus;
status_updated_signal_t* mStatusUpdatedSignal;
diff --git a/indra/newview/llmaterialmgr.cpp b/indra/newview/llmaterialmgr.cpp
index 1045def72e..9ac560c217 100755
--- a/indra/newview/llmaterialmgr.cpp
+++ b/indra/newview/llmaterialmgr.cpp
@@ -579,46 +579,59 @@ void LLMaterialMgr::onIdle(void*)
instancep->mHttpRequest->update(0L);
}
-void LLMaterialMgr::processGetQueue()
+/*static*/
+void LLMaterialMgr::CapsRecvForRegion(const LLUUID& regionId, LLUUID regionTest, std::string pumpname)
{
- get_queue_t::iterator loopRegionQueue = mGetQueue.begin();
- while (mGetQueue.end() != loopRegionQueue)
- {
- get_queue_t::iterator itRegionQueue = loopRegionQueue++;
-
- const LLUUID& region_id = itRegionQueue->first;
- if (isGetAllPending(region_id))
- {
- continue;
- }
-
- LLViewerRegion* regionp = LLWorld::instance().getRegionFromID(region_id);
- if (!regionp)
- {
- LL_WARNS("Materials") << "Unknown region with id " << region_id.asString() << LL_ENDL;
- mGetQueue.erase(itRegionQueue);
- continue;
- }
- else if (!regionp->capabilitiesReceived() || regionp->materialsCapThrottled())
- {
- continue;
- }
- else if (mGetAllRequested.end() == mGetAllRequested.find(region_id))
- {
- LL_DEBUGS("Materials") << "calling getAll for " << regionp->getName() << LL_ENDL;
- getAll(region_id);
- continue;
- }
-
- const std::string capURL = regionp->getCapability(MATERIALS_CAPABILITY_NAME);
- if (capURL.empty())
- {
- LL_WARNS("Materials") << "Capability '" << MATERIALS_CAPABILITY_NAME
- << "' is not defined on region '" << regionp->getName() << "'" << LL_ENDL;
- mGetQueue.erase(itRegionQueue);
- continue;
- }
+ if (regionId == regionTest)
+ {
+ LLEventPumps::instance().obtain(pumpname).post(LLSD());
+ }
+}
+void LLMaterialMgr::processGetQueue()
+{
+ get_queue_t::iterator loopRegionQueue = mGetQueue.begin();
+ while (mGetQueue.end() != loopRegionQueue)
+ {
+#if 1
+ //* $TODO: This block is screaming to be turned into a coroutine.
+ // see processGetQueueCoro() below.
+ //
+ get_queue_t::iterator itRegionQueue = loopRegionQueue++;
+
+ const LLUUID& region_id = itRegionQueue->first;
+ if (isGetAllPending(region_id))
+ {
+ continue;
+ }
+
+ LLViewerRegion* regionp = LLWorld::instance().getRegionFromID(region_id);
+ if (!regionp)
+ {
+ LL_WARNS("Materials") << "Unknown region with id " << region_id.asString() << LL_ENDL;
+ mGetQueue.erase(itRegionQueue);
+ continue;
+ }
+ else if (!regionp->capabilitiesReceived() || regionp->materialsCapThrottled())
+ {
+ continue;
+ }
+ else if (mGetAllRequested.end() == mGetAllRequested.find(region_id))
+ {
+ LL_DEBUGS("Materials") << "calling getAll for " << regionp->getName() << LL_ENDL;
+ getAll(region_id);
+ continue;
+ }
+
+ const std::string capURL = regionp->getCapability(MATERIALS_CAPABILITY_NAME);
+ if (capURL.empty())
+ {
+ LL_WARNS("Materials") << "Capability '" << MATERIALS_CAPABILITY_NAME
+ << "' is not defined on region '" << regionp->getName() << "'" << LL_ENDL;
+ mGetQueue.erase(itRegionQueue);
+ continue;
+ }
+
LLSD materialsData = LLSD::emptyArray();
material_queue_t& materials = itRegionQueue->second;
@@ -652,10 +665,9 @@ void LLMaterialMgr::processGetQueue()
LLSD postData = LLSD::emptyMap();
postData[MATERIALS_CAP_ZIP_FIELD] = materialBinary;
- LLMaterialHttpHandler * handler =
- new LLMaterialHttpHandler("POST",
+ LLCore::HttpHandler::ptr_t handler(new LLMaterialHttpHandler("POST",
boost::bind(&LLMaterialMgr::onGetResponse, this, _1, _2, region_id)
- );
+ ));
LL_DEBUGS("Materials") << "POSTing to region '" << regionp->getName() << "' at '" << capURL << " for " << materialsData.size() << " materials."
<< "\ndata: " << ll_pretty_print_sd(materialsData) << LL_ENDL;
@@ -666,7 +678,6 @@ void LLMaterialMgr::processGetQueue()
if (handle == LLCORE_HTTP_HANDLE_INVALID)
{
- delete handler;
LLCore::HttpStatus status = mHttpRequest->getStatus();
LL_ERRS("Meterials") << "Failed to execute material POST. Status = " <<
status.toULong() << "\"" << status.toString() << "\"" << LL_ENDL;
@@ -674,6 +685,103 @@ void LLMaterialMgr::processGetQueue()
regionp->resetMaterialsCapThrottle();
}
+#endif
+}
+
+void LLMaterialMgr::processGetQueueCoro()
+{
+#if 0
+ get_queue_t::iterator itRegionQueue = loopRegionQueue++;
+
+ const LLUUID& region_id = itRegionQueue->first;
+ if (isGetAllPending(region_id))
+ {
+ continue;
+ }
+
+ LLViewerRegion* regionp = LLWorld::instance().getRegionFromID(region_id);
+ if (!regionp)
+ {
+ LL_WARNS("Materials") << "Unknown region with id " << region_id.asString() << LL_ENDL;
+ mGetQueue.erase(itRegionQueue);
+ continue;
+ }
+ else if (!regionp->capabilitiesReceived() || regionp->materialsCapThrottled())
+ {
+ continue;
+ }
+ else if (mGetAllRequested.end() == mGetAllRequested.find(region_id))
+ {
+ LL_DEBUGS("Materials") << "calling getAll for " << regionp->getName() << LL_ENDL;
+ getAll(region_id);
+ continue;
+ }
+
+ const std::string capURL = regionp->getCapability(MATERIALS_CAPABILITY_NAME);
+ if (capURL.empty())
+ {
+ LL_WARNS("Materials") << "Capability '" << MATERIALS_CAPABILITY_NAME
+ << "' is not defined on region '" << regionp->getName() << "'" << LL_ENDL;
+ mGetQueue.erase(itRegionQueue);
+ continue;
+ }
+
+ LLSD materialsData = LLSD::emptyArray();
+
+ material_queue_t& materials = itRegionQueue->second;
+ U32 max_entries = regionp->getMaxMaterialsPerTransaction();
+ material_queue_t::iterator loopMaterial = materials.begin();
+ while ((materials.end() != loopMaterial) && (materialsData.size() < max_entries))
+ {
+ material_queue_t::iterator itMaterial = loopMaterial++;
+ materialsData.append((*itMaterial).asLLSD());
+ materials.erase(itMaterial);
+ markGetPending(region_id, *itMaterial);
+ }
+ if (materials.empty())
+ {
+ mGetQueue.erase(itRegionQueue);
+ }
+
+ std::string materialString = zip_llsd(materialsData);
+
+ S32 materialSize = materialString.size();
+ if (materialSize <= 0)
+ {
+ LL_ERRS("Materials") << "cannot zip LLSD binary content" << LL_ENDL;
+ return;
+ }
+
+ LLSD::Binary materialBinary;
+ materialBinary.resize(materialSize);
+ memcpy(materialBinary.data(), materialString.data(), materialSize);
+
+ LLSD postData = LLSD::emptyMap();
+ postData[MATERIALS_CAP_ZIP_FIELD] = materialBinary;
+
+ LLMaterialHttpHandler * handler =
+ new LLMaterialHttpHandler("POST",
+ boost::bind(&LLMaterialMgr::onGetResponse, this, _1, _2, region_id)
+ );
+
+ LL_DEBUGS("Materials") << "POSTing to region '" << regionp->getName() << "' at '" << capURL << " for " << materialsData.size() << " materials."
+ << "\ndata: " << ll_pretty_print_sd(materialsData) << LL_ENDL;
+
+ LLCore::HttpHandle handle = LLCoreHttpUtil::requestPostWithLLSD(mHttpRequest,
+ mHttpPolicy, mHttpPriority, capURL,
+ postData, mHttpOptions, mHttpHeaders, handler);
+
+ if (handle == LLCORE_HTTP_HANDLE_INVALID)
+ {
+ delete handler;
+ LLCore::HttpStatus status = mHttpRequest->getStatus();
+ LL_ERRS("Meterials") << "Failed to execute material POST. Status = " <<
+ status.toULong() << "\"" << status.toString() << "\"" << LL_ENDL;
+ }
+
+ regionp->resetMaterialsCapThrottle();
+#endif
+
}
void LLMaterialMgr::processGetAllQueue()
@@ -684,50 +792,87 @@ void LLMaterialMgr::processGetAllQueue()
getall_queue_t::iterator itRegion = loopRegion++;
const LLUUID& region_id = *itRegion;
- LLViewerRegion* regionp = LLWorld::instance().getRegionFromID(region_id);
- if (regionp == NULL)
- {
- LL_WARNS("Materials") << "Unknown region with id " << region_id.asString() << LL_ENDL;
- clearGetQueues(region_id); // Invalidates region_id
- continue;
- }
- else if (!regionp->capabilitiesReceived() || regionp->materialsCapThrottled())
- {
- continue;
- }
- std::string capURL = regionp->getCapability(MATERIALS_CAPABILITY_NAME);
- if (capURL.empty())
- {
- LL_WARNS("Materials") << "Capability '" << MATERIALS_CAPABILITY_NAME
- << "' is not defined on the current region '" << regionp->getName() << "'" << LL_ENDL;
- clearGetQueues(region_id); // Invalidates region_id
- continue;
- }
-
- LL_DEBUGS("Materials") << "GET all for region " << region_id << "url " << capURL << LL_ENDL;
- LLMaterialHttpHandler *handler =
- new LLMaterialHttpHandler("GET",
- boost::bind(&LLMaterialMgr::onGetAllResponse, this, _1, _2, *itRegion)
- );
-
- LLCore::HttpHandle handle = mHttpRequest->requestGet(mHttpPolicy, mHttpPriority, capURL,
- mHttpOptions, mHttpHeaders, handler);
-
- if (handle == LLCORE_HTTP_HANDLE_INVALID)
- {
- delete handler;
- LLCore::HttpStatus status = mHttpRequest->getStatus();
- LL_ERRS("Meterials") << "Failed to execute material GET. Status = " <<
- status.toULong() << "\"" << status.toString() << "\"" << LL_ENDL;
- }
+ LLCoros::instance().launch("LLMaterialMgr::processGetAllQueueCoro", boost::bind(&LLMaterialMgr::processGetAllQueueCoro,
+ this, region_id));
- regionp->resetMaterialsCapThrottle();
- mGetAllPending.insert(std::pair<LLUUID, F64>(region_id, LLFrameTimer::getTotalSeconds()));
+ mGetAllPending.insert(std::pair<LLUUID, F64>(region_id, LLFrameTimer::getTotalSeconds()));
mGetAllQueue.erase(itRegion); // Invalidates region_id
}
}
+void LLMaterialMgr::processGetAllQueueCoro(LLUUID regionId)
+{
+ LLViewerRegion* regionp = LLWorld::instance().getRegionFromID(regionId);
+ if (regionp == NULL)
+ {
+ LL_WARNS("Materials") << "Unknown region with id " << regionId.asString() << LL_ENDL;
+ clearGetQueues(regionId); // Invalidates region_id
+ return;
+ }
+ else if (!regionp->capabilitiesReceived())
+ {
+ LLEventStream capsRecv("waitForCaps", true);
+
+ regionp->setCapabilitiesReceivedCallback(
+ boost::bind(&LLMaterialMgr::CapsRecvForRegion,
+ _1, regionId, capsRecv.getName()));
+
+ llcoro::suspendUntilEventOn(capsRecv);
+
+ // reget the region from the region ID since it may have gone away while waiting.
+ regionp = LLWorld::instance().getRegionFromID(regionId);
+ if (!regionp)
+ {
+ LL_WARNS("Materials") << "Region with ID " << regionId << " is no longer valid." << LL_ENDL;
+ return;
+ }
+ }
+ else if (regionp->materialsCapThrottled())
+ {
+ // TODO:
+ // Figure out how to handle the throttle.
+ }
+
+ std::string capURL = regionp->getCapability(MATERIALS_CAPABILITY_NAME);
+ if (capURL.empty())
+ {
+ LL_WARNS("Materials") << "Capability '" << MATERIALS_CAPABILITY_NAME
+ << "' is not defined on the current region '" << regionp->getName() << "'" << LL_ENDL;
+ clearGetQueues(regionId); // Invalidates region_id
+ return;
+ }
+
+ LL_DEBUGS("Materials") << "GET all for region " << regionId << "url " << capURL << LL_ENDL;
+
+ LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t httpAdapter(
+ new LLCoreHttpUtil::HttpCoroutineAdapter("processGetAllQueue", LLCore::HttpRequest::DEFAULT_POLICY_ID));
+ LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest());
+
+ LLSD result = httpAdapter->getAndSuspend(httpRequest, capURL);
+
+ LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+ LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+ if (!status)
+ {
+ onGetAllResponse(false, LLSD(), regionId);
+ }
+ else
+ {
+ onGetAllResponse(true, result, regionId);
+ }
+
+ // reget the region from the region ID since it may have gone away while waiting.
+ regionp = LLWorld::instance().getRegionFromID(regionId);
+ if (!regionp)
+ {
+ LL_WARNS("Materials") << "Region with ID " << regionId << " is no longer valid." << LL_ENDL;
+ return;
+ }
+ regionp->resetMaterialsCapThrottle();
+}
+
void LLMaterialMgr::processPutQueue()
{
typedef std::map<LLViewerRegion*, LLSD> regionput_request_map;
@@ -749,34 +894,34 @@ void LLMaterialMgr::processPutQueue()
{
LLViewerRegion* regionp = objectp->getRegion();
if ( !regionp )
- {
+ {
LL_WARNS("Materials") << "Object region is NULL" << LL_ENDL;
mPutQueue.erase(itQueue);
- }
+ }
else if ( regionp->capabilitiesReceived() && !regionp->materialsCapThrottled())
{
- LLSD& facesData = requests[regionp];
-
- facematerial_map_t& face_map = itQueue->second;
- U32 max_entries = regionp->getMaxMaterialsPerTransaction();
- facematerial_map_t::iterator itFace = face_map.begin();
- while ( (face_map.end() != itFace) && (facesData.size() < max_entries) )
- {
- LLSD faceData = LLSD::emptyMap();
- faceData[MATERIALS_CAP_FACE_FIELD] = static_cast<LLSD::Integer>(itFace->first);
- faceData[MATERIALS_CAP_OBJECT_ID_FIELD] = static_cast<LLSD::Integer>(objectp->getLocalID());
- if (!itFace->second.isNull())
- {
- faceData[MATERIALS_CAP_MATERIAL_FIELD] = itFace->second.asLLSD();
- }
- facesData.append(faceData);
- face_map.erase(itFace++);
- }
- if (face_map.empty())
- {
- mPutQueue.erase(itQueue);
- }
- }
+ LLSD& facesData = requests[regionp];
+
+ facematerial_map_t& face_map = itQueue->second;
+ U32 max_entries = regionp->getMaxMaterialsPerTransaction();
+ facematerial_map_t::iterator itFace = face_map.begin();
+ while ( (face_map.end() != itFace) && (facesData.size() < max_entries) )
+ {
+ LLSD faceData = LLSD::emptyMap();
+ faceData[MATERIALS_CAP_FACE_FIELD] = static_cast<LLSD::Integer>(itFace->first);
+ faceData[MATERIALS_CAP_OBJECT_ID_FIELD] = static_cast<LLSD::Integer>(objectp->getLocalID());
+ if (!itFace->second.isNull())
+ {
+ faceData[MATERIALS_CAP_MATERIAL_FIELD] = itFace->second.asLLSD();
+ }
+ facesData.append(faceData);
+ face_map.erase(itFace++);
+ }
+ if (face_map.empty())
+ {
+ mPutQueue.erase(itQueue);
+ }
+ }
}
}
@@ -809,10 +954,9 @@ void LLMaterialMgr::processPutQueue()
LL_DEBUGS("Materials") << "put for " << itRequest->second.size() << " faces to region " << itRequest->first->getName() << LL_ENDL;
- LLMaterialHttpHandler * handler =
- new LLMaterialHttpHandler("PUT",
- boost::bind(&LLMaterialMgr::onPutResponse, this, _1, _2)
- );
+ LLCore::HttpHandler::ptr_t handler (new LLMaterialHttpHandler("PUT",
+ boost::bind(&LLMaterialMgr::onPutResponse, this, _1, _2)
+ ));
LLCore::HttpHandle handle = LLCoreHttpUtil::requestPutWithLLSD(
mHttpRequest, mHttpPolicy, mHttpPriority, capURL,
@@ -820,7 +964,6 @@ void LLMaterialMgr::processPutQueue()
if (handle == LLCORE_HTTP_HANDLE_INVALID)
{
- delete handler;
LLCore::HttpStatus status = mHttpRequest->getStatus();
LL_ERRS("Meterials") << "Failed to execute material PUT. Status = " <<
status.toULong() << "\"" << status.toString() << "\"" << LL_ENDL;
@@ -838,6 +981,7 @@ void LLMaterialMgr::processPutQueue()
void LLMaterialMgr::clearGetQueues(const LLUUID& region_id)
{
mGetQueue.erase(region_id);
+
for (get_pending_map_t::iterator itPending = mGetPending.begin(); itPending != mGetPending.end();)
{
if (region_id == itPending->first.first)
diff --git a/indra/newview/llmaterialmgr.h b/indra/newview/llmaterialmgr.h
index ef202d24ba..36dd0904b6 100644
--- a/indra/newview/llmaterialmgr.h
+++ b/indra/newview/llmaterialmgr.h
@@ -67,9 +67,14 @@ private:
const LLMaterialPtr setMaterial(const LLUUID& region_id, const LLMaterialID& material_id, const LLSD& material_data);
static void onIdle(void*);
+
+ static void CapsRecvForRegion(const LLUUID& regionId, LLUUID regionTest, std::string pumpname);
+
void processGetQueue();
+ void processGetQueueCoro();
void onGetResponse(bool success, const LLSD& content, const LLUUID& region_id);
void processGetAllQueue();
+ void processGetAllQueueCoro(LLUUID regionId);
void onGetAllResponse(bool success, const LLSD& content, const LLUUID& region_id);
void processPutQueue();
void onPutResponse(bool success, const LLSD& content);
@@ -116,7 +121,9 @@ private:
typedef std::map<U8, LLMaterial> facematerial_map_t;
typedef std::map<LLUUID, facematerial_map_t> put_queue_t;
+
get_queue_t mGetQueue;
+ uuid_set_t mRegionGets;
get_pending_map_t mGetPending;
get_callback_map_t mGetCallbacks;
diff --git a/indra/newview/llmediactrl.cpp b/indra/newview/llmediactrl.cpp
index b96bdd73ff..73faed7ef5 100755
--- a/indra/newview/llmediactrl.cpp
+++ b/indra/newview/llmediactrl.cpp
@@ -95,6 +95,7 @@ LLMediaCtrl::LLMediaCtrl( const Params& p) :
mStretchToFill( true ),
mMaintainAspectRatio ( true ),
mDecoupleTextureSize ( false ),
+ mUpdateScrolls( false ),
mTextureWidth ( 1024 ),
mTextureHeight ( 1024 ),
mClearCache(false),
@@ -682,7 +683,13 @@ bool LLMediaCtrl::ensureMediaSourceExists()
mMediaSource->addObserver( this );
mMediaSource->setBackgroundColor( getBackgroundColor() );
mMediaSource->setTrustedBrowser(mTrusted);
- mMediaSource->setPageZoomFactor( LLUI::getScaleFactor().mV[ VX ] );
+
+ F32 scale_factor = LLUI::getScaleFactor().mV[ VX ];
+ if (scale_factor != mMediaSource->getPageZoomFactor())
+ {
+ mMediaSource->setPageZoomFactor( scale_factor );
+ mUpdateScrolls = true;
+ }
if(mClearCache)
{
@@ -720,10 +727,11 @@ void LLMediaCtrl::draw()
{
F32 alpha = getDrawContext().mAlpha;
- if ( gRestoreGL == 1 )
+ if ( gRestoreGL == 1 || mUpdateScrolls)
{
LLRect r = getRect();
reshape( r.getWidth(), r.getHeight(), FALSE );
+ mUpdateScrolls = false;
return;
}
@@ -765,7 +773,12 @@ void LLMediaCtrl::draw()
{
gGL.pushUIMatrix();
{
- mMediaSource->setPageZoomFactor( LLUI::getScaleFactor().mV[ VX ] );
+ F32 scale_factor = LLUI::getScaleFactor().mV[ VX ];
+ if (scale_factor != mMediaSource->getPageZoomFactor())
+ {
+ mMediaSource->setPageZoomFactor( scale_factor );
+ mUpdateScrolls = true;
+ }
// scale texture to fit the space using texture coords
gGL.getTexUnit(0)->bind(media_texture);
@@ -970,11 +983,11 @@ void LLMediaCtrl::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event)
case MEDIA_EVENT_CLICK_LINK_HREF:
{
- LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_CLICK_LINK_HREF, target is \"" << self->getClickTarget() << "\", uri is " << self->getClickURL() << LL_ENDL;
// retrieve the event parameters
std::string url = self->getClickURL();
- std::string target = self->getClickTarget();
+ std::string target = self->isOverrideClickTarget() ? self->getOverrideClickTarget() : self->getClickTarget();
std::string uuid = self->getClickUUID();
+ LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_CLICK_LINK_HREF, target is \"" << target << "\", uri is " << url << LL_ENDL;
LLNotification::Params notify_params;
notify_params.name = "PopupAttempt";
diff --git a/indra/newview/llmediactrl.h b/indra/newview/llmediactrl.h
index 785c57b78a..988733b85a 100755
--- a/indra/newview/llmediactrl.h
+++ b/indra/newview/llmediactrl.h
@@ -192,7 +192,8 @@ public:
mHidingInitialLoad,
mClearCache,
mHoverTextChanged,
- mDecoupleTextureSize;
+ mDecoupleTextureSize,
+ mUpdateScrolls;
std::string mHomePageUrl,
mHomePageMimeType,
diff --git a/indra/newview/llmediadataclient.cpp b/indra/newview/llmediadataclient.cpp
index b8ff76aa6d..bd8f464acd 100755
--- a/indra/newview/llmediadataclient.cpp
+++ b/indra/newview/llmediadataclient.cpp
@@ -353,14 +353,12 @@ void LLMediaDataClient::serviceQueue()
trackRequest(request);
// and make the post
- LLHttpSDHandler *handler = request->createHandler();
+ LLCore::HttpHandler::ptr_t handler = request->createHandler();
LLCore::HttpHandle handle = LLCoreHttpUtil::requestPostWithLLSD(mHttpRequest, mHttpPolicy, 0,
url, sd_payload, mHttpOpts, mHttpHeaders, handler);
if (handle == LLCORE_HTTP_HANDLE_INVALID)
{
- // *TODO: Change this metaphore to use boost::shared_ptr<> for handlers. Requires change in LLCore::HTTP
- delete handler;
LLCore::HttpStatus status = mHttpRequest->getStatus();
LL_WARNS("LLMediaDataClient") << "'" << url << "' request POST failed. Reason "
<< status.toTerseString() << " \"" << status.toString() << "\"" << LL_ENDL;
@@ -631,14 +629,8 @@ void LLMediaDataClient::Handler::onFailure(LLCore::HttpResponse * response, LLCo
if (status == LLCore::HttpStatus(HTTP_SERVICE_UNAVAILABLE))
{
F32 retry_timeout;
-#if 0
- // *TODO: Honor server Retry-After header.
- if (!hasResponseHeader(HTTP_IN_HEADER_RETRY_AFTER)
- || !getSecondsUntilRetryAfter(getResponseHeader(HTTP_IN_HEADER_RETRY_AFTER), retry_timeout))
-#endif
- {
- retry_timeout = mRequest->getRetryTimerDelay();
- }
+
+ retry_timeout = mRequest->getRetryTimerDelay();
mRequest->incRetryCount();
@@ -884,9 +876,9 @@ LLSD LLObjectMediaDataClient::RequestGet::getPayload() const
return result;
}
-LLHttpSDHandler *LLObjectMediaDataClient::RequestGet::createHandler()
+LLCore::HttpHandler::ptr_t LLObjectMediaDataClient::RequestGet::createHandler()
{
- return new LLObjectMediaDataClient::Handler(shared_from_this());
+ return LLCore::HttpHandler::ptr_t(new LLObjectMediaDataClient::Handler(shared_from_this()));
}
@@ -920,10 +912,10 @@ LLSD LLObjectMediaDataClient::RequestUpdate::getPayload() const
return result;
}
-LLHttpSDHandler *LLObjectMediaDataClient::RequestUpdate::createHandler()
+LLCore::HttpHandler::ptr_t LLObjectMediaDataClient::RequestUpdate::createHandler()
{
// This just uses the base class's responder.
- return new LLMediaDataClient::Handler(shared_from_this());
+ return LLCore::HttpHandler::ptr_t(new LLMediaDataClient::Handler(shared_from_this()));
}
void LLObjectMediaDataClient::Handler::onSuccess(LLCore::HttpResponse * response, const LLSD &content)
@@ -1055,9 +1047,9 @@ LLSD LLObjectMediaNavigateClient::RequestNavigate::getPayload() const
return result;
}
-LLHttpSDHandler *LLObjectMediaNavigateClient::RequestNavigate::createHandler()
+LLCore::HttpHandler::ptr_t LLObjectMediaNavigateClient::RequestNavigate::createHandler()
{
- return new LLObjectMediaNavigateClient::Handler(shared_from_this());
+ return LLCore::HttpHandler::ptr_t(new LLObjectMediaNavigateClient::Handler(shared_from_this()));
}
void LLObjectMediaNavigateClient::Handler::onSuccess(LLCore::HttpResponse * response, const LLSD &content)
diff --git a/indra/newview/llmediadataclient.h b/indra/newview/llmediadataclient.h
index 9907897613..58f8bad3e4 100755
--- a/indra/newview/llmediadataclient.h
+++ b/indra/newview/llmediadataclient.h
@@ -124,7 +124,7 @@ protected:
// Subclasses must implement this to build a payload for their request type.
virtual LLSD getPayload() const = 0;
// and must create the correct type of responder.
- virtual LLHttpSDHandler *createHandler() = 0;
+ virtual LLCore::HttpHandler::ptr_t createHandler() = 0;
virtual std::string getURL() { return ""; }
@@ -324,7 +324,7 @@ public:
public:
RequestGet(LLMediaDataClientObject *obj, LLMediaDataClient *mdc);
/*virtual*/ LLSD getPayload() const;
- /*virtual*/ LLHttpSDHandler *createHandler();
+ /*virtual*/ LLCore::HttpHandler::ptr_t createHandler();
};
class RequestUpdate: public Request
@@ -332,7 +332,7 @@ public:
public:
RequestUpdate(LLMediaDataClientObject *obj, LLMediaDataClient *mdc);
/*virtual*/ LLSD getPayload() const;
- /*virtual*/ LLHttpSDHandler *createHandler();
+ /*virtual*/ LLCore::HttpHandler::ptr_t createHandler();
};
// Returns true iff the queue is empty
@@ -409,7 +409,7 @@ public:
public:
RequestNavigate(LLMediaDataClientObject *obj, LLMediaDataClient *mdc, U8 texture_index, const std::string &url);
/*virtual*/ LLSD getPayload() const;
- /*virtual*/ LLHttpSDHandler *createHandler();
+ /*virtual*/ LLCore::HttpHandler::ptr_t createHandler();
/*virtual*/ std::string getURL() { return mURL; }
private:
std::string mURL;
diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp
index 5bd9df54e2..e42367ad9e 100755
--- a/indra/newview/llmeshrepository.cpp
+++ b/indra/newview/llmeshrepository.cpp
@@ -1,4 +1,4 @@
-/**
+/**
* @file llmeshrepository.cpp
* @brief Mesh repository implementation.
*
@@ -36,7 +36,6 @@
#include "llappviewer.h"
#include "llbufferstream.h"
#include "llcallbacklist.h"
-#include "llcurl.h"
#include "lldatapacker.h"
#include "lldeadmantimer.h"
#include "llfloatermodelpreview.h"
@@ -393,6 +392,19 @@ U32 LLMeshRepository::sMaxLockHoldoffs = 0;
LLDeadmanTimer LLMeshRepository::sQuiescentTimer(15.0, false); // true -> gather cpu metrics
+namespace {
+ // The NoOpDeletor is used when passing certain objects (generally the LLMeshUploadThread)
+ // in a smart pointer below for passage into the LLCore::Http libararies.
+ // When the smart pointer is destroyed, no action will be taken since we
+ // do not in these cases want the object to be destroyed at the end of the call.
+ //
+ // *NOTE$: Yes! It is "Deletor"
+ // http://english.stackexchange.com/questions/4733/what-s-the-rule-for-adding-er-vs-or-when-nouning-a-verb
+ // "delete" derives from Latin "deletus"
+
+ void NoOpDeletor(LLCore::HttpHandler *)
+ { /*NoOp*/ }
+}
static S32 dump_num = 0;
std::string make_dump_name(std::string prefix, S32 num)
@@ -508,6 +520,12 @@ void get_vertex_buffer_from_mesh(LLCDMeshData& mesh, LLModel::PhysicsMesh& res,
}
}
+LLViewerFetchedTexture* LLMeshUploadThread::FindViewerTexture(const LLImportMaterial& material)
+{
+ LLPointer< LLViewerFetchedTexture > * ppTex = static_cast< LLPointer< LLViewerFetchedTexture > * >(material.mOpaqueData);
+ return ppTex ? (*ppTex).get() : NULL;
+}
+
volatile S32 LLMeshRepoThread::sActiveHeaderRequests = 0;
volatile S32 LLMeshRepoThread::sActiveLODRequests = 0;
U32 LLMeshRepoThread::sMaxConcurrentRequests = 1;
@@ -533,9 +551,12 @@ S32 LLMeshRepoThread::sRequestWaterLevel = 0;
// LLMeshPhysicsShapeHandler
// LLMeshUploadThread
-class LLMeshHandlerBase : public LLCore::HttpHandler
+class LLMeshHandlerBase : public LLCore::HttpHandler,
+ public boost::enable_shared_from_this<LLMeshHandlerBase>
{
public:
+ typedef boost::shared_ptr<LLMeshHandlerBase> ptr_t;
+
LOG_CLASS(LLMeshHandlerBase);
LLMeshHandlerBase(U32 offset, U32 requested_bytes)
: LLCore::HttpHandler(),
@@ -602,16 +623,16 @@ public:
LLMeshLODHandler(const LLVolumeParams & mesh_params, S32 lod, U32 offset, U32 requested_bytes)
: LLMeshHandlerBase(offset, requested_bytes),
mLOD(lod)
- {
+ {
mMeshParams = mesh_params;
LLMeshRepoThread::incActiveLODRequests();
}
virtual ~LLMeshLODHandler();
-
+
protected:
LLMeshLODHandler(const LLMeshLODHandler &); // Not defined
void operator=(const LLMeshLODHandler &); // Not defined
-
+
public:
virtual void processData(LLCore::BufferArray * body, S32 body_offset, U8 * data, S32 data_size);
virtual void processFailure(LLCore::HttpStatus status);
@@ -811,7 +832,7 @@ LLMeshRepoThread::LLMeshRepoThread()
mHttpLargePolicyClass = app_core_http.getPolicy(LLAppCoreHttp::AP_LARGE_MESH);
}
-
+
LLMeshRepoThread::~LLMeshRepoThread()
{
LL_INFOS(LOG_MESH) << "Small GETs issued: " << LLMeshRepository::sHTTPRequestCount
@@ -819,12 +840,6 @@ LLMeshRepoThread::~LLMeshRepoThread()
<< ", Max Lock Holdoffs: " << LLMeshRepository::sMaxLockHoldoffs
<< LL_ENDL;
- for (http_request_set::iterator iter(mHttpRequestSet.begin());
- iter != mHttpRequestSet.end();
- ++iter)
- {
- delete *iter;
- }
mHttpRequestSet.clear();
mHttpHeaders.reset();
@@ -867,16 +882,16 @@ void LLMeshRepoThread::run()
{
break;
}
-
+
if (! mHttpRequestSet.empty())
{
// Dispatch all HttpHandler notifications
mHttpRequest->update(0L);
}
sRequestWaterLevel = mHttpRequestSet.size(); // Stats data update
-
- // NOTE: order of queue processing intentionally favors LOD requests over header requests
+ // NOTE: order of queue processing intentionally favors LOD requests over header requests
+
while (!mLODReqQ.empty() && mHttpRequestSet.size() < sRequestHighWater)
{
if (! mMutex)
@@ -940,7 +955,7 @@ void LLMeshRepoThread::run()
mSkinRequests.erase(iter);
mMutex->unlock();
- if (!fetchMeshSkinInfo(mesh_id))
+ if (! fetchMeshSkinInfo(mesh_id))
{
incomplete.insert(mesh_id);
}
@@ -969,7 +984,7 @@ void LLMeshRepoThread::run()
mDecompositionRequests.erase(iter);
mMutex->unlock();
- if (!fetchMeshDecomposition(mesh_id))
+ if (! fetchMeshDecomposition(mesh_id))
{
incomplete.insert(mesh_id);
}
@@ -995,7 +1010,7 @@ void LLMeshRepoThread::run()
mPhysicsShapeRequests.erase(iter);
mMutex->unlock();
- if (!fetchMeshPhysicsShape(mesh_id))
+ if (! fetchMeshPhysicsShape(mesh_id))
{
incomplete.insert(mesh_id);
}
@@ -1156,7 +1171,7 @@ void LLMeshRepoThread::constructUrl(LLUUID mesh_id, std::string * url, int * ver
// Thread: repo
LLCore::HttpHandle LLMeshRepoThread::getByteRange(const std::string & url, int cap_version,
size_t offset, size_t len,
- LLCore::HttpHandler * handler)
+ const LLCore::HttpHandler::ptr_t &handler)
{
// Also used in lltexturefetch.cpp
static LLCachedControl<bool> disable_range_req(gSavedSettings, "HttpRangeRequestsDisable", false);
@@ -1221,7 +1236,7 @@ bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id)
}
++LLMeshRepository::sMeshRequestCount;
- bool ret = true ;
+ bool ret = true;
U32 header_size = mMeshHeaderSize[mesh_id];
if (header_size > 0)
@@ -1269,8 +1284,8 @@ bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id)
constructUrl(mesh_id, &http_url, &cap_version);
if (!http_url.empty())
- {
- LLMeshSkinInfoHandler * handler = new LLMeshSkinInfoHandler(mesh_id, offset, size);
+ {
+ LLMeshHandlerBase::ptr_t handler(new LLMeshSkinInfoHandler(mesh_id, offset, size));
LLCore::HttpHandle handle = getByteRange(http_url, cap_version, offset, size, handler);
if (LLCORE_HTTP_HANDLE_INVALID == handle)
{
@@ -1278,7 +1293,6 @@ bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id)
<< ". Reason: " << mHttpStatus.toString()
<< " (" << mHttpStatus.toTerseString() << ")"
<< LL_ENDL;
- delete handler;
ret = false;
}
else
@@ -1315,7 +1329,7 @@ bool LLMeshRepoThread::fetchMeshDecomposition(const LLUUID& mesh_id)
++LLMeshRepository::sMeshRequestCount;
U32 header_size = mMeshHeaderSize[mesh_id];
- bool ret = true ;
+ bool ret = true;
if (header_size > 0)
{
@@ -1361,10 +1375,10 @@ bool LLMeshRepoThread::fetchMeshDecomposition(const LLUUID& mesh_id)
int cap_version(2);
std::string http_url;
constructUrl(mesh_id, &http_url, &cap_version);
-
+
if (!http_url.empty())
- {
- LLMeshDecompositionHandler * handler = new LLMeshDecompositionHandler(mesh_id, offset, size);
+ {
+ LLMeshHandlerBase::ptr_t handler(new LLMeshDecompositionHandler(mesh_id, offset, size));
LLCore::HttpHandle handle = getByteRange(http_url, cap_version, offset, size, handler);
if (LLCORE_HTTP_HANDLE_INVALID == handle)
{
@@ -1372,7 +1386,6 @@ bool LLMeshRepoThread::fetchMeshDecomposition(const LLUUID& mesh_id)
<< ". Reason: " << mHttpStatus.toString()
<< " (" << mHttpStatus.toTerseString() << ")"
<< LL_ENDL;
- delete handler;
ret = false;
}
else
@@ -1409,7 +1422,7 @@ bool LLMeshRepoThread::fetchMeshPhysicsShape(const LLUUID& mesh_id)
++LLMeshRepository::sMeshRequestCount;
U32 header_size = mMeshHeaderSize[mesh_id];
- bool ret = true ;
+ bool ret = true;
if (header_size > 0)
{
@@ -1454,10 +1467,10 @@ bool LLMeshRepoThread::fetchMeshPhysicsShape(const LLUUID& mesh_id)
int cap_version(2);
std::string http_url;
constructUrl(mesh_id, &http_url, &cap_version);
-
+
if (!http_url.empty())
- {
- LLMeshPhysicsShapeHandler * handler = new LLMeshPhysicsShapeHandler(mesh_id, offset, size);
+ {
+ LLMeshHandlerBase::ptr_t handler(new LLMeshPhysicsShapeHandler(mesh_id, offset, size));
LLCore::HttpHandle handle = getByteRange(http_url, cap_version, offset, size, handler);
if (LLCORE_HTTP_HANDLE_INVALID == handle)
{
@@ -1465,7 +1478,6 @@ bool LLMeshRepoThread::fetchMeshPhysicsShape(const LLUUID& mesh_id)
<< ". Reason: " << mHttpStatus.toString()
<< " (" << mHttpStatus.toTerseString() << ")"
<< LL_ENDL;
- delete handler;
ret = false;
}
else
@@ -1545,18 +1557,18 @@ bool LLMeshRepoThread::fetchMeshHeader(const LLVolumeParams& mesh_params)
}
//either cache entry doesn't exist or is corrupt, request header from simulator
- bool retval = true ;
+ bool retval = true;
int cap_version(2);
std::string http_url;
constructUrl(mesh_params.getSculptID(), &http_url, &cap_version);
-
+
if (!http_url.empty())
{
//grab first 4KB if we're going to bother with a fetch. Cache will prevent future fetches if a full mesh fits
//within the first 4KB
//NOTE -- this will break of headers ever exceed 4KB
- LLMeshHeaderHandler * handler = new LLMeshHeaderHandler(mesh_params, 0, MESH_HEADER_SIZE);
+ LLMeshHandlerBase::ptr_t handler(new LLMeshHeaderHandler(mesh_params, 0, MESH_HEADER_SIZE));
LLCore::HttpHandle handle = getByteRange(http_url, cap_version, 0, MESH_HEADER_SIZE, handler);
if (LLCORE_HTTP_HANDLE_INVALID == handle)
{
@@ -1564,7 +1576,6 @@ bool LLMeshRepoThread::fetchMeshHeader(const LLVolumeParams& mesh_params)
<< ". Reason: " << mHttpStatus.toString()
<< " (" << mHttpStatus.toTerseString() << ")"
<< LL_ENDL;
- delete handler;
retval = false;
}
else
@@ -1637,10 +1648,10 @@ bool LLMeshRepoThread::fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod)
int cap_version(2);
std::string http_url;
constructUrl(mesh_id, &http_url, &cap_version);
-
+
if (!http_url.empty())
- {
- LLMeshLODHandler * handler = new LLMeshLODHandler(mesh_params, lod, offset, size);
+ {
+ LLMeshHandlerBase::ptr_t handler(new LLMeshLODHandler(mesh_params, lod, offset, size));
LLCore::HttpHandle handle = getByteRange(http_url, cap_version, offset, size, handler);
if (LLCORE_HTTP_HANDLE_INVALID == handle)
{
@@ -1648,7 +1659,6 @@ bool LLMeshRepoThread::fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod)
<< ". Reason: " << mHttpStatus.toString()
<< " (" << mHttpStatus.toTerseString() << ")"
<< LL_ENDL;
- delete handler;
retval = false;
}
else
@@ -1911,7 +1921,7 @@ LLMeshUploadThread::LLMeshUploadThread(LLMeshUploadThread::instance_list& data,
mOrigin += gAgent.getAtAxis() * scale.magVec();
- mMeshUploadTimeOut = gSavedSettings.getS32("MeshUploadTimeOut") ;
+ mMeshUploadTimeOut = gSavedSettings.getS32("MeshUploadTimeOut");
mHttpRequest = new LLCore::HttpRequest;
mHttpOptions = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions);
@@ -1969,14 +1979,14 @@ void LLMeshUploadThread::preStart()
void LLMeshUploadThread::discard()
{
- LLMutexLock lock(mMutex) ;
+ LLMutexLock lock(mMutex);
mDiscarded = true;
}
bool LLMeshUploadThread::isDiscarded() const
{
- LLMutexLock lock(mMutex) ;
- return mDiscarded ;
+ LLMutexLock lock(mMutex);
+ return mDiscarded;
}
void LLMeshUploadThread::run()
@@ -2041,6 +2051,14 @@ void LLMeshUploadThread::wholeModelToLLSD(LLSD& dest, bool include_textures)
{
LLMeshUploadData data;
data.mBaseModel = iter->first;
+
+ if (data.mBaseModel->mSubmodelID)
+ {
+ // These are handled below to insure correct parenting order on creation
+ // due to map walking being based on model address (aka random)
+ continue;
+ }
+
LLModelInstance& first_instance = *(iter->second.begin());
for (S32 i = 0; i < 5; i++)
{
@@ -2078,7 +2096,10 @@ void LLMeshUploadThread::wholeModelToLLSD(LLSD& dest, bool include_textures)
data.mModel[LLModel::LOD_IMPOSTOR],
decomp,
mUploadSkin,
- mUploadJoints);
+ mUploadJoints,
+ FALSE,
+ FALSE,
+ data.mBaseModel->mSubmodelID);
data.mAssetData = ostr.str();
std::string str = ostr.str();
@@ -2112,17 +2133,26 @@ void LLMeshUploadThread::wholeModelToLLSD(LLSD& dest, bool include_textures)
instance_entry["scale"] = ll_sd_from_vector3(scale);
instance_entry["material"] = LL_MCODE_WOOD;
- instance_entry["physics_shape_type"] = (U8)(LLViewerObject::PHYSICS_SHAPE_CONVEX_HULL);
+ instance_entry["physics_shape_type"] = data.mModel[LLModel::LOD_PHYSICS].notNull() ? (U8)(LLViewerObject::PHYSICS_SHAPE_PRIM) : (U8)(LLViewerObject::PHYSICS_SHAPE_CONVEX_HULL);
instance_entry["mesh"] = mesh_index[data.mBaseModel];
instance_entry["face_list"] = LLSD::emptyArray();
- S32 end = llmin((S32)data.mBaseModel->mMaterialList.size(), data.mBaseModel->getNumVolumeFaces()) ;
+ // We want to be able to allow more than 8 materials...
+ //
+ S32 end = llmin((S32)instance.mMaterial.size(), instance.mModel->getNumVolumeFaces()) ;
+
for (S32 face_num = 0; face_num < end; face_num++)
{
LLImportMaterial& material = instance.mMaterial[data.mBaseModel->mMaterialList[face_num]];
LLSD face_entry = LLSD::emptyMap();
- LLViewerFetchedTexture *texture = material.mDiffuseMap.get();
+
+ LLViewerFetchedTexture *texture = NULL;
+
+ if (material.mDiffuseMapFilename.size())
+ {
+ texture = FindViewerTexture(material);
+ }
if ((texture != NULL) &&
(textures.find(texture) == textures.end()))
@@ -2137,9 +2167,171 @@ void LLMeshUploadThread::wholeModelToLLSD(LLSD& dest, bool include_textures)
{
LLPointer<LLImageJ2C> upload_file =
LLViewerTextureList::convertToUploadFile(texture->getSavedRawImage());
+
+ if (!upload_file.isNull() && upload_file->getDataSize())
+ {
+ texture_str.write((const char*) upload_file->getData(), upload_file->getDataSize());
+ }
+ }
+ }
+
+ if (texture != NULL &&
+ mUploadTextures &&
+ texture_index.find(texture) == texture_index.end())
+ {
+ texture_index[texture] = texture_num;
+ std::string str = texture_str.str();
+ res["texture_list"][texture_num] = LLSD::Binary(str.begin(),str.end());
+ texture_num++;
+ }
+
+ // Subset of TextureEntry fields.
+ if (texture != NULL && mUploadTextures)
+ {
+ face_entry["image"] = texture_index[texture];
+ face_entry["scales"] = 1.0;
+ face_entry["scalet"] = 1.0;
+ face_entry["offsets"] = 0.0;
+ face_entry["offsett"] = 0.0;
+ face_entry["imagerot"] = 0.0;
+ }
+ face_entry["diffuse_color"] = ll_sd_from_color4(material.mDiffuseColor);
+ face_entry["fullbright"] = material.mFullbright;
+ instance_entry["face_list"][face_num] = face_entry;
+ }
+
+ res["instance_list"][instance_num] = instance_entry;
+ instance_num++;
+ }
+ }
+
+ for (instance_map::iterator iter = mInstance.begin(); iter != mInstance.end(); ++iter)
+ {
+ LLMeshUploadData data;
+ data.mBaseModel = iter->first;
+
+ if (!data.mBaseModel->mSubmodelID)
+ {
+ // These were handled above already...
+ //
+ continue;
+ }
+
+ LLModelInstance& first_instance = *(iter->second.begin());
+ for (S32 i = 0; i < 5; i++)
+ {
+ data.mModel[i] = first_instance.mLOD[i];
+ }
+
+ if (mesh_index.find(data.mBaseModel) == mesh_index.end())
+ {
+ // Have not seen this model before - create a new mesh_list entry for it.
+ if (model_name.empty())
+ {
+ model_name = data.mBaseModel->getName();
+ }
+
+ if (model_metric.empty())
+ {
+ model_metric = data.mBaseModel->getMetric();
+ }
+
+ std::stringstream ostr;
+
+ LLModel::Decomposition& decomp =
+ data.mModel[LLModel::LOD_PHYSICS].notNull() ?
+ data.mModel[LLModel::LOD_PHYSICS]->mPhysics :
+ data.mBaseModel->mPhysics;
+
+ decomp.mBaseHull = mHullMap[data.mBaseModel];
+
+ LLSD mesh_header = LLModel::writeModel(
+ ostr,
+ data.mModel[LLModel::LOD_PHYSICS],
+ data.mModel[LLModel::LOD_HIGH],
+ data.mModel[LLModel::LOD_MEDIUM],
+ data.mModel[LLModel::LOD_LOW],
+ data.mModel[LLModel::LOD_IMPOSTOR],
+ decomp,
+ mUploadSkin,
+ mUploadJoints,
+ FALSE,
+ FALSE,
+ data.mBaseModel->mSubmodelID);
+
+ data.mAssetData = ostr.str();
+ std::string str = ostr.str();
+
+ res["mesh_list"][mesh_num] = LLSD::Binary(str.begin(),str.end());
+ mesh_index[data.mBaseModel] = mesh_num;
+ mesh_num++;
+ }
+
+ // For all instances that use this model
+ for (instance_list::iterator instance_iter = iter->second.begin();
+ instance_iter != iter->second.end();
+ ++instance_iter)
+ {
+
+ LLModelInstance& instance = *instance_iter;
+
+ LLSD instance_entry;
+
+ for (S32 i = 0; i < 5; i++)
+ {
+ data.mModel[i] = instance.mLOD[i];
+ }
+
+ LLVector3 pos, scale;
+ LLQuaternion rot;
+ LLMatrix4 transformation = instance.mTransform;
+ decomposeMeshMatrix(transformation,pos,rot,scale);
+ instance_entry["position"] = ll_sd_from_vector3(pos);
+ instance_entry["rotation"] = ll_sd_from_quaternion(rot);
+ instance_entry["scale"] = ll_sd_from_vector3(scale);
+
+ instance_entry["material"] = LL_MCODE_WOOD;
+ instance_entry["physics_shape_type"] = (U8)(LLViewerObject::PHYSICS_SHAPE_NONE);
+ instance_entry["mesh"] = mesh_index[data.mBaseModel];
+
+ instance_entry["face_list"] = LLSD::emptyArray();
+
+ // We want to be able to allow more than 8 materials...
+ //
+ S32 end = llmin((S32)instance.mMaterial.size(), instance.mModel->getNumVolumeFaces()) ;
+
+ for (S32 face_num = 0; face_num < end; face_num++)
+ {
+ LLImportMaterial& material = instance.mMaterial[data.mBaseModel->mMaterialList[face_num]];
+ LLSD face_entry = LLSD::emptyMap();
+
+ LLViewerFetchedTexture *texture = NULL;
+
+ if (material.mDiffuseMapFilename.size())
+ {
+ texture = FindViewerTexture(material);
+ }
+
+ if ((texture != NULL) &&
+ (textures.find(texture) == textures.end()))
+ {
+ textures.insert(texture);
+ }
+
+ std::stringstream texture_str;
+ if (texture != NULL && include_textures && mUploadTextures)
+ {
+ if(texture->hasSavedRawImage())
+ {
+ LLPointer<LLImageJ2C> upload_file =
+ LLViewerTextureList::convertToUploadFile(texture->getSavedRawImage());
+
+ if (!upload_file.isNull() && upload_file->getDataSize())
+ {
texture_str.write((const char*) upload_file->getData(), upload_file->getDataSize());
}
}
+ }
if (texture != NULL &&
mUploadTextures &&
@@ -2227,7 +2419,7 @@ void LLMeshUploadThread::generateHulls()
}
}
- if(has_valid_requests)
+ if (has_valid_requests)
{
// *NOTE: Interesting livelock condition on shutdown. If there
// is an upload request in generateHulls() when shutdown starts,
@@ -2269,7 +2461,7 @@ void LLMeshUploadThread::doWholeModelUpload()
body,
mHttpOptions,
mHttpHeaders,
- this);
+ LLCore::HttpHandler::ptr_t(this, &NoOpDeletor));
if (LLCORE_HTTP_HANDLE_INVALID == handle)
{
mHttpStatus = mHttpRequest->getStatus();
@@ -2320,7 +2512,7 @@ void LLMeshUploadThread::requestWholeModelFee()
mModelData,
mHttpOptions,
mHttpHeaders,
- this);
+ LLCore::HttpHandler::ptr_t(this, &NoOpDeletor));
if (LLCORE_HTTP_HANDLE_INVALID == handle)
{
mHttpStatus = mHttpRequest->getStatus();
@@ -2332,7 +2524,7 @@ void LLMeshUploadThread::requestWholeModelFee()
else
{
U32 sleep_time(10);
-
+
mHttpRequest->update(0);
while (! LLApp::isQuitting() && ! finished() && ! isDiscarded())
{
@@ -2427,7 +2619,7 @@ void LLMeshUploadThread::onCompleted(LLCore::HttpHandle handle, LLCore::HttpResp
// model fee case
LLWholeModelFeeObserver* observer(mFeeObserverHandle.get());
mWholeModelUploadURL.clear();
-
+
if (! status)
{
LL_WARNS(LOG_MESH) << "Fee request failed. Reason: " << reason
@@ -2457,7 +2649,7 @@ void LLMeshUploadThread::onCompleted(LLCore::HttpHandle handle, LLCore::HttpResp
LLCoreHttpUtil::responseToLLSD(response, true, body);
}
dump_llsd_to_file(body, make_dump_name("whole_model_fee_response_", dump_num));
-
+
if (body["state"].asString() == "upload")
{
mWholeModelUploadURL = body["uploader"].asString();
@@ -2528,7 +2720,7 @@ void LLMeshRepoThread::notifyLoadedMeshes()
LODRequest req = mUnavailableQ.front();
mUnavailableQ.pop();
mMutex->unlock();
-
+
update_metrics = true;
gMeshRepo.notifyMeshUnavailable(req.mMeshParams, req.mLOD);
}
@@ -2664,7 +2856,7 @@ void LLMeshRepository::cacheOutgoingMesh(LLMeshUploadData& data, LLSD& header)
void LLMeshHandlerBase::onCompleted(LLCore::HttpHandle handle, LLCore::HttpResponse * response)
{
mProcessed = true;
-
+
unsigned int retries(0U);
response->getRetries(NULL, &retries);
LLMeshRepository::sHTTPRetryCount += retries;
@@ -2720,7 +2912,7 @@ void LLMeshHandlerBase::onCompleted(LLCore::HttpHandle handle, LLCore::HttpRespo
// 200 case, typically
offset = 0;
}
-
+
// *DEBUG: To test validation below
// offset += 1;
@@ -2761,8 +2953,7 @@ void LLMeshHandlerBase::onCompleted(LLCore::HttpHandle handle, LLCore::HttpRespo
// Release handler
common_exit:
- gMeshRepo.mThread->mHttpRequestSet.erase(this);
- delete this; // Must be last statement
+ gMeshRepo.mThread->mHttpRequestSet.erase(this->shared_from_this());
}
@@ -2836,7 +3027,7 @@ void LLMeshHeaderHandler::processData(LLCore::BufferArray * /* body */, S32 /* b
const std::string & lod_name = header_lod[i];
lod_bytes = llmax(lod_bytes, header[lod_name]["offset"].asInteger()+header[lod_name]["size"].asInteger());
}
-
+
// just in case skin info or decomposition is at the end of the file (which it shouldn't be)
lod_bytes = llmax(lod_bytes, header["skin"]["offset"].asInteger() + header["skin"]["size"].asInteger());
lod_bytes = llmax(lod_bytes, header["physics_convex"]["offset"].asInteger() + header["physics_convex"]["size"].asInteger());
@@ -2844,7 +3035,7 @@ void LLMeshHeaderHandler::processData(LLCore::BufferArray * /* body */, S32 /* b
S32 header_bytes = (S32) gMeshRepo.mThread->mMeshHeaderSize[mesh_id];
S32 bytes = lod_bytes + header_bytes;
-
+
// It's possible for the remote asset to have more data than is needed for the local cache
// only allocate as much space in the VFS as is needed for the local cache
data_size = llmin(data_size, bytes);
@@ -2856,11 +3047,11 @@ void LLMeshHeaderHandler::processData(LLCore::BufferArray * /* body */, S32 /* b
++LLMeshRepository::sCacheWrites;
file.write(data, data_size);
-
+
// zero out the rest of the file
U8 block[MESH_HEADER_SIZE];
memset(block, 0, sizeof(block));
-
+
while (bytes-file.tell() > sizeof(block))
{
file.write(block, sizeof(block));
@@ -2886,8 +3077,8 @@ LLMeshLODHandler::~LLMeshLODHandler()
gMeshRepo.mThread->lockAndLoadMeshLOD(mMeshParams, mLOD);
}
LLMeshRepoThread::decActiveLODRequests();
- }
}
+}
void LLMeshLODHandler::processFailure(LLCore::HttpStatus status)
{
@@ -2905,7 +3096,7 @@ void LLMeshLODHandler::processData(LLCore::BufferArray * /* body */, S32 /* body
{
if ((! MESH_LOD_PROCESS_FAILED) && gMeshRepo.mThread->lodReceived(mMeshParams, mLOD, data, data_size))
{
- //good fetch from sim, write to VFS for caching
+ // good fetch from sim, write to VFS for caching
LLVFile file(gVFS, mMeshParams.getSculptID(), LLAssetType::AT_MESH, LLVFile::WRITE);
S32 offset = mOffset;
@@ -2950,7 +3141,7 @@ void LLMeshSkinInfoHandler::processData(LLCore::BufferArray * /* body */, S32 /*
{
if ((! MESH_SKIN_INFO_PROCESS_FAILED) && gMeshRepo.mThread->skinInfoReceived(mMeshID, data, data_size))
{
- //good fetch from sim, write to VFS for caching
+ // good fetch from sim, write to VFS for caching
LLVFile file(gVFS, mMeshID, LLAssetType::AT_MESH, LLVFile::WRITE);
S32 offset = mOffset;
@@ -3274,7 +3465,7 @@ void LLMeshRepository::notifyLoadedMeshes()
REQUEST2_LOW_WATER_MIN,
REQUEST2_LOW_WATER_MAX);
}
-
+
//clean up completed upload threads
for (std::vector<LLMeshUploadThread*>::iterator iter = mUploads.begin(); iter != mUploads.end(); )
{
@@ -3351,7 +3542,7 @@ void LLMeshRepository::notifyLoadedMeshes()
//call completed callbacks on finished decompositions
mDecompThread->notifyCompleted();
-
+
// For major operations, attempt to get the required locks
// without blocking and punt if they're not available. The
// longest run of holdoffs is kept in sMaxLockHoldoffs just
@@ -3370,12 +3561,12 @@ void LLMeshRepository::notifyLoadedMeshes()
return;
}
hold_offs = 0;
-
+
if (gAgent.getRegion())
{
// Update capability urls
static std::string region_name("never name a region this");
-
+
if (gAgent.getRegion()->getName() != region_name && gAgent.getRegion()->capabilitiesReceived())
{
region_name = gAgent.getRegion()->getName();
@@ -3391,7 +3582,7 @@ void LLMeshRepository::notifyLoadedMeshes()
<< LL_ENDL;
}
}
-
+
//popup queued error messages from background threads
while (!mUploadErrorQ.empty())
{
@@ -3746,7 +3937,7 @@ LLSD& LLMeshRepoThread::getMeshHeader(const LLUUID& mesh_id)
void LLMeshRepository::uploadModel(std::vector<LLModelInstance>& data, LLVector3& scale, bool upload_textures,
- bool upload_skin, bool upload_joints, std::string upload_url, bool do_upload,
+ bool upload_skin, bool upload_joints, std::string upload_url, bool do_upload,
LLHandle<LLWholeModelFeeObserver> fee_observer, LLHandle<LLWholeModelUploadObserver> upload_observer)
{
LLMeshUploadThread* thread = new LLMeshUploadThread(data, scale, upload_textures, upload_skin, upload_joints, upload_url,
@@ -3817,37 +4008,6 @@ void LLMeshUploadThread::decomposeMeshMatrix(LLMatrix4& transformation,
result_rot = quat_rotation;
}
-bool LLImportMaterial::operator<(const LLImportMaterial &rhs) const
-{
- if (mDiffuseMap != rhs.mDiffuseMap)
- {
- return mDiffuseMap < rhs.mDiffuseMap;
- }
-
- if (mDiffuseMapFilename != rhs.mDiffuseMapFilename)
- {
- return mDiffuseMapFilename < rhs.mDiffuseMapFilename;
- }
-
- if (mDiffuseMapLabel != rhs.mDiffuseMapLabel)
- {
- return mDiffuseMapLabel < rhs.mDiffuseMapLabel;
- }
-
- if (mDiffuseColor != rhs.mDiffuseColor)
- {
- return mDiffuseColor < rhs.mDiffuseColor;
- }
-
- if (mBinding != rhs.mBinding)
- {
- return mBinding < rhs.mBinding;
- }
-
- return mFullbright < rhs.mFullbright;
-}
-
-
void LLMeshRepository::updateInventory(inventory_data data)
{
LLMutexLock lock(mMeshMutex);
@@ -4245,7 +4405,7 @@ void LLPhysicsDecomp::doDecompositionSingleHull()
setMeshData(mesh, true);
LLCDResult ret = decomp->buildSingleHull() ;
- if(ret)
+ if (ret)
{
LL_WARNS(LOG_MESH) << "Could not execute decomposition stage when attempting to create single hull." << LL_ENDL;
make_box(mCurRequest);
@@ -4433,60 +4593,6 @@ void LLPhysicsDecomp::Request::setStatusMessage(const std::string& msg)
mStatusMessage = msg;
}
-LLModelInstance::LLModelInstance(LLSD& data)
-{
- mLocalMeshID = data["mesh_id"].asInteger();
- mLabel = data["label"].asString();
- mTransform.setValue(data["transform"]);
-
- for (U32 i = 0; i < data["material"].size(); ++i)
- {
- LLImportMaterial mat(data["material"][i]);
- mMaterial[mat.mBinding] = mat;
- }
-}
-
-
-LLSD LLModelInstance::asLLSD()
-{
- LLSD ret;
-
- ret["mesh_id"] = mModel->mLocalID;
- ret["label"] = mLabel;
- ret["transform"] = mTransform.getValue();
-
- U32 i = 0;
- for (std::map<std::string, LLImportMaterial>::iterator iter = mMaterial.begin(); iter != mMaterial.end(); ++iter)
- {
- ret["material"][i++] = iter->second.asLLSD();
- }
-
- return ret;
-}
-
-LLImportMaterial::LLImportMaterial(LLSD& data)
-{
- mDiffuseMapFilename = data["diffuse"]["filename"].asString();
- mDiffuseMapLabel = data["diffuse"]["label"].asString();
- mDiffuseColor.setValue(data["diffuse"]["color"]);
- mFullbright = data["fullbright"].asBoolean();
- mBinding = data["binding"].asString();
-}
-
-
-LLSD LLImportMaterial::asLLSD()
-{
- LLSD ret;
-
- ret["diffuse"]["filename"] = mDiffuseMapFilename;
- ret["diffuse"]["label"] = mDiffuseMapLabel;
- ret["diffuse"]["color"] = mDiffuseColor.getValue();
- ret["fullbright"] = mFullbright;
- ret["binding"] = mBinding;
-
- return ret;
-}
-
void LLMeshRepository::buildPhysicsMesh(LLModel::Decomposition& decomp)
{
decomp.mMesh.resize(decomp.mHull.size());
diff --git a/indra/newview/llmeshrepository.h b/indra/newview/llmeshrepository.h
index 55157cc040..d35c44397b 100755
--- a/indra/newview/llmeshrepository.h
+++ b/indra/newview/llmeshrepository.h
@@ -38,6 +38,7 @@
#include "httpoptions.h"
#include "httpheaders.h"
#include "httphandler.h"
+#include "llthread.h"
#define LLCONVEXDECOMPINTER_STATIC 1
@@ -90,54 +91,6 @@ public:
}
};
-class LLImportMaterial
-{
-public:
- LLPointer<LLViewerFetchedTexture> mDiffuseMap;
- std::string mDiffuseMapFilename;
- std::string mDiffuseMapLabel;
- std::string mBinding;
- LLColor4 mDiffuseColor;
- bool mFullbright;
-
- bool operator<(const LLImportMaterial &params) const;
-
- LLImportMaterial()
- : mFullbright(false)
- {
- mDiffuseColor.set(1,1,1,1);
- }
-
- LLImportMaterial(LLSD& data);
-
- LLSD asLLSD();
-};
-
-class LLModelInstance
-{
-public:
- LLPointer<LLModel> mModel;
- LLPointer<LLModel> mLOD[5];
-
- std::string mLabel;
-
- LLUUID mMeshID;
- S32 mLocalMeshID;
-
- LLMatrix4 mTransform;
- std::map<std::string, LLImportMaterial> mMaterial;
-
- LLModelInstance(LLModel* model, const std::string& label, LLMatrix4& transform, std::map<std::string, LLImportMaterial>& materials)
- : mModel(model), mLabel(label), mTransform(transform), mMaterial(materials)
- {
- mLocalMeshID = -1;
- }
-
- LLModelInstance(LLSD& data);
-
- LLSD asLLSD();
-};
-
class LLPhysicsDecomp : public LLThread
{
public:
@@ -330,7 +283,7 @@ public:
LLCore::HttpRequest::policy_t mHttpLargePolicyClass;
LLCore::HttpRequest::priority_t mHttpPriority;
- typedef std::set<LLCore::HttpHandler *> http_request_set;
+ typedef std::set<LLCore::HttpHandler::ptr_t> http_request_set;
http_request_set mHttpRequestSet; // Outstanding HTTP requests
std::string mGetMeshCapability;
@@ -398,7 +351,7 @@ private:
// Threads: Repo thread only
LLCore::HttpHandle getByteRange(const std::string & url, int cap_version,
size_t offset, size_t len,
- LLCore::HttpHandler * handler);
+ const LLCore::HttpHandler::ptr_t &handler);
};
@@ -483,6 +436,8 @@ public:
// Inherited from LLCore::HttpHandler
virtual void onCompleted(LLCore::HttpHandle handle, LLCore::HttpResponse * response);
+ LLViewerFetchedTexture* FindViewerTexture(const LLImportMaterial& material);
+
private:
LLHandle<LLWholeModelFeeObserver> mFeeObserverHandle;
LLHandle<LLWholeModelUploadObserver> mUploadObserverHandle;
diff --git a/indra/newview/llmoveview.cpp b/indra/newview/llmoveview.cpp
index fe562baf96..70035bcc74 100755
--- a/indra/newview/llmoveview.cpp
+++ b/indra/newview/llmoveview.cpp
@@ -303,7 +303,15 @@ void LLFloaterMove::onFlyButtonClick()
void LLFloaterMove::setMovementMode(const EMovementMode mode)
{
mCurrentMode = mode;
- gAgent.setFlying(MM_FLY == mode);
+
+ if(MM_FLY == mode)
+ {
+ LLAgent::toggleFlying();
+ }
+ else
+ {
+ gAgent.setFlying(FALSE);
+ }
// attempts to set avatar flying can not set it real flying in some cases.
// For ex. when avatar fell down & is standing up.
diff --git a/indra/newview/llnamelistctrl.cpp b/indra/newview/llnamelistctrl.cpp
index 79988a0800..5510598ae7 100755
--- a/indra/newview/llnamelistctrl.cpp
+++ b/indra/newview/llnamelistctrl.cpp
@@ -130,8 +130,14 @@ BOOL LLNameListCtrl::handleDragAndDrop(
return handled;
}
-void LLNameListCtrl::showInspector(const LLUUID& avatar_id, bool is_group)
+void LLNameListCtrl::showInspector(const LLUUID& avatar_id, bool is_group, bool is_experience)
{
+ if(is_experience)
+ {
+ LLFloaterReg::showInstance("experience_profile", avatar_id, true);
+ return;
+ }
+
if (is_group)
LLFloaterReg::showInstance("inspect_group", LLSD().with("group_id", avatar_id));
else
@@ -230,10 +236,11 @@ BOOL LLNameListCtrl::handleToolTip(S32 x, S32 y, MASK mask)
// Should we show a group or an avatar inspector?
bool is_group = hit_item->isGroup();
+ bool is_experience = hit_item->isExperience();
LLToolTip::Params params;
params.background_visible( false );
- params.click_callback( boost::bind(&LLNameListCtrl::showInspector, this, avatar_id, is_group) );
+ params.click_callback( boost::bind(&LLNameListCtrl::showInspector, this, avatar_id, is_group, is_experience) );
params.delay_time(0.0f); // spawn instantly on hover
params.image( icon );
params.message("");
@@ -295,7 +302,7 @@ LLScrollListItem* LLNameListCtrl::addNameItemRow(
const std::string& prefix)
{
LLUUID id = name_item.value().asUUID();
- LLNameListItem* item = new LLNameListItem(name_item,name_item.target() == GROUP);
+ LLNameListItem* item = new LLNameListItem(name_item,name_item.target() == GROUP, name_item.target() == EXPERIENCE);
if (!item) return NULL;
@@ -353,6 +360,8 @@ LLScrollListItem* LLNameListCtrl::addNameItemRow(
}
break;
}
+ case EXPERIENCE:
+ // just use supplied name
default:
break;
}
diff --git a/indra/newview/llnamelistctrl.h b/indra/newview/llnamelistctrl.h
index 515962df7d..19ce3c7aed 100755
--- a/indra/newview/llnamelistctrl.h
+++ b/indra/newview/llnamelistctrl.h
@@ -44,22 +44,30 @@ class LLNameListItem : public LLScrollListItem, public LLHandleProvider<LLNameLi
public:
bool isGroup() const { return mIsGroup; }
void setIsGroup(bool is_group) { mIsGroup = is_group; }
+ bool isExperience() const { return mIsExperience; }
+ void setIsExperience(bool is_experience) { mIsExperience = is_experience; }
protected:
friend class LLNameListCtrl;
LLNameListItem( const LLScrollListItem::Params& p )
- : LLScrollListItem(p), mIsGroup(false)
+ : LLScrollListItem(p), mIsGroup(false), mIsExperience(false)
{
}
LLNameListItem( const LLScrollListItem::Params& p, bool is_group )
- : LLScrollListItem(p), mIsGroup(is_group)
+ : LLScrollListItem(p), mIsGroup(is_group), mIsExperience(false)
+ {
+ }
+
+ LLNameListItem( const LLScrollListItem::Params& p, bool is_group, bool is_experience )
+ : LLScrollListItem(p), mIsGroup(is_group), mIsExperience(is_experience)
{
}
private:
bool mIsGroup;
+ bool mIsExperience;
};
@@ -73,7 +81,8 @@ public:
{
INDIVIDUAL,
GROUP,
- SPECIAL
+ SPECIAL,
+ EXPERIENCE
} ENameType;
// provide names for enums
@@ -160,7 +169,7 @@ public:
/*virtual*/ void mouseOverHighlightNthItem( S32 index );
private:
- void showInspector(const LLUUID& avatar_id, bool is_group);
+ void showInspector(const LLUUID& avatar_id, bool is_group, bool is_experience = false);
void onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name, std::string suffix, LLHandle<LLNameListItem> item);
private:
diff --git a/indra/newview/llnotificationhandler.h b/indra/newview/llnotificationhandler.h
index 3e7f05b5e1..7a183cb298 100755
--- a/indra/newview/llnotificationhandler.h
+++ b/indra/newview/llnotificationhandler.h
@@ -277,22 +277,6 @@ protected:
virtual void initChannel() {};
};
-/**
- * Handler for outbox notifications
- */
-class LLOutboxNotification : public LLSystemNotificationHandler
-{
-public:
- LLOutboxNotification();
- virtual ~LLOutboxNotification() {};
- virtual void onChange(LLNotificationPtr p) { }
- virtual void onDelete(LLNotificationPtr p);
- virtual bool processNotification(const LLNotificationPtr& p);
-
-protected:
- virtual void initChannel() {};
-};
-
class LLHandlerUtil
{
public:
diff --git a/indra/newview/llnotificationlistitem.cpp b/indra/newview/llnotificationlistitem.cpp
new file mode 100644
index 0000000000..8cdc2d7c0b
--- /dev/null
+++ b/indra/newview/llnotificationlistitem.cpp
@@ -0,0 +1,645 @@
+/**
+ * @file llnotificationlistitem.cpp
+ * @brief
+ *
+ * $LicenseInfo:firstyear=2015&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2015, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+
+#include "llviewerprecompiledheaders.h" // must be first include
+
+#include "llnotificationlistitem.h"
+
+#include "llagent.h"
+#include "llgroupactions.h"
+#include "llinventoryicon.h"
+#include "llwindow.h"
+#include "v4color.h"
+#include "lltrans.h"
+#include "lluicolortable.h"
+#include "message.h"
+#include "llnotificationsutil.h"
+#include <boost/regex.hpp>
+
+LLNotificationListItem::LLNotificationListItem(const Params& p) : LLPanel(p),
+ mParams(p),
+ mTitleBox(NULL),
+ mExpandBtn(NULL),
+ mCondenseBtn(NULL),
+ mCloseBtn(NULL),
+ mCondensedViewPanel(NULL),
+ mExpandedViewPanel(NULL),
+ mCondensedHeight(0),
+ mExpandedHeight(0),
+ mExpandedHeightResize(0),
+ mExpanded(false)
+{
+ mNotificationName = p.notification_name;
+}
+
+BOOL LLNotificationListItem::postBuild()
+{
+ BOOL rv = LLPanel::postBuild();
+ mTitleBox = getChild<LLTextBox>("notification_title");
+ mTitleBoxExp = getChild<LLTextBox>("notification_title_exp");
+ mNoticeTextExp = getChild<LLChatEntry>("notification_text_exp");
+
+ mTimeBox = getChild<LLTextBox>("notification_time");
+ mTimeBoxExp = getChild<LLTextBox>("notification_time_exp");
+ mExpandBtn = getChild<LLButton>("expand_btn");
+ mCondenseBtn = getChild<LLButton>("condense_btn");
+ mCloseBtn = getChild<LLButton>("close_btn");
+ mCloseBtnExp = getChild<LLButton>("close_expanded_btn");
+
+ mTitleBox->setValue(mParams.title);
+ mTitleBoxExp->setValue(mParams.title);
+ mNoticeTextExp->setValue(mParams.title);
+ mNoticeTextExp->setEnabled(FALSE);
+ mNoticeTextExp->setTextExpandedCallback(boost::bind(&LLNotificationListItem::reshapeNotification, this));
+
+ mTitleBox->setContentTrusted(false);
+ mTitleBoxExp->setContentTrusted(false);
+ mNoticeTextExp->setContentTrusted(false);
+
+ mTimeBox->setValue(buildNotificationDate(mParams.time_stamp));
+ mTimeBoxExp->setValue(buildNotificationDate(mParams.time_stamp));
+
+ mExpandBtn->setClickedCallback(boost::bind(&LLNotificationListItem::onClickExpandBtn,this));
+ mCondenseBtn->setClickedCallback(boost::bind(&LLNotificationListItem::onClickCondenseBtn,this));
+
+ //mCloseBtn and mCloseExpandedBtn share the same callback
+ mCloseBtn->setClickedCallback(boost::bind(&LLNotificationListItem::onClickCloseBtn,this));
+ mCloseBtnExp->setClickedCallback(boost::bind(&LLNotificationListItem::onClickCloseBtn,this));
+
+ mCondensedViewPanel = getChild<LLPanel>("layout_panel_condensed_view");
+ mExpandedViewPanel = getChild<LLPanel>("layout_panel_expanded_view");
+
+ std::string expanded_height_str = getString("item_expanded_height");
+ std::string condensed_height_str = getString("item_condensed_height");
+
+ mExpandedHeight = (S32)atoi(expanded_height_str.c_str());
+ mCondensedHeight = (S32)atoi(condensed_height_str.c_str());
+
+ setExpanded(FALSE);
+
+ return rv;
+}
+
+LLNotificationListItem::~LLNotificationListItem()
+{
+}
+
+//static
+std::string LLNotificationListItem::buildNotificationDate(const LLDate& time_stamp, ETimeType time_type)
+{
+ std::string timeStr;
+ switch(time_type)
+ {
+ case Local:
+ timeStr = "[" + LLTrans::getString("LTimeMthNum") + "]/["
+ +LLTrans::getString("LTimeDay")+"]/["
+ +LLTrans::getString("LTimeYear")+"] ["
+ +LLTrans::getString("LTimeHour")+"]:["
+ +LLTrans::getString("LTimeMin")+ "]";
+ break;
+ case UTC:
+ timeStr = "[" + LLTrans::getString("UTCTimeMth") + "]/["
+ +LLTrans::getString("UTCTimeDay")+"]/["
+ +LLTrans::getString("UTCTimeYr")+"] ["
+ +LLTrans::getString("UTCTimeHr")+"]:["
+ +LLTrans::getString("UTCTimeMin")+"] ["
+ +LLTrans::getString("UTCTimeTimezone")+"]";
+ break;
+ case SLT:
+ default:
+ timeStr = "[" + LLTrans::getString("TimeMonth") + "]/["
+ +LLTrans::getString("TimeDay")+"]/["
+ +LLTrans::getString("TimeYear")+"] ["
+ +LLTrans::getString("TimeHour")+"]:["
+ +LLTrans::getString("TimeMin")+"]";
+ break;
+ }
+ LLSD substitution;
+ substitution["datetime"] = time_stamp;
+ LLStringUtil::format(timeStr, substitution);
+ return timeStr;
+}
+
+void LLNotificationListItem::onClickCloseBtn()
+{
+ mOnItemClose(this);
+ close();
+}
+
+BOOL LLNotificationListItem::handleMouseUp(S32 x, S32 y, MASK mask)
+{
+ BOOL res = LLPanel::handleMouseUp(x, y, mask);
+ mOnItemClick(this);
+ return res;
+}
+
+void LLNotificationListItem::onMouseEnter(S32 x, S32 y, MASK mask)
+{
+ mCondensedViewPanel->setTransparentColor(LLUIColorTable::instance().getColor( "ScrollHoveredColor" ));
+ mExpandedViewPanel->setTransparentColor(LLUIColorTable::instance().getColor( "ScrollHoveredColor" ));
+}
+
+void LLNotificationListItem::onMouseLeave(S32 x, S32 y, MASK mask)
+{
+ mCondensedViewPanel->setTransparentColor(LLUIColorTable::instance().getColor( "SysWellItemUnselected" ));
+ mExpandedViewPanel->setTransparentColor(LLUIColorTable::instance().getColor( "SysWellItemUnselected" ));
+}
+
+//static
+LLNotificationListItem* LLNotificationListItem::create(const Params& p)
+{
+ if (LLNotificationListItem::getGroupInviteTypes().count(p.notification_name))
+ {
+ return new LLGroupInviteNotificationListItem(p);
+ }
+ else if (LLNotificationListItem::getGroupNoticeTypes().count(p.notification_name))
+ {
+ return new LLGroupNoticeNotificationListItem(p);
+ }
+ else if (LLNotificationListItem::getTransactionTypes().count(p.notification_name))
+ {
+ return new LLTransactionNotificationListItem(p);
+ }
+ return new LLSystemNotificationListItem(p);
+}
+
+//static
+std::set<std::string> LLNotificationListItem::getGroupInviteTypes()
+{
+ return LLGroupInviteNotificationListItem::getTypes();
+}
+
+
+std::set<std::string> LLNotificationListItem::getGroupNoticeTypes()
+{
+ return LLGroupNoticeNotificationListItem::getTypes();
+}
+
+//static
+std::set<std::string> LLNotificationListItem::getTransactionTypes()
+{
+ return LLTransactionNotificationListItem::getTypes();
+}
+
+void LLNotificationListItem::onClickExpandBtn()
+{
+ setExpanded(TRUE);
+}
+
+void LLNotificationListItem::onClickCondenseBtn()
+{
+ setExpanded(FALSE);
+}
+
+void LLNotificationListItem::reshapeNotification()
+{
+ if(mExpanded)
+ {
+ S32 width = this->getRect().getWidth();
+ this->reshape(width, mNoticeTextExp->getRect().getHeight() + mExpandedHeight, FALSE);
+ }
+}
+
+void LLNotificationListItem::setExpanded(BOOL value)
+{
+ mCondensedViewPanel->setVisible(!value);
+ mExpandedViewPanel->setVisible(value);
+ S32 width = this->getRect().getWidth();
+
+ if (value)
+ {
+ this->reshape(width, mNoticeTextExp->getRect().getHeight() + mExpandedHeight, FALSE);
+ }
+ else
+ {
+ this->reshape(width, mCondensedHeight, FALSE);
+ }
+ mExpanded = value;
+
+}
+
+std::set<std::string> LLGroupInviteNotificationListItem::getTypes()
+{
+ std::set<std::string> types;
+ types.insert("JoinGroup");
+ return types;
+}
+
+std::set<std::string> LLGroupNoticeNotificationListItem::getTypes()
+{
+ std::set<std::string> types;
+ types.insert("GroupNotice");
+ return types;
+}
+
+std::set<std::string> LLTransactionNotificationListItem::getTypes()
+{
+ std::set<std::string> types;
+ types.insert("PaymentReceived");
+ types.insert("PaymentSent");
+ return types;
+}
+
+LLGroupNotificationListItem::LLGroupNotificationListItem(const Params& p)
+ : LLNotificationListItem(p),
+ mSenderOrFeeBox(NULL)
+{
+}
+
+LLGroupInviteNotificationListItem::LLGroupInviteNotificationListItem(const Params& p)
+ : LLGroupNotificationListItem(p)
+{
+ buildFromFile("panel_notification_list_item.xml");
+}
+
+BOOL LLGroupInviteNotificationListItem::postBuild()
+{
+ BOOL rv = LLGroupNotificationListItem::postBuild();
+ setFee(mParams.fee);
+ mInviteButtonPanel = getChild<LLPanel>("button_panel");
+ mInviteButtonPanel->setVisible(TRUE);
+ mJoinBtn = getChild<LLButton>("join_btn");
+ mDeclineBtn = getChild<LLButton>("decline_btn");
+ mInfoBtn = getChild<LLButton>("info_btn");
+
+ //invitation with any non-default group role, doesn't have newline characters at the end unlike simple invitations
+ std::string invitation_desc = mNoticeTextExp->getValue().asString();
+ boost::regex pattern = boost::regex("\n\n$", boost::regex::perl|boost::regex::icase);
+ boost::match_results<std::string::const_iterator> matches;
+ if(!boost::regex_search(invitation_desc, matches, pattern))
+ {
+ invitation_desc += "\n\n";
+ mNoticeTextExp->setValue(invitation_desc);
+ }
+
+ mJoinBtn->setClickedCallback(boost::bind(&LLGroupInviteNotificationListItem::onClickJoinBtn,this));
+ mDeclineBtn->setClickedCallback(boost::bind(&LLGroupInviteNotificationListItem::onClickDeclineBtn,this));
+ mInfoBtn->setClickedCallback(boost::bind(&LLGroupInviteNotificationListItem::onClickInfoBtn,this));
+
+ std::string expanded_height_resize_str = getString("expanded_height_resize_for_attachment");
+ mExpandedHeightResize = (S32)atoi(expanded_height_resize_str.c_str());
+
+ return rv;
+}
+
+void LLGroupInviteNotificationListItem::onClickJoinBtn()
+{
+ if (!gAgent.canJoinGroups())
+ {
+ LLNotificationsUtil::add("JoinedTooManyGroups");
+ return;
+ }
+
+ if(mParams.fee > 0)
+ {
+ LLSD args;
+ args["COST"] = llformat("%d", mParams.fee);
+ // Set the fee for next time to 0, so that we don't keep
+ // asking about a fee.
+ LLSD next_payload;
+ next_payload["group_id"]= mParams.group_id;
+ next_payload["transaction_id"]= mParams.transaction_id;
+ next_payload["fee"] = 0;
+ LLNotificationsUtil::add("JoinGroupCanAfford", args, next_payload);
+ }
+ else
+ {
+ send_improved_im(mParams.group_id,
+ std::string("name"),
+ std::string("message"),
+ IM_ONLINE,
+ IM_GROUP_INVITATION_ACCEPT,
+ mParams.transaction_id);
+ }
+ LLNotificationListItem::onClickCloseBtn();
+}
+
+void LLGroupInviteNotificationListItem::onClickDeclineBtn()
+{
+ send_improved_im(mParams.group_id,
+ std::string("name"),
+ std::string("message"),
+ IM_ONLINE,
+ IM_GROUP_INVITATION_DECLINE,
+ mParams.transaction_id);
+ LLNotificationListItem::onClickCloseBtn();
+}
+
+void LLGroupInviteNotificationListItem::onClickInfoBtn()
+{
+ LLGroupActions::show(mParams.group_id);
+}
+
+void LLGroupInviteNotificationListItem::setFee(S32 fee)
+{
+ LLStringUtil::format_map_t string_args;
+ string_args["[GROUP_FEE]"] = llformat("%d", fee);
+ std::string fee_text = getString("group_fee_text", string_args);
+ mSenderOrFeeBox->setValue(fee_text);
+ mSenderOrFeeBoxExp->setValue(fee_text);
+ mSenderOrFeeBox->setVisible(TRUE);
+ mSenderOrFeeBoxExp->setVisible(TRUE);
+}
+
+LLGroupNoticeNotificationListItem::LLGroupNoticeNotificationListItem(const Params& p)
+ : LLGroupNotificationListItem(p),
+ mAttachmentPanel(NULL),
+ mAttachmentTextBox(NULL),
+ mAttachmentIcon(NULL),
+ mAttachmentIconExp(NULL),
+ mInventoryOffer(NULL)
+{
+ if (mParams.inventory_offer.isDefined())
+ {
+ mInventoryOffer = new LLOfferInfo(mParams.inventory_offer);
+ }
+
+ buildFromFile("panel_notification_list_item.xml");
+}
+
+LLGroupNoticeNotificationListItem::~LLGroupNoticeNotificationListItem()
+{
+ LLGroupMgr::getInstance()->removeObserver(this);
+}
+
+BOOL LLGroupNoticeNotificationListItem::postBuild()
+{
+ BOOL rv = LLGroupNotificationListItem::postBuild();
+
+ mAttachmentTextBox = getChild<LLTextBox>("attachment_text");
+ mAttachmentIcon = getChild<LLIconCtrl>("attachment_icon");
+ mAttachmentIconExp = getChild<LLIconCtrl>("attachment_icon_exp");
+ mAttachmentPanel = getChild<LLPanel>("attachment_panel");
+ mAttachmentPanel->setVisible(FALSE);
+
+
+ mTitleBox->setValue(mParams.subject);
+ mTitleBoxExp->setValue(mParams.subject);
+ mNoticeTextExp->setValue(mParams.message);
+
+ mTimeBox->setValue(buildNotificationDate(mParams.time_stamp, UTC));
+ mTimeBoxExp->setValue(buildNotificationDate(mParams.time_stamp, UTC));
+ //Workaround: in case server timestamp is 0 - we use the time when notification was actually received
+ if (mParams.time_stamp.isNull())
+ {
+ mTimeBox->setValue(buildNotificationDate(mParams.received_time, UTC));
+ mTimeBoxExp->setValue(buildNotificationDate(mParams.received_time, UTC));
+ }
+ setSender(mParams.sender);
+
+ if (mInventoryOffer != NULL)
+ {
+ mAttachmentTextBox->setValue(mInventoryOffer->mDesc);
+ mAttachmentTextBox->setVisible(TRUE);
+ mAttachmentIcon->setVisible(TRUE);
+
+ std::string icon_name = LLInventoryIcon::getIconName(mInventoryOffer->mType,
+ LLInventoryType::IT_TEXTURE);
+ mAttachmentIconExp->setValue(icon_name);
+ mAttachmentIconExp->setVisible(TRUE);
+
+ mAttachmentTextBox->setClickedCallback(boost::bind(
+ &LLGroupNoticeNotificationListItem::onClickAttachment, this));
+
+ std::string expanded_height_resize_str = getString("expanded_height_resize_for_attachment");
+ mExpandedHeightResize = (S32)atoi(expanded_height_resize_str.c_str());
+
+ mAttachmentPanel->setVisible(TRUE);
+ }
+ return rv;
+}
+
+BOOL LLGroupNotificationListItem::postBuild()
+{
+ BOOL rv = LLNotificationListItem::postBuild();
+
+ mGroupIcon = getChild<LLGroupIconCtrl>("group_icon");
+ mGroupIconExp = getChild<LLGroupIconCtrl>("group_icon_exp");
+ mGroupNameBoxExp = getChild<LLTextBox>("group_name_exp");
+
+ mGroupIcon->setValue(mParams.group_id);
+ mGroupIconExp->setValue(mParams.group_id);
+
+ mGroupIcon->setVisible(TRUE);
+ mGroupIconExp->setVisible(TRUE);
+
+ mGroupId = mParams.group_id;
+
+ mSenderOrFeeBox = getChild<LLTextBox>("sender_or_fee_box");
+ mSenderOrFeeBoxExp = getChild<LLTextBox>("sender_or_fee_box_exp");
+
+ LLSD value(mParams.group_id);
+ setGroupId(value);
+
+ return rv;
+}
+
+void LLGroupNotificationListItem::changed(LLGroupChange gc)
+{
+ if (GC_PROPERTIES == gc)
+ {
+ updateFromCache();
+ LLGroupMgr::getInstance()->removeObserver(this);
+ }
+}
+
+bool LLGroupNotificationListItem::updateFromCache()
+{
+ LLGroupMgrGroupData* group_data = LLGroupMgr::getInstance()->getGroupData(mGroupId);
+ if (!group_data) return false;
+ setGroupName(group_data->mName);
+ return true;
+}
+
+void LLGroupNotificationListItem::setGroupId(const LLUUID& value)
+{
+ LLGroupMgr* gm = LLGroupMgr::getInstance();
+ if (mGroupId.notNull())
+ {
+ gm->removeObserver(this);
+
+
+ mID = mGroupId;
+
+ // Check if cache already contains image_id for that group
+ if (!updateFromCache())
+ {
+ gm->addObserver(this);
+ gm->sendGroupPropertiesRequest(mGroupId);
+ }
+ }
+}
+
+void LLGroupNotificationListItem::setGroupName(std::string name)
+{
+ if (!name.empty())
+ {
+ LLStringUtil::format_map_t string_args;
+ string_args["[GROUP_NAME]"] = llformat("%s", name.c_str());
+ std::string group_box_str = getString("group_name_text", string_args);
+ mGroupNameBoxExp->setValue(group_box_str);
+ mGroupNameBoxExp->setVisible(TRUE);
+ }
+ else
+ {
+ mGroupNameBoxExp->setValue(LLStringUtil::null);
+ mGroupNameBoxExp->setVisible(FALSE);
+ }
+}
+
+void LLGroupNoticeNotificationListItem::setSender(std::string sender)
+{
+ if (!sender.empty())
+ {
+ LLStringUtil::format_map_t string_args;
+ string_args["[SENDER_RESIDENT]"] = llformat("%s", sender.c_str());
+ std::string sender_text = getString("sender_resident_text", string_args);
+ mSenderOrFeeBox->setValue(sender_text);
+ mSenderOrFeeBoxExp->setValue(sender_text);
+ mSenderOrFeeBox->setVisible(TRUE);
+ mSenderOrFeeBoxExp->setVisible(TRUE);
+ } else {
+ mSenderOrFeeBox->setValue(LLStringUtil::null);
+ mSenderOrFeeBoxExp->setValue(LLStringUtil::null);
+ mSenderOrFeeBox->setVisible(FALSE);
+ mSenderOrFeeBoxExp->setVisible(FALSE);
+ }
+}
+void LLGroupNoticeNotificationListItem::close()
+{
+ // The group notice dialog may be an inventory offer.
+ // If it has an inventory save button and that button is still enabled
+ // Then we need to send the inventory declined message
+ if (mInventoryOffer != NULL)
+ {
+ mInventoryOffer->forceResponse(IOR_DECLINE);
+ mInventoryOffer = NULL;
+ }
+ LLGroupMgr::getInstance()->removeObserver(this);
+}
+
+void LLGroupNoticeNotificationListItem::onClickAttachment()
+{
+ if (mInventoryOffer != NULL) {
+ mInventoryOffer->forceResponse(IOR_ACCEPT);
+
+ static const LLUIColor textColor = LLUIColorTable::instance().getColor(
+ "GroupNotifyDimmedTextColor");
+ mAttachmentTextBox->setColor(textColor);
+ mAttachmentIconExp->setEnabled(FALSE);
+
+ //if attachment isn't openable - notify about saving
+ if (!isAttachmentOpenable(mInventoryOffer->mType)) {
+ LLNotifications::instance().add("AttachmentSaved", LLSD(), LLSD());
+ }
+
+ mInventoryOffer = NULL;
+ }
+}
+
+//static
+bool LLGroupNoticeNotificationListItem::isAttachmentOpenable(LLAssetType::EType type)
+{
+ switch (type)
+ {
+ case LLAssetType::AT_LANDMARK:
+ case LLAssetType::AT_NOTECARD:
+ case LLAssetType::AT_IMAGE_JPEG:
+ case LLAssetType::AT_IMAGE_TGA:
+ case LLAssetType::AT_TEXTURE:
+ case LLAssetType::AT_TEXTURE_TGA:
+ return true;
+ default:
+ return false;
+ }
+}
+
+LLTransactionNotificationListItem::LLTransactionNotificationListItem(const Params& p)
+ : LLNotificationListItem(p),
+ mAvatarIcon(NULL)
+{
+ buildFromFile("panel_notification_list_item.xml");
+}
+
+BOOL LLTransactionNotificationListItem::postBuild()
+{
+ BOOL rv = LLNotificationListItem::postBuild();
+ mAvatarIcon = getChild<LLAvatarIconCtrl>("avatar_icon");
+ mAvatarIconExp = getChild<LLAvatarIconCtrl>("avatar_icon_exp");
+ mAvatarIcon->setValue("System_Notification");
+ mAvatarIconExp->setValue("System_Notification");
+
+ mAvatarIcon->setVisible(TRUE);
+ mAvatarIconExp->setVisible(TRUE);
+ if((GOVERNOR_LINDEN_ID == mParams.paid_to_id) ||
+ (GOVERNOR_LINDEN_ID == mParams.paid_from_id))
+ {
+ return rv;
+ }
+
+ if (mParams.notification_name == "PaymentReceived")
+ {
+ mAvatarIcon->setValue(mParams.paid_from_id);
+ mAvatarIconExp->setValue(mParams.paid_from_id);
+ }
+ else if (mParams.notification_name == "PaymentSent")
+ {
+ mAvatarIcon->setValue(mParams.paid_to_id);
+ mAvatarIconExp->setValue(mParams.paid_to_id);
+ }
+
+ return rv;
+}
+
+LLSystemNotificationListItem::LLSystemNotificationListItem(const Params& p)
+ : LLNotificationListItem(p),
+ mSystemNotificationIcon(NULL),
+ mIsCaution(false)
+{
+ buildFromFile("panel_notification_list_item.xml");
+ mIsCaution = p.notification_priority >= NOTIFICATION_PRIORITY_HIGH;
+ if (mIsCaution)
+ {
+ mTitleBox->setColor(LLUIColorTable::instance().getColor("NotifyCautionBoxColor"));
+ mTitleBoxExp->setColor(LLUIColorTable::instance().getColor("NotifyCautionBoxColor"));
+ mNoticeTextExp->setReadOnlyColor(LLUIColorTable::instance().getColor("NotifyCautionBoxColor"));
+ mTimeBox->setColor(LLUIColorTable::instance().getColor("NotifyCautionBoxColor"));
+ mTimeBoxExp->setColor(LLUIColorTable::instance().getColor("NotifyCautionBoxColor"));
+ }
+}
+
+BOOL LLSystemNotificationListItem::postBuild()
+{
+ BOOL rv = LLNotificationListItem::postBuild();
+ mSystemNotificationIcon = getChild<LLIconCtrl>("system_notification_icon");
+ mSystemNotificationIconExp = getChild<LLIconCtrl>("system_notification_icon_exp");
+ if (mSystemNotificationIcon)
+ mSystemNotificationIcon->setVisible(TRUE);
+ if (mSystemNotificationIconExp)
+ mSystemNotificationIconExp->setVisible(TRUE);
+ return rv;
+}
diff --git a/indra/newview/llnotificationlistitem.h b/indra/newview/llnotificationlistitem.h
new file mode 100644
index 0000000000..9a4ce2be4b
--- /dev/null
+++ b/indra/newview/llnotificationlistitem.h
@@ -0,0 +1,250 @@
+/**
+ * @file llnotificationlistitem.h
+ * @brief
+ *
+ * $LicenseInfo:firstyear=2015&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2015, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLNOTIFICATIONLISTITEM_H
+#define LL_LLNOTIFICATIONLISTITEM_H
+
+#include "llpanel.h"
+#include "lllayoutstack.h"
+#include "lltextbox.h"
+#include "llviewertexteditor.h"
+#include "llbutton.h"
+#include "llgroupiconctrl.h"
+#include "llavatariconctrl.h"
+#include "llchatentry.h"
+#include "llgroupmgr.h"
+#include "llviewermessage.h"
+
+#include <string>
+
+class LLNotificationListItem : public LLPanel
+{
+public:
+ struct Params : public LLInitParam::Block<Params, LLPanel::Params>
+ {
+ LLUUID notification_id;
+ LLUUID transaction_id;
+ LLUUID group_id;
+ LLUUID paid_from_id;
+ LLUUID paid_to_id;
+ std::string notification_name;
+ std::string title;
+ std::string subject;
+ std::string message;
+ std::string sender;
+ S32 fee;
+ LLDate time_stamp;
+ LLDate received_time;
+ LLSD inventory_offer;
+ e_notification_priority notification_priority;
+ Params() {};
+ };
+
+ static LLNotificationListItem* create(const Params& p);
+
+ static std::set<std::string> getTransactionTypes();
+ static std::set<std::string> getGroupInviteTypes();
+ static std::set<std::string> getGroupNoticeTypes();
+
+ // title
+ void setTitle( std::string title );
+
+ // get item's ID
+ LLUUID getID() { return mParams.notification_id; }
+ std::string& getTitle() { return mTitle; }
+ std::string& getNotificationName() { return mNotificationName; }
+
+ // handlers
+ virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask);
+ virtual void onMouseEnter(S32 x, S32 y, MASK mask);
+ virtual void onMouseLeave(S32 x, S32 y, MASK mask);
+
+ //callbacks
+ typedef boost::function<void (LLNotificationListItem* item)> item_callback_t;
+ typedef boost::signals2::signal<void (LLNotificationListItem* item)> item_signal_t;
+ item_signal_t mOnItemClose;
+ item_signal_t mOnItemClick;
+ boost::signals2::connection setOnItemCloseCallback(item_callback_t cb) { return mOnItemClose.connect(cb); }
+ boost::signals2::connection setOnItemClickCallback(item_callback_t cb) { return mOnItemClick.connect(cb); }
+
+ virtual bool showPopup() { return true; }
+ void setExpanded(BOOL value);
+ virtual BOOL postBuild();
+ void reshapeNotification();
+
+ typedef enum e_time_type
+ {
+ SLT = 1,
+ Local = 2,
+ UTC = 3,
+ }ETimeType;
+
+protected:
+ LLNotificationListItem(const Params& p);
+ virtual ~LLNotificationListItem();
+
+ static std::string buildNotificationDate(const LLDate& time_stamp, ETimeType time_type = SLT);
+ void onClickExpandBtn();
+ void onClickCondenseBtn();
+ void onClickCloseBtn();
+ virtual void close() {};
+
+ Params mParams;
+ LLTextBox* mTitleBox;
+ LLTextBox* mTitleBoxExp;
+ LLChatEntry* mNoticeTextExp;
+ LLTextBox* mTimeBox;
+ LLTextBox* mTimeBoxExp;
+ LLButton* mExpandBtn;
+ LLButton* mCondenseBtn;
+ LLButton* mCloseBtn;
+ LLButton* mCloseBtnExp;
+ LLPanel* mCondensedViewPanel;
+ LLPanel* mExpandedViewPanel;
+ std::string mTitle;
+ std::string mNotificationName;
+ S32 mCondensedHeight;
+ S32 mExpandedHeight;
+ S32 mExpandedHeightResize;
+ bool mExpanded;
+};
+
+class LLGroupNotificationListItem
+ : public LLNotificationListItem, public LLGroupMgrObserver
+{
+public:
+ virtual BOOL postBuild();
+
+ void setGroupId(const LLUUID& value);
+ // LLGroupMgrObserver observer trigger
+ virtual void changed(LLGroupChange gc);
+
+ friend class LLNotificationListItem;
+protected:
+ LLGroupNotificationListItem(const Params& p);
+
+ LLGroupIconCtrl* mGroupIcon;
+ LLGroupIconCtrl* mGroupIconExp;
+ LLUUID mGroupId;
+ LLTextBox* mSenderOrFeeBox;
+ LLTextBox* mSenderOrFeeBoxExp;
+ LLTextBox* mGroupNameBoxExp;
+
+private:
+ LLGroupNotificationListItem(const LLGroupNotificationListItem &);
+ LLGroupNotificationListItem & operator=(LLGroupNotificationListItem &);
+
+ void setGroupName(std::string name);
+ bool updateFromCache();
+};
+
+class LLGroupInviteNotificationListItem
+ : public LLGroupNotificationListItem
+{
+public:
+ static std::set<std::string> getTypes();
+ virtual BOOL postBuild();
+
+ /*virtual*/ bool showPopup() { return false; }
+
+private:
+ friend class LLNotificationListItem;
+ LLGroupInviteNotificationListItem(const Params& p);
+ LLGroupInviteNotificationListItem(const LLGroupInviteNotificationListItem &);
+ LLGroupInviteNotificationListItem & operator=(LLGroupInviteNotificationListItem &);
+
+ void setFee(S32 fee);
+
+ void onClickJoinBtn();
+ void onClickDeclineBtn();
+ void onClickInfoBtn();
+
+ LLPanel* mInviteButtonPanel;
+ LLButton* mJoinBtn;
+ LLButton* mDeclineBtn;
+ LLButton* mInfoBtn;
+};
+
+class LLGroupNoticeNotificationListItem
+ : public LLGroupNotificationListItem
+{
+public:
+ ~LLGroupNoticeNotificationListItem();
+ static std::set<std::string> getTypes();
+ virtual BOOL postBuild();
+
+ /*virtual*/ bool showPopup() { return false; }
+
+private:
+ friend class LLNotificationListItem;
+ LLGroupNoticeNotificationListItem(const Params& p);
+ LLGroupNoticeNotificationListItem(const LLGroupNoticeNotificationListItem &);
+ LLGroupNoticeNotificationListItem & operator=(LLGroupNoticeNotificationListItem &);
+
+ void setSender(std::string sender);
+ void onClickAttachment();
+ /*virtual*/ void close();
+
+ static bool isAttachmentOpenable(LLAssetType::EType);
+
+ LLPanel* mAttachmentPanel;
+ LLTextBox* mAttachmentTextBox;
+ LLIconCtrl* mAttachmentIcon;
+ LLIconCtrl* mAttachmentIconExp;
+ LLOfferInfo* mInventoryOffer;
+};
+
+class LLTransactionNotificationListItem : public LLNotificationListItem
+{
+public:
+ static std::set<std::string> getTypes();
+ virtual BOOL postBuild();
+private:
+ friend class LLNotificationListItem;
+ LLTransactionNotificationListItem(const Params& p);
+ LLTransactionNotificationListItem(const LLTransactionNotificationListItem &);
+ LLTransactionNotificationListItem & operator=(LLTransactionNotificationListItem &);
+ LLAvatarIconCtrl* mAvatarIcon;
+ LLAvatarIconCtrl* mAvatarIconExp;
+};
+
+class LLSystemNotificationListItem : public LLNotificationListItem
+{
+public:
+ virtual BOOL postBuild();
+private:
+ friend class LLNotificationListItem;
+ LLSystemNotificationListItem(const Params& p);
+ LLSystemNotificationListItem(const LLSystemNotificationListItem &);
+ LLSystemNotificationListItem & operator=(LLSystemNotificationListItem &);
+ LLIconCtrl* mSystemNotificationIcon;
+ LLIconCtrl* mSystemNotificationIconExp;
+ bool mIsCaution;
+};
+
+#endif // LL_LLNOTIFICATIONLISTITEM_H
+
+
diff --git a/indra/newview/lltexturestatsuploader.cpp b/indra/newview/llnotificationlistview.cpp
index c4809bc8e7..9dce68c9c6 100755..100644
--- a/indra/newview/lltexturestatsuploader.cpp
+++ b/indra/newview/llnotificationlistview.cpp
@@ -1,10 +1,10 @@
/**
- * @file lltexturerstats.cpp
- * @brief texture stats upload class
+ * @file llnotificationlistview.cpp
+ * @brief
*
- * $LicenseInfo:firstyear=2002&license=viewerlgpl$
+ * $LicenseInfo:firstyear=2015&license=viewerlgpl$
* Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
+ * Copyright (C) 2015, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -23,27 +23,22 @@
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
-
#include "llviewerprecompiledheaders.h"
-#include "lltexturestatsuploader.h"
+#include "llnotificationlistview.h"
+
+static const LLDefaultChildRegistry::Register<LLNotificationListView> notification_list_view("notification_list_view");
-#include "llhttpclient.h"
+LLNotificationListView::LLNotificationListView(const Params& p)
+ : LLFlatListView(p)
+{}
+LLNotificationListView::~LLNotificationListView()
+{}
-// static
-void LLTextureStatsUploader::uploadStatsToSimulator(const std::string texture_cap_url, const LLSD &texture_stats)
+bool LLNotificationListView::addNotification(LLNotificationListItem * item)
{
- if ( texture_cap_url != "" )
- {
- LLHTTPClient::post(texture_cap_url, texture_stats, NULL);
- }
- else
- {
- LL_INFOS() << "Not sending texture stats: "
- << texture_stats
- << " as there is no cap url."
- << LL_ENDL;
- }
+ return LLFlatListView::addItem(item, item->getID(), ADD_TOP);
}
+//EOF
diff --git a/indra/newview/lltexturestatsuploader.h b/indra/newview/llnotificationlistview.h
index ac268c2516..307ad87789 100755..100644
--- a/indra/newview/lltexturestatsuploader.h
+++ b/indra/newview/llnotificationlistview.h
@@ -1,10 +1,10 @@
/**
- * @file lltexturestatsuploader.h
- * @brief Class to send the texture stats to the simulatore
+ * @file llnotificationlistview.h
+ * @brief LLNotificationListView class to support notifications list contained in enclosing floater.
*
- * $LicenseInfo:firstyear=2009&license=viewerlgpl$
+ * $LicenseInfo:firstyear=2015&license=viewerlgpl$
* Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
+ * Copyright (C) 2015, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -24,17 +24,26 @@
* $/LicenseInfo$
*/
-#ifndef LL_LLTEXTURESTATSUPLOADER_H
-#define LL_LLTEXTURESTATSUPLOADER_H
+#ifndef LL_LLNOTIFICATIONLISTVIEW_H
+#define LL_LLNOTIFICATIONLISTVIEW_H
-#include "llappviewer.h"
+#include "llflatlistview.h"
+#include "llnotificationlistitem.h"
-// utility functions to capture data on texture download speeds and send to simulator periodically
-
-class LLTextureStatsUploader
+/**
+ * Notification list
+ */
+class LLNotificationListView : public LLFlatListView
{
+ LOG_CLASS(LLNotificationListView);
public:
- static void uploadStatsToSimulator(const std::string texture_cap_url, const LLSD &texture_stats);
+ struct Params : public LLInitParam::Block<Params, LLFlatListView::Params> {};
+
+ LLNotificationListView(const Params& p);
+ ~LLNotificationListView();
+ friend class LLUICtrlFactory;
+
+ virtual bool addNotification(LLNotificationListItem * item);
};
-#endif // LL_LLTEXTURESTATSUPLOADER_H
+#endif
diff --git a/indra/newview/llnotificationmanager.cpp b/indra/newview/llnotificationmanager.cpp
index 152581c5a0..a6f20a9f27 100755
--- a/indra/newview/llnotificationmanager.cpp
+++ b/indra/newview/llnotificationmanager.cpp
@@ -61,7 +61,6 @@ void LLNotificationManager::init()
mChannels.push_back(new LLOfferHandler());
mChannels.push_back(new LLHintHandler());
mChannels.push_back(new LLBrowserNotification());
- mChannels.push_back(new LLOutboxNotification());
mChannels.push_back(new LLIMHandler());
mChatHandler = boost::shared_ptr<LLFloaterIMNearbyChatHandler>(new LLFloaterIMNearbyChatHandler());
@@ -70,7 +69,7 @@ void LLNotificationManager::init()
//--------------------------------------------------------------------------
void LLNotificationManager::onChat(const LLChat& msg, const LLSD &args)
{
- if(mChatHandler)
- mChatHandler->processChat(msg, args);
- }
+ if(mChatHandler)
+ mChatHandler->processChat(msg, args);
+}
diff --git a/indra/newview/llpaneleditwearable.cpp b/indra/newview/llpaneleditwearable.cpp
index 9bd6007772..b7e1b2d3a4 100755
--- a/indra/newview/llpaneleditwearable.cpp
+++ b/indra/newview/llpaneleditwearable.cpp
@@ -1168,6 +1168,8 @@ void LLPanelEditWearable::showWearable(LLViewerWearable* wearable, BOOL show, BO
targetPanel->setVisible(show);
toggleTypeSpecificControls(type);
+ // Update type controls here
+ updateTypeSpecificControls(type);
if (show)
{
@@ -1179,7 +1181,6 @@ void LLPanelEditWearable::showWearable(LLViewerWearable* wearable, BOOL show, BO
mNameEditor->setText(mWearableItem->getName());
updatePanelPickerControls(type);
- updateTypeSpecificControls(type);
// clear and rebuild visual param list
U8 num_subparts = wearable_entry->mSubparts.size();
diff --git a/indra/newview/llpanelexperiencelisteditor.cpp b/indra/newview/llpanelexperiencelisteditor.cpp
index 20fe0c52fa..32ec4930ab 100644
--- a/indra/newview/llpanelexperiencelisteditor.cpp
+++ b/indra/newview/llpanelexperiencelisteditor.cpp
@@ -33,6 +33,7 @@
#include "llfloaterexperiencepicker.h"
#include "llfloaterreg.h"
#include "llhandle.h"
+#include "llnamelistctrl.h"
#include "llscrolllistctrl.h"
#include "llviewerregion.h"
#include "llagent.h"
@@ -54,7 +55,7 @@ LLPanelExperienceListEditor::LLPanelExperienceListEditor()
BOOL LLPanelExperienceListEditor::postBuild()
{
- mItems = getChild<LLScrollListCtrl>("experience_list");
+ mItems = getChild<LLNameListCtrl>("experience_list");
mAdd = getChild<LLButton>("btn_add");
mRemove = getChild<LLButton>("btn_remove");
mProfile = getChild<LLButton>("btn_profile");
@@ -178,12 +179,13 @@ void LLPanelExperienceListEditor::onItems()
{
const LLUUID& experience = *it;
item["id"]=experience;
+ item["target"] = LLNameListCtrl::EXPERIENCE;
LLSD& columns = item["columns"];
columns[0]["column"] = "experience_name";
columns[0]["value"] = getString("loading");
mItems->addElement(item);
- LLExperienceCache::getInstance()->get(experience, boost::bind(&LLPanelExperienceListEditor::experienceDetailsCallback,
+ LLExperienceCache::instance().get(experience, boost::bind(&LLPanelExperienceListEditor::experienceDetailsCallback,
getDerivedHandle<LLPanelExperienceListEditor>(), _1));
}
diff --git a/indra/newview/llpanelexperiencelisteditor.h b/indra/newview/llpanelexperiencelisteditor.h
index f69f0509be..bc9867752d 100644
--- a/indra/newview/llpanelexperiencelisteditor.h
+++ b/indra/newview/llpanelexperiencelisteditor.h
@@ -31,6 +31,7 @@
#include "lluuid.h"
#include <set>
+class LLNameListCtrl;
class LLScrollListCtrl;
class LLButton;
class LLFloaterExperiencePicker;
@@ -82,7 +83,7 @@ private:
uuid_list_t mExperienceIds;
- LLScrollListCtrl* mItems;
+ LLNameListCtrl* mItems;
filter_list mFilters;
LLButton* mAdd;
LLButton* mRemove;
diff --git a/indra/newview/llpanelexperiencelog.cpp b/indra/newview/llpanelexperiencelog.cpp
index 9329d900b1..d5979b6e96 100644
--- a/indra/newview/llpanelexperiencelog.cpp
+++ b/indra/newview/llpanelexperiencelog.cpp
@@ -140,7 +140,7 @@ void LLPanelExperienceLog::refresh()
}
const LLSD event = dayArray[i];
LLUUID id = event[LLExperienceCache::EXPERIENCE_ID].asUUID();
- const LLSD& experience = LLExperienceCache::getInstance()->get(id);
+ const LLSD& experience = LLExperienceCache::instance().get(id);
if(experience.isUndefined()){
waiting = true;
waiting_id = id;
@@ -168,7 +168,7 @@ void LLPanelExperienceLog::refresh()
{
mEventList->deleteAllItems();
mEventList->setCommentText(getString("loading"));
- LLExperienceCache::getInstance()->get(waiting_id, boost::bind(&LLPanelExperienceLog::refresh, this));
+ LLExperienceCache::instance().get(waiting_id, boost::bind(&LLPanelExperienceLog::refresh, this));
}
else
{
diff --git a/indra/newview/llpanelexperiencepicker.cpp b/indra/newview/llpanelexperiencepicker.cpp
index 7c19e32e7e..a7f2dbafa2 100644
--- a/indra/newview/llpanelexperiencepicker.cpp
+++ b/indra/newview/llpanelexperiencepicker.cpp
@@ -42,7 +42,7 @@
#include "llviewercontrol.h"
#include "llfloater.h"
#include "lltrans.h"
-#include "llhttpclient.h" // *TODO: Rider, remove when converting
+#include <boost/regex.hpp>
#define BTN_FIND "find"
#define BTN_OK "ok_btn"
@@ -59,41 +59,6 @@ const static std::string columnSpace = " ";
static LLPanelInjector<LLPanelExperiencePicker> t_panel_status("llpanelexperiencepicker");
-class LLExperienceSearchResponder : public LLHTTPClient::Responder
-{
-public:
- LLUUID mQueryID;
- LLHandle<LLPanelExperiencePicker> mParent;
-
- LLExperienceSearchResponder(const LLUUID& id, const LLHandle<LLPanelExperiencePicker>& parent) : mQueryID(id), mParent(parent) { }
-
-protected:
- /*virtual*/ void httpSuccess()
- {
- if(mParent.isDead())
- return;
-
- LLPanelExperiencePicker* panel =mParent.get();
- if (panel)
- {
- panel->processResponse(mQueryID, getContent());
- }
- }
-
- /*virtual*/ void httpFailure()
- {
- if(mParent.isDead())
- return;
-
- LLPanelExperiencePicker* panel =mParent.get();
- if (panel)
- {
- panel->processResponse(mQueryID, LLSD());
- }
- LL_WARNS() << "experience picker failed [status:" << getStatus() << "]: " << getContent() << LL_ENDL;
- }
-};
-
LLPanelExperiencePicker::LLPanelExperiencePicker()
:LLPanel()
{
@@ -148,6 +113,46 @@ void LLPanelExperiencePicker::editKeystroke( class LLLineEditor* caller, void* u
void LLPanelExperiencePicker::onBtnFind()
{
mCurrentPage=1;
+ boost::cmatch what;
+ std::string text = getChild<LLUICtrl>(TEXT_EDIT)->getValue().asString();
+ const boost::regex expression("secondlife:///app/experience/[\\da-f-]+/profile");
+ if (boost::regex_match(text.c_str(), what, expression))
+ {
+ LLURI uri(text);
+ LLSD path_array = uri.pathArray();
+ if (path_array.size() == 4)
+ {
+ std::string exp_id = path_array.get(2).asString();
+ LLUUID experience_id(exp_id);
+ if (!experience_id.isNull())
+ {
+ const LLSD& experience_details = LLExperienceCache::instance().get(experience_id);
+ if(!experience_details.isUndefined())
+ {
+ std::string experience_name_string = experience_details[LLExperienceCache::NAME].asString();
+ if(!experience_name_string.empty())
+ {
+ getChild<LLUICtrl>(TEXT_EDIT)->setValue(experience_name_string);
+ }
+ }
+ else
+ {
+ getChild<LLScrollListCtrl>(LIST_RESULTS)->deleteAllItems();
+ getChild<LLScrollListCtrl>(LIST_RESULTS)->setCommentText(getString("searching"));
+
+ getChildView(BTN_OK)->setEnabled(FALSE);
+ getChildView(BTN_PROFILE)->setEnabled(FALSE);
+
+ getChildView(BTN_RIGHT)->setEnabled(FALSE);
+ getChildView(BTN_LEFT)->setEnabled(FALSE);
+ LLExperienceCache::instance().get(experience_id, boost::bind(&LLPanelExperiencePicker::onBtnFind, this));
+ return;
+ }
+ }
+ }
+ }
+
+
find();
}
@@ -164,17 +169,11 @@ void LLPanelExperiencePicker::find()
{
std::string text = getChild<LLUICtrl>(TEXT_EDIT)->getValue().asString();
mQueryID.generate();
- std::ostringstream url;
- LLViewerRegion* region = gAgent.getRegion();
- std::string cap = region->getCapability("FindExperienceByName");
- if (!cap.empty())
- {
- url << cap << "?page=" << mCurrentPage << "&page_size=30&query=" << LLURI::escape(text);
- LLHTTPClient::get(url.str(), new LLExperienceSearchResponder(mQueryID, getDerivedHandle<LLPanelExperiencePicker>()));
+ LLExperienceCache::instance().findExperienceByName(text, mCurrentPage,
+ boost::bind(&LLPanelExperiencePicker::findResults, getDerivedHandle<LLPanelExperiencePicker>(), mQueryID, _1));
- }
- getChild<LLScrollListCtrl>(LIST_RESULTS)->deleteAllItems();
+ getChild<LLScrollListCtrl>(LIST_RESULTS)->deleteAllItems();
getChild<LLScrollListCtrl>(LIST_RESULTS)->setCommentText(getString("searching"));
getChildView(BTN_OK)->setEnabled(FALSE);
@@ -184,6 +183,18 @@ void LLPanelExperiencePicker::find()
getChildView(BTN_LEFT)->setEnabled(FALSE);
}
+/*static*/
+void LLPanelExperiencePicker::findResults(LLHandle<LLPanelExperiencePicker> hparent, LLUUID queryId, LLSD foundResult)
+{
+ if (hparent.isDead())
+ return;
+
+ LLPanelExperiencePicker* panel = hparent.get();
+ if (panel)
+ {
+ panel->processResponse(queryId, foundResult);
+ }
+}
bool LLPanelExperiencePicker::isSelectButtonEnabled()
{
@@ -234,13 +245,6 @@ void LLPanelExperiencePicker::processResponse( const LLUUID& query_id, const LLS
mResponse = content;
- const LLSD& experiences=mResponse["experience_keys"];
- LLSD::array_const_iterator it = experiences.beginArray();
- for ( ; it != experiences.endArray(); ++it)
- {
- LLExperienceCache::getInstance()->insert(*it);
- }
-
getChildView(BTN_RIGHT)->setEnabled(content.has("next_page_url"));
getChildView(BTN_LEFT)->setEnabled(content.has("previous_page_url"));
diff --git a/indra/newview/llpanelexperiencepicker.h b/indra/newview/llpanelexperiencepicker.h
index e39ffed70b..97aa04cf4c 100644
--- a/indra/newview/llpanelexperiencepicker.h
+++ b/indra/newview/llpanelexperiencepicker.h
@@ -74,8 +74,9 @@ private:
void getSelectedExperienceIds( const LLScrollListCtrl* results, uuid_vec_t &experience_ids );
void setAllowMultiple(bool allow_multiple);
-
void find();
+ static void findResults(LLHandle<LLPanelExperiencePicker> hparent, LLUUID queryId, LLSD foundResult);
+
bool isSelectButtonEnabled();
void processResponse( const LLUUID& query_id, const LLSD& content );
diff --git a/indra/newview/llpanelface.h b/indra/newview/llpanelface.h
index 9823e84cd9..d7e89b4832 100755
--- a/indra/newview/llpanelface.h
+++ b/indra/newview/llpanelface.h
@@ -307,7 +307,7 @@ private:
LLMaterialMgr::getInstance()->put(object->getID(),face,*new_material);
}
- object->setTEMaterialParams(face, new_material);
+ object->setTEMaterialParams(face, new_material, TRUE);
return new_material;
}
return NULL;
diff --git a/indra/newview/llpanelgroup.cpp b/indra/newview/llpanelgroup.cpp
index f67a90fd01..342b57ba4a 100755
--- a/indra/newview/llpanelgroup.cpp
+++ b/indra/newview/llpanelgroup.cpp
@@ -338,7 +338,7 @@ void LLPanelGroup::update(LLGroupChange gc)
group_name_ctrl->setToolTip(group_name);
LLGroupData agent_gdatap;
- bool is_member = gAgent.getGroupData(mID,agent_gdatap) || gAgent.isGodlike();
+ bool is_member = gAgent.getGroupData(mID,agent_gdatap) || gAgent.isGodlikeWithoutAdminMenuFakery();
bool join_btn_visible = !is_member && gdatap->mOpenEnrollment;
mButtonJoin->setVisible(join_btn_visible);
@@ -470,7 +470,7 @@ void LLPanelGroup::setGroupID(const LLUUID& group_id)
}
LLGroupData agent_gdatap;
- bool is_member = gAgent.getGroupData(mID,agent_gdatap) || gAgent.isGodlike();
+ bool is_member = gAgent.getGroupData(mID,agent_gdatap) || gAgent.isGodlikeWithoutAdminMenuFakery();
tab_roles->setVisible(is_member);
tab_notices->setVisible(is_member);
diff --git a/indra/newview/llpanelgroupexperiences.cpp b/indra/newview/llpanelgroupexperiences.cpp
index 76b68122fb..a88a55ab22 100644
--- a/indra/newview/llpanelgroupexperiences.cpp
+++ b/indra/newview/llpanelgroupexperiences.cpp
@@ -31,45 +31,16 @@
#include "lluictrlfactory.h"
#include "roles_constants.h"
-#include "llhttpclient.h"
#include "llagent.h"
#include "llviewerregion.h"
#include "llflatlistview.h"
#include "llpanelexperiences.h"
#include "llsd.h"
-
+#include "llexperiencecache.h"
static LLPanelInjector<LLPanelGroupExperiences> t_panel_group_experiences("panel_group_experiences");
-class LLGroupExperienceResponder : public LLHTTPClient::Responder
-{
-public:
- LLHandle<LLPanelGroupExperiences> mHandle;
-
- LLGroupExperienceResponder(LLHandle<LLPanelGroupExperiences> handle) : mHandle(handle) { }
-
-protected:
- /*virtual*/ void httpSuccess()
- {
- if (mHandle.isDead())
- {
- return;
- }
-
- LLPanelGroupExperiences* panel = mHandle.get();
- if (panel)
- {
- panel->setExperienceList(getContent().get("experience_ids"));
- }
- }
-
- /*virtual*/ void httpFailure()
- {
- LL_WARNS() << "experience responder failed [status:" << getStatus() << "]: " << getContent() << LL_ENDL;
- }
-};
-
LLPanelGroupExperiences::LLPanelGroupExperiences()
: LLPanelGroupTab(), mExperiencesList(NULL)
{
@@ -101,14 +72,8 @@ void LLPanelGroupExperiences::activate()
return;
}
- // search for experiences owned by the current group
- std::string url = gAgent.getRegion()->getCapability("GroupExperiences");
- if (!url.empty())
- {
- url += "?" + getGroupID().asString();
-
- LLHTTPClient::get(url, new LLGroupExperienceResponder(getDerivedHandle<LLPanelGroupExperiences>()));
- }
+ LLExperienceCache::instance().getGroupExperiences(getGroupID(),
+ boost::bind(&LLPanelGroupExperiences::groupExperiencesResults, getDerivedHandle<LLPanelGroupExperiences>(), _1));
}
void LLPanelGroupExperiences::setGroupID(const LLUUID& id)
@@ -141,3 +106,19 @@ void LLPanelGroupExperiences::setExperienceList(const LLSD& experiences)
mExperiencesList->addItem(item, public_key);
}
}
+
+/*static*/
+void LLPanelGroupExperiences::groupExperiencesResults(LLHandle<LLPanelGroupExperiences> handle, const LLSD &experiences)
+{
+ if (handle.isDead())
+ {
+ return;
+ }
+
+ LLPanelGroupExperiences* panel = handle.get();
+ if (panel)
+ {
+ panel->setExperienceList(experiences);
+ }
+
+}
diff --git a/indra/newview/llpanelgroupexperiences.h b/indra/newview/llpanelgroupexperiences.h
index ae1ecc1ac5..7c79f77332 100644
--- a/indra/newview/llpanelgroupexperiences.h
+++ b/indra/newview/llpanelgroupexperiences.h
@@ -48,6 +48,9 @@ public:
protected:
LLFlatListView* mExperiencesList;
+
+private:
+ static void groupExperiencesResults(LLHandle<LLPanelGroupExperiences>, const LLSD &);
};
#endif
diff --git a/indra/newview/llpanelgroupgeneral.cpp b/indra/newview/llpanelgroupgeneral.cpp
index 7ffaa05919..b2164c1f21 100755
--- a/indra/newview/llpanelgroupgeneral.cpp
+++ b/indra/newview/llpanelgroupgeneral.cpp
@@ -287,11 +287,6 @@ void LLPanelGroupGeneral::activate()
{
LLGroupMgr::getInstance()->sendGroupTitlesRequest(mGroupID);
LLGroupMgr::getInstance()->sendGroupPropertiesRequest(mGroupID);
-
- if (!gdatap || !gdatap->isMemberDataComplete() )
- {
- LLGroupMgr::getInstance()->sendCapGroupMembersRequest(mGroupID);
- }
mFirstUse = FALSE;
}
diff --git a/indra/newview/llpanelgroupinvite.cpp b/indra/newview/llpanelgroupinvite.cpp
index e662a05dfc..866cb8dbef 100755
--- a/indra/newview/llpanelgroupinvite.cpp
+++ b/indra/newview/llpanelgroupinvite.cpp
@@ -243,56 +243,59 @@ void LLPanelGroupInvite::impl::addRoleNames(LLGroupMgrGroupData* gdatap)
LLGroupMgrGroupData::member_list_t::iterator agent_iter =
gdatap->mMembers.find(gAgent.getID());
+ //loop over the agent's roles in the group
+ //then add those roles to the list of roles that the agent
+ //can invite people to be.
+ //if the user is the owner then we add
+ //all of the roles in the group,
+ //else if they have the add to roles power
+ //we add every role but owner,
+ //else if they have the limited add to roles power
+ //we add every role the user is in,
+ //else we just add to everyone
+ bool is_owner = FALSE;
+ bool can_assign_any = gAgent.hasPowerInGroup(mGroupID,
+ GP_ROLE_ASSIGN_MEMBER);
+ bool can_assign_limited = gAgent.hasPowerInGroup(mGroupID,
+ GP_ROLE_ASSIGN_MEMBER_LIMITED);
+ LLGroupMemberData* member_data = NULL;
//get the member data for the agent if it exists
- if ( agent_iter != gdatap->mMembers.end() )
+ if (agent_iter != gdatap->mMembers.end())
{
- LLGroupMemberData* member_data = (*agent_iter).second;
-
- //loop over the agent's roles in the group
- //then add those roles to the list of roles that the agent
- //can invite people to be
- if ( member_data && mRoleNames)
+ member_data = (*agent_iter).second;
+ if (member_data && mRoleNames)
{
- //if the user is the owner then we add
- //all of the roles in the group
- //else if they have the add to roles power
- //we add every role but owner,
- //else if they have the limited add to roles power
- //we add every role the user is in
- //else we just add to everyone
- bool is_owner = member_data->isOwner();
- bool can_assign_any = gAgent.hasPowerInGroup(mGroupID,
- GP_ROLE_ASSIGN_MEMBER);
- bool can_assign_limited = gAgent.hasPowerInGroup(mGroupID,
- GP_ROLE_ASSIGN_MEMBER_LIMITED);
+ is_owner = member_data->isOwner();
+ }//end if member data is not null
+ }//end if agent is in the group
+
- LLGroupMgrGroupData::role_list_t::iterator rit = gdatap->mRoles.begin();
- LLGroupMgrGroupData::role_list_t::iterator end = gdatap->mRoles.end();
- //populate the role list
- for ( ; rit != end; ++rit)
+ LLGroupMgrGroupData::role_list_t::iterator rit = gdatap->mRoles.begin();
+ LLGroupMgrGroupData::role_list_t::iterator end = gdatap->mRoles.end();
+
+ //populate the role list:
+ for ( ; rit != end; ++rit)
+ {
+ LLUUID role_id = (*rit).first;
+ LLRoleData rd;
+ if ( gdatap->getRoleData(role_id,rd) )
+ {
+ // Owners can add any role.
+ if ( is_owner
+ // Even 'can_assign_any' can't add owner role.
+ || (can_assign_any && role_id != gdatap->mOwnerRole)
+ // Add all roles user is in
+ || (can_assign_limited && member_data && member_data->isInRole(role_id))
+ // Everyone role.
+ || role_id == LLUUID::null )
{
- LLUUID role_id = (*rit).first;
- LLRoleData rd;
- if ( gdatap->getRoleData(role_id,rd) )
- {
- // Owners can add any role.
- if ( is_owner
- // Even 'can_assign_any' can't add owner role.
- || (can_assign_any && role_id != gdatap->mOwnerRole)
- // Add all roles user is in
- || (can_assign_limited && member_data->isInRole(role_id))
- // Everyone role.
- || role_id == LLUUID::null )
- {
- mRoleNames->add(rd.mRoleName,
- role_id,
- ADD_BOTTOM);
- }
- }
+ mRoleNames->add(rd.mRoleName,
+ role_id,
+ ADD_BOTTOM);
}
- }//end if member data is not null
- }//end if agent is in the group
+ }
+ }
}
//static
@@ -579,7 +582,8 @@ void LLPanelGroupInvite::updateLists()
{
waiting = true;
}
- if (gdatap->isRoleDataComplete() && gdatap->isMemberDataComplete() && gdatap->isRoleMemberDataComplete())
+ if (gdatap->isRoleDataComplete() && gdatap->isMemberDataComplete()
+ && (gdatap->isRoleMemberDataComplete() || !gdatap->mMembers.size())) // MAINT-5270: large groups receives an empty members list without some powers, so RoleMemberData wouldn't be complete for them
{
if ( mImplementation->mRoleNames )
{
diff --git a/indra/newview/llpanelgrouproles.cpp b/indra/newview/llpanelgrouproles.cpp
index c3a10b3fa0..00c204e702 100755
--- a/indra/newview/llpanelgrouproles.cpp
+++ b/indra/newview/llpanelgrouproles.cpp
@@ -350,12 +350,10 @@ void LLPanelGroupRoles::update(LLGroupChange gc)
void LLPanelGroupRoles::activate()
{
+ if (!gAgent.isInGroup(mGroupID)) return;
+
// Start requesting member and role data if needed.
LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mGroupID);
- if (!gdatap || !gdatap->isMemberDataComplete() )
- {
- LLGroupMgr::getInstance()->sendCapGroupMembersRequest(mGroupID);
- }
if (!gdatap || !gdatap->isRoleDataComplete() )
{
@@ -364,13 +362,7 @@ void LLPanelGroupRoles::activate()
LLGroupMgr::getInstance()->sendGroupRoleDataRequest(mGroupID);
}
-
- // Check role-member mapping data.
- if (!gdatap || !gdatap->isRoleMemberDataComplete() )
- {
- LLGroupMgr::getInstance()->sendGroupRoleMembersRequest(mGroupID);
- }
-
+
// Need this to get base group member powers
if (!gdatap || !gdatap->isGroupPropertiesDataComplete() )
{
@@ -1163,7 +1155,37 @@ void LLPanelGroupMembersSubTab::onEjectMembers(void *userdata)
if ( selfp )
{
- selfp->handleEjectMembers();
+ selfp->confirmEjectMembers();
+ }
+}
+
+void LLPanelGroupMembersSubTab::confirmEjectMembers()
+{
+ std::vector<LLScrollListItem*> selection = mMembersList->getAllSelected();
+ if (selection.empty()) return;
+
+ S32 selection_count = selection.size();
+ if (selection_count == 1)
+ {
+ LLSD args;
+ std::string fullname;
+ gCacheName->getFullName(mMembersList->getValue(), fullname);
+ args["AVATAR_NAME"] = fullname;
+ LLSD payload;
+ LLNotificationsUtil::add("EjectGroupMemberWarning",
+ args,
+ payload,
+ boost::bind(&LLPanelGroupMembersSubTab::handleEjectCallback, this, _1, _2));
+ }
+ else
+ {
+ LLSD args;
+ args["COUNT"] = llformat("%d", selection_count);
+ LLSD payload;
+ LLNotificationsUtil::add("EjectGroupMembersWarning",
+ args,
+ payload,
+ boost::bind(&LLPanelGroupMembersSubTab::handleEjectCallback, this, _1, _2));
}
}
@@ -1190,6 +1212,16 @@ void LLPanelGroupMembersSubTab::handleEjectMembers()
LLGroupMgr::getInstance()->sendGroupMemberEjects(mGroupID, selected_members);
}
+bool LLPanelGroupMembersSubTab::handleEjectCallback(const LLSD& notification, const LLSD& response)
+{
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+ if (0 == option) // Eject button
+ {
+ handleEjectMembers();
+ }
+ return false;
+}
+
void LLPanelGroupMembersSubTab::sendEjectNotifications(const LLUUID& group_id, const uuid_vec_t& selected_members)
{
LLGroupMgrGroupData* group_data = LLGroupMgr::getInstance()->getGroupData(group_id);
@@ -1327,15 +1359,26 @@ void LLPanelGroupMembersSubTab::handleMemberDoubleClick()
void LLPanelGroupMembersSubTab::activate()
{
+ LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mGroupID);
+
LLPanelGroupSubTab::activate();
if(!mActivated)
{
+ if (!gdatap || !gdatap->isMemberDataComplete())
+ {
+ LLGroupMgr::getInstance()->sendCapGroupMembersRequest(mGroupID);
+ }
+
+ if (!gdatap || !gdatap->isRoleMemberDataComplete())
+ {
+ LLGroupMgr::getInstance()->sendGroupRoleMembersRequest(mGroupID);
+ }
+
update(GC_ALL);
mActivated = true;
}
else
{
- LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mGroupID);
// Members can be removed outside of this tab, checking changes
if (!gdatap || (gdatap->isMemberDataComplete() && gdatap->mMembers.size() != mMembersList->getItemCount()))
{
@@ -1636,7 +1679,13 @@ void LLPanelGroupMembersSubTab::update(LLGroupChange gc)
{
// Build a string with info on retrieval progress.
std::ostringstream retrieved;
- if ( !gdatap->isMemberDataComplete() )
+
+ if ( gdatap->isRoleDataComplete() && gdatap->isMemberDataComplete() && !gdatap->mMembers.size() )
+ {
+ // MAINT-5237
+ retrieved << "Member list not available.";
+ }
+ else if ( !gdatap->isMemberDataComplete() )
{
// Still busy retreiving member list.
retrieved << "Retrieving member list (" << gdatap->mMembers.size()
@@ -1783,7 +1832,7 @@ void LLPanelGroupMembersSubTab::updateMembers()
{
mMembersList->setEnabled(TRUE);
}
- else
+ else if (gdatap->mMembers.size())
{
mMembersList->setEnabled(FALSE);
mMembersList->setCommentText(std::string("No match."));
@@ -1801,7 +1850,47 @@ void LLPanelGroupMembersSubTab::updateMembers()
void LLPanelGroupMembersSubTab::onBanMember(void* user_data)
{
LLPanelGroupMembersSubTab* self = static_cast<LLPanelGroupMembersSubTab*>(user_data);
- self->handleBanMember();
+ self->confirmBanMembers();
+}
+
+void LLPanelGroupMembersSubTab::confirmBanMembers()
+{
+ std::vector<LLScrollListItem*> selection = mMembersList->getAllSelected();
+ if (selection.empty()) return;
+
+ S32 selection_count = selection.size();
+ if (selection_count == 1)
+ {
+ LLSD args;
+ std::string fullname;
+ gCacheName->getFullName(mMembersList->getValue(), fullname);
+ args["AVATAR_NAME"] = fullname;
+ LLSD payload;
+ LLNotificationsUtil::add("BanGroupMemberWarning",
+ args,
+ payload,
+ boost::bind(&LLPanelGroupMembersSubTab::handleBanCallback, this, _1, _2));
+ }
+ else
+ {
+ LLSD args;
+ args["COUNT"] = llformat("%d", selection_count);
+ LLSD payload;
+ LLNotificationsUtil::add("BanGroupMembersWarning",
+ args,
+ payload,
+ boost::bind(&LLPanelGroupMembersSubTab::handleBanCallback, this, _1, _2));
+ }
+}
+
+bool LLPanelGroupMembersSubTab::handleBanCallback(const LLSD& notification, const LLSD& response)
+{
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+ if (0 == option) // Eject button
+ {
+ handleBanMember();
+ }
+ return false;
}
void LLPanelGroupMembersSubTab::handleBanMember()
@@ -2111,20 +2200,7 @@ void LLPanelGroupRolesSubTab::update(LLGroupChange gc)
mDeleteRoleButton->setEnabled(FALSE);
}
}
-
- if(!mFirstOpen)
- {
- if (!gdatap || !gdatap->isMemberDataComplete())
- {
- LLGroupMgr::getInstance()->sendCapGroupMembersRequest(mGroupID);
- }
-
- if (!gdatap || !gdatap->isRoleMemberDataComplete())
- {
- LLGroupMgr::getInstance()->sendGroupRoleMembersRequest(mGroupID);
- }
- }
-
+
if ((GC_ROLE_MEMBER_DATA == gc || GC_MEMBER_DATA == gc)
&& gdatap
&& gdatap->isMemberDataComplete()
diff --git a/indra/newview/llpanelgrouproles.h b/indra/newview/llpanelgrouproles.h
index 540b24ada6..9a696124a8 100755
--- a/indra/newview/llpanelgrouproles.h
+++ b/indra/newview/llpanelgrouproles.h
@@ -171,6 +171,7 @@ public:
void handleEjectMembers();
void sendEjectNotifications(const LLUUID& group_id, const uuid_vec_t& selected_members);
bool handleEjectCallback(const LLSD& notification, const LLSD& response);
+ void confirmEjectMembers();
static void onRoleCheck(LLUICtrl* check, void* user_data);
void handleRoleCheck(const LLUUID& role_id,
@@ -178,6 +179,8 @@ public:
static void onBanMember(void* user_data);
void handleBanMember();
+ bool handleBanCallback(const LLSD& notification, const LLSD& response);
+ void confirmBanMembers();
void applyMemberChanges();
diff --git a/indra/newview/llpanellandmarkinfo.cpp b/indra/newview/llpanellandmarkinfo.cpp
index d4894d4a42..06bb886ae8 100755
--- a/indra/newview/llpanellandmarkinfo.cpp
+++ b/indra/newview/llpanellandmarkinfo.cpp
@@ -147,6 +147,7 @@ void LLPanelLandmarkInfo::setInfoType(EInfoType type)
}
else
{
+ LLAgentUI::buildLocationString(desc, LLAgentUI::LOCATION_FORMAT_NORMAL, agent_pos);
region_name = desc;
}
diff --git a/indra/newview/llpanellogin.cpp b/indra/newview/llpanellogin.cpp
index f972b320c3..360b144604 100755
--- a/indra/newview/llpanellogin.cpp
+++ b/indra/newview/llpanellogin.cpp
@@ -40,7 +40,6 @@
#include "llcheckboxctrl.h"
#include "llcommandhandler.h" // for secondlife:///app/login/
#include "llcombobox.h"
-#include "llcurl.h"
#include "llviewercontrol.h"
#include "llfloaterpreference.h"
#include "llfocusmgr.h"
@@ -435,17 +434,10 @@ void LLPanelLogin::show(const LLRect &rect,
void (*callback)(S32 option, void* user_data),
void* callback_data)
{
- // instance management
- if (LLPanelLogin::sInstance)
- {
- LL_WARNS("AppInit") << "Duplicate instance of login view deleted" << LL_ENDL;
- // Don't leave bad pointer in gFocusMgr
- gFocusMgr.setDefaultKeyboardFocus(NULL);
-
- delete LLPanelLogin::sInstance;
- }
-
- new LLPanelLogin(rect, callback, callback_data);
+ if (!LLPanelLogin::sInstance)
+ {
+ new LLPanelLogin(rect, callback, callback_data);
+ }
if( !gFocusMgr.getKeyboardFocus() )
{
diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp
index 7aaf9510eb..4229419fce 100755
--- a/indra/newview/llpanelmaininventory.cpp
+++ b/indra/newview/llpanelmaininventory.cpp
@@ -604,7 +604,7 @@ void LLPanelMainInventory::updateItemcountText()
}
else
{
- text = getString("ItemcountUnknown");
+ text = getString("ItemcountUnknown", string_args);
}
mCounterCtrl->setValue(text);
diff --git a/indra/newview/llpanelmediasettingsgeneral.cpp b/indra/newview/llpanelmediasettingsgeneral.cpp
index 2856ea9db1..d7c43c224c 100755
--- a/indra/newview/llpanelmediasettingsgeneral.cpp
+++ b/indra/newview/llpanelmediasettingsgeneral.cpp
@@ -319,6 +319,10 @@ void LLPanelMediaSettingsGeneral::initValues( void* userdata, const LLSD& _media
// Helper to set media control to media URL as required
void LLPanelMediaSettingsGeneral::updateMediaPreview()
{
+ if(LLTrans::getString("Multiple Media") == mHomeURL->getValue().asString())
+ {
+ return;
+ }
if ( mHomeURL->getValue().asString().length() > 0 )
{
if(mPreviewMedia->getCurrentNavUrl() != mHomeURL->getValue().asString())
diff --git a/indra/newview/llpanelobject.cpp b/indra/newview/llpanelobject.cpp
index dcd0aab3ab..5dd44b4444 100755
--- a/indra/newview/llpanelobject.cpp
+++ b/indra/newview/llpanelobject.cpp
@@ -1739,9 +1739,10 @@ void LLPanelObject::sendSculpt()
return;
LLSculptParams sculpt_params;
+ LLUUID sculpt_id = LLUUID::null;
if (mCtrlSculptTexture)
- sculpt_params.setSculptTexture(mCtrlSculptTexture->getImageAssetID());
+ sculpt_id = mCtrlSculptTexture->getImageAssetID();
U8 sculpt_type = 0;
@@ -1765,7 +1766,7 @@ void LLPanelObject::sendSculpt()
if ((mCtrlSculptInvert) && (mCtrlSculptInvert->get()))
sculpt_type |= LL_SCULPT_FLAG_INVERT;
- sculpt_params.setSculptType(sculpt_type);
+ sculpt_params.setSculptTexture(sculpt_id, sculpt_type);
mObject->setParameterEntry(LLNetworkData::PARAMS_SCULPT, sculpt_params, TRUE);
}
@@ -2000,7 +2001,11 @@ void LLPanelObject::onCancelSculpt(const LLSD& data)
LLTextureCtrl* mTextureCtrl = getChild<LLTextureCtrl>("sculpt texture control");
if(!mTextureCtrl)
return;
-
+
+ if(mSculptTextureRevert == LLUUID::null)
+ {
+ mSculptTextureRevert = LLUUID(SCULPT_DEFAULT_TEXTURE);
+ }
mTextureCtrl->setImageAssetID(mSculptTextureRevert);
sendSculpt();
diff --git a/indra/newview/llpanelpeople.cpp b/indra/newview/llpanelpeople.cpp
index 5977d558d3..de4efc8612 100755
--- a/indra/newview/llpanelpeople.cpp
+++ b/indra/newview/llpanelpeople.cpp
@@ -85,6 +85,8 @@ static const std::string RECENT_TAB_NAME = "recent_panel";
static const std::string BLOCKED_TAB_NAME = "blocked_panel"; // blocked avatars
static const std::string COLLAPSED_BY_USER = "collapsed_by_user";
+const S32 BASE_MAX_AGENT_GROUPS = 42;
+const S32 PREMIUM_MAX_AGENT_GROUPS = 60;
extern S32 gMaxAgentGroups;
@@ -585,6 +587,7 @@ BOOL LLPanelPeople::postBuild()
getChild<LLFilterEditor>("groups_filter_input")->setCommitCallback(boost::bind(&LLPanelPeople::onFilterEdit, this, _2));
getChild<LLFilterEditor>("recent_filter_input")->setCommitCallback(boost::bind(&LLPanelPeople::onFilterEdit, this, _2));
getChild<LLFilterEditor>("fbc_filter_input")->setCommitCallback(boost::bind(&LLPanelPeople::onFilterEdit, this, _2));
+ getChild<LLTextBox>("groupcount")->setURLClickedCallback(boost::bind(&LLPanelPeople::onGroupLimitInfo, this));
mTabContainer = getChild<LLTabContainer>("tabs");
mTabContainer->setCommitCallback(boost::bind(&LLPanelPeople::onTabSelected, this, _2));
@@ -902,8 +905,11 @@ void LLPanelPeople::updateButtons()
LLPanel* groups_panel = mTabContainer->getCurrentPanel();
groups_panel->getChildView("minus_btn")->setEnabled(item_selected && selected_id.notNull()); // a real group selected
- groups_panel->getChild<LLUICtrl>("groupcount")->setTextArg("[COUNT]", llformat("%d",gAgent.mGroups.size()));
- groups_panel->getChild<LLUICtrl>("groupcount")->setTextArg("[REMAINING]", llformat("%d",(gMaxAgentGroups-gAgent.mGroups.size())));
+
+ U32 groups_count = gAgent.mGroups.size();
+ U32 groups_ramaining = gMaxAgentGroups > groups_count ? gMaxAgentGroups - groups_count : 0;
+ groups_panel->getChild<LLUICtrl>("groupcount")->setTextArg("[COUNT]", llformat("%d", groups_count));
+ groups_panel->getChild<LLUICtrl>("groupcount")->setTextArg("[REMAINING]", llformat("%d", groups_ramaining));
}
else
{
@@ -1114,6 +1120,14 @@ void LLPanelPeople::onFilterEdit(const std::string& search_string)
}
}
+void LLPanelPeople::onGroupLimitInfo()
+{
+ LLSD args;
+ args["MAX_BASIC"] = BASE_MAX_AGENT_GROUPS;
+ args["MAX_PREMIUM"] = PREMIUM_MAX_AGENT_GROUPS;
+ LLNotificationsUtil::add("GroupLimitInfo", args);
+}
+
void LLPanelPeople::onTabSelected(const LLSD& param)
{
std::string tab_name = getChild<LLPanel>(param.asString())->getName();
diff --git a/indra/newview/llpanelpeople.h b/indra/newview/llpanelpeople.h
index c1d7a134fa..eb7e76a772 100755
--- a/indra/newview/llpanelpeople.h
+++ b/indra/newview/llpanelpeople.h
@@ -93,6 +93,7 @@ private:
// UI callbacks
void onFilterEdit(const std::string& search_string);
+ void onGroupLimitInfo();
void onTabSelected(const LLSD& param);
void onAddFriendButtonClicked();
void onAddFriendWizButtonClicked();
diff --git a/indra/newview/llpanelpicks.cpp b/indra/newview/llpanelpicks.cpp
index d73a5b402e..55c09d85ea 100755
--- a/indra/newview/llpanelpicks.cpp
+++ b/indra/newview/llpanelpicks.cpp
@@ -432,7 +432,7 @@ void LLPanelPicks::processProperties(void* data, EAvatarProcessorType type)
mNoPicks = !mPicksList->size();
}
- else if(APT_CLASSIFIEDS == type)
+ else if((APT_CLASSIFIEDS == type) || (APT_CLASSIFIED_INFO == type))
{
LLAvatarClassifieds* c_info = static_cast<LLAvatarClassifieds*>(data);
if(c_info && getAvatarId() == c_info->target_id)
diff --git a/indra/newview/llpanelplaces.cpp b/indra/newview/llpanelplaces.cpp
index 4bcd932d4b..a9a0c30e26 100755
--- a/indra/newview/llpanelplaces.cpp
+++ b/indra/newview/llpanelplaces.cpp
@@ -921,7 +921,12 @@ void LLPanelPlaces::onBackButtonClicked()
void LLPanelPlaces::togglePickPanel(BOOL visible)
{
if (mPickPanel)
+ {
mPickPanel->setVisible(visible);
+ mPlaceProfile->setVisible(!visible);
+ updateVerbs();
+ }
+
}
void LLPanelPlaces::togglePlaceInfoPanel(BOOL visible)
@@ -1141,16 +1146,21 @@ void LLPanelPlaces::updateVerbs()
bool is_agent_place_info_visible = mPlaceInfoType == AGENT_INFO_TYPE;
bool is_create_landmark_visible = mPlaceInfoType == CREATE_LANDMARK_INFO_TYPE;
+ bool is_pick_panel_visible = false;
+ if(mPickPanel)
+ {
+ is_pick_panel_visible = mPickPanel->isInVisibleChain();
+ }
bool have_3d_pos = ! mPosGlobal.isExactlyZero();
- mTeleportBtn->setVisible(!is_create_landmark_visible && !isLandmarkEditModeOn);
- mShowOnMapBtn->setVisible(!is_create_landmark_visible && !isLandmarkEditModeOn);
+ mTeleportBtn->setVisible(!is_create_landmark_visible && !isLandmarkEditModeOn && !is_pick_panel_visible);
+ mShowOnMapBtn->setVisible(!is_create_landmark_visible && !isLandmarkEditModeOn && !is_pick_panel_visible);
mOverflowBtn->setVisible(is_place_info_visible && !is_create_landmark_visible && !isLandmarkEditModeOn);
mEditBtn->setVisible(mPlaceInfoType == LANDMARK_INFO_TYPE && !isLandmarkEditModeOn);
mSaveBtn->setVisible(isLandmarkEditModeOn);
mCancelBtn->setVisible(isLandmarkEditModeOn);
mCloseBtn->setVisible(is_create_landmark_visible && !isLandmarkEditModeOn);
- mPlaceInfoBtn->setVisible(!is_place_info_visible && !is_create_landmark_visible && !isLandmarkEditModeOn);
+ mPlaceInfoBtn->setVisible(!is_place_info_visible && !is_create_landmark_visible && !isLandmarkEditModeOn && !is_pick_panel_visible);
mPlaceInfoBtn->setEnabled(!is_create_landmark_visible && !isLandmarkEditModeOn && have_3d_pos);
diff --git a/indra/newview/llpaneltopinfobar.cpp b/indra/newview/llpaneltopinfobar.cpp
index ac9a31ce4e..109013498e 100755
--- a/indra/newview/llpaneltopinfobar.cpp
+++ b/indra/newview/llpaneltopinfobar.cpp
@@ -313,14 +313,11 @@ void LLPanelTopInfoBar::updateParcelIcons()
bool allow_damage = vpm->allowAgentDamage(agent_region, current_parcel);
bool see_avs = current_parcel->getSeeAVs();
- bool is_parcel_owner = (gAgent.getID() == current_parcel->getOwnerID());
- bool allow_group_modify = (gAgent.isInGroup(current_parcel->getGroupID()) && current_parcel->getAllowGroupModify());
-
// Most icons are "block this ability"
mParcelIcon[VOICE_ICON]->setVisible( !allow_voice );
mParcelIcon[FLY_ICON]->setVisible( !allow_fly );
mParcelIcon[PUSH_ICON]->setVisible( !allow_push );
- mParcelIcon[BUILD_ICON]->setVisible( !allow_build && !is_parcel_owner && !allow_group_modify );
+ mParcelIcon[BUILD_ICON]->setVisible( !allow_build );
mParcelIcon[SCRIPTS_ICON]->setVisible( !allow_scripts );
mParcelIcon[DAMAGE_ICON]->setVisible( allow_damage );
mDamageText->setVisible(allow_damage);
diff --git a/indra/newview/llpathfindingmanager.cpp b/indra/newview/llpathfindingmanager.cpp
index 2e6937a79f..711a869e82 100755
--- a/indra/newview/llpathfindingmanager.cpp
+++ b/indra/newview/llpathfindingmanager.cpp
@@ -464,7 +464,7 @@ void LLPathfindingManager::navMeshStatusRequestCoro(std::string url, U64 regionH
LLUUID regionUUID = region->getRegionID();
region = NULL;
- LLSD result = httpAdapter->getAndYield(httpRequest, url);
+ LLSD result = httpAdapter->getAndSuspend(httpRequest, url);
region = LLWorld::getInstance()->getRegionFromHandle(regionHandle);
@@ -519,7 +519,7 @@ void LLPathfindingManager::navMeshStatusRequestCoro(std::string url, U64 regionH
navMeshPtr->handleNavMeshStart(navMeshStatus);
LLSD postData;
- result = httpAdapter->postAndYield(httpRequest, navMeshURL, postData);
+ result = httpAdapter->postAndSuspend(httpRequest, navMeshURL, postData);
U32 navMeshVersion = navMeshStatus.getVersion();
@@ -545,7 +545,7 @@ void LLPathfindingManager::navAgentStateRequestCoro(std::string url)
httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("NavAgentStateRequest", httpPolicy));
LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
- LLSD result = httpAdapter->getAndYield(httpRequest, url);
+ LLSD result = httpAdapter->getAndSuspend(httpRequest, url);
LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
@@ -577,7 +577,7 @@ void LLPathfindingManager::navMeshRebakeCoro(std::string url, rebake_navmesh_cal
LLSD postData = LLSD::emptyMap();
postData["command"] = "rebuild";
- LLSD result = httpAdapter->postAndYield(httpRequest, url, postData);
+ LLSD result = httpAdapter->postAndSuspend(httpRequest, url, postData);
LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
@@ -606,11 +606,11 @@ void LLPathfindingManager::linksetObjectsCoro(std::string url, LinksetsResponder
if (putData.isUndefined())
{
- result = httpAdapter->getAndYield(httpRequest, url);
+ result = httpAdapter->getAndSuspend(httpRequest, url);
}
else
{
- result = httpAdapter->putAndYield(httpRequest, url, putData);
+ result = httpAdapter->putAndSuspend(httpRequest, url, putData);
}
LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
@@ -642,11 +642,11 @@ void LLPathfindingManager::linksetTerrainCoro(std::string url, LinksetsResponder
if (putData.isUndefined())
{
- result = httpAdapter->getAndYield(httpRequest, url);
+ result = httpAdapter->getAndSuspend(httpRequest, url);
}
else
{
- result = httpAdapter->putAndYield(httpRequest, url, putData);
+ result = httpAdapter->putAndSuspend(httpRequest, url, putData);
}
LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
@@ -673,7 +673,7 @@ void LLPathfindingManager::charactersCoro(std::string url, request_id_t requestI
httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("LinksetTerrain", httpPolicy));
LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
- LLSD result = httpAdapter->getAndYield(httpRequest, url);
+ LLSD result = httpAdapter->getAndSuspend(httpRequest, url);
LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp
index 4f5d21b6be..ed34190caa 100755
--- a/indra/newview/llpreviewscript.cpp
+++ b/indra/newview/llpreviewscript.cpp
@@ -87,7 +87,6 @@
#include "llfloatergotoline.h"
#include "llexperiencecache.h"
#include "llfloaterexperienceprofile.h"
-#include "llexperienceassociationresponder.h"
#include "llviewerassetupload.h"
const std::string HELLO_LSL =
@@ -1326,7 +1325,7 @@ void LLLiveLSLEditor::buildExperienceList()
position = ADD_TOP;
}
- const LLSD& experience = LLExperienceCache::getInstance()->get(id);
+ const LLSD& experience = LLExperienceCache::instance().get(id);
if(experience.isUndefined())
{
mExperiences->add(getString("loading"), id, position);
@@ -1345,7 +1344,7 @@ void LLLiveLSLEditor::buildExperienceList()
if(!foundAssociated )
{
- const LLSD& experience = LLExperienceCache::getInstance()->get(associated);
+ const LLSD& experience = LLExperienceCache::instance().get(associated);
if(experience.isDefined())
{
std::string experience_name_string = experience[LLExperienceCache::NAME].asString();
@@ -1366,11 +1365,13 @@ void LLLiveLSLEditor::buildExperienceList()
if(last.notNull())
{
mExperiences->setEnabled(FALSE);
- LLExperienceCache::getInstance()->get(last, boost::bind(&LLLiveLSLEditor::buildExperienceList, this));
+ LLExperienceCache::instance().get(last, boost::bind(&LLLiveLSLEditor::buildExperienceList, this));
}
else
{
mExperiences->setEnabled(TRUE);
+ mExperiences->sortByName(TRUE);
+ mExperiences->setCurrentByIndex(mExperiences->getCurrentIndex());
getChild<LLButton>("view_profile")->setVisible(TRUE);
}
}
@@ -2039,8 +2040,9 @@ void LLLiveLSLEditor::loadAsset()
if(item)
{
- ExperienceAssociationResponder::fetchAssociatedExperience(item->getParentUUID(), item->getUUID(), boost::bind(&LLLiveLSLEditor::setAssociatedExperience, getDerivedHandle<LLLiveLSLEditor>(), _1));
-
+ LLExperienceCache::instance().fetchAssociatedExperience(item->getParentUUID(), item->getUUID(),
+ boost::bind(&LLLiveLSLEditor::setAssociatedExperience, getDerivedHandle<LLLiveLSLEditor>(), _1));
+
bool isGodlike = gAgent.isGodlike();
bool copyManipulate = gAgent.allowOperation(PERM_COPY, item->getPermissions(), GP_OBJECT_MANIPULATE);
mIsModifiable = gAgent.allowOperation(PERM_MODIFY, item->getPermissions(), GP_OBJECT_MANIPULATE);
@@ -2642,8 +2644,12 @@ void LLLiveLSLEditor::onLoad(void* userdata)
void LLLiveLSLEditor::onSave(void* userdata, BOOL close_after_save)
{
LLLiveLSLEditor* self = (LLLiveLSLEditor*)userdata;
- self->mCloseAfterSave = close_after_save;
- self->saveIfNeeded();
+ if(self)
+ {
+ self->mCloseAfterSave = close_after_save;
+ self->mScriptEd->mErrorList->setCommentText("");
+ self->saveIfNeeded();
+ }
}
diff --git a/indra/newview/llpreviewtexture.cpp b/indra/newview/llpreviewtexture.cpp
index f91a18d8d3..c8cf0faa15 100755
--- a/indra/newview/llpreviewtexture.cpp
+++ b/indra/newview/llpreviewtexture.cpp
@@ -618,4 +618,5 @@ void LLPreviewTexture::setObjectID(const LLUUID& object_id)
mAssetStatus = PREVIEW_ASSET_UNLOADED;
loadAsset();
}
+ refreshFromItem();
}
diff --git a/indra/newview/llproductinforequest.cpp b/indra/newview/llproductinforequest.cpp
index 467e9df482..b663df4aae 100755
--- a/indra/newview/llproductinforequest.cpp
+++ b/indra/newview/llproductinforequest.cpp
@@ -73,7 +73,7 @@ void LLProductInfoRequestManager::getLandDescriptionsCoro(std::string url)
httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("genericPostCoro", httpPolicy));
LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
- LLSD result = httpAdapter->getAndYield(httpRequest, url);
+ LLSD result = httpAdapter->getAndSuspend(httpRequest, url);
LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
diff --git a/indra/newview/llprogressview.cpp b/indra/newview/llprogressview.cpp
index 1257ee7f94..c17b86783d 100755
--- a/indra/newview/llprogressview.cpp
+++ b/indra/newview/llprogressview.cpp
@@ -175,6 +175,10 @@ void LLProgressView::setStartupComplete()
void LLProgressView::setVisible(BOOL visible)
{
+ if (!visible && mFadeFromLoginTimer.getStarted())
+ {
+ mFadeFromLoginTimer.stop();
+ }
// hiding progress view
if (getVisible() && !visible)
{
diff --git a/indra/newview/llremoteparcelrequest.cpp b/indra/newview/llremoteparcelrequest.cpp
index 06bf90c7cb..055ccd5818 100755
--- a/indra/newview/llremoteparcelrequest.cpp
+++ b/indra/newview/llremoteparcelrequest.cpp
@@ -200,7 +200,7 @@ void LLRemoteParcelInfoProcessor::regionParcelInfoCoro(std::string url,
bodyData["region_handle"] = ll_sd_from_U64(regionHandle);
}
- LLSD result = httpAdapter->postAndYield(httpRequest, url, bodyData);
+ LLSD result = httpAdapter->postAndSuspend(httpRequest, url, bodyData);
LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
diff --git a/indra/newview/llsecapi.cpp b/indra/newview/llsecapi.cpp
index 43bb7b1596..4f9f83b6f2 100755
--- a/indra/newview/llsecapi.cpp
+++ b/indra/newview/llsecapi.cpp
@@ -32,7 +32,6 @@
#include <openssl/evp.h>
#include <openssl/err.h>
#include <map>
-#include "llhttpclient.h"
@@ -99,46 +98,6 @@ std::ostream& operator <<(std::ostream& s, const LLCredential& cred)
return s << (std::string)cred;
}
-
-// secapiSSLCertVerifyCallback
-// basic callback called when a cert verification is requested.
-// calls SECAPI to validate the context
-// not initialized in the above initialization function, due to unit tests
-// see llappviewer
-
-int secapiSSLCertVerifyCallback(X509_STORE_CTX *ctx, void *param)
-{
- LLURLRequest *req = (LLURLRequest *)param;
- LLPointer<LLCertificateStore> store = gSecAPIHandler->getCertificateStore("");
- LLPointer<LLCertificateChain> chain = gSecAPIHandler->getCertificateChain(ctx);
- LLSD validation_params = LLSD::emptyMap();
- LLURI uri(req->getURL());
- validation_params[CERT_HOSTNAME] = uri.hostName();
- try
- {
- // we rely on libcurl to validate the hostname, as libcurl does more extensive validation
- // leaving our hostname validation call mechanism for future additions with respect to
- // OS native (Mac keyring, windows CAPI) validation.
- store->validate(VALIDATION_POLICY_SSL & (~VALIDATION_POLICY_HOSTNAME), chain, validation_params);
- }
- catch (LLCertValidationTrustException& cert_exception)
- {
- LL_WARNS("AppInit") << "Cert not trusted: " << cert_exception.getMessage() << LL_ENDL;
- return 0;
- }
- catch (LLCertException& cert_exception)
- {
- LL_WARNS("AppInit") << "cert error " << cert_exception.getMessage() << LL_ENDL;
- return 0;
- }
- catch (...)
- {
- LL_WARNS("AppInit") << "cert error " << LL_ENDL;
- return 0;
- }
- return 1;
-}
-
LLSD LLCredential::getLoginParams()
{
LLSD result = LLSD::emptyMap();
diff --git a/indra/newview/llsecapi.h b/indra/newview/llsecapi.h
index c01d318f56..6fe3ee31cf 100755
--- a/indra/newview/llsecapi.h
+++ b/indra/newview/llsecapi.h
@@ -489,7 +489,4 @@ void registerSecHandler(const std::string& handler_type,
extern LLPointer<LLSecAPIHandler> gSecAPIHandler;
-int secapiSSLCertVerifyCallback(X509_STORE_CTX *ctx, void *param);
-
-
#endif // LL_SECAPI_H
diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp
index 4fafbf917b..55bcb3dc65 100755
--- a/indra/newview/llselectmgr.cpp
+++ b/indra/newview/llselectmgr.cpp
@@ -2127,7 +2127,7 @@ void LLSelectMgr::selectionRemoveMaterial()
{
LL_DEBUGS("Materials") << "Removing material from object " << object->getID() << " face " << face << LL_ENDL;
LLMaterialMgr::getInstance()->remove(object->getID(),face);
- object->setTEMaterialParams(face, NULL);
+ object->setTEMaterialParams(face, NULL, FALSE);
}
return true;
}
@@ -4950,6 +4950,7 @@ void LLSelectMgr::sendListToRegions(const std::string& message_name,
ESendType send_type)
{
LLSelectNode* node;
+ LLSelectNode* linkset_root = NULL;
LLViewerRegion* last_region;
LLViewerRegion* current_region;
@@ -4957,6 +4958,8 @@ void LLSelectMgr::sendListToRegions(const std::string& message_name,
S32 packets_sent = 0;
S32 objects_in_this_packet = 0;
+ bool link_operation = message_name == "ObjectLink";
+
//clear update override data (allow next update through)
struct f : public LLSelectedNodeFunctor
{
@@ -5065,6 +5068,12 @@ void LLSelectMgr::sendListToRegions(const std::string& message_name,
&& (! gMessageSystem->isSendFull(NULL))
&& (objects_in_this_packet < MAX_OBJECTS_PER_PACKET))
{
+ if (link_operation && linkset_root == NULL)
+ {
+ // linksets over 254 will be split into multiple messages,
+ // but we need to provide same root for all messages or we will get separate linksets
+ linkset_root = node;
+ }
// add another instance of the body of the data
(*pack_body)(node, user_data);
// do any related logging
@@ -5093,6 +5102,22 @@ void LLSelectMgr::sendListToRegions(const std::string& message_name,
gMessageSystem->newMessage(message_name.c_str());
(*pack_header)(user_data);
+ if (linkset_root != NULL)
+ {
+ if (current_region != last_region)
+ {
+ // root should be in one region with the child, reset it
+ linkset_root = NULL;
+ }
+ else
+ {
+ // add root instance into new message
+ (*pack_body)(linkset_root, user_data);
+ ++objects_sent;
+ ++objects_in_this_packet;
+ }
+ }
+
// don't move to the next object, we still need to add the
// body data.
}
diff --git a/indra/newview/llsidepanelinventory.cpp b/indra/newview/llsidepanelinventory.cpp
index 0e23e2ad10..67ac875428 100755
--- a/indra/newview/llsidepanelinventory.cpp
+++ b/indra/newview/llsidepanelinventory.cpp
@@ -37,7 +37,6 @@
#include "llfloatersidepanelcontainer.h"
#include "llfoldertype.h"
#include "llfolderview.h"
-#include "llhttpclient.h"
#include "llinventorybridge.h"
#include "llinventoryfunctions.h"
#include "llinventorymodel.h"
diff --git a/indra/newview/llsidepaneliteminfo.cpp b/indra/newview/llsidepaneliteminfo.cpp
index a7cfc173af..12cbff888d 100755
--- a/indra/newview/llsidepaneliteminfo.cpp
+++ b/indra/newview/llsidepaneliteminfo.cpp
@@ -44,7 +44,6 @@
#include "llviewercontrol.h"
#include "llviewerinventory.h"
#include "llviewerobjectlist.h"
-#include "llexperienceassociationresponder.h"
#include "llexperiencecache.h"
#include "lltrans.h"
@@ -328,7 +327,9 @@ void LLSidepanelItemInfo::refreshFromItem(LLViewerInventoryItem* item)
LLTextBox* tb = getChild<LLTextBox>("LabelItemExperience");
tb->setText(getString("loading_experience"));
tb->setVisible(TRUE);
- ExperienceAssociationResponder::fetchAssociatedExperience(item->getParentUUID(), item->getUUID(), boost::bind(&LLSidepanelItemInfo::setAssociatedExperience, getDerivedHandle<LLSidepanelItemInfo>(), _1));
+
+ LLExperienceCache::instance().fetchAssociatedExperience(item->getParentUUID(), item->getUUID(),
+ boost::bind(&LLSidepanelItemInfo::setAssociatedExperience, getDerivedHandle<LLSidepanelItemInfo>(), _1));
}
//////////////////////
diff --git a/indra/newview/llsidepaneltaskinfo.cpp b/indra/newview/llsidepaneltaskinfo.cpp
index 17ecfab4fb..2548d730f0 100755
--- a/indra/newview/llsidepaneltaskinfo.cpp
+++ b/indra/newview/llsidepaneltaskinfo.cpp
@@ -370,18 +370,25 @@ void LLSidepanelTaskInfo::refresh()
// Update creator text field
getChildView("Creator:")->setEnabled(TRUE);
+
std::string creator_name;
- LLSelectMgr::getInstance()->selectGetCreator(mCreatorID, creator_name);
+ LLUUID creator_id;
+ LLSelectMgr::getInstance()->selectGetCreator(creator_id, creator_name);
- getChild<LLUICtrl>("Creator Name")->setValue(creator_name);
- getChildView("Creator Name")->setEnabled(TRUE);
+ if(creator_id != mCreatorID )
+ {
+ mDACreatorName->setValue(creator_name);
+ mCreatorID = creator_id;
+ }
+ mDACreatorName->setEnabled(TRUE);
// Update owner text field
getChildView("Owner:")->setEnabled(TRUE);
std::string owner_name;
- const BOOL owners_identical = LLSelectMgr::getInstance()->selectGetOwner(mOwnerID, owner_name);
- if (mOwnerID.isNull())
+ LLUUID owner_id;
+ const BOOL owners_identical = LLSelectMgr::getInstance()->selectGetOwner(owner_id, owner_name);
+ if (owner_id.isNull())
{
if (LLSelectMgr::getInstance()->selectIsGroupOwned())
{
@@ -402,7 +409,12 @@ void LLSidepanelTaskInfo::refresh()
}
}
}
- getChild<LLUICtrl>("Owner Name")->setValue(owner_name);
+
+ if(owner_id.isNull() || (owner_id != mOwnerID))
+ {
+ mDAOwnerName->setValue(owner_name);
+ mOwnerID = owner_id;
+ }
getChildView("Owner Name")->setEnabled(TRUE);
// update group text field
diff --git a/indra/newview/llslurl.cpp b/indra/newview/llslurl.cpp
index 728fc69723..a8e012bfa1 100755
--- a/indra/newview/llslurl.cpp
+++ b/indra/newview/llslurl.cpp
@@ -271,7 +271,14 @@ LLSLURL::LLSLURL(const std::string& slurl)
// at this point, head of the path array should be [ <region>, <x>, <y>, <z> ] where x, y and z
// are collectively optional
// are optional
+
mRegion = LLURI::unescape(path_array[0].asString());
+
+ if(LLStringUtil::containsNonprintable(mRegion))
+ {
+ LLStringUtil::stripNonprintable(mRegion);
+ }
+
path_array.erase(0);
// parse the x, y, and optionally z
diff --git a/indra/newview/llsnapshotlivepreview.cpp b/indra/newview/llsnapshotlivepreview.cpp
index 8fb3340db0..b9e2e11bfa 100644
--- a/indra/newview/llsnapshotlivepreview.cpp
+++ b/indra/newview/llsnapshotlivepreview.cpp
@@ -195,7 +195,8 @@ void LLSnapshotLivePreview::updateSnapshot(BOOL new_snapshot, BOOL new_thumbnail
// Stop shining animation.
mShineAnimTimer.stop();
mSnapshotDelayTimer.start();
- mSnapshotDelayTimer.setTimerExpirySec(delay);
+ mSnapshotDelayTimer.resetWithExpiry(delay);
+
mPosTakenGlobal = gAgentCamera.getCameraPositionGlobal();
@@ -670,10 +671,27 @@ BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview )
return FALSE;
}
- // If we're in freeze-frame mode and camera has moved, update snapshot.
+ if (previewp->mSnapshotDelayTimer.getStarted()) // Wait for a snapshot delay timer
+ {
+ if (!previewp->mSnapshotDelayTimer.hasExpired())
+ {
+ return FALSE;
+ }
+ previewp->mSnapshotDelayTimer.stop();
+ }
+
+ if (LLToolCamera::getInstance()->hasMouseCapture()) // Hide full-screen preview while camming, either don't take snapshots while ALT-zoom active
+ {
+ previewp->setVisible(FALSE);
+ return FALSE;
+ }
+
+ // If we're in freeze-frame and/or auto update mode and camera has moved, update snapshot.
LLVector3 new_camera_pos = LLViewerCamera::getInstance()->getOrigin();
LLQuaternion new_camera_rot = LLViewerCamera::getInstance()->getQuaternion();
- if (previewp->mForceUpdateSnapshot || (gSavedSettings.getBOOL("FreezeTime") && previewp->mAllowFullScreenPreview &&
+ if (previewp->mForceUpdateSnapshot ||
+ (((gSavedSettings.getBOOL("AutoSnapshot") && LLView::isAvailable(previewp->mViewContainer)) ||
+ (gSavedSettings.getBOOL("FreezeTime") && previewp->mAllowFullScreenPreview)) &&
(new_camera_pos != previewp->mCameraPos || dot(new_camera_rot, previewp->mCameraRot) < 0.995f)))
{
previewp->mCameraPos = new_camera_pos;
@@ -688,11 +706,7 @@ BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview )
previewp->mForceUpdateSnapshot = FALSE;
}
- // see if it's time yet to snap the shot and bomb out otherwise.
- previewp->mSnapshotActive =
- (previewp->mSnapshotDelayTimer.getStarted() && previewp->mSnapshotDelayTimer.hasExpired())
- && !LLToolCamera::getInstance()->hasMouseCapture(); // don't take snapshots while ALT-zoom active
- if (!previewp->mSnapshotActive && previewp->getSnapshotUpToDate() && previewp->getThumbnailUpToDate())
+ if (previewp->getSnapshotUpToDate() && previewp->getThumbnailUpToDate())
{
return FALSE;
}
@@ -706,6 +720,8 @@ BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview )
previewp->mPreviewImage = new LLImageRaw;
}
+ previewp->mSnapshotActive = TRUE;
+
previewp->setVisible(FALSE);
previewp->setEnabled(FALSE);
@@ -734,40 +750,9 @@ BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview )
// Full size preview is set: get the decoded image result and save it for animation
if (gSavedSettings.getBOOL("UseFreezeFrame") && previewp->mAllowFullScreenPreview)
{
- // Get the decoded version of the formatted image
- previewp->getEncodedImage();
-
- // We need to scale that a bit for display...
- LLPointer<LLImageRaw> scaled = new LLImageRaw(
- previewp->mPreviewImageEncoded->getData(),
- previewp->mPreviewImageEncoded->getWidth(),
- previewp->mPreviewImageEncoded->getHeight(),
- previewp->mPreviewImageEncoded->getComponents());
-
- if (!scaled->isBufferInvalid())
- {
- // leave original image dimensions, just scale up texture buffer
- if (previewp->mPreviewImageEncoded->getWidth() > 1024 || previewp->mPreviewImageEncoded->getHeight() > 1024)
- {
- // go ahead and shrink image to appropriate power of 2 for display
- scaled->biasedScaleToPowerOfTwo(1024);
- previewp->setImageScaled(TRUE);
- }
- else
- {
- // expand image but keep original image data intact
- scaled->expandToPowerOfTwo(1024, FALSE);
- }
-
- previewp->mViewerImage[previewp->mCurImageIndex] = LLViewerTextureManager::getLocalTexture(scaled.get(), FALSE);
- LLPointer<LLViewerTexture> curr_preview_image = previewp->mViewerImage[previewp->mCurImageIndex];
- gGL.getTexUnit(0)->bind(curr_preview_image);
- curr_preview_image->setFilteringOption(previewp->getSnapshotType() == SNAPSHOT_TEXTURE ? LLTexUnit::TFO_ANISOTROPIC : LLTexUnit::TFO_POINT);
- curr_preview_image->setAddressMode(LLTexUnit::TAM_CLAMP);
-
- previewp->mShineCountdown = 4; // wait a few frames to avoid animation glitch due to readback this frame
- }
+ previewp->prepareFreezeFrame();
}
+
// The snapshot is updated now...
previewp->mSnapshotUpToDate = TRUE;
@@ -777,7 +762,6 @@ BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview )
}
previewp->getWindow()->decBusyCount();
previewp->setVisible(gSavedSettings.getBOOL("UseFreezeFrame") && previewp->mAllowFullScreenPreview); // only show fullscreen preview when in freeze frame mode
- previewp->mSnapshotDelayTimer.stop();
previewp->mSnapshotActive = FALSE;
LL_DEBUGS() << "done creating snapshot" << LL_ENDL;
}
@@ -796,6 +780,47 @@ BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview )
return TRUE;
}
+void LLSnapshotLivePreview::prepareFreezeFrame()
+{
+ // Get the decoded version of the formatted image
+ getEncodedImage();
+
+ // We need to scale that a bit for display...
+ LLPointer<LLImageRaw> scaled = new LLImageRaw(
+ mPreviewImageEncoded->getData(),
+ mPreviewImageEncoded->getWidth(),
+ mPreviewImageEncoded->getHeight(),
+ mPreviewImageEncoded->getComponents());
+
+ if (!scaled->isBufferInvalid())
+ {
+ // leave original image dimensions, just scale up texture buffer
+ if (mPreviewImageEncoded->getWidth() > 1024 || mPreviewImageEncoded->getHeight() > 1024)
+ {
+ // go ahead and shrink image to appropriate power of 2 for display
+ scaled->biasedScaleToPowerOfTwo(1024);
+ setImageScaled(TRUE);
+ }
+ else
+ {
+ // expand image but keep original image data intact
+ scaled->expandToPowerOfTwo(1024, FALSE);
+ }
+
+ mViewerImage[mCurImageIndex] = LLViewerTextureManager::getLocalTexture(scaled.get(), FALSE);
+ LLPointer<LLViewerTexture> curr_preview_image = mViewerImage[mCurImageIndex];
+ gGL.getTexUnit(0)->bind(curr_preview_image);
+ curr_preview_image->setFilteringOption(getSnapshotType() == SNAPSHOT_TEXTURE ? LLTexUnit::TFO_ANISOTROPIC : LLTexUnit::TFO_POINT);
+ curr_preview_image->setAddressMode(LLTexUnit::TAM_CLAMP);
+
+
+ if (gSavedSettings.getBOOL("UseFreezeFrame") && mAllowFullScreenPreview)
+ {
+ mShineCountdown = 4; // wait a few frames to avoid animation glitch due to readback this frame
+ }
+ }
+}
+
S32 LLSnapshotLivePreview::getEncodedImageWidth() const
{
S32 width = getWidth();
diff --git a/indra/newview/llsnapshotlivepreview.h b/indra/newview/llsnapshotlivepreview.h
index fed33bf37c..57e5d83f8e 100644
--- a/indra/newview/llsnapshotlivepreview.h
+++ b/indra/newview/llsnapshotlivepreview.h
@@ -119,7 +119,7 @@ public:
void generateThumbnailImage(BOOL force_update = FALSE) ;
void resetThumbnailImage() { mThumbnailImage = NULL ; }
void drawPreviewRect(S32 offset_x, S32 offset_y) ;
-
+ void prepareFreezeFrame();
LLViewerTexture* getBigThumbnailImage();
S32 getBigThumbnailWidth() const { return mBigThumbnailWidth ; }
diff --git a/indra/newview/llspeakers.cpp b/indra/newview/llspeakers.cpp
index 3b060d8343..e7971028bf 100755
--- a/indra/newview/llspeakers.cpp
+++ b/indra/newview/llspeakers.cpp
@@ -504,21 +504,8 @@ void LLSpeakerMgr::updateSpeakerList()
// For groups, we need to hit the group manager.
// Note: The session uuid and the group uuid are actually one and the same. If that was to change, this will fail.
LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(session_id);
- F32 large_group_delay = 0.f;
- if (gdatap)
- {
- //This is a viewer-side bandaid for maint-4414 it does not fix the core issue.
- large_group_delay = (F32)(gdatap->mMemberCount / 5000);
- }
-
- const F32 load_group_timeout = gSavedSettings.getF32("ChatLoadGroupTimeout") + large_group_delay;
-
- if (!gdatap && (mGetListTime.getElapsedTimeF32() >= load_group_timeout))
- {
- // Request the data the first time around
- LLGroupMgr::getInstance()->sendCapGroupMembersRequest(session_id);
- }
- else if (gdatap && gdatap->isMemberDataComplete() && !gdatap->mMembers.empty())
+
+ if (gdatap && gdatap->isMemberDataComplete() && !gdatap->mMembers.empty())
{
// Add group members when we get the complete list (note: can take a while before we get that list)
LLGroupMgrGroupData::member_list_t::iterator member_it = gdatap->mMembers.begin();
@@ -881,7 +868,7 @@ void LLIMSpeakerMgr::moderationActionCoro(std::string url, LLSD action)
LLUUID sessionId = action["session-id"];
- LLSD result = httpAdapter->postAndYield(httpRequest, url, action, httpOpts);
+ LLSD result = httpAdapter->postAndSuspend(httpRequest, url, action, httpOpts);
LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index 361cc6c48b..e97b73763b 100755
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -46,7 +46,6 @@
#include "llaudioengine_openal.h"
#endif
-#include "llares.h"
#include "llavatarnamecache.h"
#include "llexperiencecache.h"
#include "lllandmark.h"
@@ -112,7 +111,6 @@
#include "llgroupmgr.h"
#include "llhudeffecttrail.h"
#include "llhudmanager.h"
-#include "llhttpclient.h"
#include "llimagebmp.h"
#include "llinventorybridge.h"
#include "llinventorymodel.h"
@@ -406,9 +404,7 @@ bool idle_startup()
gSavedSettings.setS32("LastFeatureVersion", LLFeatureManager::getInstance()->getVersion());
gSavedSettings.setString("LastGPUString", thisGPU);
- // load dynamic GPU/feature tables from website (S3)
- LLFeatureManager::getInstance()->fetchHTTPTables();
-
+
std::string xml_file = LLUI::locateSkin("xui_version.xml");
LLXMLNodePtr root;
bool xml_ok = false;
@@ -445,13 +441,6 @@ bool idle_startup()
// Load the throttle settings
gViewerThrottle.load();
- if (ll_init_ares() == NULL || !gAres->isInitialized())
- {
- std::string diagnostic = "Could not start address resolution system";
- LL_WARNS("AppInit") << diagnostic << LL_ENDL;
- LLAppViewer::instance()->earlyExit("LoginFailedNoNetwork", LLSD().with("DIAGNOSTIC", diagnostic));
- }
-
//
// Initialize messaging system
//
@@ -737,12 +726,9 @@ bool idle_startup()
if (gLoginMenuBarView == NULL)
{
LL_DEBUGS("AppInit") << "initializing menu bar" << LL_ENDL;
- display_startup();
initialize_edit_menu();
initialize_spellcheck_menu();
- display_startup();
init_menus();
- display_startup();
}
if (show_connect_box)
@@ -754,23 +740,17 @@ bool idle_startup()
if (gUserCredential.isNull())
{
LL_DEBUGS("AppInit") << "loading credentials from gLoginHandler" << LL_ENDL;
- display_startup();
gUserCredential = gLoginHandler.initializeLoginInfo();
- display_startup();
}
// Make sure the process dialog doesn't hide things
- display_startup();
gViewerWindow->setShowProgress(FALSE);
- display_startup();
// Show the login dialog
login_show();
- display_startup();
// connect dialog is already shown, so fill in the names
if (gUserCredential.notNull())
{
LLPanelLogin::setFields( gUserCredential, gRememberPassword);
}
- display_startup();
LLPanelLogin::giveFocus();
// MAINT-3231 Show first run dialog only for Desura viewer
@@ -796,22 +776,15 @@ bool idle_startup()
LLStartUp::setStartupState( STATE_LOGIN_CLEANUP );
}
- display_startup();
gViewerWindow->setNormalControlsVisible( FALSE );
- display_startup();
gLoginMenuBarView->setVisible( TRUE );
- display_startup();
gLoginMenuBarView->setEnabled( TRUE );
- display_startup();
show_debug_menus();
- display_startup();
// Hide the splash screen
LLSplashScreen::hide();
- display_startup();
// Push our window frontmost
gViewerWindow->getWindow()->show();
- display_startup();
// DEV-16927. The following code removes errant keystrokes that happen while the window is being
// first made visible.
@@ -819,9 +792,9 @@ bool idle_startup()
MSG msg;
while( PeekMessage( &msg, /*All hWnds owned by this thread */ NULL, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE ) )
{ }
- display_startup();
#endif
- timeout.reset();
+ display_startup();
+ timeout.reset();
return FALSE;
}
@@ -2760,8 +2733,6 @@ void reset_login()
gAgent.cleanup();
LLWorld::getInstance()->destroyClass();
- LLStartUp::setStartupState( STATE_LOGIN_SHOW );
-
if ( gViewerWindow )
{ // Hide menus and normal buttons
gViewerWindow->setNormalControlsVisible( FALSE );
@@ -2771,6 +2742,7 @@ void reset_login()
// Hide any other stuff
LLFloaterReg::hideVisibleInstances();
+ LLStartUp::setStartupState( STATE_BROWSER_INIT );
}
//---------------------------------------------------------------------------
@@ -2822,7 +2794,7 @@ void LLStartUp::initNameCache()
void LLStartUp::initExperiences()
{
// Should trigger loading the cache.
- LLExperienceCache::getInstance()->setCapabilityQuery(
+ LLExperienceCache::instance().setCapabilityQuery(
boost::bind(&LLAgent::getRegionCapability, &gAgent, _1));
LLExperienceLog::instance().initialize();
@@ -3223,6 +3195,23 @@ bool process_login_success_response()
LLStringUtil::trim(gDisplayName);
}
}
+ std::string first_name;
+ if(response.has("first_name"))
+ {
+ first_name = response["first_name"].asString();
+ LLStringUtil::replaceChar(first_name, '"', ' ');
+ LLStringUtil::trim(first_name);
+ gAgentUsername = first_name;
+ }
+
+ if(response.has("last_name") && !gAgentUsername.empty() && (gAgentUsername != "Resident"))
+ {
+ std::string last_name = response["last_name"].asString();
+ LLStringUtil::replaceChar(last_name, '"', ' ');
+ LLStringUtil::trim(last_name);
+ gAgentUsername = gAgentUsername + " " + last_name;
+ }
+
if(gDisplayName.empty())
{
if(response.has("first_name"))
@@ -3243,6 +3232,7 @@ bool process_login_success_response()
gDisplayName += text;
}
}
+
if(gDisplayName.empty())
{
gDisplayName.assign(gUserCredential->asString());
diff --git a/indra/newview/llsyntaxid.cpp b/indra/newview/llsyntaxid.cpp
index 7f286044d6..9e54c521b5 100644
--- a/indra/newview/llsyntaxid.cpp
+++ b/indra/newview/llsyntaxid.cpp
@@ -129,7 +129,7 @@ void LLSyntaxIdLSL::fetchKeywordsFileCoro(std::string url, std::string fileSpec)
return;
}
- LLSD result = httpAdapter->getAndYield(httpRequest, url);
+ LLSD result = httpAdapter->getAndSuspend(httpRequest, url);
LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
diff --git a/indra/newview/llsyswellwindow.cpp b/indra/newview/llsyswellwindow.cpp
index 8babb874f8..8f64cff47c 100755
--- a/indra/newview/llsyswellwindow.cpp
+++ b/indra/newview/llsyswellwindow.cpp
@@ -296,158 +296,6 @@ BOOL LLIMWellWindow::ObjectRowPanel::handleRightMouseDown(S32 x, S32 y, MASK mas
}
/************************************************************************/
-/* LLNotificationWellWindow implementation */
-/************************************************************************/
-
-//////////////////////////////////////////////////////////////////////////
-// PUBLIC METHODS
-LLNotificationWellWindow::WellNotificationChannel::WellNotificationChannel(LLNotificationWellWindow* well_window)
-: LLNotificationChannel(LLNotificationChannel::Params().name(well_window->getPathname())),
- mWellWindow(well_window)
-{
- connectToChannel("Notifications");
- connectToChannel("Group Notifications");
- connectToChannel("Offer");
-}
-
-LLNotificationWellWindow::LLNotificationWellWindow(const LLSD& key)
-: LLSysWellWindow(key)
-{
- mNotificationUpdates.reset(new WellNotificationChannel(this));
-}
-
-// static
-LLNotificationWellWindow* LLNotificationWellWindow::getInstance(const LLSD& key /*= LLSD()*/)
-{
- return LLFloaterReg::getTypedInstance<LLNotificationWellWindow>("notification_well_window", key);
-}
-
-// virtual
-BOOL LLNotificationWellWindow::postBuild()
-{
- BOOL rv = LLSysWellWindow::postBuild();
- setTitle(getString("title_notification_well_window"));
- return rv;
-}
-
-// virtual
-void LLNotificationWellWindow::setVisible(BOOL visible)
-{
- if (visible)
- {
- // when Notification channel is cleared, storable toasts will be added into the list.
- clearScreenChannels();
- }
-
- LLSysWellWindow::setVisible(visible);
-}
-
-//---------------------------------------------------------------------------------
-void LLNotificationWellWindow::addItem(LLSysWellItem::Params p)
-{
- LLSD value = p.notification_id;
- // do not add clones
- if( mMessageList->getItemByValue(value))
- return;
-
- LLSysWellItem* new_item = new LLSysWellItem(p);
- if (mMessageList->addItem(new_item, value, ADD_TOP))
- {
- mSysWellChiclet->updateWidget(isWindowEmpty());
- reshapeWindow();
- new_item->setOnItemCloseCallback(boost::bind(&LLNotificationWellWindow::onItemClose, this, _1));
- new_item->setOnItemClickCallback(boost::bind(&LLNotificationWellWindow::onItemClick, this, _1));
- }
- else
- {
- LL_WARNS() << "Unable to add Notification into the list, notification ID: " << p.notification_id
- << ", title: " << p.title
- << LL_ENDL;
-
- new_item->die();
- }
-}
-
-void LLNotificationWellWindow::closeAll()
-{
- // Need to clear notification channel, to add storable toasts into the list.
- clearScreenChannels();
- std::vector<LLPanel*> items;
- mMessageList->getItems(items);
- for (std::vector<LLPanel*>::iterator
- iter = items.begin(),
- iter_end = items.end();
- iter != iter_end; ++iter)
- {
- LLSysWellItem* sys_well_item = dynamic_cast<LLSysWellItem*>(*iter);
- if (sys_well_item)
- onItemClose(sys_well_item);
- }
-}
-
-//////////////////////////////////////////////////////////////////////////
-// PRIVATE METHODS
-void LLNotificationWellWindow::initChannel()
-{
- LLSysWellWindow::initChannel();
- if(mChannel)
- {
- mChannel->addOnStoreToastCallback(boost::bind(&LLNotificationWellWindow::onStoreToast, this, _1, _2));
- }
-}
-
-void LLNotificationWellWindow::clearScreenChannels()
-{
- // 1 - remove StartUp toast and channel if present
- if(!LLNotificationsUI::LLScreenChannel::getStartUpToastShown())
- {
- LLNotificationsUI::LLChannelManager::getInstance()->onStartUpToastClose();
- }
-
- // 2 - remove toasts in Notification channel
- if(mChannel)
- {
- mChannel->removeAndStoreAllStorableToasts();
- }
-}
-
-void LLNotificationWellWindow::onStoreToast(LLPanel* info_panel, LLUUID id)
-{
- LLSysWellItem::Params p;
- p.notification_id = id;
- p.title = static_cast<LLToastPanel*>(info_panel)->getTitle();
- addItem(p);
-}
-
-void LLNotificationWellWindow::onItemClick(LLSysWellItem* item)
-{
- LLUUID id = item->getID();
- LLFloaterReg::showInstance("inspect_toast", id);
-}
-
-void LLNotificationWellWindow::onItemClose(LLSysWellItem* item)
-{
- LLUUID id = item->getID();
-
- if(mChannel)
- {
- // removeItemByID() is invoked from killToastByNotificationID() and item will removed;
- mChannel->killToastByNotificationID(id);
- }
- else
- {
- // removeItemByID() should be called one time for each item to remove it from notification well
- removeItemByID(id);
- }
-
-}
-
-void LLNotificationWellWindow::onAdd( LLNotificationPtr notify )
-{
- removeItemByID(notify->getID());
-}
-
-/************************************************************************/
/* LLIMWellWindow implementation */
/************************************************************************/
diff --git a/indra/newview/llsyswellwindow.h b/indra/newview/llsyswellwindow.h
index 71b41476f5..d02293e6ff 100755
--- a/indra/newview/llsyswellwindow.h
+++ b/indra/newview/llsyswellwindow.h
@@ -96,57 +96,6 @@ protected:
};
/**
- * Class intended to manage incoming notifications.
- *
- * It contains a list of notifications that have not been responded to.
- */
-class LLNotificationWellWindow : public LLSysWellWindow
-{
-public:
- LLNotificationWellWindow(const LLSD& key);
- static LLNotificationWellWindow* getInstance(const LLSD& key = LLSD());
-
- /*virtual*/ BOOL postBuild();
- /*virtual*/ void setVisible(BOOL visible);
- /*virtual*/ void onAdd(LLNotificationPtr notify);
- // Operating with items
- void addItem(LLSysWellItem::Params p);
-
- // Closes all notifications and removes them from the Notification Well
- void closeAll();
-
-protected:
- struct WellNotificationChannel : public LLNotificationChannel
- {
- WellNotificationChannel(LLNotificationWellWindow*);
- void onDelete(LLNotificationPtr notify)
- {
- mWellWindow->removeItemByID(notify->getID());
- }
-
- LLNotificationWellWindow* mWellWindow;
- };
-
- LLNotificationChannelPtr mNotificationUpdates;
- /*virtual*/ const std::string& getAnchorViewName() { return NOTIFICATION_WELL_ANCHOR_NAME; }
-
-private:
- // init Window's channel
- void initChannel();
- void clearScreenChannels();
-
- void onStoreToast(LLPanel* info_panel, LLUUID id);
-
- // Handlers
- void onItemClick(LLSysWellItem* item);
- void onItemClose(LLSysWellItem* item);
-
- // ID of a toast loaded by user (by clicking notification well item)
- LLUUID mLoadedToastId;
-
-};
-
-/**
* Class intended to manage incoming messages in IM chats.
*
* It contains a list list of all active IM sessions.
diff --git a/indra/newview/lltexturecache.cpp b/indra/newview/lltexturecache.cpp
index ef852bc905..bcdf8360ed 100755
--- a/indra/newview/lltexturecache.cpp
+++ b/indra/newview/lltexturecache.cpp
@@ -1544,17 +1544,20 @@ void LLTextureCache::purgeAllTextures(bool purge_directories)
{
std::string dirname = mTexturesDirName + delem + subdirs[i];
LL_INFOS() << "Deleting files in directory: " << dirname << LL_ENDL;
- gDirUtilp->deleteFilesInDir(dirname, mask);
if (purge_directories)
{
- LLFile::rmdir(dirname);
+ gDirUtilp->deleteDirAndContents(dirname);
+ }
+ else
+ {
+ gDirUtilp->deleteFilesInDir(dirname, mask);
}
}
if (purge_directories)
{
gDirUtilp->deleteFilesInDir(mTexturesDirName, mask);
LLFile::rmdir(mTexturesDirName);
- }
+ }
}
mHeaderIDMap.clear();
mTexturesSizeMap.clear();
diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp
index 30d90431ea..1f966dc76f 100755
--- a/indra/newview/lltexturefetch.cpp
+++ b/indra/newview/lltexturefetch.cpp
@@ -254,6 +254,20 @@ static const S32 HTTP_NONPIPE_REQUESTS_LOW_WATER = 20;
static const S32 HTTP_REQUESTS_RANGE_END_MAX = 20000000;
//////////////////////////////////////////////////////////////////////////////
+namespace
+{
+ // The NoOpDeletor is used when passing certain objects (the LLTextureFetchWorker and
+ // the LLTextureFetchDebugger) in a smart pointer below for passage into
+ // the LLCore::Http libararies. When the smart pointer is destroyed, no
+ // action will be taken since we do not in these cases want the object to
+ // be destroyed at the end of the call.
+ //
+ // *NOTE$: Yes! It is "Deletor"
+ // http://english.stackexchange.com/questions/4733/what-s-the-rule-for-adding-er-vs-or-when-nouning-a-verb
+ // "delete" derives from Latin "deletus"
+ void NoOpDeletor(LLCore::HttpHandler *)
+ { /*NoOp*/ }
+}
static const char* e_state_name[] =
{
@@ -806,16 +820,10 @@ public:
* ownership of the copy and disposes of it
* when done.
*/
- TFReqSendMetrics(const std::string & caps_url,
- const LLUUID & session_id,
- const LLUUID & agent_id,
- LLViewerAssetStats * main_stats)
- : LLTextureFetch::TFRequest(),
- mCapsURL(caps_url),
- mSessionID(session_id),
- mAgentID(agent_id),
- mMainStats(main_stats)
- {}
+ TFReqSendMetrics(const std::string & caps_url,
+ const LLUUID & session_id,
+ const LLUUID & agent_id,
+ LLViewerAssetStats * main_stats);
TFReqSendMetrics & operator=(const TFReqSendMetrics &); // Not defined
virtual ~TFReqSendMetrics();
@@ -827,6 +835,9 @@ public:
const LLUUID mSessionID;
const LLUUID mAgentID;
LLViewerAssetStats * mMainStats;
+
+private:
+ LLCore::HttpHandler::ptr_t mHandler;
};
/*
@@ -965,7 +976,7 @@ LLTextureFetchWorker::~LLTextureFetchWorker()
if (mHttpActive)
{
// Issue a cancel on a live request...
- mFetcher->getHttpRequest().requestCancel(mHttpHandle, NULL);
+ mFetcher->getHttpRequest().requestCancel(mHttpHandle, LLCore::HttpHandler::ptr_t());
}
if (mCacheReadHandle != LLTextureCache::nullHandle() && mFetcher->mTextureCache)
{
@@ -1569,7 +1580,7 @@ bool LLTextureFetchWorker::doWork(S32 param)
mUrl,
options,
mFetcher->mHttpHeaders,
- this);
+ LLCore::HttpHandler::ptr_t(this, &NoOpDeletor));
}
else
{
@@ -1582,7 +1593,7 @@ bool LLTextureFetchWorker::doWork(S32 param)
: mRequestedSize,
options,
mFetcher->mHttpHeaders,
- this);
+ LLCore::HttpHandler::ptr_t(this, &NoOpDeletor));
}
if (LLCORE_HTTP_HANDLE_INVALID == mHttpHandle)
{
@@ -3937,9 +3948,6 @@ public:
}
}; // end class AssetReportHandler
-AssetReportHandler stats_handler;
-
-
/**
* Implements the 'Set Region' command.
*
@@ -3953,6 +3961,18 @@ TFReqSetRegion::doWork(LLTextureFetch *)
return true;
}
+TFReqSendMetrics::TFReqSendMetrics(const std::string & caps_url,
+ const LLUUID & session_id,
+ const LLUUID & agent_id,
+ LLViewerAssetStats * main_stats):
+ LLTextureFetch::TFRequest(),
+ mCapsURL(caps_url),
+ mSessionID(session_id),
+ mAgentID(agent_id),
+ mMainStats(main_stats),
+ mHandler(new AssetReportHandler)
+{}
+
TFReqSendMetrics::~TFReqSendMetrics()
{
@@ -3971,7 +3991,6 @@ bool
TFReqSendMetrics::doWork(LLTextureFetch * fetcher)
{
static const U32 report_priority(1);
- static LLCore::HttpHandler * const handler(fetcher->isQAMode() || true ? &stats_handler : NULL);
//if (! gViewerAssetStatsThread1)
// return true;
@@ -4021,7 +4040,7 @@ TFReqSendMetrics::doWork(LLTextureFetch * fetcher)
sd,
LLCore::HttpOptions::ptr_t(),
fetcher->getMetricsHeaders(),
- handler);
+ mHandler);
LLTextureFetch::svMetricsDataBreak = false;
}
else
@@ -4598,7 +4617,7 @@ S32 LLTextureFetchDebugger::fillCurlQueue()
requestedSize,
LLCore::HttpOptions::ptr_t(),
mHttpHeaders,
- this);
+ LLCore::HttpHandler::ptr_t(this, &NoOpDeletor));
if (LLCORE_HTTP_HANDLE_INVALID != handle)
{
mHandleToFetchIndex[handle] = i;
diff --git a/indra/newview/lltexturefetch.h b/indra/newview/lltexturefetch.h
index e569175e8f..50233eee5e 100755
--- a/indra/newview/lltexturefetch.h
+++ b/indra/newview/lltexturefetch.h
@@ -37,7 +37,6 @@
#include "lltextureinfo.h"
#include "llapr.h"
#include "llimageworker.h"
-#include "llcurl.h"
#include "httprequest.h"
#include "httpoptions.h"
#include "httpheaders.h"
diff --git a/indra/newview/lltexturestats.cpp b/indra/newview/lltexturestats.cpp
index ca42d710f8..8ded148e17 100755
--- a/indra/newview/lltexturestats.cpp
+++ b/indra/newview/lltexturestats.cpp
@@ -30,8 +30,8 @@
#include "llagent.h"
#include "lltexturefetch.h"
#include "lltexturestats.h"
-#include "lltexturestatsuploader.h"
#include "llviewerregion.h"
+#include "llcorehttputil.h"
void send_texture_stats_to_sim(const LLSD &texture_stats)
{
@@ -49,6 +49,16 @@ void send_texture_stats_to_sim(const LLSD &texture_stats)
std::string texture_cap_url = gAgent.getRegion()->getCapability("TextureStats");
LL_INFOS() << "uploading texture stats data to simulator" << LL_ENDL;
- LLTextureStatsUploader::uploadStatsToSimulator(texture_cap_url, texture_stats);
+
+ if (texture_cap_url != "")
+ {
+ LLCoreHttpUtil::HttpCoroutineAdapter::messageHttpPost(texture_cap_url, texture_stats,
+ "Texture statistics posted to sim.", "Error posting texture statistics to sim");
+ }
+ else
+ {
+ LL_INFOS() << "Not sending texture stats: " << texture_stats
+ << " as there is no cap url." << LL_ENDL;
+ }
}
diff --git a/indra/newview/lltoastgroupnotifypanel.cpp b/indra/newview/lltoastgroupnotifypanel.cpp
index e00b18dedb..e22f527a65 100755
--- a/indra/newview/lltoastgroupnotifypanel.cpp
+++ b/indra/newview/lltoastgroupnotifypanel.cpp
@@ -92,7 +92,7 @@ LLToastGroupNotifyPanel::LLToastGroupNotifyPanel(const LLNotificationPtr& notifi
+LLTrans::getString("UTCTimeSec")+"] ["
+LLTrans::getString("UTCTimeTimezone")+"]";
const LLDate timeStamp = notification->getDate();
- LLDate notice_date = timeStamp.notNull() ? timeStamp : LLDate::now();
+ LLDate notice_date = timeStamp.notNull() ? timeStamp : payload["received_time"].asDate();
LLSD substitution;
substitution["datetime"] = (S32) notice_date.secondsSinceEpoch();
LLStringUtil::format(timeStr, substitution);
diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp
index 81fbc471b3..05c98826d2 100755
--- a/indra/newview/lltooldraganddrop.cpp
+++ b/indra/newview/lltooldraganddrop.cpp
@@ -821,21 +821,6 @@ void LLToolDragAndDrop::dragOrDrop( S32 x, S32 y, MASK mask, BOOL drop,
if (!handled)
{
- // *TODO: Suppress the "outbox" case once "marketplace" is used everywhere for everyone
- // Disallow drag and drop to 3D from the outbox
- const LLUUID outbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false);
- if (outbox_id.notNull())
- {
- for (S32 item_index = 0; item_index < (S32)mCargoIDs.size(); item_index++)
- {
- if (gInventory.isObjectDescendentOf(mCargoIDs[item_index], outbox_id))
- {
- *acceptance = ACCEPT_NO;
- mToolTipMsg = LLTrans::getString("TooltipOutboxDragToWorld");
- return;
- }
- }
- }
// Disallow drag and drop to 3D from the marketplace
const LLUUID marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false);
if (marketplacelistings_id.notNull())
@@ -1155,8 +1140,7 @@ void LLToolDragAndDrop::dropMesh(LLViewerObject* hit_obj,
}
LLSculptParams sculpt_params;
- sculpt_params.setSculptTexture(asset_id);
- sculpt_params.setSculptType(LL_SCULPT_TYPE_MESH);
+ sculpt_params.setSculptTexture(asset_id, LL_SCULPT_TYPE_MESH);
hit_obj->setParameterEntry(LLNetworkData::PARAMS_SCULPT, sculpt_params, TRUE);
dialog_refresh_all();
diff --git a/indra/newview/lltranslate.cpp b/indra/newview/lltranslate.cpp
index c0ba0a1f39..1936e24761 100755
--- a/indra/newview/lltranslate.cpp
+++ b/indra/newview/lltranslate.cpp
@@ -35,31 +35,257 @@
#include "llui.h"
#include "llversioninfo.h"
#include "llviewercontrol.h"
-
+#include "llcoros.h"
#include "reader.h"
+#include "llcorehttputil.h"
+
+
+/**
+* Handler of an HTTP machine translation service.
+*
+* Derived classes know the service URL
+* and how to parse the translation result.
+*/
+class LLTranslationAPIHandler
+{
+public:
+ typedef std::pair<std::string, std::string> LanguagePair_t;
+
+ /**
+ * Get URL for translation of the given string.
+ *
+ * Sending HTTP GET request to the URL will initiate translation.
+ *
+ * @param[out] url Place holder for the result.
+ * @param from_lang Source language. Leave empty for auto-detection.
+ * @param to_lang Target language.
+ * @param text Text to translate.
+ */
+ virtual std::string getTranslateURL(
+ const std::string &from_lang,
+ const std::string &to_lang,
+ const std::string &text) const = 0;
+
+ /**
+ * Get URL to verify the given API key.
+ *
+ * Sending request to the URL verifies the key.
+ * Positive HTTP response (code 200) means that the key is valid.
+ *
+ * @param[out] url Place holder for the URL.
+ * @param[in] key Key to verify.
+ */
+ virtual std::string getKeyVerificationURL(
+ const std::string &key) const = 0;
+
+ /**
+ * Parse translation response.
+ *
+ * @param[in,out] status HTTP status. May be modified while parsing.
+ * @param body Response text.
+ * @param[out] translation Translated text.
+ * @param[out] detected_lang Detected source language. May be empty.
+ * @param[out] err_msg Error message (in case of error).
+ */
+ virtual bool parseResponse(
+ int& status,
+ const std::string& body,
+ std::string& translation,
+ std::string& detected_lang,
+ std::string& err_msg) const = 0;
+
+ /**
+ * @return if the handler is configured to function properly
+ */
+ virtual bool isConfigured() const = 0;
+
+ virtual void verifyKey(const std::string &key, LLTranslate::KeyVerificationResult_fn fnc) = 0;
+ virtual void translateMessage(LanguagePair_t fromTo, std::string msg, LLTranslate::TranslationSuccess_fn success, LLTranslate::TranslationFailure_fn failure);
+
+
+ virtual ~LLTranslationAPIHandler() {}
+
+ void verifyKeyCoro(LLTranslate::EService service, std::string key, LLTranslate::KeyVerificationResult_fn fnc);
+ void translateMessageCoro(LanguagePair_t fromTo, std::string msg, LLTranslate::TranslationSuccess_fn success, LLTranslate::TranslationFailure_fn failure);
+};
+
+void LLTranslationAPIHandler::translateMessage(LanguagePair_t fromTo, std::string msg, LLTranslate::TranslationSuccess_fn success, LLTranslate::TranslationFailure_fn failure)
+{
+ LLCoros::instance().launch("Translation", boost::bind(&LLTranslationAPIHandler::translateMessageCoro,
+ this, fromTo, msg, success, failure));
+
+}
+
+
+void LLTranslationAPIHandler::verifyKeyCoro(LLTranslate::EService service, std::string key, LLTranslate::KeyVerificationResult_fn fnc)
+{
+ LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+ LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+ httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("getMerchantStatusCoro", httpPolicy));
+ LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+ LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions);
+ LLCore::HttpHeaders::ptr_t httpHeaders(new LLCore::HttpHeaders);
+
+
+ std::string user_agent = llformat("%s %d.%d.%d (%d)",
+ LLVersionInfo::getChannel().c_str(),
+ LLVersionInfo::getMajor(),
+ LLVersionInfo::getMinor(),
+ LLVersionInfo::getPatch(),
+ LLVersionInfo::getBuild());
+
+ httpHeaders->append(HTTP_OUT_HEADER_ACCEPT, HTTP_CONTENT_TEXT_PLAIN);
+ httpHeaders->append(HTTP_OUT_HEADER_USER_AGENT, user_agent);
+
+ httpOpts->setFollowRedirects(true);
+
+ std::string url = this->getKeyVerificationURL(key);
+ if (url.empty())
+ {
+ LL_INFOS("Translate") << "No translation URL" << LL_ENDL;
+ return;
+ }
+ LLSD result = httpAdapter->getAndSuspend(httpRequest, url, httpOpts, httpHeaders);
+
+ LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+ LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+ bool bOk = true;
+ if (!status)
+ bOk = false;
+
+ if (!fnc.empty())
+ fnc(service, bOk);
+}
+
+void LLTranslationAPIHandler::translateMessageCoro(LanguagePair_t fromTo, std::string msg,
+ LLTranslate::TranslationSuccess_fn success, LLTranslate::TranslationFailure_fn failure)
+{
+ LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+ LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+ httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("getMerchantStatusCoro", httpPolicy));
+ LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+ LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions);
+ LLCore::HttpHeaders::ptr_t httpHeaders(new LLCore::HttpHeaders);
+
+
+ std::string user_agent = llformat("%s %d.%d.%d (%d)",
+ LLVersionInfo::getChannel().c_str(),
+ LLVersionInfo::getMajor(),
+ LLVersionInfo::getMinor(),
+ LLVersionInfo::getPatch(),
+ LLVersionInfo::getBuild());
+
+ httpHeaders->append(HTTP_OUT_HEADER_ACCEPT, HTTP_CONTENT_TEXT_PLAIN);
+ httpHeaders->append(HTTP_OUT_HEADER_USER_AGENT, user_agent);
+
+ std::string url = this->getTranslateURL(fromTo.first, fromTo.second, msg);
+ if (url.empty())
+ {
+ LL_INFOS("Translate") << "No translation URL" << LL_ENDL;
+ return;
+ }
+
+ LLSD result = httpAdapter->getRawAndSuspend(httpRequest, url, httpOpts, httpHeaders);
+
+ LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+ LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+ std::string translation, err_msg;
+ std::string detected_lang(fromTo.second);
+
+ int parseResult = status.getType();
+ const LLSD::Binary &rawBody = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS_RAW].asBinary();
+ std::string body(rawBody.begin(), rawBody.end());
+
+ if (this->parseResponse(parseResult, body, translation, detected_lang, err_msg))
+ {
+ // Fix up the response
+ LLStringUtil::replaceString(translation, "&lt;", "<");
+ LLStringUtil::replaceString(translation, "&gt;", ">");
+ LLStringUtil::replaceString(translation, "&quot;", "\"");
+ LLStringUtil::replaceString(translation, "&#39;", "'");
+ LLStringUtil::replaceString(translation, "&amp;", "&");
+ LLStringUtil::replaceString(translation, "&apos;", "'");
+
+ if (!success.empty())
+ success(translation, detected_lang);
+ }
+ else
+ {
+ if (err_msg.empty())
+ {
+ err_msg = LLTrans::getString("TranslationResponseParseError");
+ }
+
+ LL_WARNS() << "Translation request failed: " << err_msg << LL_ENDL;
+ if (!failure.empty())
+ failure(status, err_msg);
+ }
+
+
+}
+
+//=========================================================================
+/// Google Translate v2 API handler.
+class LLGoogleTranslationHandler : public LLTranslationAPIHandler
+{
+ LOG_CLASS(LLGoogleTranslationHandler);
+
+public:
+ /*virtual*/ std::string getTranslateURL(
+ const std::string &from_lang,
+ const std::string &to_lang,
+ const std::string &text) const;
+ /*virtual*/ std::string getKeyVerificationURL(
+ const std::string &key) const;
+ /*virtual*/ bool parseResponse(
+ int& status,
+ const std::string& body,
+ std::string& translation,
+ std::string& detected_lang,
+ std::string& err_msg) const;
+ /*virtual*/ bool isConfigured() const;
+
+ /*virtual*/ void verifyKey(const std::string &key, LLTranslate::KeyVerificationResult_fn fnc);
+
+private:
+ static void parseErrorResponse(
+ const Json::Value& root,
+ int& status,
+ std::string& err_msg);
+ static bool parseTranslation(
+ const Json::Value& root,
+ std::string& translation,
+ std::string& detected_lang);
+ static std::string getAPIKey();
+
+};
+
+//-------------------------------------------------------------------------
// virtual
-void LLGoogleTranslationHandler::getTranslateURL(
- std::string &url,
+std::string LLGoogleTranslationHandler::getTranslateURL(
const std::string &from_lang,
const std::string &to_lang,
const std::string &text) const
{
- url = std::string("https://www.googleapis.com/language/translate/v2?key=")
+ std::string url = std::string("https://www.googleapis.com/language/translate/v2?key=")
+ getAPIKey() + "&q=" + LLURI::escape(text) + "&target=" + to_lang;
if (!from_lang.empty())
{
url += "&source=" + from_lang;
}
+ return url;
}
// virtual
-void LLGoogleTranslationHandler::getKeyVerificationURL(
- std::string& url,
+std::string LLGoogleTranslationHandler::getKeyVerificationURL(
const std::string& key) const
{
- url = std::string("https://www.googleapis.com/language/translate/v2/languages?key=")
+ std::string url = std::string("https://www.googleapis.com/language/translate/v2/languages?key=")
+ key + "&target=en";
+ return url;
}
// virtual
@@ -154,28 +380,66 @@ std::string LLGoogleTranslationHandler::getAPIKey()
return gSavedSettings.getString("GoogleTranslateAPIKey");
}
+/*virtual*/
+void LLGoogleTranslationHandler::verifyKey(const std::string &key, LLTranslate::KeyVerificationResult_fn fnc)
+{
+ LLCoros::instance().launch("Google /Verify Key", boost::bind(&LLTranslationAPIHandler::verifyKeyCoro,
+ this, LLTranslate::SERVICE_GOOGLE, key, fnc));
+}
+
+
+//=========================================================================
+/// Microsoft Translator v2 API handler.
+class LLBingTranslationHandler : public LLTranslationAPIHandler
+{
+ LOG_CLASS(LLBingTranslationHandler);
+
+public:
+ /*virtual*/ std::string getTranslateURL(
+ const std::string &from_lang,
+ const std::string &to_lang,
+ const std::string &text) const;
+ /*virtual*/ std::string getKeyVerificationURL(
+ const std::string &key) const;
+ /*virtual*/ bool parseResponse(
+ int& status,
+ const std::string& body,
+ std::string& translation,
+ std::string& detected_lang,
+ std::string& err_msg) const;
+ /*virtual*/ bool isConfigured() const;
+
+ /*virtual*/ void verifyKey(const std::string &key, LLTranslate::KeyVerificationResult_fn fnc);
+private:
+ static std::string getAPIKey();
+ static std::string getAPILanguageCode(const std::string& lang);
+
+};
+
+//-------------------------------------------------------------------------
// virtual
-void LLBingTranslationHandler::getTranslateURL(
- std::string &url,
+std::string LLBingTranslationHandler::getTranslateURL(
const std::string &from_lang,
const std::string &to_lang,
const std::string &text) const
{
- url = std::string("http://api.microsofttranslator.com/v2/Http.svc/Translate?appId=")
+ std::string url = std::string("http://api.microsofttranslator.com/v2/Http.svc/Translate?appId=")
+ getAPIKey() + "&text=" + LLURI::escape(text) + "&to=" + getAPILanguageCode(to_lang);
if (!from_lang.empty())
{
url += "&from=" + getAPILanguageCode(from_lang);
}
+ return url;
}
+
// virtual
-void LLBingTranslationHandler::getKeyVerificationURL(
- std::string& url,
+std::string LLBingTranslationHandler::getKeyVerificationURL(
const std::string& key) const
{
- url = std::string("http://api.microsofttranslator.com/v2/Http.svc/GetLanguagesForTranslate?appId=")
+ std::string url = std::string("http://api.microsofttranslator.com/v2/Http.svc/GetLanguagesForTranslate?appId=")
+ key;
+ return url;
}
// virtual
@@ -242,96 +506,31 @@ std::string LLBingTranslationHandler::getAPILanguageCode(const std::string& lang
return lang == "zh" ? "zh-CHT" : lang; // treat Chinese as Traditional Chinese
}
-LLTranslate::TranslationReceiver::TranslationReceiver(const std::string& from_lang, const std::string& to_lang)
-: mFromLang(from_lang)
-, mToLang(to_lang)
-, mHandler(LLTranslate::getPreferredHandler())
+/*virtual*/
+void LLBingTranslationHandler::verifyKey(const std::string &key, LLTranslate::KeyVerificationResult_fn fnc)
{
+ LLCoros::instance().launch("Bing /Verify Key", boost::bind(&LLTranslationAPIHandler::verifyKeyCoro,
+ this, LLTranslate::SERVICE_BING, key, fnc));
}
-// virtual
-void LLTranslate::TranslationReceiver::completedRaw(
- const LLChannelDescriptors& channels,
- const LLIOPipe::buffer_ptr_t& buffer)
+//=========================================================================
+/*static*/
+void LLTranslate::translateMessage(const std::string &from_lang, const std::string &to_lang,
+ const std::string &mesg, TranslationSuccess_fn success, TranslationFailure_fn failure)
{
- LLBufferStream istr(channels, buffer.get());
- std::stringstream strstrm;
- strstrm << istr.rdbuf();
-
- const std::string body = strstrm.str();
- std::string translation, detected_lang, err_msg;
- int status = getStatus();
- LL_DEBUGS("Translate") << "HTTP status: " << status << " " << getReason() << LL_ENDL;
- LL_DEBUGS("Translate") << "Response body: " << body << LL_ENDL;
- if (mHandler.parseResponse(status, body, translation, detected_lang, err_msg))
- {
- // Fix up the response
- LLStringUtil::replaceString(translation, "&lt;", "<");
- LLStringUtil::replaceString(translation, "&gt;",">");
- LLStringUtil::replaceString(translation, "&quot;","\"");
- LLStringUtil::replaceString(translation, "&#39;","'");
- LLStringUtil::replaceString(translation, "&amp;","&");
- LLStringUtil::replaceString(translation, "&apos;","'");
-
- handleResponse(translation, detected_lang);
- }
- else
- {
- if (err_msg.empty())
- {
- err_msg = LLTrans::getString("TranslationResponseParseError");
- }
+ LLTranslationAPIHandler& handler = getPreferredHandler();
- LL_WARNS() << "Translation request failed: " << err_msg << LL_ENDL;
- handleFailure(status, err_msg);
- }
+ handler.translateMessage(LLTranslationAPIHandler::LanguagePair_t(from_lang, to_lang), mesg, success, failure);
}
-LLTranslate::KeyVerificationReceiver::KeyVerificationReceiver(EService service)
-: mService(service)
+/*static*/
+void LLTranslate::verifyKey(EService service, const std::string &key, KeyVerificationResult_fn fnc)
{
-}
+ LLTranslationAPIHandler& handler = getHandler(service);
-LLTranslate::EService LLTranslate::KeyVerificationReceiver::getService() const
-{
- return mService;
+ handler.verifyKey(key, fnc);
}
-// virtual
-void LLTranslate::KeyVerificationReceiver::completedRaw(
- const LLChannelDescriptors& channels,
- const LLIOPipe::buffer_ptr_t& buffer)
-{
- bool ok = (getStatus() == HTTP_OK);
- setVerificationStatus(ok);
-}
-
-//static
-void LLTranslate::translateMessage(
- TranslationReceiverPtr &receiver,
- const std::string &from_lang,
- const std::string &to_lang,
- const std::string &mesg)
-{
- std::string url;
- receiver->mHandler.getTranslateURL(url, from_lang, to_lang, mesg);
-
- LL_DEBUGS("Translate") << "Sending translation request: " << url << LL_ENDL;
- sendRequest(url, receiver);
-}
-
-// static
-void LLTranslate::verifyKey(
- KeyVerificationReceiverPtr& receiver,
- const std::string& key)
-{
- std::string url;
- const LLTranslationAPIHandler& handler = getHandler(receiver->getService());
- handler.getKeyVerificationURL(url, key);
-
- LL_DEBUGS("Translate") << "Sending key verification request: " << url << LL_ENDL;
- sendRequest(url, receiver);
-}
//static
std::string LLTranslate::getTranslateLanguage()
@@ -352,7 +551,7 @@ bool LLTranslate::isTranslationConfigured()
}
// static
-const LLTranslationAPIHandler& LLTranslate::getPreferredHandler()
+LLTranslationAPIHandler& LLTranslate::getPreferredHandler()
{
EService service = SERVICE_BING;
@@ -366,7 +565,7 @@ const LLTranslationAPIHandler& LLTranslate::getPreferredHandler()
}
// static
-const LLTranslationAPIHandler& LLTranslate::getHandler(EService service)
+LLTranslationAPIHandler& LLTranslate::getHandler(EService service)
{
static LLGoogleTranslationHandler google;
static LLBingTranslationHandler bing;
@@ -378,25 +577,3 @@ const LLTranslationAPIHandler& LLTranslate::getHandler(EService service)
return bing;
}
-
-// static
-void LLTranslate::sendRequest(const std::string& url, LLHTTPClient::ResponderPtr responder)
-{
- static const float REQUEST_TIMEOUT = 5;
- static LLSD sHeader;
-
- if (!sHeader.size())
- {
- std::string user_agent = llformat("%s %d.%d.%d (%d)",
- LLVersionInfo::getChannel().c_str(),
- LLVersionInfo::getMajor(),
- LLVersionInfo::getMinor(),
- LLVersionInfo::getPatch(),
- LLVersionInfo::getBuild());
-
- sHeader.insert(HTTP_OUT_HEADER_ACCEPT, HTTP_CONTENT_TEXT_PLAIN);
- sHeader.insert(HTTP_OUT_HEADER_USER_AGENT, user_agent);
- }
-
- LLHTTPClient::get(url, responder, sHeader, REQUEST_TIMEOUT);
-}
diff --git a/indra/newview/lltranslate.h b/indra/newview/lltranslate.h
index 972274714a..bf431cdfbb 100755
--- a/indra/newview/lltranslate.h
+++ b/indra/newview/lltranslate.h
@@ -27,136 +27,15 @@
#ifndef LL_LLTRANSLATE_H
#define LL_LLTRANSLATE_H
-#include "llhttpclient.h"
#include "llbufferstream.h"
+#include <boost/function.hpp>
namespace Json
{
class Value;
}
-/**
- * Handler of an HTTP machine translation service.
- *
- * Derived classes know the service URL
- * and how to parse the translation result.
- */
-class LLTranslationAPIHandler
-{
-public:
- /**
- * Get URL for translation of the given string.
- *
- * Sending HTTP GET request to the URL will initiate translation.
- *
- * @param[out] url Place holder for the result.
- * @param from_lang Source language. Leave empty for auto-detection.
- * @param to_lang Target language.
- * @param text Text to translate.
- */
- virtual void getTranslateURL(
- std::string &url,
- const std::string &from_lang,
- const std::string &to_lang,
- const std::string &text) const = 0;
-
- /**
- * Get URL to verify the given API key.
- *
- * Sending request to the URL verifies the key.
- * Positive HTTP response (code 200) means that the key is valid.
- *
- * @param[out] url Place holder for the URL.
- * @param[in] key Key to verify.
- */
- virtual void getKeyVerificationURL(
- std::string &url,
- const std::string &key) const = 0;
-
- /**
- * Parse translation response.
- *
- * @param[in,out] status HTTP status. May be modified while parsing.
- * @param body Response text.
- * @param[out] translation Translated text.
- * @param[out] detected_lang Detected source language. May be empty.
- * @param[out] err_msg Error message (in case of error).
- */
- virtual bool parseResponse(
- int& status,
- const std::string& body,
- std::string& translation,
- std::string& detected_lang,
- std::string& err_msg) const = 0;
-
- /**
- * @return if the handler is configured to function properly
- */
- virtual bool isConfigured() const = 0;
-
- virtual ~LLTranslationAPIHandler() {}
-};
-
-/// Google Translate v2 API handler.
-class LLGoogleTranslationHandler : public LLTranslationAPIHandler
-{
- LOG_CLASS(LLGoogleTranslationHandler);
-
-public:
- /*virtual*/ void getTranslateURL(
- std::string &url,
- const std::string &from_lang,
- const std::string &to_lang,
- const std::string &text) const;
- /*virtual*/ void getKeyVerificationURL(
- std::string &url,
- const std::string &key) const;
- /*virtual*/ bool parseResponse(
- int& status,
- const std::string& body,
- std::string& translation,
- std::string& detected_lang,
- std::string& err_msg) const;
- /*virtual*/ bool isConfigured() const;
-
-private:
- static void parseErrorResponse(
- const Json::Value& root,
- int& status,
- std::string& err_msg);
- static bool parseTranslation(
- const Json::Value& root,
- std::string& translation,
- std::string& detected_lang);
- static std::string getAPIKey();
-};
-
-/// Microsoft Translator v2 API handler.
-class LLBingTranslationHandler : public LLTranslationAPIHandler
-{
- LOG_CLASS(LLBingTranslationHandler);
-
-public:
- /*virtual*/ void getTranslateURL(
- std::string &url,
- const std::string &from_lang,
- const std::string &to_lang,
- const std::string &text) const;
- /*virtual*/ void getKeyVerificationURL(
- std::string &url,
- const std::string &key) const;
- /*virtual*/ bool parseResponse(
- int& status,
- const std::string& body,
- std::string& translation,
- std::string& detected_lang,
- std::string& err_msg) const;
- /*virtual*/ bool isConfigured() const;
-private:
- static std::string getAPIKey();
- static std::string getAPILanguageCode(const std::string& lang);
-};
-
+class LLTranslationAPIHandler;
/**
* Entry point for machine translation services.
*
@@ -180,84 +59,9 @@ public :
SERVICE_GOOGLE,
} EService;
- /**
- * Subclasses are supposed to handle translation results (e.g. show them in chat)
- */
- class TranslationReceiver: public LLHTTPClient::Responder
- {
- public:
-
- /**
- * Using mHandler, parse incoming response.
- *
- * Calls either handleResponse() or handleFailure()
- * depending on the HTTP status code and parsing success.
- *
- * @see handleResponse()
- * @see handleFailure()
- * @see mHandler
- */
- /*virtual*/ void completedRaw(
- const LLChannelDescriptors& channels,
- const LLIOPipe::buffer_ptr_t& buffer);
-
- protected:
- friend class LLTranslate;
-
- /// Remember source and target languages for subclasses to be able to filter inappropriate results.
- TranslationReceiver(const std::string& from_lang, const std::string& to_lang);
-
- /// Override point to handle successful translation.
- virtual void handleResponse(const std::string &translation, const std::string &recognized_lang) = 0;
-
- /// Override point to handle unsuccessful translation.
- virtual void handleFailure(int status, const std::string& err_msg) = 0;
-
- std::string mFromLang;
- std::string mToLang;
- const LLTranslationAPIHandler& mHandler;
- };
-
- /**
- * Subclasses are supposed to handle API key verification result.
- */
- class KeyVerificationReceiver: public LLHTTPClient::Responder
- {
- public:
- EService getService() const;
-
- protected:
- /**
- * Save the translation service the key belongs to.
- *
- * Subclasses need to know it.
- *
- * @see getService()
- */
- KeyVerificationReceiver(EService service);
-
- /**
- * Parse verification response.
- *
- * Calls setVerificationStatus() with the verification status,
- * which is true if HTTP status code is 200.
- *
- * @see setVerificationStatus()
- */
- /*virtual*/ void completedRaw(
- const LLChannelDescriptors& channels,
- const LLIOPipe::buffer_ptr_t& buffer);
-
- /**
- * Override point for subclasses to handle key verification status.
- */
- virtual void setVerificationStatus(bool ok) = 0;
-
- EService mService;
- };
-
- typedef LLPointer<TranslationReceiver> TranslationReceiverPtr;
- typedef LLPointer<KeyVerificationReceiver> KeyVerificationReceiverPtr;
+ typedef boost::function<void(EService, bool)> KeyVerificationResult_fn;
+ typedef boost::function<void(std::string , std::string )> TranslationSuccess_fn;
+ typedef boost::function<void(int, std::string)> TranslationFailure_fn;
/**
* Translate given text.
@@ -267,15 +71,15 @@ public :
* @param to_lang Target language.
* @param mesg Text to translate.
*/
- static void translateMessage(TranslationReceiverPtr &receiver, const std::string &from_lang, const std::string &to_lang, const std::string &mesg);
+ static void translateMessage(const std::string &from_lang, const std::string &to_lang, const std::string &mesg, TranslationSuccess_fn success, TranslationFailure_fn failure);
- /**
+ /**
* Verify given API key of a translation service.
*
* @param receiver Object to pass verification result to.
* @param key Key to verify.
*/
- static void verifyKey(KeyVerificationReceiverPtr& receiver, const std::string& key);
+ static void verifyKey(EService service, const std::string &key, KeyVerificationResult_fn fnc);
/**
* @return translation target language
@@ -288,9 +92,8 @@ public :
static bool isTranslationConfigured();
private:
- static const LLTranslationAPIHandler& getPreferredHandler();
- static const LLTranslationAPIHandler& getHandler(EService service);
- static void sendRequest(const std::string& url, LLHTTPClient::ResponderPtr responder);
+ static LLTranslationAPIHandler& getPreferredHandler();
+ static LLTranslationAPIHandler& getHandler(EService service);
};
#endif
diff --git a/indra/newview/lltwitterconnect.cpp b/indra/newview/lltwitterconnect.cpp
index c6a0a15759..9b7c13b57d 100644
--- a/indra/newview/lltwitterconnect.cpp
+++ b/indra/newview/lltwitterconnect.cpp
@@ -84,9 +84,7 @@ void LLTwitterConnect::twitterConnectCoro(std::string requestToken, std::string
if (!oauthVerifier.empty())
body["oauth_verifier"] = oauthVerifier;
- setConnectionState(LLTwitterConnect::TWITTER_CONNECTION_IN_PROGRESS);
-
- LLSD result = httpAdapter->putAndYield(httpRequest, getTwitterConnectURL("/connection"), body, httpOpts);
+ LLSD result = httpAdapter->putAndSuspend(httpRequest, getTwitterConnectURL("/connection"), body, httpOpts);
LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
@@ -168,9 +166,7 @@ void LLTwitterConnect::twitterShareCoro(std::string route, LLSD share)
httpOpts->setWantHeaders(true);
httpOpts->setFollowRedirects(false);
- setConnectionState(LLTwitterConnect::TWITTER_POSTING);
-
- LLSD result = httpAdapter->postAndYield(httpRequest, getTwitterConnectURL(route, true), share, httpOpts);
+ LLSD result = httpAdapter->postAndSuspend(httpRequest, getTwitterConnectURL(route, true), share, httpOpts);
if (testShareStatus(result))
{
@@ -235,7 +231,7 @@ void LLTwitterConnect::twitterShareImageCoro(LLPointer<LLImageFormatted> image,
body << "\r\n--" << boundary << "--\r\n";
- LLSD result = httpAdapter->postAndYield(httpRequest, getTwitterConnectURL("/share/photo", true), raw, httpOpts, httpHeaders);
+ LLSD result = httpAdapter->postAndSuspend(httpRequest, getTwitterConnectURL("/share/photo", true), raw, httpOpts, httpHeaders);
if (testShareStatus(result))
{
@@ -257,9 +253,7 @@ void LLTwitterConnect::twitterDisconnectCoro()
httpOpts->setFollowRedirects(false);
- setConnectionState(LLTwitterConnect::TWITTER_DISCONNECTING);
-
- LLSD result = httpAdapter->deleteAndYield(httpRequest, getTwitterConnectURL("/connection"), httpOpts);
+ LLSD result = httpAdapter->deleteAndSuspend(httpRequest, getTwitterConnectURL("/connection"), httpOpts);
LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
@@ -293,7 +287,7 @@ void LLTwitterConnect::twitterConnectedCoro(bool autoConnect)
httpOpts->setFollowRedirects(false);
setConnectionState(LLTwitterConnect::TWITTER_CONNECTION_IN_PROGRESS);
- LLSD result = httpAdapter->getAndYield(httpRequest, getTwitterConnectURL("/connection", true), httpOpts);
+ LLSD result = httpAdapter->getAndSuspend(httpRequest, getTwitterConnectURL("/connection", true), httpOpts);
LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
@@ -342,7 +336,7 @@ void LLTwitterConnect::twitterInfoCoro()
httpOpts->setWantHeaders(true);
httpOpts->setFollowRedirects(false);
- LLSD result = httpAdapter->getAndYield(httpRequest, getTwitterConnectURL("/info", true), httpOpts);
+ LLSD result = httpAdapter->getAndSuspend(httpRequest, getTwitterConnectURL("/info", true), httpOpts);
LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
@@ -424,12 +418,16 @@ std::string LLTwitterConnect::getTwitterConnectURL(const std::string& route, boo
void LLTwitterConnect::connectToTwitter(const std::string& request_token, const std::string& oauth_verifier)
{
+ setConnectionState(LLTwitterConnect::TWITTER_CONNECTION_IN_PROGRESS);
+
LLCoros::instance().launch("LLTwitterConnect::twitterConnectCoro",
boost::bind(&LLTwitterConnect::twitterConnectCoro, this, request_token, oauth_verifier));
}
void LLTwitterConnect::disconnectFromTwitter()
{
+ setConnectionState(LLTwitterConnect::TWITTER_DISCONNECTING);
+
LLCoros::instance().launch("LLTwitterConnect::twitterDisconnectCoro",
boost::bind(&LLTwitterConnect::twitterDisconnectCoro, this));
}
@@ -455,12 +453,16 @@ void LLTwitterConnect::uploadPhoto(const std::string& image_url, const std::stri
body["image"] = image_url;
body["status"] = status;
+ setConnectionState(LLTwitterConnect::TWITTER_POSTING);
+
LLCoros::instance().launch("LLTwitterConnect::twitterShareCoro",
boost::bind(&LLTwitterConnect::twitterShareCoro, this, "/share/photo", body));
}
void LLTwitterConnect::uploadPhoto(LLPointer<LLImageFormatted> image, const std::string& status)
{
+ setConnectionState(LLTwitterConnect::TWITTER_POSTING);
+
LLCoros::instance().launch("LLTwitterConnect::twitterShareImageCoro",
boost::bind(&LLTwitterConnect::twitterShareImageCoro, this, image, status));
}
@@ -470,6 +472,8 @@ void LLTwitterConnect::updateStatus(const std::string& status)
LLSD body;
body["status"] = status;
+ setConnectionState(LLTwitterConnect::TWITTER_POSTING);
+
LLCoros::instance().launch("LLTwitterConnect::twitterShareCoro",
boost::bind(&LLTwitterConnect::twitterShareCoro, this, "/share/status", body));
}
diff --git a/indra/newview/lluploadfloaterobservers.h b/indra/newview/lluploadfloaterobservers.h
index 02baf8f1c0..15c3dad38e 100755
--- a/indra/newview/lluploadfloaterobservers.h
+++ b/indra/newview/lluploadfloaterobservers.h
@@ -28,7 +28,6 @@
#define LL_LLUPLOADFLOATEROBSERVERS_H
#include "llfloater.h"
-#include "llhttpclient.h"
#include "llhandle.h"
class LLUploadPermissionsObserver
diff --git a/indra/newview/llurllineeditorctrl.cpp b/indra/newview/llurllineeditorctrl.cpp
index cad5769042..8a61114852 100755
--- a/indra/newview/llurllineeditorctrl.cpp
+++ b/indra/newview/llurllineeditorctrl.cpp
@@ -84,7 +84,7 @@ void LLURLLineEditor::copyEscapedURLToClipboard()
const std::string unescaped_text = wstring_to_utf8str(mText.getWString().substr(left_pos, length));
LLWString text_to_copy;
// *HACK: Because LLSLURL is currently broken we cannot use it to check if unescaped_text is a valid SLURL (see EXT-8335).
- if (LLStringUtil::startsWith(unescaped_text, "http://")) // SLURL
+ if (LLStringUtil::startsWith(unescaped_text, "http://") || LLStringUtil::startsWith(unescaped_text, "secondlife://")) // SLURL
text_to_copy = utf8str_to_wstring(LLWeb::escapeURL(unescaped_text));
else // human-readable location
text_to_copy = utf8str_to_wstring(unescaped_text);
diff --git a/indra/newview/llviewerassetupload.cpp b/indra/newview/llviewerassetupload.cpp
index 6c6d3a4f33..f0dafec240 100644
--- a/indra/newview/llviewerassetupload.cpp
+++ b/indra/newview/llviewerassetupload.cpp
@@ -174,7 +174,7 @@ S32 LLResourceUploadInfo::getEconomyUploadCost()
getAssetType() == LLAssetType::AT_ANIMATION ||
getAssetType() == LLAssetType::AT_MESH)
{
- return LLGlobalEconomy::Singleton::getInstance()->getPriceUpload();
+ return LLGlobalEconomy::Singleton::instance().getPriceUpload();
}
return 0;
@@ -666,7 +666,7 @@ LLUUID LLViewerAssetUpload::EnqueueInventoryUpload(const std::string &url, const
{
std::string procName("LLViewerAssetUpload::AssetInventoryUploadCoproc(");
- LLUUID queueId = LLCoprocedureManager::getInstance()->enqueueCoprocedure("Upload",
+ LLUUID queueId = LLCoprocedureManager::instance().enqueueCoprocedure("Upload",
procName + LLAssetType::lookup(uploadInfo->getAssetType()) + ")",
boost::bind(&LLViewerAssetUpload::AssetInventoryUploadCoproc, _1, _2, url, uploadInfo));
@@ -689,7 +689,7 @@ void LLViewerAssetUpload::AssetInventoryUploadCoproc(LLCoreHttpUtil::HttpCorouti
return;
}
- llcoro::yield();
+ llcoro::suspend();
if (uploadInfo->showUploadDialog())
{
@@ -700,7 +700,7 @@ void LLViewerAssetUpload::AssetInventoryUploadCoproc(LLCoreHttpUtil::HttpCorouti
LLSD body = uploadInfo->generatePostBody();
- result = httpAdapter->postAndYield(httpRequest, url, body);
+ result = httpAdapter->postAndSuspend(httpRequest, url, body);
LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
@@ -718,11 +718,13 @@ void LLViewerAssetUpload::AssetInventoryUploadCoproc(LLCoreHttpUtil::HttpCorouti
bool success = false;
if (!uploader.empty() && uploadInfo->getAssetId().notNull())
{
- result = httpAdapter->postFileAndYield(httpRequest, uploader, uploadInfo->getAssetId(), uploadInfo->getAssetType());
+ result = httpAdapter->postFileAndSuspend(httpRequest, uploader, uploadInfo->getAssetId(), uploadInfo->getAssetType());
httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
- if (!status)
+ std::string ulstate = result["state"].asString();
+
+ if ((!status) || (ulstate != "complete"))
{
HandleUploadError(status, result, uploadInfo);
if (uploadInfo->showUploadDialog())
@@ -730,7 +732,7 @@ void LLViewerAssetUpload::AssetInventoryUploadCoproc(LLCoreHttpUtil::HttpCorouti
return;
}
- S32 uploadPrice = uploadInfo->getEconomyUploadCost();
+ S32 uploadPrice = result["upload_price"].asInteger();//uploadInfo->getEconomyUploadCost();
if (uploadPrice > 0)
{
diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp
index 2bd8e5f99c..c0e5e632e6 100755
--- a/indra/newview/llviewerfloaterreg.cpp
+++ b/indra/newview/llviewerfloaterreg.cpp
@@ -89,9 +89,9 @@
#include "llfloatermodelpreview.h"
#include "llfloaternamedesc.h"
#include "llfloaternotificationsconsole.h"
+#include "llfloaternotificationstabbed.h"
#include "llfloaterobjectweights.h"
#include "llfloateropenobject.h"
-#include "llfloateroutbox.h"
#include "llfloaterpathfindingcharacters.h"
#include "llfloaterpathfindingconsole.h"
#include "llfloaterpathfindinglinksets.h"
@@ -266,11 +266,11 @@ void LLViewerFloaterReg::registerFloaters()
LLFloaterReg::add("mini_map", "floater_map.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterMap>);
LLFloaterReg::add("notifications_console", "floater_notifications_console.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterNotificationConsole>);
- LLFloaterReg::add("notification_well_window", "floater_sys_well.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLNotificationWellWindow>);
+
+ LLFloaterReg::add("notification_well_window", "floater_notifications_tabbed.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterNotificationsTabbed>);
LLFloaterReg::add("object_weights", "floater_object_weights.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterObjectWeights>);
LLFloaterReg::add("openobject", "floater_openobject.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterOpenObject>);
- LLFloaterReg::add("outbox", "floater_merchant_outbox.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterOutbox>);
LLFloaterReg::add("outgoing_call", "floater_outgoing_call.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLOutgoingCallDialog>);
LLFloaterPayUtil::registerFloater();
diff --git a/indra/newview/llviewerfoldertype.cpp b/indra/newview/llviewerfoldertype.cpp
index 158cacbc81..b8ff2cc9b4 100644
--- a/indra/newview/llviewerfoldertype.cpp
+++ b/indra/newview/llviewerfoldertype.cpp
@@ -137,7 +137,7 @@ LLViewerFolderDictionary::LLViewerFolderDictionary()
bool boxes_invisible = !gSavedSettings.getBOOL("InventoryOutboxMakeVisible");
addEntry(LLFolderType::FT_INBOX, new ViewerFolderEntry("Received Items", "Inv_SysOpen", "Inv_SysClosed", FALSE, boxes_invisible));
- addEntry(LLFolderType::FT_OUTBOX, new ViewerFolderEntry("Merchant Outbox", "Inv_SysOpen", "Inv_SysClosed", FALSE, boxes_invisible));
+ addEntry(LLFolderType::FT_OUTBOX, new ViewerFolderEntry("Merchant Outbox", "Inv_SysOpen", "Inv_SysClosed", FALSE, true));
addEntry(LLFolderType::FT_BASIC_ROOT, new ViewerFolderEntry("Basic Root", "Inv_SysOpen", "Inv_SysClosed", FALSE, true));
diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp
index 573791aca3..0ee873d7a1 100755
--- a/indra/newview/llviewerinventory.cpp
+++ b/indra/newview/llviewerinventory.cpp
@@ -427,7 +427,7 @@ void LLViewerInventoryItem::fetchFromServer(void) const
body["items"][0]["owner_id"] = mPermissions.getOwner();
body["items"][0]["item_id"] = mUUID;
- LLInventoryModel::FetchItemHttpHandler * handler(new LLInventoryModel::FetchItemHttpHandler(body));
+ LLCore::HttpHandler::ptr_t handler(new LLInventoryModel::FetchItemHttpHandler(body));
gInventory.requestPost(true, url, body, handler, "Inventory Item");
}
else
diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp
index f332a4e98e..4e8fa28b86 100755
--- a/indra/newview/llviewermedia.cpp
+++ b/indra/newview/llviewermedia.cpp
@@ -1280,7 +1280,7 @@ void LLViewerMedia::getOpenIDCookieCoro(std::string url)
LL_DEBUGS("MediaAuth") << "Requesting " << url << LL_ENDL;
LL_DEBUGS("MediaAuth") << "sOpenIDCookie = [" << sOpenIDCookie << "]" << LL_ENDL;
- LLSD result = httpAdapter->getRawAndYield(httpRequest, url, httpOpts, httpHeaders);
+ LLSD result = httpAdapter->getRawAndSuspend(httpRequest, url, httpOpts, httpHeaders);
LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
@@ -1347,7 +1347,7 @@ void LLViewerMedia::openIDSetupCoro(std::string openidUrl, std::string openidTok
bas << std::noskipws << openidToken;
- LLSD result = httpAdapter->postRawAndYield(httpRequest, openidUrl, rawbody, httpOpts, httpHeaders);
+ LLSD result = httpAdapter->postRawAndSuspend(httpRequest, openidUrl, rawbody, httpOpts, httpHeaders);
LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
@@ -2592,6 +2592,9 @@ void LLViewerMediaImpl::mimeDiscoveryCoro(std::string url)
LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions);
LLCore::HttpHeaders::ptr_t httpHeaders(new LLCore::HttpHeaders);
+ // Increment our refcount so that we do not go away while the coroutine is active.
+ this->ref();
+
mMimeProbe = httpAdapter;
httpOpts->setFollowRedirects(true);
@@ -2600,7 +2603,7 @@ void LLViewerMediaImpl::mimeDiscoveryCoro(std::string url)
httpHeaders->append(HTTP_OUT_HEADER_ACCEPT, "*/*");
httpHeaders->append(HTTP_OUT_HEADER_COOKIE, "");
- LLSD result = httpAdapter->getRawAndYield(httpRequest, url, httpOpts, httpHeaders);
+ LLSD result = httpAdapter->getRawAndSuspend(httpRequest, url, httpOpts, httpHeaders);
mMimeProbe.reset();
@@ -2612,35 +2615,47 @@ void LLViewerMediaImpl::mimeDiscoveryCoro(std::string url)
LL_WARNS() << "Error retrieving media headers." << LL_ENDL;
}
- LLSD resultHeaders = httpResults[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS_HEADERS];
-
- const std::string& mediaType = resultHeaders[HTTP_IN_HEADER_CONTENT_TYPE].asStringRef();
+ if (this->getNumRefs() > 1)
+ { // if there is only a single ref count outstanding it will be the one we took out above...
+ // we can skip the rest of this routine
- std::string::size_type idx1 = mediaType.find_first_of(";");
- std::string mimeType = mediaType.substr(0, idx1);
+ LLSD resultHeaders = httpResults[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS_HEADERS];
- // We now no longer need to check the error code returned from the probe.
- // If we have a mime type, use it. If not, default to the web plugin and let it handle error reporting.
- // The probe was successful.
- if (mimeType.empty())
- {
- // Some sites don't return any content-type header at all.
- // Treat an empty mime type as text/html.
- mimeType = HTTP_CONTENT_TEXT_HTML;
- }
+ const std::string& mediaType = resultHeaders[HTTP_IN_HEADER_CONTENT_TYPE].asStringRef();
- LL_DEBUGS() << "Media type \"" << mediaType << "\", mime type is \"" << mimeType << "\"" << LL_ENDL;
+ std::string::size_type idx1 = mediaType.find_first_of(";");
+ std::string mimeType = mediaType.substr(0, idx1);
- // the call to initializeMedia may disconnect the responder, which will clear mMediaImpl.
- // Make a local copy so we can call loadURI() afterwards.
+ // We now no longer need to check the error code returned from the probe.
+ // If we have a mime type, use it. If not, default to the web plugin and let it handle error reporting.
+ // The probe was successful.
+ if (mimeType.empty())
+ {
+ // Some sites don't return any content-type header at all.
+ // Treat an empty mime type as text/html.
+ mimeType = HTTP_CONTENT_TEXT_HTML;
+ }
- if (!mimeType.empty())
- {
- if (initializeMedia(mimeType))
+ LL_DEBUGS() << "Media type \"" << mediaType << "\", mime type is \"" << mimeType << "\"" << LL_ENDL;
+
+ // the call to initializeMedia may disconnect the responder, which will clear mMediaImpl.
+ // Make a local copy so we can call loadURI() afterwards.
+
+ if (!mimeType.empty())
{
- loadURI();
+ if (initializeMedia(mimeType))
+ {
+ loadURI();
+ }
}
+
}
+ else
+ {
+ LL_WARNS() << "LLViewerMediaImpl to be released." << LL_ENDL;
+ }
+
+ this->unref();
}
//////////////////////////////////////////////////////////////////////////////////////////
@@ -3634,7 +3649,7 @@ void LLViewerMediaImpl::cancelMimeTypeProbe()
LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t probeAdapter = mMimeProbe.lock();
if (probeAdapter)
- probeAdapter->cancelYieldingOperation();
+ probeAdapter->cancelSuspendedOperation();
}
void LLViewerMediaImpl::addObject(LLVOVolume* obj)
diff --git a/indra/newview/llviewermedia.h b/indra/newview/llviewermedia.h
index 92d644c900..d93eb3d6e0 100755
--- a/indra/newview/llviewermedia.h
+++ b/indra/newview/llviewermedia.h
@@ -254,6 +254,7 @@ public:
void setHomeURL(const std::string& home_url, const std::string& mime_type = LLStringUtil::null) { mHomeURL = home_url; mHomeMimeType = mime_type;};
void clearCache();
void setPageZoomFactor( double factor );
+ double getPageZoomFactor() {return mZoomFactor;}
std::string getMimeType() { return mMimeType; }
void scaleMouse(S32 *mouse_x, S32 *mouse_y);
void scaleTextureCoords(const LLVector2& texture_coords, S32 *x, S32 *y);
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index 2505ae6a9c..f32ae27073 100755
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -57,6 +57,7 @@
#include "llfacebookconnect.h"
#include "llfilepicker.h"
#include "llfirstuse.h"
+#include "llfloaterabout.h"
#include "llfloaterbuy.h"
#include "llfloaterbuycontents.h"
#include "llbuycurrencyhtml.h"
@@ -390,32 +391,10 @@ void set_underclothes_menu_options()
void set_merchant_SLM_menu()
{
- // DD-170 : SLM Alpha and Beta program : for the moment, we always show the SLM menu and
- // tools so that all merchants can try out the UI, even if not migrated.
- // *TODO : Keep SLM UI hidden for non migrated merchant in released viewer
-
- //if (LLMarketplaceData::instance().getSLMStatus() == MarketplaceStatusCodes::MARKET_PLACE_NOT_MIGRATED_MERCHANT)
- //{
- // Merchant not migrated: show only the old Merchant Outbox menu
- // gMenuHolder->getChild<LLView>("MerchantOutbox")->setVisible(TRUE);
- //}
- //else
- //{
- // All other cases (new merchant, not merchant, migrated merchant): show the new Marketplace Listings menu and enable the tool
- gMenuHolder->getChild<LLView>("MarketplaceListings")->setVisible(TRUE);
- LLCommand* command = LLCommandManager::instance().getCommand("marketplacelistings");
- gToolBarView->enableCommand(command->id(), true);
- //}
-}
-
-void set_merchant_outbox_menu(U32 status, const LLSD& content)
-{
- // If the merchant is fully migrated, the API is disabled (503) and we won't show the old menu item.
- // In all other cases, we show it.
- if (status != MarketplaceErrorCodes::IMPORT_SERVER_API_DISABLED)
- {
- gMenuHolder->getChild<LLView>("MerchantOutbox")->setVisible(TRUE);
- }
+ // All other cases (new merchant, not merchant, migrated merchant): show the new Marketplace Listings menu and enable the tool
+ gMenuHolder->getChild<LLView>("MarketplaceListings")->setVisible(TRUE);
+ LLCommand* command = LLCommandManager::instance().getCommand("marketplacelistings");
+ gToolBarView->enableCommand(command->id(), true);
}
void check_merchant_status()
@@ -434,17 +413,6 @@ void check_merchant_status()
// Launch an SLM test connection to get the merchant status
LLMarketplaceData::instance().initializeSLM(boost::bind(&set_merchant_SLM_menu));
-
- // Do the Merchant Outbox init only once per session
- if (LLMarketplaceInventoryImporter::instance().getMarketPlaceStatus() == MarketplaceStatusCodes::MARKET_PLACE_NOT_INITIALIZED)
- {
- // Hide merchant outbox related menu item
- gMenuHolder->getChild<LLView>("MerchantOutbox")->setVisible(FALSE);
-
- // Launch a Merchant Outbox test connection to get the migration status
- LLMarketplaceInventoryImporter::instance().setStatusReportCallback(boost::bind(&set_merchant_outbox_menu,_1, _2));
- LLMarketplaceInventoryImporter::instance().initialize();
- }
}
}
@@ -2139,6 +2107,22 @@ class LLAdvancedCheckShowObjectUpdates : public view_listener_t
+///////////////////////
+// CHECK FOR UPDATES //
+///////////////////////
+
+
+
+class LLAdvancedCheckViewerUpdates : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ LLFloaterAboutUtil::checkUpdatesAndNotify();
+ return true;
+ }
+};
+
+
////////////////////
// COMPRESS IMAGE //
////////////////////
@@ -7140,11 +7124,10 @@ void handle_selected_texture_info(void*)
{
msg.append( llformat("%d ", (S32)(it->second[i])));
}
-
- LLSD args;
- args["MESSAGE"] = msg;
- LLNotificationsUtil::add("SystemMessage", args);
}
+ LLSD args;
+ args["MESSAGE"] = msg;
+ LLNotificationsUtil::add("SystemMessage", args);
}
}
@@ -8920,6 +8903,7 @@ void initialize_menus()
// Advanced (toplevel)
view_listener_t::addMenu(new LLAdvancedToggleShowObjectUpdates(), "Advanced.ToggleShowObjectUpdates");
view_listener_t::addMenu(new LLAdvancedCheckShowObjectUpdates(), "Advanced.CheckShowObjectUpdates");
+ view_listener_t::addMenu(new LLAdvancedCheckViewerUpdates(), "Advanced.CheckViewerUpdates");
view_listener_t::addMenu(new LLAdvancedCompressImage(), "Advanced.CompressImage");
view_listener_t::addMenu(new LLAdvancedShowDebugSettings(), "Advanced.ShowDebugSettings");
view_listener_t::addMenu(new LLAdvancedEnableViewAdminOptions(), "Advanced.EnableViewAdminOptions");
diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp
index 782a27a846..4f24dfafac 100755
--- a/indra/newview/llviewermenufile.cpp
+++ b/indra/newview/llviewermenufile.cpp
@@ -66,7 +66,6 @@
// linden libraries
#include "lleconomy.h"
-#include "llhttpclient.h"
#include "llnotificationsutil.h"
#include "llsdserialize.h"
#include "llsdutil.h"
diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp
index 4e1a86bb71..d995ce4cdf 100755
--- a/indra/newview/llviewermessage.cpp
+++ b/indra/newview/llviewermessage.cpp
@@ -57,6 +57,7 @@
#include "llcallingcard.h"
#include "llbuycurrencyhtml.h"
#include "llfirstuse.h"
+#include "llfloaterbump.h"
#include "llfloaterbuyland.h"
#include "llfloaterland.h"
#include "llfloaterregioninfo.h"
@@ -120,6 +121,8 @@
#include "llnotificationmanager.h" //
#include "llexperiencecache.h"
+#include "llexperiencecache.h"
+
#if LL_MSVC
// disable boost::lexical_cast warning
#pragma warning (disable:4702)
@@ -2349,7 +2352,8 @@ static void god_message_name_cb(const LLAvatarName& av_name, LLChat chat, std::s
LLNotificationsUtil::add("GodMessage", args);
// Treat like a system message and put in chat history.
- chat.mText = av_name.getCompleteName() + ": " + message;
+ chat.mSourceType = CHAT_SOURCE_SYSTEM;
+ chat.mText = message;
LLFloaterIMNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance<LLFloaterIMNearbyChat>("nearby_chat");
if (nearby_chat)
@@ -2681,6 +2685,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
payload["sender_name"] = name;
payload["group_id"] = group_id;
payload["inventory_name"] = item_name;
+ payload["received_time"] = LLDate::now();
if(info && info->asLLSD())
{
payload["inventory_offer"] = info->asLLSD();
@@ -2860,6 +2865,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
case IM_FROM_TASK:
{
+
if (is_do_not_disturb && !is_owned_by_me)
{
return;
@@ -2943,17 +2949,13 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
payload["from_id"] = from_id;
payload["slurl"] = location;
payload["name"] = name;
- std::string session_name;
+
if (from_group)
{
payload["group_owned"] = "true";
}
- LLNotification::Params params("ServerObjectMessage");
- params.substitutions = substitutions;
- params.payload = payload;
-
- LLPostponedNotification::add<LLPostponedServerObjectNotification>(params, from_id, from_group);
+ LLNotificationsUtil::add("ServerObjectMessage", substitutions, payload);
}
break;
@@ -3490,53 +3492,29 @@ void process_decline_callingcard(LLMessageSystem* msg, void**)
LLNotificationsUtil::add("CallingCardDeclined");
}
-class ChatTranslationReceiver : public LLTranslate::TranslationReceiver
+void translateSuccess(LLChat chat, LLSD toastArgs, std::string originalMsg, std::string expectLang, std::string translation, const std::string detected_language)
{
-public :
- ChatTranslationReceiver(const std::string &from_lang, const std::string &to_lang, const std::string &mesg,
- const LLChat &chat, const LLSD &toast_args)
- : LLTranslate::TranslationReceiver(from_lang, to_lang),
- m_chat(chat),
- m_toastArgs(toast_args),
- m_origMesg(mesg)
- {
- }
-
- static ChatTranslationReceiver* build(const std::string &from_lang, const std::string &to_lang, const std::string &mesg, const LLChat &chat, const LLSD &toast_args)
- {
- return new ChatTranslationReceiver(from_lang, to_lang, mesg, chat, toast_args);
- }
-
-protected:
- void handleResponse(const std::string &translation, const std::string &detected_language)
- {
- // filter out non-interesting responeses
- if ( !translation.empty()
- && (mToLang != detected_language)
- && (LLStringUtil::compareInsensitive(translation, m_origMesg) != 0) )
- {
- m_chat.mText += " (" + translation + ")";
- }
+ // filter out non-interesting responses
+ if (!translation.empty()
+ && ((detected_language.empty()) || (expectLang != detected_language))
+ && (LLStringUtil::compareInsensitive(translation, originalMsg) != 0))
+ {
+ chat.mText += " (" + translation + ")";
+ }
- LLNotificationsUI::LLNotificationManager::instance().onChat(m_chat, m_toastArgs);
- }
+ LLNotificationsUI::LLNotificationManager::instance().onChat(chat, toastArgs);
+}
- void handleFailure(int status, const std::string& err_msg)
- {
- LL_WARNS() << "Translation failed for mesg " << m_origMesg << " toLang " << mToLang << " fromLang " << mFromLang << LL_ENDL;
+void translateFailure(LLChat chat, LLSD toastArgs, int status, const std::string err_msg)
+{
+ std::string msg = LLTrans::getString("TranslationFailed", LLSD().with("[REASON]", err_msg));
+ LLStringUtil::replaceString(msg, "\n", " "); // we want one-line error messages
+ chat.mText += " (" + msg + ")";
- std::string msg = LLTrans::getString("TranslationFailed", LLSD().with("[REASON]", err_msg));
- LLStringUtil::replaceString(msg, "\n", " "); // we want one-line error messages
- m_chat.mText += " (" + msg + ")";
+ LLNotificationsUI::LLNotificationManager::instance().onChat(chat, toastArgs);
+}
- LLNotificationsUI::LLNotificationManager::instance().onChat(m_chat, m_toastArgs);
- }
-private:
- LLChat m_chat;
- std::string m_origMesg;
- LLSD m_toastArgs;
-};
void process_chat_from_simulator(LLMessageSystem *msg, void **user_data)
{
LLChat chat;
@@ -3772,8 +3750,10 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data)
const std::string from_lang = ""; // leave empty to trigger autodetect
const std::string to_lang = LLTranslate::getTranslateLanguage();
- LLTranslate::TranslationReceiverPtr result = ChatTranslationReceiver::build(from_lang, to_lang, mesg, chat, args);
- LLTranslate::translateMessage(result, from_lang, to_lang, mesg);
+ LLTranslate::translateMessage(from_lang, to_lang, mesg,
+ boost::bind(&translateSuccess, chat, args, mesg, from_lang, _1, _2),
+ boost::bind(&translateFailure, chat, args, _1, _2));
+
}
else
{
@@ -3789,11 +3769,15 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data)
}
}
- LLSD msg_notify = LLSD(LLSD::emptyMap());
- msg_notify["session_id"] = LLUUID();
- msg_notify["from_id"] = chat.mFromID;
- msg_notify["source_type"] = chat.mSourceType;
- on_new_message(msg_notify);
+ if (mesg != "")
+ {
+ LLSD msg_notify = LLSD(LLSD::emptyMap());
+ msg_notify["session_id"] = LLUUID();
+ msg_notify["from_id"] = chat.mFromID;
+ msg_notify["source_type"] = chat.mSourceType;
+ on_new_message(msg_notify);
+ }
+
}
}
@@ -5635,6 +5619,7 @@ static void process_money_balance_reply_extended(LLMessageSystem* msg)
}
}
final_args["MESSAGE"] = message;
+ payload["dest_id"] = dest_id;
notification = success ? "PaymentSent" : "PaymentFailure";
}
else {
@@ -6263,6 +6248,11 @@ void process_mean_collision_alert_message(LLMessageSystem *msgsystem, void **use
gCacheName->get(perp, false, boost::bind(&mean_name_callback, _1, _2, _3));
}
}
+ LLFloaterBump* bumps_floater = LLFloaterBump::getInstance();
+ if(bumps_floater && bumps_floater->isInVisibleChain())
+ {
+ bumps_floater->populateCollisionList();
+ }
}
void process_frozen_message(LLMessageSystem *msgsystem, void **user_data)
@@ -6468,17 +6458,14 @@ bool script_question_cb(const LLSD& notification, const LLSD& response)
if (!region)
return false;
- std::string lookup_url=region->getCapability("ExperiencePreferences");
- if(lookup_url.empty())
- return false;
- LLSD permission;
- LLSD data;
- permission["permission"]="Block";
+ LLExperienceCache::instance().setExperiencePermission(experience, std::string("Block"), LLExperienceCache::ExperienceGetFn_t());
- data[experience.asString()]=permission;
- LLHTTPClient::put(lookup_url, data, NULL);
- data["experience"]=experience;
- LLEventPumps::instance().obtain("experience_permission").post(data);
+ LLSD permission;
+ LLSD data;
+ permission["permission"] = "Block";
+ data[experience.asString()] = permission;
+ data["experience"] = experience;
+ LLEventPumps::instance().obtain("experience_permission").post(data);
}
}
return false;
@@ -6653,7 +6640,7 @@ void process_script_question(LLMessageSystem *msg, void **user_data)
else if(experienceid.notNull())
{
payload["experience"]=experienceid;
- LLExperienceCache::getInstance()->get(experienceid, boost::bind(process_script_experience_details, _1, args, payload));
+ LLExperienceCache::instance().get(experienceid, boost::bind(process_script_experience_details, _1, args, payload));
return;
}
diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp
index 190102ff0f..c1a7518ba2 100755
--- a/indra/newview/llviewerobject.cpp
+++ b/indra/newview/llviewerobject.cpp
@@ -2885,6 +2885,9 @@ struct LLFilenameAndTask
{
LLUUID mTaskID;
std::string mFilename;
+
+ // for sequencing in case of multiple updates
+ S16 mSerial;
#ifdef _DEBUG
static S32 sCount;
LLFilenameAndTask()
@@ -2920,9 +2923,17 @@ void LLViewerObject::processTaskInv(LLMessageSystem* msg, void** user_data)
return;
}
- msg->getS16Fast(_PREHASH_InventoryData, _PREHASH_Serial, object->mInventorySerialNum);
LLFilenameAndTask* ft = new LLFilenameAndTask;
ft->mTaskID = task_id;
+ // we can receive multiple task updates simultaneously, make sure we will not rewrite newer with older update
+ msg->getS16Fast(_PREHASH_InventoryData, _PREHASH_Serial, ft->mSerial);
+
+ if (ft->mSerial < object->mInventorySerialNum)
+ {
+ // viewer did some changes to inventory that were not saved yet.
+ LL_DEBUGS() << "Task inventory serial might be out of sync, server serial: " << ft->mSerial << " client serial: " << object->mInventorySerialNum << LL_ENDL;
+ object->mInventorySerialNum = ft->mSerial;
+ }
std::string unclean_filename;
msg->getStringFast(_PREHASH_InventoryData, _PREHASH_Filename, unclean_filename);
@@ -2962,9 +2973,13 @@ void LLViewerObject::processTaskInvFile(void** user_data, S32 error_code, LLExtS
{
LLFilenameAndTask* ft = (LLFilenameAndTask*)user_data;
LLViewerObject* object = NULL;
- if(ft && (0 == error_code) &&
- (object = gObjectList.findObject(ft->mTaskID)))
+
+ if (ft
+ && (0 == error_code)
+ && (object = gObjectList.findObject(ft->mTaskID))
+ && ft->mSerial >= object->mInventorySerialNum)
{
+ object->mInventorySerialNum = ft->mSerial;
if (object->loadTaskInvFile(ft->mFilename))
{
@@ -2995,7 +3010,7 @@ void LLViewerObject::processTaskInvFile(void** user_data, S32 error_code, LLExtS
}
else
{
- // This Occurs When to requests were made, and the first one
+ // This Occurs When two requests were made, and the first one
// has already handled it.
LL_DEBUGS() << "Problem loading task inventory. Return code: "
<< error_code << LL_ENDL;
@@ -4637,7 +4652,7 @@ S32 LLViewerObject::setTEMaterialID(const U8 te, const LLMaterialID& pMaterialID
return retval;
}
-S32 LLViewerObject::setTEMaterialParams(const U8 te, const LLMaterialPtr pMaterialParams)
+S32 LLViewerObject::setTEMaterialParams(const U8 te, const LLMaterialPtr pMaterialParams, bool isInitFromServer)
{
S32 retval = 0;
const LLTextureEntry *tep = getTE(te);
@@ -4647,13 +4662,14 @@ S32 LLViewerObject::setTEMaterialParams(const U8 te, const LLMaterialPtr pMateri
return 0;
}
- retval = LLPrimitive::setTEMaterialParams(te, pMaterialParams);
+ setTENormalMap(te, (pMaterialParams) ? pMaterialParams->getNormalID() : LLUUID::null);
+ setTESpecularMap(te, (pMaterialParams) ? pMaterialParams->getSpecularID() : LLUUID::null);
+
+ retval = LLPrimitive::setTEMaterialParams(te, pMaterialParams, isInitFromServer);
LL_DEBUGS("Material") << "Changing material params for te " << (S32)te
<< ", object " << mID
<< " (" << retval << ")"
<< LL_ENDL;
- setTENormalMap(te, (pMaterialParams) ? pMaterialParams->getNormalID() : LLUUID::null);
- setTESpecularMap(te, (pMaterialParams) ? pMaterialParams->getSpecularID() : LLUUID::null);
refreshMaterials();
return retval;
diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h
index 05c87c153b..db2749f413 100755
--- a/indra/newview/llviewerobject.h
+++ b/indra/newview/llviewerobject.h
@@ -330,7 +330,7 @@ public:
/*virtual*/ S32 setTEMediaFlags(const U8 te, const U8 media_flags );
/*virtual*/ S32 setTEGlow(const U8 te, const F32 glow);
/*virtual*/ S32 setTEMaterialID(const U8 te, const LLMaterialID& pMaterialID);
- /*virtual*/ S32 setTEMaterialParams(const U8 te, const LLMaterialPtr pMaterialParams);
+ /*virtual*/ S32 setTEMaterialParams(const U8 te, const LLMaterialPtr pMaterialParams, bool isInitFromServer);
// Used by Materials update functions to properly kick off rebuilds
// of VBs etc when materials updates require changes.
diff --git a/indra/newview/llviewerobjectlist.cpp b/indra/newview/llviewerobjectlist.cpp
index 9b0035d547..5f01cdbb6f 100755
--- a/indra/newview/llviewerobjectlist.cpp
+++ b/indra/newview/llviewerobjectlist.cpp
@@ -80,6 +80,9 @@
#include "llvocache.h"
#include "llcorehttputil.h"
+#include <algorithm>
+#include <iterator>
+
extern F32 gMinObjectDistance;
extern BOOL gAnimateTextures;
@@ -1021,38 +1024,35 @@ void LLViewerObjectList::fetchObjectCostsCoro(std::string url)
httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("genericPostCoro", httpPolicy));
LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
- LLSD idList;
- U32 objectIndex = 0;
- for (std::set<LLUUID>::iterator it = mStaleObjectCost.begin(); it != mStaleObjectCost.end(); )
- {
- // Check to see if a request for this object
- // has already been made.
- if (mPendingObjectCost.find(*it) == mPendingObjectCost.end())
- {
- mPendingObjectCost.insert(*it);
- idList[objectIndex++] = *it;
- }
- mStaleObjectCost.erase(it++);
+ uuid_set_t diff;
- if (objectIndex >= MAX_CONCURRENT_PHYSICS_REQUESTS)
- {
- break;
- }
- }
+ std::set_difference(mStaleObjectCost.begin(), mStaleObjectCost.end(),
+ mPendingObjectCost.begin(), mPendingObjectCost.end(),
+ std::inserter(diff, diff.begin()));
- if (idList.size() < 1)
+ if (diff.empty())
{
LL_INFOS() << "No outstanding object IDs to request." << LL_ENDL;
return;
}
-
+
+ LLSD idList(LLSD::emptyArray());
+
+ for (uuid_set_t::iterator it = diff.begin(); it != diff.end(); ++it)
+ {
+ idList.append(*it);
+ mStaleObjectCost.erase(*it);
+ }
+
+ mPendingObjectCost.insert(diff.begin(), diff.end());
+
LLSD postData = LLSD::emptyMap();
postData["object_ids"] = idList;
- LLSD result = httpAdapter->postAndYield(httpRequest, url, postData);
+ LLSD result = httpAdapter->postAndSuspend(httpRequest, url, postData);
LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
@@ -1080,29 +1080,28 @@ void LLViewerObjectList::fetchObjectCostsCoro(std::string url)
{
LLUUID objectId = it->asUUID();
+ // If the object was added to the StaleObjectCost set after it had been
+ // added to mPendingObjectCost it would still be in the StaleObjectCost
+ // set when we got the response back.
+ mStaleObjectCost.erase(objectId);
+ mPendingObjectCost.erase(objectId);
+
// Check to see if the request contains data for the object
if (result.has(it->asString()))
{
- const LLSD& data = result[it->asString()];
+ LLSD objectData = result[it->asString()];
- S32 shapeType = data["PhysicsShapeType"].asInteger();
-
- gObjectList.updatePhysicsShapeType(objectId, shapeType);
-
- if (data.has("Density"))
- {
- F32 density = data["Density"].asReal();
- F32 friction = data["Friction"].asReal();
- F32 restitution = data["Restitution"].asReal();
- F32 gravityMult = data["GravityMultiplier"].asReal();
+ F32 linkCost = objectData["linked_set_resource_cost"].asReal();
+ F32 objectCost = objectData["resource_cost"].asReal();
+ F32 physicsCost = objectData["physics_cost"].asReal();
+ F32 linkPhysicsCost = objectData["linked_set_physics_cost"].asReal();
- gObjectList.updatePhysicsProperties(objectId, density, friction, restitution, gravityMult);
- }
+ gObjectList.updateObjectCost(objectId, objectCost, linkCost, physicsCost, linkPhysicsCost);
}
else
{
// TODO*: Give user feedback about the missing data?
- gObjectList.onPhysicsFlagsFetchFailure(objectId);
+ gObjectList.onObjectCostFetchFailure(objectId);
}
}
@@ -1153,7 +1152,7 @@ void LLViewerObjectList::fetchPhisicsFlagsCoro(std::string url)
LLSD idList;
U32 objectIndex = 0;
- for (std::set<LLUUID>::iterator it = mStalePhysicsFlags.begin(); it != mStalePhysicsFlags.end(); )
+ for (uuid_set_t::iterator it = mStalePhysicsFlags.begin(); it != mStalePhysicsFlags.end();)
{
// Check to see if a request for this object
// has already been made.
@@ -1181,7 +1180,7 @@ void LLViewerObjectList::fetchPhisicsFlagsCoro(std::string url)
postData["object_ids"] = idList;
- LLSD result = httpAdapter->postAndYield(httpRequest, url, postData);
+ LLSD result = httpAdapter->postAndSuspend(httpRequest, url, postData);
LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
@@ -1522,8 +1521,6 @@ void LLViewerObjectList::updateObjectCost(LLViewerObject* object)
void LLViewerObjectList::updateObjectCost(const LLUUID& object_id, F32 object_cost, F32 link_cost, F32 physics_cost, F32 link_physics_cost)
{
- mPendingObjectCost.erase(object_id);
-
LLViewerObject* object = findObject(object_id);
if (object)
{
diff --git a/indra/newview/llviewerobjectlist.h b/indra/newview/llviewerobjectlist.h
index 9ec7c4bc22..94c751acc6 100755
--- a/indra/newview/llviewerobjectlist.h
+++ b/indra/newview/llviewerobjectlist.h
@@ -205,17 +205,17 @@ protected:
vobj_list_t mMapObjects;
- std::set<LLUUID> mDeadObjects;
+ uuid_set_t mDeadObjects;
std::map<LLUUID, LLPointer<LLViewerObject> > mUUIDObjectMap;
//set of objects that need to update their cost
- std::set<LLUUID> mStaleObjectCost;
- std::set<LLUUID> mPendingObjectCost;
+ uuid_set_t mStaleObjectCost;
+ uuid_set_t mPendingObjectCost;
//set of objects that need to update their physics flags
- std::set<LLUUID> mStalePhysicsFlags;
- std::set<LLUUID> mPendingPhysicsFlags;
+ uuid_set_t mStalePhysicsFlags;
+ uuid_set_t mPendingPhysicsFlags;
std::vector<LLDebugBeacon> mDebugBeacons;
diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp
index 57548b6e8f..b0280ef3e0 100755
--- a/indra/newview/llviewerregion.cpp
+++ b/indra/newview/llviewerregion.cpp
@@ -34,7 +34,6 @@
#include "llavatarnamecache.h" // name lookup cap url
#include "llfloaterreg.h"
#include "llmath.h"
-#include "llhttpclient.h"
#include "llregionflags.h"
#include "llregionhandle.h"
#include "llsurface.h"
@@ -274,7 +273,7 @@ void LLViewerRegionImpl::requestBaseCapabilitiesCoro(U64 regionHandle)
<< " (attempt #" << mSeedCapAttempts << ")" << LL_ENDL;
regionp = NULL;
- result = httpAdapter->postAndYield(httpRequest, url, capabilityNames);
+ result = httpAdapter->postAndSuspend(httpRequest, url, capabilityNames);
regionp = LLWorld::getInstance()->getRegionFromHandle(regionHandle);
if (!regionp) //region was removed
@@ -311,6 +310,10 @@ void LLViewerRegionImpl::requestBaseCapabilitiesCoro(U64 regionHandle)
<< "Capability '" << iter->first << "' is '" << iter->second << "'" << LL_ENDL;
}
+#if 0
+ log_capabilities(mCapabilities);
+#endif
+
regionp->setCapabilitiesReceived(true);
if (STATE_SEED_GRANTED_WAIT == LLStartUp::getStartupState())
@@ -364,7 +367,7 @@ void LLViewerRegionImpl::requestBaseCapabilitiesCompleteCoro(U64 regionHandle)
LL_INFOS("AppInit", "Capabilities") << "Requesting second Seed from " << url << LL_ENDL;
regionp = NULL;
- result = httpAdapter->postAndYield(httpRequest, url, capabilityNames);
+ result = httpAdapter->postAndSuspend(httpRequest, url, capabilityNames);
LLSD httpResults = result["http_result"];
LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
@@ -391,6 +394,10 @@ void LLViewerRegionImpl::requestBaseCapabilitiesCompleteCoro(U64 regionHandle)
//LL_INFOS()<<"BaseCapabilitiesCompleteTracker New Caps "<<iter->first<<" "<< iter->second<<LL_ENDL;
}
+#if 0
+ log_capabilities(mCapabilities);
+#endif
+
if (mCapabilities.size() != mSecondCapabilitiesTracker.size())
{
LL_WARNS("AppInit", "Capabilities")
@@ -463,7 +470,7 @@ void LLViewerRegionImpl::requestSimulatorFeatureCoro(std::string url, U64 region
}
regionp = NULL;
- LLSD result = httpAdapter->getAndYield(httpRequest, url);
+ LLSD result = httpAdapter->getAndSuspend(httpRequest, url);
LLSD httpResults = result["http_result"];
LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
@@ -2940,11 +2947,7 @@ void LLViewerRegion::setCapability(const std::string& name, const std::string& u
}
else if(name == "UntrustedSimulatorMessage")
{
-#if 1
mImpl->mHost.setUntrustedSimulatorCap(url);
-#else
- LLHTTPSender::setSender(mImpl->mHost, new LLCapHTTPSender(url));
-#endif
}
else if (name == "SimulatorFeatures")
{
@@ -3042,7 +3045,7 @@ void LLViewerRegion::setCapabilitiesReceived(bool received)
{
mCapabilitiesReceivedSignal(getRegionID());
- LLFloaterPermsDefault::sendInitialPerms();
+ //LLFloaterPermsDefault::sendInitialPerms();
// This is a single-shot signal. Forget callbacks to save resources.
mCapabilitiesReceivedSignal.disconnect_all_slots();
diff --git a/indra/newview/llviewerstats.cpp b/indra/newview/llviewerstats.cpp
index 2c3067cd3a..f52c82dab7 100755
--- a/indra/newview/llviewerstats.cpp
+++ b/indra/newview/llviewerstats.cpp
@@ -60,6 +60,7 @@
#include "llfeaturemanager.h"
#include "llviewernetwork.h"
#include "llmeshrepository.h" //for LLMeshRepository::sBytesReceived
+#include "llsdserialize.h"
#include "llcorehttputil.h"
namespace LLStatViewer
@@ -599,8 +600,10 @@ void send_stats()
body["DisplayNamesShowUsername"] = gSavedSettings.getBOOL("NameTagShowUsernames");
body["MinimalSkin"] = false;
-
+
LLViewerStats::getInstance()->addToMessage(body);
+
+ LL_INFOS("LogViewerStatsPacket") << "Sending viewer statistics: " << body << LL_ENDL;
LLCoreHttpUtil::HttpCoroutineAdapter::messageHttpPost(url, body,
"Statistics posted to sim", "Failed to post statistics to sim");
LLViewerStats::instance().getRecording().resume();
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index db949437a7..e0932ec36e 100755
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -160,6 +160,9 @@ const F32 HEAD_MOVEMENT_AVG_TIME = 0.9f;
const S32 MORPH_MASK_REQUESTED_DISCARD = 0;
+const F32 MAX_STANDOFF_FROM_ORIGIN = 3;
+const F32 MAX_STANDOFF_DISTANCE_CHANGE = 32;
+
// Discard level at which to switch to baked textures
// Should probably be 4 or 3, but didn't want to change it while change other logic - SJB
const S32 SWITCH_TO_BAKED_DISCARD = 5;
@@ -2132,7 +2135,7 @@ void LLVOAvatar::idleUpdate(LLAgent &agent, const F64 &time)
// animate the character
// store off last frame's root position to be consistent with camera position
- LLVector3 root_pos_last = mRoot->getWorldPosition();
+ mLastRootPos = mRoot->getWorldPosition();
BOOL detailed_update = updateCharacter(agent);
static LLUICachedControl<bool> visualizers_in_calls("ShowVoiceVisualizersInCalls", false);
@@ -2150,7 +2153,7 @@ void LLVOAvatar::idleUpdate(LLAgent &agent, const F64 &time)
idleUpdateWindEffect();
}
- idleUpdateNameTag( root_pos_last );
+ idleUpdateNameTag( mLastRootPos );
idleUpdateRenderCost();
}
@@ -6080,10 +6083,10 @@ void LLVOAvatar::getOffObject()
{
return;
}
-
+
LLViewerObject* sit_object = (LLViewerObject*)getParent();
- if (sit_object)
+ if (sit_object)
{
stopMotionFromSource(sit_object->getID());
LLFollowCamMgr::setCameraActive(sit_object->getID(), FALSE);
@@ -6100,9 +6103,19 @@ void LLVOAvatar::getOffObject()
}
// assumes that transform will not be updated with drawable still having a parent
+ // or that drawable had no parent from the start
LLVector3 cur_position_world = mDrawable->getWorldPosition();
LLQuaternion cur_rotation_world = mDrawable->getWorldRotation();
+ if (mLastRootPos.length() >= MAX_STANDOFF_FROM_ORIGIN
+ && (cur_position_world.length() < MAX_STANDOFF_FROM_ORIGIN
+ || dist_vec(cur_position_world, mLastRootPos) > MAX_STANDOFF_DISTANCE_CHANGE))
+ {
+ // Most likely drawable got updated too early or some updates were missed - we got relative position to non-existing parent
+ // restore coordinates from cache
+ cur_position_world = mLastRootPos;
+ }
+
// set *local* position based on last *world* position, since we're unparenting the avatar
mDrawable->mXform.setPosition(cur_position_world);
mDrawable->mXform.setRotation(cur_rotation_world);
@@ -6278,6 +6291,7 @@ void LLVOAvatar::onGlobalColorChanged(const LLTexGlobalColor* global_color)
BOOL LLVOAvatar::isVisible() const
{
return mDrawable.notNull()
+ && (!mOrphaned || isSelf())
&& (mDrawable->isVisible() || mIsDummy);
}
diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h
index 1c3f4f2aa7..5b4379165a 100755
--- a/indra/newview/llvoavatar.h
+++ b/indra/newview/llvoavatar.h
@@ -869,6 +869,8 @@ public:
private:
// set this property only with LLVOAvatar::sitDown method
BOOL mIsSitting;
+ // position backup in case of missing data
+ LLVector3 mLastRootPos;
/** Hierarchy
** **
diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp
index fb2171ccc2..e7dee14387 100755
--- a/indra/newview/llvoavatarself.cpp
+++ b/indra/newview/llvoavatarself.cpp
@@ -2203,7 +2203,7 @@ void LLVOAvatarSelf::appearanceChangeMetricsCoro(std::string url)
gPendingMetricsUploads++;
- LLSD result = httpAdapter->postAndYield(httpRequest, url, msg);
+ LLSD result = httpAdapter->postAndSuspend(httpRequest, url, msg);
LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
diff --git a/indra/newview/llvoicechannel.cpp b/indra/newview/llvoicechannel.cpp
index 192d50ae9b..3abb716593 100755
--- a/indra/newview/llvoicechannel.cpp
+++ b/indra/newview/llvoicechannel.cpp
@@ -617,7 +617,7 @@ void LLVoiceChannelGroup::voiceCallCapCoro(std::string url)
LL_INFOS("Voice", "voiceCallCapCoro") << "Generic POST for " << url << LL_ENDL;
- LLSD result = httpAdapter->postAndYield(httpRequest, url, postData);
+ LLSD result = httpAdapter->postAndSuspend(httpRequest, url, postData);
LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp
index f50ffdeae7..d14fac5fb8 100755
--- a/indra/newview/llvoicevivox.cpp
+++ b/indra/newview/llvoicevivox.cpp
@@ -462,7 +462,7 @@ void LLVivoxVoiceClient::voiceAccountProvisionCoro(std::string url, S32 retries)
httpOpts->setRetries(retries);
- LLSD result = httpAdapter->postAndYield(httpRequest, url, LLSD(), httpOpts);
+ LLSD result = httpAdapter->postAndSuspend(httpRequest, url, LLSD(), httpOpts);
LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
@@ -3941,7 +3941,7 @@ void LLVivoxVoiceClient::parcelVoiceInfoRequestCoro(std::string url)
LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
state requestingState = getState();
- LLSD result = httpAdapter->postAndYield(httpRequest, url, LLSD());
+ LLSD result = httpAdapter->postAndSuspend(httpRequest, url, LLSD());
LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index 0432f6f27c..19d61f6e33 100755
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -1624,6 +1624,66 @@ static LLTrace::BlockTimerStatHandle FTM_GEN_FLEX("Generate Flexies");
static LLTrace::BlockTimerStatHandle FTM_UPDATE_PRIMITIVES("Update Primitives");
static LLTrace::BlockTimerStatHandle FTM_UPDATE_RIGGED_VOLUME("Update Rigged");
+bool LLVOVolume::lodOrSculptChanged(LLDrawable *drawable, BOOL &compiled)
+{
+ bool regen_faces = false;
+
+ LLVolume *old_volumep, *new_volumep;
+ F32 old_lod, new_lod;
+ S32 old_num_faces, new_num_faces;
+
+ old_volumep = getVolume();
+ old_lod = old_volumep->getDetail();
+ old_num_faces = old_volumep->getNumFaces();
+ old_volumep = NULL;
+
+ {
+ LL_RECORD_BLOCK_TIME(FTM_GEN_VOLUME);
+ const LLVolumeParams &volume_params = getVolume()->getParams();
+ setVolume(volume_params, 0);
+ }
+
+ new_volumep = getVolume();
+ new_lod = new_volumep->getDetail();
+ new_num_faces = new_volumep->getNumFaces();
+ new_volumep = NULL;
+
+ if ((new_lod != old_lod) || mSculptChanged)
+ {
+ compiled = TRUE;
+ sNumLODChanges += new_num_faces;
+
+ if ((S32)getNumTEs() != getVolume()->getNumFaces())
+ {
+ setNumTEs(getVolume()->getNumFaces()); //mesh loading may change number of faces.
+ }
+
+ drawable->setState(LLDrawable::REBUILD_VOLUME); // for face->genVolumeTriangles()
+
+ {
+ LL_RECORD_BLOCK_TIME(FTM_GEN_TRIANGLES);
+ regen_faces = new_num_faces != old_num_faces || mNumFaces != (S32)getNumTEs();
+ if (regen_faces)
+ {
+ regenFaces();
+ }
+
+ if (mSculptChanged)
+ { //changes in sculpt maps can thrash an object bounding box without
+ //triggering a spatial group bounding box update -- force spatial group
+ //to update bounding boxes
+ LLSpatialGroup* group = mDrawable->getSpatialGroup();
+ if (group)
+ {
+ group->unbound();
+ }
+ }
+ }
+ }
+
+ return regen_faces;
+}
+
BOOL LLVOVolume::updateGeometry(LLDrawable *drawable)
{
LL_RECORD_BLOCK_TIME(FTM_UPDATE_PRIMITIVES);
@@ -1664,83 +1724,35 @@ BOOL LLVOVolume::updateGeometry(LLDrawable *drawable)
return TRUE; // No update to complete
}
- if (mVolumeChanged || mFaceMappingChanged )
+ if (mVolumeChanged || mFaceMappingChanged)
{
dirtySpatialGroup(drawable->isState(LLDrawable::IN_REBUILD_Q1));
- compiled = TRUE;
+ bool was_regen_faces = false;
if (mVolumeChanged)
{
- LL_RECORD_BLOCK_TIME(FTM_GEN_VOLUME);
- LLVolumeParams volume_params = getVolume()->getParams();
- setVolume(volume_params, 0);
+ was_regen_faces = lodOrSculptChanged(drawable, compiled);
drawable->setState(LLDrawable::REBUILD_VOLUME);
}
-
+ else if (mSculptChanged || mLODChanged)
{
+ compiled = TRUE;
+ was_regen_faces = lodOrSculptChanged(drawable, compiled);
+ }
+
+ if (!was_regen_faces) {
LL_RECORD_BLOCK_TIME(FTM_GEN_TRIANGLES);
regenFaces();
- genBBoxes(FALSE);
}
+
+ genBBoxes(FALSE);
}
- else if ((mLODChanged) || (mSculptChanged))
+ else if (mLODChanged || mSculptChanged)
{
dirtySpatialGroup(drawable->isState(LLDrawable::IN_REBUILD_Q1));
-
- LLVolume *old_volumep, *new_volumep;
- F32 old_lod, new_lod;
- S32 old_num_faces, new_num_faces ;
-
- old_volumep = getVolume();
- old_lod = old_volumep->getDetail();
- old_num_faces = old_volumep->getNumFaces() ;
- old_volumep = NULL ;
-
- {
- LL_RECORD_BLOCK_TIME(FTM_GEN_VOLUME);
- LLVolumeParams volume_params = getVolume()->getParams();
- setVolume(volume_params, 0);
- }
-
- new_volumep = getVolume();
- new_lod = new_volumep->getDetail();
- new_num_faces = new_volumep->getNumFaces() ;
- new_volumep = NULL ;
-
- if ((new_lod != old_lod) || mSculptChanged)
- {
- compiled = TRUE;
- sNumLODChanges += new_num_faces ;
-
- if((S32)getNumTEs() != getVolume()->getNumFaces())
- {
- setNumTEs(getVolume()->getNumFaces()); //mesh loading may change number of faces.
- }
-
- drawable->setState(LLDrawable::REBUILD_VOLUME); // for face->genVolumeTriangles()
-
- {
- LL_RECORD_BLOCK_TIME(FTM_GEN_TRIANGLES);
- if (new_num_faces != old_num_faces || mNumFaces != (S32)getNumTEs())
- {
- regenFaces();
- }
- genBBoxes(FALSE);
-
- if (mSculptChanged)
- { //changes in sculpt maps can thrash an object bounding box without
- //triggering a spatial group bounding box update -- force spatial group
- //to update bounding boxes
- LLSpatialGroup* group = mDrawable->getSpatialGroup();
- if (group)
- {
- group->unbound();
- }
- }
- }
- }
-
+ compiled = TRUE;
+ lodOrSculptChanged(drawable, compiled);
genBBoxes(FALSE);
}
// it has its own drawable (it's moved) or it has changed UVs or it has changed xforms from global<->local
@@ -2010,7 +2022,7 @@ void LLVOVolume::setTEMaterialParamsCallbackTE(const LLUUID& objectID, const LLM
LLTextureEntry* texture_entry = pVol->getTE(te);
if (texture_entry && (texture_entry->getMaterialID() == pMaterialID))
{
- pVol->setTEMaterialParams(te, pMaterialParams);
+ pVol->setTEMaterialParams(te, pMaterialParams, FALSE);
}
}
}
@@ -2081,7 +2093,7 @@ bool LLVOVolume::notifyAboutCreatingTexture(LLViewerTexture *texture)
for(map_te_material::const_iterator it = new_material.begin(), end = new_material.end(); it != end; ++it)
{
LLMaterialMgr::getInstance()->put(getID(), it->first, *it->second);
- LLViewerObject::setTEMaterialParams(it->first, it->second);
+ LLViewerObject::setTEMaterialParams(it->first, it->second, FALSE);
}
//clear wait-list
@@ -2158,7 +2170,7 @@ bool LLVOVolume::notifyAboutMissingAsset(LLViewerTexture *texture)
for(map_te_material::const_iterator it = new_material.begin(), end = new_material.end(); it != end; ++it)
{
LLMaterialMgr::getInstance()->put(getID(), it->first, *it->second);
- LLViewerObject::setTEMaterialParams(it->first, it->second);
+ LLViewerObject::setTEMaterialParams(it->first, it->second, FALSE);
}
//clear wait-list
@@ -2167,7 +2179,7 @@ bool LLVOVolume::notifyAboutMissingAsset(LLViewerTexture *texture)
return 0 != new_material.size();
}
-S32 LLVOVolume::setTEMaterialParams(const U8 te, const LLMaterialPtr pMaterialParams)
+S32 LLVOVolume::setTEMaterialParams(const U8 te, const LLMaterialPtr pMaterialParams, bool isInitFromServer)
{
LLMaterialPtr pMaterial = const_cast<LLMaterialPtr&>(pMaterialParams);
@@ -2264,7 +2276,7 @@ S32 LLVOVolume::setTEMaterialParams(const U8 te, const LLMaterialPtr pMaterialPa
}
}
- S32 res = LLViewerObject::setTEMaterialParams(te, pMaterial);
+ S32 res = LLViewerObject::setTEMaterialParams(te, pMaterial, isInitFromServer);
LL_DEBUGS("MaterialTEs") << "te " << (S32)te << " material " << ((pMaterial) ? pMaterial->asLLSD() : LLSD("null")) << " res " << res
<< ( LLSelectMgr::getInstance()->getSelection()->contains(const_cast<LLVOVolume*>(this), te) ? " selected" : " not selected" )
@@ -4163,7 +4175,7 @@ void LLRiggedVolume::update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, cons
}
//build matrix palette
- static const size_t kMaxJoints = 64;
+ static const size_t kMaxJoints = 52;
LLMatrix4a mp[kMaxJoints];
LLMatrix4* mat = (LLMatrix4*) mp;
@@ -4172,6 +4184,12 @@ void LLRiggedVolume::update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, cons
for (U32 j = 0; j < maxJoints; ++j)
{
LLJoint* joint = avatar->getJoint(skin->mJointNames[j]);
+ if (!joint)
+ {
+ // Fall back to a point inside the avatar if mesh is
+ // rigged to an unknown joint.
+ joint = avatar->getJoint("mPelvis");
+ }
if (joint)
{
mat[j] = skin->mInvBindMatrix[j];
@@ -4216,8 +4234,9 @@ void LLRiggedVolume::update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, cons
wght[k] = w - floorf(w);
scale += wght[k];
}
-
- wght *= 1.f/scale;
+ // This is enforced in unpackVolumeFaces()
+ llassert(scale>0.f);
+ wght *= 1.f / scale;
for (U32 k = 0; k < 4; k++)
{
@@ -4225,9 +4244,9 @@ void LLRiggedVolume::update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, cons
LLMatrix4a src;
// Insure ref'd bone is in our clamped array of mats
- llassert(idx[k] < kMaxJoints);
- // clamp k to kMaxJoints to avoid reading garbage off stack in release
- src.setMul(mp[idx[(k < kMaxJoints) ? k : 0]], w);
+ // clamp idx to maxJoints to avoid reading garbage off stack in release
+ S32 index = llclamp((S32)idx[k],(S32)0,(S32)kMaxJoints-1);
+ src.setMul(mp[index], w);
final_mat.add(src);
}
diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h
index bbaca316b0..ff7438ac09 100755
--- a/indra/newview/llvovolume.h
+++ b/indra/newview/llvovolume.h
@@ -192,7 +192,7 @@ public:
static void setTEMaterialParamsCallbackTE(const LLUUID& objectID, const LLMaterialID& pMaterialID, const LLMaterialPtr pMaterialParams, U32 te);
- /*virtual*/ S32 setTEMaterialParams(const U8 te, const LLMaterialPtr pMaterialParams);
+ /*virtual*/ S32 setTEMaterialParams(const U8 te, const LLMaterialPtr pMaterialParams, bool isInitFromServer);
/*virtual*/ S32 setTEScale(const U8 te, const F32 s, const F32 t);
/*virtual*/ S32 setTEScaleS(const U8 te, const F32 s);
/*virtual*/ S32 setTEScaleT(const U8 te, const F32 t);
@@ -339,6 +339,10 @@ protected:
void cleanUpMediaImpls();
void addMediaImpl(LLViewerMediaImpl* media_impl, S32 texture_index) ;
void removeMediaImpl(S32 texture_index) ;
+
+private:
+ bool lodOrSculptChanged(LLDrawable *drawable, BOOL &compiled);
+
public:
static S32 getRenderComplexityMax() {return mRenderComplexity_last;}
diff --git a/indra/newview/llwebprofile.cpp b/indra/newview/llwebprofile.cpp
index 2033a5f36a..06ce497510 100755
--- a/indra/newview/llwebprofile.cpp
+++ b/indra/newview/llwebprofile.cpp
@@ -124,7 +124,7 @@ void LLWebProfile::uploadImageCoro(LLPointer<LLImageFormatted> image, std::strin
httpHeaders = buildDefaultHeaders();
httpHeaders->append(HTTP_OUT_HEADER_COOKIE, getAuthCookie());
- LLSD result = httpAdapter->getJsonAndYield(httpRequest, configUrl, httpOpts, httpHeaders);
+ LLSD result = httpAdapter->getJsonAndSuspend(httpRequest, configUrl, httpOpts, httpHeaders);
LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
@@ -150,7 +150,7 @@ void LLWebProfile::uploadImageCoro(LLPointer<LLImageFormatted> image, std::strin
LLCore::BufferArray::ptr_t body = LLWebProfile::buildPostData(data, image, boundary);
- result = httpAdapter->postAndYield(httpRequest, uploadUrl, body, httpOpts, httpHeaders);
+ result = httpAdapter->postAndSuspend(httpRequest, uploadUrl, body, httpOpts, httpHeaders);
body.reset();
httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
@@ -178,7 +178,7 @@ void LLWebProfile::uploadImageCoro(LLPointer<LLImageFormatted> image, std::strin
LL_DEBUGS("Snapshots") << "Got redirection URL: " << redirUrl << LL_ENDL;
- result = httpAdapter->getRawAndYield(httpRequest, redirUrl, httpOpts, httpHeaders);
+ result = httpAdapter->getRawAndSuspend(httpRequest, redirUrl, httpOpts, httpHeaders);
httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
diff --git a/indra/newview/llwlhandlers.cpp b/indra/newview/llwlhandlers.cpp
index ff15afa598..87e8c3008e 100755
--- a/indra/newview/llwlhandlers.cpp
+++ b/indra/newview/llwlhandlers.cpp
@@ -101,7 +101,7 @@ void LLEnvironmentRequest::environmentRequestCoro(std::string url)
httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("EnvironmentRequest", httpPolicy));
LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
- LLSD result = httpAdapter->getAndYield(httpRequest, url);
+ LLSD result = httpAdapter->getAndSuspend(httpRequest, url);
if (requestId != LLEnvironmentRequest::sLastRequest)
{
@@ -126,7 +126,7 @@ void LLEnvironmentRequest::environmentRequestCoro(std::string url)
regionId = gAgent.getRegion()->getRegionID();
}
- if (result[0]["regionID"].asUUID() != regionId)
+ if ((result[0]["regionID"].asUUID() != regionId) && regionId.notNull())
{
LL_WARNS("WindlightCaps") << "Not in the region from where this data was received (wanting "
<< regionId << " but got " << result[0]["regionID"].asUUID()
@@ -185,7 +185,7 @@ void LLEnvironmentApply::environmentApplyCoro(std::string url, LLSD content)
httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("EnvironmentApply", httpPolicy));
LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
- LLSD result = httpAdapter->postAndYield(httpRequest, url, content);
+ LLSD result = httpAdapter->postAndSuspend(httpRequest, url, content);
LLSD notify; // for error reporting. If there is something to report to user this will be defined.
/*
diff --git a/indra/newview/llworldmap.cpp b/indra/newview/llworldmap.cpp
index bfae142812..837b30586b 100755
--- a/indra/newview/llworldmap.cpp
+++ b/indra/newview/llworldmap.cpp
@@ -383,6 +383,7 @@ void LLWorldMap::reloadItems(bool force)
LLWorldMapMessage::getInstance()->sendItemRequest(MAP_ITEM_MATURE_EVENT);
LLWorldMapMessage::getInstance()->sendItemRequest(MAP_ITEM_ADULT_EVENT);
LLWorldMapMessage::getInstance()->sendItemRequest(MAP_ITEM_LAND_FOR_SALE);
+ LLWorldMapMessage::getInstance()->sendItemRequest(MAP_ITEM_LAND_FOR_SALE_ADULT);
}
}
diff --git a/indra/newview/llxmlrpctransaction.cpp b/indra/newview/llxmlrpctransaction.cpp
index 5828aee7fc..f8b38669b6 100755
--- a/indra/newview/llxmlrpctransaction.cpp
+++ b/indra/newview/llxmlrpctransaction.cpp
@@ -34,8 +34,8 @@
#include "llxmlrpctransaction.h"
#include "llxmlrpclistener.h"
-#include "llcurl.h"
#include "httpcommon.h"
+#include "llhttpconstants.h"
#include "httprequest.h"
#include "httpoptions.h"
#include "httpheaders.h"
@@ -175,7 +175,7 @@ public:
virtual void onCompleted(LLCore::HttpHandle handle, LLCore::HttpResponse * response);
- typedef boost::unique_ptr<LLXMLRPCTransaction::Handler> ptr_t;
+ typedef boost::shared_ptr<LLXMLRPCTransaction::Handler> ptr_t;
private:
@@ -390,7 +390,7 @@ void LLXMLRPCTransaction::Impl::init(XMLRPC_REQUEST request, bool useGzip)
mHandler = LLXMLRPCTransaction::Handler::ptr_t(new Handler( mHttpRequest, this ));
mPostH = mHttpRequest->requestPost(LLCore::HttpRequest::DEFAULT_POLICY_ID, 0,
- mURI, body.get(), httpOpts, httpHeaders, mHandler.get());
+ mURI, body.get(), httpOpts, httpHeaders, mHandler);
}
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index 03712c1065..57e2faca5b 100755
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -105,7 +105,6 @@
#include "llspatialpartition.h"
#include "llmutelist.h"
#include "lltoolpie.h"
-#include "llcurl.h"
#include "llnotifications.h"
#include "llpathinglib.h"
#include "llfloaterpathfindingconsole.h"
diff --git a/indra/newview/skins/default/colors.xml b/indra/newview/skins/default/colors.xml
index bdc884885f..8533625e50 100755
--- a/indra/newview/skins/default/colors.xml
+++ b/indra/newview/skins/default/colors.xml
@@ -873,8 +873,11 @@
<color
name="ToolbarDropZoneColor"
value=".48 .69 1 .5" />
-
- <!-- Generic color names (legacy) -->
+ <color
+ name="PanelNotificationListItem"
+ value="0.3 0.3 0.3 .3" />
+
+ <!-- Generic color names (legacy) -->
<color
name="white"
value="1 1 1 1"/>
diff --git a/indra/newview/skins/default/textures/icons/Icon_Attachment_Large.png b/indra/newview/skins/default/textures/icons/Icon_Attachment_Large.png
new file mode 100644
index 0000000000..0732a33d93
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Icon_Attachment_Large.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Icon_Attachment_Small.png b/indra/newview/skins/default/textures/icons/Icon_Attachment_Small.png
new file mode 100644
index 0000000000..8124554902
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Icon_Attachment_Small.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Icon_Notification_Condense.png b/indra/newview/skins/default/textures/icons/Icon_Notification_Condense.png
new file mode 100644
index 0000000000..4d245eb57a
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Icon_Notification_Condense.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Icon_Notification_Expand.png b/indra/newview/skins/default/textures/icons/Icon_Notification_Expand.png
new file mode 100644
index 0000000000..186822da43
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Icon_Notification_Expand.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/System_Notification_Large.png b/indra/newview/skins/default/textures/icons/System_Notification_Large.png
new file mode 100644
index 0000000000..434ce3e8b6
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/System_Notification_Large.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/System_Notification_Small.png b/indra/newview/skins/default/textures/icons/System_Notification_Small.png
new file mode 100644
index 0000000000..027a8446d8
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/System_Notification_Small.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml
index a5f2ce1f84..e453d94883 100755
--- a/indra/newview/skins/default/textures/textures.xml
+++ b/indra/newview/skins/default/textures/textures.xml
@@ -804,4 +804,9 @@ with the same filename but different name
<texture name="Camera_Drag_Dot" file_name="world/CameraDragDot.png"/>
<texture name="NavBar Separator" file_name="navbar/separator.png"/>
+ <texture name="Notification_Condense" file_name="icons/Icon_Notification_Condense.png" preload="true"/>
+ <texture name="Notification_Expand" file_name="icons/Icon_Notification_Expand.png" preload="true"/>
+ <texture name="System_Notification" file_name="icons/SL_Logo.png" preload="true"/>
+ <texture name="Icon_Attachment_Small" file_name="icons/Icon_Attachment_Small.png" preload="true"/>
+ <texture name="Icon_Attachment_Large" file_name="icons/Icon_Attachment_Large.png" preload="true"/>
</textures>
diff --git a/indra/newview/skins/default/xui/da/menu_viewer.xml b/indra/newview/skins/default/xui/da/menu_viewer.xml
index aa6bc53672..299322001b 100755
--- a/indra/newview/skins/default/xui/da/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/da/menu_viewer.xml
@@ -37,7 +37,7 @@
<menu_item_separator/>
<menu_item_call label="Profil for sted" name="Place Profile"/>
<menu_item_call label="Om land" name="About Land"/>
- <menu_item_call label="Region/Estate" name="Region/Estate"/>
+ <menu_item_call label="Region/Estate" name="RegionEstate"/>
<menu_item_call label="Køb dette land" name="Buy Land"/>
<menu_item_call label="Mit land" name="My Land"/>
<menu label="Vis" name="LandShow">
diff --git a/indra/newview/skins/default/xui/da/notifications.xml b/indra/newview/skins/default/xui/da/notifications.xml
index 33b876bdb9..aad3b9d062 100755
--- a/indra/newview/skins/default/xui/da/notifications.xml
+++ b/indra/newview/skins/default/xui/da/notifications.xml
@@ -1311,9 +1311,6 @@ Prøv igen om lidt.
<notification name="NoValidCircuit">
Ingen gyldig kode for kredsløb.
</notification>
- <notification name="NoValidTimestamp">
- Ikke et gyldigt klokkeslæt.
- </notification>
<notification name="NoPendingConnection">
Kunne ikke skabe fast forbindelse.
</notification>
diff --git a/indra/newview/skins/default/xui/de/menu_viewer.xml b/indra/newview/skins/default/xui/de/menu_viewer.xml
index 1924ff4ec3..956530c990 100755
--- a/indra/newview/skins/default/xui/de/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/de/menu_viewer.xml
@@ -15,7 +15,7 @@
<menu_item_check label="Fliegen" name="Fly"/>
<menu_item_check label="Immer rennen" name="Always Run"/>
<menu_item_call label="Animation meines Avatars stoppen" name="Stop Animating My Avatar"/>
- <menu_item_call label="Gehen/Rennen/Fliegen..." name="Walk / run / fly"/>
+ <menu_item_call label="Gehen/Rennen/Fliegen..." name="WalkRunFly"/>
</menu>
<menu label="Status" name="Status">
<menu_item_check label="Abwesend" name="Away"/>
@@ -64,7 +64,7 @@
<menu_item_call label="Foto" name="Take Snapshot"/>
<menu_item_call label="Ortsprofil" name="Place Profile"/>
<menu_item_call label="Landinformationen" name="About Land"/>
- <menu_item_call label="Region/Grundbesitz" name="Region/Estate"/>
+ <menu_item_call label="Region/Grundbesitz" name="RegionEstate"/>
<menu_item_call label="Mein Landbesitz..." name="My Land"/>
<menu_item_call label="Dieses Land kaufen" name="Buy Land"/>
<menu label="Anzeigen" name="LandShow">
diff --git a/indra/newview/skins/default/xui/de/notifications.xml b/indra/newview/skins/default/xui/de/notifications.xml
index 0b1c18cd51..fa7db0a8a3 100755
--- a/indra/newview/skins/default/xui/de/notifications.xml
+++ b/indra/newview/skins/default/xui/de/notifications.xml
@@ -2802,9 +2802,6 @@ Versuchen Sie es in einigen Minuten erneut.
<notification name="NoValidCircuit">
Kein gültiger Verbindungscode.
</notification>
- <notification name="NoValidTimestamp">
- Kein gültiger Zeitstempel.
- </notification>
<notification name="NoPendingConnection">
Verbindung kann nicht hergestellt werden.
</notification>
diff --git a/indra/newview/skins/default/xui/en/floater_about.xml b/indra/newview/skins/default/xui/en/floater_about.xml
index 60f36770bb..ec87b3684e 100755
--- a/indra/newview/skins/default/xui/en/floater_about.xml
+++ b/indra/newview/skins/default/xui/en/floater_about.xml
@@ -43,6 +43,14 @@
top_pad="5"
height="25"
width="180" />
+ <button
+ follows="left|top"
+ label="Check for updates"
+ name="update_btn"
+ left_pad="70"
+ top_delta="0"
+ height="25"
+ width="180" />
</panel>
<panel
border="true"
diff --git a/indra/newview/skins/default/xui/en/floater_about_land.xml b/indra/newview/skins/default/xui/en/floater_about_land.xml
index 90d45d5ebc..edf028bf60 100755
--- a/indra/newview/skins/default/xui/en/floater_about_land.xml
+++ b/indra/newview/skins/default/xui/en/floater_about_land.xml
@@ -2013,7 +2013,7 @@ Only large parcels can be listed in search.
name="AllowedText"
top="0"
width="230">
- Allowed Residents
+ Allowed Residents ([COUNT])
</text>
<name_list
column_padding="0"
@@ -2062,7 +2062,7 @@ Only large parcels can be listed in search.
name="BanCheck"
top="0"
width="200">
- Banned Residents
+ Banned Residents ([COUNT])
</text>
<name_list
column_padding="0"
diff --git a/indra/newview/skins/default/xui/en/floater_bumps.xml b/indra/newview/skins/default/xui/en/floater_bumps.xml
index 1f2fe62b3c..126e3aac48 100755
--- a/indra/newview/skins/default/xui/en/floater_bumps.xml
+++ b/indra/newview/skins/default/xui/en/floater_bumps.xml
@@ -7,7 +7,7 @@
help_topic="floater_bumps"
save_rect="true"
title="BUMPS, PUSHES &amp; HITS"
- width="400">
+ width="420">
<floater.string
name="none_detected">
None detected
@@ -34,7 +34,7 @@
</floater.string>
<floater.string
name="timeStr">
- [[hour,datetime,slt]:[min,datetime,slt]]
+ [[hour,datetime,slt]:[min,datetime,slt]:[second,datetime,slt]]
</floater.string>
<scroll_list
draw_border="false"
@@ -45,5 +45,5 @@
multi_select="true"
name="bump_list"
top="20"
- width="388" />
+ width="408" />
</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_experiences.xml b/indra/newview/skins/default/xui/en/floater_experiences.xml
index 70e7507907..442da887c5 100644
--- a/indra/newview/skins/default/xui/en/floater_experiences.xml
+++ b/indra/newview/skins/default/xui/en/floater_experiences.xml
@@ -12,7 +12,7 @@
name="floater_experiences"
save_rect="true"
single_instance="true"
- reuse_instance="false"
+
bg_opaque_color="0 0.5 0 0.3"
title="EXPERIENCES">
<tab_container
diff --git a/indra/newview/skins/default/xui/en/floater_model_preview.xml b/indra/newview/skins/default/xui/en/floater_model_preview.xml
index a4acd1df78..7183b2f1f9 100755
--- a/indra/newview/skins/default/xui/en/floater_model_preview.xml
+++ b/indra/newview/skins/default/xui/en/floater_model_preview.xml
@@ -31,6 +31,7 @@
<string name="mesh_status_too_many_vertices">Level of detail has too many vertices.</string>
<string name="mesh_status_missing_lod">Missing required level of detail.</string>
<string name="mesh_status_invalid_material_list">LOD materials are not a subset of reference model.</string>
+ <string name="phys_status_vertex_limit_exceeded">Some physical hulls exceed vertex limitations.</string>
<string name="layer_all">All</string> <!-- Text to display in physics layer combo box for "all layers" -->
<string name="decomposing">Analyzing...</string>
<string name="simplifying">Simplifying...</string>
@@ -66,7 +67,7 @@
follows="top|left"
layout="topleft"
height="19"
- max_length_bytes="64"
+ max_length_bytes="63"
name="description_form"
prevalidate_callback="ascii"
top_pad="5"
@@ -1027,19 +1028,19 @@
bg_alpha_color="0 0 0 0"
bg_opaque_color="0 0 0 0.3"
follows="left|top"
- height="16"
+ height="19"
layout="topleft"
left="18"
name="physics info"
- top_pad="15"
- width="589">
+ top_pad="12"
+ width="319">
<text
follows="top|left"
height="15"
layout="topleft"
left="0"
text_color="White"
- top_pad="0"
+ top_pad="3"
name="results_text"
width="50">
Results:
@@ -1077,6 +1078,33 @@
Hulls: [HULLS]
</text>
</panel>
+ <panel
+ bg_alpha_color="0 0 0 0"
+ bg_opaque_color="0 0 0 0.3"
+ follows="left|top"
+ height="19"
+ layout="topleft"
+ left_pad="5"
+ top_delta="0"
+ name="physics message"
+ width="270">
+ <icon
+ follows="left|top"
+ height="16"
+ left="0"
+ layout="topleft"
+ name="physics_status_message_icon"
+ top_pad="0"
+ width="16" />
+ <text
+ follows="left|top"
+ height="15"
+ layout="topleft"
+ left_pad="2"
+ name="physics_status_message_text"
+ width="252"
+ top_delta="3"/>
+ </panel>
</panel>
<!-- MODIFIERS PANEL -->
<panel
diff --git a/indra/newview/skins/default/xui/en/floater_notifications_tabbed.xml b/indra/newview/skins/default/xui/en/floater_notifications_tabbed.xml
new file mode 100644
index 0000000000..afc609de52
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_notifications_tabbed.xml
@@ -0,0 +1,154 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater
+ legacy_header_height="18"
+ bevel_style="in"
+ layout="topleft"
+ name="floater_notifications_tabbed"
+ help_topic="notification_chiclet"
+ save_rect="true"
+ title="NOTIFICATIONS"
+ width="350"
+ min_width="435"
+ height="550"
+ min_height="150"
+ can_minimize="false"
+ can_tear_off="false"
+ can_resize="true"
+ can_drag_on_left="false"
+ can_dock="true"
+ save_dock_state="true"
+ save_visibility="true"
+ single_instance="true"
+>
+ <floater.string
+ name="system_tab_title">
+ System ([COUNT])
+ </floater.string>
+ <floater.string
+ name="transactions_tab_title">
+ Transactions ([COUNT])
+ </floater.string>
+ <floater.string
+ name="group_invitations_tab_title">
+ Invitations ([COUNT])
+ </floater.string>
+ <floater.string
+ name="group_notices_tab_title">
+ Group ([COUNT])
+ </floater.string>
+
+ <string
+ name="title_notification_tabbed_window">
+ NOTIFICATIONS
+ </string>
+ <layout_stack
+ width="336"
+ height="533"
+ enabled="true"
+ orientation="vertical"
+ name="TabButtonsStack"
+ follows="left|top|right|bottom"
+ top="17">
+ <layout_panel
+ width="336"
+ height="530"
+ enabled="true"
+ name="TabButtonsLayoutPanel">
+ <tab_container
+ follows="left|top|right|bottom"
+ halign="center"
+ layout="topleft"
+ tab_position="top"
+ left="7"
+ top="7"
+ width="336"
+ height="491"
+ mouse_opaque="true"
+ name="notifications_tab_container">
+ <panel
+ border="true"
+ bevel_style="none"
+ follows="left|top|right|bottom"
+ label="System (0)"
+ layout="topleft"
+ name="system_notification_list_tab">
+ <notification_list_view
+ color="FloaterDefaultBackgroundColor"
+ follows="all"
+ layout="topleft"
+ name="system_notification_list"
+ left="0"
+ top="5"
+ height="0"
+ width="330"/>
+ </panel>
+ <panel
+ border="true"
+ bevel_style="none"
+ follows="left|top|right|bottom"
+ label="Transactions (0)"
+ layout="topleft"
+ name="transaction_notifications_tab">
+ <notification_list_view
+ color="FloaterDefaultBackgroundColor"
+ follows="all"
+ layout="topleft"
+ name="transaction_notification_list"
+ left="0"
+ top="5"
+ height="0"
+ width="328"/>
+ </panel>
+ <panel
+ border="true"
+ bevel_style="none"
+ follows="left|top|right|bottom"
+ label="Invitations (0)"
+ layout="topleft"
+ name="group_invite_notifications_tab">
+ <notification_list_view
+ color="FloaterDefaultBackgroundColor"
+ follows="all"
+ layout="topleft"
+ name="group_invite_notification_list"
+ left="0"
+ top="5"
+ height="0"
+ width="328"/>
+ </panel>
+ <panel
+ border="true"
+ bevel_style="none"
+ follows="left|top|right|bottom"
+ label="Group (0)"
+ layout="topleft"
+ name="group_notice_notifications_tab">
+ <notification_list_view
+ color="FloaterDefaultBackgroundColor"
+ follows="all"
+ layout="topleft"
+ name="group_notice_notification_list"
+ left="0"
+ top="5"
+ height="0"
+ width="328"/>
+ </panel>
+ </tab_container>
+
+ <layout_stack width="336" height="26" enabled="true" orientation="horizontal" follows="left|right" name="ButtonsStack">
+ <layout_panel width="336" height="30" enabled="true" orientation="horizontal" name="CondenseAllButtonPanel">
+ <button width="93" height="21" left="2" label="Collapse all" name="collapse_all_button">
+ </button>
+ </layout_panel>
+ <layout_panel width="336" height="30" enabled="true" orientation="horizontal" name="GapLayoutPanel">
+ <panel width="90" height="21" left="2" label="Gap Panel" border="false" name="GapPanel">
+ </panel>
+ </layout_panel>
+ <layout_panel width="336" height="30" enabled="true" orientation="horizontal" name="DeleteAllButtonPanel">
+ <button width="93" height="21" left="2" label="Delete all" name="delete_all_button">
+ </button>
+ </layout_panel>
+ </layout_stack>
+ </layout_panel>
+ </layout_stack>
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_sys_well.xml b/indra/newview/skins/default/xui/en/floater_sys_well.xml
index ecedb27438..2c5176cf01 100755
--- a/indra/newview/skins/default/xui/en/floater_sys_well.xml
+++ b/indra/newview/skins/default/xui/en/floater_sys_well.xml
@@ -23,10 +23,6 @@
name="title_im_well_window">
CONVERSATIONS
</string>
- <string
- name="title_notification_well_window">
- NOTIFICATIONS
- </string>
<flat_list_view
color="FloaterDefaultBackgroundColor"
diff --git a/indra/newview/skins/default/xui/en/menu_inventory.xml b/indra/newview/skins/default/xui/en/menu_inventory.xml
index 91adec0789..61002bf1b5 100755
--- a/indra/newview/skins/default/xui/en/menu_inventory.xml
+++ b/indra/newview/skins/default/xui/en/menu_inventory.xml
@@ -565,14 +565,6 @@
<menu_item_call
label="Delete"
layout="topleft"
- name="Remove Link">
- <menu_item_call.on_click
- function="Inventory.DoToSelected"
- parameter="delete" />
- </menu_item_call>
- <menu_item_call
- label="Delete"
- layout="topleft"
name="Delete">
<menu_item_call.on_click
function="Inventory.DoToSelected"
@@ -785,14 +777,6 @@
layout="topleft"
name="Marketplace Separator" />
<menu_item_call
- label="Copy to Merchant Outbox"
- layout="topleft"
- name="Merchant Copy">
- <menu_item_call.on_click
- function="Inventory.DoToSelected"
- parameter="copy_to_outbox" />
- </menu_item_call>
- <menu_item_call
label="Copy to Marketplace Listings"
layout="topleft"
name="Marketplace Copy">
diff --git a/indra/newview/skins/default/xui/en/menu_login.xml b/indra/newview/skins/default/xui/en/menu_login.xml
index e91eea04d1..73ca7c529d 100755
--- a/indra/newview/skins/default/xui/en/menu_login.xml
+++ b/indra/newview/skins/default/xui/en/menu_login.xml
@@ -108,6 +108,12 @@
function="Floater.Show"
parameter="sl_about" />
</menu_item_call>
+ <menu_item_call
+ label="Check for Updates"
+ name="Check for Updates">
+ <menu_item_call.on_click
+ function="Advanced.CheckViewerUpdates"/>
+ </menu_item_call>
</menu>
<menu_item_check
label="Show Debug Menu"
diff --git a/indra/newview/skins/default/xui/en/menu_url_email.xml b/indra/newview/skins/default/xui/en/menu_url_email.xml
new file mode 100644
index 0000000000..6467fe5c90
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/menu_url_email.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<context_menu
+ layout="topleft"
+ name="Email Popup">
+ <menu_item_call
+ label="Compose Email in an External client"
+ layout="topleft"
+ name="email_open_external">
+ <menu_item_call.on_click
+ function="Url.OpenExternal" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_call
+ label="Copy Email to clipboard"
+ layout="topleft"
+ name="email_copy">
+ <menu_item_call.on_click
+ function="Url.CopyLabel" />
+ </menu_item_call>
+</context_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml
index 2463c5f43b..f22986438c 100755
--- a/indra/newview/skins/default/xui/en/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/en/menu_viewer.xml
@@ -134,7 +134,7 @@
</menu_item_call>
<menu_item_call
label="Walk / run / fly..."
- name="Walk / run / fly">
+ name="WalkRunFly">
<menu_item_call.on_click
function="Floater.ToggleOrBringToFront"
parameter="moveview" />
@@ -173,13 +173,6 @@
<menu_item_call.on_click
function="BuyCurrency" />
</menu_item_call>
- <menu_item_call
- label="Merchant Outbox..."
- name="MerchantOutbox">
- <menu_item_call.on_click
- function="Floater.ToggleOrBringToFront"
- parameter="outbox" />
- </menu_item_call>
<menu_item_call
label="Marketplace listings..."
name="MarketplaceListings">
@@ -509,7 +502,7 @@
</menu_item_call>
<menu_item_call
label="Region / Estate"
- name="Region/Estate">
+ name="RegionEstate">
<menu_item_call.on_click
function="Floater.Show"
parameter="region_info" />
@@ -1438,7 +1431,7 @@
function="Floater.Show"
parameter="bumps" />
</menu_item_call>
- <menu_item_separator/>
+ <menu_item_separator/>
<menu_item_call
label="About [APP_NAME]"
name="About Second Life">
@@ -1446,6 +1439,12 @@
function="Floater.Show"
parameter="sl_about" />
</menu_item_call>
+ <menu_item_call
+ label="Check for Updates"
+ name="Check for Updates">
+ <menu_item_call.on_click
+ function="Advanced.CheckViewerUpdates"/>
+ </menu_item_call>
</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 f847c73287..f79e8103b6 100755
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -244,7 +244,7 @@ You don't have permission to copy one or more of these items to the Merchant Out
<notification
icon="OutboxStatus_Success"
name="OutboxFolderCreated"
- type="outbox">
+ type="alertmodal">
<unique/>
A new folder has been created for each item you have transferred into the top level of your Merchant Outbox.
@@ -257,7 +257,7 @@ A new folder has been created for each item you have transferred into the top le
<notification
icon="OutboxStatus_Success"
name="OutboxImportComplete"
- type="outbox">
+ type="alertmodal">
Success
All folders were successfully sent to the Marketplace.
@@ -271,7 +271,7 @@ All folders were successfully sent to the Marketplace.
<notification
icon="OutboxStatus_Warning"
name="OutboxImportHadErrors"
- type="outbox">
+ type="alertmodal">
Some folders did not transfer
Errors occurred when some folders were sent to the Marketplace. Those folders are still in your Merchant Outbox.
@@ -286,7 +286,7 @@ See the [[MARKETPLACE_IMPORTS_URL] error log] for more information.
<notification
icon="OutboxStatus_Error"
name="OutboxImportFailed"
- type="outbox">
+ type="alertmodal">
Transfer failed with error &apos;[ERROR_CODE]&apos;
No folders were sent to the Marketplace because of a system or network error. Try again later.
@@ -299,7 +299,7 @@ No folders were sent to the Marketplace because of a system or network error. T
<notification
icon="OutboxStatus_Error"
name="OutboxInitFailed"
- type="outbox">
+ type="alertmodal">
Marketplace initialization failed with error &apos;[ERROR_CODE]&apos;
Initialization with the Marketplace failed because of a system or network error. Try again later.
@@ -312,7 +312,7 @@ Initialization with the Marketplace failed because of a system or network error.
<notification
icon="OutboxStatus_Error"
name="StockPasteFailed"
- type="outbox">
+ type="alertmodal">
Copy or move to Stock Folder failed with error :
&apos;[ERROR_CODE]&apos;
@@ -325,7 +325,7 @@ Initialization with the Marketplace failed because of a system or network error.
<notification
icon="OutboxStatus_Error"
name="MerchantPasteFailed"
- type="outbox">
+ type="alertmodal">
Copy or move to Marketplace Listings failed with error :
&apos;[ERROR_CODE]&apos;
@@ -338,7 +338,7 @@ Initialization with the Marketplace failed because of a system or network error.
<notification
icon="OutboxStatus_Error"
name="MerchantTransactionFailed"
- type="outbox">
+ type="alertmodal">
The transaction with the Marketplace failed with the following error :
Reason : &apos;[ERROR_REASON]&apos;
@@ -352,7 +352,7 @@ Initialization with the Marketplace failed because of a system or network error.
<notification
icon="OutboxStatus_Error"
name="MerchantUnprocessableEntity"
- type="outbox">
+ type="alertmodal">
We are unable to list this product or activate the version folder. Usually this is caused by missing information in the listing description form, but it may be due to errors in the folder structure. Either edit the listing or check the listing folder for errors.
<usetemplate
@@ -363,7 +363,7 @@ Initialization with the Marketplace failed because of a system or network error.
<notification
icon="OutboxStatus_Error"
name="MerchantListingFailed"
- type="outbox">
+ type="alertmodal">
Listing to Marketplace failed with error :
&apos;[ERROR_CODE]&apos;
@@ -376,7 +376,7 @@ Initialization with the Marketplace failed because of a system or network error.
<notification
icon="OutboxStatus_Error"
name="MerchantFolderActivationFailed"
- type="outbox">
+ type="alertmodal">
Activating this version folder failed with error :
&apos;[ERROR_CODE]&apos;
@@ -819,6 +819,33 @@ If you no longer wish to have these abilities granted to this role, disable them
notext="Cancel"
yestext="Eject"/>
</notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="BanGroupMemberWarning"
+ type="alertmodal">
+ You are about to ban [AVATAR_NAME] from the group.
+ <tag>group</tag>
+ <tag>confirm</tag>
+ <usetemplate
+ ignoretext="Confirm banning a participant from group"
+ name="okcancelignore"
+ notext="Cancel"
+ yestext="Ban"/>
+ </notification>
+ <notification
+ icon="alertmodal.tga"
+ name="BanGroupMembersWarning"
+ type="alertmodal">
+ You are about to ban [COUNT] members from group.
+ <tag>group</tag>
+ <tag>confirm</tag>
+ <usetemplate
+ ignoretext="Confirm banning multiple members from group"
+ name="okcancelignore"
+ notext="Cancel"
+ yestext="Ban"/>
+ </notification>
<notification
icon="alertmodal.tga"
@@ -3892,6 +3919,53 @@ see [[INFO_URL] Information about this update]
name="okbutton"
yestext="OK"/>
</notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="UpdateDownloadInProgress"
+ type="alertmodal">
+An update is available!
+It's downloading in the background and we will prompt you to restart your viewer to finish installing it as soon as it's ready.
+ <tag>confirm</tag>
+ <usetemplate
+ name="okbutton"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="UpdateDownloadComplete"
+ type="alertmodal">
+An update was downloaded. It will be installed during restart.
+ <tag>confirm</tag>
+ <usetemplate
+ name="okbutton"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="UpdateCheckError"
+ type="alertmodal">
+An error occured while checking for update.
+Please try again later.
+ <tag>confirm</tag>
+ <usetemplate
+ name="okbutton"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="UpdateViewerUpToDate"
+ type="alertmodal">
+Your viewer is up to date!
+If you can't wait to try out the latest features and fixes, check out the Alternate Viewers page. http://wiki.secondlife.com/wiki/Linden_Lab_Official:Alternate_Viewers.
+ <tag>confirm</tag>
+ <usetemplate
+ name="okbutton"
+ yestext="OK"/>
+ </notification>
<notification
icon="alertmodal.tga"
@@ -4217,6 +4291,21 @@ You have reached your maximum number of groups. Please leave some group before j
<notification
icon="alert.tga"
+ name="GroupLimitInfo"
+ type="alert">
+The group limit for base accounts is [MAX_BASIC], and for [https://secondlife.com/premium/ premium]
+accounts is [MAX_PREMIUM].
+If you downgraded your account, you will need to get below [MAX_BASIC] group limit before you can join more.
+
+[https://secondlife.com/my/account/membership.php Upgrade today!]
+ <tag>group</tag>
+ <usetemplate
+ name="okbutton"
+ yestext="Close"/>
+ </notification>
+
+ <notification
+ icon="alert.tga"
name="KickUser"
type="alert">
<tag>win</tag>
@@ -7029,15 +7118,6 @@ No valid circuit code.
<notification
icon="notify.tga"
- name="NoValidTimestamp"
- persist="true"
- type="notify">
- <tag>fail</tag>
-No valid timestamp.
- </notification>
-
- <notification
- icon="notify.tga"
name="NoPendingConnection"
persist="true"
type="notify">
diff --git a/indra/newview/skins/default/xui/en/panel_experience_list_editor.xml b/indra/newview/skins/default/xui/en/panel_experience_list_editor.xml
index c76b958eda..c357f9e7d5 100644
--- a/indra/newview/skins/default/xui/en/panel_experience_list_editor.xml
+++ b/indra/newview/skins/default/xui/en/panel_experience_list_editor.xml
@@ -47,19 +47,19 @@
height="12"
follows="top|left">
</text>
- <scroll_list
+ <name_list
draw_heading="false"
left="3"
width="225"
height="75"
follows="all"
name="experience_list">
- <columns
+ <name_list.columns
width="225"
user_resize="false"
name="experience_name"
label="Name"/>
- </scroll_list>
+ </name_list>
<button
layout="topleft"
follows="top|right"
diff --git a/indra/newview/skins/default/xui/en/panel_main_inventory.xml b/indra/newview/skins/default/xui/en/panel_main_inventory.xml
index 0518688f45..0a85477bf4 100755
--- a/indra/newview/skins/default/xui/en/panel_main_inventory.xml
+++ b/indra/newview/skins/default/xui/en/panel_main_inventory.xml
@@ -21,7 +21,7 @@
</panel.string>
<panel.string
name="ItemcountUnknown">
-
+ Fetched [ITEM_COUNT] Items [FILTER]
</panel.string>
<text
type="string"
diff --git a/indra/newview/skins/default/xui/en/panel_notification_list_item.xml b/indra/newview/skins/default/xui/en/panel_notification_list_item.xml
new file mode 100644
index 0000000000..a909028f9f
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_notification_list_item.xml
@@ -0,0 +1,144 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<!-- All our XML is utf-8 encoded. -->
+<panel
+ translate="false"
+ name="main_panel"
+ title="panel_notification_list_item"
+ visible="true"
+ top="0"
+ left="0"
+ width="331"
+ height="202"
+ can_resize="true"
+ layout="topleft"
+ follows="left|top|right|bottom" >
+ <!-- background_opaque="false" -->
+ <!-- background_visible="true"> -->
+ <!-- bg_alpha_color="PanelNotificationListItem"> -->
+ <panel.string
+ name="sender_resident_text">
+ Sender: "[SENDER_RESIDENT]"
+ </panel.string>
+ <panel.string
+ name="group_name_text">
+ Group: "[GROUP_NAME]"
+ </panel.string>
+ <panel.string
+ name="group_fee_text">
+ Fee: [GROUP_FEE]
+ </panel.string>
+ <panel.string
+ name="item_condensed_height">
+ 50
+ </panel.string>
+ <panel.string
+ name="item_expanded_height">
+ 87
+ </panel.string>
+ <panel.string
+ name="expanded_height_resize_for_attachment">
+ 27
+ </panel.string>
+
+ <panel top="0" left="0" width="331" height="196" bevel_style="none" layout="topleft" follows="left|top|right|bottom" name="panel_total_view">
+ <layout_stack top="0" left="0" width="331" height="196" orientation="vertical" follows="left|top|right|bottom" name="item_vertical_stack">
+ <layout_panel top="0" left="0" height="30" follows="left|top|right|bottom" layout="topleft" name="layout_panel_condensed_view" visible="false" background_opaque="false" background_visible="true" bg_alpha_color="SysWellItemUnselected">
+ <panel border="true" top="0" left="5" height="30" bevel_style="none" layout="topleft" follows="left|top|right|bottom" name="panel_condensed_view">
+ <layout_stack top="0" left="0" width="325" height="50" orientation="horizontal" follows="left|top|right|bottom" name="horizontal_stack">
+ <layout_panel width="30" height="39" orientation="horizontal" follows="left|top|right|bottom" name="layout_panel_right">
+ <group_icon left="5" top="6" width="25" height="25" mouse_opaque="true" name="group_icon" tool_tip="Group" default_icon_name="Generic_Group" visible="true"/>
+ <avatar_icon left="5" top="6" width="25" height="25" mouse_opaque="true" name="avatar_icon" tool_tip="Avatar" default_icon_name="Generic_Person" visible="false"/>
+ <icon left="5" top="6" width="25" height="25" mouse_opaque="true" name="system_notification_icon" tool_tip="Icon" image_name="System_Notification" visible="false"/>
+ </layout_panel>
+ <layout_panel width="260" height="50" orientation="horizontal" name="layout_panel_middle">
+ <panel border="false" top="0" width="260" height="38" bevel_style="none" follows="left|top|right" layout="topleft" name="main_info_panel">
+ <panel border="false" top="0" left="0" width="260" height="19" bevel_style="none" follows="left|top|right|bottom" layout="topleft" name="notification_title_panel">
+ <text allow_scroll="false" font="SansSerifSmall" top="6" left="0" width="260" height="12" layout="topleft" follows="right|left" text_color="White"
+ use_ellipses="true" word_wrap="true" mouse_opaque="false" name="notification_title" >
+ Group Name:Notice Title N o t i c e T i t l e N o t i c e T i t l e N o t i c e T i t l e N oticeTitle
+ </text>
+ <icon top="1" left="242" width="21" height="21" image_name="Icon_Attachment_Small" follows="right" mouse_opaque="true" name="attachment_icon" tool_tip="Attachment" visible="false"/>
+ </panel>
+ <panel border="false" top="23" left="0" width="260" height="15" bevel_style="none" follows="left|top|right|bottom" layout="topleft" name="sender_time_panel">
+ <text allow_scroll="false" font="SansSerifSmall" top="0" left="0" width="170" height="13" layout="topleft" follows="right|left"
+ use_ellipses="true" word_wrap="false" mouse_opaque="false" name="sender_or_fee_box" visible="false">
+ Sender: "Resident R e s i d e n t R e s i d e n t"
+ </text>
+ <text allow_scroll="false" font="SansSerifSmall" top="0" right="-5" width="95" height="13" follows="right" halign="right" layout="topleft" left_pad="5"
+ name="notification_time" value="2014/12/24 23:30" />
+ </panel>
+ </panel>
+ </layout_panel>
+ <layout_panel width="18" height="48" orientation="horizontal" follows="right|top|bottom" name="layout_panel_right">
+ <panel top="0" left="0" width="17" height="39" follows="left|top|right|bottom" layout="topleft" name="close_expand_panel">
+ <button top="0" left="0" width="17" height="17" layout="topleft" follows="top" name="close_btn" mouse_opaque="true"
+ tab_stop="false" image_unselected="Icon_Close_Foreground" image_selected="Icon_Close_Press" />
+ <button bottom="-16" right="15" width="17" height="17" layout="topleft" follows="bottom" name="expand_btn" mouse_opaque="true"
+ tab_stop="false" image_unselected="Notification_Expand" image_selected="Notification_Expand" />
+ </panel>
+ </layout_panel>
+ </layout_stack>
+ </panel>
+ </layout_panel>
+ <layout_panel top="0" left="0" height="196" follows="left|top|right|bottom" layout="topleft" name="layout_panel_expanded_view" visible="true" background_opaque="false" background_visible="true" bg_alpha_color="SysWellItemUnselected">
+ <panel border="true" top="0" left="5" height="196" bevel_style="none" follows="left|top|right|bottom" layout="topleft" name="panel_expanded_view">
+ <layout_stack top="0" left="0" width="325" height="196" orientation="horizontal" follows="left|top|right|bottom" name="horizontal_stack">
+ <layout_panel width="30" height="170" orientation="horizontal" follows="left|top|bottom" name="layout_panel_right_exp">
+ <group_icon left="5" top="6" width="25" height="25" mouse_opaque="true" name="group_icon_exp" tool_tip="Group" default_icon_name="Generic_Group" visible="true"/>
+ <avatar_icon left="5" top="6" width="25" height="25" mouse_opaque="true" name="avatar_icon_exp" tool_tip="Avatar" default_icon_name="Generic_Person" visible="false"/>
+ <icon left="5" top="6" width="25" height="25" mouse_opaque="true" name="system_notification_icon_exp" tool_tip="Icon" image_name="System_Notification" visible="false"/>
+ <icon left="12" top="144" width="20" height="20" name="attachment_icon_exp" tool_tip="Attachment" image_name="Icon_Attachment_Large" follows="left" mouse_opaque="true" visible="false"/>
+ </layout_panel>
+ <layout_panel width="230" height="196" orientation="horizontal" follows="left|top|right|bottom" name="layout_panel_middle_exp">
+ <panel border="false" top="0" width="230" height="196" bevel_style="none" follows="left|top|right|bottom" layout="topleft" name="main_info_panel_expanded">
+ <panel border="false" top="0" left="0" width="230" height="30" bevel_style="none" follows="left|top|right" layout="topleft" name="notification_title_panel_exp" >
+ <text allow_scroll="false" font="SansSerif" top="6" left="0" width="233" height="10" layout="topleft" follows="right|left" text_color="White"
+ use_ellipses="true" word_wrap="false" mouse_opaque="false" name="notification_title_exp">
+ Notice Title Notice Title N o t i c e T i t l e N o t i c e T i t l e
+ </text>
+ <text allow_scroll="false" font="SansSerif" left="0" width="233" height="10" layout="topleft" follows="right|left" text_color="White"
+ use_ellipses="true" word_wrap="false" mouse_opaque="false" name="group_name_exp" parse_urls="false" visible="false">
+ Group Name Group Name Group Na m e e
+ </text>
+ </panel>
+ <panel border="false" left="0" width="230" height="15" bevel_style="none" follows="left|top|right" layout="topleft" name="sender_time_panel_exp">
+ <text allow_scroll="false" font="SansSerifSmall" top="0" left="0" width="145" height="13" layout="topleft" follows="right|left"
+ use_ellipses="true" word_wrap="false" mouse_opaque="false" name="sender_or_fee_box_exp" visible="false">
+ Sender: "Resident R e s i d e n t R e s i d e n t"
+ </text>
+ <text allow_scroll="false" font="SansSerifSmall" top="0" right="-1" width="95" height="13" follows="right" halign="right" layout="topleft" left_pad="5"
+ name="notification_time_exp" value="2014/12/24 23:30" />
+ </panel>
+ <panel border="false" left="0" height="115" width="230" bevel_style="none" follows="all" layout="topleft" name="notification_text_panel_exp" visible="true">
+ <chat_editor is_expandable="true" top="0" left="0" width="230" height="110" layout="topleft" follows="left|right"
+ word_wrap="true" max_length="65536" name="notification_text_exp" parse_urls="true">
+ Notice text goes here b l a b l a b l a b l a b l a b l a b l a b l a b l a b l a b l a b l a b l a b l a b l a b l a b l a b l a b l a b l a b l a b l a b l a b l a b l a b l a b l a b l a b l a b l a b l a bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla. bla bla bla bla bla bla bla bla bla bla bla bla bla .
+ </chat_editor>
+ </panel>
+ <panel border="false" left="1" bottom="-5" width="230" height="22" bevel_style="none" follows="left|right|bottom" layout="topleft" name="attachment_panel" visible="false">
+ <text allow_scroll="false" font="SansSerifSmall" top="4" left="5" width="220" height="12" layout="topleft" follows="left|top|right|bottom"
+ use_ellipses="true" word_wrap="true" max_length="96" name="attachment_text">
+ Attachment goes here b l a b l a b l a b l a b l a b l a b l a b l a b l a b l a b l a b l a b l a b l a b l a b l a b l a b l a b l a b l a b l a b l a b l a b l a b l a b l a b l a b l a b l a b l a b l a bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla. bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla .
+ </text>
+ </panel>
+ <panel border="false" left="1" bottom="-5" height="55" bevel_style="none" follows="left|right|bottom" layout="topleft" name="button_panel" visible="false">
+ <button top="2" left="0" width="65" height="23" layout="topleft" follows="left|top|bottom" name="join_btn" mouse_opaque="true" tab_stop="false" label = "Join"/>
+ <button top="2" left_pad="12" width="65" height="23" layout="topleft" follows="left|top|bottom" name="decline_btn" mouse_opaque="true" tab_stop="false" label = "Decline"/>
+ <button top="2" left_pad="12" width="65" height="23" layout="topleft" follows="left|top|bottom" name="info_btn" mouse_opaque="true" tab_stop="false" label = "Info"/>
+ </panel>
+ </panel>
+ </layout_panel>
+ <layout_panel width="18" orientation="horizontal" follows="right|top|bottom" name="layout_panel_left_exp">
+ <panel top="0" left="0" width="17" follows="left|top|right|bottom" layout="topleft" name="close_expand_panel_exp">
+ <button top="0" left="2" width="17" height="17" layout="topleft" follows="top" name="close_expanded_btn" mouse_opaque="true"
+ tab_stop="false" image_unselected="Icon_Close_Foreground" image_selected="Icon_Close_Press" />
+ <button bottom="5" left="0" width="17" height="17" layout="topleft" follows="bottom" name="condense_btn" mouse_opaque="true"
+ tab_stop="false" image_unselected="Notification_Condense" image_selected="Notification_Condense" />
+ </panel>
+ </layout_panel>
+ </layout_stack>
+ </panel>
+ </layout_panel>
+ </layout_stack>
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_people.xml b/indra/newview/skins/default/xui/en/panel_people.xml
index 2d4665c128..4fb8b9a67f 100755
--- a/indra/newview/skins/default/xui/en/panel_people.xml
+++ b/indra/newview/skins/default/xui/en/panel_people.xml
@@ -506,7 +506,7 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M
left="3"
use_ellipses="true"
name="groupcount">
- You belong to [COUNT] groups, and can join [REMAINING] more.
+ You belong to [COUNT] groups, and can join [REMAINING] more. [secondlife:/// Want more?]
</text>
<group_list
allow_select="true"
diff --git a/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml b/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml
index 2e778014c5..3e96160834 100755
--- a/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml
+++ b/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml
@@ -216,7 +216,7 @@
control_name="QAMode"
follows="top|left"
height="15"
- label="Show Developer Menu"
+ label="Show Develop Menu"
layout="topleft"
left="30"
name="show_develop_menu_check"
diff --git a/indra/newview/skins/default/xui/en/panel_preferences_setup.xml b/indra/newview/skins/default/xui/en/panel_preferences_setup.xml
index 1e9a1aa27c..b201e071ef 100755
--- a/indra/newview/skins/default/xui/en/panel_preferences_setup.xml
+++ b/indra/newview/skins/default/xui/en/panel_preferences_setup.xml
@@ -270,7 +270,7 @@
value="1" />
-->
<combo_box.item
- label="Download and install updates manually"
+ label="I will download and install updates manually"
name="Install_manual"
value="0" />
</combo_box>
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index b7e0cff146..4eb6e2462d 100755
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -238,6 +238,7 @@ Please try logging in again in a minute.</string>
<string name="TooltipMustSingleDrop">Only a single item can be dragged here</string>
<string name="TooltipTooManyWearables">You can't wear a folder containing more than [AMOUNT] items. You can change this limit in Advanced > Show Debug Settings > WearFolderLimit.</string>
<string name="TooltipPrice" value="L$[AMOUNT]: "/>
+ <string name="TooltipSLIcon">This links to a page on the official SecondLife.com or LindenLab.com domain.</string>
<string name="TooltipOutboxDragToWorld">You can't rez items from the Marketplace Listings folder</string>
<string name="TooltipOutboxWorn">You can't put items you are wearing in the Marketplace Listings folder</string>
@@ -277,6 +278,7 @@ Please try logging in again in a minute.</string>
<string name="TooltipMapUrl">Click to view this location on a map</string>
<string name="TooltipSLAPP">Click to run the secondlife:// command</string>
<string name="CurrentURL" value=" CurrentURL: [CurrentURL]" />
+ <string name="TooltipEmail">Click to compose an email</string>
<!-- text for SLURL labels -->
<string name="SLurlLabelTeleport">Teleport to</string>
diff --git a/indra/newview/skins/default/xui/en/widgets/notification_list_view.xml b/indra/newview/skins/default/xui/en/widgets/notification_list_view.xml
new file mode 100644
index 0000000000..150225af27
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/widgets/notification_list_view.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<notification_list_view
+ allow_select="false"
+ color="PanelFocusBackgroundColor"
+ item_pad="0"
+ keep_one_selected="false"
+ multi_select="false"
+ opaque="true">
+ <flat_list_view
+ color="FloaterDefaultBackgroundColor"
+ follows="all"
+ layout="topleft"
+ name="notification_list"
+ left="1"
+ top="20"
+ height="0"
+ width="318"/>
+</notification_list_view> \ No newline at end of file
diff --git a/indra/newview/skins/default/xui/es/menu_viewer.xml b/indra/newview/skins/default/xui/es/menu_viewer.xml
index 5118171d80..f6ebb498ec 100755
--- a/indra/newview/skins/default/xui/es/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/es/menu_viewer.xml
@@ -15,7 +15,7 @@
<menu_item_check label="Volar" name="Fly"/>
<menu_item_check label="Correr siempre" name="Always Run"/>
<menu_item_call label="Parar mis animaciones" name="Stop Animating My Avatar"/>
- <menu_item_call label="Caminar / Correr / Volar..." name="Walk / run / fly"/>
+ <menu_item_call label="Caminar / Correr / Volar..." name="WalkRunFly"/>
</menu>
<menu label="Estado" name="Status">
<menu_item_check label="Ausente" name="Away"/>
@@ -63,7 +63,7 @@
<menu_item_call label="Foto" name="Take Snapshot"/>
<menu_item_call label="Perfil del lugar" name="Place Profile"/>
<menu_item_call label="Acerca del terreno" name="About Land"/>
- <menu_item_call label="Región/Estado" name="Region/Estate"/>
+ <menu_item_call label="Región/Estado" name="RegionEstate"/>
<menu_item_call label="Mis terrenos..." name="My Land"/>
<menu_item_call label="Comprar este terreno" name="Buy Land"/>
<menu label="Mostrar" name="LandShow">
diff --git a/indra/newview/skins/default/xui/es/notifications.xml b/indra/newview/skins/default/xui/es/notifications.xml
index 9578e1b863..1e367b33fc 100755
--- a/indra/newview/skins/default/xui/es/notifications.xml
+++ b/indra/newview/skins/default/xui/es/notifications.xml
@@ -2796,9 +2796,6 @@ Por favor, vuelve a intentarlo en unos momentos.
<notification name="NoValidCircuit">
Circuito de código inválido.
</notification>
- <notification name="NoValidTimestamp">
- Fecha inválida.
- </notification>
<notification name="NoPendingConnection">
No se puede crear la conexión.
</notification>
diff --git a/indra/newview/skins/default/xui/fr/menu_viewer.xml b/indra/newview/skins/default/xui/fr/menu_viewer.xml
index 33b2ba6982..788cdbf856 100755
--- a/indra/newview/skins/default/xui/fr/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/fr/menu_viewer.xml
@@ -15,7 +15,7 @@
<menu_item_check label="Voler" name="Fly"/>
<menu_item_check label="Toujours courir" name="Always Run"/>
<menu_item_call label="Arrêter mon animation" name="Stop Animating My Avatar"/>
- <menu_item_call label="Marcher / Courir / Voler..." name="Walk / run / fly"/>
+ <menu_item_call label="Marcher / Courir / Voler..." name="WalkRunFly"/>
</menu>
<menu label="Statut" name="Status">
<menu_item_check label="Absent" name="Away"/>
@@ -64,7 +64,7 @@
<menu_item_call label="Photo" name="Take Snapshot"/>
<menu_item_call label="Profil du lieu" name="Place Profile"/>
<menu_item_call label="À propos du terrain" name="About Land"/>
- <menu_item_call label="Région/Domaine" name="Region/Estate"/>
+ <menu_item_call label="Région/Domaine" name="RegionEstate"/>
<menu_item_call label="Mes terrains..." name="My Land"/>
<menu_item_call label="Acheter ce terrain" name="Buy Land"/>
<menu label="Afficher" name="LandShow">
diff --git a/indra/newview/skins/default/xui/fr/notifications.xml b/indra/newview/skins/default/xui/fr/notifications.xml
index f13a80fe61..29e6fe1979 100755
--- a/indra/newview/skins/default/xui/fr/notifications.xml
+++ b/indra/newview/skins/default/xui/fr/notifications.xml
@@ -2788,9 +2788,6 @@ Veuillez réessayer dans quelques minutes.
<notification name="NoValidCircuit">
Aucun code de circuit valide.
</notification>
- <notification name="NoValidTimestamp">
- Timestamp non valide.
- </notification>
<notification name="NoPendingConnection">
Impossible de créer la connexion en attente.
</notification>
diff --git a/indra/newview/skins/default/xui/fr/panel_login.xml b/indra/newview/skins/default/xui/fr/panel_login.xml
index 40082cb265..2b8249c8a9 100755
--- a/indra/newview/skins/default/xui/fr/panel_login.xml
+++ b/indra/newview/skins/default/xui/fr/panel_login.xml
@@ -1,9 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<panel name="panel_login">
<panel.string name="forgot_password_url">http://secondlife.com/account/request.php?lang=fr</panel.string>
- <panel.string name="forgot_password_url">
- http://secondlife.com/account/request.php?lang=fr
- </panel.string>
<layout_stack name="ui_stack">
<layout_panel name="ui_container">
<combo_box label="Nom d&apos;utilisateur" name="username_combo" tool_tip="Nom d&apos;utilisateur que vous avez choisi lors de votre inscription (par exemple, bobsmith12 ou Steller Sunshine)."/>
diff --git a/indra/newview/skins/default/xui/it/menu_viewer.xml b/indra/newview/skins/default/xui/it/menu_viewer.xml
index 3f4c370ccd..18ddad5ee8 100755
--- a/indra/newview/skins/default/xui/it/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/it/menu_viewer.xml
@@ -15,7 +15,7 @@
<menu_item_check label="Vola" name="Fly"/>
<menu_item_check label="Corri sempre" name="Always Run"/>
<menu_item_call label="Ferma animazione" name="Stop Animating My Avatar"/>
- <menu_item_call label="Cammina / corri / vola..." name="Walk / run / fly"/>
+ <menu_item_call label="Cammina / corri / vola..." name="WalkRunFly"/>
</menu>
<menu label="Stato" name="Status">
<menu_item_check label="Assente" name="Away"/>
@@ -64,7 +64,7 @@
<menu_item_call label="Istantanea" name="Take Snapshot"/>
<menu_item_call label="Profilo del luogo" name="Place Profile"/>
<menu_item_call label="Informazioni sul terreno" name="About Land"/>
- <menu_item_call label="Regione/proprietà immobiliare" name="Region/Estate"/>
+ <menu_item_call label="Regione/proprietà immobiliare" name="RegionEstate"/>
<menu_item_call label="Terreni posseduti..." name="My Land"/>
<menu_item_call label="Acquista questo terreno" name="Buy Land"/>
<menu label="Mostra" name="LandShow">
diff --git a/indra/newview/skins/default/xui/it/notifications.xml b/indra/newview/skins/default/xui/it/notifications.xml
index 06f2b70dcf..61131b09c3 100755
--- a/indra/newview/skins/default/xui/it/notifications.xml
+++ b/indra/newview/skins/default/xui/it/notifications.xml
@@ -2793,9 +2793,6 @@ Riprova tra qualche istante.
<notification name="NoValidCircuit">
Nessun codice circuito valido.
</notification>
- <notification name="NoValidTimestamp">
- Nessuna data/timestamp valido.
- </notification>
<notification name="NoPendingConnection">
Impossibile creare la connessione in sospeso.
</notification>
diff --git a/indra/newview/skins/default/xui/ja/menu_viewer.xml b/indra/newview/skins/default/xui/ja/menu_viewer.xml
index 3f756c5f94..0384dc1efc 100755
--- a/indra/newview/skins/default/xui/ja/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/ja/menu_viewer.xml
@@ -15,7 +15,7 @@
<menu_item_check label="飛ぶ" name="Fly"/>
<menu_item_check label="常に走る" name="Always Run"/>
<menu_item_call label="私のアニメーションを停止する" name="Stop Animating My Avatar"/>
- <menu_item_call label="歩行/走行/飛行..." name="Walk / run / fly"/>
+ <menu_item_call label="歩行/走行/飛行..." name="WalkRunFly"/>
</menu>
<menu label="ログイン" name="Status">
<menu_item_check label="一時退席中" name="Away"/>
@@ -64,7 +64,7 @@
<menu_item_call label="スナップショット" name="Take Snapshot"/>
<menu_item_call label="場所のプロフィール" name="Place Profile"/>
<menu_item_call label="土地情報" name="About Land"/>
- <menu_item_call label="地域 / 不動産" name="Region/Estate"/>
+ <menu_item_call label="地域 / 不動産" name="RegionEstate"/>
<menu_item_call label="保有地..." name="My Land"/>
<menu_item_call label="この土地を購入" name="Buy Land"/>
<menu label="表示" name="LandShow">
diff --git a/indra/newview/skins/default/xui/ja/notifications.xml b/indra/newview/skins/default/xui/ja/notifications.xml
index 694f38467e..5f0ce7a73b 100755
--- a/indra/newview/skins/default/xui/ja/notifications.xml
+++ b/indra/newview/skins/default/xui/ja/notifications.xml
@@ -2836,9 +2836,6 @@ Web ページにリンクすると、他人がこの場所に簡単にアクセ
<notification name="NoValidCircuit">
回路コードが無効です。
</notification>
- <notification name="NoValidTimestamp">
- タイムスタンプが無効です。
- </notification>
<notification name="NoPendingConnection">
接続を生成できません。
</notification>
diff --git a/indra/newview/skins/default/xui/pl/menu_viewer.xml b/indra/newview/skins/default/xui/pl/menu_viewer.xml
index ef3fe71945..6fd498eea8 100755
--- a/indra/newview/skins/default/xui/pl/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/pl/menu_viewer.xml
@@ -33,7 +33,7 @@
<menu_item_call label="Zrób zdjęcie" name="Take Snapshot"/>
<menu_item_call label="Profil miejsca" name="Place Profile"/>
<menu_item_call label="O posiadłości" name="About Land"/>
- <menu_item_call label="Region/Majątek" name="Region/Estate"/>
+ <menu_item_call label="Region/Majątek" name="RegionEstate"/>
<menu_item_call label="Moje posiadłości" name="My Land"/>
<menu_item_call label="Kup posiadłość" name="Buy Land"/>
<menu label="Pokaż" name="LandShow">
diff --git a/indra/newview/skins/default/xui/pl/notifications.xml b/indra/newview/skins/default/xui/pl/notifications.xml
index 62fda0d601..c4a65d92b4 100755
--- a/indra/newview/skins/default/xui/pl/notifications.xml
+++ b/indra/newview/skins/default/xui/pl/notifications.xml
@@ -2368,9 +2368,6 @@ Spróbuj ponowanie za kilka minut.
<notification name="NoValidCircuit">
Nieważny obwód kodowania.
</notification>
- <notification name="NoValidTimestamp">
- Niewłaściwy czas zapisu.
- </notification>
<notification name="NoPendingConnection">
Brak możliwości wykonania połączenia.
</notification>
diff --git a/indra/newview/skins/default/xui/pt/menu_viewer.xml b/indra/newview/skins/default/xui/pt/menu_viewer.xml
index 9b3b6077ed..3d5d9eccc6 100755
--- a/indra/newview/skins/default/xui/pt/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/pt/menu_viewer.xml
@@ -15,7 +15,7 @@
<menu_item_check label="Voar" name="Fly"/>
<menu_item_check label="Correr sempre" name="Always Run"/>
<menu_item_call label="Parar minha animação" name="Stop Animating My Avatar"/>
- <menu_item_call label="Andar/correr/voar..." name="Walk / run / fly"/>
+ <menu_item_call label="Andar/correr/voar..." name="WalkRunFly"/>
</menu>
<menu label="Status" name="Status">
<menu_item_check label="Ausente" name="Away"/>
@@ -64,7 +64,7 @@
<menu_item_call label="Foto" name="Take Snapshot"/>
<menu_item_call label="Perfil da região" name="Place Profile"/>
<menu_item_call label="Sobre terrenos" name="About Land"/>
- <menu_item_call label="Região/Propriedade" name="Region/Estate"/>
+ <menu_item_call label="Região/Propriedade" name="RegionEstate"/>
<menu_item_call label="Meus terrenos..." name="My Land"/>
<menu_item_call label="Comprar este terreno" name="Buy Land"/>
<menu label="Mostrar" name="LandShow">
diff --git a/indra/newview/skins/default/xui/pt/notifications.xml b/indra/newview/skins/default/xui/pt/notifications.xml
index 29b85d9e97..a264495404 100755
--- a/indra/newview/skins/default/xui/pt/notifications.xml
+++ b/indra/newview/skins/default/xui/pt/notifications.xml
@@ -2777,9 +2777,6 @@ Por favor, tente novamente em alguns instantes.
<notification name="NoValidCircuit">
Código de circuito inválido.
</notification>
- <notification name="NoValidTimestamp">
- Hora inválida.
- </notification>
<notification name="NoPendingConnection">
Impossível criar a conexão pendente.
</notification>
diff --git a/indra/newview/skins/default/xui/ru/menu_viewer.xml b/indra/newview/skins/default/xui/ru/menu_viewer.xml
index 958105a70f..d22ca845f9 100755
--- a/indra/newview/skins/default/xui/ru/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/ru/menu_viewer.xml
@@ -15,7 +15,7 @@
<menu_item_check label="Полет" name="Fly"/>
<menu_item_check label="Всегда бегать" name="Always Run"/>
<menu_item_call label="Остановить анимацию" name="Stop Animating My Avatar"/>
- <menu_item_call label="Ходьба / бег / полет..." name="Walk / run / fly"/>
+ <menu_item_call label="Ходьба / бег / полет..." name="WalkRunFly"/>
</menu>
<menu label="Статус" name="Status">
<menu_item_check label="Нет на месте" name="Away"/>
@@ -62,7 +62,7 @@
<menu_item_call label="Снимок" name="Take Snapshot"/>
<menu_item_call label="Профиль места" name="Place Profile"/>
<menu_item_call label="О земле" name="About Land"/>
- <menu_item_call label="Регион/землевладение" name="Region/Estate"/>
+ <menu_item_call label="Регион/землевладение" name="RegionEstate"/>
<menu_item_call label="Мои владения..." name="My Land"/>
<menu_item_call label="Купить эту землю" name="Buy Land"/>
<menu label="Показать" name="LandShow">
diff --git a/indra/newview/skins/default/xui/ru/notifications.xml b/indra/newview/skins/default/xui/ru/notifications.xml
index acf3ce608f..70b9a25590 100755
--- a/indra/newview/skins/default/xui/ru/notifications.xml
+++ b/indra/newview/skins/default/xui/ru/notifications.xml
@@ -2788,9 +2788,6 @@ http://secondlife.com/download.
<notification name="NoValidCircuit">
Нет подходящего кода канала.
</notification>
- <notification name="NoValidTimestamp">
- Нет подходящей метки времени.
- </notification>
<notification name="NoPendingConnection">
Невозможно создать отложенное соединение.
</notification>
diff --git a/indra/newview/skins/default/xui/tr/menu_viewer.xml b/indra/newview/skins/default/xui/tr/menu_viewer.xml
index cc8d8c895b..cea57011dd 100755
--- a/indra/newview/skins/default/xui/tr/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/tr/menu_viewer.xml
@@ -15,7 +15,7 @@
<menu_item_check label="Uç" name="Fly"/>
<menu_item_check label="Daima Koş" name="Always Run"/>
<menu_item_call label="Beni Anime Etmeyi Durdur" name="Stop Animating My Avatar"/>
- <menu_item_call label="Yürü / koş / uç..." name="Walk / run / fly"/>
+ <menu_item_call label="Yürü / koş / uç..." name="WalkRunFly"/>
</menu>
<menu label="Durum" name="Status">
<menu_item_check label="Uzakta" name="Away"/>
@@ -62,7 +62,7 @@
<menu_item_call label="Anlık Görüntü" name="Take Snapshot"/>
<menu_item_call label="Profili yerleştir" name="Place Profile"/>
<menu_item_call label="Arazi hakkında" name="About Land"/>
- <menu_item_call label="Bölge / Gayrimenkul" name="Region/Estate"/>
+ <menu_item_call label="Bölge / Gayrimenkul" name="RegionEstate"/>
<menu_item_call label="Sahip olduğum arazi parçaları..." name="My Land"/>
<menu_item_call label="Bu araziyi satın al" name="Buy Land"/>
<menu label="Göster" name="LandShow">
diff --git a/indra/newview/skins/default/xui/tr/notifications.xml b/indra/newview/skins/default/xui/tr/notifications.xml
index a6c69c7ab2..df22251b3d 100755
--- a/indra/newview/skins/default/xui/tr/notifications.xml
+++ b/indra/newview/skins/default/xui/tr/notifications.xml
@@ -2788,9 +2788,6 @@ Lütfen biraz sonra tekrar deneyin.
<notification name="NoValidCircuit">
Geçerli bir devre kodu yok.
</notification>
- <notification name="NoValidTimestamp">
- Geçerli bir zaman damgası yok.
- </notification>
<notification name="NoPendingConnection">
Beklemedeki bağlantı oluşturulamıyor.
</notification>
diff --git a/indra/newview/skins/default/xui/zh/menu_viewer.xml b/indra/newview/skins/default/xui/zh/menu_viewer.xml
index e94f52a401..9572ad49d3 100755
--- a/indra/newview/skins/default/xui/zh/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/zh/menu_viewer.xml
@@ -15,7 +15,7 @@
<menu_item_check label="飛行" name="Fly"/>
<menu_item_check label="以跑代步" name="Always Run"/>
<menu_item_call label="停止我身上的動作" name="Stop Animating My Avatar"/>
- <menu_item_call label="行走 / 跑步 / 飛行…" name="Walk / run / fly"/>
+ <menu_item_call label="行走 / 跑步 / 飛行…" name="WalkRunFly"/>
</menu>
<menu label="狀態" name="Status">
<menu_item_check label="離開" name="Away"/>
@@ -62,7 +62,7 @@
<menu_item_call label="快照" name="Take Snapshot"/>
<menu_item_call label="地點小檔案" name="Place Profile"/>
<menu_item_call label="土地資料" name="About Land"/>
- <menu_item_call label="地區/領地" name="Region/Estate"/>
+ <menu_item_call label="地區/領地" name="RegionEstate"/>
<menu_item_call label="我所擁有的土地…" name="My Land"/>
<menu_item_call label="購買這塊土地" name="Buy Land"/>
<menu label="顯示" name="LandShow">
diff --git a/indra/newview/skins/default/xui/zh/notifications.xml b/indra/newview/skins/default/xui/zh/notifications.xml
index 179f01e90d..0a98101b60 100755
--- a/indra/newview/skins/default/xui/zh/notifications.xml
+++ b/indra/newview/skins/default/xui/zh/notifications.xml
@@ -2778,9 +2778,6 @@ SHA1 指紋:[MD5_DIGEST]
<notification name="NoValidCircuit">
沒有有效的線路碼。
</notification>
- <notification name="NoValidTimestamp">
- 沒有有效的時間戳記。
- </notification>
<notification name="NoPendingConnection">
無法建立待通的連線。
</notification>
diff --git a/indra/newview/tests/llhttpretrypolicy_test.cpp b/indra/newview/tests/llhttpretrypolicy_test.cpp
index 8bd6cc2690..21c83184dc 100755
--- a/indra/newview/tests/llhttpretrypolicy_test.cpp
+++ b/indra/newview/tests/llhttpretrypolicy_test.cpp
@@ -234,13 +234,13 @@ void RetryPolicyTestObject::test<6>()
std::string str1("0");
seconds_to_wait = F32_MAX;
- success = getSecondsUntilRetryAfter(str1, seconds_to_wait);
+ success = LLAdaptiveRetryPolicy::getSecondsUntilRetryAfter(str1, seconds_to_wait);
ensure("parse 1", success);
ensure_equals("parse 1", seconds_to_wait, 0.0);
std::string str2("999.9");
seconds_to_wait = F32_MAX;
- success = getSecondsUntilRetryAfter(str2, seconds_to_wait);
+ success = LLAdaptiveRetryPolicy::getSecondsUntilRetryAfter(str2, seconds_to_wait);
ensure("parse 2", success);
ensure_approximately_equals("parse 2", seconds_to_wait, 999.9F, 8);
@@ -248,7 +248,7 @@ void RetryPolicyTestObject::test<6>()
time(&nowseconds);
std::string str3 = LLDate((F64)(nowseconds+44)).asRFC1123();
seconds_to_wait = F32_MAX;
- success = getSecondsUntilRetryAfter(str3, seconds_to_wait);
+ success = LLAdaptiveRetryPolicy::getSecondsUntilRetryAfter(str3, seconds_to_wait);
std::cerr << " str3 [" << str3 << "]" << std::endl;
ensure("parse 3", success);
ensure_approximately_equals_range("parse 3", seconds_to_wait, 44.0F, 2.0F);
diff --git a/indra/newview/tests/lltranslate_test.cpp b/indra/newview/tests/lltranslate_test.cpp
deleted file mode 100755
index 5e73dbb981..0000000000
--- a/indra/newview/tests/lltranslate_test.cpp
+++ /dev/null
@@ -1,340 +0,0 @@
-/**
- * @file lltranslate_test.cpp
- *
- * $LicenseInfo:firstyear=2011&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2011, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#include "linden_common.h"
-
-#include "../test/lltut.h"
-#include "../lltranslate.h"
-#include "../llversioninfo.h"
-#include "../llviewercontrol.h"
-
-#include "llbufferstream.h"
-#include "lltrans.h"
-#include "llui.h"
-
-#include "../../llmessage/llhttpconstants.cpp"
-
-static const std::string GOOGLE_VALID_RESPONSE1 =
-"{\
- \"data\": {\
- \"translations\": [\
- {\
- \"translatedText\": \"привет\",\
- \"detectedSourceLanguage\": \"es\"\
- }\
- ]\
- }\
-}";
-
-static const std::string GOOGLE_VALID_RESPONSE2 =
-"{\
- \"data\": {\
- \"translations\": [\
- {\
- \"translatedText\": \"привет\"\
- }\
- ]\
- }\
-}\
-";
-
-static const std::string GOOGLE_VALID_RESPONSE3 =
-"{\
- \"error\": {\
- \"errors\": [\
- {\
- \"domain\": \"global\",\
- \"reason\": \"invalid\",\
- \"message\": \"Invalid Value\"\
- }\
- ],\
- \"code\": 400,\
- \"message\": \"Invalid Value\"\
- }\
-}";
-
-static const std::string BING_VALID_RESPONSE1 =
-"<string xmlns=\"http://schemas.microsoft.com/2003/10/Serialization/\">Привет</string>";
-
-static const std::string BING_VALID_RESPONSE2 =
-"<html><body><h1>Argument Exception</h1><p>Method: Translate()</p><p>Parameter: </p>\
-<p>Message: 'from' must be a valid language</p><code></code>\
-<p>message id=3743.V2_Rest.Translate.58E8454F</p></body></html>";
-
-static const std::string BING_VALID_RESPONSE3 =
-"<html><body><h1>Argument Exception</h1><p>Method: Translate()</p>\
-<p>Parameter: appId</p><p>Message: Invalid appId&#xD;\nParameter name: appId</p>\
-<code></code><p>message id=3737.V2_Rest.Translate.56016759</p></body></html>";
-
-namespace tut
-{
- class translate_test
- {
- protected:
- void test_translation(
- LLTranslationAPIHandler& handler,
- int status, const std::string& resp,
- const std::string& exp_trans, const std::string& exp_lang, const std::string& exp_err)
- {
- std::string translation, detected_lang, err_msg;
- bool rc = handler.parseResponse(status, resp, translation, detected_lang, err_msg);
- ensure_equals("rc", rc, (status == 200));
- ensure_equals("err_msg", err_msg, exp_err);
- ensure_equals("translation", translation, exp_trans);
- ensure_equals("detected_lang", detected_lang, exp_lang);
- }
-
- LLGoogleTranslationHandler mGoogle;
- LLBingTranslationHandler mBing;
- };
-
- typedef test_group<translate_test> translate_test_group_t;
- typedef translate_test_group_t::object translate_test_object_t;
- tut::translate_test_group_t tut_translate("LLTranslate");
-
- template<> template<>
- void translate_test_object_t::test<1>()
- {
- test_translation(mGoogle, 200, GOOGLE_VALID_RESPONSE1, "привет", "es", "");
- }
-
- template<> template<>
- void translate_test_object_t::test<2>()
- {
- test_translation(mGoogle, 200, GOOGLE_VALID_RESPONSE2, "привет", "", "");
- }
-
- template<> template<>
- void translate_test_object_t::test<3>()
- {
- test_translation(mGoogle, 400, GOOGLE_VALID_RESPONSE3, "", "", "Invalid Value");
- }
-
- template<> template<>
- void translate_test_object_t::test<4>()
- {
- test_translation(mGoogle, 400,
- "",
- "", "", "* Line 1, Column 1\n Syntax error: value, object or array expected.\n");
- }
-
- template<> template<>
- void translate_test_object_t::test<5>()
- {
- test_translation(mGoogle, 400,
- "[]",
- "", "", "");
- }
-
- template<> template<>
- void translate_test_object_t::test<6>()
- {
- test_translation(mGoogle, 400,
- "{\"oops\": \"invalid\"}",
- "", "", "");
- }
-
- template<> template<>
- void translate_test_object_t::test<7>()
- {
- test_translation(mGoogle, 400,
- "{\"data\": {}}",
- "", "", "");
- }
-
- template<> template<>
- void translate_test_object_t::test<8>()
- {
- test_translation(mGoogle, 400,
- "{\"data\": { \"translations\": [ {} ] }}",
- "", "", "");
- }
-
- template<> template<>
- void translate_test_object_t::test<9>()
- {
- test_translation(mGoogle, 400,
- "{\"data\": { \"translations\": [ { \"translatedTextZZZ\": \"привет\", \"detectedSourceLanguageZZZ\": \"es\" } ] }}",
- "", "", "");
- }
-
- template<> template<>
- void translate_test_object_t::test<10>()
- {
- test_translation(mBing, 200, BING_VALID_RESPONSE1, "Привет", "", "");
- }
-
- template<> template<>
- void translate_test_object_t::test<11>()
- {
- test_translation(mBing, 400, BING_VALID_RESPONSE2, "", "", "'from' must be a valid language");
- }
-
- template<> template<>
- void translate_test_object_t::test<12>()
- {
- test_translation(mBing, 400, BING_VALID_RESPONSE3, "", "", "Invalid appId\nParameter name: appId");
- }
-
- template<> template<>
- void translate_test_object_t::test<13>()
- {
- test_translation(mBing, 200,
- "Привет</string>",
- "Привет", "", "");
- }
-
- template<> template<>
- void translate_test_object_t::test<14>()
- {
- test_translation(mBing, 200,
- "<string xmlns=\"http://schemas.microsoft.com/2003/10/Serialization/\">Привет",
- "Привет", "", "");
- }
-
- template<> template<>
- void translate_test_object_t::test<15>()
- {
- test_translation(mBing, 200,
- "Привет",
- "Привет", "", "");
- }
-
- template<> template<>
- void translate_test_object_t::test<16>()
- {
- test_translation(mBing, 400,
- "Message: some error</p>",
- "", "", "some error");
- }
-
- template<> template<>
- void translate_test_object_t::test<17>()
- {
- test_translation(mBing, 400,
- "Message: some error",
- "", "", "some error");
- }
-
- template<> template<>
- void translate_test_object_t::test<18>()
- {
- test_translation(mBing, 400,
- "some error</p>",
- "", "", "some error");
- }
-
- template<> template<>
- void translate_test_object_t::test<19>()
- {
- test_translation(mBing, 400,
- "some error",
- "", "", "some error");
- }
-
- template<> template<>
- void translate_test_object_t::test<20>()
- {
- std::string url;
- mBing.getTranslateURL(url, "en", "es", "hi");
- ensure_equals("bing URL", url,
- "http://api.microsofttranslator.com/v2/Http.svc/Translate?appId=dummy&text=hi&to=es&from=en");
- }
-
- template<> template<>
- void translate_test_object_t::test<21>()
- {
- std::string url;
- mBing.getTranslateURL(url, "", "es", "hi");
- ensure_equals("bing URL", url,
- "http://api.microsofttranslator.com/v2/Http.svc/Translate?appId=dummy&text=hi&to=es");
- }
-
- template<> template<>
- void translate_test_object_t::test<22>()
- {
- std::string url;
- mGoogle.getTranslateURL(url, "en", "es", "hi");
- ensure_equals("google URL", url,
- "https://www.googleapis.com/language/translate/v2?key=dummy&q=hi&target=es&source=en");
- }
-
- template<> template<>
- void translate_test_object_t::test<23>()
- {
- std::string url;
- mGoogle.getTranslateURL(url, "", "es", "hi");
- ensure_equals("google URL", url,
- "https://www.googleapis.com/language/translate/v2?key=dummy&q=hi&target=es");
- }
-}
-
-//== Misc stubs ===============================================================
-LLControlGroup gSavedSettings("test");
-
-std::string LLUI::getLanguage() { return "en"; }
-std::string LLTrans::getString(const std::string &xml_desc, const LLStringUtil::format_map_t& args) { return "dummy"; }
-
-LLControlGroup::LLControlGroup(const std::string& name) : LLInstanceTracker<LLControlGroup, std::string>(name) {}
-std::string LLControlGroup::getString(const std::string& name) { return "dummy"; }
-LLControlGroup::~LLControlGroup() {}
-
-LLCurl::Responder::Responder() {}
-void LLCurl::Responder::httpFailure() { }
-void LLCurl::Responder::httpSuccess() { }
-void LLCurl::Responder::httpCompleted() { }
-void LLCurl::Responder::completedRaw(LLChannelDescriptors const &,boost::shared_ptr<LLBufferArray> const &) { }
-LLCurl::Responder::~Responder() {}
-
-void LLHTTPClient::get(const std::string&, const LLSD&, ResponderPtr, const LLSD&, const F32, bool) {}
-void LLHTTPClient::get(const std::string&, LLPointer<LLCurl::Responder>, const LLSD&, const F32, bool) {}
-
-LLBufferStream::LLBufferStream(const LLChannelDescriptors& channels, LLBufferArray* buffer)
-: std::iostream(&mStreamBuf), mStreamBuf(channels, buffer) {}
-LLBufferStream::~LLBufferStream() {}
-
-LLBufferStreamBuf::LLBufferStreamBuf(const LLChannelDescriptors&, LLBufferArray*) {}
-#if( LL_WINDOWS || __GNUC__ > 2)
-LLBufferStreamBuf::pos_type LLBufferStreamBuf::seekoff(
- off_type off,
- std::ios::seekdir way,
- std::ios::openmode which)
-#else
-streampos LLBufferStreamBuf::seekoff(
- streamoff off,
- std::ios::seekdir way,
- std::ios::openmode which)
-#endif
-{ return 0; }
-int LLBufferStreamBuf::sync() {return 0;}
-int LLBufferStreamBuf::underflow() {return 0;}
-int LLBufferStreamBuf::overflow(int) {return 0;}
-LLBufferStreamBuf::~LLBufferStreamBuf() {}
-
-S32 LLVersionInfo::getBuild() { return 0; }
-const std::string& LLVersionInfo::getChannel() {static std::string dummy; return dummy;}
-S32 LLVersionInfo::getMajor() { return 0; }
-S32 LLVersionInfo::getMinor() { return 0; }
-S32 LLVersionInfo::getPatch() { return 0; }