summaryrefslogtreecommitdiff
path: root/indra
diff options
context:
space:
mode:
Diffstat (limited to 'indra')
-rw-r--r--indra/llcommon/CMakeLists.txt2
-rw-r--r--indra/llcommon/llavatarname.cpp119
-rw-r--r--indra/llcommon/llavatarname.h101
-rw-r--r--indra/llcommon/llchat.h3
-rw-r--r--indra/llcommon/llqueuedthread.cpp5
-rw-r--r--indra/llcommon/llstring.cpp11
-rw-r--r--indra/llinventory/lltransactionflags.cpp6
-rw-r--r--indra/llmessage/CMakeLists.txt3
-rw-r--r--indra/llmessage/llavatarnamecache.cpp795
-rw-r--r--indra/llmessage/llavatarnamecache.h103
-rw-r--r--indra/llmessage/llcachename.cpp227
-rw-r--r--indra/llmessage/llcachename.h51
-rw-r--r--indra/llmessage/mean_collision_data.h5
-rw-r--r--indra/llmessage/tests/llavatarnamecache_test.cpp109
-rw-r--r--indra/llui/llcombobox.cpp10
-rw-r--r--indra/llui/llcombobox.h7
-rw-r--r--indra/llui/llnotifications.cpp50
-rw-r--r--indra/llui/llnotifications.h17
-rw-r--r--indra/llui/llstyle.cpp6
-rw-r--r--indra/llui/llstyle.h2
-rw-r--r--indra/llui/lltextbase.cpp134
-rw-r--r--indra/llui/lltextbase.h6
-rw-r--r--indra/llui/llurlentry.cpp301
-rw-r--r--indra/llui/llurlentry.h90
-rw-r--r--indra/llui/llurlmatch.cpp11
-rw-r--r--indra/llui/llurlmatch.h21
-rw-r--r--indra/llui/llurlregistry.cpp20
-rw-r--r--indra/llui/llurlregistry.h8
-rw-r--r--indra/llui/tests/llurlentry_stub.cpp127
-rw-r--r--indra/llui/tests/llurlentry_test.cpp21
-rw-r--r--indra/llui/tests/llurlmatch_test.cpp154
-rw-r--r--indra/newview/CMakeLists.txt4
-rw-r--r--indra/newview/app_settings/settings.xml52
-rw-r--r--indra/newview/llagent.cpp3
-rw-r--r--indra/newview/llagentui.cpp23
-rw-r--r--indra/newview/llagentui.h1
-rw-r--r--indra/newview/llappviewer.cpp92
-rw-r--r--indra/newview/llappviewer.h2
-rw-r--r--indra/newview/llavataractions.cpp140
-rw-r--r--indra/newview/llavataractions.h1
-rw-r--r--indra/newview/llavatariconctrl.cpp33
-rw-r--r--indra/newview/llavatariconctrl.h14
-rw-r--r--indra/newview/llavatarlist.cpp36
-rw-r--r--indra/newview/llavatarlist.h1
-rw-r--r--indra/newview/llavatarlistitem.cpp25
-rw-r--r--indra/newview/llavatarlistitem.h9
-rw-r--r--indra/newview/llcallfloater.cpp42
-rw-r--r--indra/newview/llcallfloater.h5
-rw-r--r--indra/newview/llcallingcard.cpp114
-rw-r--r--indra/newview/llcallingcard.h9
-rw-r--r--indra/newview/llchathistory.cpp80
-rw-r--r--indra/newview/lldateutil.cpp20
-rw-r--r--indra/newview/lldateutil.h8
-rw-r--r--indra/newview/lldrawable.h1
-rw-r--r--indra/newview/llfloateravatarpicker.cpp173
-rw-r--r--indra/newview/llfloateravatarpicker.h4
-rw-r--r--indra/newview/llfloateravatartextures.cpp9
-rw-r--r--indra/newview/llfloaterbump.cpp5
-rw-r--r--indra/newview/llfloaterbuyland.cpp19
-rw-r--r--indra/newview/llfloatergodtools.cpp5
-rw-r--r--indra/newview/llfloatergodtools.h3
-rw-r--r--indra/newview/llfloaterinspect.cpp10
-rw-r--r--indra/newview/llfloaterland.cpp34
-rw-r--r--indra/newview/llfloaterland.h4
-rw-r--r--indra/newview/llfloaterpay.cpp34
-rw-r--r--indra/newview/llfloaterpreference.cpp19
-rw-r--r--indra/newview/llfloaterregioninfo.cpp41
-rw-r--r--indra/newview/llfloaterregioninfo.h9
-rw-r--r--indra/newview/llfloaterreporter.cpp58
-rw-r--r--indra/newview/llfloaterreporter.h6
-rw-r--r--indra/newview/llfloaterscriptlimits.cpp50
-rw-r--r--indra/newview/llfloaterscriptlimits.h4
-rw-r--r--indra/newview/llfloatersellland.cpp22
-rw-r--r--indra/newview/llfloatertopobjects.cpp66
-rw-r--r--indra/newview/llfolderview.h2
-rw-r--r--indra/newview/llfoldervieweventlistener.h2
-rw-r--r--indra/newview/llfolderviewitem.h2
-rw-r--r--indra/newview/llfriendcard.cpp10
-rw-r--r--indra/newview/llglsandbox.cpp3
-rw-r--r--indra/newview/llhudicon.h1
-rw-r--r--indra/newview/llhudnametag.cpp1072
-rw-r--r--indra/newview/llhudnametag.h191
-rw-r--r--indra/newview/llhudobject.cpp18
-rw-r--r--indra/newview/llhudobject.h9
-rw-r--r--indra/newview/llhudtext.cpp642
-rw-r--r--indra/newview/llhudtext.h50
-rw-r--r--indra/newview/llimfloater.cpp36
-rw-r--r--indra/newview/llimfloater.h7
-rw-r--r--indra/newview/llimview.cpp121
-rw-r--r--indra/newview/llimview.h11
-rw-r--r--indra/newview/llinspectavatar.cpp53
-rw-r--r--indra/newview/llinspectgroup.cpp17
-rw-r--r--indra/newview/llinspectremoteobject.cpp27
-rw-r--r--indra/newview/llinventorybridge.cpp8
-rw-r--r--indra/newview/lllogchat.cpp168
-rw-r--r--indra/newview/lllogchat.h49
-rw-r--r--indra/newview/lllogininstance.cpp1
-rw-r--r--indra/newview/llmutelist.cpp29
-rw-r--r--indra/newview/llmutelist.h4
-rw-r--r--indra/newview/llnamebox.cpp19
-rw-r--r--indra/newview/llnamebox.h5
-rw-r--r--indra/newview/llnameeditor.cpp19
-rw-r--r--indra/newview/llnameeditor.h5
-rw-r--r--indra/newview/llnamelistctrl.cpp61
-rw-r--r--indra/newview/llnamelistctrl.h9
-rw-r--r--indra/newview/llnearbychat.cpp25
-rw-r--r--indra/newview/llnetmap.cpp12
-rw-r--r--indra/newview/llnotificationhandlerutil.cpp35
-rw-r--r--indra/newview/llpanelavatar.cpp19
-rw-r--r--indra/newview/llpanelavatartag.cpp2
-rw-r--r--indra/newview/llpanelblockedlist.cpp5
-rw-r--r--indra/newview/llpanelblockedlist.h5
-rw-r--r--indra/newview/llpanelgroupgeneral.cpp5
-rw-r--r--indra/newview/llpanelgroupgeneral.h3
-rw-r--r--indra/newview/llpanelgroupinvite.cpp56
-rw-r--r--indra/newview/llpanelgroupinvite.h2
-rw-r--r--indra/newview/llpanelgroupnotices.cpp7
-rw-r--r--indra/newview/llpanelgrouproles.cpp6
-rw-r--r--indra/newview/llpanelimcontrolpanel.cpp21
-rw-r--r--indra/newview/llpanelimcontrolpanel.h3
-rw-r--r--indra/newview/llpanellandmarkinfo.cpp22
-rw-r--r--indra/newview/llpanellogin.cpp32
-rw-r--r--indra/newview/llpanelme.cpp183
-rw-r--r--indra/newview/llpanelme.h7
-rw-r--r--indra/newview/llpanelmediasettingspermissions.cpp34
-rw-r--r--indra/newview/llpaneloutfitedit.cpp102
-rw-r--r--indra/newview/llpaneloutfitedit.h6
-rw-r--r--indra/newview/llpanelpeople.cpp7
-rw-r--r--indra/newview/llpanelpeople.h9
-rw-r--r--indra/newview/llpanelpermissions.cpp2
-rw-r--r--indra/newview/llpanelpicks.cpp6
-rw-r--r--indra/newview/llpanelplaceinfo.cpp15
-rw-r--r--indra/newview/llpanelplaceinfo.h8
-rw-r--r--indra/newview/llpanelplaceprofile.cpp27
-rw-r--r--indra/newview/llpanelprofile.h1
-rw-r--r--indra/newview/llpanelprofileview.cpp20
-rw-r--r--indra/newview/llpanelprofileview.h11
-rw-r--r--indra/newview/llparticipantlist.cpp19
-rw-r--r--indra/newview/llpreviewtexture.cpp6
-rw-r--r--indra/newview/llpreviewtexture.h8
-rw-r--r--indra/newview/llsidepaneliteminfo.cpp12
-rw-r--r--indra/newview/llsidepaneltaskinfo.cpp2
-rw-r--r--indra/newview/llspeakers.cpp7
-rw-r--r--indra/newview/llspeakers.h2
-rw-r--r--indra/newview/llstartup.cpp47
-rw-r--r--indra/newview/llstartup.h4
-rw-r--r--indra/newview/llsyswellwindow.cpp26
-rw-r--r--indra/newview/llsyswellwindow.h2
-rw-r--r--indra/newview/lltoastgroupnotifypanel.cpp7
-rw-r--r--indra/newview/lltoastimpanel.cpp3
-rw-r--r--indra/newview/lltoolpie.cpp25
-rw-r--r--indra/newview/lltracker.cpp10
-rw-r--r--indra/newview/llviewerdisplay.cpp2
-rw-r--r--indra/newview/llviewerdisplayname.cpp205
-rw-r--r--indra/newview/llviewerdisplayname.h53
-rw-r--r--indra/newview/llviewerinventory.cpp4
-rw-r--r--indra/newview/llviewerinventory.h2
-rw-r--r--indra/newview/llviewerjointattachment.cpp1
-rw-r--r--indra/newview/llviewermenu.cpp85
-rw-r--r--indra/newview/llviewermessage.cpp592
-rw-r--r--indra/newview/llviewerobject.cpp14
-rw-r--r--indra/newview/llviewerobject.h2
-rw-r--r--indra/newview/llviewerobjectlist.cpp4
-rw-r--r--indra/newview/llviewerparcelmgr.cpp5
-rw-r--r--indra/newview/llviewerregion.cpp22
-rw-r--r--indra/newview/llviewerregion.h6
-rw-r--r--indra/newview/llviewerstats.cpp8
-rw-r--r--indra/newview/llviewerstats.h55
-rw-r--r--indra/newview/llviewertexture.cpp71
-rw-r--r--indra/newview/llviewertexture.h13
-rw-r--r--indra/newview/llviewerwindow.cpp13
-rw-r--r--indra/newview/llvoavatar.cpp415
-rw-r--r--indra/newview/llvoavatar.h28
-rw-r--r--indra/newview/llvoavatarself.cpp2
-rw-r--r--indra/newview/llvoicechannel.h3
-rw-r--r--indra/newview/llvoicevivox.cpp28
-rw-r--r--indra/newview/llvoicevivox.h4
-rw-r--r--indra/newview/pipeline.cpp6
-rw-r--r--indra/newview/skins/default/colors.xml38
-rw-r--r--indra/newview/skins/default/textures/Rounded_Rect.pngbin0 -> 338 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Person_Check.pngbin0 -> 3824 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Person_Star.pngbin0 -> 3762 bytes
-rw-r--r--indra/newview/skins/default/textures/textures.xml3
-rw-r--r--indra/newview/skins/default/xui/da/floater_windlight_options.xml142
-rw-r--r--indra/newview/skins/default/xui/da/panel_classified_info.xml2
-rw-r--r--indra/newview/skins/default/xui/en/floater_about_land.xml7
-rw-r--r--indra/newview/skins/default/xui/en/floater_avatar_picker.xml56
-rw-r--r--indra/newview/skins/default/xui/en/floater_bumps.xml10
-rw-r--r--indra/newview/skins/default/xui/en/floater_buy_land.xml17
-rw-r--r--indra/newview/skins/default/xui/en/floater_buy_object.xml11
-rw-r--r--indra/newview/skins/default/xui/en/floater_camera.xml15
-rw-r--r--indra/newview/skins/default/xui/en/floater_incoming_call.xml2
-rw-r--r--indra/newview/skins/default/xui/en/floater_pay.xml46
-rw-r--r--indra/newview/skins/default/xui/en/floater_pay_object.xml28
-rw-r--r--indra/newview/skins/default/xui/en/floater_report_abuse.xml1
-rw-r--r--indra/newview/skins/default/xui/en/floater_sell_land.xml2
-rw-r--r--indra/newview/skins/default/xui/en/floater_tools.xml52
-rw-r--r--indra/newview/skins/default/xui/en/inspect_avatar.xml15
-rw-r--r--indra/newview/skins/default/xui/en/menu_viewer.xml6
-rw-r--r--indra/newview/skins/default/xui/en/notifications.xml152
-rw-r--r--indra/newview/skins/default/xui/en/panel_activeim_row.xml2
-rw-r--r--indra/newview/skins/default/xui/en/panel_edit_profile.xml41
-rw-r--r--indra/newview/skins/default/xui/en/panel_group_general.xml9
-rw-r--r--indra/newview/skins/default/xui/en/panel_group_roles.xml1
-rw-r--r--indra/newview/skins/default/xui/en/panel_im_control_panel.xml24
-rw-r--r--indra/newview/skins/default/xui/en/panel_instant_message.xml2
-rw-r--r--indra/newview/skins/default/xui/en/panel_landmarks.xml4
-rw-r--r--indra/newview/skins/default/xui/en/panel_login.xml19
-rw-r--r--indra/newview/skins/default/xui/en/panel_my_profile.xml2
-rw-r--r--indra/newview/skins/default/xui/en/panel_outfit_edit.xml119
-rw-r--r--indra/newview/skins/default/xui/en/panel_people.xml8
-rw-r--r--indra/newview/skins/default/xui/en/panel_preferences_advanced.xml6
-rw-r--r--indra/newview/skins/default/xui/en/panel_preferences_general.xml68
-rw-r--r--indra/newview/skins/default/xui/en/panel_preferences_setup.xml27
-rw-r--r--indra/newview/skins/default/xui/en/panel_profile.xml2
-rw-r--r--indra/newview/skins/default/xui/en/panel_profile_view.xml11
-rw-r--r--indra/newview/skins/default/xui/en/panel_region_debug.xml2
-rw-r--r--indra/newview/skins/default/xui/en/panel_region_estate.xml3
-rw-r--r--indra/newview/skins/default/xui/en/sidepanel_item_info.xml4
-rw-r--r--indra/newview/skins/default/xui/en/sidepanel_task_info.xml4
-rw-r--r--indra/newview/skins/default/xui/en/strings.xml8
-rw-r--r--indra/newview/skins/default/xui/es/notifications.xml8
-rw-r--r--indra/newview/skins/default/xui/fr/notifications.xml2
-rw-r--r--indra/newview/skins/default/xui/fr/panel_group_general.xml2
-rw-r--r--indra/newview/skins/default/xui/it/floater_about_land.xml10
-rw-r--r--indra/newview/skins/default/xui/it/floater_buy_currency.xml6
-rw-r--r--indra/newview/skins/default/xui/it/panel_people.xml2
-rw-r--r--indra/newview/skins/default/xui/ja/panel_group_land_money.xml2
-rw-r--r--indra/newview/skins/default/xui/ja/panel_group_roles.xml4
-rw-r--r--indra/newview/skins/default/xui/pt/floater_preview_gesture.xml22
-rw-r--r--indra/newview/skins/default/xui/pt/floater_tools.xml44
-rw-r--r--indra/newview/skins/default/xui/pt/floater_voice_effect.xml2
-rw-r--r--indra/newview/skins/default/xui/pt/floater_world_map.xml8
-rw-r--r--indra/newview/skins/default/xui/pt/menu_inventory.xml8
-rw-r--r--indra/newview/skins/default/xui/pt/panel_landmark_info.xml16
-rw-r--r--indra/newview/skins/default/xui/pt/panel_place_profile.xml16
-rw-r--r--indra/newview/skins/default/xui/pt/panel_preferences_privacy.xml4
-rw-r--r--indra/newview/skins/default/xui/pt/role_actions.xml4
-rw-r--r--indra/newview/skins/default/xui/pt/strings.xml6
-rw-r--r--indra/newview/tests/lldateutil_test.cpp10
240 files changed, 7273 insertions, 2861 deletions
diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt
index 2a036df06e..77740fb8bf 100644
--- a/indra/llcommon/CMakeLists.txt
+++ b/indra/llcommon/CMakeLists.txt
@@ -33,6 +33,7 @@ set(llcommon_SOURCE_FILES
llapp.cpp
llapr.cpp
llassettype.cpp
+ llavatarname.cpp
llbase32.cpp
llbase64.cpp
llcommon.cpp
@@ -115,6 +116,7 @@ set(llcommon_HEADER_FILES
llallocator.h
llallocator_heap_profile.h
llagentconstants.h
+ llavatarname.h
llapp.h
llapr.h
llassettype.h
diff --git a/indra/llcommon/llavatarname.cpp b/indra/llcommon/llavatarname.cpp
new file mode 100644
index 0000000000..14dc41591b
--- /dev/null
+++ b/indra/llcommon/llavatarname.cpp
@@ -0,0 +1,119 @@
+/**
+ * @file llavatarname.cpp
+ * @brief Represents name-related data for an avatar, such as the
+ * username/SLID ("bobsmith123" or "james.linden") and the display
+ * name ("James Cook")
+ *
+ * $LicenseInfo:firstyear=2010&license=viewergpl$
+ *
+ * Copyright (c) 2010, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+#include "linden_common.h"
+
+#include "llavatarname.h"
+
+#include "lldate.h"
+#include "llsd.h"
+
+// Store these in pre-built std::strings to avoid memory allocations in
+// LLSD map lookups
+static const std::string USERNAME("username");
+static const std::string DISPLAY_NAME("display_name");
+static const std::string LEGACY_FIRST_NAME("legacy_first_name");
+static const std::string LEGACY_LAST_NAME("legacy_last_name");
+static const std::string IS_DISPLAY_NAME_DEFAULT("is_display_name_default");
+static const std::string DISPLAY_NAME_EXPIRES("display_name_expires");
+static const std::string DISPLAY_NAME_NEXT_UPDATE("display_name_next_update");
+
+LLAvatarName::LLAvatarName()
+: mUsername(),
+ mDisplayName(),
+ mLegacyFirstName(),
+ mLegacyLastName(),
+ mIsDisplayNameDefault(false),
+ mIsDummy(false),
+ mExpires(F64_MAX),
+ mNextUpdate(0.0)
+{ }
+
+bool LLAvatarName::operator<(const LLAvatarName& rhs) const
+{
+ if (mUsername == rhs.mUsername)
+ return mDisplayName < rhs.mDisplayName;
+ else
+ return mUsername < rhs.mUsername;
+}
+
+LLSD LLAvatarName::asLLSD() const
+{
+ LLSD sd;
+ sd[USERNAME] = mUsername;
+ sd[DISPLAY_NAME] = mDisplayName;
+ sd[LEGACY_FIRST_NAME] = mLegacyFirstName;
+ sd[LEGACY_LAST_NAME] = mLegacyLastName;
+ sd[IS_DISPLAY_NAME_DEFAULT] = mIsDisplayNameDefault;
+ sd[DISPLAY_NAME_EXPIRES] = LLDate(mExpires);
+ sd[DISPLAY_NAME_NEXT_UPDATE] = LLDate(mNextUpdate);
+ return sd;
+}
+
+void LLAvatarName::fromLLSD(const LLSD& sd)
+{
+ mUsername = sd[USERNAME].asString();
+ mDisplayName = sd[DISPLAY_NAME].asString();
+ mLegacyFirstName = sd[LEGACY_FIRST_NAME].asString();
+ mLegacyLastName = sd[LEGACY_LAST_NAME].asString();
+ mIsDisplayNameDefault = sd[IS_DISPLAY_NAME_DEFAULT].asBoolean();
+ LLDate expires = sd[DISPLAY_NAME_EXPIRES];
+ mExpires = expires.secondsSinceEpoch();
+ LLDate next_update = sd[DISPLAY_NAME_NEXT_UPDATE];
+ mNextUpdate = next_update.secondsSinceEpoch();
+}
+
+std::string LLAvatarName::getCompleteName() const
+{
+ std::string name;
+ if (!mUsername.empty())
+ {
+ name = mDisplayName + " (" + mUsername + ")";
+ }
+ else
+ {
+ // ...display names are off, legacy name is in mDisplayName
+ name = mDisplayName;
+ }
+ return name;
+}
+
+std::string LLAvatarName::getLegacyName() const
+{
+ std::string name;
+ name.reserve( mLegacyFirstName.size() + 1 + mLegacyLastName.size() );
+ name = mLegacyFirstName;
+ name += " ";
+ name += mLegacyLastName;
+ return name;
+}
diff --git a/indra/llcommon/llavatarname.h b/indra/llcommon/llavatarname.h
new file mode 100644
index 0000000000..650a09a125
--- /dev/null
+++ b/indra/llcommon/llavatarname.h
@@ -0,0 +1,101 @@
+/**
+ * @file llavatarname.h
+ * @brief Represents name-related data for an avatar, such as the
+ * username/SLID ("bobsmith123" or "james.linden") and the display
+ * name ("James Cook")
+ *
+ * $LicenseInfo:firstyear=2010&license=viewergpl$
+ *
+ * Copyright (c) 2010, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+#ifndef LLAVATARNAME_H
+#define LLAVATARNAME_H
+
+#include <string>
+
+class LLSD;
+
+class LL_COMMON_API LLAvatarName
+{
+public:
+ LLAvatarName();
+
+ bool operator<(const LLAvatarName& rhs) const;
+
+ LLSD asLLSD() const;
+
+ void fromLLSD(const LLSD& sd);
+
+ // For normal names, returns "James Linden (james.linden)"
+ // When display names are disabled returns just "James Linden"
+ std::string getCompleteName() const;
+
+ // Returns "James Linden" or "bobsmith123 Resident" for backwards
+ // compatibility with systems like voice and muting
+ // *TODO: Eliminate this in favor of username only
+ std::string getLegacyName() const;
+
+ // "bobsmith123" or "james.linden", US-ASCII only
+ std::string mUsername;
+
+ // "Jose' Sanchez" or "James Linden", UTF-8 encoded Unicode
+ // Contains data whether or not user has explicitly set
+ // a display name; may duplicate their username.
+ std::string mDisplayName;
+
+ // For "James Linden", "James"
+ // For "bobsmith123", "bobsmith123"
+ // Used to communicate with legacy systems like voice and muting which
+ // rely on old-style names.
+ // *TODO: Eliminate this in favor of username only
+ std::string mLegacyFirstName;
+
+ // For "James Linden", "Linden"
+ // For "bobsmith123", "Resident"
+ // see above for rationale
+ std::string mLegacyLastName;
+
+ // If true, both display name and SLID were generated from
+ // a legacy first and last name, like "James Linden (james.linden)"
+ bool mIsDisplayNameDefault;
+
+ // Under error conditions, we may insert "dummy" records with
+ // names like "???" into caches as placeholders. These can be
+ // shown in UI, but are not serialized.
+ bool mIsDummy;
+
+ // Names can change, so need to keep track of when name was
+ // last checked.
+ // Unix time-from-epoch seconds for efficiency
+ F64 mExpires;
+
+ // You can only change your name every N hours, so record
+ // when the next update is allowed
+ // Unix time-from-epoch seconds
+ F64 mNextUpdate;
+};
+
+#endif
diff --git a/indra/llcommon/llchat.h b/indra/llcommon/llchat.h
index 63cce24005..2cc6e5c9bc 100644
--- a/indra/llcommon/llchat.h
+++ b/indra/llcommon/llchat.h
@@ -34,7 +34,6 @@
#ifndef LL_LLCHAT_H
#define LL_LLCHAT_H
-#include "llstring.h"
#include "lluuid.h"
#include "v3math.h"
@@ -77,7 +76,7 @@ typedef enum e_chat_style
class LLChat
{
public:
- LLChat(const std::string& text = LLStringUtil::null)
+ LLChat(const std::string& text = std::string())
: mText(text),
mFromName(),
mFromID(),
diff --git a/indra/llcommon/llqueuedthread.cpp b/indra/llcommon/llqueuedthread.cpp
index 809a626c93..e0b56b7973 100644
--- a/indra/llcommon/llqueuedthread.cpp
+++ b/indra/llcommon/llqueuedthread.cpp
@@ -428,9 +428,11 @@ S32 LLQueuedThread::processNextRequest()
llassert_always(req->getStatus() == STATUS_QUEUED);
break;
}
+ U32 start_priority = 0 ;
if (req)
{
req->setStatus(STATUS_INPROGRESS);
+ start_priority = req->getPriority();
}
unlockData();
@@ -439,8 +441,7 @@ S32 LLQueuedThread::processNextRequest()
// safe to access req.
if (req)
{
- // process request
- U32 start_priority = req->getPriority();
+ // process request
bool complete = req->processRequest();
if (complete)
diff --git a/indra/llcommon/llstring.cpp b/indra/llcommon/llstring.cpp
index 1561bda201..e9a54c3bf4 100644
--- a/indra/llcommon/llstring.cpp
+++ b/indra/llcommon/llstring.cpp
@@ -705,14 +705,17 @@ void LLStringOps::setupDatetimeInfo (bool daylight)
nowT = time (NULL);
- tmpT = localtime (&nowT);
- localT = mktime (tmpT);
-
tmpT = gmtime (&nowT);
gmtT = mktime (tmpT);
+ tmpT = localtime (&nowT);
+ localT = mktime (tmpT);
+
sLocalTimeOffset = (long) (gmtT - localT);
-
+ if (tmpT->tm_isdst)
+ {
+ sLocalTimeOffset -= 60 * 60; // 1 hour
+ }
sPacificDaylightTime = daylight;
sPacificTimeOffset = (sPacificDaylightTime? 7 : 8 ) * 60 * 60;
diff --git a/indra/llinventory/lltransactionflags.cpp b/indra/llinventory/lltransactionflags.cpp
index e0f87aa7db..79f8589bb1 100644
--- a/indra/llinventory/lltransactionflags.cpp
+++ b/indra/llinventory/lltransactionflags.cpp
@@ -114,6 +114,9 @@ std::string build_transfer_message_to_source(
std::ostringstream ostr;
if(dest_id.isNull())
{
+ // *NOTE: Do not change these strings! The viewer matches
+ // them in llviewermessage.cpp to perform localization.
+ // If you need to make changes, add a new, localizable message. JC
ostr << "You paid L$" << amount;
switch(transaction_type)
{
@@ -160,6 +163,9 @@ std::string build_transfer_message_to_destination(
return description;
}
std::ostringstream ostr;
+ // *NOTE: Do not change these strings! The viewer matches
+ // them in llviewermessage.cpp to perform localization.
+ // If you need to make changes, add a new, localizable message. JC
ostr << source_name << " paid you L$" << amount;
append_reason(ostr, transaction_type, description);
ostr << ".";
diff --git a/indra/llmessage/CMakeLists.txt b/indra/llmessage/CMakeLists.txt
index 1f8ee26716..1cad0f6d22 100644
--- a/indra/llmessage/CMakeLists.txt
+++ b/indra/llmessage/CMakeLists.txt
@@ -25,6 +25,7 @@ set(llmessage_SOURCE_FILES
llares.cpp
llareslistener.cpp
llassetstorage.cpp
+ llavatarnamecache.cpp
llblowfishcipher.cpp
llbuffer.cpp
llbufferstream.cpp
@@ -110,6 +111,7 @@ set(llmessage_HEADER_FILES
llares.h
llareslistener.h
llassetstorage.h
+ llavatarnamecache.h
llblowfishcipher.h
llbuffer.h
llbufferstream.h
@@ -248,6 +250,7 @@ if (LL_TESTS)
"${CMAKE_CURRENT_SOURCE_DIR}/tests/test_llsdmessage_peer.py"
)
+ LL_ADD_INTEGRATION_TEST(llavatarnamecache "" "${test_libs}")
LL_ADD_INTEGRATION_TEST(llhost "" "${test_libs}")
LL_ADD_INTEGRATION_TEST(llpartdata "" "${test_libs}")
LL_ADD_INTEGRATION_TEST(llxfer_file "" "${test_libs}")
diff --git a/indra/llmessage/llavatarnamecache.cpp b/indra/llmessage/llavatarnamecache.cpp
new file mode 100644
index 0000000000..912f34fcae
--- /dev/null
+++ b/indra/llmessage/llavatarnamecache.cpp
@@ -0,0 +1,795 @@
+/**
+ * @file llavatarnamecache.cpp
+ * @brief Provides lookup of avatar SLIDs ("bobsmith123") and display names
+ * ("James Cook") from avatar UUIDs.
+ *
+ * $LicenseInfo:firstyear=2010&license=viewergpl$
+ *
+ * Copyright (c) 2010, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+#include "linden_common.h"
+
+#include "llavatarnamecache.h"
+
+#include "llcachename.h" // we wrap this system
+#include "llframetimer.h"
+#include "llhttpclient.h"
+#include "llsd.h"
+#include "llsdserialize.h"
+
+#include <boost/tokenizer.hpp>
+
+#include <map>
+#include <set>
+
+namespace LLAvatarNameCache
+{
+ // Manual override for display names - can disable even if the region
+ // supports it.
+ bool sUseDisplayNames = true;
+
+ // Cache starts in a paused state until we can determine if the
+ // current region supports display names.
+ bool sRunning = false;
+
+ // Base lookup URL for name service.
+ // On simulator, loaded from indra.xml
+ // On viewer, usually a simulator capability (at People API team's request)
+ // Includes the trailing slash, like "http://pdp60.lindenlab.com:8000/agents/"
+ std::string sNameLookupURL;
+
+ // accumulated agent IDs for next query against service
+ typedef std::set<LLUUID> ask_queue_t;
+ ask_queue_t sAskQueue;
+
+ // agent IDs that have been requested, but with no reply
+ // maps agent ID to frame time request was made
+ typedef std::map<LLUUID, F64> pending_queue_t;
+ pending_queue_t sPendingQueue;
+
+ // Callbacks to fire when we received a name.
+ // May have multiple callbacks for a single ID, which are
+ // represented as multiple slots bound to the signal.
+ // Avoid copying signals via pointers.
+ typedef std::map<LLUUID, callback_signal_t*> signal_map_t;
+ signal_map_t sSignalMap;
+
+ // names we know about
+ typedef std::map<LLUUID, LLAvatarName> cache_t;
+ cache_t sCache;
+
+ // Send bulk lookup requests a few times a second at most
+ // only need per-frame timing resolution
+ LLFrameTimer sRequestTimer;
+
+ // Periodically clean out expired entries from the cache
+ LLFrameTimer sEraseExpiredTimer;
+
+ //-----------------------------------------------------------------------
+ // Internal methods
+ //-----------------------------------------------------------------------
+
+ // Handle name response off network.
+ // Optionally skip adding to cache, used when this is a fallback to the
+ // legacy name system.
+ void processName(const LLUUID& agent_id,
+ const LLAvatarName& av_name,
+ bool add_to_cache);
+
+ void requestNamesViaCapability();
+
+ // Legacy name system callback
+ void legacyNameCallback(const LLUUID& agent_id,
+ const std::string& full_name,
+ bool is_group);
+
+ void requestNamesViaLegacy();
+
+ // Fill in an LLAvatarName with the legacy name data
+ void buildLegacyName(const std::string& full_name,
+ LLAvatarName* av_name);
+
+ // Do a single callback to a given slot
+ void fireSignal(const LLUUID& agent_id,
+ const callback_slot_t& slot,
+ const LLAvatarName& av_name);
+
+ // Is a request in-flight over the network?
+ bool isRequestPending(const LLUUID& agent_id);
+
+ // Erase expired names from cache
+ void eraseExpired();
+
+ bool expirationFromCacheControl(LLSD headers, F64 *expires);
+}
+
+/* Sample response:
+<?xml version="1.0"?>
+<llsd>
+ <map>
+ <key>agents</key>
+ <array>
+ <map>
+ <key>display_name_next_update</key>
+ <date>2010-04-16T21:34:02+00:00Z</date>
+ <key>display_name_expires</key>
+ <date>2010-04-16T21:32:26.142178+00:00Z</date>
+ <key>display_name</key>
+ <string>MickBot390 LLQABot</string>
+ <key>sl_id</key>
+ <string>mickbot390.llqabot</string>
+ <key>id</key>
+ <string>0012809d-7d2d-4c24-9609-af1230a37715</string>
+ <key>is_display_name_default</key>
+ <boolean>false</boolean>
+ </map>
+ <map>
+ <key>display_name_next_update</key>
+ <date>2010-04-16T21:34:02+00:00Z</date>
+ <key>display_name_expires</key>
+ <date>2010-04-16T21:32:26.142178+00:00Z</date>
+ <key>display_name</key>
+ <string>Bjork Gudmundsdottir</string>
+ <key>sl_id</key>
+ <string>sardonyx.linden</string>
+ <key>id</key>
+ <string>3941037e-78ab-45f0-b421-bd6e77c1804d</string>
+ <key>is_display_name_default</key>
+ <boolean>true</boolean>
+ </map>
+ </array>
+ </map>
+</llsd>
+*/
+
+class LLAvatarNameResponder : public LLHTTPClient::Responder
+{
+private:
+ // need to store agent ids that are part of this request in case of
+ // an error, so we can flag them as unavailable
+ std::vector<LLUUID> mAgentIDs;
+
+ // Need the headers to look up Expires: and Retry-After:
+ LLSD mHeaders;
+
+public:
+ LLAvatarNameResponder(const std::vector<LLUUID>& agent_ids)
+ : mAgentIDs(agent_ids),
+ mHeaders()
+ { }
+
+ /*virtual*/ void completedHeader(U32 status, const std::string& reason,
+ const LLSD& headers)
+ {
+ mHeaders = headers;
+ }
+
+ /*virtual*/ void result(const LLSD& content)
+ {
+ // Pull expiration out of headers if available
+ F64 expires = LLAvatarNameCache::nameExpirationFromHeaders(mHeaders);
+
+ LLSD agents = content["agents"];
+ LLSD::array_const_iterator it = agents.beginArray();
+ for ( ; it != agents.endArray(); ++it)
+ {
+ const LLSD& row = *it;
+ LLUUID agent_id = row["id"].asUUID();
+
+ LLAvatarName av_name;
+ av_name.fromLLSD(row);
+
+ // Use expiration time from header
+ av_name.mExpires = expires;
+
+ // Some avatars don't have explicit display names set
+ if (av_name.mDisplayName.empty())
+ {
+ av_name.mDisplayName = av_name.mUsername;
+ }
+
+ // cache it and fire signals
+ LLAvatarNameCache::processName(agent_id, av_name, true);
+ }
+
+ // Same logic as error response case
+ LLSD unresolved_agents = content["bad_ids"];
+ if (unresolved_agents.size() > 0)
+ {
+ const std::string DUMMY_NAME("\?\?\?");
+ LLAvatarName av_name;
+ av_name.mUsername = DUMMY_NAME;
+ av_name.mDisplayName = DUMMY_NAME;
+ av_name.mIsDisplayNameDefault = false;
+ av_name.mIsDummy = true;
+ av_name.mExpires = expires;
+
+ it = unresolved_agents.beginArray();
+ for ( ; it != unresolved_agents.endArray(); ++it)
+ {
+ const LLUUID& agent_id = *it;
+ // cache it and fire signals
+ LLAvatarNameCache::processName(agent_id, av_name, true);
+ }
+ }
+ }
+
+ /*virtual*/ void error(U32 status, const std::string& reason)
+ {
+ // We're going to construct a dummy record and cache it for a while,
+ // either briefly for a 503 Service Unavailable, or longer for other
+ // errors.
+ F64 retry_timestamp = errorRetryTimestamp(status);
+
+ // *NOTE: "??" starts trigraphs in C/C++, escape the question marks.
+ const std::string DUMMY_NAME("\?\?\?");
+ LLAvatarName av_name;
+ av_name.mUsername = DUMMY_NAME;
+ av_name.mDisplayName = DUMMY_NAME;
+ av_name.mIsDisplayNameDefault = false;
+ av_name.mIsDummy = true;
+ av_name.mExpires = retry_timestamp;
+
+ // Add dummy records for all agent IDs in this request
+ std::vector<LLUUID>::const_iterator it = mAgentIDs.begin();
+ for ( ; it != mAgentIDs.end(); ++it)
+ {
+ const LLUUID& agent_id = *it;
+ // cache it and fire signals
+ LLAvatarNameCache::processName(agent_id, av_name, true);
+ }
+ }
+
+ // Return time to retry a request that generated an error, based on
+ // error type and headers. Return value is seconds-since-epoch.
+ F64 errorRetryTimestamp(S32 status)
+ {
+ F64 now = LLFrameTimer::getTotalSeconds();
+
+ // Retry-After takes priority
+ LLSD retry_after = mHeaders["retry-after"];
+ if (retry_after.isDefined())
+ {
+ // We only support the delta-seconds type
+ S32 delta_seconds = retry_after.asInteger();
+ if (delta_seconds > 0)
+ {
+ // ...valid delta-seconds
+ return now + F64(delta_seconds);
+ }
+ }
+
+ // If no Retry-After, look for Cache-Control max-age
+ F64 expires = 0.0;
+ if (LLAvatarNameCache::expirationFromCacheControl(mHeaders, &expires))
+ {
+ return expires;
+ }
+
+ // No information in header, make a guess
+ if (status == 503)
+ {
+ // ...service unavailable, retry soon
+ const F64 SERVICE_UNAVAILABLE_DELAY = 600.0; // 10 min
+ return now + SERVICE_UNAVAILABLE_DELAY;
+ }
+ else
+ {
+ // ...other unexpected error
+ const F64 DEFAULT_DELAY = 3600.0; // 1 hour
+ return now + DEFAULT_DELAY;
+ }
+ }
+};
+
+void LLAvatarNameCache::processName(const LLUUID& agent_id,
+ const LLAvatarName& av_name,
+ bool add_to_cache)
+{
+ if (add_to_cache)
+ {
+ sCache[agent_id] = av_name;
+ }
+
+ sPendingQueue.erase(agent_id);
+
+ // signal everyone waiting on this name
+ signal_map_t::iterator sig_it = sSignalMap.find(agent_id);
+ if (sig_it != sSignalMap.end())
+ {
+ callback_signal_t* signal = sig_it->second;
+ (*signal)(agent_id, av_name);
+
+ sSignalMap.erase(agent_id);
+
+ delete signal;
+ signal = NULL;
+ }
+}
+
+void LLAvatarNameCache::requestNamesViaCapability()
+{
+ F64 now = LLFrameTimer::getTotalSeconds();
+
+ // URL format is like:
+ // http://pdp60.lindenlab.com:8000/agents/?ids=3941037e-78ab-45f0-b421-bd6e77c1804d&ids=0012809d-7d2d-4c24-9609-af1230a37715&ids=0019aaba-24af-4f0a-aa72-6457953cf7f0
+ //
+ // Apache can handle URLs of 4096 chars, but let's be conservative
+ const U32 NAME_URL_MAX = 4096;
+ const U32 NAME_URL_SEND_THRESHOLD = 3000;
+ std::string url;
+ url.reserve(NAME_URL_MAX);
+
+ std::vector<LLUUID> agent_ids;
+ agent_ids.reserve(128);
+
+ ask_queue_t::const_iterator it = sAskQueue.begin();
+ for ( ; it != sAskQueue.end(); ++it)
+ {
+ const LLUUID& agent_id = *it;
+
+ if (url.empty())
+ {
+ // ...starting new request
+ url += sNameLookupURL;
+ url += "?ids=";
+ }
+ else
+ {
+ // ...continuing existing request
+ url += "&ids=";
+ }
+ url += agent_id.asString();
+ agent_ids.push_back(agent_id);
+
+ // mark request as pending
+ sPendingQueue[agent_id] = now;
+
+ if (url.size() > NAME_URL_SEND_THRESHOLD)
+ {
+ //llinfos << "requestNames " << url << llendl;
+ LLHTTPClient::get(url, new LLAvatarNameResponder(agent_ids));
+ url.clear();
+ agent_ids.clear();
+ }
+ }
+
+ if (!url.empty())
+ {
+ //llinfos << "requestNames " << url << llendl;
+ LLHTTPClient::get(url, new LLAvatarNameResponder(agent_ids));
+ url.clear();
+ agent_ids.clear();
+ }
+
+ // We've moved all asks to the pending request queue
+ sAskQueue.clear();
+}
+
+void LLAvatarNameCache::legacyNameCallback(const LLUUID& agent_id,
+ const std::string& full_name,
+ bool is_group)
+{
+ // Construct a dummy record for this name. By convention, SLID is blank
+ // Never expires, but not written to disk, so lasts until end of session.
+ LLAvatarName av_name;
+ buildLegacyName(full_name, &av_name);
+
+ // Don't add to cache, the data already exists in the legacy name system
+ // cache and we don't want or need duplicate storage, because keeping the
+ // two copies in sync is complex.
+ processName(agent_id, av_name, false);
+}
+
+void LLAvatarNameCache::requestNamesViaLegacy()
+{
+ F64 now = LLFrameTimer::getTotalSeconds();
+ std::string full_name;
+ ask_queue_t::const_iterator it = sAskQueue.begin();
+ for (; it != sAskQueue.end(); ++it)
+ {
+ const LLUUID& agent_id = *it;
+
+ // Mark as pending first, just in case the callback is immediately
+ // invoked below. This should never happen in practice.
+ sPendingQueue[agent_id] = now;
+
+ gCacheName->get(agent_id, false, // legacy compatibility
+ boost::bind(&LLAvatarNameCache::legacyNameCallback,
+ _1, _2, _3));
+ }
+
+ // We've either answered immediately or moved all asks to the
+ // pending queue
+ sAskQueue.clear();
+}
+
+void LLAvatarNameCache::initClass(bool running)
+{
+ sRunning = running;
+}
+
+void LLAvatarNameCache::cleanupClass()
+{
+}
+
+void LLAvatarNameCache::importFile(std::istream& istr)
+{
+ LLSD data;
+ S32 parse_count = LLSDSerialize::fromXMLDocument(data, istr);
+ if (parse_count < 1) return;
+
+ // by convention LLSD storage is a map
+ // we only store one entry in the map
+ LLSD agents = data["agents"];
+
+ LLUUID agent_id;
+ LLAvatarName av_name;
+ LLSD::map_const_iterator it = agents.beginMap();
+ for ( ; it != agents.endMap(); ++it)
+ {
+ agent_id.set(it->first);
+ av_name.fromLLSD( it->second );
+ sCache[agent_id] = av_name;
+ }
+ // entries may have expired since we last ran the viewer, just
+ // clean them out now
+ eraseExpired();
+ llinfos << "loaded " << sCache.size() << llendl;
+}
+
+void LLAvatarNameCache::exportFile(std::ostream& ostr)
+{
+ LLSD agents;
+ cache_t::const_iterator it = sCache.begin();
+ for ( ; it != sCache.end(); ++it)
+ {
+ const LLUUID& agent_id = it->first;
+ const LLAvatarName& av_name = it->second;
+ if (!av_name.mIsDummy)
+ {
+ // key must be a string
+ agents[agent_id.asString()] = av_name.asLLSD();
+ }
+ }
+ LLSD data;
+ data["agents"] = agents;
+ LLSDSerialize::toPrettyXML(data, ostr);
+}
+
+void LLAvatarNameCache::setNameLookupURL(const std::string& name_lookup_url)
+{
+ sNameLookupURL = name_lookup_url;
+}
+
+bool LLAvatarNameCache::hasNameLookupURL()
+{
+ return !sNameLookupURL.empty();
+}
+
+void LLAvatarNameCache::idle()
+{
+ // By convention, start running at first idle() call
+ sRunning = true;
+
+ // *TODO: Possibly re-enabled this based on People API load measurements
+ // 100 ms is the threshold for "user speed" operations, so we can
+ // stall for about that long to batch up requests.
+ //const F32 SECS_BETWEEN_REQUESTS = 0.1f;
+ //if (!sRequestTimer.checkExpirationAndReset(SECS_BETWEEN_REQUESTS))
+ //{
+ // return;
+ //}
+
+ // Must be large relative to above
+ const F32 ERASE_EXPIRED_TIMEOUT = 60.f; // seconds
+ if (sEraseExpiredTimer.checkExpirationAndReset(ERASE_EXPIRED_TIMEOUT))
+ {
+ eraseExpired();
+ }
+
+ if (sAskQueue.empty())
+ {
+ return;
+ }
+
+ if (useDisplayNames())
+ {
+ requestNamesViaCapability();
+ }
+ else
+ {
+ // ...fall back to legacy name cache system
+ requestNamesViaLegacy();
+ }
+}
+
+bool LLAvatarNameCache::isRequestPending(const LLUUID& agent_id)
+{
+ const F64 PENDING_TIMEOUT_SECS = 5.0 * 60.0;
+ F64 now = LLFrameTimer::getTotalSeconds();
+ F64 expire_time = now - PENDING_TIMEOUT_SECS;
+
+ pending_queue_t::const_iterator it = sPendingQueue.find(agent_id);
+ if (it != sPendingQueue.end())
+ {
+ bool request_expired = (it->second < expire_time);
+ return !request_expired;
+ }
+ return false;
+}
+
+void LLAvatarNameCache::eraseExpired()
+{
+ F64 now = LLFrameTimer::getTotalSeconds();
+ cache_t::iterator it = sCache.begin();
+ while (it != sCache.end())
+ {
+ cache_t::iterator cur = it;
+ ++it;
+ const LLAvatarName& av_name = cur->second;
+ if (av_name.mExpires < now)
+ {
+ sCache.erase(cur);
+ }
+ }
+}
+
+void LLAvatarNameCache::buildLegacyName(const std::string& full_name,
+ LLAvatarName* av_name)
+{
+ llassert(av_name);
+ av_name->mUsername = "";
+ av_name->mDisplayName = full_name;
+ av_name->mIsDisplayNameDefault = true;
+ av_name->mIsDummy = true;
+ av_name->mExpires = F64_MAX;
+}
+
+bool LLAvatarNameCache::get(const LLUUID& agent_id, LLAvatarName *av_name)
+{
+ if (sRunning)
+ {
+ // ...only do immediate lookups when cache is running
+ if (useDisplayNames())
+ {
+ // ...use display names cache
+ std::map<LLUUID,LLAvatarName>::iterator it = sCache.find(agent_id);
+ if (it != sCache.end())
+ {
+ *av_name = it->second;
+ return true;
+ }
+ }
+ else
+ {
+ // ...use legacy names cache
+ std::string full_name;
+ if (gCacheName->getFullName(agent_id, full_name))
+ {
+ buildLegacyName(full_name, av_name);
+ return true;
+ }
+ }
+ }
+
+ if (!isRequestPending(agent_id))
+ {
+ sAskQueue.insert(agent_id);
+ }
+
+ return false;
+}
+
+void LLAvatarNameCache::fireSignal(const LLUUID& agent_id,
+ const callback_slot_t& slot,
+ const LLAvatarName& av_name)
+{
+ callback_signal_t signal;
+ signal.connect(slot);
+ signal(agent_id, av_name);
+}
+
+void LLAvatarNameCache::get(const LLUUID& agent_id, callback_slot_t slot)
+{
+ if (sRunning)
+ {
+ // ...only do immediate lookups when cache is running
+ if (useDisplayNames())
+ {
+ // ...use new cache
+ std::map<LLUUID,LLAvatarName>::iterator it = sCache.find(agent_id);
+ if (it != sCache.end())
+ {
+ // ...name already exists in cache, fire callback now
+ fireSignal(agent_id, slot, it->second);
+ return;
+ }
+ }
+ else
+ {
+ // ...use old name system
+ std::string full_name;
+ if (gCacheName->getFullName(agent_id, full_name))
+ {
+ LLAvatarName av_name;
+ buildLegacyName(full_name, &av_name);
+ fireSignal(agent_id, slot, av_name);
+ return;
+ }
+ }
+ }
+
+ // schedule a request
+ if (!isRequestPending(agent_id))
+ {
+ sAskQueue.insert(agent_id);
+ }
+
+ // always store additional callback, even if request is pending
+ signal_map_t::iterator sig_it = sSignalMap.find(agent_id);
+ if (sig_it == sSignalMap.end())
+ {
+ // ...new callback for this id
+ callback_signal_t* signal = new callback_signal_t();
+ signal->connect(slot);
+ sSignalMap[agent_id] = signal;
+ }
+ else
+ {
+ // ...existing callback, bind additional slot
+ callback_signal_t* signal = sig_it->second;
+ signal->connect(slot);
+ }
+}
+
+
+void LLAvatarNameCache::setUseDisplayNames(bool use)
+{
+ if (use != sUseDisplayNames)
+ {
+ sUseDisplayNames = use;
+ // flush our cache
+ sCache.clear();
+ }
+}
+
+bool LLAvatarNameCache::useDisplayNames()
+{
+ // Must be both manually set on and able to look up names.
+ return sUseDisplayNames && !sNameLookupURL.empty();
+}
+
+void LLAvatarNameCache::erase(const LLUUID& agent_id)
+{
+ sCache.erase(agent_id);
+}
+
+void LLAvatarNameCache::fetch(const LLUUID& agent_id)
+{
+ // re-request, even if request is already pending
+ sAskQueue.insert(agent_id);
+}
+
+void LLAvatarNameCache::insert(const LLUUID& agent_id, const LLAvatarName& av_name)
+{
+ // *TODO: update timestamp if zero?
+ sCache[agent_id] = av_name;
+}
+
+F64 LLAvatarNameCache::nameExpirationFromHeaders(LLSD headers)
+{
+ F64 expires = 0.0;
+ if (expirationFromCacheControl(headers, &expires))
+ {
+ return expires;
+ }
+ else
+ {
+ // With no expiration info, default to a day
+ const F64 DEFAULT_EXPIRES = 24.0 * 60.0 * 60.0;
+ F64 now = LLFrameTimer::getTotalSeconds();
+ return now + DEFAULT_EXPIRES;
+ }
+}
+
+bool LLAvatarNameCache::expirationFromCacheControl(LLSD headers, F64 *expires)
+{
+ // Allow the header to override the default
+ LLSD cache_control_header = headers["cache-control"];
+ if (cache_control_header.isDefined())
+ {
+ S32 max_age = 0;
+ std::string cache_control = cache_control_header.asString();
+ if (max_age_from_cache_control(cache_control, &max_age))
+ {
+ F64 now = LLFrameTimer::getTotalSeconds();
+ *expires = now + (F64)max_age;
+ return true;
+ }
+ }
+ return false;
+}
+
+static const std::string MAX_AGE("max-age");
+static const boost::char_separator<char> EQUALS_SEPARATOR("=");
+static const boost::char_separator<char> COMMA_SEPARATOR(",");
+
+bool max_age_from_cache_control(const std::string& cache_control, S32 *max_age)
+{
+ // Split the string on "," to get a list of directives
+ typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
+ tokenizer directives(cache_control, COMMA_SEPARATOR);
+
+ tokenizer::iterator token_it = directives.begin();
+ for ( ; token_it != directives.end(); ++token_it)
+ {
+ // Tokens may have leading or trailing whitespace
+ std::string token = *token_it;
+ LLStringUtil::trim(token);
+
+ if (token.compare(0, MAX_AGE.size(), MAX_AGE) == 0)
+ {
+ // ...this token starts with max-age, so let's chop it up by "="
+ tokenizer subtokens(token, EQUALS_SEPARATOR);
+ tokenizer::iterator subtoken_it = subtokens.begin();
+
+ // Must have a token
+ if (subtoken_it == subtokens.end()) return false;
+ std::string subtoken = *subtoken_it;
+
+ // Must exactly equal "max-age"
+ LLStringUtil::trim(subtoken);
+ if (subtoken != MAX_AGE) return false;
+
+ // Must have another token
+ ++subtoken_it;
+ if (subtoken_it == subtokens.end()) return false;
+ subtoken = *subtoken_it;
+
+ // Must be a valid integer
+ // *NOTE: atoi() returns 0 for invalid values, so we have to
+ // check the string first.
+ // *TODO: Do servers ever send "0000" for zero? We don't handle it
+ LLStringUtil::trim(subtoken);
+ if (subtoken == "0")
+ {
+ *max_age = 0;
+ return true;
+ }
+ S32 val = atoi( subtoken.c_str() );
+ if (val > 0 && val < S32_MAX)
+ {
+ *max_age = val;
+ return true;
+ }
+ return false;
+ }
+ }
+ return false;
+}
+
+
diff --git a/indra/llmessage/llavatarnamecache.h b/indra/llmessage/llavatarnamecache.h
new file mode 100644
index 0000000000..0a8b987b05
--- /dev/null
+++ b/indra/llmessage/llavatarnamecache.h
@@ -0,0 +1,103 @@
+/**
+ * @file llavatarnamecache.h
+ * @brief Provides lookup of avatar SLIDs ("bobsmith123") and display names
+ * ("James Cook") from avatar UUIDs.
+ *
+ * $LicenseInfo:firstyear=2010&license=viewergpl$
+ *
+ * Copyright (c) 2010, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+#ifndef LLAVATARNAMECACHE_H
+#define LLAVATARNAMECACHE_H
+
+#include "llavatarname.h" // for convenience
+
+#include <boost/signals2.hpp>
+
+class LLSD;
+class LLUUID;
+
+namespace LLAvatarNameCache
+{
+ // Until the cache is set running, immediate lookups will fail and
+ // async lookups will be queued. This allows us to block requests
+ // until we know if the first region supports display names.
+ void initClass(bool running);
+ void cleanupClass();
+
+ void importFile(std::istream& istr);
+ void exportFile(std::ostream& ostr);
+
+ // On the viewer, usually a simulator capabilitity
+ // If empty, name cache will fall back to using legacy name
+ // lookup system
+ void setNameLookupURL(const std::string& name_lookup_url);
+
+ // Do we have a valid lookup URL, hence are we trying to use the
+ // new display name lookup system?
+ bool hasNameLookupURL();
+
+ // Periodically makes a batch request for display names not already in
+ // cache. Call once per frame.
+ void idle();
+
+ // If name is in cache, returns true and fills in provided LLAvatarName
+ // otherwise returns false
+ bool get(const LLUUID& agent_id, LLAvatarName *av_name);
+
+ // Callback types for get() below
+ typedef boost::signals2::signal<
+ void (const LLUUID& agent_id, const LLAvatarName& av_name)>
+ callback_signal_t;
+ typedef callback_signal_t::slot_type callback_slot_t;
+
+ // Fetches name information and calls callback.
+ // If name information is in cache, callback will be called immediately.
+ void get(const LLUUID& agent_id, callback_slot_t slot);
+
+ // Allow display names to be explicitly disabled for testing.
+ void setUseDisplayNames(bool use);
+ bool useDisplayNames();
+
+ void erase(const LLUUID& agent_id);
+
+ // Force a re-fetch of the most recent data, but keep the current
+ // data in cache
+ void fetch(const LLUUID& agent_id);
+
+ void insert(const LLUUID& agent_id, const LLAvatarName& av_name);
+
+ // Compute name expiration time from HTTP Cache-Control header,
+ // or return default value, in seconds from epoch.
+ F64 nameExpirationFromHeaders(LLSD headers);
+}
+
+// Parse a cache-control header to get the max-age delta-seconds.
+// Returns true if header has max-age param and it parses correctly.
+// Exported here to ease unit testing.
+bool max_age_from_cache_control(const std::string& cache_control, S32 *max_age);
+
+#endif
diff --git a/indra/llmessage/llcachename.cpp b/indra/llmessage/llcachename.cpp
index 9871c922f1..ef60fd5c4e 100644
--- a/indra/llmessage/llcachename.cpp
+++ b/indra/llmessage/llcachename.cpp
@@ -75,6 +75,8 @@ public:
public:
bool mIsGroup;
U32 mCreateTime; // unix time_t
+ // IDEVO TODO collapse names to one field, which will eliminate
+ // many string compares on "Resident"
std::string mFirstName;
std::string mLastName;
std::string mGroupName;
@@ -220,7 +222,9 @@ public:
Impl(LLMessageSystem* msg);
~Impl();
-
+
+ BOOL getName(const LLUUID& id, std::string& first, std::string& last);
+
boost::signals2::connection addPending(const LLUUID& id, const LLCacheNameCallback& callback);
void addPending(const LLUUID& id, const LLHost& host);
@@ -306,89 +310,10 @@ boost::signals2::connection LLCacheName::addObserver(const LLCacheNameCallback&
return impl.mSignal.connect(callback);
}
-void LLCacheName::importFile(LLFILE* fp)
-{
- S32 count = 0;
-
- const S32 BUFFER_SIZE = 1024;
- char buffer[BUFFER_SIZE]; /*Flawfinder: ignore*/
-
- // *NOTE: These buffer sizes are hardcoded into sscanf() below
- char id_string[MAX_STRING]; /*Flawfinder: ignore*/
- char firstname[MAX_STRING]; /*Flawfinder: ignore*/
- char lastname[MAX_STRING]; /*Flawfinder: ignore*/
- U32 create_time;
-
- // This is OK if the first line is actually a name. We just don't load it.
- char* valid = fgets(buffer, BUFFER_SIZE, fp);
- if (!valid) return;
-
- // *NOTE: This buffer size is hardcoded into sscanf() below
- char version_string[BUFFER_SIZE]; /*Flawfinder: ignore*/
- S32 version = 0;
- S32 match = sscanf( /* Flawfinder: ignore */
- buffer,
- "%1023s %d",
- version_string, &version);
- if ( match != 2
- || strcmp(version_string, "version")
- || version != CN_FILE_VERSION)
- {
- llwarns << "Ignoring old cache name file format" << llendl;
- return;
- }
-
- // We'll expire entries more than a week old
- U32 now = (U32)time(NULL);
- const U32 SECS_PER_DAY = 60 * 60 * 24;
- U32 delete_before_time = now - (7 * SECS_PER_DAY);
-
- while(!feof(fp))
- {
- valid = fgets(buffer, BUFFER_SIZE, fp);
- if (!valid) break;
-
- match = sscanf( /* Flawfinder: ignore */
- buffer,
- "%254s %u %254s %254s",
- id_string,
- &create_time,
- firstname,
- lastname);
- if (4 != match) continue;
-
- LLUUID id(id_string);
- if (id.isNull()) continue;
-
- // undo trivial XOR
- S32 i;
- for (i = 0; i < UUID_BYTES; i++)
- {
- id.mData[i] ^= 0x33;
- }
-
- // Don't load entries that are more than a week old
- if (create_time < delete_before_time) continue;
-
- LLCacheNameEntry* entry = new LLCacheNameEntry();
- entry->mIsGroup = false;
- entry->mCreateTime = create_time;
- entry->mFirstName = firstname;
- entry->mLastName = lastname;
- impl.mCache[id] = entry;
- std::string fullname = entry->mFirstName + " " + entry->mLastName;
- impl.mReverseCache[fullname] = id;
-
- count++;
- }
-
- llinfos << "LLCacheName loaded " << count << " names" << llendl;
-}
-
bool LLCacheName::importFile(std::istream& istr)
{
LLSD data;
- if(LLSDSerialize::fromXML(data, istr) < 1)
+ if(LLSDSerialize::fromXMLDocument(data, istr) < 1)
return false;
// We'll expire entries more than a week old
@@ -414,7 +339,7 @@ bool LLCacheName::importFile(std::istream& istr)
entry->mFirstName = agent[FIRST].asString();
entry->mLastName = agent[LAST].asString();
impl.mCache[id] = entry;
- std::string fullname = entry->mFirstName + " " + entry->mLastName;
+ std::string fullname = buildFullName(entry->mFirstName, entry->mLastName);
impl.mReverseCache[fullname] = id;
++count;
@@ -463,6 +388,7 @@ void LLCacheName::exportFile(std::ostream& ostr)
// store it
LLUUID id = iter->first;
std::string id_str = id.asString();
+ // IDEVO TODO: Should we store SLIDs with last name "Resident" or not?
if(!entry->mFirstName.empty() && !entry->mLastName.empty())
{
data[AGENTS][id_str][FIRST] = entry->mFirstName;
@@ -480,7 +406,7 @@ void LLCacheName::exportFile(std::ostream& ostr)
}
-BOOL LLCacheName::getName(const LLUUID& id, std::string& first, std::string& last)
+BOOL LLCacheName::Impl::getName(const LLUUID& id, std::string& first, std::string& last)
{
if(id.isNull())
{
@@ -489,7 +415,7 @@ BOOL LLCacheName::getName(const LLUUID& id, std::string& first, std::string& las
return TRUE;
}
- LLCacheNameEntry* entry = get_ptr_in_map(impl.mCache, id );
+ LLCacheNameEntry* entry = get_ptr_in_map(mCache, id );
if (entry)
{
first = entry->mFirstName;
@@ -500,16 +426,17 @@ BOOL LLCacheName::getName(const LLUUID& id, std::string& first, std::string& las
{
first = sCacheName["waiting"];
last.clear();
- if (!impl.isRequestPending(id))
+ if (!isRequestPending(id))
{
- impl.mAskNameQueue.insert(id);
+ mAskNameQueue.insert(id);
}
return FALSE;
}
}
+
// static
-void LLCacheName::LocalizeCacheName(std::string key, std::string value)
+void LLCacheName::localizeCacheName(std::string key, std::string value)
{
if (key!="" && value!= "" )
sCacheName[key]=value;
@@ -520,11 +447,13 @@ void LLCacheName::LocalizeCacheName(std::string key, std::string value)
BOOL LLCacheName::getFullName(const LLUUID& id, std::string& fullname)
{
std::string first_name, last_name;
- BOOL res = getName(id, first_name, last_name);
- fullname = first_name + " " + last_name;
+ BOOL res = impl.getName(id, first_name, last_name);
+ fullname = buildFullName(first_name, last_name);
return res;
}
+
+
BOOL LLCacheName::getGroupName(const LLUUID& id, std::string& group)
{
if(id.isNull())
@@ -561,13 +490,13 @@ BOOL LLCacheName::getGroupName(const LLUUID& id, std::string& group)
BOOL LLCacheName::getUUID(const std::string& first, const std::string& last, LLUUID& id)
{
- std::string fullname = first + " " + last;
- return getUUID(fullname, id);
+ std::string full_name = buildFullName(first, last);
+ return getUUID(full_name, id);
}
-BOOL LLCacheName::getUUID(const std::string& fullname, LLUUID& id)
+BOOL LLCacheName::getUUID(const std::string& full_name, LLUUID& id)
{
- ReverseCache::iterator iter = impl.mReverseCache.find(fullname);
+ ReverseCache::iterator iter = impl.mReverseCache.find(full_name);
if (iter != impl.mReverseCache.end())
{
id = iter->second;
@@ -579,6 +508,55 @@ BOOL LLCacheName::getUUID(const std::string& fullname, LLUUID& id)
}
}
+//static
+std::string LLCacheName::buildFullName(const std::string& first, const std::string& last)
+{
+ std::string fullname = first;
+ if (!last.empty()
+ && last != "Resident")
+ {
+ fullname += ' ';
+ fullname += last;
+ }
+ return fullname;
+}
+
+//static
+std::string LLCacheName::cleanFullName(const std::string& full_name)
+{
+ return full_name.substr(0, full_name.find(" Resident"));
+}
+
+//static
+std::string LLCacheName::buildUsername(const std::string& full_name)
+{
+ // rare, but handle hard-coded error names returned from server
+ if (full_name == "(\?\?\?) (\?\?\?)")
+ {
+ return "(\?\?\?)";
+ }
+
+ std::string::size_type index = full_name.find(' ');
+
+ if (index != std::string::npos)
+ {
+ std::string username;
+ username = full_name.substr(0, index);
+ std::string lastname = full_name.substr(index+1);
+
+ if (lastname != "Resident")
+ {
+ username = username + "." + lastname;
+ }
+
+ LLStringUtil::toLower(username);
+ return username;
+ }
+
+ // if the input wasn't a correctly formatted legacy name just return it unchanged
+ return full_name;
+}
+
// This is a little bit kludgy. LLCacheNameCallback is a slot instead of a function pointer.
// The reason it is a slot is so that the legacy get() function below can bind an old callback
// and pass it as a slot. The reason it isn't a boost::function is so that trackable behavior
@@ -586,7 +564,7 @@ BOOL LLCacheName::getUUID(const std::string& fullname, LLUUID& id)
// we call it immediately. -Steve
// NOTE: Even though passing first and last name is a bit of extra overhead, it eliminates the
// potential need for any parsing should any code need to handle first and last name independently.
-boost::signals2::connection LLCacheName::get(const LLUUID& id, BOOL is_group, const LLCacheNameCallback& callback)
+boost::signals2::connection LLCacheName::get(const LLUUID& id, bool is_group, const LLCacheNameCallback& callback)
{
boost::signals2::connection res;
@@ -594,7 +572,7 @@ boost::signals2::connection LLCacheName::get(const LLUUID& id, BOOL is_group, co
{
LLCacheNameSignal signal;
signal.connect(callback);
- signal(id, sCacheName["nobody"], "", is_group);
+ signal(id, sCacheName["nobody"], is_group);
return res;
}
@@ -606,11 +584,13 @@ boost::signals2::connection LLCacheName::get(const LLUUID& id, BOOL is_group, co
// id found in map therefore we can call the callback immediately.
if (entry->mIsGroup)
{
- signal(id, entry->mGroupName, "", entry->mIsGroup);
+ signal(id, entry->mGroupName, entry->mIsGroup);
}
else
{
- signal(id, entry->mFirstName, entry->mLastName, entry->mIsGroup);
+ std::string fullname =
+ buildFullName(entry->mFirstName, entry->mLastName);
+ signal(id, fullname, entry->mIsGroup);
}
}
else
@@ -632,9 +612,15 @@ boost::signals2::connection LLCacheName::get(const LLUUID& id, BOOL is_group, co
return res;
}
-boost::signals2::connection LLCacheName::get(const LLUUID& id, BOOL is_group, old_callback_t callback, void* user_data)
+boost::signals2::connection LLCacheName::getGroup(const LLUUID& group_id,
+ const LLCacheNameCallback& callback)
+{
+ return get(group_id, true, callback);
+}
+
+boost::signals2::connection LLCacheName::get(const LLUUID& id, bool is_group, old_callback_t callback, void* user_data)
{
- return get(id, is_group, boost::bind(callback, _1, _2, _3, _4, user_data));
+ return get(id, is_group, boost::bind(callback, _1, _2, _3, user_data));
}
void LLCacheName::processPending()
@@ -706,7 +692,7 @@ void LLCacheName::dump()
{
llinfos
<< iter->first << " = "
- << entry->mFirstName << " " << entry->mLastName
+ << buildFullName(entry->mFirstName, entry->mLastName)
<< " @ " << entry->mCreateTime
<< llendl;
}
@@ -725,12 +711,24 @@ void LLCacheName::dumpStats()
<< llendl;
}
+void LLCacheName::clear()
+{
+ for_each(impl.mCache.begin(), impl.mCache.end(), DeletePairedPointer());
+ impl.mCache.clear();
+}
+
//static
std::string LLCacheName::getDefaultName()
{
return sCacheName["waiting"];
}
+//static
+std::string LLCacheName::getDefaultLastName()
+{
+ return "Resident";
+}
+
void LLCacheName::Impl::processPendingAsks()
{
LLMemType mt_ppa(LLMemType::MTYPE_CACHE_PROCESS_PENDING_ASKS);
@@ -752,11 +750,13 @@ void LLCacheName::Impl::processPendingReplies()
if (!entry->mIsGroup)
{
- (reply->mSignal)(reply->mID, entry->mFirstName, entry->mLastName, FALSE);
+ std::string fullname =
+ LLCacheName::buildFullName(entry->mFirstName, entry->mLastName);
+ (reply->mSignal)(reply->mID, fullname, false);
}
else
{
- (reply->mSignal)(reply->mID, entry->mGroupName, "", TRUE);
+ (reply->mSignal)(reply->mID, entry->mGroupName, true);
}
}
@@ -927,13 +927,27 @@ void LLCacheName::Impl::processUUIDReply(LLMessageSystem* msg, bool isGroup)
if (!isGroup)
{
- mSignal(id, entry->mFirstName, entry->mLastName, FALSE);
- std::string fullname = entry->mFirstName + " " + entry->mLastName;
- mReverseCache[fullname] = id;
+ // NOTE: Very occasionally the server sends down a full name
+ // in the first name field with an empty last name, for example,
+ // first = "Ladanie1 Resident", last = "".
+ // I cannot reproduce this, nor can I find a bug in the server code.
+ // Ensure "Resident" does not appear via cleanFullName, because
+ // buildFullName only checks last name. JC
+ std::string full_name;
+ if (entry->mLastName.empty())
+ {
+ full_name = cleanFullName(entry->mFirstName);
+ }
+ else
+ {
+ full_name = LLCacheName::buildFullName(entry->mFirstName, entry->mLastName);
+ }
+ mSignal(id, full_name, false);
+ mReverseCache[full_name] = id;
}
else
{
- mSignal(id, entry->mGroupName, "", TRUE);
+ mSignal(id, entry->mGroupName, true);
mReverseCache[entry->mGroupName] = id;
}
}
@@ -962,4 +976,3 @@ void LLCacheName::Impl::handleUUIDGroupNameReply(LLMessageSystem* msg, void** us
{
((LLCacheName::Impl*)userData)->processUUIDReply(msg, true);
}
-
diff --git a/indra/llmessage/llcachename.h b/indra/llmessage/llcachename.h
index 111cc8b650..697bb27556 100644
--- a/indra/llmessage/llcachename.h
+++ b/indra/llmessage/llcachename.h
@@ -42,13 +42,12 @@ class LLUUID;
typedef boost::signals2::signal<void (const LLUUID& id,
- const std::string& first_name,
- const std::string& last_name,
- BOOL is_group)> LLCacheNameSignal;
+ const std::string& name,
+ bool is_group)> LLCacheNameSignal;
typedef LLCacheNameSignal::slot_type LLCacheNameCallback;
// Old callback with user data for compatability
-typedef void (*old_callback_t)(const LLUUID&, const std::string&, const std::string&, BOOL, void*);
+typedef void (*old_callback_t)(const LLUUID&, const std::string&, bool, void*);
// Here's the theory:
// If you request a name that isn't in the cache, it returns "waiting"
@@ -71,24 +70,31 @@ public:
boost::signals2::connection addObserver(const LLCacheNameCallback& callback);
- // janky old format. Remove after a while. Phoenix. 2008-01-30
- void importFile(LLFILE* fp);
-
// storing cache on disk; for viewer, in name.cache
bool importFile(std::istream& istr);
void exportFile(std::ostream& ostr);
- // If available, copies the first and last name into the strings provided.
- // first must be at least DB_FIRST_NAME_BUF_SIZE characters.
- // last must be at least DB_LAST_NAME_BUF_SIZE characters.
+ // If available, copies name ("bobsmith123" or "James Linden") into string
// If not available, copies the string "waiting".
// Returns TRUE iff available.
- BOOL getName(const LLUUID& id, std::string& first, std::string& last);
- BOOL getFullName(const LLUUID& id, std::string& fullname);
-
+ BOOL getFullName(const LLUUID& id, std::string& full_name);
+
// Reverse lookup of UUID from name
BOOL getUUID(const std::string& first, const std::string& last, LLUUID& id);
BOOL getUUID(const std::string& fullname, LLUUID& id);
+
+ // IDEVO Temporary code
+ // Clean up new-style "bobsmith123 Resident" names to "bobsmith123" for display
+ static std::string buildFullName(const std::string& first, const std::string& last);
+
+ // Clean up legacy "bobsmith123 Resident" to "bobsmith123"
+ // If name does not contain "Resident" returns it unchanged.
+ static std::string cleanFullName(const std::string& full_name);
+
+ // Converts a standard legacy name to a username
+ // "bobsmith123 Resident" -> "bobsmith"
+ // "Random Linden" -> "random.linden"
+ static std::string buildUsername(const std::string& name);
// If available, this method copies the group name into the string
// provided. The caller must allocate at least
@@ -100,10 +106,15 @@ public:
// If the data is currently available, may call the callback immediatly
// otherwise, will request the data, and will call the callback when
// available. There is no garuntee the callback will ever be called.
- boost::signals2::connection get(const LLUUID& id, BOOL is_group, const LLCacheNameCallback& callback);
-
+ boost::signals2::connection get(const LLUUID& id, bool is_group, const LLCacheNameCallback& callback);
+
+ // Convenience method for looking up a group name, so you can
+ // tell the difference between avatar lookup and group lookup
+ // in global searches
+ boost::signals2::connection getGroup(const LLUUID& group_id, const LLCacheNameCallback& callback);
+
// LEGACY
- boost::signals2::connection get(const LLUUID& id, BOOL is_group, old_callback_t callback, void* user_data);
+ boost::signals2::connection get(const LLUUID& id, bool is_group, old_callback_t callback, void* user_data);
// This method needs to be called from time to time to send out
// requests.
void processPending();
@@ -114,9 +125,15 @@ public:
// Debugging
void dump(); // Dumps the contents of the cache
void dumpStats(); // Dumps the sizes of the cache and associated queues.
+ void clear(); // Deletes all entries from the cache
static std::string getDefaultName();
- static void LocalizeCacheName(std::string key, std::string value);
+
+ // Returns "Resident", the default last name for SLID-based accounts
+ // that have no last name.
+ static std::string getDefaultLastName();
+
+ static void localizeCacheName(std::string key, std::string value);
static std::map<std::string, std::string> sCacheName;
private:
diff --git a/indra/llmessage/mean_collision_data.h b/indra/llmessage/mean_collision_data.h
index 03b96f9f90..a6c635e81e 100644
--- a/indra/llmessage/mean_collision_data.h
+++ b/indra/llmessage/mean_collision_data.h
@@ -61,7 +61,7 @@ public:
LLMeanCollisionData(LLMeanCollisionData *mcd)
: mVictim(mcd->mVictim), mPerp(mcd->mPerp), mTime(mcd->mTime), mType(mcd->mType), mMag(mcd->mMag),
- mFirstName(mcd->mFirstName), mLastName(mcd->mLastName)
+ mFullName(mcd->mFullName)
{
}
@@ -95,8 +95,7 @@ public:
time_t mTime;
EMeanCollisionType mType;
F32 mMag;
- std::string mFirstName;
- std::string mLastName;
+ std::string mFullName;
};
diff --git a/indra/llmessage/tests/llavatarnamecache_test.cpp b/indra/llmessage/tests/llavatarnamecache_test.cpp
new file mode 100644
index 0000000000..eeadb703d1
--- /dev/null
+++ b/indra/llmessage/tests/llavatarnamecache_test.cpp
@@ -0,0 +1,109 @@
+/**
+ * @file llhost_test.cpp
+ * @author Adroit
+ * @date 2007-02
+ * @brief llhost test cases.
+ *
+ * $LicenseInfo:firstyear=2007&license=viewergpl$
+ *
+ * Copyright (c) 2007-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "../llavatarnamecache.h"
+
+#include "../test/lltut.h"
+
+namespace tut
+{
+ struct avatarnamecache_data
+ {
+ };
+ typedef test_group<avatarnamecache_data> avatarnamecache_test;
+ typedef avatarnamecache_test::object avatarnamecache_object;
+ tut::avatarnamecache_test avatarnamecache_testcase("llavatarnamecache");
+
+ template<> template<>
+ void avatarnamecache_object::test<1>()
+ {
+ bool valid = false;
+ S32 max_age = 0;
+
+ valid = max_age_from_cache_control("max-age=3600", &max_age);
+ ensure("typical input valid", valid);
+ ensure_equals("typical input parsed", max_age, 3600);
+
+ valid = max_age_from_cache_control(
+ " max-age=600 , no-cache,private=\"stuff\" ", &max_age);
+ ensure("complex input valid", valid);
+ ensure_equals("complex input parsed", max_age, 600);
+
+ valid = max_age_from_cache_control(
+ "no-cache, max-age = 123 ", &max_age);
+ ensure("complex input 2 valid", valid);
+ ensure_equals("complex input 2 parsed", max_age, 123);
+ }
+
+ template<> template<>
+ void avatarnamecache_object::test<2>()
+ {
+ bool valid = false;
+ S32 max_age = -1;
+
+ valid = max_age_from_cache_control("", &max_age);
+ ensure("empty input returns invalid", !valid);
+ ensure_equals("empty input doesn't change val", max_age, -1);
+
+ valid = max_age_from_cache_control("no-cache", &max_age);
+ ensure("no max-age field returns invalid", !valid);
+
+ valid = max_age_from_cache_control("max", &max_age);
+ ensure("just 'max' returns invalid", !valid);
+
+ valid = max_age_from_cache_control("max-age", &max_age);
+ ensure("partial max-age is invalid", !valid);
+
+ valid = max_age_from_cache_control("max-age=", &max_age);
+ ensure("longer partial max-age is invalid", !valid);
+
+ valid = max_age_from_cache_control("max-age=FOO", &max_age);
+ ensure("invalid integer max-age is invalid", !valid);
+
+ valid = max_age_from_cache_control("max-age 234", &max_age);
+ ensure("space separated max-age is invalid", !valid);
+
+ valid = max_age_from_cache_control("max-age=0", &max_age);
+ ensure("zero max-age is valid", valid);
+
+ // *TODO: Handle "0000" as zero
+ //valid = max_age_from_cache_control("max-age=0000", &max_age);
+ //ensure("multi-zero max-age is valid", valid);
+
+ valid = max_age_from_cache_control("max-age=-123", &max_age);
+ ensure("less than zero max-age is invalid", !valid);
+ }
+}
diff --git a/indra/llui/llcombobox.cpp b/indra/llui/llcombobox.cpp
index cc107c972d..f49069f065 100644
--- a/indra/llui/llcombobox.cpp
+++ b/indra/llui/llcombobox.cpp
@@ -58,8 +58,6 @@
#include "lltooltip.h"
// Globals
-S32 LLCOMBOBOX_HEIGHT = 0;
-S32 LLCOMBOBOX_WIDTH = 0;
S32 MAX_COMBO_WIDTH = 500;
static LLDefaultChildRegistry::Register<LLComboBox> register_combo_box("combo_box");
@@ -711,10 +709,10 @@ void LLComboBox::onItemSelected(const LLSD& data)
setLabel(getSelectedItemLabel());
if (mAllowTextEntry)
- {
- gFocusMgr.setKeyboardFocus(mTextEntry);
- mTextEntry->selectAll();
- }
+ {
+ gFocusMgr.setKeyboardFocus(mTextEntry);
+ mTextEntry->selectAll();
+ }
}
// hiding the list reasserts the old value stored in the text editor/dropdown button
hideList();
diff --git a/indra/llui/llcombobox.h b/indra/llui/llcombobox.h
index f0bd432f3a..7f93cd1477 100644
--- a/indra/llui/llcombobox.h
+++ b/indra/llui/llcombobox.h
@@ -49,9 +49,6 @@
class LLFontGL;
class LLViewBorder;
-extern S32 LLCOMBOBOX_HEIGHT;
-extern S32 LLCOMBOBOX_WIDTH;
-
class LLComboBox
: public LLUICtrl, public LLCtrlListInterface
{
@@ -230,8 +227,8 @@ private:
commit_callback_t mPrearrangeCallback;
commit_callback_t mTextEntryCallback;
commit_callback_t mSelectionCallback;
- boost::signals2::connection mTopLostSignalConnection;
- S32 mLastSelectedIndex;
+ boost::signals2::connection mTopLostSignalConnection;
+ S32 mLastSelectedIndex;
};
// A combo box with icons for the list of items.
diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp
index 621e72ce38..75b92e47da 100644
--- a/indra/llui/llnotifications.cpp
+++ b/indra/llui/llnotifications.cpp
@@ -34,6 +34,9 @@
#include "llnotifications.h"
+#include "llavatarnamecache.h"
+#include "llinstantmessage.h"
+#include "llcachename.h"
#include "llxmlnode.h"
#include "lluictrl.h"
#include "lluictrlfactory.h"
@@ -41,6 +44,7 @@
#include "llsdserialize.h"
#include "lltrans.h"
#include "llnotificationslistener.h"
+#include "llstring.h"
#include <algorithm>
#include <boost/regex.hpp>
@@ -1484,10 +1488,50 @@ std::ostream& operator<<(std::ostream& s, const LLNotification& notification)
return s;
}
-void LLPostponedNotification::onCachedNameReceived(const LLUUID& id, const std::string& first,
- const std::string& last, bool is_group)
+//static
+void LLPostponedNotification::lookupName(LLPostponedNotification* thiz,
+ const LLUUID& id,
+ bool is_group)
+{
+ if (is_group)
+ {
+ gCacheName->getGroup(id,
+ boost::bind(&LLPostponedNotification::onGroupNameCache,
+ thiz, _1, _2, _3));
+ }
+ else
+ {
+ LLAvatarNameCache::get(id,
+ boost::bind(&LLPostponedNotification::onAvatarNameCache,
+ thiz, _1, _2));
+ }
+}
+
+void LLPostponedNotification::onGroupNameCache(const LLUUID& id,
+ const std::string& full_name,
+ bool is_group)
+{
+ finalizeName(full_name);
+}
+
+void LLPostponedNotification::onAvatarNameCache(const LLUUID& agent_id,
+ const LLAvatarName& av_name)
+{
+ std::string name = av_name.getCompleteName();
+
+ // from PE merge - we should figure out if this is the right thing to do
+ if (name.empty())
+ {
+ llwarns << "Empty name received for Id: " << agent_id << llendl;
+ name = SYSTEM_FROM;
+ }
+
+ finalizeName(name);
+}
+
+void LLPostponedNotification::finalizeName(const std::string& name)
{
- gCacheName->getFullName(id, mName);
+ mName = name;
modifyNotificationParams();
LLNotifications::instance().add(mParams);
cleanup();
diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h
index 8bfada0e71..fd6f79d831 100644
--- a/indra/llui/llnotifications.h
+++ b/indra/llui/llnotifications.h
@@ -104,8 +104,8 @@
#include "llinitparam.h"
#include "llnotificationslistener.h"
#include "llnotificationptr.h"
-#include "llcachename.h"
+class LLAvatarName;
typedef enum e_notification_priority
{
@@ -998,17 +998,20 @@ public:
{
// upcast T to the base type to restrict T derivation from LLPostponedNotification
LLPostponedNotification* thiz = new T();
-
thiz->mParams = params;
- gCacheName->get(id, is_group, boost::bind(
- &LLPostponedNotification::onCachedNameReceived, thiz, _1, _2,
- _3, _4));
+ // Avoid header file dependency on llcachename.h
+ lookupName(thiz, id, is_group);
}
private:
- void onCachedNameReceived(const LLUUID& id, const std::string& first,
- const std::string& last, bool is_group);
+ static void lookupName(LLPostponedNotification* thiz, const LLUUID& id, bool is_group);
+ // only used for groups
+ void onGroupNameCache(const LLUUID& id, const std::string& full_name, bool is_group);
+ // only used for avatars
+ void onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name);
+ // used for both group and avatar names
+ void finalizeName(const std::string& name);
void cleanup()
{
diff --git a/indra/llui/llstyle.cpp b/indra/llui/llstyle.cpp
index b8f93b6a0e..5965ca6fb5 100644
--- a/indra/llui/llstyle.cpp
+++ b/indra/llui/llstyle.cpp
@@ -44,7 +44,8 @@ LLStyle::Params::Params()
color("color", LLColor4::black),
font("font", LLFontGL::getFontMonospace()),
image("image"),
- link_href("href")
+ link_href("href"),
+ is_link("is_link")
{}
@@ -57,6 +58,7 @@ LLStyle::LLStyle(const LLStyle::Params& p)
mReadOnlyColor(p.readonly_color()),
mFont(p.font()),
mLink(p.link_href),
+ mIsLink(p.is_link.isProvided() ? p.is_link : !p.link_href().empty()),
mDropShadow(p.drop_shadow),
mImagep(p.image())
{}
@@ -79,7 +81,7 @@ void LLStyle::setLinkHREF(const std::string& href)
BOOL LLStyle::isLink() const
{
- return mLink.size();
+ return mIsLink;
}
BOOL LLStyle::isVisible() const
diff --git a/indra/llui/llstyle.h b/indra/llui/llstyle.h
index 2067e8e8be..0ca1f2027e 100644
--- a/indra/llui/llstyle.h
+++ b/indra/llui/llstyle.h
@@ -51,6 +51,7 @@ public:
Optional<const LLFontGL*> font;
Optional<LLUIImage*> image;
Optional<std::string> link_href;
+ Optional<bool> is_link;
Params();
};
LLStyle(const Params& p = Params());
@@ -113,6 +114,7 @@ private:
std::string mFontName;
const LLFontGL* mFont; // cached for performance
std::string mLink;
+ bool mIsLink;
LLUIImagePtr mImagep;
};
diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp
index d3b2a368a5..f8e97f2b39 100644
--- a/indra/llui/lltextbase.cpp
+++ b/indra/llui/lltextbase.cpp
@@ -976,9 +976,9 @@ void LLTextBase::reshape(S32 width, S32 height, BOOL called_from_parent)
if (width != getRect().getWidth() || height != getRect().getHeight())
{
bool scrolled_to_bottom = mScroller ? mScroller->isAtBottom() : false;
-
+
LLUICtrl::reshape( width, height, called_from_parent );
-
+
if (mScroller && scrolled_to_bottom && mTrackEnd)
{
// keep bottom of text buffer visible
@@ -987,7 +987,7 @@ void LLTextBase::reshape(S32 width, S32 height, BOOL called_from_parent)
// not be scrolled to the bottom, since the scroll index
// specified the _top_ of the visible document region
mScroller->goToBottom();
- }
+ }
// do this first after reshape, because other things depend on
// up-to-date mVisibleTextRect
@@ -1298,28 +1298,28 @@ void LLTextBase::reflow()
}
}
- // apply scroll constraints after reflowing text
- if (!hasMouseCapture() && mScroller)
- {
- if (scrolled_to_bottom && mTrackEnd)
+ // apply scroll constraints after reflowing text
+ if (!hasMouseCapture() && mScroller)
{
- // keep bottom of text buffer visible
- endOfDoc();
- }
- else if (hasSelection() && follow_selection)
- {
- // keep cursor in same vertical position on screen when selecting text
- LLRect new_cursor_rect_doc = getDocRectFromDocIndex(mCursorPos);
+ if (scrolled_to_bottom && mTrackEnd)
+ {
+ // keep bottom of text buffer visible
+ endOfDoc();
+ }
+ else if (hasSelection() && follow_selection)
+ {
+ // keep cursor in same vertical position on screen when selecting text
+ LLRect new_cursor_rect_doc = getDocRectFromDocIndex(mCursorPos);
LLRect old_cursor_rect = cursor_rect;
old_cursor_rect.mTop = mVisibleTextRect.mTop - cursor_rect.mTop;
old_cursor_rect.mBottom = mVisibleTextRect.mTop - cursor_rect.mBottom;
- mScroller->scrollToShowRect(new_cursor_rect_doc, old_cursor_rect);
- }
- else
- {
- // keep first line of text visible
- LLRect new_first_char_rect = getDocRectFromDocIndex(mScrollIndex);
+ mScroller->scrollToShowRect(new_cursor_rect_doc, old_cursor_rect);
+ }
+ else
+ {
+ // keep first line of text visible
+ LLRect new_first_char_rect = getDocRectFromDocIndex(mScrollIndex);
// pass in desired rect in the coordinate frame of the document viewport
LLRect old_first_char_rect = first_char_rect;
@@ -1327,12 +1327,12 @@ void LLTextBase::reflow()
old_first_char_rect.mBottom = mVisibleTextRect.mTop - first_char_rect.mBottom;
mScroller->scrollToShowRect(new_first_char_rect, old_first_char_rect);
+ }
}
- }
- // reset desired x cursor position
- updateCursorXPos();
-}
+ // reset desired x cursor position
+ updateCursorXPos();
+ }
LLRect LLTextBase::getTextBoundingRect()
{
@@ -1603,6 +1603,20 @@ std::string LLTextBase::getText() const
return getViewModel()->getValue().asString();
}
+// IDEVO - icons can be UI image names or UUID sent from
+// server with avatar display name
+static LLUIImagePtr image_from_icon_name(const std::string& icon_name)
+{
+ if (LLUUID::validate(icon_name))
+ {
+ return LLUI::getUIImageByID( LLUUID(icon_name) );
+ }
+ else
+ {
+ return LLUI::getUIImage(icon_name);
+ }
+}
+
void LLTextBase::appendTextImpl(const std::string &new_text, const LLStyle::Params& input_params)
{
LLStyle::Params style_params(input_params);
@@ -1615,7 +1629,7 @@ void LLTextBase::appendTextImpl(const std::string &new_text, const LLStyle::Para
LLUrlMatch match;
std::string text = new_text;
while ( LLUrlRegistry::instance().findUrl(text, match,
- boost::bind(&LLTextBase::replaceUrlLabel, this, _1, _2)) )
+ boost::bind(&LLTextBase::replaceUrl, this, _1, _2, _3)) )
{
LLTextUtil::processUrlMatch(&match,this);
@@ -1623,11 +1637,8 @@ void LLTextBase::appendTextImpl(const std::string &new_text, const LLStyle::Para
start = match.getStart();
end = match.getEnd()+1;
- LLStyle::Params link_params = style_params;
- link_params.color = match.getColor();
- link_params.readonly_color = match.getColor();
- link_params.font.style("UNDERLINE");
- link_params.link_href = match.getUrl();
+ LLStyle::Params link_params(style_params);
+ link_params.overwriteFrom(match.getStyle());
// output the text before the Url
if (start > 0)
@@ -1644,26 +1655,21 @@ void LLTextBase::appendTextImpl(const std::string &new_text, const LLStyle::Para
std::string subtext=text.substr(0,start);
appendAndHighlightText(subtext, part, style_params);
}
- // output the styled Url (unless we've been asked to suppress hyperlinking)
- if (match.isLinkDisabled())
+
+ // output the styled Url
+ appendAndHighlightTextImpl(match.getLabel(), part, link_params);
+
+ // set the tooltip for the Url label
+ if (! match.getTooltip().empty())
{
- appendAndHighlightText(match.getLabel(), part, style_params);
+ segment_set_t::iterator it = getSegIterContaining(getLength()-1);
+ if (it != mSegments.end())
+ {
+ LLTextSegmentPtr segment = *it;
+ segment->setToolTip(match.getTooltip());
+ }
}
- else
- {
- appendAndHighlightText(match.getLabel(), part, link_params);
- // set the tooltip for the Url label
- if (! match.getTooltip().empty())
- {
- segment_set_t::iterator it = getSegIterContaining(getLength()-1);
- if (it != mSegments.end())
- {
- LLTextSegmentPtr segment = *it;
- segment->setToolTip(match.getTooltip());
- }
- }
- }
// move on to the rest of the text after the Url
if (end < (S32)text.length())
{
@@ -1761,7 +1767,7 @@ void LLTextBase::appendAndHighlightTextImpl(const std::string &new_text, S32 hig
highlight_params.color = lcolor;
LLWString wide_text;
- wide_text = utf8str_to_wstring(pieces[i]["text"].asString());
+ wide_text = utf8str_to_wstring(pieces[i]["text"].asString());
S32 cur_length = getLength();
LLStyleConstSP sp(new LLStyle(highlight_params));
@@ -1774,7 +1780,7 @@ void LLTextBase::appendAndHighlightTextImpl(const std::string &new_text, S32 hig
else
{
LLWString wide_text;
- wide_text = utf8str_to_wstring(new_text);
+ wide_text = utf8str_to_wstring(new_text);
segment_vec_t segments;
S32 segment_start = old_length;
@@ -1828,8 +1834,9 @@ void LLTextBase::appendAndHighlightText(const std::string &new_text, S32 highlig
}
-void LLTextBase::replaceUrlLabel(const std::string &url,
- const std::string &label)
+void LLTextBase::replaceUrl(const std::string &url,
+ const std::string &label,
+ const std::string &icon)
{
// get the full (wide) text for the editor so we can change it
LLWString text = getWText();
@@ -1850,7 +1857,7 @@ void LLTextBase::replaceUrlLabel(const std::string &url,
seg->setEnd(seg_start + seg_length);
// if we find a link with our Url, then replace the label
- if (style->isLink() && style->getLinkHREF() == url)
+ if (style->getLinkHREF() == url)
{
S32 start = seg->getStart();
S32 end = seg->getEnd();
@@ -1859,6 +1866,21 @@ void LLTextBase::replaceUrlLabel(const std::string &url,
modified = true;
}
+ // Icon might be updated when more avatar or group info
+ // becomes available
+ if (style->isImage() && style->getLinkHREF() == url)
+ {
+ LLUIImagePtr image = image_from_icon_name( icon );
+ if (image)
+ {
+ LLStyle::Params icon_params;
+ icon_params.image = image;
+ LLStyleConstSP new_style(new LLStyle(icon_params));
+ seg->setStyle(new_style);
+ modified = true;
+ }
+ }
+
// work out the character offset for the next segment
seg_start = seg->getEnd();
}
@@ -1956,8 +1978,8 @@ S32 LLTextBase::getDocIndexFromLocalCoord( S32 local_x, S32 local_y, BOOL round,
else if (hit_past_end_of_line && segmentp->getEnd() > line_iter->mDocIndexEnd - 1)
{
// segment wraps to next line, so just set doc pos to the end of the line
- // segment wraps to next line, so just set doc pos to start of next line (represented by mDocIndexEnd)
- pos = llmin(getLength(), line_iter->mDocIndexEnd);
+ // segment wraps to next line, so just set doc pos to start of next line (represented by mDocIndexEnd)
+ pos = llmin(getLength(), line_iter->mDocIndexEnd);
break;
}
start_x += text_width;
@@ -2613,8 +2635,8 @@ bool LLNormalTextSegment::getDimensions(S32 first_char, S32 num_chars, S32& widt
height = mFontHeight;
const LLWString &text = mEditor.getWText();
// if last character is a newline, then return true, forcing line break
- width = mStyle->getFont()->getWidth(text.c_str(), mStart + first_char, num_chars);
- }
+ width = mStyle->getFont()->getWidth(text.c_str(), mStart + first_char, num_chars);
+ }
return false;
}
diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h
index 4b0eeeb7d6..63451a2ae0 100644
--- a/indra/llui/lltextbase.h
+++ b/indra/llui/lltextbase.h
@@ -481,7 +481,11 @@ protected:
// misc
void updateRects();
void needsScroll() { mScrollNeeded = TRUE; }
- void replaceUrlLabel(const std::string &url, const std::string &label);
+
+ struct URLLabelCallback;
+ // Replace a URL with a new icon and label, for example, when
+ // avatar names are looked up.
+ void replaceUrl(const std::string &url, const std::string &label, const std::string& icon);
void appendTextImpl(const std::string &new_text, const LLStyle::Params& input_params = LLStyle::Params());
void appendAndHighlightTextImpl(const std::string &new_text, S32 highlight_part, const LLStyle::Params& style_params);
diff --git a/indra/llui/llurlentry.cpp b/indra/llui/llurlentry.cpp
index e075699a6e..c408f8d8b5 100644
--- a/indra/llui/llurlentry.cpp
+++ b/indra/llui/llurlentry.cpp
@@ -37,18 +37,19 @@
#include "llurlmatch.h"
#include "llurlregistry.h"
+#include "llavatarnamecache.h"
#include "llcachename.h"
#include "lltrans.h"
#include "lluicolortable.h"
#define APP_HEADER_REGEX "((x-grid-location-info://[-\\w\\.]+/app)|(secondlife:///app))"
+// Utility functions
+std::string localize_slapp_label(const std::string& url, const std::string& full_name);
-LLUrlEntryBase::LLUrlEntryBase() :
- mColor(LLUIColorTable::instance().getColor("HTMLLinkColor")),
- mDisabledLink(false)
-{
-}
+
+LLUrlEntryBase::LLUrlEntryBase()
+{}
LLUrlEntryBase::~LLUrlEntryBase()
{
@@ -59,6 +60,22 @@ std::string LLUrlEntryBase::getUrl(const std::string &string) const
return escapeUrl(string);
}
+//virtual
+std::string LLUrlEntryBase::getIcon(const std::string &url)
+{
+ return mIcon;
+}
+
+LLStyle::Params LLUrlEntryBase::getStyle() const
+{
+ LLStyle::Params style_params;
+ style_params.color = LLUIColorTable::instance().getColor("HTMLLinkColor");
+ style_params.readonly_color = LLUIColorTable::instance().getColor("HTMLLinkColor");
+ style_params.font.style = "UNDERLINE";
+ return style_params;
+}
+
+
std::string LLUrlEntryBase::getIDStringFromUrl(const std::string &url) const
{
// return the id from a SLURL in the format /app/{cmd}/{id}/about
@@ -136,16 +153,20 @@ void LLUrlEntryBase::addObserver(const std::string &id,
mObservers.insert(std::pair<std::string, LLUrlEntryObserver>(id, observer));
}
}
-
-void LLUrlEntryBase::callObservers(const std::string &id, const std::string &label)
+
+// *NOTE: See also LLUrlEntryAgent::callObservers()
+void LLUrlEntryBase::callObservers(const std::string &id,
+ const std::string &label,
+ const std::string &icon)
{
// notify all callbacks waiting on the given uuid
- std::multimap<std::string, LLUrlEntryObserver>::iterator it;
- for (it = mObservers.find(id); it != mObservers.end();)
+ typedef std::multimap<std::string, LLUrlEntryObserver>::iterator observer_it;
+ std::pair<observer_it, observer_it> matching_range = mObservers.equal_range(id);
+ for (observer_it it = matching_range.first; it != matching_range.second;)
{
// call the callback - give it the new label
LLUrlEntryObserver &observer = it->second;
- (*observer.signal)(it->second.url, label);
+ (*observer.signal)(it->second.url, label, icon);
// then remove the signal - we only need to call it once
delete observer.signal;
mObservers.erase(it++);
@@ -314,16 +335,35 @@ LLUrlEntryAgent::LLUrlEntryAgent()
boost::regex::perl|boost::regex::icase);
mMenuName = "menu_url_agent.xml";
mIcon = "Generic_Person";
- mColor = LLUIColorTable::instance().getColor("AgentLinkColor");
}
-void LLUrlEntryAgent::onAgentNameReceived(const LLUUID& id,
- const std::string& first,
- const std::string& last,
- BOOL is_group)
+// virtual
+void LLUrlEntryAgent::callObservers(const std::string &id,
+ const std::string &label,
+ const std::string &icon)
{
+ // notify all callbacks waiting on the given uuid
+ typedef std::multimap<std::string, LLUrlEntryObserver>::iterator observer_it;
+ std::pair<observer_it, observer_it> matching_range = mObservers.equal_range(id);
+ for (observer_it it = matching_range.first; it != matching_range.second;)
+ {
+ // call the callback - give it the new label
+ LLUrlEntryObserver &observer = it->second;
+ std::string final_label = localize_slapp_label(observer.url, label);
+ (*observer.signal)(observer.url, final_label, icon);
+ // then remove the signal - we only need to call it once
+ delete observer.signal;
+ mObservers.erase(it++);
+ }
+}
+
+void LLUrlEntryAgent::onAvatarNameCache(const LLUUID& id,
+ const LLAvatarName& av_name)
+{
+ std::string label = av_name.getCompleteName();
+
// received the agent name from the server - tell our observers
- callObservers(id.asString(), first + " " + last);
+ callObservers(id.asString(), label, mIcon);
}
LLUUID LLUrlEntryAgent::getID(const std::string &string) const
@@ -336,6 +376,10 @@ std::string LLUrlEntryAgent::getTooltip(const std::string &string) const
// return a tooltip corresponding to the URL type instead of the generic one
std::string url = getUrl(string);
+ if (LLStringUtil::endsWith(url, "/inspect"))
+ {
+ return LLTrans::getString("TooltipAgentInspect");
+ }
if (LLStringUtil::endsWith(url, "/mute"))
{
return LLTrans::getString("TooltipAgentMute");
@@ -379,50 +423,182 @@ std::string LLUrlEntryAgent::getLabel(const std::string &url, const LLUrlLabelCa
}
LLUUID agent_id(agent_id_string);
- std::string full_name;
if (agent_id.isNull())
{
return LLTrans::getString("AvatarNameNobody");
}
- else if (gCacheName->getFullName(agent_id, full_name))
- {
- // customize label string based on agent SLapp suffix
- if (LLStringUtil::endsWith(url, "/mute"))
- {
- return LLTrans::getString("SLappAgentMute") + " " + full_name;
- }
- if (LLStringUtil::endsWith(url, "/unmute"))
- {
- return LLTrans::getString("SLappAgentUnmute") + " " + full_name;
- }
- if (LLStringUtil::endsWith(url, "/im"))
- {
- return LLTrans::getString("SLappAgentIM") + " " + full_name;
- }
- if (LLStringUtil::endsWith(url, "/pay"))
- {
- return LLTrans::getString("SLappAgentPay") + " " + full_name;
- }
- if (LLStringUtil::endsWith(url, "/offerteleport"))
- {
- return LLTrans::getString("SLappAgentOfferTeleport") + " " + full_name;
- }
- if (LLStringUtil::endsWith(url, "/requestfriend"))
- {
- return LLTrans::getString("SLappAgentRequestFriend") + " " + full_name;
- }
- return full_name;
+
+ LLAvatarName av_name;
+ if (LLAvatarNameCache::get(agent_id, &av_name))
+ {
+ std::string label = av_name.getCompleteName();
+
+ // handle suffixes like /mute or /offerteleport
+ label = localize_slapp_label(url, label);
+ return label;
}
else
{
- gCacheName->get(agent_id, FALSE,
- boost::bind(&LLUrlEntryAgent::onAgentNameReceived,
- this, _1, _2, _3, _4));
+ LLAvatarNameCache::get(agent_id,
+ boost::bind(&LLUrlEntryAgent::onAvatarNameCache,
+ this, _1, _2));
addObserver(agent_id_string, url, cb);
return LLTrans::getString("LoadingData");
}
}
+LLStyle::Params LLUrlEntryAgent::getStyle() const
+{
+ LLStyle::Params style_params = LLUrlEntryBase::getStyle();
+ style_params.color = LLUIColorTable::instance().getColor("AgentLinkColor");
+ style_params.readonly_color = LLUIColorTable::instance().getColor("AgentLinkColor");
+ return style_params;
+}
+
+std::string localize_slapp_label(const std::string& url, const std::string& full_name)
+{
+ // customize label string based on agent SLapp suffix
+ if (LLStringUtil::endsWith(url, "/mute"))
+ {
+ return LLTrans::getString("SLappAgentMute") + " " + full_name;
+ }
+ if (LLStringUtil::endsWith(url, "/unmute"))
+ {
+ return LLTrans::getString("SLappAgentUnmute") + " " + full_name;
+ }
+ if (LLStringUtil::endsWith(url, "/im"))
+ {
+ return LLTrans::getString("SLappAgentIM") + " " + full_name;
+ }
+ if (LLStringUtil::endsWith(url, "/pay"))
+ {
+ return LLTrans::getString("SLappAgentPay") + " " + full_name;
+ }
+ if (LLStringUtil::endsWith(url, "/offerteleport"))
+ {
+ return LLTrans::getString("SLappAgentOfferTeleport") + " " + full_name;
+ }
+ if (LLStringUtil::endsWith(url, "/requestfriend"))
+ {
+ return LLTrans::getString("SLappAgentRequestFriend") + " " + full_name;
+ }
+ return full_name;
+}
+
+
+std::string LLUrlEntryAgent::getIcon(const std::string &url)
+{
+ // *NOTE: Could look up a badge here by calling getIDStringFromUrl()
+ // and looking up the badge for the agent.
+ return mIcon;
+}
+
+//
+// LLUrlEntryAgentName describes a Second Life agent name Url, e.g.,
+// secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/(completename|displayname|username)
+// x-grid-location-info://lincoln.lindenlab.com/app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/(completename|displayname|username)
+//
+LLUrlEntryAgentName::LLUrlEntryAgentName()
+{}
+
+void LLUrlEntryAgentName::onAvatarNameCache(const LLUUID& id,
+ const LLAvatarName& av_name)
+{
+ std::string label = getName(av_name);
+ // received the agent name from the server - tell our observers
+ callObservers(id.asString(), label, mIcon);
+}
+
+std::string LLUrlEntryAgentName::getLabel(const std::string &url, const LLUrlLabelCallback &cb)
+{
+ if (!gCacheName)
+ {
+ // probably at the login screen, use short string for layout
+ return LLTrans::getString("LoadingData");
+ }
+
+ std::string agent_id_string = getIDStringFromUrl(url);
+ if (agent_id_string.empty())
+ {
+ // something went wrong, just give raw url
+ return unescapeUrl(url);
+ }
+
+ LLUUID agent_id(agent_id_string);
+ if (agent_id.isNull())
+ {
+ return LLTrans::getString("AvatarNameNobody");
+ }
+
+ LLAvatarName av_name;
+ if (LLAvatarNameCache::get(agent_id, &av_name))
+ {
+ return getName(av_name);
+ }
+ else
+ {
+ LLAvatarNameCache::get(agent_id,
+ boost::bind(&LLUrlEntryAgentCompleteName::onAvatarNameCache,
+ this, _1, _2));
+ addObserver(agent_id_string, url, cb);
+ return LLTrans::getString("LoadingData");
+ }
+}
+
+LLStyle::Params LLUrlEntryAgentName::getStyle() const
+{
+ // don't override default colors
+ return LLStyle::Params().is_link(false);
+}
+
+//
+// LLUrlEntryAgentCompleteName describes a Second Life agent complete name Url, e.g.,
+// secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/completename
+// x-grid-location-info://lincoln.lindenlab.com/app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/completename
+//
+LLUrlEntryAgentCompleteName::LLUrlEntryAgentCompleteName()
+{
+ mPattern = boost::regex(APP_HEADER_REGEX "/agent/[\\da-f-]+/completename",
+ boost::regex::perl|boost::regex::icase);
+}
+
+std::string LLUrlEntryAgentCompleteName::getName(const LLAvatarName& avatar_name)
+{
+ return avatar_name.getCompleteName();
+}
+
+//
+// LLUrlEntryAgentDisplayName describes a Second Life agent display name Url, e.g.,
+// secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/displayname
+// x-grid-location-info://lincoln.lindenlab.com/app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/displayname
+//
+LLUrlEntryAgentDisplayName::LLUrlEntryAgentDisplayName()
+{
+ mPattern = boost::regex(APP_HEADER_REGEX "/agent/[\\da-f-]+/displayname",
+ boost::regex::perl|boost::regex::icase);
+}
+
+std::string LLUrlEntryAgentDisplayName::getName(const LLAvatarName& avatar_name)
+{
+ return avatar_name.mDisplayName;
+}
+
+//
+// LLUrlEntryAgentUserName describes a Second Life agent user name Url, e.g.,
+// secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/username
+// x-grid-location-info://lincoln.lindenlab.com/app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/username
+//
+LLUrlEntryAgentUserName::LLUrlEntryAgentUserName()
+{
+ mPattern = boost::regex(APP_HEADER_REGEX "/agent/[\\da-f-]+/username",
+ boost::regex::perl|boost::regex::icase);
+}
+
+std::string LLUrlEntryAgentUserName::getName(const LLAvatarName& avatar_name)
+{
+ return avatar_name.mUsername.empty() ? avatar_name.getLegacyName() : avatar_name.mUsername;
+}
+
//
// LLUrlEntryGroup Describes a Second Life group Url, e.g.,
// secondlife:///app/group/00005ff3-4044-c79f-9de8-fb28ae0df991/about
@@ -436,18 +612,16 @@ LLUrlEntryGroup::LLUrlEntryGroup()
mMenuName = "menu_url_group.xml";
mIcon = "Generic_Group";
mTooltip = LLTrans::getString("TooltipGroupUrl");
- mColor = LLUIColorTable::instance().getColor("GroupLinkColor");
}
void LLUrlEntryGroup::onGroupNameReceived(const LLUUID& id,
- const std::string& first,
- const std::string& last,
- BOOL is_group)
+ const std::string& name,
+ bool is_group)
{
// received the group name from the server - tell our observers
- callObservers(id.asString(), first);
+ callObservers(id.asString(), name, mIcon);
}
LLUUID LLUrlEntryGroup::getID(const std::string &string) const
@@ -483,14 +657,23 @@ std::string LLUrlEntryGroup::getLabel(const std::string &url, const LLUrlLabelCa
}
else
{
- gCacheName->get(group_id, TRUE,
+ gCacheName->getGroup(group_id,
boost::bind(&LLUrlEntryGroup::onGroupNameReceived,
- this, _1, _2, _3, _4));
+ this, _1, _2, _3));
addObserver(group_id_string, url, cb);
return LLTrans::getString("LoadingData");
}
}
+LLStyle::Params LLUrlEntryGroup::getStyle() const
+{
+ LLStyle::Params style_params = LLUrlEntryBase::getStyle();
+ style_params.color = LLUIColorTable::instance().getColor("GroupLinkColor");
+ style_params.readonly_color = LLUIColorTable::instance().getColor("GroupLinkColor");
+ return style_params;
+}
+
+
//
// LLUrlEntryInventory Describes a Second Life inventory Url, e.g.,
// secondlife:///app/inventory/0e346d8b-4433-4d66-a6b0-fd37083abc4c/select
@@ -778,7 +961,6 @@ LLUrlEntryNoLink::LLUrlEntryNoLink()
{
mPattern = boost::regex("<nolink>[^<]*</nolink>",
boost::regex::perl|boost::regex::icase);
- mDisabledLink = true;
}
std::string LLUrlEntryNoLink::getUrl(const std::string &url) const
@@ -792,6 +974,12 @@ std::string LLUrlEntryNoLink::getLabel(const std::string &url, const LLUrlLabelC
return getUrl(url);
}
+LLStyle::Params LLUrlEntryNoLink::getStyle() const
+{
+ return LLStyle::Params();
+}
+
+
//
// LLUrlEntryIcon describes an icon with <icon>...</icon> tags
//
@@ -799,7 +987,6 @@ LLUrlEntryIcon::LLUrlEntryIcon()
{
mPattern = boost::regex("<icon\\s*>\\s*([^<]*)?\\s*</icon\\s*>",
boost::regex::perl|boost::regex::icase);
- mDisabledLink = true;
}
std::string LLUrlEntryIcon::getUrl(const std::string &url) const
diff --git a/indra/llui/llurlentry.h b/indra/llui/llurlentry.h
index 7d718b67a9..f60ef0d968 100644
--- a/indra/llui/llurlentry.h
+++ b/indra/llui/llurlentry.h
@@ -36,13 +36,17 @@
#include "lluuid.h"
#include "lluicolor.h"
+#include "llstyle.h"
#include <boost/signals2.hpp>
#include <boost/regex.hpp>
#include <string>
#include <map>
+class LLAvatarName;
+
typedef boost::signals2::signal<void (const std::string& url,
- const std::string& label)> LLUrlLabelSignal;
+ const std::string& label,
+ const std::string& icon)> LLUrlLabelSignal;
typedef LLUrlLabelSignal::slot_type LLUrlLabelCallback;
///
@@ -77,10 +81,10 @@ public:
virtual std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb) { return url; }
/// Return an icon that can be displayed next to Urls of this type
- virtual std::string getIcon(const std::string &url) { return mIcon; }
+ virtual std::string getIcon(const std::string &url);
- /// Return the color to render the displayed text
- LLUIColor getColor() const { return mColor; }
+ /// Return the style to render the displayed text
+ virtual LLStyle::Params getStyle() const;
/// Given a matched Url, return a tooltip string for the hyperlink
virtual std::string getTooltip(const std::string &string) const { return mTooltip; }
@@ -91,9 +95,6 @@ public:
/// Return the name of a SL location described by this Url, if any
virtual std::string getLocation(const std::string &url) const { return ""; }
- /// is this a match for a URL that should not be hyperlinked?
- bool isLinkDisabled() const { return mDisabledLink; }
-
virtual LLUUID getID(const std::string &string) const { return LLUUID::null; }
protected:
@@ -103,7 +104,7 @@ protected:
std::string getLabelFromWikiLink(const std::string &url) const;
std::string getUrlFromWikiLink(const std::string &string) const;
void addObserver(const std::string &id, const std::string &url, const LLUrlLabelCallback &cb);
- void callObservers(const std::string &id, const std::string &label);
+ virtual void callObservers(const std::string &id, const std::string &label, const std::string& icon);
typedef struct {
std::string url;
@@ -114,9 +115,7 @@ protected:
std::string mIcon;
std::string mMenuName;
std::string mTooltip;
- LLUIColor mColor;
std::multimap<std::string, LLUrlEntryObserver> mObservers;
- bool mDisabledLink;
};
///
@@ -165,17 +164,77 @@ public:
///
/// LLUrlEntryAgent Describes a Second Life agent Url, e.g.,
/// secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/about
-///
class LLUrlEntryAgent : public LLUrlEntryBase
{
public:
LLUrlEntryAgent();
/*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
+ /*virtual*/ std::string getIcon(const std::string &url);
/*virtual*/ std::string getTooltip(const std::string &string) const;
+ /*virtual*/ LLStyle::Params getStyle() const;
/*virtual*/ LLUUID getID(const std::string &string) const;
+protected:
+ /*virtual*/ void callObservers(const std::string &id, const std::string &label, const std::string& icon);
+private:
+ void onAvatarNameCache(const LLUUID& id, const LLAvatarName& av_name);
+};
+
+///
+/// LLUrlEntryAgentName Describes a Second Life agent name Url, e.g.,
+/// secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/(completename|displayname|username)
+/// that displays various forms of user name
+/// This is a base class for the various implementations of name display
+class LLUrlEntryAgentName : public LLUrlEntryBase
+{
+public:
+ LLUrlEntryAgentName();
+ /*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
+ /*virtual*/ LLStyle::Params getStyle() const;
+protected:
+ // override this to pull out relevant name fields
+ virtual std::string getName(const LLAvatarName& avatar_name) = 0;
+private:
+ void onAvatarNameCache(const LLUUID& id, const LLAvatarName& av_name);
+};
+
+
+///
+/// LLUrlEntryAgentCompleteName Describes a Second Life agent name Url, e.g.,
+/// secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/completename
+/// that displays the full display name + user name for an avatar
+/// such as "James Linden (james.linden)"
+class LLUrlEntryAgentCompleteName : public LLUrlEntryAgentName
+{
+public:
+ LLUrlEntryAgentCompleteName();
+private:
+ /*virtual*/ std::string getName(const LLAvatarName& avatar_name);
+};
+
+///
+/// LLUrlEntryAgentDisplayName Describes a Second Life agent display name Url, e.g.,
+/// secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/displayname
+/// that displays the just the display name for an avatar
+/// such as "James Linden"
+class LLUrlEntryAgentDisplayName : public LLUrlEntryAgentName
+{
+public:
+ LLUrlEntryAgentDisplayName();
+private:
+ /*virtual*/ std::string getName(const LLAvatarName& avatar_name);
+};
+
+///
+/// LLUrlEntryAgentUserName Describes a Second Life agent username Url, e.g.,
+/// secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/username
+/// that displays the just the display name for an avatar
+/// such as "james.linden"
+class LLUrlEntryAgentUserName : public LLUrlEntryAgentName
+{
+public:
+ LLUrlEntryAgentUserName();
private:
- void onAgentNameReceived(const LLUUID& id, const std::string& first,
- const std::string& last, BOOL is_group);
+ /*virtual*/ std::string getName(const LLAvatarName& avatar_name);
};
///
@@ -187,10 +246,10 @@ class LLUrlEntryGroup : public LLUrlEntryBase
public:
LLUrlEntryGroup();
/*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
+ /*virtual*/ LLStyle::Params getStyle() const;
/*virtual*/ LLUUID getID(const std::string &string) const;
private:
- void onGroupNameReceived(const LLUUID& id, const std::string& first,
- const std::string& last, BOOL is_group);
+ void onGroupNameReceived(const LLUUID& id, const std::string& name, bool is_group);
};
///
@@ -298,6 +357,7 @@ public:
LLUrlEntryNoLink();
/*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
/*virtual*/ std::string getUrl(const std::string &string) const;
+ /*virtual*/ LLStyle::Params getStyle() const;
};
///
diff --git a/indra/llui/llurlmatch.cpp b/indra/llui/llurlmatch.cpp
index 7c96665ce4..55ef07da36 100644
--- a/indra/llui/llurlmatch.cpp
+++ b/indra/llui/llurlmatch.cpp
@@ -42,16 +42,15 @@ LLUrlMatch::LLUrlMatch() :
mTooltip(""),
mIcon(""),
mMenuName(""),
- mLocation(""),
- mDisabledLink(false)
+ mLocation("")
{
}
void LLUrlMatch::setValues(U32 start, U32 end, const std::string &url,
const std::string &label, const std::string &tooltip,
- const std::string &icon, const LLUIColor& color,
+ const std::string &icon, const LLStyle::Params& style,
const std::string &menu, const std::string &location,
- bool disabled_link, const LLUUID& id)
+ const LLUUID& id)
{
mStart = start;
mEnd = end;
@@ -59,9 +58,9 @@ void LLUrlMatch::setValues(U32 start, U32 end, const std::string &url,
mLabel = label;
mTooltip = tooltip;
mIcon = icon;
- mColor = color;
+ mStyle = style;
+ mStyle.link_href = url;
mMenuName = menu;
mLocation = location;
- mDisabledLink = disabled_link;
mID = id;
}
diff --git a/indra/llui/llurlmatch.h b/indra/llui/llurlmatch.h
index 78dd2c528f..1ffac6ea0f 100644
--- a/indra/llui/llurlmatch.h
+++ b/indra/llui/llurlmatch.h
@@ -34,11 +34,11 @@
#ifndef LL_LLURLMATCH_H
#define LL_LLURLMATCH_H
-#include "linden_common.h"
+//#include "linden_common.h"
#include <string>
#include <vector>
-#include "lluicolor.h"
+#include "llstyle.h"
///
/// LLUrlMatch describes a single Url that was matched within a string by
@@ -75,7 +75,7 @@ public:
std::string getIcon() const { return mIcon; }
/// Return the color to render the displayed text
- LLUIColor getColor() const { return mColor; }
+ LLStyle::Params getStyle() const { return mStyle; }
/// Return the name of a XUI file containing the context menu items
std::string getMenuName() const { return mMenuName; }
@@ -83,18 +83,13 @@ public:
/// return the SL location that this Url describes, or "" if none.
std::string getLocation() const { return mLocation; }
- /// is this a match for a URL that should not be hyperlinked?
- bool isLinkDisabled() const { return mDisabledLink; }
-
/// Change the contents of this match object (used by LLUrlRegistry)
void setValues(U32 start, U32 end, const std::string &url, const std::string &label,
const std::string &tooltip, const std::string &icon,
- const LLUIColor& color, const std::string &menu,
- const std::string &location, bool disabled_link
- , const LLUUID& id );
-
- const LLUUID& getID() const { return mID;}
+ const LLStyle::Params& style, const std::string &menu,
+ const std::string &location, const LLUUID& id);
+ const LLUUID& getID() const { return mID; }
private:
U32 mStart;
U32 mEnd;
@@ -104,10 +99,8 @@ private:
std::string mIcon;
std::string mMenuName;
std::string mLocation;
-
LLUUID mID;
- LLUIColor mColor;
- bool mDisabledLink;
+ LLStyle::Params mStyle;
};
#endif
diff --git a/indra/llui/llurlregistry.cpp b/indra/llui/llurlregistry.cpp
index 1f86f72faa..5de249d994 100644
--- a/indra/llui/llurlregistry.cpp
+++ b/indra/llui/llurlregistry.cpp
@@ -37,18 +37,25 @@
#include <boost/regex.hpp>
// default dummy callback that ignores any label updates from the server
-void LLUrlRegistryNullCallback(const std::string &url, const std::string &label)
+void LLUrlRegistryNullCallback(const std::string &url, const std::string &label, const std::string& icon)
{
}
LLUrlRegistry::LLUrlRegistry()
{
+ mUrlEntry.reserve(20);
+
// Urls are matched in the order that they were registered
registerUrl(new LLUrlEntryNoLink());
registerUrl(new LLUrlEntryIcon());
registerUrl(new LLUrlEntrySLURL());
registerUrl(new LLUrlEntryHTTP());
registerUrl(new LLUrlEntryHTTPLabel());
+ registerUrl(new LLUrlEntryAgentCompleteName());
+ registerUrl(new LLUrlEntryAgentDisplayName());
+ registerUrl(new LLUrlEntryAgentUserName());
+ // LLUrlEntryAgent*Name must appear before LLUrlEntryAgent since
+ // LLUrlEntryAgent is a less specific (catchall for agent urls)
registerUrl(new LLUrlEntryAgent());
registerUrl(new LLUrlEntryGroup());
registerUrl(new LLUrlEntryParcel());
@@ -77,10 +84,13 @@ LLUrlRegistry::~LLUrlRegistry()
}
}
-void LLUrlRegistry::registerUrl(LLUrlEntryBase *url)
+void LLUrlRegistry::registerUrl(LLUrlEntryBase *url, bool force_front)
{
if (url)
{
+ if (force_front) // IDEVO
+ mUrlEntry.insert(mUrlEntry.begin(), url);
+ else
mUrlEntry.push_back(url);
}
}
@@ -180,10 +190,9 @@ bool LLUrlRegistry::findUrl(const std::string &text, LLUrlMatch &match, const LL
match_entry->getLabel(url, cb),
match_entry->getTooltip(url),
match_entry->getIcon(url),
- match_entry->getColor(),
+ match_entry->getStyle(),
match_entry->getMenuName(),
match_entry->getLocation(url),
- match_entry->isLinkDisabled(),
match_entry->getID(url));
return true;
}
@@ -215,10 +224,9 @@ bool LLUrlRegistry::findUrl(const LLWString &text, LLUrlMatch &match, const LLUr
match.getLabel(),
match.getTooltip(),
match.getIcon(),
- match.getColor(),
+ match.getStyle(),
match.getMenuName(),
match.getLocation(),
- match.isLinkDisabled(),
match.getID());
return true;
}
diff --git a/indra/llui/llurlregistry.h b/indra/llui/llurlregistry.h
index 399ee0a988..dffbd9d4bf 100644
--- a/indra/llui/llurlregistry.h
+++ b/indra/llui/llurlregistry.h
@@ -43,7 +43,9 @@
#include <vector>
/// This default callback for findUrl() simply ignores any label updates
-void LLUrlRegistryNullCallback(const std::string &url, const std::string &label);
+void LLUrlRegistryNullCallback(const std::string &url,
+ const std::string &label,
+ const std::string &icon);
///
/// LLUrlRegistry is a singleton that contains a set of Url types that
@@ -70,7 +72,9 @@ public:
~LLUrlRegistry();
/// add a new Url handler to the registry (will be freed on destruction)
- void registerUrl(LLUrlEntryBase *url);
+ /// optionally force it to the front of the list, making it take
+ /// priority over other regular expression matches for URLs
+ void registerUrl(LLUrlEntryBase *url, bool force_front = false);
/// get the next Url in an input string, starting at a given character offset
/// your callback is invoked if the matched Url's label changes in the future
diff --git a/indra/llui/tests/llurlentry_stub.cpp b/indra/llui/tests/llurlentry_stub.cpp
index 26d1f2e067..bc0f5dc9c2 100644
--- a/indra/llui/tests/llurlentry_stub.cpp
+++ b/indra/llui/tests/llurlentry_stub.cpp
@@ -22,11 +22,28 @@
#include "llstring.h"
#include "llfile.h"
+#include "llavatarnamecache.h"
#include "llcachename.h"
#include "lluuid.h"
#include <string>
+// Stub for LLAvatarNameCache
+bool LLAvatarNameCache::get(const LLUUID& agent_id, LLAvatarName *av_name)
+{
+ return false;
+}
+
+void LLAvatarNameCache::get(const LLUUID& agent_id, callback_slot_t slot)
+{
+ return;
+}
+
+bool LLAvatarNameCache::useDisplayNames()
+{
+ return false;
+}
+
//
// Stub implementation for LLCacheName
//
@@ -42,7 +59,12 @@ BOOL LLCacheName::getGroupName(const LLUUID& id, std::string& group)
return TRUE;
}
-boost::signals2::connection LLCacheName::get(const LLUUID& id, BOOL is_group, const LLCacheNameCallback& callback)
+boost::signals2::connection LLCacheName::get(const LLUUID& id, bool is_group, const LLCacheNameCallback& callback)
+{
+ return boost::signals2::connection();
+}
+
+boost::signals2::connection LLCacheName::getGroup(const LLUUID& id, const LLCacheNameCallback& callback)
{
return boost::signals2::connection();
}
@@ -62,3 +84,106 @@ std::string LLTrans::getString(const std::string &xml_desc, const LLStringUtil::
{
return std::string();
}
+
+//
+// Stub implementation for LLStyle::Params::Params
+//
+
+LLStyle::Params::Params()
+{
+}
+
+//
+// Stub implementations for various LLInitParam classes
+//
+
+namespace LLInitParam
+{
+ BaseBlock::BaseBlock() {}
+ BaseBlock::~BaseBlock() {}
+ Param::Param(BaseBlock* enclosing_block)
+ : mIsProvided(false)
+ {
+ const U8* my_addr = reinterpret_cast<const U8*>(this);
+ const U8* block_addr = reinterpret_cast<const U8*>(enclosing_block);
+ mEnclosingBlockOffset = (U16)(my_addr - block_addr);
+ }
+ void BaseBlock::setLastChangedParam(const Param& last_param, bool user_provided) {}
+
+ void BaseBlock::addParam(BlockDescriptor& block_data, const ParamDescriptor& in_param, const char* char_name){}
+ param_handle_t BaseBlock::getHandleFromParam(const Param* param) const {return 0;}
+
+ void BaseBlock::init(BlockDescriptor& descriptor, BlockDescriptor& base_descriptor, size_t block_size)
+ {
+ mBlockDescriptor = &descriptor;
+ descriptor.mCurrentBlockPtr = this;
+ }
+ bool BaseBlock::deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack){ return true; }
+ bool BaseBlock::serializeBlock(Parser& parser, Parser::name_stack_t name_stack, const LLInitParam::BaseBlock* diff_block) const { return true; }
+ bool BaseBlock::inspectBlock(Parser& parser, Parser::name_stack_t name_stack) const { return true; }
+ bool BaseBlock::merge(BlockDescriptor& block_data, const BaseBlock& other, bool overwrite) { return true; }
+ bool BaseBlock::validateBlock(bool emit_errors) const { return true; }
+
+ TypedParam<LLUIColor >::TypedParam(BlockDescriptor& descriptor, const char* name, const LLUIColor& value, ParamDescriptor::validation_func_t func, S32 min_count, S32 max_count)
+ : super_t(descriptor, name, value, func, min_count, max_count)
+ {}
+
+ void TypedParam<LLUIColor>::setValueFromBlock() const
+ {}
+
+ void TypedParam<LLUIColor>::setBlockFromValue()
+ {}
+
+ void TypeValues<LLUIColor>::declareValues()
+ {}
+
+ bool ParamCompare<const LLFontGL*, false>::equals(const LLFontGL* a, const LLFontGL* b)
+ {
+ return false;
+ }
+
+ TypedParam<const LLFontGL*>::TypedParam(BlockDescriptor& descriptor, const char* _name, const LLFontGL*const value, ParamDescriptor::validation_func_t func, S32 min_count, S32 max_count)
+ : super_t(descriptor, _name, value, func, min_count, max_count)
+ {}
+
+ void TypedParam<const LLFontGL*>::setValueFromBlock() const
+ {}
+
+ void TypedParam<const LLFontGL*>::setBlockFromValue()
+ {}
+
+ void TypeValues<LLFontGL::HAlign>::declareValues()
+ {}
+
+ void TypeValues<LLFontGL::VAlign>::declareValues()
+ {}
+
+ void TypeValues<LLFontGL::ShadowType>::declareValues()
+ {}
+
+ void TypedParam<LLUIImage*>::setValueFromBlock() const
+ {}
+
+ void TypedParam<LLUIImage*>::setBlockFromValue()
+ {}
+
+
+ bool ParamCompare<LLUIImage*, false>::equals(
+ LLUIImage* const &a,
+ LLUIImage* const &b)
+ {
+ return false;
+ }
+
+ bool ParamCompare<LLUIColor, false>::equals(const LLUIColor &a, const LLUIColor &b)
+ {
+ return false;
+ }
+
+}
+
+//static
+LLFontGL* LLFontGL::getFontDefault()
+{
+ return NULL;
+}
diff --git a/indra/llui/tests/llurlentry_test.cpp b/indra/llui/tests/llurlentry_test.cpp
index 4463b6cc6f..009d82ed99 100644
--- a/indra/llui/tests/llurlentry_test.cpp
+++ b/indra/llui/tests/llurlentry_test.cpp
@@ -25,6 +25,7 @@
#include "llurlentry_stub.cpp"
#include "lltut.h"
#include "../lluicolortable.h"
+#include "../lluiimage.h"
#include <boost/regex.hpp>
@@ -35,6 +36,26 @@ LLUIColor LLUIColorTable::getColor(const std::string& name, const LLColor4& defa
LLUIColor::LLUIColor() : mColorPtr(NULL) {}
+LLUIImage::LLUIImage(const std::string& name, LLPointer<LLTexture> image)
+{
+}
+
+LLUIImage::~LLUIImage()
+{
+}
+
+//virtual
+S32 LLUIImage::getWidth() const
+{
+ return 0;
+}
+
+//virtual
+S32 LLUIImage::getHeight() const
+{
+ return 0;
+}
+
namespace tut
{
struct LLUrlEntryData
diff --git a/indra/llui/tests/llurlmatch_test.cpp b/indra/llui/tests/llurlmatch_test.cpp
index 06b850d233..93fd11d999 100644
--- a/indra/llui/tests/llurlmatch_test.cpp
+++ b/indra/llui/tests/llurlmatch_test.cpp
@@ -20,14 +20,136 @@
* $/LicenseInfo$
*/
+#include "linden_common.h"
+
#include "../llurlmatch.h"
+#include "../lluiimage.h"
#include "lltut.h"
-// link seam
+// link seams
+
LLUIColor::LLUIColor()
: mColorPtr(NULL)
{}
+LLStyle::Params::Params()
+{
+}
+
+LLUIImage::LLUIImage(const std::string& name, LLPointer<LLTexture> image)
+{
+}
+
+LLUIImage::~LLUIImage()
+{
+}
+
+//virtual
+S32 LLUIImage::getWidth() const
+{
+ return 0;
+}
+
+//virtual
+S32 LLUIImage::getHeight() const
+{
+ return 0;
+}
+
+namespace LLInitParam
+{
+ BaseBlock::BaseBlock() {}
+ BaseBlock::~BaseBlock() {}
+
+ void BaseBlock::setLastChangedParam(const Param& last_param, bool user_provided) {}
+
+ void BaseBlock::addParam(BlockDescriptor& block_data, const ParamDescriptor& in_param, const char* char_name){}
+ param_handle_t BaseBlock::getHandleFromParam(const Param* param) const {return 0;}
+
+ void BaseBlock::init(BlockDescriptor& descriptor, BlockDescriptor& base_descriptor, size_t block_size)
+ {
+ mBlockDescriptor = &descriptor;
+ descriptor.mCurrentBlockPtr = this;
+ }
+
+ Param::Param(BaseBlock* enclosing_block)
+ : mIsProvided(false)
+ {
+ const U8* my_addr = reinterpret_cast<const U8*>(this);
+ const U8* block_addr = reinterpret_cast<const U8*>(enclosing_block);
+ mEnclosingBlockOffset = (U16)(my_addr - block_addr);
+ }
+
+ bool BaseBlock::deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack){ return true; }
+ bool BaseBlock::serializeBlock(Parser& parser, Parser::name_stack_t name_stack, const LLInitParam::BaseBlock* diff_block) const { return true; }
+ bool BaseBlock::inspectBlock(Parser& parser, Parser::name_stack_t name_stack) const { return true; }
+ bool BaseBlock::merge(BlockDescriptor& block_data, const BaseBlock& other, bool overwrite) { return true; }
+ bool BaseBlock::validateBlock(bool emit_errors) const { return true; }
+
+ TypedParam<LLUIColor >::TypedParam(BlockDescriptor& descriptor, const char* name, const LLUIColor& value, ParamDescriptor::validation_func_t func, S32 min_count, S32 max_count)
+ : super_t(descriptor, name, value, func, min_count, max_count)
+ {}
+
+ void TypedParam<LLUIColor>::setValueFromBlock() const
+ {}
+
+ void TypedParam<LLUIColor>::setBlockFromValue()
+ {}
+
+ void TypeValues<LLUIColor>::declareValues()
+ {}
+
+ bool ParamCompare<const LLFontGL*, false>::equals(const LLFontGL* a, const LLFontGL* b)
+ {
+ return false;
+ }
+
+ TypedParam<const LLFontGL*>::TypedParam(BlockDescriptor& descriptor, const char* _name, const LLFontGL*const value, ParamDescriptor::validation_func_t func, S32 min_count, S32 max_count)
+ : super_t(descriptor, _name, value, func, min_count, max_count)
+ {}
+
+ void TypedParam<const LLFontGL*>::setValueFromBlock() const
+ {}
+
+ void TypedParam<const LLFontGL*>::setBlockFromValue()
+ {}
+
+ void TypeValues<LLFontGL::HAlign>::declareValues()
+ {}
+
+ void TypeValues<LLFontGL::VAlign>::declareValues()
+ {}
+
+ void TypeValues<LLFontGL::ShadowType>::declareValues()
+ {}
+
+ void TypedParam<LLUIImage*>::setValueFromBlock() const
+ {}
+
+ void TypedParam<LLUIImage*>::setBlockFromValue()
+ {}
+
+ bool ParamCompare<LLUIImage*, false>::equals(
+ LLUIImage* const &a,
+ LLUIImage* const &b)
+ {
+ return false;
+ }
+
+ bool ParamCompare<LLUIColor, false>::equals(const LLUIColor &a, const LLUIColor &b)
+ {
+ return false;
+ }
+
+}
+
+//static
+LLFontGL* LLFontGL::getFontDefault()
+{
+ return NULL;
+}
+
+
namespace tut
{
struct LLUrlMatchData
@@ -54,7 +176,7 @@ namespace tut
LLUrlMatch match;
ensure("empty()", match.empty());
- match.setValues(0, 1, "http://secondlife.com", "Second Life", "", "", LLUIColor(), "", "", false,LLUUID::null);
+ match.setValues(0, 1, "http://secondlife.com", "Second Life", "", "", LLStyle::Params(), "", "", LLUUID::null);
ensure("! empty()", ! match.empty());
}
@@ -67,7 +189,7 @@ namespace tut
LLUrlMatch match;
ensure_equals("getStart() == 0", match.getStart(), 0);
- match.setValues(10, 20, "", "", "", "", LLUIColor(), "", "", false,LLUUID::null);
+ match.setValues(10, 20, "", "", "", "", LLStyle::Params(), "", "", LLUUID::null);
ensure_equals("getStart() == 10", match.getStart(), 10);
}
@@ -80,7 +202,7 @@ namespace tut
LLUrlMatch match;
ensure_equals("getEnd() == 0", match.getEnd(), 0);
- match.setValues(10, 20, "", "", "", "", LLUIColor(), "", "", false,LLUUID::null);
+ match.setValues(10, 20, "", "", "", "", LLStyle::Params(), "", "", LLUUID::null);
ensure_equals("getEnd() == 20", match.getEnd(), 20);
}
@@ -93,10 +215,10 @@ namespace tut
LLUrlMatch match;
ensure_equals("getUrl() == ''", match.getUrl(), "");
- match.setValues(10, 20, "http://slurl.com/", "", "", "", LLUIColor(), "", "", false,LLUUID::null);
+ match.setValues(10, 20, "http://slurl.com/", "", "", "", LLStyle::Params(), "", "", LLUUID::null);
ensure_equals("getUrl() == 'http://slurl.com/'", match.getUrl(), "http://slurl.com/");
- match.setValues(10, 20, "", "", "", "", LLUIColor(), "", "", false,LLUUID::null);
+ match.setValues(10, 20, "", "", "", "", LLStyle::Params(), "", "", LLUUID::null);
ensure_equals("getUrl() == '' (2)", match.getUrl(), "");
}
@@ -109,10 +231,10 @@ namespace tut
LLUrlMatch match;
ensure_equals("getLabel() == ''", match.getLabel(), "");
- match.setValues(10, 20, "", "Label", "", "", LLUIColor(), "", "", false,LLUUID::null);
+ match.setValues(10, 20, "", "Label", "", "", LLStyle::Params(), "", "", LLUUID::null);
ensure_equals("getLabel() == 'Label'", match.getLabel(), "Label");
- match.setValues(10, 20, "", "", "", "", LLUIColor(), "", "", false,LLUUID::null);
+ match.setValues(10, 20, "", "", "", "", LLStyle::Params(), "", "", LLUUID::null);
ensure_equals("getLabel() == '' (2)", match.getLabel(), "");
}
@@ -125,10 +247,10 @@ namespace tut
LLUrlMatch match;
ensure_equals("getTooltip() == ''", match.getTooltip(), "");
- match.setValues(10, 20, "", "", "Info", "", LLUIColor(), "", "", false,LLUUID::null);
+ match.setValues(10, 20, "", "", "Info", "", LLStyle::Params(), "", "", LLUUID::null);
ensure_equals("getTooltip() == 'Info'", match.getTooltip(), "Info");
- match.setValues(10, 20, "", "", "", "", LLUIColor(), "", "", false,LLUUID::null);
+ match.setValues(10, 20, "", "", "", "", LLStyle::Params(), "", "", LLUUID::null);
ensure_equals("getTooltip() == '' (2)", match.getTooltip(), "");
}
@@ -141,10 +263,10 @@ namespace tut
LLUrlMatch match;
ensure_equals("getIcon() == ''", match.getIcon(), "");
- match.setValues(10, 20, "", "", "", "Icon", LLUIColor(), "", "", false,LLUUID::null);
+ match.setValues(10, 20, "", "", "", "Icon", LLStyle::Params(), "", "", LLUUID::null);
ensure_equals("getIcon() == 'Icon'", match.getIcon(), "Icon");
- match.setValues(10, 20, "", "", "", "", LLUIColor(), "", "", false,LLUUID::null);
+ match.setValues(10, 20, "", "", "", "", LLStyle::Params(), "", "", LLUUID::null);
ensure_equals("getIcon() == '' (2)", match.getIcon(), "");
}
@@ -157,10 +279,10 @@ namespace tut
LLUrlMatch match;
ensure("getMenuName() empty", match.getMenuName().empty());
- match.setValues(10, 20, "", "", "", "Icon", LLUIColor(), "xui_file.xml", "", false,LLUUID::null);
+ match.setValues(10, 20, "", "", "", "Icon", LLStyle::Params(), "xui_file.xml", "", LLUUID::null);
ensure_equals("getMenuName() == \"xui_file.xml\"", match.getMenuName(), "xui_file.xml");
- match.setValues(10, 20, "", "", "", "", LLUIColor(), "", "", false,LLUUID::null);
+ match.setValues(10, 20, "", "", "", "", LLStyle::Params(), "", "", LLUUID::null);
ensure("getMenuName() empty (2)", match.getMenuName().empty());
}
@@ -173,10 +295,10 @@ namespace tut
LLUrlMatch match;
ensure("getLocation() empty", match.getLocation().empty());
- match.setValues(10, 20, "", "", "", "Icon", LLUIColor(), "xui_file.xml", "Paris", false,LLUUID::null);
+ match.setValues(10, 20, "", "", "", "Icon", LLStyle::Params(), "xui_file.xml", "Paris", LLUUID::null);
ensure_equals("getLocation() == \"Paris\"", match.getLocation(), "Paris");
- match.setValues(10, 20, "", "", "", "", LLUIColor(), "", "", false,LLUUID::null);
+ match.setValues(10, 20, "", "", "", "", LLStyle::Params(), "", "", LLUUID::null);
ensure("getLocation() empty (2)", match.getLocation().empty());
}
}
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 65502209f7..b75bff507e 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -240,6 +240,7 @@ set(viewer_SOURCE_FILES
llhudeffecttrail.cpp
llhudicon.cpp
llhudmanager.cpp
+ llhudnametag.cpp
llhudobject.cpp
llhudrender.cpp
llhudtext.cpp
@@ -479,6 +480,7 @@ set(viewer_SOURCE_FILES
llviewercontrol.cpp
llviewercontrollistener.cpp
llviewerdisplay.cpp
+ llviewerdisplayname.cpp
llviewerfloaterreg.cpp
llviewerfoldertype.cpp
llviewergenericmessage.cpp
@@ -766,6 +768,7 @@ set(viewer_HEADER_FILES
llhudeffecttrail.h
llhudicon.h
llhudmanager.h
+ llhudnametag.h
llhudobject.h
llhudrender.h
llhudtext.h
@@ -1005,6 +1008,7 @@ set(viewer_HEADER_FILES
llviewercontrol.h
llviewercontrollistener.h
llviewerdisplay.h
+ llviewerdisplayname.h
llviewerfloaterreg.h
llviewerfoldertype.h
llviewergenericmessage.h
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 1c32f33290..1f50f18516 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -4666,7 +4666,7 @@
<key>Type</key>
<string>String</string>
<key>Value</key>
- <string>https://www.xstreetsl.com/modules.php?name=Marketplace</string>
+ <string>http://marketplace.secondlife.com/</string>
</map>
<key>MarketplaceURL_objectFemale</key>
<map>
@@ -4721,7 +4721,7 @@
<key>Type</key>
<string>String</string>
<key>Value</key>
- <string>https://www.xstreetsl.com/modules.php?name=Marketplace</string>
+ <string>http://marketplace.secondlife.com</string>
</map>
<key>MarketplaceURL_bodypartMale</key>
<map>
@@ -4732,7 +4732,7 @@
<key>Type</key>
<string>String</string>
<key>Value</key>
- <string>https://www.xstreetsl.com/modules.php?name=Marketplace</string>
+ <string>http://marketplace.secondlife.com/</string>
</map>
<key>MarketplaceURL_glovesMale</key>
<map>
@@ -7810,7 +7810,7 @@
<key>Value</key>
<integer>0</integer>
</map>
- <key>RenderShowGroupTitleAll</key>
+ <key>NameTagShowGroupTitles</key>
<map>
<key>Comment</key>
<string>Show group titles in name labels</string>
@@ -7819,7 +7819,40 @@
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
+ <integer>0</integer>
+ </map>
+ <key>NameTagShowDisplayNames</key>
+ <map>
+ <key>Comment</key>
+ <string>Show display names in name labels</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
+ <key>NameTagShowFriends</key>
+ <map>
+ <key>Comment</key>
+ <string>Highlight the name tags of your friends</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
+ <key>NameTagShowUsernames</key>
+ <map>
+ <key>Comment</key>
+ <string>Show usernames in avatar name tags</string>
+ <key>Persist</key>
<integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
</map>
<key>RenderInitError</key>
<map>
@@ -10846,6 +10879,17 @@
<key>Value</key>
<integer>0</integer>
</map>
+ <key>UseDisplayNames</key>
+ <map>
+ <key>Comment</key>
+ <string>Use new, changeable, unicode names</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
<key>UseEnergy</key>
<map>
<key>Comment</key>
diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp
index 4e5fdb1219..72d51540ef 100644
--- a/indra/newview/llagent.cpp
+++ b/indra/newview/llagent.cpp
@@ -3406,6 +3406,9 @@ void LLAgent::setTeleportState(ETeleportState state)
}
else if(mTeleportState == TELEPORT_ARRIVING)
{
+ // First two position updates after a teleport tend to be weird
+ LLViewerStats::getInstance()->mAgentPositionSnaps.mCountOfNextUpdatesToIgnore = 2;
+
// Let the interested parties know we've teleported.
LLViewerParcelMgr::getInstance()->onTeleportFinished(false, getPositionGlobal());
}
diff --git a/indra/newview/llagentui.cpp b/indra/newview/llagentui.cpp
index 15d9f36b74..b5f9810e24 100644
--- a/indra/newview/llagentui.cpp
+++ b/indra/newview/llagentui.cpp
@@ -46,29 +46,6 @@
#include "llslurl.h"
//static
-void LLAgentUI::buildName(std::string& name)
-{
- name.clear();
- if (isAgentAvatarValid())
- {
- LLNameValue *first_nv = gAgentAvatarp->getNVPair("FirstName");
- LLNameValue *last_nv = gAgentAvatarp->getNVPair("LastName");
- if (first_nv && last_nv)
- {
- name = first_nv->printData() + " " + last_nv->printData();
- }
- else
- {
- llwarns << "Agent is missing FirstName and/or LastName nv pair." << llendl;
- }
- }
- else
- {
- name = gSavedSettings.getString("FirstName") + " " + gSavedSettings.getString("LastName");
- }
-}
-
-//static
void LLAgentUI::buildFullname(std::string& name)
{
if (isAgentAvatarValid())
diff --git a/indra/newview/llagentui.h b/indra/newview/llagentui.h
index 577b752fbe..2c3c65fb8a 100644
--- a/indra/newview/llagentui.h
+++ b/indra/newview/llagentui.h
@@ -47,7 +47,6 @@ public:
LOCATION_FORMAT_FULL, // Parcel, Region (x, y, z) - Maturity
};
- static void buildName(std::string& name);
static void buildFullname(std::string &name);
static void buildSLURL(LLSLURL& slurl, const bool escaped = true);
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index d8b2866a9f..2969a1676e 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -89,6 +89,7 @@
#include "llsecondlifeurls.h"
// Linden library includes
+#include "llavatarnamecache.h"
#include "llimagej2c.h"
#include "llmemory.h"
#include "llprimitive.h"
@@ -161,7 +162,6 @@
// Included so that constants/settings might be initialized
// in save_settings_to_globals()
#include "llbutton.h"
-#include "llcombobox.h"
#include "llstatusbar.h"
#include "llsurface.h"
#include "llvosky.h"
@@ -437,9 +437,6 @@ static void settings_to_globals()
MENU_BAR_HEIGHT = gSavedSettings.getS32("MenuBarHeight");
MENU_BAR_WIDTH = gSavedSettings.getS32("MenuBarWidth");
- LLCOMBOBOX_HEIGHT = BTN_HEIGHT - 2;
- LLCOMBOBOX_WIDTH = 128;
-
LLSurface::setTextureSize(gSavedSettings.getU32("RegionTextureSize"));
LLImageGL::sGlobalUseAnisotropic = gSavedSettings.getBOOL("RenderAnisotropic");
@@ -1354,8 +1351,7 @@ bool LLAppViewer::cleanup()
LLPolyMesh::freeAllMeshes();
- delete gCacheName;
- gCacheName = NULL;
+ LLStartUp::cleanupNameCache();
// Note: this is where gLocalSpeakerMgr and gActiveSpeakerMgr used to be deleted.
@@ -3421,6 +3417,15 @@ void LLAppViewer::saveFinalSnapshot()
void LLAppViewer::loadNameCache()
{
+ // display names cache
+ std::string filename =
+ gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "avatar_name_cache.xml");
+ llifstream name_cache_stream(filename);
+ if(name_cache_stream.is_open())
+ {
+ LLAvatarNameCache::importFile(name_cache_stream);
+ }
+
if (!gCacheName) return;
std::string name_cache;
@@ -3430,19 +3435,19 @@ void LLAppViewer::loadNameCache()
{
if(gCacheName->importFile(cache_file)) return;
}
+}
- // Try to load from the legacy format. This should go away after a
- // while. Phoenix 2008-01-30
- LLFILE* name_cache_fp = LLFile::fopen(name_cache, "r"); // Flawfinder: ignore
- if (name_cache_fp)
+void LLAppViewer::saveNameCache()
{
- gCacheName->importFile(name_cache_fp);
- fclose(name_cache_fp);
- }
+ // display names cache
+ std::string filename =
+ gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "avatar_name_cache.xml");
+ llofstream name_cache_stream(filename);
+ if(name_cache_stream.is_open())
+ {
+ LLAvatarNameCache::exportFile(name_cache_stream);
}
-void LLAppViewer::saveNameCache()
-{
if (!gCacheName) return;
std::string name_cache;
@@ -3638,6 +3643,7 @@ void LLAppViewer::idle()
// NOTE: Starting at this point, we may still have pointers to "dead" objects
// floating throughout the various object lists.
//
+ idleNameCache();
idleNetwork();
@@ -3975,6 +3981,60 @@ void LLAppViewer::sendLogoutRequest()
}
}
+void LLAppViewer::idleNameCache()
+{
+ // Neither old nor new name cache can function before agent has a region
+ LLViewerRegion* region = gAgent.getRegion();
+ if (!region) return;
+
+ // deal with any queued name requests and replies.
+ gCacheName->processPending();
+
+ // Can't run the new cache until we have the list of capabilities
+ // for the agent region, and can therefore decide whether to use
+ // display names or fall back to the old name system.
+ if (!region->capabilitiesReceived()) return;
+
+ // Agent may have moved to a different region, so need to update cap URL
+ // for name lookups. Can't do this in the cap grant code, as caps are
+ // granted to neighbor regions before the main agent gets there. Can't
+ // do it in the move-into-region code because cap not guaranteed to be
+ // granted yet, for example on teleport.
+ bool had_capability = LLAvatarNameCache::hasNameLookupURL();
+ std::string name_lookup_url;
+ name_lookup_url.reserve(128); // avoid a memory allocation below
+ name_lookup_url = region->getCapability("GetDisplayNames");
+ bool have_capability = !name_lookup_url.empty();
+ if (have_capability)
+ {
+ // we have support for display names, use it
+ U32 url_size = name_lookup_url.size();
+ // capabilities require URLs with slashes before query params:
+ // https://<host>:<port>/cap/<uuid>/?ids=<blah>
+ // but the caps are granted like:
+ // https://<host>:<port>/cap/<uuid>
+ if (url_size > 0 && name_lookup_url[url_size-1] != '/')
+ {
+ name_lookup_url += '/';
+ }
+ LLAvatarNameCache::setNameLookupURL(name_lookup_url);
+ }
+ else
+ {
+ // Display names not available on this region
+ LLAvatarNameCache::setNameLookupURL( std::string() );
+ }
+
+ // Error recovery - did we change state?
+ if (had_capability != have_capability)
+ {
+ // name tags are persistant on screen, so make sure they refresh
+ LLVOAvatar::invalidateNameTags();
+ }
+
+ LLAvatarNameCache::idle();
+}
+
//
// Handle messages, and all message related stuff
//
@@ -4000,8 +4060,6 @@ void LLAppViewer::idleNetwork()
{
LLFastTimer t(FTM_IDLE_NETWORK); // decode
- // deal with any queued name requests and replies.
- gCacheName->processPending();
LLTimer check_message_timer;
// Read all available packets from network
const S64 frame_count = gFrameCount; // U32->S64
diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h
index 0b862a92a1..cac580e896 100644
--- a/indra/newview/llappviewer.h
+++ b/indra/newview/llappviewer.h
@@ -209,6 +209,8 @@ private:
void idle();
void idleShutdown();
+ // update avatar SLID and display name caches
+ void idleNameCache();
void idleNetwork();
void sendLogoutRequest();
diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp
index 752a2e7504..a6e1691ffa 100644
--- a/indra/newview/llavataractions.cpp
+++ b/indra/newview/llavataractions.cpp
@@ -37,11 +37,11 @@
#include "boost/lambda/lambda.hpp" // for lambda::constant
+#include "llavatarnamecache.h" // IDEVO
#include "llsd.h"
#include "lldarray.h"
#include "llnotifications.h"
#include "llnotificationsutil.h"
-
#include "roles_constants.h" // for GP_MEMBER_INVITE
#include "llagent.h"
@@ -70,6 +70,7 @@
#include "llimfloater.h"
#include "lltrans.h"
#include "llcallingcard.h"
+#include "llslurl.h" // IDEVO
// static
void LLAvatarActions::requestFriendshipDialog(const LLUUID& id, const std::string& name)
@@ -81,26 +82,22 @@ void LLAvatarActions::requestFriendshipDialog(const LLUUID& id, const std::strin
}
LLSD args;
- args["NAME"] = name;
+ args["NAME"] = LLSLURL("agent", id, "completename").getSLURLString();
LLSD payload;
payload["id"] = id;
payload["name"] = name;
- // Look for server versions like: Second Life Server 1.24.4.95600
- if (gLastVersionChannel.find(" 1.24.") != std::string::npos)
- {
- // Old and busted server version, doesn't support friend
- // requests with messages.
- LLNotificationsUtil::add("AddFriend", args, payload, &callbackAddFriend);
- }
- else
- {
+
LLNotificationsUtil::add("AddFriendWithMessage", args, payload, &callbackAddFriendWithMessage);
- }
// add friend to recent people list
LLRecentPeople::instance().add(id);
}
+void on_avatar_name_friendship(const LLUUID& id, const LLAvatarName av_name)
+{
+ LLAvatarActions::requestFriendshipDialog(id, av_name.getCompleteName());
+}
+
// static
void LLAvatarActions::requestFriendshipDialog(const LLUUID& id)
{
@@ -109,9 +106,7 @@ void LLAvatarActions::requestFriendshipDialog(const LLUUID& id)
return;
}
- std::string full_name;
- gCacheName->getFullName(id, full_name);
- requestFriendshipDialog(id, full_name);
+ LLAvatarNameCache::get(id, boost::bind(&on_avatar_name_friendship, _1, _2));
}
// static
@@ -136,11 +131,10 @@ void LLAvatarActions::removeFriendsDialog(const uuid_vec_t& ids)
if(ids.size() == 1)
{
LLUUID agent_id = ids[0];
- std::string first, last;
- if(gCacheName->getName(agent_id, first, last))
+ LLAvatarName av_name;
+ if(LLAvatarNameCache::get(agent_id, &av_name))
{
- args["FIRST_NAME"] = first;
- args["LAST_NAME"] = last;
+ args["NAME"] = av_name.mDisplayName;
}
msgType = "RemoveFromFriends";
@@ -168,14 +162,6 @@ void LLAvatarActions::offerTeleport(const LLUUID& invitee)
if (invitee.isNull())
return;
- //waiting until Name Cache gets updated with corresponding avatar name
- std::string just_to_request_name;
- if (!gCacheName->getFullName(invitee, just_to_request_name))
- {
- gCacheName->get(invitee, FALSE, boost::bind((void (*)(const LLUUID&)) &LLAvatarActions::offerTeleport, invitee));
- return;
- }
-
LLDynamicArray<LLUUID> ids;
ids.push_back(invitee);
offerTeleport(ids);
@@ -190,20 +176,11 @@ void LLAvatarActions::offerTeleport(const uuid_vec_t& ids)
handle_lure(ids);
}
-// static
-void LLAvatarActions::startIM(const LLUUID& id)
+static void on_avatar_name_cache_start_im(const LLUUID& agent_id,
+ const LLAvatarName& av_name)
{
- if (id.isNull())
- return;
-
- std::string name;
- if (!gCacheName->getFullName(id, name))
- {
- gCacheName->get(id, FALSE, boost::bind(&LLAvatarActions::startIM, id));
- return;
- }
-
- LLUUID session_id = gIMMgr->addSession(name, IM_NOTHING_SPECIAL, id);
+ std::string name = av_name.getCompleteName();
+ LLUUID session_id = gIMMgr->addSession(name, IM_NOTHING_SPECIAL, agent_id);
if (session_id != LLUUID::null)
{
LLIMFloater::show(session_id);
@@ -212,6 +189,16 @@ void LLAvatarActions::startIM(const LLUUID& id)
}
// static
+void LLAvatarActions::startIM(const LLUUID& id)
+{
+ if (id.isNull())
+ return;
+
+ LLAvatarNameCache::get(id,
+ boost::bind(&on_avatar_name_cache_start_im, _1, _2));
+}
+
+// static
void LLAvatarActions::endIM(const LLUUID& id)
{
if (id.isNull())
@@ -224,6 +211,18 @@ void LLAvatarActions::endIM(const LLUUID& id)
}
}
+static void on_avatar_name_cache_start_call(const LLUUID& agent_id,
+ const LLAvatarName& av_name)
+{
+ std::string name = av_name.getCompleteName();
+ LLUUID session_id = gIMMgr->addSession(name, IM_NOTHING_SPECIAL, agent_id, true);
+ if (session_id != LLUUID::null)
+ {
+ gIMMgr->startCall(session_id);
+ }
+ make_ui_sound("UISndStartIM");
+}
+
// static
void LLAvatarActions::startCall(const LLUUID& id)
{
@@ -231,15 +230,8 @@ void LLAvatarActions::startCall(const LLUUID& id)
{
return;
}
-
- std::string name;
- gCacheName->getFullName(id, name);
- LLUUID session_id = gIMMgr->addSession(name, IM_NOTHING_SPECIAL, id, true);
- if (session_id != LLUUID::null)
- {
- gIMMgr->startCall(session_id);
- }
- make_ui_sound("UISndStartIM");
+ LLAvatarNameCache::get(id,
+ boost::bind(&on_avatar_name_cache_start_call, _1, _2));
}
// static
@@ -335,14 +327,14 @@ void LLAvatarActions::showProfile(const LLUUID& id)
// static
void LLAvatarActions::showOnMap(const LLUUID& id)
{
- std::string name;
- if (!gCacheName->getFullName(id, name))
+ LLAvatarName av_name;
+ if (!LLAvatarNameCache::get(id, &av_name))
{
- gCacheName->get(id, FALSE, boost::bind(&LLAvatarActions::showOnMap, id));
+ LLAvatarNameCache::get(id, boost::bind(&LLAvatarActions::showOnMap, id));
return;
}
- gFloaterWorldMap->trackAvatar(id, name);
+ gFloaterWorldMap->trackAvatar(id, av_name.mDisplayName);
LLFloaterReg::showInstance("world_map");
}
@@ -492,14 +484,15 @@ namespace action_give_inventory
return acceptable;
}
- static void build_residents_string(const std::vector<std::string>& avatar_names, std::string& residents_string)
+ static void build_residents_string(const std::vector<LLAvatarName> avatar_names, std::string& residents_string)
{
llassert(avatar_names.size() > 0);
const std::string& separator = LLTrans::getString("words_separator");
- for (std::vector<std::string>::const_iterator it = avatar_names.begin(); ; )
+ for (std::vector<LLAvatarName>::const_iterator it = avatar_names.begin(); ; )
{
- residents_string.append(*it);
+ LLAvatarName av_name = *it;
+ residents_string.append(av_name.mDisplayName);
if (++it == avatar_names.end())
{
break;
@@ -536,7 +529,7 @@ namespace action_give_inventory
struct LLShareInfo : public LLSingleton<LLShareInfo>
{
- std::vector<std::string> mAvatarNames;
+ std::vector<LLAvatarName> mAvatarNames;
uuid_vec_t mAvatarUuids;
};
@@ -600,7 +593,7 @@ namespace action_give_inventory
}
else
{
- LLGiveInventory::doGiveInventoryItem(avatar_uuid, inv_item, session_id);
+ LLGiveInventory::doGiveInventoryItem(avatar_uuid, inv_item, session_id);
shared = true;
}
}
@@ -632,11 +625,10 @@ namespace action_give_inventory
* @param avatar_names - avatar names request to be sent.
* @param avatar_uuids - avatar names request to be sent.
*/
- static void give_inventory(const std::vector<std::string>& avatar_names, const uuid_vec_t& avatar_uuids)
+ static void give_inventory(const uuid_vec_t& avatar_uuids, const std::vector<LLAvatarName> avatar_names)
{
llassert(avatar_names.size() == avatar_uuids.size());
-
LLInventoryPanel* active_panel = LLInventoryPanel::getActiveInventoryPanel(FALSE);
if (!active_panel)
{
@@ -682,7 +674,7 @@ void LLAvatarActions::toggleBlock(const LLUUID& id)
{
std::string name;
- gCacheName->getFullName(id, name);
+ gCacheName->getFullName(id, name); // needed for mute
LLMute mute(id, name, LLMute::AGENT);
if (LLMuteList::getInstance()->isMuted(mute.mID, mute.mName))
@@ -854,23 +846,6 @@ bool LLAvatarActions::handleUnfreeze(const LLSD& notification, const LLSD& respo
}
return false;
}
-// static
-bool LLAvatarActions::callbackAddFriend(const LLSD& notification, const LLSD& response)
-{
- S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
- if (option == 0)
- {
- // Servers older than 1.25 require the text of the message to be the
- // calling card folder ID for the offering user. JC
- LLUUID calling_card_folder_id =
- gInventory.findCategoryUUIDForType(LLFolderType::FT_CALLINGCARD);
- std::string message = calling_card_folder_id.asString();
- requestFriendship(notification["payload"]["id"].asUUID(),
- notification["payload"]["name"].asString(),
- message);
- }
- return false;
-}
// static
void LLAvatarActions::requestFriendship(const LLUUID& target_id, const std::string& target_name, const std::string& message)
@@ -888,7 +863,6 @@ void LLAvatarActions::requestFriendship(const LLUUID& target_id, const std::stri
LLSD payload;
payload["from_id"] = target_id;
- payload["SESSION_NAME"] = target_name;
payload["SUPPRESS_TOAST"] = true;
LLNotificationsUtil::add("FriendshipOffered", args, payload);
}
@@ -903,16 +877,16 @@ bool LLAvatarActions::isFriend(const LLUUID& id)
bool LLAvatarActions::isBlocked(const LLUUID& id)
{
std::string name;
- gCacheName->getFullName(id, name);
+ gCacheName->getFullName(id, name); // needed for mute
return LLMuteList::getInstance()->isMuted(id, name);
}
// static
bool LLAvatarActions::canBlock(const LLUUID& id)
{
- std::string firstname, lastname;
- gCacheName->getName(id, firstname, lastname);
- bool is_linden = !LLStringUtil::compareStrings(lastname, "Linden");
+ std::string full_name;
+ gCacheName->getFullName(id, full_name); // needed for mute
+ bool is_linden = (full_name.find("Linden") != std::string::npos);
bool is_self = id == gAgentID;
return !is_self && !is_linden;
}
diff --git a/indra/newview/llavataractions.h b/indra/newview/llavataractions.h
index d106a83eea..2d69c01ffe 100644
--- a/indra/newview/llavataractions.h
+++ b/indra/newview/llavataractions.h
@@ -184,7 +184,6 @@ public:
private:
- static bool callbackAddFriend(const LLSD& notification, const LLSD& response);
static bool callbackAddFriendWithMessage(const LLSD& notification, const LLSD& response);
static bool handleRemove(const LLSD& notification, const LLSD& response);
static bool handlePay(const LLSD& notification, const LLSD& response, LLUUID avatar_id);
diff --git a/indra/newview/llavatariconctrl.cpp b/indra/newview/llavatariconctrl.cpp
index abb79b53a7..f4d5d45726 100644
--- a/indra/newview/llavatariconctrl.cpp
+++ b/indra/newview/llavatariconctrl.cpp
@@ -34,17 +34,19 @@
#include "llavatariconctrl.h"
+// viewer includes
#include "llagent.h"
#include "llavatarconstants.h"
#include "llcallingcard.h" // for LLAvatarTracker
#include "llavataractions.h"
#include "llmenugl.h"
#include "lluictrlfactory.h"
-
-#include "llcachename.h"
#include "llagentdata.h"
#include "llimfloater.h"
+// library includes
+#include "llavatarnamecache.h"
+
#define MENU_ITEM_VIEW_PROFILE 0
#define MENU_ITEM_SEND_IM 1
@@ -233,6 +235,9 @@ void LLAvatarIconCtrl::setValue(const LLSD& value)
// Check if cache already contains image_id for that avatar
if (!updateFromCache())
{
+ // *TODO: Consider getting avatar icon/badge directly from
+ // People API, rather than sending AvatarPropertyRequest
+ // messages. People API already hits the user table.
LLIconCtrl::setValue(mDefaultIconName);
app->addObserver(mAvatarId, this);
app->sendAvatarPropertiesRequest(mAvatarId);
@@ -244,10 +249,9 @@ void LLAvatarIconCtrl::setValue(const LLSD& value)
LLIconCtrl::setValue(value);
}
- if (gCacheName)
- {
- gCacheName->get(mAvatarId, FALSE, boost::bind(&LLAvatarIconCtrl::nameUpdatedCallback, this, _1, _2, _3, _4));
- }
+ LLAvatarNameCache::get(mAvatarId,
+ boost::bind(&LLAvatarIconCtrl::onAvatarNameCache,
+ this, _1, _2));
}
bool LLAvatarIconCtrl::updateFromCache()
@@ -290,24 +294,21 @@ void LLAvatarIconCtrl::processProperties(void* data, EAvatarProcessorType type)
}
}
-void LLAvatarIconCtrl::nameUpdatedCallback(
- const LLUUID& id,
- const std::string& first,
- const std::string& last,
- BOOL is_group)
+void LLAvatarIconCtrl::onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name)
{
- if (id == mAvatarId)
+ if (agent_id == mAvatarId)
{
- mFirstName = first;
- mLastName = last;
+ // Most avatar icon controls are next to a UI element that shows
+ // a display name, so only show username.
+ mFullName = av_name.mUsername;
if (mDrawTooltip)
{
- setToolTip(mFirstName + " " + mLastName);
+ setToolTip(mFullName);
}
else
{
- setToolTip(std::string(""));
+ setToolTip(std::string());
}
}
}
diff --git a/indra/newview/llavatariconctrl.h b/indra/newview/llavatariconctrl.h
index 38616b7852..5befc73d92 100644
--- a/indra/newview/llavatariconctrl.h
+++ b/indra/newview/llavatariconctrl.h
@@ -37,6 +37,8 @@
#include "llavatarpropertiesprocessor.h"
#include "llviewermenu.h"
+class LLAvatarName;
+
class LLAvatarIconIDCache: public LLSingleton<LLAvatarIconIDCache>
{
public:
@@ -90,22 +92,16 @@ public:
// LLAvatarPropertiesProcessor observer trigger
virtual void processProperties(void* data, EAvatarProcessorType type);
- void nameUpdatedCallback(
- const LLUUID& id,
- const std::string& first,
- const std::string& last,
- BOOL is_group);
+ void onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name);
const LLUUID& getAvatarId() const { return mAvatarId; }
- const std::string& getFirstName() const { return mFirstName; }
- const std::string& getLastName() const { return mLastName; }
+ const std::string& getFullName() const { return mFullName; }
void setDrawTooltip(bool value) { mDrawTooltip = value;}
protected:
LLUUID mAvatarId;
- std::string mFirstName;
- std::string mLastName;
+ std::string mFullName;
bool mDrawTooltip;
std::string mDefaultIconName;
diff --git a/indra/newview/llavatarlist.cpp b/indra/newview/llavatarlist.cpp
index 99156b9d9d..9d14804b33 100644
--- a/indra/newview/llavatarlist.cpp
+++ b/indra/newview/llavatarlist.cpp
@@ -44,6 +44,7 @@
// newview
#include "llagentdata.h" // for comparator
#include "llavatariconctrl.h"
+#include "llavatarnamecache.h"
#include "llcallingcard.h" // for LLAvatarTracker
#include "llcachename.h"
#include "lllistcontextmenu.h"
@@ -242,12 +243,15 @@ void LLAvatarList::refresh()
// Handle added items.
unsigned nadded = 0;
+ const std::string waiting_str = LLTrans::getString("AvatarNameWaiting");
+
for (uuid_vec_t::const_iterator it=added.begin(); it != added.end(); it++)
{
- std::string name;
const LLUUID& buddy_id = *it;
- have_names &= (bool)gCacheName->getFullName(buddy_id, name);
- if (!have_filter || findInsensitive(name, mNameFilter))
+ LLAvatarName av_name;
+ have_names &= LLAvatarNameCache::get(buddy_id, &av_name);
+
+ if (!have_filter || findInsensitive(av_name.mDisplayName, mNameFilter))
{
if (nadded >= ADD_LIMIT)
{
@@ -256,7 +260,11 @@ void LLAvatarList::refresh()
}
else
{
- addNewItem(buddy_id, name, LLAvatarTracker::instance().isBuddyOnline(buddy_id));
+ // *NOTE: If you change the UI to show a different string,
+ // be sure to change the filter code below.
+ addNewItem(buddy_id,
+ av_name.mDisplayName.empty() ? waiting_str : av_name.mDisplayName,
+ LLAvatarTracker::instance().isBuddyOnline(buddy_id));
modified = true;
nadded++;
}
@@ -278,10 +286,10 @@ void LLAvatarList::refresh()
for (std::vector<LLSD>::const_iterator it=cur_values.begin(); it != cur_values.end(); it++)
{
- std::string name;
const LLUUID& buddy_id = it->asUUID();
- have_names &= (bool)gCacheName->getFullName(buddy_id, name);
- if (!findInsensitive(name, mNameFilter))
+ LLAvatarName av_name;
+ have_names &= LLAvatarNameCache::get(buddy_id, &av_name);
+ if (!findInsensitive(av_name.mDisplayName, mNameFilter))
{
removeItemByUUID(buddy_id);
modified = true;
@@ -333,14 +341,14 @@ bool LLAvatarList::filterHasMatches()
for (uuid_vec_t::const_iterator it=values.begin(); it != values.end(); it++)
{
- std::string name;
const LLUUID& buddy_id = *it;
- BOOL have_name = gCacheName->getFullName(buddy_id, name);
+ LLAvatarName av_name;
+ bool have_name = LLAvatarNameCache::get(buddy_id, &av_name);
// If name has not been loaded yet we consider it as a match.
// When the name will be loaded the filter will be applied again(in refresh()).
- if (have_name && !findInsensitive(name, mNameFilter))
+ if (have_name && !findInsensitive(av_name.mDisplayName, mNameFilter))
{
continue;
}
@@ -374,7 +382,7 @@ S32 LLAvatarList::notifyParent(const LLSD& info)
void LLAvatarList::addNewItem(const LLUUID& id, const std::string& name, BOOL is_online, EAddPosition pos)
{
LLAvatarListItem* item = new LLAvatarListItem();
- item->setName(name);
+ // This sets the name as a side effect
item->setAvatarId(id, mSessionID, mIgnoreOnlineStatus);
item->setOnline(mIgnoreOnlineStatus ? true : is_online);
item->showLastInteractionTime(mShowLastInteractionTime);
@@ -540,11 +548,13 @@ void LLAvalineListItem::setName(const std::string& name)
std::string hidden_name = LLTrans::getString("AvalineCaller", args);
LL_DEBUGS("Avaline") << "Avaline caller: " << uuid << ", name: " << hidden_name << LL_ENDL;
- LLAvatarListItem::setName(hidden_name);
+ LLAvatarListItem::setAvatarName(hidden_name);
+ LLAvatarListItem::setAvatarToolTip(hidden_name);
}
else
{
const std::string& formatted_phone = LLTextUtil::formatPhoneNumber(name);
- LLAvatarListItem::setName(formatted_phone);
+ LLAvatarListItem::setAvatarName(formatted_phone);
+ LLAvatarListItem::setAvatarToolTip(formatted_phone);
}
}
diff --git a/indra/newview/llavatarlist.h b/indra/newview/llavatarlist.h
index fffc6e6e73..b9b85094fb 100644
--- a/indra/newview/llavatarlist.h
+++ b/indra/newview/llavatarlist.h
@@ -34,7 +34,6 @@
#define LL_LLAVATARLIST_H
#include "llflatlistview.h"
-
#include "llavatarlistitem.h"
class LLTimer;
diff --git a/indra/newview/llavatarlistitem.cpp b/indra/newview/llavatarlistitem.cpp
index c74075d67f..079a7d3ed2 100644
--- a/indra/newview/llavatarlistitem.cpp
+++ b/indra/newview/llavatarlistitem.cpp
@@ -41,6 +41,7 @@
#include "lltextutil.h"
#include "llagent.h"
+#include "llavatarnamecache.h"
#include "llavatariconctrl.h"
#include "lloutputmonitorctrl.h"
@@ -167,11 +168,16 @@ void LLAvatarListItem::setOnline(bool online)
setState(online ? IS_ONLINE : IS_OFFLINE);
}
-void LLAvatarListItem::setName(const std::string& name)
+void LLAvatarListItem::setAvatarName(const std::string& name)
{
setNameInternal(name, mHighlihtSubstring);
}
+void LLAvatarListItem::setAvatarToolTip(const std::string& tooltip)
+{
+ mAvatarName->setToolTip(tooltip);
+}
+
void LLAvatarListItem::setHighlight(const std::string& highlight)
{
setNameInternal(mAvatarName->getText(), mHighlihtSubstring = highlight);
@@ -230,7 +236,8 @@ void LLAvatarListItem::setAvatarId(const LLUUID& id, const LLUUID& session_id, b
mAvatarIcon->setValue(id);
// Set avatar name.
- gCacheName->get(id, FALSE, boost::bind(&LLAvatarListItem::onNameCache, this, _2, _3));
+ LLAvatarNameCache::get(id,
+ boost::bind(&LLAvatarListItem::onAvatarNameCache, this, _2));
}
}
@@ -323,23 +330,27 @@ const LLUUID& LLAvatarListItem::getAvatarId() const
return mAvatarId;
}
-const std::string LLAvatarListItem::getAvatarName() const
+std::string LLAvatarListItem::getAvatarName() const
{
return mAvatarName->getValue();
}
+std::string LLAvatarListItem::getAvatarToolTip() const
+{
+ return mAvatarName->getToolTip();
+}
+
//== PRIVATE SECITON ==========================================================
void LLAvatarListItem::setNameInternal(const std::string& name, const std::string& highlight)
{
LLTextUtil::textboxSetHighlightedVal(mAvatarName, mAvatarNameStyle, name, highlight);
- mAvatarName->setToolTip(name);
}
-void LLAvatarListItem::onNameCache(const std::string& first_name, const std::string& last_name)
+void LLAvatarListItem::onAvatarNameCache(const LLAvatarName& av_name)
{
- std::string name = first_name + " " + last_name;
- setName(name);
+ setAvatarName(av_name.mDisplayName);
+ setAvatarToolTip(av_name.mUsername);
//requesting the list to resort
notifyParent(LLSD().with("sort", LLSD()));
diff --git a/indra/newview/llavatarlistitem.h b/indra/newview/llavatarlistitem.h
index ba9c3574d5..78257ce9ba 100644
--- a/indra/newview/llavatarlistitem.h
+++ b/indra/newview/llavatarlistitem.h
@@ -42,6 +42,7 @@
#include "llcallingcard.h" // for LLFriendObserver
class LLAvatarIconCtrl;
+class LLAvatarName;
class LLAvatarListItem : public LLPanel, public LLFriendObserver
{
@@ -91,7 +92,8 @@ public:
virtual void changed(U32 mask); // from LLFriendObserver
void setOnline(bool online);
- void setName(const std::string& name);
+ void setAvatarName(const std::string& name);
+ void setAvatarToolTip(const std::string& tooltip);
void setHighlight(const std::string& highlight);
void setState(EItemState item_style);
void setAvatarId(const LLUUID& id, const LLUUID& session_id, bool ignore_status_changes = false, bool is_resident = true);
@@ -104,7 +106,8 @@ public:
void setAvatarIconVisible(bool visible);
const LLUUID& getAvatarId() const;
- const std::string getAvatarName() const;
+ std::string getAvatarName() const;
+ std::string getAvatarToolTip() const;
void onInfoBtnClick();
void onProfileBtnClick();
@@ -145,7 +148,7 @@ private:
} EAvatarListItemChildIndex;
void setNameInternal(const std::string& name, const std::string& highlight);
- void onNameCache(const std::string& first_name, const std::string& last_name);
+ void onAvatarNameCache(const LLAvatarName& av_name);
std::string formatSeconds(U32 secs);
diff --git a/indra/newview/llcallfloater.cpp b/indra/newview/llcallfloater.cpp
index b494470cbc..03ab8a9de1 100644
--- a/indra/newview/llcallfloater.cpp
+++ b/indra/newview/llcallfloater.cpp
@@ -33,13 +33,14 @@
#include "llviewerprecompiledheaders.h"
+#include "llcallfloater.h"
+
#include "llnotificationsutil.h"
#include "lltrans.h"
-#include "llcallfloater.h"
-
#include "llagent.h"
#include "llagentdata.h" // for gAgentID
+#include "llavatarnamecache.h"
#include "llavatariconctrl.h"
#include "llavatarlist.h"
#include "llbottomtray.h"
@@ -83,7 +84,8 @@ public:
void setName(const std::string& name)
{
const std::string& formatted_phone = LLTextUtil::formatPhoneNumber(name);
- LLAvatarListItem::setName(formatted_phone);
+ LLAvatarListItem::setAvatarName(formatted_phone);
+ LLAvatarListItem::setAvatarToolTip(formatted_phone);
}
void setSpeakerId(const LLUUID& id) { mSpeakingIndicator->setSpeakerId(id); }
@@ -374,9 +376,31 @@ void LLCallFloater::sOnCurrentChannelChanged(const LLUUID& /*session_id*/)
call_floater->connectToChannel(channel);
}
+void LLCallFloater::onAvatarNameCache(const LLUUID& agent_id,
+ const LLAvatarName& av_name)
+{
+ LLStringUtil::format_map_t args;
+ args["[NAME]"] = av_name.getCompleteName();
+ std::string title = getString("title_peer_2_peer", args);
+ setTitle(title);
+}
+
void LLCallFloater::updateTitle()
{
LLVoiceChannel* voice_channel = LLVoiceChannel::getCurrentVoiceChannel();
+ if (mVoiceType == VC_PEER_TO_PEER)
+ {
+ LLUUID session_id = voice_channel->getSessionID();
+ LLIMModel::LLIMSession* im_session =
+ LLIMModel::getInstance()->findIMSession(session_id);
+ if (im_session)
+ {
+ LLAvatarNameCache::get(im_session->mOtherParticipantID,
+ boost::bind(&LLCallFloater::onAvatarNameCache,
+ this, _1, _2));
+ return;
+ }
+ }
std::string title;
switch (mVoiceType)
{
@@ -421,9 +445,10 @@ void LLCallFloater::initAgentData()
{
mAgentPanel->childSetValue("user_icon", gAgentID);
- std::string name;
- gCacheName->getFullName(gAgentID, name);
- mAgentPanel->childSetValue("user_text", name);
+ // Just use display name, because it's you
+ LLAvatarName av_name;
+ LLAvatarNameCache::get( gAgentID, &av_name );
+ mAgentPanel->childSetValue("user_text", av_name.mDisplayName);
mSpeakingIndicator = mAgentPanel->getChild<LLOutputMonitorCtrl>("speaking_indicator");
mSpeakingIndicator->setSpeakerId(gAgentID);
@@ -444,7 +469,10 @@ void LLCallFloater::setModeratorMutedVoice(bool moderator_muted)
void LLCallFloater::updateAgentModeratorState()
{
std::string name;
- gCacheName->getFullName(gAgentID, name);
+ // Just use display name, because it's you
+ LLAvatarName av_name;
+ LLAvatarNameCache::get(gAgentID, &av_name);
+ name = av_name.mDisplayName;
if(gAgent.isInGroup(mSpeakerManager->getSessionID()))
{
diff --git a/indra/newview/llcallfloater.h b/indra/newview/llcallfloater.h
index e4341175e2..5eafede482 100644
--- a/indra/newview/llcallfloater.h
+++ b/indra/newview/llcallfloater.h
@@ -40,6 +40,7 @@
class LLAvatarList;
class LLAvatarListItem;
+class LLAvatarName;
class LLNonAvatarCaller;
class LLOutputMonitorCtrl;
class LLParticipantList;
@@ -122,6 +123,10 @@ private:
*/
void onAvatarListRefreshed();
+ /**
+ * Updates window title with an avatar name
+ */
+ void onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name);
void updateTitle();
void initAgentData();
diff --git a/indra/newview/llcallingcard.cpp b/indra/newview/llcallingcard.cpp
index 1a6c11fa73..1685562013 100644
--- a/indra/newview/llcallingcard.cpp
+++ b/indra/newview/llcallingcard.cpp
@@ -43,6 +43,7 @@
//#include <iterator>
#include "indra_constants.h"
+#include "llavatarnamecache.h"
#include "llcachename.h"
#include "llstl.h"
#include "lltimer.h"
@@ -50,6 +51,7 @@
#include "message.h"
#include "llagent.h"
+#include "llavatarnamecache.h"
#include "llbutton.h"
#include "llinventoryobserver.h"
#include "llinventorymodel.h"
@@ -96,8 +98,10 @@ const F32 OFFLINE_SECONDS = FIND_FREQUENCY + 8.0f;
// static
LLAvatarTracker LLAvatarTracker::sInstance;
-
-
+static void on_avatar_name_cache_notify(const LLUUID& agent_id,
+ const LLAvatarName& av_name,
+ bool online,
+ LLSD payload);
///----------------------------------------------------------------------------
/// Class LLAvatarTracker
@@ -250,7 +254,7 @@ S32 LLAvatarTracker::addBuddyList(const LLAvatarTracker::buddy_map_t& buds)
using namespace std;
U32 new_buddy_count = 0;
- std::string first,last;
+ std::string full_name;
LLUUID agent_id;
for(buddy_map_t::const_iterator itr = buds.begin(); itr != buds.end(); ++itr)
{
@@ -260,7 +264,8 @@ S32 LLAvatarTracker::addBuddyList(const LLAvatarTracker::buddy_map_t& buds)
{
++new_buddy_count;
mBuddyInfo[agent_id] = (*itr).second;
- gCacheName->getName(agent_id, first, last);
+ // IDEVO: is this necessary? name is unused?
+ gCacheName->getFullName(agent_id, full_name);
addChangedMask(LLFriendObserver::ADD, agent_id);
lldebugs << "Added buddy " << agent_id
<< ", " << (mBuddyInfo[agent_id]->isOnline() ? "Online" : "Offline")
@@ -633,12 +638,9 @@ void LLAvatarTracker::processChange(LLMessageSystem* msg)
{
if((mBuddyInfo[agent_id]->getRightsGrantedFrom() ^ new_rights) & LLRelationship::GRANT_MODIFY_OBJECTS)
{
- std::string name;
LLSD args;
- if(gCacheName->getFullName(agent_id, name))
- {
- args["NAME"] = name;
- }
+ args["NAME"] = LLSLURL("agent", agent_id, "displayname").getSLURLString();
+
LLSD payload;
payload["from_id"] = agent_id;
if(LLRelationship::GRANT_MODIFY_OBJECTS & new_rights)
@@ -680,8 +682,6 @@ void LLAvatarTracker::processNotify(LLMessageSystem* msg, bool online)
{
tracking_id = mTrackingData->mAvatarID;
}
- BOOL notify = FALSE;
- LLSD args;
LLSD payload;
for(S32 i = 0; i < count; ++i)
{
@@ -691,17 +691,6 @@ void LLAvatarTracker::processNotify(LLMessageSystem* msg, bool online)
if(info)
{
setBuddyOnline(agent_id,online);
- if(chat_notify)
- {
- std::string first, last;
- if(gCacheName->getName(agent_id, first, last))
- {
- notify = TRUE;
- args["FIRST"] = first;
- args["LAST"] = last;
- }
-
- }
}
else
{
@@ -717,29 +706,12 @@ void LLAvatarTracker::processNotify(LLMessageSystem* msg, bool online)
// *TODO: get actual inventory id
gInventory.addChangedMask(LLInventoryObserver::CALLING_CARD, LLUUID::null);
}
- if(notify)
+ if(chat_notify)
{
- // Popup a notify box with online status of this agent
- LLNotificationPtr notification;
-
- if (online)
- {
- notification =
- LLNotificationsUtil::add("FriendOnline",
- args,
- payload.with("respond_on_mousedown", TRUE),
- boost::bind(&LLAvatarActions::startIM, agent_id));
- }
- else
- {
- notification =
- LLNotificationsUtil::add("FriendOffline", args, payload);
- }
-
- // If there's an open IM session with this agent, send a notification there too.
- LLUUID session_id = LLIMMgr::computeSessionID(IM_NOTHING_SPECIAL, agent_id);
- std::string notify_msg = notification->getMessage();
- LLIMModel::instance().proccessOnlineOfflineNotification(session_id, notify_msg);
+ // Look up the name of this agent for the notification
+ LLAvatarNameCache::get(agent_id,
+ boost::bind(&on_avatar_name_cache_notify,
+ _1, _2, online, payload));
}
mModifyMask |= LLFriendObserver::ONLINE;
@@ -748,6 +720,37 @@ void LLAvatarTracker::processNotify(LLMessageSystem* msg, bool online)
}
}
+static void on_avatar_name_cache_notify(const LLUUID& agent_id,
+ const LLAvatarName& av_name,
+ bool online,
+ LLSD payload)
+{
+ // Popup a notify box with online status of this agent
+ // Use display name only because this user is your friend
+ LLSD args;
+ args["NAME"] = av_name.mDisplayName;
+
+ LLNotificationPtr notification;
+ if (online)
+ {
+ notification =
+ LLNotificationsUtil::add("FriendOnline",
+ args,
+ payload.with("respond_on_mousedown", TRUE),
+ boost::bind(&LLAvatarActions::startIM, agent_id));
+ }
+ else
+ {
+ notification =
+ LLNotificationsUtil::add("FriendOffline", args, payload);
+ }
+
+ // If there's an open IM session with this agent, send a notification there too.
+ LLUUID session_id = LLIMMgr::computeSessionID(IM_NOTHING_SPECIAL, agent_id);
+ std::string notify_msg = notification->getMessage();
+ LLIMModel::instance().proccessOnlineOfflineNotification(session_id, notify_msg);
+}
+
void LLAvatarTracker::formFriendship(const LLUUID& id)
{
if(id.notNull())
@@ -868,10 +871,9 @@ bool LLCollectProxyBuddies::operator()(const LLUUID& buddy_id, LLRelationship* b
bool LLCollectMappableBuddies::operator()(const LLUUID& buddy_id, LLRelationship* buddy)
{
- gCacheName->getName(buddy_id, mFirst, mLast);
- std::ostringstream fullname;
- fullname << mFirst << " " << mLast;
- buddy_map_t::value_type value(fullname.str(), buddy_id);
+ LLAvatarName av_name;
+ LLAvatarNameCache::get( buddy_id, &av_name);
+ buddy_map_t::value_type value(av_name.mDisplayName, buddy_id);
if(buddy->isOnline() && buddy->isRightGrantedFrom(LLRelationship::GRANT_MAP_LOCATION))
{
mMappable.insert(value);
@@ -881,10 +883,8 @@ bool LLCollectMappableBuddies::operator()(const LLUUID& buddy_id, LLRelationship
bool LLCollectOnlineBuddies::operator()(const LLUUID& buddy_id, LLRelationship* buddy)
{
- gCacheName->getName(buddy_id, mFirst, mLast);
- std::ostringstream fullname;
- fullname << mFirst << " " << mLast;
- buddy_map_t::value_type value(fullname.str(), buddy_id);
+ gCacheName->getFullName(buddy_id, mFullName);
+ buddy_map_t::value_type value(mFullName, buddy_id);
if(buddy->isOnline())
{
mOnline.insert(value);
@@ -894,10 +894,10 @@ bool LLCollectOnlineBuddies::operator()(const LLUUID& buddy_id, LLRelationship*
bool LLCollectAllBuddies::operator()(const LLUUID& buddy_id, LLRelationship* buddy)
{
- gCacheName->getName(buddy_id, mFirst, mLast);
- std::ostringstream fullname;
- fullname << mFirst << " " << mLast;
- buddy_map_t::value_type value(fullname.str(), buddy_id);
+ LLAvatarName av_name;
+ LLAvatarNameCache::get(buddy_id, &av_name);
+ mFullName = av_name.mDisplayName;
+ buddy_map_t::value_type value(mFullName, buddy_id);
if(buddy->isOnline())
{
mOnline.insert(value);
@@ -908,5 +908,3 @@ bool LLCollectAllBuddies::operator()(const LLUUID& buddy_id, LLRelationship* bud
}
return true;
}
-
-
diff --git a/indra/newview/llcallingcard.h b/indra/newview/llcallingcard.h
index 47b0dcb903..5bd1f05687 100644
--- a/indra/newview/llcallingcard.h
+++ b/indra/newview/llcallingcard.h
@@ -241,8 +241,7 @@ public:
virtual bool operator()(const LLUUID& buddy_id, LLRelationship* buddy);
typedef std::map<std::string, LLUUID, LLDictionaryLess> buddy_map_t;
buddy_map_t mMappable;
- std::string mFirst;
- std::string mLast;
+ std::string mFullName;
};
// collect dictionary sorted map of name -> agent_id for every online buddy
@@ -254,8 +253,7 @@ public:
virtual bool operator()(const LLUUID& buddy_id, LLRelationship* buddy);
typedef std::map<std::string, LLUUID, LLDictionaryLess> buddy_map_t;
buddy_map_t mOnline;
- std::string mFirst;
- std::string mLast;
+ std::string mFullName;
};
// collect dictionary sorted map of name -> agent_id for every buddy,
@@ -269,8 +267,7 @@ public:
typedef std::map<std::string, LLUUID, LLDictionaryLess> buddy_map_t;
buddy_map_t mOnline;
buddy_map_t mOffline;
- std::string mFirst;
- std::string mLast;
+ std::string mFullName;
};
#endif // LL_LLCALLINGCARD_H
diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp
index c0fa910f86..c21ec9e919 100644
--- a/indra/newview/llchathistory.cpp
+++ b/indra/newview/llchathistory.cpp
@@ -32,10 +32,12 @@
#include "llviewerprecompiledheaders.h"
+#include "llchathistory.h"
+
+#include "llavatarnamecache.h"
#include "llinstantmessage.h"
#include "llimview.h"
-#include "llchathistory.h"
#include "llcommandhandler.h"
#include "llpanel.h"
#include "lluictrlfactory.h"
@@ -104,6 +106,18 @@ LLObjectIMHandler gObjectIMHandler;
class LLChatHistoryHeader: public LLPanel
{
public:
+ LLChatHistoryHeader()
+ : LLPanel(),
+ mPopupMenuHandleAvatar(),
+ mPopupMenuHandleObject(),
+ mAvatarID(),
+ mSourceType(CHAT_SOURCE_UNKNOWN),
+ mFrom(),
+ mSessionID(),
+ mMinUserNameWidth(0),
+ mUserNameFont(NULL)
+ {}
+
static LLChatHistoryHeader* createInstance(const std::string& file_name)
{
LLChatHistoryHeader* pInstance = new LLChatHistoryHeader;
@@ -240,7 +254,6 @@ public:
mAvatarID = chat.mFromID;
mSessionID = chat.mSessionID;
mSourceType = chat.mSourceType;
- gCacheName->get(mAvatarID, FALSE, boost::bind(&LLChatHistoryHeader::nameUpdatedCallback, this, _1, _2, _3, _4));
//*TODO overly defensive thing, source type should be maintained out there
if((chat.mFromID.isNull() && chat.mFromName.empty()) || chat.mFromName == SYSTEM_FROM && chat.mFromID.isNull())
@@ -248,22 +261,40 @@ public:
mSourceType = CHAT_SOURCE_SYSTEM;
}
- LLTextBox* userName = getChild<LLTextBox>("user_name");
+ mUserNameFont = style_params.font();
+ LLTextBox* user_name = getChild<LLTextBox>("user_name");
+ user_name->setReadOnlyColor(style_params.readonly_color());
+ user_name->setColor(style_params.color());
- userName->setReadOnlyColor(style_params.readonly_color());
- userName->setColor(style_params.color());
-
- userName->setValue(chat.mFromName);
- mFrom = chat.mFromName;
- if (chat.mFromName.empty() || CHAT_SOURCE_SYSTEM == mSourceType)
+ if (chat.mFromName.empty()
+ || mSourceType == CHAT_SOURCE_SYSTEM
+ || mAvatarID.isNull())
{
mFrom = LLTrans::getString("SECOND_LIFE");
- userName->setValue(mFrom);
+ user_name->setValue(mFrom);
+ updateMinUserNameWidth();
+ }
+ else if (mSourceType == CHAT_SOURCE_AGENT
+ && chat.mChatStyle != CHAT_STYLE_HISTORY)
+ {
+ // ...from a normal user, lookup the name and fill in later.
+ // *NOTE: Do not do this for chat history logs, otherwise the viewer
+ // will flood the People API with lookup requests on startup
+
+ // Start with blank so sample data from XUI XML doesn't
+ // flash on the screen
+ user_name->setValue( LLSD() );
+ LLAvatarNameCache::get(mAvatarID,
+ boost::bind(&LLChatHistoryHeader::onAvatarNameCache, this, _1, _2));
+ }
+ else {
+ // ...from an object, just use name as given
+ mFrom = chat.mFromName;
+ user_name->setValue(mFrom);
+ updateMinUserNameWidth();
}
- mMinUserNameWidth = style_params.font()->getWidth(userName->getWText().c_str()) + PADDING;
-
setTimeField(chat);
LLAvatarIconCtrl* icon = getChild<LLAvatarIconCtrl>("avatar_icon");
@@ -317,12 +348,28 @@ public:
LLPanel::draw();
}
- void nameUpdatedCallback(const LLUUID& id,const std::string& first,const std::string& last,BOOL is_group)
+ void updateMinUserNameWidth()
{
- if (id != mAvatarID)
- return;
- mFrom = first + " " + last;
+ if (mUserNameFont)
+ {
+ LLTextBox* user_name = getChild<LLTextBox>("user_name");
+ const LLWString& text = user_name->getWText();
+ mMinUserNameWidth = mUserNameFont->getWidth(text.c_str()) + PADDING;
+ }
}
+
+ void onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name)
+ {
+ mFrom = av_name.mDisplayName;
+
+ LLTextBox* user_name = getChild<LLTextBox>("user_name");
+ user_name->setValue( LLSD(av_name.mDisplayName ) );
+ user_name->setToolTip( av_name.mUsername );
+ setToolTip( av_name.mUsername );
+ // name might have changed, update width
+ updateMinUserNameWidth();
+ }
+
protected:
static const S32 PADDING = 20;
@@ -439,6 +486,7 @@ protected:
LLUUID mSessionID;
S32 mMinUserNameWidth;
+ const LLFontGL* mUserNameFont;
};
LLUICtrl* LLChatHistoryHeader::sInfoCtrl = NULL;
diff --git a/indra/newview/lldateutil.cpp b/indra/newview/lldateutil.cpp
index 3e71ecdfba..ae955b6cad 100644
--- a/indra/newview/lldateutil.cpp
+++ b/indra/newview/lldateutil.cpp
@@ -172,3 +172,23 @@ std::string LLDateUtil::ageFromDate(const std::string& date_string)
{
return ageFromDate(date_string, LLDate::now());
}
+
+//std::string LLDateUtil::ageFromDateISO(const std::string& date_string,
+// const LLDate& now)
+//{
+// S32 born_month, born_day, born_year;
+// S32 matched = sscanf(date_string.c_str(), "%d-%d-%d",
+// &born_year, &born_month, &born_day);
+// if (matched != 3) return "???";
+// date.fromYMDHMS(year, month, day);
+// F64 secs_since_epoch = date.secondsSinceEpoch();
+// // Correct for the fact that specified date is in Pacific time, == UTC - 8
+// secs_since_epoch += 8.0 * 60.0 * 60.0;
+// date.secondsSinceEpoch(secs_since_epoch);
+// return ageFromDate(born_year, born_month, born_day, now);
+//}
+//
+//std::string LLDateUtil::ageFromDateISO(const std::string& date_string)
+//{
+// return ageFromDateISO(date_string, LLDate::now());
+//}
diff --git a/indra/newview/lldateutil.h b/indra/newview/lldateutil.h
index a0df21022e..8d41eea511 100644
--- a/indra/newview/lldateutil.h
+++ b/indra/newview/lldateutil.h
@@ -67,6 +67,14 @@ namespace LLDateUtil
// Calls the above with LLDate::now()
std::string ageFromDate(const std::string& date_string);
+
+ // As above, for YYYY-MM-DD dates
+ //std::string ageFromDateISO(const std::string& date_string, const LLDate& now);
+
+ // Calls the above with LLDate::now()
+ //std::string ageFromDateISO(const std::string& date_string);
+
+ //std::string ageFromDate(S32 born_year, S32 born_month, S32 born_day, const LLDate& now);
}
#endif
diff --git a/indra/newview/lldrawable.h b/indra/newview/lldrawable.h
index 08972853c3..05ce8cbe57 100644
--- a/indra/newview/lldrawable.h
+++ b/indra/newview/lldrawable.h
@@ -53,6 +53,7 @@ class LLCamera;
class LLDrawPool;
class LLDrawable;
class LLFace;
+class LLFacePool;
class LLSpatialGroup;
class LLSpatialBridge;
class LLSpatialPartition;
diff --git a/indra/newview/llfloateravatarpicker.cpp b/indra/newview/llfloateravatarpicker.cpp
index 8f6816b845..7ed6539387 100644
--- a/indra/newview/llfloateravatarpicker.cpp
+++ b/indra/newview/llfloateravatarpicker.cpp
@@ -41,10 +41,14 @@
#include "llimview.h" // for gIMMgr
#include "lltooldraganddrop.h" // for LLToolDragAndDrop
#include "llviewercontrol.h"
+#include "llviewerregion.h" // getCapability()
#include "llworld.h"
// Linden libraries
+#include "llavatarnamecache.h" // IDEVO
#include "llbutton.h"
+#include "llcachename.h"
+#include "llhttpclient.h" // IDEVO
#include "lllineeditor.h"
#include "llscrolllistctrl.h"
#include "llscrolllistitem.h"
@@ -53,6 +57,11 @@
#include "lluictrlfactory.h"
#include "message.h"
+//#include "llsdserialize.h"
+
+//put it back as a member once the legacy path is out?
+static std::map<LLUUID, LLAvatarName> sAvatarNameMap;
+
LLFloaterAvatarPicker* LLFloaterAvatarPicker::show(select_callback_t callback,
BOOL allow_multiple,
BOOL closeOnSelect)
@@ -159,7 +168,7 @@ void LLFloaterAvatarPicker::onBtnFind()
find();
}
-static void getSelectedAvatarData(const LLScrollListCtrl* from, std::vector<std::string>& avatar_names, uuid_vec_t& avatar_ids)
+static void getSelectedAvatarData(const LLScrollListCtrl* from, uuid_vec_t& avatar_ids, std::vector<LLAvatarName>& avatar_names)
{
std::vector<LLScrollListItem*> items = from->getAllSelected();
for (std::vector<LLScrollListItem*>::iterator iter = items.begin(); iter != items.end(); ++iter)
@@ -167,8 +176,21 @@ static void getSelectedAvatarData(const LLScrollListCtrl* from, std::vector<std:
LLScrollListItem* item = *iter;
if (item->getUUID().notNull())
{
- avatar_names.push_back(item->getColumn(0)->getValue().asString());
avatar_ids.push_back(item->getUUID());
+
+ std::map<LLUUID, LLAvatarName>::iterator iter = sAvatarNameMap.find(item->getUUID());
+ if (iter != sAvatarNameMap.end())
+ {
+ avatar_names.push_back(iter->second);
+ }
+ else
+ {
+ // the only case where it isn't in the name map is friends
+ // but it should be in the name cache
+ LLAvatarName av_name;
+ LLAvatarNameCache::get(item->getUUID(), &av_name);
+ avatar_names.push_back(av_name);
+ }
}
}
}
@@ -204,10 +226,10 @@ void LLFloaterAvatarPicker::onBtnSelect()
if(list)
{
- std::vector<std::string> avatar_names;
uuid_vec_t avatar_ids;
- getSelectedAvatarData(list, avatar_names, avatar_ids);
- mSelectionCallback(avatar_names, avatar_ids);
+ std::vector<LLAvatarName> avatar_names;
+ getSelectedAvatarData(list, avatar_ids, avatar_names);
+ mSelectionCallback(avatar_ids, avatar_names);
}
}
getChild<LLScrollListCtrl>("SearchResults")->deselectAllItems(TRUE);
@@ -257,15 +279,22 @@ void LLFloaterAvatarPicker::populateNearMe()
if(av == gAgent.getID()) continue;
LLSD element;
element["id"] = av; // value
- std::string fullname;
- if(!gCacheName->getFullName(av, fullname))
+ LLAvatarName av_name;
+
+ if (!LLAvatarNameCache::get(av, &av_name))
{
+ element["columns"][0]["column"] = "name";
element["columns"][0]["value"] = LLCacheName::getDefaultName();
all_loaded = FALSE;
}
else
{
- element["columns"][0]["value"] = fullname;
+ element["columns"][0]["column"] = "name";
+ element["columns"][0]["value"] = av_name.mDisplayName;
+ element["columns"][1]["column"] = "username";
+ element["columns"][1]["value"] = av_name.mUsername;
+
+ sAvatarNameMap[av] = av_name;
}
near_me_scroller->addElement(element);
empty = FALSE;
@@ -300,7 +329,6 @@ void LLFloaterAvatarPicker::populateFriend()
LLAvatarTracker::instance().applyFunctor(collector);
LLCollectAllBuddies::buddy_map_t::iterator it;
-
for(it = collector.mOnline.begin(); it!=collector.mOnline.end(); it++)
{
friends_scroller->addStringUUIDItem(it->first, it->second);
@@ -352,14 +380,69 @@ BOOL LLFloaterAvatarPicker::visibleItemsSelected() const
return FALSE;
}
+class LLAvatarPickerResponder : public LLHTTPClient::Responder
+{
+public:
+ LLUUID mQueryID;
+
+ LLAvatarPickerResponder(const LLUUID& id) : mQueryID(id) { }
+
+ /*virtual*/ void completed(U32 status, const std::string& reason, const LLSD& content)
+ {
+ //std::ostringstream ss;
+ //LLSDSerialize::toPrettyXML(content, ss);
+ //llinfos << ss.str() << llendl;
+
+ if (isGoodStatus(status))
+ {
+ LLFloaterAvatarPicker* floater =
+ LLFloaterReg::findTypedInstance<LLFloaterAvatarPicker>("avatar_picker");
+ if (floater)
+ {
+ floater->processResponse(mQueryID, content);
+ }
+ }
+ else
+ {
+ llinfos << "avatar picker failed " << status
+ << " reason " << reason << llendl;
+ }
+ }
+};
+
void LLFloaterAvatarPicker::find()
{
+ //clear our stored LLAvatarNames
+ sAvatarNameMap.clear();
+
std::string text = childGetValue("Edit").asString();
mQueryID.generate();
- LLMessageSystem* msg = gMessageSystem;
+ std::string url;
+ url.reserve(128); // avoid a memory allocation or two
+ LLViewerRegion* region = gAgent.getRegion();
+ url = region->getCapability("AvatarPickerSearch");
+ // Prefer use of capabilities to search on both SLID and display name
+ // but allow display name search to be manually turned off for test
+ if (!url.empty()
+ && LLAvatarNameCache::useDisplayNames())
+ {
+ // capability urls don't end in '/', but we need one to parse
+ // query parameters correctly
+ if (url.size() > 0 && url[url.size()-1] != '/')
+ {
+ url += "/";
+ }
+ url += "?names=";
+ url += LLURI::escape(text);
+ llinfos << "avatar picker " << url << llendl;
+ LLHTTPClient::get(url, new LLAvatarPickerResponder(mQueryID));
+ }
+ else
+ {
+ LLMessageSystem* msg = gMessageSystem;
msg->newMessage("AvatarPickerRequest");
msg->nextBlock("AgentData");
msg->addUUID("AgentID", gAgent.getID());
@@ -367,8 +450,8 @@ void LLFloaterAvatarPicker::find()
msg->addUUID("QueryID", mQueryID); // not used right now
msg->nextBlock("Data");
msg->addString("Name", text);
-
gAgent.sendReliableMessage();
+ }
getChild<LLScrollListCtrl>("SearchResults")->deleteAllItems();
getChild<LLScrollListCtrl>("SearchResults")->setCommentText(getString("searching"));
@@ -509,12 +592,21 @@ void LLFloaterAvatarPicker::processAvatarPickerReply(LLMessageSystem* msg, void*
}
else
{
- avatar_name = first_name + " " + last_name;
+ avatar_name = LLCacheName::buildFullName(first_name, last_name);
search_results->setEnabled(TRUE);
found_one = TRUE;
+
+ LLAvatarName av_name;
+ av_name.mLegacyFirstName = first_name;
+ av_name.mLegacyLastName = last_name;
+ av_name.mDisplayName = avatar_name;
+ const LLUUID& agent_id = avatar_id;
+ sAvatarNameMap[agent_id] = av_name;
+
}
LLSD element;
element["id"] = avatar_id; // value
+ element["columns"][0]["column"] = "name";
element["columns"][0]["value"] = avatar_name;
search_results->addElement(element);
}
@@ -528,10 +620,61 @@ void LLFloaterAvatarPicker::processAvatarPickerReply(LLMessageSystem* msg, void*
}
}
+void LLFloaterAvatarPicker::processResponse(const LLUUID& query_id, const LLSD& content)
+{
+ // Check for out-of-date query
+ if (query_id != mQueryID) return;
+
+ LLScrollListCtrl* search_results = getChild<LLScrollListCtrl>("SearchResults");
+
+ LLSD agents = content["agents"];
+ if (agents.size() == 0)
+ {
+ LLStringUtil::format_map_t map;
+ map["[TEXT]"] = childGetText("Edit");
+ LLSD item;
+ item["id"] = LLUUID::null;
+ item["columns"][0]["column"] = "name";
+ item["columns"][0]["value"] = getString("not_found", map);
+ search_results->addElement(item);
+ search_results->setEnabled(FALSE);
+ childDisable("ok_btn");
+ return;
+ }
+
+ // clear "Searching" label on first results
+ search_results->deleteAllItems();
+
+ LLSD item;
+ LLSD::array_const_iterator it = agents.beginArray();
+ for ( ; it != agents.endArray(); ++it)
+ {
+ const LLSD& row = *it;
+ item["id"] = row["id"];
+ LLSD& columns = item["columns"];
+ columns[0]["column"] = "name";
+ columns[0]["value"] = row["display_name"];
+ columns[1]["column"] = "username";
+ columns[1]["value"] = row["username"];
+ search_results->addElement(item);
+
+ // add the avatar name to our list
+ LLAvatarName avatar_name;
+ avatar_name.fromLLSD(row);
+ sAvatarNameMap[row["id"].asUUID()] = avatar_name;
+ }
+
+ childEnable("ok_btn");
+ search_results->setEnabled(true);
+ search_results->selectFirstItem();
+ onList();
+ search_results->setFocus(TRUE);
+}
+
//static
void LLFloaterAvatarPicker::editKeystroke(LLLineEditor* caller, void* user_data)
{
- childSetEnabled("Find", caller->getText().size() >= 3);
+ childSetEnabled("Find", caller->getText().size() > 0);
}
// virtual
@@ -589,8 +732,8 @@ bool LLFloaterAvatarPicker::isSelectBtnEnabled()
if(list)
{
uuid_vec_t avatar_ids;
- std::vector<std::string> avatar_names;
- getSelectedAvatarData(list, avatar_names, avatar_ids);
+ std::vector<LLAvatarName> avatar_names;
+ getSelectedAvatarData(list, avatar_ids, avatar_names);
return mOkButtonValidateSignal(avatar_ids);
}
}
diff --git a/indra/newview/llfloateravatarpicker.h b/indra/newview/llfloateravatarpicker.h
index 0af72e85a0..2607500dd8 100644
--- a/indra/newview/llfloateravatarpicker.h
+++ b/indra/newview/llfloateravatarpicker.h
@@ -37,6 +37,7 @@
#include <vector>
+class LLAvatarName;
class LLScrollListCtrl;
class LLFloaterAvatarPicker : public LLFloater
@@ -46,7 +47,7 @@ public:
typedef validate_signal_t::slot_type validate_callback_t;
// The callback function will be called with an avatar name and UUID.
- typedef boost::function<void (const std::vector<std::string>&, const uuid_vec_t&)> select_callback_t;
+ typedef boost::function<void (const uuid_vec_t&, const std::vector<LLAvatarName>&)> select_callback_t;
// Call this to select an avatar.
static LLFloaterAvatarPicker* show(select_callback_t callback,
BOOL allow_multiple = FALSE,
@@ -60,6 +61,7 @@ public:
void setOkBtnEnableCb(validate_callback_t cb);
static void processAvatarPickerReply(class LLMessageSystem* msg, void**);
+ void processResponse(const LLUUID& query_id, const LLSD& content);
BOOL handleDragAndDrop(S32 x, S32 y, MASK mask,
BOOL drop, EDragAndDropType cargo_type,
diff --git a/indra/newview/llfloateravatartextures.cpp b/indra/newview/llfloateravatartextures.cpp
index 847462a6c3..f09071e92d 100644
--- a/indra/newview/llfloateravatartextures.cpp
+++ b/indra/newview/llfloateravatartextures.cpp
@@ -33,6 +33,9 @@
#include "llviewerprecompiledheaders.h"
#include "llfloateravatartextures.h"
+// library headers
+#include "llavatarnamecache.h"
+
#include "llagent.h"
#include "llagentwearables.h"
#include "lltexturectrl.h"
@@ -138,10 +141,10 @@ void LLFloaterAvatarTextures::refresh()
LLVOAvatar *avatarp = find_avatar(mID);
if (avatarp)
{
- std::string fullname;
- if (gCacheName->getFullName(avatarp->getID(), fullname))
+ LLAvatarName av_name;
+ if (LLAvatarNameCache::get(avatarp->getID(), &av_name))
{
- setTitle(mTitle + ": " + fullname);
+ setTitle(mTitle + ": " + av_name.getCompleteName());
}
for (U32 i=0; i < TEX_NUM_INDICES; i++)
{
diff --git a/indra/newview/llfloaterbump.cpp b/indra/newview/llfloaterbump.cpp
index e925796526..9ccae43a92 100644
--- a/indra/newview/llfloaterbump.cpp
+++ b/indra/newview/llfloaterbump.cpp
@@ -89,7 +89,7 @@ void LLFloaterBump::onOpen(const LLSD& key)
void LLFloaterBump::add(LLScrollListCtrl* list, LLMeanCollisionData* mcd)
{
- if (mcd->mFirstName.empty() || list->getItemCount() >= 20)
+ if (mcd->mFullName.empty() || list->getItemCount() >= 20)
{
return;
}
@@ -127,8 +127,7 @@ void LLFloaterBump::add(LLScrollListCtrl* list, LLMeanCollisionData* mcd)
// All above action strings are in XML file
LLUIString text = getString(action);
text.setArg("[TIME]", timeStr);
- text.setArg("[FIRST]", mcd->mFirstName);
- text.setArg("[LAST]", mcd->mLastName);
+ text.setArg("[NAME]", mcd->mFullName);
LLSD row;
row["id"] = mcd->mPerp;
diff --git a/indra/newview/llfloaterbuyland.cpp b/indra/newview/llfloaterbuyland.cpp
index 9379b3f5a8..1e6b748bd7 100644
--- a/indra/newview/llfloaterbuyland.cpp
+++ b/indra/newview/llfloaterbuyland.cpp
@@ -186,9 +186,8 @@ public:
void updateNames();
// Name cache callback
void updateGroupName(const LLUUID& id,
- const std::string& first_name,
- const std::string& last_name,
- BOOL is_group);
+ const std::string& name,
+ bool is_group);
void refreshUI();
@@ -825,28 +824,26 @@ void LLFloaterBuyLandUI::updateNames()
}
else if (parcelp->getIsGroupOwned())
{
- gCacheName->get(parcelp->getGroupID(), TRUE,
+ gCacheName->getGroup(parcelp->getGroupID(),
boost::bind(&LLFloaterBuyLandUI::updateGroupName, this,
- _1, _2, _3, _4));
+ _1, _2, _3));
}
else
{
- mParcelSellerName =
- LLSLURL("agent", parcelp->getOwnerID(), "inspect").getSLURLString();
+ mParcelSellerName = LLSLURL("agent", parcelp->getOwnerID(), "completename").getSLURLString();
}
}
void LLFloaterBuyLandUI::updateGroupName(const LLUUID& id,
- const std::string& first_name,
- const std::string& last_name,
- BOOL is_group)
+ const std::string& name,
+ bool is_group)
{
LLParcel* parcelp = mParcel->getParcel();
if (parcelp
&& parcelp->getGroupID() == id)
{
// request is current
- mParcelSellerName = first_name;
+ mParcelSellerName = name;
}
}
diff --git a/indra/newview/llfloatergodtools.cpp b/indra/newview/llfloatergodtools.cpp
index bd07cfdfbf..44f104d687 100644
--- a/indra/newview/llfloatergodtools.cpp
+++ b/indra/newview/llfloatergodtools.cpp
@@ -34,6 +34,7 @@
#include "llfloatergodtools.h"
+#include "llavatarnamecache.h"
#include "llcoord.h"
#include "llfontgl.h"
#include "llframetimer.h"
@@ -1151,11 +1152,11 @@ void LLPanelObjectTools::onClickSetBySelection(void* data)
panelp->childSetValue("target_avatar_name", name);
}
-void LLPanelObjectTools::callbackAvatarID(const std::vector<std::string>& names, const uuid_vec_t& ids)
+void LLPanelObjectTools::callbackAvatarID(const uuid_vec_t& ids, const std::vector<LLAvatarName> names)
{
if (ids.empty() || names.empty()) return;
mTargetAvatar = ids[0];
- childSetValue("target_avatar_name", names[0]);
+ childSetValue("target_avatar_name", names[0].getCompleteName());
refresh();
}
diff --git a/indra/newview/llfloatergodtools.h b/indra/newview/llfloatergodtools.h
index aee9db78a3..438f1024ce 100644
--- a/indra/newview/llfloatergodtools.h
+++ b/indra/newview/llfloatergodtools.h
@@ -41,6 +41,7 @@
#include "llpanel.h"
#include <vector>
+class LLAvatarName;
class LLButton;
class LLCheckBoxCtrl;
class LLComboBox;
@@ -231,7 +232,7 @@ public:
void onChangeAnything();
void onApplyChanges();
void onClickSet();
- void callbackAvatarID(const std::vector<std::string>& names, const uuid_vec_t& ids);
+ void callbackAvatarID(const uuid_vec_t& ids, const std::vector<LLAvatarName> names);
void onClickDeletePublicOwnedBy();
void onClickDeleteAllScriptedOwnedBy();
void onClickDeleteAllOwnedBy();
diff --git a/indra/newview/llfloaterinspect.cpp b/indra/newview/llfloaterinspect.cpp
index 13ca7638c5..f22ab70678 100644
--- a/indra/newview/llfloaterinspect.cpp
+++ b/indra/newview/llfloaterinspect.cpp
@@ -37,7 +37,7 @@
#include "llfloaterreg.h"
#include "llfloatertools.h"
#include "llavataractions.h"
-#include "llcachename.h"
+#include "llavatarnamecache.h"
#include "llscrolllistctrl.h"
#include "llscrolllistitem.h"
#include "llselectmgr.h"
@@ -212,8 +212,12 @@ void LLFloaterInspect::refresh()
substitution["datetime"] = (S32) timestamp;
LLStringUtil::format (timeStr, substitution);
- gCacheName->getFullName(obj->mPermissions->getOwner(), owner_name);
- gCacheName->getFullName(obj->mPermissions->getCreator(), creator_name);
+ LLAvatarName av_name;
+ LLAvatarNameCache::get(obj->mPermissions->getOwner(), &av_name);
+ owner_name = av_name.getCompleteName();
+ LLAvatarNameCache::get(obj->mPermissions->getCreator(), &av_name);
+ creator_name = av_name.getCompleteName();
+
row["id"] = obj->getObject()->getID();
row["columns"][0]["column"] = "object_name";
row["columns"][0]["type"] = "text";
diff --git a/indra/newview/llfloaterland.cpp b/indra/newview/llfloaterland.cpp
index 913bb676b0..6cbd01ae1f 100644
--- a/indra/newview/llfloaterland.cpp
+++ b/indra/newview/llfloaterland.cpp
@@ -37,7 +37,7 @@
#include "llfloaterland.h"
-#include "llcachename.h"
+#include "llavatarnamecache.h"
#include "llfocusmgr.h"
#include "llnotificationsutil.h"
#include "llparcel.h"
@@ -1392,10 +1392,7 @@ bool LLPanelLandObjects::callbackReturnOwnerObjects(const LLSD& notification, co
}
else
{
- std::string first, last;
- gCacheName->getName(owner_id, first, last);
- args["FIRST"] = first;
- args["LAST"] = last;
+ args["NAME"] = LLSLURL("agent", owner_id, "completename").getSLURLString();
LLNotificationsUtil::add("OtherObjectsReturned", args);
}
send_return_objects_message(parcel->getLocalID(), RT_OWNER);
@@ -1613,9 +1610,9 @@ void LLPanelLandObjects::processParcelObjectOwnersReply(LLMessageSystem *msg, vo
}
// Placeholder for name.
- std::string name;
- gCacheName->getFullName(owner_id, name);
- item_params.columns.add().value(name).font(FONT).column("name");
+ LLAvatarName av_name;
+ LLAvatarNameCache::get(owner_id, &av_name);
+ item_params.columns.add().value(av_name.getCompleteName()).font(FONT).column("name");
object_count_str = llformat("%d", object_count);
item_params.columns.add().value(object_count_str).font(FONT).column("count");
@@ -1724,9 +1721,7 @@ void LLPanelLandObjects::onClickReturnOwnerObjects(void* userdata)
}
else
{
- std::string name;
- gCacheName->getFullName(owner_id, name);
- args["NAME"] = name;
+ args["NAME"] = LLSLURL("agent", owner_id, "completename").getSLURLString();
LLNotificationsUtil::add("ReturnObjectsOwnedByUser", args, LLSD(), boost::bind(&LLPanelLandObjects::callbackReturnOwnerObjects, panelp, _1, _2));
}
}
@@ -1785,10 +1780,7 @@ void LLPanelLandObjects::onClickReturnOtherObjects(void* userdata)
}
else
{
- std::string name;
- gCacheName->getFullName(owner_id, name);
- args["NAME"] = name;
-
+ args["NAME"] = LLSLURL("agent", owner_id, "completename").getSLURLString();
LLNotificationsUtil::add("ReturnObjectsNotOwnedByUser", args, LLSD(), boost::bind(&LLPanelLandObjects::callbackReturnOtherObjects, panelp, _1, _2));
}
}
@@ -2778,12 +2770,12 @@ void LLPanelLandAccess::onCommitAny(LLUICtrl *ctrl, void *userdata)
void LLPanelLandAccess::onClickAddAccess()
{
- gFloaterView->getParentFloater(this)->addDependentFloater(LLFloaterAvatarPicker::show(boost::bind(&LLPanelLandAccess::callbackAvatarCBAccess, this, _1,_2)) );
+ gFloaterView->getParentFloater(this)->addDependentFloater(LLFloaterAvatarPicker::show(boost::bind(&LLPanelLandAccess::callbackAvatarCBAccess, this, _1)) );
}
-void LLPanelLandAccess::callbackAvatarCBAccess(const std::vector<std::string>& names, const uuid_vec_t& ids)
+void LLPanelLandAccess::callbackAvatarCBAccess(const uuid_vec_t& ids)
{
- if (!names.empty() && !ids.empty())
+ if (!ids.empty())
{
LLUUID id = ids[0];
LLParcel* parcel = mParcel->getParcel();
@@ -2822,13 +2814,13 @@ void LLPanelLandAccess::onClickRemoveAccess(void* data)
// static
void LLPanelLandAccess::onClickAddBanned()
{
- gFloaterView->getParentFloater(this)->addDependentFloater(LLFloaterAvatarPicker::show(boost::bind(&LLPanelLandAccess::callbackAvatarCBBanned, this, _1,_2)));
+ gFloaterView->getParentFloater(this)->addDependentFloater(LLFloaterAvatarPicker::show(boost::bind(&LLPanelLandAccess::callbackAvatarCBBanned, this, _1)));
}
// static
-void LLPanelLandAccess::callbackAvatarCBBanned(const std::vector<std::string>& names, const uuid_vec_t& ids)
+void LLPanelLandAccess::callbackAvatarCBBanned(const uuid_vec_t& ids)
{
- if (!names.empty() && !ids.empty())
+ if (!ids.empty())
{
LLUUID id = ids[0];
LLParcel* parcel = mParcel->getParcel();
diff --git a/indra/newview/llfloaterland.h b/indra/newview/llfloaterland.h
index 0a743e5215..e742d04aa0 100644
--- a/indra/newview/llfloaterland.h
+++ b/indra/newview/llfloaterland.h
@@ -379,8 +379,8 @@ public:
void onClickAddAccess();
void onClickAddBanned();
- void callbackAvatarCBBanned(const std::vector<std::string>& names, const uuid_vec_t& ids);
- void callbackAvatarCBAccess(const std::vector<std::string>& names, const uuid_vec_t& ids);
+ void callbackAvatarCBBanned(const uuid_vec_t& ids);
+ void callbackAvatarCBAccess(const uuid_vec_t& ids);
protected:
LLNameListCtrl* mListAccess;
diff --git a/indra/newview/llfloaterpay.cpp b/indra/newview/llfloaterpay.cpp
index ba7526ccd5..dc424720a7 100644
--- a/indra/newview/llfloaterpay.cpp
+++ b/indra/newview/llfloaterpay.cpp
@@ -47,6 +47,7 @@
#include "lllineeditor.h"
#include "llmutelist.h"
#include "llfloaterreporter.h"
+#include "llslurl.h"
#include "llviewerobject.h"
#include "llviewerobjectlist.h"
#include "llviewerregion.h"
@@ -102,10 +103,6 @@ private:
static void onGive(void* data);
void give(S32 amount);
static void processPayPriceReply(LLMessageSystem* msg, void **userdata);
- void onCacheOwnerName(const LLUUID& owner_id,
- const std::string& firstname,
- const std::string& lastname,
- BOOL is_group);
void finishPayUI(const LLUUID& target_id, BOOL is_group);
protected:
@@ -430,33 +427,26 @@ void LLFloaterPay::payDirectly(money_callback callback,
void LLFloaterPay::finishPayUI(const LLUUID& target_id, BOOL is_group)
{
- gCacheName->get(target_id, is_group, boost::bind(&LLFloaterPay::onCacheOwnerName, this, _1, _2, _3, _4));
-
- // Make sure the amount field has focus
-
- childSetFocus("amount", TRUE);
-
- LLLineEditor* amount = getChild<LLLineEditor>("amount");
- amount->selectAll();
- mTargetIsGroup = is_group;
-}
-
-void LLFloaterPay::onCacheOwnerName(const LLUUID& owner_id,
- const std::string& firstname,
- const std::string& lastname,
- BOOL is_group)
-{
+ std::string slurl;
if (is_group)
{
setTitle(getString("payee_group"));
+ slurl = LLSLURL("group", target_id, "inspect").getSLURLString();
}
else
{
setTitle(getString("payee_resident"));
+ slurl = LLSLURL("agent", target_id, "inspect").getSLURLString();
}
+ childSetText("payee_name", slurl);
- childSetTextArg("payee_name", "[FIRST]", firstname);
- childSetTextArg("payee_name", "[LAST]", lastname);
+ // Make sure the amount field has focus
+
+ childSetFocus("amount", TRUE);
+
+ LLLineEditor* amount = getChild<LLLineEditor>("amount");
+ amount->selectAll();
+ mTargetIsGroup = is_group;
}
// static
diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp
index 3ce1b46a4c..69e81ce157 100644
--- a/indra/newview/llfloaterpreference.cpp
+++ b/indra/newview/llfloaterpreference.cpp
@@ -82,6 +82,7 @@
#include "llvosky.h"
// linden library includes
+#include "llavatarnamecache.h"
#include "llerror.h"
#include "llfontgl.h"
#include "llrect.h"
@@ -185,6 +186,8 @@ void LLVoiceSetKeyDialog::onCancel(void* user_data)
// if creating/destroying these is too slow, we'll need to create
// a static member and update all our static callbacks
+void handleNameTagOptionChanged(const LLSD& newvalue);
+void handleDisplayNamesOptionChanged(const LLSD& newvalue);
bool callback_clear_browser_cache(const LLSD& notification, const LLSD& response);
//bool callback_skip_dialogs(const LLSD& notification, const LLSD& response, LLFloaterPreference* floater);
@@ -220,6 +223,18 @@ bool callback_clear_browser_cache(const LLSD& notification, const LLSD& response
return false;
}
+void handleNameTagOptionChanged(const LLSD& newvalue)
+{
+ LLVOAvatar::invalidateNameTags();
+}
+
+void handleDisplayNamesOptionChanged(const LLSD& newvalue)
+{
+ LLAvatarNameCache::setUseDisplayNames(newvalue.asBoolean());
+ LLVOAvatar::invalidateNameTags();
+}
+
+
/*bool callback_skip_dialogs(const LLSD& notification, const LLSD& response, LLFloaterPreference* floater)
{
S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
@@ -313,6 +328,10 @@ LLFloaterPreference::LLFloaterPreference(const LLSD& key)
mCommitCallbackRegistrar.add("Pref.BlockList", boost::bind(&LLFloaterPreference::onClickBlockList, this));
sSkin = gSavedSettings.getString("SkinCurrent");
+
+ gSavedSettings.getControl("NameTagShowUsernames")->getCommitSignal()->connect(boost::bind(&handleNameTagOptionChanged, _2));
+ gSavedSettings.getControl("NameTagShowFriends")->getCommitSignal()->connect(boost::bind(&handleNameTagOptionChanged, _2));
+ gSavedSettings.getControl("UseDisplayNames")->getCommitSignal()->connect(boost::bind(&handleDisplayNamesOptionChanged, _2));
}
BOOL LLFloaterPreference::postBuild()
diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp
index 8c219cb3fd..590e14a362 100644
--- a/indra/newview/llfloaterregioninfo.cpp
+++ b/indra/newview/llfloaterregioninfo.cpp
@@ -49,6 +49,7 @@
#include "llagent.h"
#include "llappviewer.h"
+#include "llavatarname.h"
#include "llfloateravatarpicker.h"
#include "llbutton.h"
#include "llcheckboxctrl.h"
@@ -606,13 +607,13 @@ void LLPanelRegionGeneralInfo::onClickKick()
// this depends on the grandparent view being a floater
// in order to set up floater dependency
LLFloater* parent_floater = gFloaterView->getParentFloater(this);
- LLFloater* child_floater = LLFloaterAvatarPicker::show(boost::bind(&LLPanelRegionGeneralInfo::onKickCommit, this, _1,_2), FALSE, TRUE);
+ LLFloater* child_floater = LLFloaterAvatarPicker::show(boost::bind(&LLPanelRegionGeneralInfo::onKickCommit, this, _1), FALSE, TRUE);
parent_floater->addDependentFloater(child_floater);
}
-void LLPanelRegionGeneralInfo::onKickCommit(const std::vector<std::string>& names, const uuid_vec_t& ids)
+void LLPanelRegionGeneralInfo::onKickCommit(const uuid_vec_t& ids)
{
- if (names.empty() || ids.empty()) return;
+ if (ids.empty()) return;
if(ids[0].notNull())
{
strings_t strings;
@@ -848,11 +849,11 @@ void LLPanelRegionDebugInfo::onClickChooseAvatar()
}
-void LLPanelRegionDebugInfo::callbackAvatarID(const std::vector<std::string>& names, const uuid_vec_t& ids)
+void LLPanelRegionDebugInfo::callbackAvatarID(const uuid_vec_t& ids, const std::vector<LLAvatarName> names)
{
if (ids.empty() || names.empty()) return;
mTargetAvatar = ids[0];
- childSetValue("target_avatar_name", LLSD(names[0]));
+ childSetValue("target_avatar_name", names[0].getCompleteName());
refreshFromRegion( gAgent.getRegion() );
}
@@ -1527,24 +1528,17 @@ void LLPanelEstateInfo::onClickKickUser()
// this depends on the grandparent view being a floater
// in order to set up floater dependency
LLFloater* parent_floater = gFloaterView->getParentFloater(this);
- LLFloater* child_floater = LLFloaterAvatarPicker::show(boost::bind(&LLPanelEstateInfo::onKickUserCommit, this, _1, _2), FALSE, TRUE);
+ LLFloater* child_floater = LLFloaterAvatarPicker::show(boost::bind(&LLPanelEstateInfo::onKickUserCommit, this, _1), FALSE, TRUE);
parent_floater->addDependentFloater(child_floater);
}
-void LLPanelEstateInfo::onKickUserCommit(const std::vector<std::string>& names, const uuid_vec_t& ids)
+void LLPanelEstateInfo::onKickUserCommit(const uuid_vec_t& ids)
{
- if (names.empty() || ids.empty()) return;
+ if (ids.empty()) return;
- //check to make sure there is one valid user and id
- if( (ids[0].isNull()) ||
- (names[0].length() == 0) )
- {
- return;
- }
-
//Bring up a confirmation dialog
LLSD args;
- args["EVIL_USER"] = names[0];
+ args["EVIL_USER"] = LLSLURL("agent", ids[0], "completename").getSLURLString();
LLSD payload;
payload["agent_id"] = ids[0];
LLNotificationsUtil::add("EstateKickUser", args, payload, boost::bind(&LLPanelEstateInfo::kickUserConfirm, this, _1, _2));
@@ -1710,12 +1704,12 @@ bool LLPanelEstateInfo::accessAddCore2(const LLSD& notification, const LLSD& res
LLEstateAccessChangeInfo* change_info = new LLEstateAccessChangeInfo(notification["payload"]);
// avatar picker yes multi-select, yes close-on-select
- LLFloaterAvatarPicker::show(boost::bind(&LLPanelEstateInfo::accessAddCore3, _1, _2, (void*)change_info), TRUE, TRUE);
+ LLFloaterAvatarPicker::show(boost::bind(&LLPanelEstateInfo::accessAddCore3, _1, (void*)change_info), TRUE, TRUE);
return false;
}
// static
-void LLPanelEstateInfo::accessAddCore3(const std::vector<std::string>& names, const uuid_vec_t& ids, void* data)
+void LLPanelEstateInfo::accessAddCore3(const uuid_vec_t& ids, void* data)
{
LLEstateAccessChangeInfo* change_info = (LLEstateAccessChangeInfo*)data;
if (!change_info) return;
@@ -1971,8 +1965,15 @@ void LLPanelEstateInfo::updateControls(LLViewerRegion* region)
childSetEnabled("remove_allowed_avatar_btn", god || owner || manager);
childSetEnabled("add_allowed_group_btn", god || owner || manager);
childSetEnabled("remove_allowed_group_btn", god || owner || manager);
- childSetEnabled("add_banned_avatar_btn", god || owner || manager);
- childSetEnabled("remove_banned_avatar_btn", god || owner || manager);
+
+ // Can't ban people from mainland, orientation islands, etc. because this
+ // creates much network traffic and server load.
+ // Disable their accounts in CSR tool instead.
+ bool linden_estate = (getEstateID() <= ESTATE_LAST_LINDEN);
+ bool enable_ban = (god || owner || manager) && !linden_estate;
+ childSetEnabled("add_banned_avatar_btn", enable_ban);
+ childSetEnabled("remove_banned_avatar_btn", enable_ban);
+
childSetEnabled("message_estate_btn", god || owner || manager);
childSetEnabled("kick_user_from_estate_btn", god || owner || manager);
diff --git a/indra/newview/llfloaterregioninfo.h b/indra/newview/llfloaterregioninfo.h
index 482ebb3303..13c2e46639 100644
--- a/indra/newview/llfloaterregioninfo.h
+++ b/indra/newview/llfloaterregioninfo.h
@@ -40,6 +40,7 @@
#include "llhost.h"
#include "llpanel.h"
+class LLAvatarName;
class LLDispatcher;
class LLLineEditor;
class LLMessageSystem;
@@ -168,7 +169,7 @@ public:
protected:
virtual BOOL sendUpdate();
void onClickKick();
- void onKickCommit(const std::vector<std::string>& names, const uuid_vec_t& ids);
+ void onKickCommit(const uuid_vec_t& ids);
static void onClickKickAll(void* userdata);
bool onKickAllCommit(const LLSD& notification, const LLSD& response);
static void onClickMessage(void* userdata);
@@ -193,7 +194,7 @@ protected:
virtual BOOL sendUpdate();
void onClickChooseAvatar();
- void callbackAvatarID(const std::vector<std::string>& names, const uuid_vec_t& ids);
+ void callbackAvatarID(const uuid_vec_t& ids, const std::vector<LLAvatarName> names);
static void onClickReturn(void *);
bool callbackReturn(const LLSD& notification, const LLSD& response);
static void onClickTopColliders(void*);
@@ -284,7 +285,7 @@ public:
// Core methods for all above add/remove button clicks
static void accessAddCore(U32 operation_flag, const std::string& dialog_name);
static bool accessAddCore2(const LLSD& notification, const LLSD& response);
- static void accessAddCore3(const std::vector<std::string>& names, const uuid_vec_t& ids, void* data);
+ static void accessAddCore3(const uuid_vec_t& ids, void* data);
static void accessRemoveCore(U32 operation_flag, const std::string& dialog_name, const std::string& list_ctrl_name);
static bool accessRemoveCore2(const LLSD& notification, const LLSD& response);
@@ -296,7 +297,7 @@ public:
// Send the actual EstateOwnerRequest "estateaccessdelta" message
static void sendEstateAccessDelta(U32 flags, const LLUUID& agent_id);
- void onKickUserCommit(const std::vector<std::string>& names, const uuid_vec_t& ids);
+ void onKickUserCommit(const uuid_vec_t& ids);
static void onClickMessageEstate(void* data);
bool onMessageCommit(const LLSD& notification, const LLSD& response);
diff --git a/indra/newview/llfloaterreporter.cpp b/indra/newview/llfloaterreporter.cpp
index f7c8855bf6..195b3e22d9 100644
--- a/indra/newview/llfloaterreporter.cpp
+++ b/indra/newview/llfloaterreporter.cpp
@@ -39,6 +39,8 @@
// linden library includes
#include "llassetstorage.h"
+#include "llavatarnamecache.h"
+#include "llcachename.h"
#include "llfontgl.h"
#include "llimagej2c.h"
#include "llinventory.h"
@@ -182,9 +184,8 @@ BOOL LLFloaterReporter::postBuild()
childSetAction("cancel_btn", onClickCancel, this);
// grab the user's name
- std::string fullname;
- LLAgentUI::buildFullname(fullname);
- childSetText("reporter_field", fullname);
+ std::string reporter = LLSLURL("agent", gAgent.getID(), "inspect").getSLURLString();
+ childSetText("reporter_field", reporter);
center();
@@ -267,22 +268,7 @@ void LLFloaterReporter::getObjectInfo(const LLUUID& object_id)
if (objectp->isAvatar())
{
- // we have the information we need
- std::string object_owner;
-
- LLNameValue* firstname = objectp->getNVPair("FirstName");
- LLNameValue* lastname = objectp->getNVPair("LastName");
- if (firstname && lastname)
- {
- object_owner.append(firstname->getString());
- object_owner.append(1, ' ');
- object_owner.append(lastname->getString());
- }
- else
- {
- object_owner.append("Unknown");
- }
- setFromAvatar(mObjectID, object_owner);
+ setFromAvatarID(mObjectID);
}
else
{
@@ -309,11 +295,11 @@ void LLFloaterReporter::onClickSelectAbuser()
gFloaterView->getParentFloater(this)->addDependentFloater(LLFloaterAvatarPicker::show(boost::bind(&LLFloaterReporter::callbackAvatarID, this, _1, _2), FALSE, TRUE ));
}
-void LLFloaterReporter::callbackAvatarID(const std::vector<std::string>& names, const uuid_vec_t& ids)
+void LLFloaterReporter::callbackAvatarID(const uuid_vec_t& ids, const std::vector<LLAvatarName> names)
{
if (ids.empty() || names.empty()) return;
- childSetText("abuser_name_edit", names[0] );
+ childSetText("abuser_name_edit", names[0].getCompleteName());
mAbuserID = ids[0];
@@ -321,18 +307,27 @@ void LLFloaterReporter::callbackAvatarID(const std::vector<std::string>& names,
}
-void LLFloaterReporter::setFromAvatar(const LLUUID& avatar_id, const std::string& avatar_name)
+void LLFloaterReporter::setFromAvatarID(const LLUUID& avatar_id)
{
mAbuserID = mObjectID = avatar_id;
- mOwnerName = avatar_name;
-
- std::string avatar_link =
- LLSLURL("agent", mObjectID, "inspect").getSLURLString();
+ std::string avatar_link = LLSLURL("agent", mObjectID, "inspect").getSLURLString();
childSetText("owner_name", avatar_link);
- childSetText("object_name", avatar_name);
- childSetText("abuser_name_edit", avatar_name);
+
+ LLAvatarNameCache::get(avatar_id, boost::bind(&LLFloaterReporter::onAvatarNameCache, this, _1, _2));
}
+void LLFloaterReporter::onAvatarNameCache(const LLUUID& avatar_id, const LLAvatarName& av_name)
+{
+ if (mObjectID == avatar_id)
+ {
+ mOwnerName = av_name.getCompleteName();
+ childSetText("object_name", av_name.getCompleteName());
+ childSetToolTip("object_name", av_name.getCompleteName());
+ childSetText("abuser_name_edit", av_name.getCompleteName());
+ }
+}
+
+
// static
void LLFloaterReporter::onClickSend(void *userdata)
{
@@ -472,16 +467,11 @@ void LLFloaterReporter::show(const LLUUID& object_id, const std::string& avatar_
{
LLFloaterReporter* f = LLFloaterReg::showTypedInstance<LLFloaterReporter>("reporter");
- // grab the user's name
- std::string fullname;
- LLAgentUI::buildFullname(fullname);
- f->childSetText("reporter_field", fullname);
-
if (avatar_name.empty())
// Request info for this object
f->getObjectInfo(object_id);
else
- f->setFromAvatar(object_id, avatar_name);
+ f->setFromAvatarID(object_id);
// Need to deselect on close
f->mDeselectOnClose = TRUE;
diff --git a/indra/newview/llfloaterreporter.h b/indra/newview/llfloaterreporter.h
index 23784b7650..1f8526b1de 100644
--- a/indra/newview/llfloaterreporter.h
+++ b/indra/newview/llfloaterreporter.h
@@ -38,6 +38,7 @@
#include "lluuid.h"
#include "v3math.h"
+class LLAvatarName;
class LLMessageSystem;
class LLViewerTexture;
class LLInventoryItem;
@@ -123,8 +124,9 @@ private:
void setPosBox(const LLVector3d &pos);
void enableControls(BOOL own_avatar);
void getObjectInfo(const LLUUID& object_id);
- void callbackAvatarID(const std::vector<std::string>& names, const uuid_vec_t& ids);
- void setFromAvatar(const LLUUID& avatar_id, const std::string& avatar_name = LLStringUtil::null);
+ void callbackAvatarID(const uuid_vec_t& ids, const std::vector<LLAvatarName> names);
+ void setFromAvatarID(const LLUUID& avatar_id);
+ void onAvatarNameCache(const LLUUID& avatar_id, const LLAvatarName& av_name);
private:
EReportType mReportType;
diff --git a/indra/newview/llfloaterscriptlimits.cpp b/indra/newview/llfloaterscriptlimits.cpp
index 0a5499b166..775dda568f 100644
--- a/indra/newview/llfloaterscriptlimits.cpp
+++ b/indra/newview/llfloaterscriptlimits.cpp
@@ -34,6 +34,8 @@
#include "llviewerprecompiledheaders.h"
#include "llfloaterscriptlimits.h"
+// library includes
+#include "llavatarnamecache.h"
#include "llsdutil.h"
#include "llsdutil_math.h"
#include "message.h"
@@ -295,7 +297,7 @@ void fetchScriptLimitsRegionSummaryResponder::result(const LLSD& content_ref)
LLTabContainer* tab = instance->getChild<LLTabContainer>("scriptlimits_panels");
if(tab)
{
- LLPanelScriptLimitsRegionMemory* panel_memory = (LLPanelScriptLimitsRegionMemory*)tab->getChild<LLPanel>("script_limits_region_memory_panel");
+ LLPanelScriptLimitsRegionMemory* panel_memory = (LLPanelScriptLimitsRegionMemory*)tab->getChild<LLPanel>("script_limits_region_memory_panel");
if(panel_memory)
{
panel_memory->childSetValue("loading_text", LLSD(std::string("")));
@@ -306,9 +308,9 @@ void fetchScriptLimitsRegionSummaryResponder::result(const LLSD& content_ref)
btn->setEnabled(true);
}
- panel_memory->setRegionSummary(content);
- }
- }
+ panel_memory->setRegionSummary(content);
+ }
+}
}
}
@@ -598,17 +600,24 @@ void LLPanelScriptLimitsRegionMemory::setErrorStatus(U32 status, const std::stri
// callback from the name cache with an owner name to add to the list
void LLPanelScriptLimitsRegionMemory::onNameCache(
const LLUUID& id,
- const std::string& first_name,
- const std::string& last_name)
+ const std::string& full_name)
{
- std::string name = first_name + " " + last_name;
-
LLScrollListCtrl *list = getChild<LLScrollListCtrl>("scripts_list");
if(!list)
{
return;
}
+ std::string name;
+ if (LLAvatarNameCache::useDisplayNames())
+ {
+ name = LLCacheName::buildUsername(full_name);
+ }
+ else
+ {
+ name = full_name;
+ }
+
std::vector<LLSD>::iterator id_itor;
for (id_itor = mObjectListItems.begin(); id_itor != mObjectListItems.end(); ++id_itor)
{
@@ -674,6 +683,9 @@ void LLPanelScriptLimitsRegionMemory::setRegionDetails(LLSD content)
std::string name_buf = content["parcels"][i]["objects"][j]["name"].asString();
LLUUID task_id = content["parcels"][i]["objects"][j]["id"].asUUID();
LLUUID owner_id = content["parcels"][i]["objects"][j]["owner_id"].asUUID();
+ // This field may not be sent by all server versions, but it's OK if
+ // it uses the LLSD default of false
+ bool is_group_owned = content["parcels"][i]["objects"][j]["is_group_owned"].asBoolean();
F32 location_x = 0.0f;
F32 location_y = 0.0f;
@@ -699,15 +711,27 @@ void LLPanelScriptLimitsRegionMemory::setRegionDetails(LLSD content)
// ...and if not use the slightly more painful method of disovery:
else
{
- BOOL name_is_cached = gCacheName->getFullName(owner_id, owner_buf);
+ BOOL name_is_cached;
+ if (is_group_owned)
+ {
+ name_is_cached = gCacheName->getGroupName(owner_id, owner_buf);
+ }
+ else
+ {
+ name_is_cached = gCacheName->getFullName(owner_id, owner_buf); // username
+ if (LLAvatarNameCache::useDisplayNames())
+ {
+ owner_buf = LLCacheName::buildUsername(owner_buf);
+ }
+ }
if(!name_is_cached)
{
if(std::find(names_requested.begin(), names_requested.end(), owner_id) == names_requested.end())
{
names_requested.push_back(owner_id);
- gCacheName->get(owner_id, TRUE,
- boost::bind(&LLPanelScriptLimitsRegionMemory::onNameCache,
- this, _1, _2, _3));
+ gCacheName->get(owner_id, is_group_owned, // username
+ boost::bind(&LLPanelScriptLimitsRegionMemory::onNameCache,
+ this, _1, _2));
}
}
}
@@ -1309,7 +1333,7 @@ void LLPanelScriptLimitsAttachment::setAttachmentSummary(LLSD content)
// static
void LLPanelScriptLimitsAttachment::onClickRefresh(void* userdata)
-{
+{
LLFloaterScriptLimits* instance = LLFloaterReg::getTypedInstance<LLFloaterScriptLimits>("script_limits");
if(instance)
{
diff --git a/indra/newview/llfloaterscriptlimits.h b/indra/newview/llfloaterscriptlimits.h
index 3c32b9f701..ba6f930bee 100644
--- a/indra/newview/llfloaterscriptlimits.h
+++ b/indra/newview/llfloaterscriptlimits.h
@@ -170,10 +170,8 @@ public:
void returnObjects();
private:
-
void onNameCache(const LLUUID& id,
- const std::string& first_name,
- const std::string& last_name);
+ const std::string& name);
LLSD mContent;
LLUUID mParcelId;
diff --git a/indra/newview/llfloatersellland.cpp b/indra/newview/llfloatersellland.cpp
index 9dddbd998a..186debe40e 100644
--- a/indra/newview/llfloatersellland.cpp
+++ b/indra/newview/llfloatersellland.cpp
@@ -33,6 +33,7 @@
#include "llfloatersellland.h"
+#include "llavatarnamecache.h"
#include "llfloateravatarpicker.h"
#include "llfloaterreg.h"
#include "llfloaterland.h"
@@ -47,6 +48,8 @@
#include "lluictrlfactory.h"
#include "llviewerwindow.h"
+class LLAvatarName;
+
// defined in llfloaterland.cpp
void send_parcel_select_objects(S32 parcel_local_id, U32 return_type,
uuid_list_t* return_ids = NULL);
@@ -95,7 +98,9 @@ private:
bool onConfirmSale(const LLSD& notification, const LLSD& response);
static void doShowObjects(void *userdata);
- void callbackAvatarPick(const std::vector<std::string>& names, const uuid_vec_t& ids);
+ void callbackAvatarPick(const uuid_vec_t& ids, const std::vector<LLAvatarName> names);
+
+ void onBuyerNameCache(const LLAvatarName& av_name);
public:
virtual BOOL postBuild();
@@ -230,12 +235,17 @@ void LLFloaterSellLandUI::updateParcelInfo()
if(mSellToBuyer)
{
- std::string name;
- gCacheName->getFullName(mAuthorizedBuyer, name);
- childSetText("sell_to_agent", name);
+ LLAvatarNameCache::get(mAuthorizedBuyer,
+ boost::bind(&LLFloaterSellLandUI::onBuyerNameCache, this, _2));
}
}
+void LLFloaterSellLandUI::onBuyerNameCache(const LLAvatarName& av_name)
+{
+ childSetText("sell_to_agent", av_name.getCompleteName());
+ childSetToolTip("sell_to_agent", av_name.mUsername);
+}
+
void LLFloaterSellLandUI::setBadge(const char* id, Badge badge)
{
static std::string badgeOK("badge_ok.j2c");
@@ -391,7 +401,7 @@ void LLFloaterSellLandUI::doSelectAgent()
addDependentFloater(LLFloaterAvatarPicker::show(boost::bind(&LLFloaterSellLandUI::callbackAvatarPick, this, _1, _2), FALSE, TRUE));
}
-void LLFloaterSellLandUI::callbackAvatarPick(const std::vector<std::string>& names, const uuid_vec_t& ids)
+void LLFloaterSellLandUI::callbackAvatarPick(const uuid_vec_t& ids, const std::vector<LLAvatarName> names)
{
LLParcel* parcel = mParcelSelection->getParcel();
@@ -402,7 +412,7 @@ void LLFloaterSellLandUI::callbackAvatarPick(const std::vector<std::string>& nam
mAuthorizedBuyer = ids[0];
- childSetText("sell_to_agent", names[0]);
+ childSetText("sell_to_agent", names[0].getCompleteName());
refreshUI();
}
diff --git a/indra/newview/llfloatertopobjects.cpp b/indra/newview/llfloatertopobjects.cpp
index 84ea353dab..c7c3c2f7da 100644
--- a/indra/newview/llfloatertopobjects.cpp
+++ b/indra/newview/llfloatertopobjects.cpp
@@ -34,7 +34,9 @@
#include "llfloatertopobjects.h"
+// library includes
#include "message.h"
+#include "llavatarnamecache.h"
#include "llfontgl.h"
#include "llagent.h"
@@ -196,37 +198,53 @@ void LLFloaterTopObjects::handleReply(LLMessageSystem *msg, void** data)
LLSD element;
element["id"] = task_id;
- element["object_name"] = name_buf;
- element["owner_name"] = owner_buf;
- element["columns"][0]["column"] = "score";
- element["columns"][0]["value"] = llformat("%0.3f", score);
- element["columns"][0]["font"] = "SANSSERIF";
+
+ LLSD columns;
+ columns[0]["column"] = "score";
+ columns[0]["value"] = llformat("%0.3f", score);
+ columns[0]["font"] = "SANSSERIF";
+
+ columns[1]["column"] = "name";
+ columns[1]["value"] = name_buf;
+ columns[1]["font"] = "SANSSERIF";
+
+ // Owner names can have trailing spaces sent from server
+ LLStringUtil::trim(owner_buf);
- element["columns"][1]["column"] = "name";
- element["columns"][1]["value"] = name_buf;
- element["columns"][1]["font"] = "SANSSERIF";
- element["columns"][2]["column"] = "owner";
- element["columns"][2]["value"] = owner_buf;
- element["columns"][2]["font"] = "SANSSERIF";
- element["columns"][3]["column"] = "location";
- element["columns"][3]["value"] = llformat("<%0.1f,%0.1f,%0.1f>", location_x, location_y, location_z);
- element["columns"][3]["font"] = "SANSSERIF";
- element["columns"][4]["column"] = "time";
- element["columns"][4]["value"] = formatted_time((time_t)time_stamp);
- element["columns"][4]["font"] = "SANSSERIF";
+ if (LLAvatarNameCache::useDisplayNames())
+ {
+ // ...convert hard-coded name from server to a username
+ // *TODO: Send owner_id from server and look up display name
+ owner_buf = LLCacheName::buildUsername(owner_buf);
+ }
+ else
+ {
+ // ...just strip out legacy "Resident" name
+ owner_buf = LLCacheName::cleanFullName(owner_buf);
+ }
+ columns[2]["column"] = "owner";
+ columns[2]["value"] = owner_buf;
+ columns[2]["font"] = "SANSSERIF";
+
+ columns[3]["column"] = "location";
+ columns[3]["value"] = llformat("<%0.1f,%0.1f,%0.1f>", location_x, location_y, location_z);
+ columns[3]["font"] = "SANSSERIF";
+ columns[4]["column"] = "time";
+ columns[4]["value"] = formatted_time((time_t)time_stamp);
+ columns[4]["font"] = "SANSSERIF";
if (mCurrentMode == STAT_REPORT_TOP_SCRIPTS
&& have_extended_data)
{
- element["columns"][5]["column"] = "mono_time";
- element["columns"][5]["value"] = llformat("%0.3f", mono_score);
- element["columns"][5]["font"] = "SANSSERIF";
+ columns[5]["column"] = "mono_time";
+ columns[5]["value"] = llformat("%0.3f", mono_score);
+ columns[5]["font"] = "SANSSERIF";
- element["columns"][6]["column"] = "URLs";
- element["columns"][6]["value"] = llformat("%d", public_urls);
- element["columns"][6]["font"] = "SANSSERIF";
+ columns[6]["column"] = "URLs";
+ columns[6]["value"] = llformat("%d", public_urls);
+ columns[6]["font"] = "SANSSERIF";
}
-
+ element["columns"] = columns;
list->addElement(element);
mObjectListData.append(element);
diff --git a/indra/newview/llfolderview.h b/indra/newview/llfolderview.h
index 3944fa53c9..42dc11846d 100644
--- a/indra/newview/llfolderview.h
+++ b/indra/newview/llfolderview.h
@@ -121,7 +121,7 @@ public:
const std::string getFilterSubString(BOOL trim = FALSE);
U32 getFilterObjectTypes() const;
PermissionMask getFilterPermissions() const;
- // JAMESDEBUG use getFilter()->getShowFolderState();
+ // *NOTE: use getFilter()->getShowFolderState();
//LLInventoryFilter::EFolderShow getShowFolderState();
U32 getSortOrder() const;
BOOL isFilterModified();
diff --git a/indra/newview/llfoldervieweventlistener.h b/indra/newview/llfoldervieweventlistener.h
index 82f8a10cf3..d672978f46 100644
--- a/indra/newview/llfoldervieweventlistener.h
+++ b/indra/newview/llfoldervieweventlistener.h
@@ -31,7 +31,7 @@
#ifndef LLFOLDERVIEWEVENTLISTENER_H
#define LLFOLDERVIEWEVENTLISTENER_H
-#include "lldarray.h" // JAMESDEBUG convert to std::vector
+#include "lldarray.h" // *TODO: convert to std::vector
#include "llfoldertype.h"
#include "llfontgl.h" // just for StyleFlags enum
#include "llinventorytype.h"
diff --git a/indra/newview/llfolderviewitem.h b/indra/newview/llfolderviewitem.h
index d6e4b2f556..b0fbcfd138 100644
--- a/indra/newview/llfolderviewitem.h
+++ b/indra/newview/llfolderviewitem.h
@@ -57,7 +57,7 @@ enum EInventorySortGroup
SG_ITEM
};
-// JAMESDEBUG *TODO: do we really need one sort object per folder?
+// *TODO: do we really need one sort object per folder?
// can we just have one of these per LLFolderView ?
class LLInventorySort
{
diff --git a/indra/newview/llfriendcard.cpp b/indra/newview/llfriendcard.cpp
index 7f28e09933..0a1b0b5df0 100644
--- a/indra/newview/llfriendcard.cpp
+++ b/indra/newview/llfriendcard.cpp
@@ -32,13 +32,14 @@
#include "llviewerprecompiledheaders.h"
+#include "llfriendcard.h"
+
+#include "llavatarnamecache.h"
#include "llinventory.h"
#include "llinventoryfunctions.h"
#include "llinventoryobserver.h"
#include "lltrans.h"
-#include "llfriendcard.h"
-
#include "llcallingcard.h" // for LLAvatarTracker
#include "llviewerinventory.h"
#include "llinventorymodel.h"
@@ -536,8 +537,9 @@ void LLFriendCardsManager::addFriendCardToInventory(const LLUUID& avatarID)
{
bool shouldBeAdded = true;
- std::string name;
- gCacheName->getFullName(avatarID, name);
+ LLAvatarName av_name;
+ LLAvatarNameCache::get(avatarID, &av_name);
+ const std::string& name = av_name.mUsername;
lldebugs << "Processing buddy name: " << name
<< ", id: " << avatarID
diff --git a/indra/newview/llglsandbox.cpp b/indra/newview/llglsandbox.cpp
index 2aba0b5c09..eec08301a8 100644
--- a/indra/newview/llglsandbox.cpp
+++ b/indra/newview/llglsandbox.cpp
@@ -54,6 +54,7 @@
#include "lltoolmgr.h"
#include "llselectmgr.h"
#include "llhudmanager.h"
+#include "llhudtext.h"
#include "llrendersphere.h"
#include "llviewerobjectlist.h"
#include "lltoolselectrect.h"
@@ -894,7 +895,7 @@ void LLViewerObjectList::renderObjectBeacons()
color = debug_beacon.mTextColor;
color.mV[3] *= 1.f;
- hud_textp->setString(utf8str_to_wstring(debug_beacon.mString));
+ hud_textp->setString(debug_beacon.mString);
hud_textp->setColor(color);
hud_textp->setPositionAgent(debug_beacon.mPositionAgent);
debug_beacon.mHUDObject = hud_textp;
diff --git a/indra/newview/llhudicon.h b/indra/newview/llhudicon.h
index 770e3bbcd0..91b3a64250 100644
--- a/indra/newview/llhudicon.h
+++ b/indra/newview/llhudicon.h
@@ -50,6 +50,7 @@
// Renders a 2D icon billboard floating at the location specified.
class LLDrawable;
class LLViewerObject;
+class LLViewerTexture;
class LLHUDIcon : public LLHUDObject
{
diff --git a/indra/newview/llhudnametag.cpp b/indra/newview/llhudnametag.cpp
new file mode 100644
index 0000000000..303f048dfc
--- /dev/null
+++ b/indra/newview/llhudnametag.cpp
@@ -0,0 +1,1072 @@
+/**
+ * @file llhudnametag.cpp
+ * @brief Name tags for avatars
+ * @author James Cook
+ *
+ * $LicenseInfo:firstyear=2010&license=viewergpl$
+ *
+ * Copyright (c) 2002-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llhudnametag.h"
+
+#include "llrender.h"
+
+#include "llagent.h"
+#include "llviewercontrol.h"
+#include "llcriticaldamp.h"
+#include "lldrawable.h"
+#include "llfontgl.h"
+#include "llglheaders.h"
+#include "llhudrender.h"
+#include "llui.h"
+#include "llviewercamera.h"
+#include "llviewertexturelist.h"
+#include "llviewerobject.h"
+#include "llvovolume.h"
+#include "llviewerwindow.h"
+#include "llstatusbar.h"
+#include "llmenugl.h"
+#include "pipeline.h"
+#include <boost/tokenizer.hpp>
+
+
+const F32 SPRING_STRENGTH = 0.7f;
+const F32 RESTORATION_SPRING_TIME_CONSTANT = 0.1f;
+const F32 HORIZONTAL_PADDING = 16.f;
+const F32 VERTICAL_PADDING = 12.f;
+const F32 LINE_PADDING = 3.f; // aka "leading"
+const F32 BUFFER_SIZE = 2.f;
+const F32 MIN_EDGE_OVERLAP = 3.f;
+const F32 HUD_TEXT_MAX_WIDTH = 190.f;
+const F32 HUD_TEXT_MAX_WIDTH_NO_BUBBLE = 1000.f;
+const F32 RESIZE_TIME = 0.f;
+const S32 NUM_OVERLAP_ITERATIONS = 10;
+const F32 NEIGHBOR_FORCE_FRACTION = 1.f;
+const F32 POSITION_DAMPING_TC = 0.2f;
+const F32 MAX_STABLE_CAMERA_VELOCITY = 0.1f;
+const F32 LOD_0_SCREEN_COVERAGE = 0.15f;
+const F32 LOD_1_SCREEN_COVERAGE = 0.30f;
+const F32 LOD_2_SCREEN_COVERAGE = 0.40f;
+
+std::set<LLPointer<LLHUDNameTag> > LLHUDNameTag::sTextObjects;
+std::vector<LLPointer<LLHUDNameTag> > LLHUDNameTag::sVisibleTextObjects;
+BOOL LLHUDNameTag::sDisplayText = TRUE ;
+
+bool llhudnametag_further_away::operator()(const LLPointer<LLHUDNameTag>& lhs, const LLPointer<LLHUDNameTag>& rhs) const
+{
+ return lhs->getDistance() > rhs->getDistance();
+}
+
+
+LLHUDNameTag::LLHUDNameTag(const U8 type)
+: LLHUDObject(type),
+ mDoFade(TRUE),
+ mFadeDistance(8.f),
+ mFadeRange(4.f),
+ mLastDistance(0.f),
+ mZCompare(TRUE),
+ mVisibleOffScreen(FALSE),
+ mOffscreen(FALSE),
+ mColor(1.f, 1.f, 1.f, 1.f),
+// mScale(),
+ mWidth(0.f),
+ mHeight(0.f),
+ mFontp(LLFontGL::getFontSansSerifSmall()),
+ mBoldFontp(LLFontGL::getFontSansSerifBold()),
+ mSoftScreenRect(),
+ mPositionAgent(),
+ mPositionOffset(),
+ mMass(10.f),
+ mMaxLines(10),
+ mOffsetY(0),
+ mRadius(0.1f),
+ mTextSegments(),
+ mLabelSegments(),
+ mTextAlignment(ALIGN_TEXT_CENTER),
+ mVertAlignment(ALIGN_VERT_CENTER),
+ mLOD(0),
+ mHidden(FALSE)
+{
+ LLPointer<LLHUDNameTag> ptr(this);
+ sTextObjects.insert(ptr);
+}
+
+LLHUDNameTag::~LLHUDNameTag()
+{
+}
+
+
+BOOL LLHUDNameTag::lineSegmentIntersect(const LLVector3& start, const LLVector3& end, LLVector3& intersection, BOOL debug_render)
+{
+ if (!mVisible || mHidden)
+ {
+ return FALSE;
+ }
+
+ // don't pick text that isn't bound to a viewerobject
+ if (!mSourceObject || mSourceObject->mDrawable.isNull())
+ {
+ return FALSE;
+ }
+
+ F32 alpha_factor = 1.f;
+ LLColor4 text_color = mColor;
+ if (mDoFade)
+ {
+ if (mLastDistance > mFadeDistance)
+ {
+ alpha_factor = llmax(0.f, 1.f - (mLastDistance - mFadeDistance)/mFadeRange);
+ text_color.mV[3] = text_color.mV[3]*alpha_factor;
+ }
+ }
+ if (text_color.mV[3] < 0.01f)
+ {
+ return FALSE;
+ }
+
+ mOffsetY = lltrunc(mHeight * ((mVertAlignment == ALIGN_VERT_CENTER) ? 0.5f : 1.f));
+
+ // scale screen size of borders down
+ //RN: for now, text on hud objects is never occluded
+
+ LLVector3 x_pixel_vec;
+ LLVector3 y_pixel_vec;
+
+ LLViewerCamera::getInstance()->getPixelVectors(mPositionAgent, y_pixel_vec, x_pixel_vec);
+
+ LLVector3 width_vec = mWidth * x_pixel_vec;
+ LLVector3 height_vec = mHeight * y_pixel_vec;
+
+ LLCoordGL screen_pos;
+ LLViewerCamera::getInstance()->projectPosAgentToScreen(mPositionAgent, screen_pos, FALSE);
+
+ LLVector2 screen_offset;
+ screen_offset = updateScreenPos(mPositionOffset);
+
+ LLVector3 render_position = mPositionAgent
+ + (x_pixel_vec * screen_offset.mV[VX])
+ + (y_pixel_vec * screen_offset.mV[VY]);
+
+
+ //if (mUseBubble)
+ {
+ LLVector3 bg_pos = render_position
+ + (F32)mOffsetY * y_pixel_vec
+ - (width_vec / 2.f)
+ - (height_vec);
+ //LLUI::translate(bg_pos.mV[VX], bg_pos.mV[VY], bg_pos.mV[VZ]);
+
+ LLVector3 v[] =
+ {
+ bg_pos,
+ bg_pos + width_vec,
+ bg_pos + width_vec + height_vec,
+ bg_pos + height_vec,
+ };
+
+ if (debug_render)
+ {
+ gGL.begin(LLRender::LINE_STRIP);
+ gGL.vertex3fv(v[0].mV);
+ gGL.vertex3fv(v[1].mV);
+ gGL.vertex3fv(v[2].mV);
+ gGL.vertex3fv(v[3].mV);
+ gGL.vertex3fv(v[0].mV);
+ gGL.vertex3fv(v[2].mV);
+ gGL.end();
+ }
+
+ LLVector3 dir = end-start;
+ F32 t = 0.f;
+
+ if (LLTriangleRayIntersect(v[0], v[1], v[2], start, dir, NULL, NULL, &t, FALSE) ||
+ LLTriangleRayIntersect(v[2], v[3], v[0], start, dir, NULL, NULL, &t, FALSE) )
+ {
+ if (t <= 1.f)
+ {
+ intersection = start + dir*t;
+ return TRUE;
+ }
+ }
+ }
+
+ return FALSE;
+}
+
+void LLHUDNameTag::render()
+{
+ if (sDisplayText)
+ {
+ LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE);
+ renderText(FALSE);
+ }
+}
+
+void LLHUDNameTag::renderForSelect()
+{
+ LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE);
+ renderText(TRUE);
+}
+
+void LLHUDNameTag::renderText(BOOL for_select)
+{
+ if (!mVisible || mHidden)
+ {
+ return;
+ }
+
+ // don't pick text that isn't bound to a viewerobject
+ if (for_select &&
+ (!mSourceObject || mSourceObject->mDrawable.isNull()))
+ {
+ return;
+ }
+
+ if (for_select)
+ {
+ gGL.getTexUnit(0)->disable();
+ }
+ else
+ {
+ gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE);
+ }
+
+ LLGLState gls_blend(GL_BLEND, for_select ? FALSE : TRUE);
+ LLGLState gls_alpha(GL_ALPHA_TEST, for_select ? FALSE : TRUE);
+
+ LLColor4 shadow_color(0.f, 0.f, 0.f, 1.f);
+ F32 alpha_factor = 1.f;
+ LLColor4 text_color = mColor;
+ if (mDoFade)
+ {
+ if (mLastDistance > mFadeDistance)
+ {
+ alpha_factor = llmax(0.f, 1.f - (mLastDistance - mFadeDistance)/mFadeRange);
+ text_color.mV[3] = text_color.mV[3]*alpha_factor;
+ }
+ }
+ if (text_color.mV[3] < 0.01f)
+ {
+ return;
+ }
+ shadow_color.mV[3] = text_color.mV[3];
+
+ mOffsetY = lltrunc(mHeight * ((mVertAlignment == ALIGN_VERT_CENTER) ? 0.5f : 1.f));
+
+ // *TODO: cache this image
+ LLUIImagePtr imagep = LLUI::getUIImage("Rounded_Rect");
+
+ // *TODO: make this a per-text setting
+ LLColor4 bg_color = LLUIColorTable::instance().getColor("NameTagBackground");
+ bg_color.setAlpha(gSavedSettings.getF32("ChatBubbleOpacity") * alpha_factor);
+
+ // maybe a no-op?
+ //const S32 border_height = 16;
+ //const S32 border_width = 16;
+ const S32 border_height = 8;
+ const S32 border_width = 8;
+
+ // *TODO move this into helper function
+ F32 border_scale = 1.f;
+
+ if (border_height * 2 > mHeight)
+ {
+ border_scale = (F32)mHeight / ((F32)border_height * 2.f);
+ }
+ if (border_width * 2 > mWidth)
+ {
+ border_scale = llmin(border_scale, (F32)mWidth / ((F32)border_width * 2.f));
+ }
+
+ // scale screen size of borders down
+ //RN: for now, text on hud objects is never occluded
+
+ LLVector3 x_pixel_vec;
+ LLVector3 y_pixel_vec;
+
+ LLViewerCamera::getInstance()->getPixelVectors(mPositionAgent, y_pixel_vec, x_pixel_vec);
+
+ LLVector2 border_scale_vec((F32)border_width / (F32)imagep->getTextureWidth(), (F32)border_height / (F32)imagep->getTextureHeight());
+ LLVector3 width_vec = mWidth * x_pixel_vec;
+ LLVector3 height_vec = mHeight * y_pixel_vec;
+ LLVector3 scaled_border_width = (F32)llfloor(border_scale * (F32)border_width) * x_pixel_vec;
+ LLVector3 scaled_border_height = (F32)llfloor(border_scale * (F32)border_height) * y_pixel_vec;
+
+ mRadius = (width_vec + height_vec).magVec() * 0.5f;
+
+ LLCoordGL screen_pos;
+ LLViewerCamera::getInstance()->projectPosAgentToScreen(mPositionAgent, screen_pos, FALSE);
+
+ LLVector2 screen_offset;
+// if (!mUseBubble)
+// {
+// screen_offset = mPositionOffset;
+// }
+// else
+// {
+ screen_offset = updateScreenPos(mPositionOffset);
+// }
+
+ LLVector3 render_position = mPositionAgent
+ + (x_pixel_vec * screen_offset.mV[VX])
+ + (y_pixel_vec * screen_offset.mV[VY]);
+
+// if (mUseBubble)
+ {
+ LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE);
+ LLUI::pushMatrix();
+ {
+ LLVector3 bg_pos = render_position
+ + (F32)mOffsetY * y_pixel_vec
+ - (width_vec / 2.f)
+ - (height_vec);
+ LLUI::translate(bg_pos.mV[VX], bg_pos.mV[VY], bg_pos.mV[VZ]);
+
+ if (for_select)
+ {
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+ S32 name = mSourceObject->mGLName;
+ LLColor4U coloru((U8)(name >> 16), (U8)(name >> 8), (U8)name);
+ gGL.color4ubv(coloru.mV);
+ gl_segmented_rect_3d_tex(border_scale_vec, scaled_border_width, scaled_border_height, width_vec, height_vec);
+ LLUI::popMatrix();
+ return;
+ }
+ else
+ {
+ gGL.getTexUnit(0)->bind(imagep->getImage());
+
+ gGL.color4fv(bg_color.mV);
+ gl_segmented_rect_3d_tex(border_scale_vec, scaled_border_width, scaled_border_height, width_vec, height_vec);
+
+ if ( mLabelSegments.size())
+ {
+ LLUI::pushMatrix();
+ {
+ gGL.color4f(text_color.mV[VX], text_color.mV[VY], text_color.mV[VZ], gSavedSettings.getF32("ChatBubbleOpacity") * alpha_factor);
+ LLVector3 label_height = (mFontp->getLineHeight() * mLabelSegments.size() + (VERTICAL_PADDING / 3.f)) * y_pixel_vec;
+ LLVector3 label_offset = height_vec - label_height;
+ LLUI::translate(label_offset.mV[VX], label_offset.mV[VY], label_offset.mV[VZ]);
+ gl_segmented_rect_3d_tex_top(border_scale_vec, scaled_border_width, scaled_border_height, width_vec, label_height);
+ }
+ LLUI::popMatrix();
+ }
+ }
+
+ BOOL outside_width = llabs(mPositionOffset.mV[VX]) > mWidth * 0.5f;
+ BOOL outside_height = llabs(mPositionOffset.mV[VY] + (mVertAlignment == ALIGN_VERT_TOP ? mHeight * 0.5f : 0.f)) > mHeight * (mVertAlignment == ALIGN_VERT_TOP ? mHeight * 0.75f : 0.5f);
+
+ // draw line segments pointing to parent object
+ if (!mOffscreen && (outside_width || outside_height))
+ {
+ LLUI::pushMatrix();
+ {
+ gGL.color4fv(bg_color.mV);
+ LLVector3 target_pos = -1.f * (mPositionOffset.mV[VX] * x_pixel_vec + mPositionOffset.mV[VY] * y_pixel_vec);
+ target_pos += (width_vec / 2.f);
+ target_pos += mVertAlignment == ALIGN_VERT_CENTER ? (height_vec * 0.5f) : LLVector3::zero;
+ target_pos -= 3.f * x_pixel_vec;
+ target_pos -= 6.f * y_pixel_vec;
+ LLUI::translate(target_pos.mV[VX], target_pos.mV[VY], target_pos.mV[VZ]);
+ gl_segmented_rect_3d_tex(border_scale_vec, 3.f * x_pixel_vec, 3.f * y_pixel_vec, 6.f * x_pixel_vec, 6.f * y_pixel_vec);
+ }
+ LLUI::popMatrix();
+
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+ LLGLDepthTest gls_depth(mZCompare ? GL_TRUE : GL_FALSE, GL_FALSE);
+
+ LLVector3 box_center_offset;
+ box_center_offset = (width_vec * 0.5f) + (height_vec * 0.5f);
+ LLUI::translate(box_center_offset.mV[VX], box_center_offset.mV[VY], box_center_offset.mV[VZ]);
+ gGL.color4fv(bg_color.mV);
+ LLUI::setLineWidth(2.0);
+ gGL.begin(LLRender::LINES);
+ {
+ if (outside_width)
+ {
+ LLVector3 vert;
+ // draw line in x then y
+ if (mPositionOffset.mV[VX] < 0.f)
+ {
+ // start at right edge
+ vert = width_vec * 0.5f;
+ gGL.vertex3fv(vert.mV);
+ }
+ else
+ {
+ // start at left edge
+ vert = width_vec * -0.5f;
+ gGL.vertex3fv(vert.mV);
+ }
+ vert = -mPositionOffset.mV[VX] * x_pixel_vec;
+ gGL.vertex3fv(vert.mV);
+ gGL.vertex3fv(vert.mV);
+ vert -= mPositionOffset.mV[VY] * y_pixel_vec;
+ vert -= ((mVertAlignment == ALIGN_VERT_TOP) ? (height_vec * 0.5f) : LLVector3::zero);
+ gGL.vertex3fv(vert.mV);
+ }
+ else
+ {
+ LLVector3 vert;
+ // draw line in y then x
+ if (mPositionOffset.mV[VY] < 0.f)
+ {
+ // start at top edge
+ vert = (height_vec * 0.5f) - (mPositionOffset.mV[VX] * x_pixel_vec);
+ gGL.vertex3fv(vert.mV);
+ }
+ else
+ {
+ // start at bottom edge
+ vert = (height_vec * -0.5f) - (mPositionOffset.mV[VX] * x_pixel_vec);
+ gGL.vertex3fv(vert.mV);
+ }
+ vert = -mPositionOffset.mV[VY] * y_pixel_vec - mPositionOffset.mV[VX] * x_pixel_vec;
+ vert -= ((mVertAlignment == ALIGN_VERT_TOP) ? (height_vec * 0.5f) : LLVector3::zero);
+ gGL.vertex3fv(vert.mV);
+ }
+ }
+ gGL.end();
+ LLUI::setLineWidth(1.0);
+
+ }
+ }
+ LLUI::popMatrix();
+ }
+
+ F32 y_offset = (F32)mOffsetY;
+
+ // Render label
+ {
+ gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT);
+
+ for(std::vector<LLHUDTextSegment>::iterator segment_iter = mLabelSegments.begin();
+ segment_iter != mLabelSegments.end(); ++segment_iter )
+ {
+ // Label segments use default font
+ const LLFontGL* fontp = (segment_iter->mStyle == LLFontGL::BOLD) ? mBoldFontp : mFontp;
+ y_offset -= fontp->getLineHeight();
+
+ F32 x_offset;
+ if (mTextAlignment == ALIGN_TEXT_CENTER)
+ {
+ x_offset = -0.5f*segment_iter->getWidth(fontp);
+ }
+ else // ALIGN_LEFT
+ {
+ x_offset = -0.5f * mWidth + (HORIZONTAL_PADDING / 2.f);
+ }
+
+ LLColor4 label_color(0.f, 0.f, 0.f, 1.f);
+ label_color.mV[VALPHA] = alpha_factor;
+ hud_render_text(segment_iter->getText(), render_position, *fontp, segment_iter->mStyle, LLFontGL::NO_SHADOW, x_offset, y_offset, label_color, FALSE);
+ }
+ }
+
+ // Render text
+ {
+ // -1 mMaxLines means unlimited lines.
+ S32 start_segment;
+ S32 max_lines = getMaxLines();
+
+ if (max_lines < 0)
+ {
+ start_segment = 0;
+ }
+ else
+ {
+ start_segment = llmax((S32)0, (S32)mTextSegments.size() - max_lines);
+ }
+
+ for (std::vector<LLHUDTextSegment>::iterator segment_iter = mTextSegments.begin() + start_segment;
+ segment_iter != mTextSegments.end(); ++segment_iter )
+ {
+ const LLFontGL* fontp = segment_iter->mFont;
+ y_offset -= fontp->getLineHeight();
+ y_offset -= LINE_PADDING;
+
+ U8 style = segment_iter->mStyle;
+ LLFontGL::ShadowType shadow = LLFontGL::DROP_SHADOW;
+
+ F32 x_offset;
+ if (mTextAlignment== ALIGN_TEXT_CENTER)
+ {
+ x_offset = -0.5f*segment_iter->getWidth(fontp);
+ }
+ else // ALIGN_LEFT
+ {
+ x_offset = -0.5f * mWidth + (HORIZONTAL_PADDING / 2.f);
+
+ // *HACK
+ x_offset += 1;
+ }
+
+ text_color = segment_iter->mColor;
+ text_color.mV[VALPHA] *= alpha_factor;
+
+ hud_render_text(segment_iter->getText(), render_position, *fontp, style, shadow, x_offset, y_offset, text_color, FALSE);
+ }
+ }
+ /// Reset the default color to white. The renderer expects this to be the default.
+ gGL.color4f(1.0f, 1.0f, 1.0f, 1.0f);
+ if (for_select)
+ {
+ gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE);
+ }
+}
+
+void LLHUDNameTag::setString(const std::string &text_utf8)
+{
+ mTextSegments.clear();
+ addLine(text_utf8, mColor);
+}
+
+void LLHUDNameTag::clearString()
+{
+ mTextSegments.clear();
+}
+
+
+void LLHUDNameTag::addLine(const std::string &text_utf8,
+ const LLColor4& color,
+ const LLFontGL::StyleFlags style,
+ const LLFontGL* font)
+{
+ LLWString wline = utf8str_to_wstring(text_utf8);
+ if (!wline.empty())
+ {
+ // use default font for segment if custom font not specified
+ if (!font)
+ {
+ font = mFontp;
+ }
+ typedef boost::tokenizer<boost::char_separator<llwchar>, LLWString::const_iterator, LLWString > tokenizer;
+ LLWString seps(utf8str_to_wstring("\r\n"));
+ boost::char_separator<llwchar> sep(seps.c_str());
+
+ tokenizer tokens(wline, sep);
+ tokenizer::iterator iter = tokens.begin();
+
+ while (iter != tokens.end())
+ {
+ U32 line_length = 0;
+ do
+ {
+ F32 max_pixels = HUD_TEXT_MAX_WIDTH;
+ S32 segment_length = font->maxDrawableChars(iter->substr(line_length).c_str(), max_pixels, wline.length(), LLFontGL::WORD_BOUNDARY_IF_POSSIBLE);
+ LLHUDTextSegment segment(iter->substr(line_length, segment_length), style, color, font);
+ mTextSegments.push_back(segment);
+ line_length += segment_length;
+ }
+ while (line_length != iter->size());
+ ++iter;
+ }
+ }
+}
+
+void LLHUDNameTag::setLabel(const std::string &label_utf8)
+{
+ mLabelSegments.clear();
+ addLabel(label_utf8);
+}
+
+void LLHUDNameTag::addLabel(const std::string& label_utf8)
+{
+ LLWString wstr = utf8string_to_wstring(label_utf8);
+ if (!wstr.empty())
+ {
+ LLWString seps(utf8str_to_wstring("\r\n"));
+ LLWString empty;
+
+ typedef boost::tokenizer<boost::char_separator<llwchar>, LLWString::const_iterator, LLWString > tokenizer;
+ boost::char_separator<llwchar> sep(seps.c_str(), empty.c_str(), boost::keep_empty_tokens);
+
+ tokenizer tokens(wstr, sep);
+ tokenizer::iterator iter = tokens.begin();
+
+ while (iter != tokens.end())
+ {
+ U32 line_length = 0;
+ do
+ {
+ S32 segment_length = mFontp->maxDrawableChars(iter->substr(line_length).c_str(),
+ HUD_TEXT_MAX_WIDTH, wstr.length(), LLFontGL::WORD_BOUNDARY_IF_POSSIBLE);
+ LLHUDTextSegment segment(iter->substr(line_length, segment_length), LLFontGL::NORMAL, mColor, mFontp);
+ mLabelSegments.push_back(segment);
+ line_length += segment_length;
+ }
+ while (line_length != iter->size());
+ ++iter;
+ }
+ }
+}
+
+void LLHUDNameTag::setZCompare(const BOOL zcompare)
+{
+ mZCompare = zcompare;
+}
+
+void LLHUDNameTag::setFont(const LLFontGL* font)
+{
+ mFontp = font;
+}
+
+
+void LLHUDNameTag::setColor(const LLColor4 &color)
+{
+ mColor = color;
+ for (std::vector<LLHUDTextSegment>::iterator segment_iter = mTextSegments.begin();
+ segment_iter != mTextSegments.end(); ++segment_iter )
+ {
+ segment_iter->mColor = color;
+ }
+}
+
+void LLHUDNameTag::setAlpha(F32 alpha)
+{
+ mColor.mV[VALPHA] = alpha;
+ for (std::vector<LLHUDTextSegment>::iterator segment_iter = mTextSegments.begin();
+ segment_iter != mTextSegments.end(); ++segment_iter )
+ {
+ segment_iter->mColor.mV[VALPHA] = alpha;
+ }
+}
+
+
+void LLHUDNameTag::setDoFade(const BOOL do_fade)
+{
+ mDoFade = do_fade;
+}
+
+void LLHUDNameTag::updateVisibility()
+{
+ if (mSourceObject)
+ {
+ mSourceObject->updateText();
+ }
+
+ mPositionAgent = gAgent.getPosAgentFromGlobal(mPositionGlobal);
+
+ if (!mSourceObject)
+ {
+ //llwarns << "LLHUDNameTag::updateScreenPos -- mSourceObject is NULL!" << llendl;
+ mVisible = TRUE;
+ sVisibleTextObjects.push_back(LLPointer<LLHUDNameTag> (this));
+ return;
+ }
+
+ // Not visible if parent object is dead
+ if (mSourceObject->isDead())
+ {
+ mVisible = FALSE;
+ return;
+ }
+
+ // push text towards camera by radius of object, but not past camera
+ LLVector3 vec_from_camera = mPositionAgent - LLViewerCamera::getInstance()->getOrigin();
+ LLVector3 dir_from_camera = vec_from_camera;
+ dir_from_camera.normVec();
+
+ if (dir_from_camera * LLViewerCamera::getInstance()->getAtAxis() <= 0.f)
+ { //text is behind camera, don't render
+ mVisible = FALSE;
+ return;
+ }
+
+ if (vec_from_camera * LLViewerCamera::getInstance()->getAtAxis() <= LLViewerCamera::getInstance()->getNear() + 0.1f + mSourceObject->getVObjRadius())
+ {
+ mPositionAgent = LLViewerCamera::getInstance()->getOrigin() + vec_from_camera * ((LLViewerCamera::getInstance()->getNear() + 0.1f) / (vec_from_camera * LLViewerCamera::getInstance()->getAtAxis()));
+ }
+ else
+ {
+ mPositionAgent -= dir_from_camera * mSourceObject->getVObjRadius();
+ }
+
+ mLastDistance = (mPositionAgent - LLViewerCamera::getInstance()->getOrigin()).magVec();
+
+ if (mLOD >= 3 || !mTextSegments.size() || (mDoFade && (mLastDistance > mFadeDistance + mFadeRange)))
+ {
+ mVisible = FALSE;
+ return;
+ }
+
+ LLVector3 x_pixel_vec;
+ LLVector3 y_pixel_vec;
+
+ LLViewerCamera::getInstance()->getPixelVectors(mPositionAgent, y_pixel_vec, x_pixel_vec);
+
+ LLVector3 render_position = mPositionAgent +
+ (x_pixel_vec * mPositionOffset.mV[VX]) +
+ (y_pixel_vec * mPositionOffset.mV[VY]);
+
+ mOffscreen = FALSE;
+ if (!LLViewerCamera::getInstance()->sphereInFrustum(render_position, mRadius))
+ {
+ if (!mVisibleOffScreen)
+ {
+ mVisible = FALSE;
+ return;
+ }
+ else
+ {
+ mOffscreen = TRUE;
+ }
+ }
+
+ mVisible = TRUE;
+ sVisibleTextObjects.push_back(LLPointer<LLHUDNameTag> (this));
+}
+
+LLVector2 LLHUDNameTag::updateScreenPos(LLVector2 &offset)
+{
+ LLCoordGL screen_pos;
+ LLVector2 screen_pos_vec;
+ LLVector3 x_pixel_vec;
+ LLVector3 y_pixel_vec;
+ LLViewerCamera::getInstance()->getPixelVectors(mPositionAgent, y_pixel_vec, x_pixel_vec);
+ LLVector3 world_pos = mPositionAgent + (offset.mV[VX] * x_pixel_vec) + (offset.mV[VY] * y_pixel_vec);
+ if (!LLViewerCamera::getInstance()->projectPosAgentToScreen(world_pos, screen_pos, FALSE) && mVisibleOffScreen)
+ {
+ // bubble off-screen, so find a spot for it along screen edge
+ LLViewerCamera::getInstance()->projectPosAgentToScreenEdge(world_pos, screen_pos);
+ }
+
+ screen_pos_vec.setVec((F32)screen_pos.mX, (F32)screen_pos.mY);
+
+ LLRect world_rect = gViewerWindow->getWorldViewRectScaled();
+ S32 bottom = world_rect.mBottom + STATUS_BAR_HEIGHT;
+
+ LLVector2 screen_center;
+ screen_center.mV[VX] = llclamp((F32)screen_pos_vec.mV[VX], (F32)world_rect.mLeft + mWidth * 0.5f, (F32)world_rect.mRight - mWidth * 0.5f);
+
+ if(mVertAlignment == ALIGN_VERT_TOP)
+ {
+ screen_center.mV[VY] = llclamp((F32)screen_pos_vec.mV[VY],
+ (F32)bottom,
+ (F32)world_rect.mTop - mHeight - (F32)MENU_BAR_HEIGHT);
+ mSoftScreenRect.setLeftTopAndSize(screen_center.mV[VX] - (mWidth + BUFFER_SIZE) * 0.5f,
+ screen_center.mV[VY] + (mHeight + BUFFER_SIZE), mWidth + BUFFER_SIZE, mHeight + BUFFER_SIZE);
+ }
+ else
+ {
+ screen_center.mV[VY] = llclamp((F32)screen_pos_vec.mV[VY],
+ (F32)bottom + mHeight * 0.5f,
+ (F32)world_rect.mTop - mHeight * 0.5f - (F32)MENU_BAR_HEIGHT);
+ mSoftScreenRect.setCenterAndSize(screen_center.mV[VX], screen_center.mV[VY], mWidth + BUFFER_SIZE, mHeight + BUFFER_SIZE);
+ }
+
+ return offset + (screen_center - LLVector2((F32)screen_pos.mX, (F32)screen_pos.mY));
+}
+
+void LLHUDNameTag::updateSize()
+{
+ F32 height = 0.f;
+ F32 width = 0.f;
+
+ S32 max_lines = getMaxLines();
+ //S32 lines = (max_lines < 0) ? (S32)mTextSegments.size() : llmin((S32)mTextSegments.size(), max_lines);
+ //F32 height = (F32)mFontp->getLineHeight() * (lines + mLabelSegments.size());
+
+ S32 start_segment;
+ if (max_lines < 0) start_segment = 0;
+ else start_segment = llmax((S32)0, (S32)mTextSegments.size() - max_lines);
+
+ std::vector<LLHUDTextSegment>::iterator iter = mTextSegments.begin() + start_segment;
+ while (iter != mTextSegments.end())
+ {
+ const LLFontGL* fontp = iter->mFont;
+ height += fontp->getLineHeight();
+ height += LINE_PADDING;
+ width = llmax(width, llmin(iter->getWidth(fontp), HUD_TEXT_MAX_WIDTH));
+ ++iter;
+ }
+
+ // Don't want line spacing under the last line
+ if (height > 0.f)
+ {
+ height -= LINE_PADDING;
+ }
+
+ iter = mLabelSegments.begin();
+ while (iter != mLabelSegments.end())
+ {
+ height += mFontp->getLineHeight();
+ width = llmax(width, llmin(iter->getWidth(mFontp), HUD_TEXT_MAX_WIDTH));
+ ++iter;
+ }
+
+ if (width == 0.f)
+ {
+ return;
+ }
+
+ width += HORIZONTAL_PADDING;
+ height += VERTICAL_PADDING;
+
+ // *TODO: Could do a timer-based resize here
+ //mWidth = llmax(width, lerp(mWidth, (F32)width, u));
+ //mHeight = llmax(height, lerp(mHeight, (F32)height, u));
+ mWidth = width;
+ mHeight = height;
+}
+
+void LLHUDNameTag::updateAll()
+{
+ // iterate over all text objects, calculate their restoration forces,
+ // and add them to the visible set if they are on screen and close enough
+ sVisibleTextObjects.clear();
+
+ TextObjectIterator text_it;
+ for (text_it = sTextObjects.begin(); text_it != sTextObjects.end(); ++text_it)
+ {
+ LLHUDNameTag* textp = (*text_it);
+ textp->mTargetPositionOffset.clearVec();
+ textp->updateSize();
+ textp->updateVisibility();
+ }
+
+ // sort back to front for rendering purposes
+ std::sort(sVisibleTextObjects.begin(), sVisibleTextObjects.end(), llhudnametag_further_away());
+
+ // iterate from front to back, and set LOD based on current screen coverage
+ F32 screen_area = (F32)(gViewerWindow->getWindowWidthScaled() * gViewerWindow->getWindowHeightScaled());
+ F32 current_screen_area = 0.f;
+ std::vector<LLPointer<LLHUDNameTag> >::reverse_iterator r_it;
+ for (r_it = sVisibleTextObjects.rbegin(); r_it != sVisibleTextObjects.rend(); ++r_it)
+ {
+ LLHUDNameTag* textp = (*r_it);
+// if (textp->mUseBubble)
+// {
+ if (current_screen_area / screen_area > LOD_2_SCREEN_COVERAGE)
+ {
+ textp->setLOD(3);
+ }
+ else if (current_screen_area / screen_area > LOD_1_SCREEN_COVERAGE)
+ {
+ textp->setLOD(2);
+ }
+ else if (current_screen_area / screen_area > LOD_0_SCREEN_COVERAGE)
+ {
+ textp->setLOD(1);
+ }
+ else
+ {
+ textp->setLOD(0);
+ }
+ textp->updateSize();
+ // find on-screen position and initialize collision rectangle
+ textp->mTargetPositionOffset = textp->updateScreenPos(LLVector2::zero);
+ current_screen_area += (F32)(textp->mSoftScreenRect.getWidth() * textp->mSoftScreenRect.getHeight());
+// }
+ }
+
+ LLStat* camera_vel_stat = LLViewerCamera::getInstance()->getVelocityStat();
+ F32 camera_vel = camera_vel_stat->getCurrent();
+ if (camera_vel > MAX_STABLE_CAMERA_VELOCITY)
+ {
+ return;
+ }
+
+ VisibleTextObjectIterator src_it;
+
+ for (S32 i = 0; i < NUM_OVERLAP_ITERATIONS; i++)
+ {
+ for (src_it = sVisibleTextObjects.begin(); src_it != sVisibleTextObjects.end(); ++src_it)
+ {
+ LLHUDNameTag* src_textp = (*src_it);
+
+// if (!src_textp->mUseBubble)
+// {
+// continue;
+// }
+ VisibleTextObjectIterator dst_it = src_it;
+ ++dst_it;
+ for (; dst_it != sVisibleTextObjects.end(); ++dst_it)
+ {
+ LLHUDNameTag* dst_textp = (*dst_it);
+
+// if (!dst_textp->mUseBubble)
+// {
+// continue;
+// }
+ if (src_textp->mSoftScreenRect.overlaps(dst_textp->mSoftScreenRect))
+ {
+ LLRectf intersect_rect = src_textp->mSoftScreenRect;
+ intersect_rect.intersectWith(dst_textp->mSoftScreenRect);
+ intersect_rect.stretch(-BUFFER_SIZE * 0.5f);
+
+ F32 src_center_x = src_textp->mSoftScreenRect.getCenterX();
+ F32 src_center_y = src_textp->mSoftScreenRect.getCenterY();
+ F32 dst_center_x = dst_textp->mSoftScreenRect.getCenterX();
+ F32 dst_center_y = dst_textp->mSoftScreenRect.getCenterY();
+ F32 intersect_center_x = intersect_rect.getCenterX();
+ F32 intersect_center_y = intersect_rect.getCenterY();
+ LLVector2 force = lerp(LLVector2(dst_center_x - intersect_center_x, dst_center_y - intersect_center_y),
+ LLVector2(intersect_center_x - src_center_x, intersect_center_y - src_center_y),
+ 0.5f);
+ force.setVec(dst_center_x - src_center_x, dst_center_y - src_center_y);
+ force.normVec();
+
+ LLVector2 src_force = -1.f * force;
+ LLVector2 dst_force = force;
+
+ LLVector2 force_strength;
+ F32 src_mult = dst_textp->mMass / (dst_textp->mMass + src_textp->mMass);
+ F32 dst_mult = 1.f - src_mult;
+ F32 src_aspect_ratio = src_textp->mSoftScreenRect.getWidth() / src_textp->mSoftScreenRect.getHeight();
+ F32 dst_aspect_ratio = dst_textp->mSoftScreenRect.getWidth() / dst_textp->mSoftScreenRect.getHeight();
+ src_force.mV[VY] *= src_aspect_ratio;
+ src_force.normVec();
+ dst_force.mV[VY] *= dst_aspect_ratio;
+ dst_force.normVec();
+
+ src_force.mV[VX] *= llmin(intersect_rect.getWidth() * src_mult, intersect_rect.getHeight() * SPRING_STRENGTH);
+ src_force.mV[VY] *= llmin(intersect_rect.getHeight() * src_mult, intersect_rect.getWidth() * SPRING_STRENGTH);
+ dst_force.mV[VX] *= llmin(intersect_rect.getWidth() * dst_mult, intersect_rect.getHeight() * SPRING_STRENGTH);
+ dst_force.mV[VY] *= llmin(intersect_rect.getHeight() * dst_mult, intersect_rect.getWidth() * SPRING_STRENGTH);
+
+ src_textp->mTargetPositionOffset += src_force;
+ dst_textp->mTargetPositionOffset += dst_force;
+ src_textp->mTargetPositionOffset = src_textp->updateScreenPos(src_textp->mTargetPositionOffset);
+ dst_textp->mTargetPositionOffset = dst_textp->updateScreenPos(dst_textp->mTargetPositionOffset);
+ }
+ }
+ }
+ }
+
+ VisibleTextObjectIterator this_object_it;
+ for (this_object_it = sVisibleTextObjects.begin(); this_object_it != sVisibleTextObjects.end(); ++this_object_it)
+ {
+// if (!(*this_object_it)->mUseBubble)
+// {
+// continue;
+// }
+ (*this_object_it)->mPositionOffset = lerp((*this_object_it)->mPositionOffset, (*this_object_it)->mTargetPositionOffset, LLCriticalDamp::getInterpolant(POSITION_DAMPING_TC));
+ }
+}
+
+void LLHUDNameTag::setLOD(S32 lod)
+{
+ mLOD = lod;
+ //RN: uncomment this to visualize LOD levels
+ //std::string label = llformat("%d", lod);
+ //setLabel(label);
+}
+
+S32 LLHUDNameTag::getMaxLines()
+{
+ switch(mLOD)
+ {
+ case 0:
+ return mMaxLines;
+ case 1:
+ return mMaxLines > 0 ? mMaxLines / 2 : 5;
+ case 2:
+ return mMaxLines > 0 ? mMaxLines / 3 : 2;
+ default:
+ // label only
+ return 0;
+ }
+}
+
+void LLHUDNameTag::markDead()
+{
+ sTextObjects.erase(LLPointer<LLHUDNameTag>(this));
+ LLHUDObject::markDead();
+}
+
+void LLHUDNameTag::shiftAll(const LLVector3& offset)
+{
+ TextObjectIterator text_it;
+ for (text_it = sTextObjects.begin(); text_it != sTextObjects.end(); ++text_it)
+ {
+ LLHUDNameTag *textp = text_it->get();
+ textp->shift(offset);
+ }
+}
+
+void LLHUDNameTag::shift(const LLVector3& offset)
+{
+ mPositionAgent += offset;
+}
+
+//static
+void LLHUDNameTag::addPickable(std::set<LLViewerObject*> &pick_list)
+{
+ //this might put an object on the pick list a second time, overriding it's mGLName, which is ok
+ // *FIX: we should probably cull against pick frustum
+ VisibleTextObjectIterator text_it;
+ for (text_it = sVisibleTextObjects.begin(); text_it != sVisibleTextObjects.end(); ++text_it)
+ {
+// if (!(*text_it)->mUseBubble)
+// {
+// continue;
+// }
+ pick_list.insert((*text_it)->mSourceObject);
+ }
+}
+
+//static
+// called when UI scale changes, to flush font width caches
+void LLHUDNameTag::reshape()
+{
+ TextObjectIterator text_it;
+ for (text_it = sTextObjects.begin(); text_it != sTextObjects.end(); ++text_it)
+ {
+ LLHUDNameTag* textp = (*text_it);
+ std::vector<LLHUDTextSegment>::iterator segment_iter;
+ for (segment_iter = textp->mTextSegments.begin();
+ segment_iter != textp->mTextSegments.end(); ++segment_iter )
+ {
+ segment_iter->clearFontWidthMap();
+ }
+ for(segment_iter = textp->mLabelSegments.begin();
+ segment_iter != textp->mLabelSegments.end(); ++segment_iter )
+ {
+ segment_iter->clearFontWidthMap();
+ }
+ }
+}
+
+//============================================================================
+
+F32 LLHUDNameTag::LLHUDTextSegment::getWidth(const LLFontGL* font)
+{
+ std::map<const LLFontGL*, F32>::iterator iter = mFontWidthMap.find(font);
+ if (iter != mFontWidthMap.end())
+ {
+ return iter->second;
+ }
+ else
+ {
+ F32 width = font->getWidthF32(mText.c_str());
+ mFontWidthMap[font] = width;
+ return width;
+ }
+}
diff --git a/indra/newview/llhudnametag.h b/indra/newview/llhudnametag.h
new file mode 100644
index 0000000000..9a92307009
--- /dev/null
+++ b/indra/newview/llhudnametag.h
@@ -0,0 +1,191 @@
+/**
+ * @file llhudnametag.h
+ * @brief Name tags for avatars
+ * @author James Cook
+ *
+ * $LicenseInfo:firstyear=2010&license=viewergpl$
+ *
+ * Copyright (c) 2002-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LLHUDNAMETAG_H
+#define LLHUDNAMETAG_H
+
+#include "llpointer.h"
+
+#include "llhudobject.h"
+#include "v4color.h"
+//#include "v4coloru.h"
+#include "v2math.h"
+#include "llrect.h"
+//#include "llframetimer.h"
+#include "llfontgl.h"
+#include <set>
+#include <vector>
+
+class LLDrawable;
+class LLHUDNameTag;
+
+struct llhudnametag_further_away
+{
+ bool operator()(const LLPointer<LLHUDNameTag>& lhs, const LLPointer<LLHUDNameTag>& rhs) const;
+};
+
+class LLHUDNameTag : public LLHUDObject
+{
+protected:
+ class LLHUDTextSegment
+ {
+ public:
+ LLHUDTextSegment(const LLWString& text, const LLFontGL::StyleFlags style, const LLColor4& color, const LLFontGL* font)
+ : mColor(color),
+ mStyle(style),
+ mText(text),
+ mFont(font)
+ {}
+ F32 getWidth(const LLFontGL* font);
+ const LLWString& getText() const { return mText; }
+ void clearFontWidthMap() { mFontWidthMap.clear(); }
+
+ LLColor4 mColor;
+ LLFontGL::StyleFlags mStyle;
+ const LLFontGL* mFont;
+ private:
+ LLWString mText;
+ std::map<const LLFontGL*, F32> mFontWidthMap;
+ };
+
+public:
+ typedef enum e_text_alignment
+ {
+ ALIGN_TEXT_LEFT,
+ ALIGN_TEXT_CENTER
+ } ETextAlignment;
+
+ typedef enum e_vert_alignment
+ {
+ ALIGN_VERT_TOP,
+ ALIGN_VERT_CENTER
+ } EVertAlignment;
+
+public:
+ // Set entire string, eliminating existing lines
+ void setString(const std::string& text_utf8);
+
+ void clearString();
+
+ // Add text a line at a time, allowing custom formatting
+ void addLine(const std::string &text_utf8, const LLColor4& color, const LLFontGL::StyleFlags style = LLFontGL::NORMAL, const LLFontGL* font = NULL);
+
+ // For bubble chat, set the part above the chat text
+ void setLabel(const std::string& label_utf8);
+ void addLabel(const std::string& label_utf8);
+
+ // Sets the default font for lines with no font specified
+ void setFont(const LLFontGL* font);
+ void setColor(const LLColor4 &color);
+ void setAlpha(F32 alpha);
+ void setZCompare(const BOOL zcompare);
+ void setDoFade(const BOOL do_fade);
+ void setVisibleOffScreen(BOOL visible) { mVisibleOffScreen = visible; }
+
+ // mMaxLines of -1 means unlimited lines.
+ void setMaxLines(S32 max_lines) { mMaxLines = max_lines; }
+ void setFadeDistance(F32 fade_distance, F32 fade_range) { mFadeDistance = fade_distance; mFadeRange = fade_range; }
+ void updateVisibility();
+ LLVector2 updateScreenPos(LLVector2 &offset_target);
+ void updateSize();
+// void setMass(F32 mass) { mMass = llmax(0.1f, mass); }
+ void setTextAlignment(ETextAlignment alignment) { mTextAlignment = alignment; }
+ void setVertAlignment(EVertAlignment alignment) { mVertAlignment = alignment; }
+ /*virtual*/ void markDead();
+ friend class LLHUDObject;
+ /*virtual*/ F32 getDistance() const { return mLastDistance; }
+ //void setUseBubble(BOOL use_bubble) { mUseBubble = use_bubble; }
+ S32 getLOD() { return mLOD; }
+ BOOL getVisible() { return mVisible; }
+ BOOL getHidden() const { return mHidden; }
+ void setHidden( BOOL hide ) { mHidden = hide; }
+ void shift(const LLVector3& offset);
+
+ BOOL lineSegmentIntersect(const LLVector3& start, const LLVector3& end, LLVector3& intersection, BOOL debug_render = FALSE);
+
+ static void shiftAll(const LLVector3& offset);
+ static void addPickable(std::set<LLViewerObject*> &pick_list);
+ static void reshape();
+ static void setDisplayText(BOOL flag) { sDisplayText = flag ; }
+
+protected:
+ LLHUDNameTag(const U8 type);
+
+ /*virtual*/ void render();
+ /*virtual*/ void renderForSelect();
+ void renderText(BOOL for_select);
+ static void updateAll();
+ void setLOD(S32 lod);
+ S32 getMaxLines();
+
+private:
+ ~LLHUDNameTag();
+ BOOL mDoFade;
+ F32 mFadeRange;
+ F32 mFadeDistance;
+ F32 mLastDistance;
+ BOOL mZCompare;
+ BOOL mVisibleOffScreen;
+ BOOL mOffscreen;
+ LLColor4 mColor;
+// LLVector3 mScale;
+ F32 mWidth;
+ F32 mHeight;
+// LLColor4U mPickColor;
+ const LLFontGL* mFontp;
+ const LLFontGL* mBoldFontp;
+ LLRectf mSoftScreenRect;
+ LLVector3 mPositionAgent;
+ LLVector2 mPositionOffset;
+ LLVector2 mTargetPositionOffset;
+ F32 mMass;
+ S32 mMaxLines;
+ S32 mOffsetY;
+ F32 mRadius;
+ std::vector<LLHUDTextSegment> mTextSegments;
+ std::vector<LLHUDTextSegment> mLabelSegments;
+// LLFrameTimer mResizeTimer;
+ ETextAlignment mTextAlignment;
+ EVertAlignment mVertAlignment;
+ S32 mLOD;
+ BOOL mHidden;
+
+ static BOOL sDisplayText ;
+ static std::set<LLPointer<LLHUDNameTag> > sTextObjects;
+ static std::vector<LLPointer<LLHUDNameTag> > sVisibleTextObjects;
+// static std::vector<LLPointer<LLHUDNameTag> > sVisibleHUDTextObjects;
+ typedef std::set<LLPointer<LLHUDNameTag> >::iterator TextObjectIterator;
+ typedef std::vector<LLPointer<LLHUDNameTag> >::iterator VisibleTextObjectIterator;
+};
+
+#endif
diff --git a/indra/newview/llhudobject.cpp b/indra/newview/llhudobject.cpp
index 2b73ed1dcd..d66ac6c5b2 100644
--- a/indra/newview/llhudobject.cpp
+++ b/indra/newview/llhudobject.cpp
@@ -30,9 +30,6 @@
* $/LicenseInfo$
*/
-// llhudobject.cpp
-// Copyright 2002, Linden Research, Inc.
-
#include "llviewerprecompiledheaders.h"
#include "llhudobject.h"
@@ -44,7 +41,7 @@
#include "llhudeffecttrail.h"
#include "llhudeffectlookat.h"
#include "llhudeffectpointat.h"
-
+#include "llhudnametag.h"
#include "llvoicevisualizer.h"
#include "llagent.h"
@@ -72,7 +69,6 @@ LLHUDObject::LLHUDObject(const U8 type) :
mVisible = TRUE;
mType = type;
mDead = FALSE;
- mOnHUDAttachment = FALSE;
}
LLHUDObject::~LLHUDObject()
@@ -151,6 +147,9 @@ LLHUDObject *LLHUDObject::addHUDObject(const U8 type)
case LL_HUD_ICON:
hud_objectp = new LLHUDIcon(type);
break;
+ case LL_HUD_NAME_TAG:
+ hud_objectp = new LLHUDNameTag(type);
+ break;
default:
llwarns << "Unknown type of hud object:" << (U32) type << llendl;
}
@@ -263,6 +262,7 @@ void LLHUDObject::updateAll()
LLFastTimer ftm(FTM_HUD_UPDATE);
LLHUDText::updateAll();
LLHUDIcon::updateAll();
+ LLHUDNameTag::updateAll();
sortObjects();
}
@@ -311,6 +311,14 @@ void LLHUDObject::renderAllForSelect()
}
// static
+void LLHUDObject::reshapeAll()
+{
+ // only hud objects that use fonts care about window size/scale changes
+ LLHUDText::reshape();
+ LLHUDNameTag::reshape();
+}
+
+// static
void LLHUDObject::sortObjects()
{
sHUDObjects.sort(hud_object_further_away());
diff --git a/indra/newview/llhudobject.h b/indra/newview/llhudobject.h
index d304ac41af..a370b31a20 100644
--- a/indra/newview/llhudobject.h
+++ b/indra/newview/llhudobject.h
@@ -42,7 +42,7 @@
#include "v4color.h"
#include "v3math.h"
#include "v3dmath.h"
-#include "lldrawpool.h"
+#include "lldrawpool.h" // TODO: eliminate, unused below
#include <list>
class LLViewerCamera;
@@ -76,6 +76,9 @@ public:
static void renderAll();
static void renderAllForSelect();
+ // Some objects may need to update when window shape changes
+ static void reshapeAll();
+
static void cleanupHUDObjects();
enum
@@ -96,7 +99,8 @@ public:
LL_HUD_EFFECT_EDIT,
LL_HUD_EFFECT_LOOKAT,
LL_HUD_EFFECT_POINTAT,
- LL_HUD_EFFECT_VOICE_VISUALIZER // Ventrella
+ LL_HUD_EFFECT_VOICE_VISUALIZER, // Ventrella
+ LL_HUD_NAME_TAG
};
protected:
static void sortObjects();
@@ -112,7 +116,6 @@ protected:
BOOL mDead;
BOOL mVisible;
LLVector3d mPositionGlobal;
- BOOL mOnHUDAttachment;
LLPointer<LLViewerObject> mSourceObject;
LLPointer<LLViewerObject> mTargetObject;
diff --git a/indra/newview/llhudtext.cpp b/indra/newview/llhudtext.cpp
index 8d1d27444b..31522f6efb 100644
--- a/indra/newview/llhudtext.cpp
+++ b/indra/newview/llhudtext.cpp
@@ -1,7 +1,6 @@
-
/**
* @file llhudtext.cpp
- * @brief LLHUDText class implementation
+ * @brief Floating text above objects, set via script with llSetText()
*
* $LicenseInfo:firstyear=2002&license=viewergpl$
*
@@ -62,16 +61,16 @@ const F32 HORIZONTAL_PADDING = 15.f;
const F32 VERTICAL_PADDING = 12.f;
const F32 BUFFER_SIZE = 2.f;
const F32 MIN_EDGE_OVERLAP = 3.f;
-F32 HUD_TEXT_MAX_WIDTH = 190.f;
+const F32 HUD_TEXT_MAX_WIDTH = 190.f;
const F32 HUD_TEXT_MAX_WIDTH_NO_BUBBLE = 1000.f;
const F32 RESIZE_TIME = 0.f;
const S32 NUM_OVERLAP_ITERATIONS = 10;
const F32 NEIGHBOR_FORCE_FRACTION = 1.f;
const F32 POSITION_DAMPING_TC = 0.2f;
const F32 MAX_STABLE_CAMERA_VELOCITY = 0.1f;
-const F32 LOD_0_SCREEN_COVERAGE = 0.15f;
-const F32 LOD_1_SCREEN_COVERAGE = 0.30f;
-const F32 LOD_2_SCREEN_COVERAGE = 0.40f;
+//const F32 LOD_0_SCREEN_COVERAGE = 0.15f;
+//const F32 LOD_1_SCREEN_COVERAGE = 0.30f;
+//const F32 LOD_2_SCREEN_COVERAGE = 0.40f;
std::set<LLPointer<LLHUDText> > LLHUDText::sTextObjects;
std::vector<LLPointer<LLHUDText> > LLHUDText::sVisibleTextObjects;
@@ -80,15 +79,14 @@ BOOL LLHUDText::sDisplayText = TRUE ;
bool lltextobject_further_away::operator()(const LLPointer<LLHUDText>& lhs, const LLPointer<LLHUDText>& rhs) const
{
- return (lhs->getDistance() > rhs->getDistance()) ? true : false;
+ return lhs->getDistance() > rhs->getDistance();
}
LLHUDText::LLHUDText(const U8 type) :
LLHUDObject(type),
- mUseBubble(FALSE),
- mUsePixelSize(TRUE),
- mVisibleOffScreen(FALSE),
+ mOnHUDAttachment(FALSE),
+// mVisibleOffScreen(FALSE),
mWidth(0.f),
mHeight(0.f),
mFontp(LLFontGL::getFontSansSerifSmall()),
@@ -98,7 +96,7 @@ LLHUDText::LLHUDText(const U8 type) :
mOffsetY(0),
mTextAlignment(ALIGN_TEXT_CENTER),
mVertAlignment(ALIGN_VERT_CENTER),
- mLOD(0),
+// mLOD(0),
mHidden(FALSE)
{
mColor = LLColor4(1.f, 1.f, 1.f, 1.f);
@@ -106,7 +104,6 @@ LLHUDText::LLHUDText(const U8 type) :
mFadeDistance = 8.f;
mFadeRange = 4.f;
mZCompare = TRUE;
- mDropShadow = TRUE;
mOffscreen = FALSE;
mRadius = 0.1f;
LLPointer<LLHUDText> ptr(this);
@@ -117,112 +114,6 @@ LLHUDText::~LLHUDText()
{
}
-
-BOOL LLHUDText::lineSegmentIntersect(const LLVector3& start, const LLVector3& end, LLVector3& intersection, BOOL debug_render)
-{
- if (!mVisible || mHidden)
- {
- return FALSE;
- }
-
- // don't pick text that isn't bound to a viewerobject or isn't in a bubble
- if (!mSourceObject || mSourceObject->mDrawable.isNull() || !mUseBubble)
- {
- return FALSE;
- }
-
- F32 alpha_factor = 1.f;
- LLColor4 text_color = mColor;
- if (mDoFade)
- {
- if (mLastDistance > mFadeDistance)
- {
- alpha_factor = llmax(0.f, 1.f - (mLastDistance - mFadeDistance)/mFadeRange);
- text_color.mV[3] = text_color.mV[3]*alpha_factor;
- }
- }
- if (text_color.mV[3] < 0.01f)
- {
- return FALSE;
- }
-
- mOffsetY = lltrunc(mHeight * ((mVertAlignment == ALIGN_VERT_CENTER) ? 0.5f : 1.f));
-
- // scale screen size of borders down
- //RN: for now, text on hud objects is never occluded
-
- LLVector3 x_pixel_vec;
- LLVector3 y_pixel_vec;
-
- if (mOnHUDAttachment)
- {
- x_pixel_vec = LLVector3::y_axis / (F32)gViewerWindow->getWindowWidthScaled();
- y_pixel_vec = LLVector3::z_axis / (F32)gViewerWindow->getWindowHeightScaled();
- }
- else
- {
- LLViewerCamera::getInstance()->getPixelVectors(mPositionAgent, y_pixel_vec, x_pixel_vec);
- }
-
- LLVector3 width_vec = mWidth * x_pixel_vec;
- LLVector3 height_vec = mHeight * y_pixel_vec;
-
- LLCoordGL screen_pos;
- LLViewerCamera::getInstance()->projectPosAgentToScreen(mPositionAgent, screen_pos, FALSE);
-
- LLVector2 screen_offset;
- screen_offset = updateScreenPos(mPositionOffset);
-
- LLVector3 render_position = mPositionAgent
- + (x_pixel_vec * screen_offset.mV[VX])
- + (y_pixel_vec * screen_offset.mV[VY]);
-
-
- if (mUseBubble)
- {
- LLVector3 bg_pos = render_position
- + (F32)mOffsetY * y_pixel_vec
- - (width_vec / 2.f)
- - (height_vec);
- //LLUI::translate(bg_pos.mV[VX], bg_pos.mV[VY], bg_pos.mV[VZ]);
-
- LLVector3 v[] =
- {
- bg_pos,
- bg_pos + width_vec,
- bg_pos + width_vec + height_vec,
- bg_pos + height_vec,
- };
-
- if (debug_render)
- {
- gGL.begin(LLRender::LINE_STRIP);
- gGL.vertex3fv(v[0].mV);
- gGL.vertex3fv(v[1].mV);
- gGL.vertex3fv(v[2].mV);
- gGL.vertex3fv(v[3].mV);
- gGL.vertex3fv(v[0].mV);
- gGL.vertex3fv(v[2].mV);
- gGL.end();
- }
-
- LLVector3 dir = end-start;
- F32 t = 0.f;
-
- if (LLTriangleRayIntersect(v[0], v[1], v[2], start, dir, NULL, NULL, &t, FALSE) ||
- LLTriangleRayIntersect(v[2], v[3], v[0], start, dir, NULL, NULL, &t, FALSE) )
- {
- if (t <= 1.f)
- {
- intersection = start + dir*t;
- return TRUE;
- }
- }
- }
-
- return FALSE;
-}
-
void LLHUDText::render()
{
if (!mOnHUDAttachment && sDisplayText)
@@ -248,21 +139,13 @@ void LLHUDText::renderText(BOOL for_select)
return;
}
- // don't pick text that isn't bound to a viewerobject or isn't in a bubble
- if (for_select &&
- (!mSourceObject || mSourceObject->mDrawable.isNull() || !mUseBubble))
+ // don't pick text
+ if (for_select)
{
return;
}
- if (for_select)
- {
- gGL.getTexUnit(0)->disable();
- }
- else
- {
- gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE);
- }
+ gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE);
LLGLState gls_blend(GL_BLEND, for_select ? FALSE : TRUE);
LLGLState gls_alpha(GL_ALPHA_TEST, for_select ? FALSE : TRUE);
@@ -290,7 +173,7 @@ void LLHUDText::renderText(BOOL for_select)
LLUIImagePtr imagep = LLUI::getUIImage("Rounded_Square");
// *TODO: make this a per-text setting
- LLColor4 bg_color = LLUIColorTable::instance().getColor("BackgroundChatColor");
+ LLColor4 bg_color = LLUIColorTable::instance().getColor("ObjectBubbleColor");
bg_color.setAlpha(gSavedSettings.getF32("ChatBubbleOpacity") * alpha_factor);
const S32 border_height = 16;
@@ -336,178 +219,17 @@ void LLHUDText::renderText(BOOL for_select)
LLViewerCamera::getInstance()->projectPosAgentToScreen(mPositionAgent, screen_pos, FALSE);
LLVector2 screen_offset;
- if (!mUseBubble)
- {
- screen_offset = mPositionOffset;
- }
- else
- {
- screen_offset = updateScreenPos(mPositionOffset);
- }
+ screen_offset = mPositionOffset;
LLVector3 render_position = mPositionAgent
+ (x_pixel_vec * screen_offset.mV[VX])
+ (y_pixel_vec * screen_offset.mV[VY]);
- //if (mOnHUD)
- //{
- // render_position.mV[VY] -= fmodf(render_position.mV[VY], 1.f / (F32)gViewerWindow->getWindowWidthScaled());
- // render_position.mV[VZ] -= fmodf(render_position.mV[VZ], 1.f / (F32)gViewerWindow->getWindowHeightScaled());
- //}
- //else
- //{
- // render_position = LLViewerCamera::getInstance()->roundToPixel(render_position);
- //}
-
- if (mUseBubble)
- {
- LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE);
- LLUI::pushMatrix();
- {
- LLVector3 bg_pos = render_position
- + (F32)mOffsetY * y_pixel_vec
- - (width_vec / 2.f)
- - (height_vec);
- LLUI::translate(bg_pos.mV[VX], bg_pos.mV[VY], bg_pos.mV[VZ]);
-
- if (for_select)
- {
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
- S32 name = mSourceObject->mGLName;
- LLColor4U coloru((U8)(name >> 16), (U8)(name >> 8), (U8)name);
- gGL.color4ubv(coloru.mV);
- gl_segmented_rect_3d_tex(border_scale_vec, scaled_border_width, scaled_border_height, width_vec, height_vec);
- LLUI::popMatrix();
- return;
- }
- else
- {
- gGL.getTexUnit(0)->bind(imagep->getImage());
-
- gGL.color4fv(bg_color.mV);
- gl_segmented_rect_3d_tex(border_scale_vec, scaled_border_width, scaled_border_height, width_vec, height_vec);
-
- if ( mLabelSegments.size())
- {
- LLUI::pushMatrix();
- {
- gGL.color4f(text_color.mV[VX], text_color.mV[VY], text_color.mV[VZ], gSavedSettings.getF32("ChatBubbleOpacity") * alpha_factor);
- LLVector3 label_height = (mFontp->getLineHeight() * mLabelSegments.size() + (VERTICAL_PADDING / 3.f)) * y_pixel_vec;
- LLVector3 label_offset = height_vec - label_height;
- LLUI::translate(label_offset.mV[VX], label_offset.mV[VY], label_offset.mV[VZ]);
- gl_segmented_rect_3d_tex_top(border_scale_vec, scaled_border_width, scaled_border_height, width_vec, label_height);
- }
- LLUI::popMatrix();
- }
- }
-
- BOOL outside_width = llabs(mPositionOffset.mV[VX]) > mWidth * 0.5f;
- BOOL outside_height = llabs(mPositionOffset.mV[VY] + (mVertAlignment == ALIGN_VERT_TOP ? mHeight * 0.5f : 0.f)) > mHeight * (mVertAlignment == ALIGN_VERT_TOP ? mHeight * 0.75f : 0.5f);
-
- // draw line segments pointing to parent object
- if (!mOffscreen && (outside_width || outside_height))
- {
- LLUI::pushMatrix();
- {
- gGL.color4fv(bg_color.mV);
- LLVector3 target_pos = -1.f * (mPositionOffset.mV[VX] * x_pixel_vec + mPositionOffset.mV[VY] * y_pixel_vec);
- target_pos += (width_vec / 2.f);
- target_pos += mVertAlignment == ALIGN_VERT_CENTER ? (height_vec * 0.5f) : LLVector3::zero;
- target_pos -= 3.f * x_pixel_vec;
- target_pos -= 6.f * y_pixel_vec;
- LLUI::translate(target_pos.mV[VX], target_pos.mV[VY], target_pos.mV[VZ]);
- gl_segmented_rect_3d_tex(border_scale_vec, 3.f * x_pixel_vec, 3.f * y_pixel_vec, 6.f * x_pixel_vec, 6.f * y_pixel_vec);
- }
- LLUI::popMatrix();
-
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
- LLGLDepthTest gls_depth(mZCompare ? GL_TRUE : GL_FALSE, GL_FALSE);
-
- LLVector3 box_center_offset;
- box_center_offset = (width_vec * 0.5f) + (height_vec * 0.5f);
- LLUI::translate(box_center_offset.mV[VX], box_center_offset.mV[VY], box_center_offset.mV[VZ]);
- gGL.color4fv(bg_color.mV);
- LLUI::setLineWidth(2.0);
- gGL.begin(LLRender::LINES);
- {
- if (outside_width)
- {
- LLVector3 vert;
- // draw line in x then y
- if (mPositionOffset.mV[VX] < 0.f)
- {
- // start at right edge
- vert = width_vec * 0.5f;
- gGL.vertex3fv(vert.mV);
- }
- else
- {
- // start at left edge
- vert = width_vec * -0.5f;
- gGL.vertex3fv(vert.mV);
- }
- vert = -mPositionOffset.mV[VX] * x_pixel_vec;
- gGL.vertex3fv(vert.mV);
- gGL.vertex3fv(vert.mV);
- vert -= mPositionOffset.mV[VY] * y_pixel_vec;
- vert -= ((mVertAlignment == ALIGN_VERT_TOP) ? (height_vec * 0.5f) : LLVector3::zero);
- gGL.vertex3fv(vert.mV);
- }
- else
- {
- LLVector3 vert;
- // draw line in y then x
- if (mPositionOffset.mV[VY] < 0.f)
- {
- // start at top edge
- vert = (height_vec * 0.5f) - (mPositionOffset.mV[VX] * x_pixel_vec);
- gGL.vertex3fv(vert.mV);
- }
- else
- {
- // start at bottom edge
- vert = (height_vec * -0.5f) - (mPositionOffset.mV[VX] * x_pixel_vec);
- gGL.vertex3fv(vert.mV);
- }
- vert = -mPositionOffset.mV[VY] * y_pixel_vec - mPositionOffset.mV[VX] * x_pixel_vec;
- vert -= ((mVertAlignment == ALIGN_VERT_TOP) ? (height_vec * 0.5f) : LLVector3::zero);
- gGL.vertex3fv(vert.mV);
- }
- }
- gGL.end();
- LLUI::setLineWidth(1.0);
-
- }
- }
- LLUI::popMatrix();
- }
-
F32 y_offset = (F32)mOffsetY;
// Render label
{
gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT);
-
- for(std::vector<LLHUDTextSegment>::iterator segment_iter = mLabelSegments.begin();
- segment_iter != mLabelSegments.end(); ++segment_iter )
- {
- const LLFontGL* fontp = (segment_iter->mStyle == LLFontGL::BOLD) ? mBoldFontp : mFontp;
- y_offset -= fontp->getLineHeight();
-
- F32 x_offset;
- if (mTextAlignment == ALIGN_TEXT_CENTER)
- {
- x_offset = -0.5f*segment_iter->getWidth(fontp);
- }
- else // ALIGN_LEFT
- {
- x_offset = -0.5f * mWidth + (HORIZONTAL_PADDING / 2.f);
- }
-
- LLColor4 label_color(0.f, 0.f, 0.f, 1.f);
- label_color.mV[VALPHA] = alpha_factor;
- hud_render_text(segment_iter->getText(), render_position, *fontp, segment_iter->mStyle, LLFontGL::NO_SHADOW, x_offset, y_offset, label_color, mOnHUDAttachment);
- }
}
// Render text
@@ -528,15 +250,11 @@ void LLHUDText::renderText(BOOL for_select)
for (std::vector<LLHUDTextSegment>::iterator segment_iter = mTextSegments.begin() + start_segment;
segment_iter != mTextSegments.end(); ++segment_iter )
{
- const LLFontGL* fontp = (segment_iter->mStyle == LLFontGL::BOLD) ? mBoldFontp : mFontp;
+ const LLFontGL* fontp = segment_iter->mFont;
y_offset -= fontp->getLineHeight();
U8 style = segment_iter->mStyle;
- LLFontGL::ShadowType shadow = LLFontGL::NO_SHADOW;
- if (mDropShadow)
- {
- shadow = LLFontGL::DROP_SHADOW;
- }
+ LLFontGL::ShadowType shadow = LLFontGL::DROP_SHADOW;
F32 x_offset;
if (mTextAlignment== ALIGN_TEXT_CENTER)
@@ -556,21 +274,12 @@ void LLHUDText::renderText(BOOL for_select)
}
/// Reset the default color to white. The renderer expects this to be the default.
gGL.color4f(1.0f, 1.0f, 1.0f, 1.0f);
- if (for_select)
- {
- gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE);
- }
-}
-
-void LLHUDText::setStringUTF8(const std::string &wtext)
-{
- setString(utf8str_to_wstring(wtext));
}
-void LLHUDText::setString(const LLWString &wtext)
+void LLHUDText::setString(const std::string &text_utf8)
{
mTextSegments.clear();
- addLine(wtext, mColor);
+ addLine(text_utf8, mColor);
}
void LLHUDText::clearString()
@@ -579,21 +288,19 @@ void LLHUDText::clearString()
}
-void LLHUDText::addLine(const std::string &str, const LLColor4& color, const LLFontGL::StyleFlags style)
+void LLHUDText::addLine(const std::string &text_utf8,
+ const LLColor4& color,
+ const LLFontGL::StyleFlags style,
+ const LLFontGL* font)
{
- addLine(utf8str_to_wstring(str), color, style);
-}
-
-
-void LLHUDText::addLine(const LLWString &wstr, const LLColor4& color, const LLFontGL::StyleFlags style)
-{
- if (gNoRender)
- {
- return;
- }
- if (!wstr.empty())
+ LLWString wline = utf8str_to_wstring(text_utf8);
+ if (!wline.empty())
{
- LLWString wline(wstr);
+ // use default font for segment if custom font not specified
+ if (!font)
+ {
+ font = mFontp;
+ }
typedef boost::tokenizer<boost::char_separator<llwchar>, LLWString::const_iterator, LLWString > tokenizer;
LLWString seps(utf8str_to_wstring("\r\n"));
boost::char_separator<llwchar> sep(seps.c_str());
@@ -606,8 +313,10 @@ void LLHUDText::addLine(const LLWString &wstr, const LLColor4& color, const LLFo
U32 line_length = 0;
do
{
- S32 segment_length = mFontp->maxDrawableChars(iter->substr(line_length).c_str(), mUseBubble ? HUD_TEXT_MAX_WIDTH : HUD_TEXT_MAX_WIDTH_NO_BUBBLE, wline.length(), LLFontGL::WORD_BOUNDARY_IF_POSSIBLE);
- mTextSegments.push_back(LLHUDTextSegment(iter->substr(line_length, segment_length), style, color));
+ F32 max_pixels = HUD_TEXT_MAX_WIDTH_NO_BUBBLE;
+ S32 segment_length = font->maxDrawableChars(iter->substr(line_length).c_str(), max_pixels, wline.length(), LLFontGL::WORD_BOUNDARY_IF_POSSIBLE);
+ LLHUDTextSegment segment(iter->substr(line_length, segment_length), style, color, font);
+ mTextSegments.push_back(segment);
line_length += segment_length;
}
while (line_length != iter->size());
@@ -616,47 +325,6 @@ void LLHUDText::addLine(const LLWString &wstr, const LLColor4& color, const LLFo
}
}
-void LLHUDText::setLabel(const std::string &label)
-{
- setLabel(utf8str_to_wstring(label));
-}
-
-void LLHUDText::setLabel(const LLWString &wlabel)
-{
- mLabelSegments.clear();
-
- if (!wlabel.empty())
- {
- LLWString wstr(wlabel);
- LLWString seps(utf8str_to_wstring("\r\n"));
- LLWString empty;
-
- typedef boost::tokenizer<boost::char_separator<llwchar>, LLWString::const_iterator, LLWString > tokenizer;
- boost::char_separator<llwchar> sep(seps.c_str(), empty.c_str(), boost::keep_empty_tokens);
-
- tokenizer tokens(wstr, sep);
- tokenizer::iterator iter = tokens.begin();
-
- while (iter != tokens.end())
- {
- U32 line_length = 0;
- do
- {
- S32 segment_length = mFontp->maxDrawableChars(iter->substr(line_length).c_str(), mUseBubble ? HUD_TEXT_MAX_WIDTH : HUD_TEXT_MAX_WIDTH_NO_BUBBLE, wstr.length(), LLFontGL::WORD_BOUNDARY_IF_POSSIBLE);
- mLabelSegments.push_back(LLHUDTextSegment(iter->substr(line_length, segment_length), LLFontGL::NORMAL, mColor));
- line_length += segment_length;
- }
- while (line_length != iter->size());
- ++iter;
- }
- }
-}
-
-void LLHUDText::setDropShadow(const BOOL do_shadow)
-{
- mDropShadow = do_shadow;
-}
-
void LLHUDText::setZCompare(const BOOL zcompare)
{
mZCompare = zcompare;
@@ -678,12 +346,17 @@ void LLHUDText::setColor(const LLColor4 &color)
}
}
-
-void LLHUDText::setUsePixelSize(const BOOL use_pixel_size)
+void LLHUDText::setAlpha(F32 alpha)
{
- mUsePixelSize = use_pixel_size;
+ mColor.mV[VALPHA] = alpha;
+ for (std::vector<LLHUDTextSegment>::iterator segment_iter = mTextSegments.begin();
+ segment_iter != mTextSegments.end(); ++segment_iter )
+ {
+ segment_iter->mColor.mV[VALPHA] = alpha;
+ }
}
+
void LLHUDText::setDoFade(const BOOL do_fade)
{
mDoFade = do_fade;
@@ -751,7 +424,7 @@ void LLHUDText::updateVisibility()
mLastDistance = (mPositionAgent - LLViewerCamera::getInstance()->getOrigin()).magVec();
- if (mLOD >= 3 || !mTextSegments.size() || (mDoFade && (mLastDistance > mFadeDistance + mFadeRange)))
+ if (!mTextSegments.size() || (mDoFade && (mLastDistance > mFadeDistance + mFadeRange)))
{
mVisible = FALSE;
return;
@@ -769,15 +442,15 @@ void LLHUDText::updateVisibility()
mOffscreen = FALSE;
if (!LLViewerCamera::getInstance()->sphereInFrustum(render_position, mRadius))
{
- if (!mVisibleOffScreen)
- {
+// if (!mVisibleOffScreen)
+// {
mVisible = FALSE;
return;
- }
- else
- {
- mOffscreen = TRUE;
- }
+// }
+// else
+// {
+// mOffscreen = TRUE;
+// }
}
mVisible = TRUE;
@@ -792,11 +465,11 @@ LLVector2 LLHUDText::updateScreenPos(LLVector2 &offset)
LLVector3 y_pixel_vec;
LLViewerCamera::getInstance()->getPixelVectors(mPositionAgent, y_pixel_vec, x_pixel_vec);
LLVector3 world_pos = mPositionAgent + (offset.mV[VX] * x_pixel_vec) + (offset.mV[VY] * y_pixel_vec);
- if (!LLViewerCamera::getInstance()->projectPosAgentToScreen(world_pos, screen_pos, FALSE) && mVisibleOffScreen)
- {
- // bubble off-screen, so find a spot for it along screen edge
- LLViewerCamera::getInstance()->projectPosAgentToScreenEdge(world_pos, screen_pos);
- }
+// if (!LLViewerCamera::getInstance()->projectPosAgentToScreen(world_pos, screen_pos, FALSE) && mVisibleOffScreen)
+// {
+// // bubble off-screen, so find a spot for it along screen edge
+// LLViewerCamera::getInstance()->projectPosAgentToScreenEdge(world_pos, screen_pos);
+// }
screen_pos_vec.setVec((F32)screen_pos.mX, (F32)screen_pos.mY);
@@ -827,12 +500,12 @@ LLVector2 LLHUDText::updateScreenPos(LLVector2 &offset)
void LLHUDText::updateSize()
{
+ F32 height = 0.f;
F32 width = 0.f;
S32 max_lines = getMaxLines();
- S32 lines = (max_lines < 0) ? (S32)mTextSegments.size() : llmin((S32)mTextSegments.size(), max_lines);
-
- F32 height = (F32)mFontp->getLineHeight() * (lines + mLabelSegments.size());
+ //S32 lines = (max_lines < 0) ? (S32)mTextSegments.size() : llmin((S32)mTextSegments.size(), max_lines);
+ //F32 height = (F32)mFontp->getLineHeight() * (lines + mLabelSegments.size());
S32 start_segment;
if (max_lines < 0) start_segment = 0;
@@ -841,17 +514,12 @@ void LLHUDText::updateSize()
std::vector<LLHUDTextSegment>::iterator iter = mTextSegments.begin() + start_segment;
while (iter != mTextSegments.end())
{
- width = llmax(width, llmin(iter->getWidth(mFontp), HUD_TEXT_MAX_WIDTH));
+ const LLFontGL* fontp = iter->mFont;
+ height += fontp->getLineHeight();
+ width = llmax(width, llmin(iter->getWidth(fontp), HUD_TEXT_MAX_WIDTH));
++iter;
}
- iter = mLabelSegments.begin();
- while (iter != mLabelSegments.end())
- {
- width = llmax(width, llmin(iter->getWidth(mFontp), HUD_TEXT_MAX_WIDTH));
- ++iter;
- }
-
if (width == 0.f)
{
return;
@@ -860,18 +528,8 @@ void LLHUDText::updateSize()
width += HORIZONTAL_PADDING;
height += VERTICAL_PADDING;
- if (!mResizeTimer.getStarted() && (width != mWidth || height != mHeight))
- {
- mResizeTimer.start();
- }
-
- // *NOTE: removed logic which did a divide by zero.
- F32 u = 1.f;//llclamp(mResizeTimer.getElapsedTimeF32() / RESIZE_TIME, 0.f, 1.f);
- if (u == 1.f)
- {
- mResizeTimer.stop();
- }
-
+ // *TODO: Could do some sort of timer-based resize logic here
+ F32 u = 1.f;
mWidth = llmax(width, lerp(mWidth, (F32)width, u));
mHeight = llmax(height, lerp(mHeight, (F32)height, u));
}
@@ -895,146 +553,31 @@ void LLHUDText::updateAll()
// sort back to front for rendering purposes
std::sort(sVisibleTextObjects.begin(), sVisibleTextObjects.end(), lltextobject_further_away());
std::sort(sVisibleHUDTextObjects.begin(), sVisibleHUDTextObjects.end(), lltextobject_further_away());
-
- // iterate from front to back, and set LOD based on current screen coverage
- F32 screen_area = (F32)(gViewerWindow->getWindowWidthScaled() * gViewerWindow->getWindowHeightScaled());
- F32 current_screen_area = 0.f;
- std::vector<LLPointer<LLHUDText> >::reverse_iterator r_it;
- for (r_it = sVisibleTextObjects.rbegin(); r_it != sVisibleTextObjects.rend(); ++r_it)
- {
- LLHUDText* textp = (*r_it);
- if (textp->mUseBubble)
- {
- if (current_screen_area / screen_area > LOD_2_SCREEN_COVERAGE)
- {
- textp->setLOD(3);
- }
- else if (current_screen_area / screen_area > LOD_1_SCREEN_COVERAGE)
- {
- textp->setLOD(2);
- }
- else if (current_screen_area / screen_area > LOD_0_SCREEN_COVERAGE)
- {
- textp->setLOD(1);
- }
- else
- {
- textp->setLOD(0);
- }
- textp->updateSize();
- // find on-screen position and initialize collision rectangle
- textp->mTargetPositionOffset = textp->updateScreenPos(LLVector2::zero);
- current_screen_area += (F32)(textp->mSoftScreenRect.getWidth() * textp->mSoftScreenRect.getHeight());
- }
- }
-
- LLStat* camera_vel_stat = LLViewerCamera::getInstance()->getVelocityStat();
- F32 camera_vel = camera_vel_stat->getCurrent();
- if (camera_vel > MAX_STABLE_CAMERA_VELOCITY)
- {
- return;
- }
-
- VisibleTextObjectIterator src_it;
-
- for (S32 i = 0; i < NUM_OVERLAP_ITERATIONS; i++)
- {
- for (src_it = sVisibleTextObjects.begin(); src_it != sVisibleTextObjects.end(); ++src_it)
- {
- LLHUDText* src_textp = (*src_it);
-
- if (!src_textp->mUseBubble)
- {
- continue;
- }
- VisibleTextObjectIterator dst_it = src_it;
- ++dst_it;
- for (; dst_it != sVisibleTextObjects.end(); ++dst_it)
- {
- LLHUDText* dst_textp = (*dst_it);
-
- if (!dst_textp->mUseBubble)
- {
- continue;
- }
- if (src_textp->mSoftScreenRect.overlaps(dst_textp->mSoftScreenRect))
- {
- LLRectf intersect_rect = src_textp->mSoftScreenRect;
- intersect_rect.intersectWith(dst_textp->mSoftScreenRect);
- intersect_rect.stretch(-BUFFER_SIZE * 0.5f);
-
- F32 src_center_x = src_textp->mSoftScreenRect.getCenterX();
- F32 src_center_y = src_textp->mSoftScreenRect.getCenterY();
- F32 dst_center_x = dst_textp->mSoftScreenRect.getCenterX();
- F32 dst_center_y = dst_textp->mSoftScreenRect.getCenterY();
- F32 intersect_center_x = intersect_rect.getCenterX();
- F32 intersect_center_y = intersect_rect.getCenterY();
- LLVector2 force = lerp(LLVector2(dst_center_x - intersect_center_x, dst_center_y - intersect_center_y),
- LLVector2(intersect_center_x - src_center_x, intersect_center_y - src_center_y),
- 0.5f);
- force.setVec(dst_center_x - src_center_x, dst_center_y - src_center_y);
- force.normVec();
-
- LLVector2 src_force = -1.f * force;
- LLVector2 dst_force = force;
-
- LLVector2 force_strength;
- F32 src_mult = dst_textp->mMass / (dst_textp->mMass + src_textp->mMass);
- F32 dst_mult = 1.f - src_mult;
- F32 src_aspect_ratio = src_textp->mSoftScreenRect.getWidth() / src_textp->mSoftScreenRect.getHeight();
- F32 dst_aspect_ratio = dst_textp->mSoftScreenRect.getWidth() / dst_textp->mSoftScreenRect.getHeight();
- src_force.mV[VY] *= src_aspect_ratio;
- src_force.normVec();
- dst_force.mV[VY] *= dst_aspect_ratio;
- dst_force.normVec();
-
- src_force.mV[VX] *= llmin(intersect_rect.getWidth() * src_mult, intersect_rect.getHeight() * SPRING_STRENGTH);
- src_force.mV[VY] *= llmin(intersect_rect.getHeight() * src_mult, intersect_rect.getWidth() * SPRING_STRENGTH);
- dst_force.mV[VX] *= llmin(intersect_rect.getWidth() * dst_mult, intersect_rect.getHeight() * SPRING_STRENGTH);
- dst_force.mV[VY] *= llmin(intersect_rect.getHeight() * dst_mult, intersect_rect.getWidth() * SPRING_STRENGTH);
-
- src_textp->mTargetPositionOffset += src_force;
- dst_textp->mTargetPositionOffset += dst_force;
- src_textp->mTargetPositionOffset = src_textp->updateScreenPos(src_textp->mTargetPositionOffset);
- dst_textp->mTargetPositionOffset = dst_textp->updateScreenPos(dst_textp->mTargetPositionOffset);
- }
- }
- }
- }
-
- VisibleTextObjectIterator this_object_it;
- for (this_object_it = sVisibleTextObjects.begin(); this_object_it != sVisibleTextObjects.end(); ++this_object_it)
- {
- if (!(*this_object_it)->mUseBubble)
- {
- continue;
- }
- (*this_object_it)->mPositionOffset = lerp((*this_object_it)->mPositionOffset, (*this_object_it)->mTargetPositionOffset, LLCriticalDamp::getInterpolant(POSITION_DAMPING_TC));
- }
}
-void LLHUDText::setLOD(S32 lod)
-{
- mLOD = lod;
- //RN: uncomment this to visualize LOD levels
- //std::string label = llformat("%d", lod);
- //setLabel(label);
-}
+//void LLHUDText::setLOD(S32 lod)
+//{
+// mLOD = lod;
+// //RN: uncomment this to visualize LOD levels
+// //std::string label = llformat("%d", lod);
+// //setLabel(label);
+//}
S32 LLHUDText::getMaxLines()
{
- switch(mLOD)
- {
- case 0:
- return mMaxLines;
- case 1:
- return mMaxLines > 0 ? mMaxLines / 2 : 5;
- case 2:
- return mMaxLines > 0 ? mMaxLines / 3 : 2;
- default:
- // label only
- return 0;
- }
+ return mMaxLines;
+ //switch(mLOD)
+ //{
+ //case 0:
+ // return mMaxLines;
+ //case 1:
+ // return mMaxLines > 0 ? mMaxLines / 2 : 5;
+ //case 2:
+ // return mMaxLines > 0 ? mMaxLines / 3 : 2;
+ //default:
+ // // label only
+ // return 0;
+ //}
}
void LLHUDText::markDead()
@@ -1085,22 +628,6 @@ void LLHUDText::shift(const LLVector3& offset)
mPositionAgent += offset;
}
-//static
-void LLHUDText::addPickable(std::set<LLViewerObject*> &pick_list)
-{
- //this might put an object on the pick list a second time, overriding it's mGLName, which is ok
- // *FIX: we should probably cull against pick frustum
- VisibleTextObjectIterator text_it;
- for (text_it = sVisibleTextObjects.begin(); text_it != sVisibleTextObjects.end(); ++text_it)
- {
- if (!(*text_it)->mUseBubble)
- {
- continue;
- }
- pick_list.insert((*text_it)->mSourceObject);
- }
-}
-
//static
// called when UI scale changes, to flush font width caches
void LLHUDText::reshape()
@@ -1115,11 +642,6 @@ void LLHUDText::reshape()
{
segment_iter->clearFontWidthMap();
}
- for(segment_iter = textp->mLabelSegments.begin();
- segment_iter != textp->mLabelSegments.end(); ++segment_iter )
- {
- segment_iter->clearFontWidthMap();
- }
}
}
diff --git a/indra/newview/llhudtext.h b/indra/newview/llhudtext.h
index dc14a8c764..27b8f07cca 100644
--- a/indra/newview/llhudtext.h
+++ b/indra/newview/llhudtext.h
@@ -34,18 +34,15 @@
#define LL_LLHUDTEXT_H
#include "llpointer.h"
-#include "lldarrayptr.h"
#include "llhudobject.h"
#include "v4color.h"
#include "v4coloru.h"
#include "v2math.h"
#include "llrect.h"
-#include "llframetimer.h"
#include "llfontgl.h"
#include <set>
#include <vector>
-#include "lldarray.h"
// Renders a 2D text billboard floating at the location specified.
class LLDrawable;
@@ -62,14 +59,19 @@ protected:
class LLHUDTextSegment
{
public:
- LLHUDTextSegment(const LLWString& text, const LLFontGL::StyleFlags style, const LLColor4& color)
- : mColor(color), mStyle(style), mText(text) {}
+ LLHUDTextSegment(const LLWString& text, const LLFontGL::StyleFlags style, const LLColor4& color, const LLFontGL* font)
+ : mColor(color),
+ mStyle(style),
+ mText(text),
+ mFont(font)
+ {}
F32 getWidth(const LLFontGL* font);
- const LLWString& getText() const { return mText; };
+ const LLWString& getText() const { return mText; }
void clearFontWidthMap() { mFontWidthMap.clear(); }
LLColor4 mColor;
LLFontGL::StyleFlags mStyle;
+ const LLFontGL* mFont;
private:
LLWString mText;
std::map<const LLFontGL*, F32> mFontWidthMap;
@@ -89,20 +91,21 @@ public:
} EVertAlignment;
public:
- void setStringUTF8(const std::string &utf8string);
- void setString(const LLWString &wstring);
+ // Set entire string, eliminating existing lines
+ void setString(const std::string& text_utf8);
+
void clearString();
- void addLine(const std::string &text, const LLColor4& color, const LLFontGL::StyleFlags style = LLFontGL::NORMAL);
- void addLine(const LLWString &wtext, const LLColor4& color, const LLFontGL::StyleFlags style = LLFontGL::NORMAL);
- void setLabel(const std::string &label);
- void setLabel(const LLWString &label);
- void setDropShadow(const BOOL do_shadow);
+
+ // Add text a line at a time, allowing custom formatting
+ void addLine(const std::string &text_utf8, const LLColor4& color, const LLFontGL::StyleFlags style = LLFontGL::NORMAL, const LLFontGL* font = NULL);
+
+ // Sets the default font for lines with no font specified
void setFont(const LLFontGL* font);
void setColor(const LLColor4 &color);
- void setUsePixelSize(const BOOL use_pixel_size);
+ void setAlpha(F32 alpha);
void setZCompare(const BOOL zcompare);
void setDoFade(const BOOL do_fade);
- void setVisibleOffScreen(BOOL visible) { mVisibleOffScreen = visible; }
+// void setVisibleOffScreen(BOOL visible) { mVisibleOffScreen = visible; }
// mMaxLines of -1 means unlimited lines.
void setMaxLines(S32 max_lines) { mMaxLines = max_lines; }
@@ -116,21 +119,17 @@ public:
/*virtual*/ void markDead();
friend class LLHUDObject;
/*virtual*/ F32 getDistance() const { return mLastDistance; }
- void setUseBubble(BOOL use_bubble) { mUseBubble = use_bubble; }
- S32 getLOD() { return mLOD; }
BOOL getVisible() { return mVisible; }
BOOL getHidden() const { return mHidden; }
void setHidden( BOOL hide ) { mHidden = hide; }
void setOnHUDAttachment(BOOL on_hud) { mOnHUDAttachment = on_hud; }
void shift(const LLVector3& offset);
- BOOL lineSegmentIntersect(const LLVector3& start, const LLVector3& end, LLVector3& intersection, BOOL debug_render = FALSE);
-
static void shiftAll(const LLVector3& offset);
static void renderAllHUD();
- static void addPickable(std::set<LLViewerObject*> &pick_list);
static void reshape();
static void setDisplayText(BOOL flag) { sDisplayText = flag ; }
+
protected:
LLHUDText(const U8 type);
@@ -138,21 +137,17 @@ protected:
/*virtual*/ void renderForSelect();
void renderText(BOOL for_select);
static void updateAll();
- void setLOD(S32 lod);
S32 getMaxLines();
private:
~LLHUDText();
- BOOL mOnHUD;
- BOOL mUseBubble;
- BOOL mDropShadow;
+ BOOL mOnHUDAttachment;
BOOL mDoFade;
F32 mFadeRange;
F32 mFadeDistance;
F32 mLastDistance;
- BOOL mUsePixelSize;
BOOL mZCompare;
- BOOL mVisibleOffScreen;
+// BOOL mVisibleOffScreen;
BOOL mOffscreen;
LLColor4 mColor;
LLVector3 mScale;
@@ -170,11 +165,8 @@ private:
S32 mOffsetY;
F32 mRadius;
std::vector<LLHUDTextSegment> mTextSegments;
- std::vector<LLHUDTextSegment> mLabelSegments;
- LLFrameTimer mResizeTimer;
ETextAlignment mTextAlignment;
EVertAlignment mVertAlignment;
- S32 mLOD;
BOOL mHidden;
static BOOL sDisplayText ;
diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp
index 967f38bfd2..38bb96fd6f 100644
--- a/indra/newview/llimfloater.cpp
+++ b/indra/newview/llimfloater.cpp
@@ -38,6 +38,7 @@
#include "llagent.h"
#include "llappviewer.h"
+#include "llavatarnamecache.h"
#include "llbutton.h"
#include "llbottomtray.h"
#include "llchannelmanager.h"
@@ -281,12 +282,6 @@ BOOL LLIMFloater::postBuild()
mInputEditor->setReplaceNewlinesWithSpaces( FALSE );
mInputEditor->setPassDelete( TRUE );
- std::string session_name(LLIMModel::instance().getName(mSessionID));
-
- mInputEditor->setLabel(LLTrans::getString("IM_to_label") + " " + session_name);
-
- setTitle(session_name);
-
childSetCommitCallback("chat_editor", onSendMsg, this);
mChatHistory = getChild<LLChatHistory>("chat_history");
@@ -304,6 +299,19 @@ BOOL LLIMFloater::postBuild()
mInputEditor->setLabel(LLTrans::getString("IM_unavailable_text_label"));
}
+ if ( im_session && im_session->isP2PSessionType())
+ {
+ // look up display name for window title
+ LLAvatarNameCache::get(im_session->mOtherParticipantID,
+ boost::bind(&LLIMFloater::onAvatarNameCache,
+ this, _1, _2));
+ }
+ else
+ {
+ std::string session_name(LLIMModel::instance().getName(mSessionID));
+ updateSessionName(session_name, session_name);
+ }
+
//*TODO if session is not initialized yet, add some sort of a warning message like "starting session...blablabla"
//see LLFloaterIMPanel for how it is done (IB)
@@ -317,6 +325,22 @@ BOOL LLIMFloater::postBuild()
}
}
+void LLIMFloater::updateSessionName(const std::string& ui_title,
+ const std::string& ui_label)
+{
+ mInputEditor->setLabel(LLTrans::getString("IM_to_label") + " " + ui_label);
+ setTitle(ui_title);
+}
+
+void LLIMFloater::onAvatarNameCache(const LLUUID& agent_id,
+ const LLAvatarName& av_name)
+{
+ // Use display name only for labels, as the extended name will be in the
+ // floater title
+ std::string ui_title = av_name.getCompleteName();
+ updateSessionName(ui_title, av_name.mDisplayName);
+}
+
// virtual
void LLIMFloater::draw()
{
diff --git a/indra/newview/llimfloater.h b/indra/newview/llimfloater.h
index f1e68a2b3d..89f57aa8bb 100644
--- a/indra/newview/llimfloater.h
+++ b/indra/newview/llimfloater.h
@@ -38,6 +38,7 @@
#include "lltooldraganddrop.h"
#include "lltransientdockablefloater.h"
+class LLAvatarName;
class LLLineEditor;
class LLPanelChatControlPanel;
class LLChatHistory;
@@ -130,6 +131,12 @@ private:
/* virtual */ void onFocusLost();
/* virtual */ void onFocusReceived();
+ // Update the window title, input field help text, etc.
+ void updateSessionName(const std::string& ui_title, const std::string& ui_label);
+
+ // For display name lookups for IM window titles
+ void onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name);
+
BOOL dropCallingCard(LLInventoryItem* item, BOOL drop);
BOOL dropCategory(LLInventoryCategory* category, BOOL drop);
diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp
index 21313f9df7..7c951e3556 100644
--- a/indra/newview/llimview.cpp
+++ b/indra/newview/llimview.cpp
@@ -34,6 +34,7 @@
#include "llimview.h"
+#include "llavatarnamecache.h" // IDEVO
#include "llfloaterreg.h"
#include "llfontgl.h"
#include "llgl.h"
@@ -70,11 +71,6 @@
#include "llviewerparcelmgr.h"
-const static std::string IM_TIME("time");
-const static std::string IM_TEXT("message");
-const static std::string IM_FROM("from");
-const static std::string IM_FROM_ID("from_id");
-
const static std::string NO_SESSION("(IM Session Doesn't Exist)");
const static std::string ADHOC_NAME_SUFFIX(" Conference");
@@ -108,6 +104,20 @@ BOOL LLSessionTimeoutTimer::tick()
return TRUE;
}
+static void on_avatar_name_cache_toast(const LLUUID& agent_id,
+ const LLAvatarName& av_name,
+ LLSD msg)
+{
+ LLSD args;
+ args["MESSAGE"] = msg["message"];
+ args["TIME"] = msg["time"];
+ // *TODO: Can this ever be an object name or group name?
+ args["FROM"] = av_name.getCompleteName();
+ args["FROM_ID"] = msg["from_id"];
+ args["SESSION_ID"] = msg["session_id"];
+ LLNotificationsUtil::add("IMToast", args, LLSD(), boost::bind(&LLIMFloater::show, msg["session_id"].asUUID()));
+}
+
void toast_callback(const LLSD& msg){
// do not show toast in busy mode or it goes from agent
if (gAgent.getBusy() || gAgent.getID() == msg["from_id"])
@@ -135,14 +145,9 @@ void toast_callback(const LLSD& msg){
return;
}
- LLSD args;
- args["MESSAGE"] = msg["message"];
- args["TIME"] = msg["time"];
- args["FROM"] = msg["from"];
- args["FROM_ID"] = msg["from_id"];
- args["SESSION_ID"] = msg["session_id"];
-
- LLNotificationsUtil::add("IMToast", args, LLSD(), boost::bind(&LLIMFloater::show, msg["session_id"].asUUID()));
+ LLAvatarNameCache::get(msg["from_id"].asUUID(),
+ boost::bind(&on_avatar_name_cache_toast,
+ _1, _2, msg));
}
void LLIMModel::setActiveSessionID(const LLUUID& session_id)
@@ -269,7 +274,7 @@ void LLIMModel::LLIMSession::onVoiceChannelStateChanged(const LLVoiceChannel::ES
// no text notifications
break;
case P2P_SESSION:
- gCacheName->getFullName(mOtherParticipantID, other_avatar_name);
+ gCacheName->getFullName(mOtherParticipantID, other_avatar_name); // voice
if(direction == LLVoiceChannel::INCOMING_CALL)
{
@@ -404,13 +409,17 @@ void LLIMModel::LLIMSession::addMessagesFromHistory(const std::list<LLSD>& histo
const LLSD& msg = *it;
std::string from = msg[IM_FROM];
- LLUUID from_id = LLUUID::null;
- if (msg[IM_FROM_ID].isUndefined())
+ LLUUID from_id;
+ if (msg[IM_FROM_ID].isDefined())
{
+ from_id = msg[IM_FROM_ID].asUUID();
+ }
+ else
+ {
+ // Legacy chat logs only wrote the legacy name, not the agent_id
gCacheName->getUUID(from, from_id);
}
-
std::string timestamp = msg[IM_TIME];
std::string text = msg[IM_TEXT];
@@ -631,7 +640,7 @@ bool LLIMModel::clearSession(const LLUUID& session_id)
void LLIMModel::getMessagesSilently(const LLUUID& session_id, std::list<LLSD>& messages, int start_index)
{
LLIMSession* session = findIMSession(session_id);
- if (!session)
+ if (!session)
{
llwarns << "session " << session_id << "does not exist " << llendl;
return;
@@ -639,7 +648,7 @@ void LLIMModel::getMessagesSilently(const LLUUID& session_id, std::list<LLSD>& m
int i = session->mMsgs.size() - start_index;
- for (std::list<LLSD>::iterator iter = session->mMsgs.begin();
+ for (std::list<LLSD>::iterator iter = session->mMsgs.begin();
iter != session->mMsgs.end() && i > 0;
iter++)
{
@@ -1750,11 +1759,23 @@ void LLOutgoingCallDialog::show(const LLSD& key)
callee_name = LLTextUtil::formatPhoneNumber(callee_name);
}
- setTitle(callee_name);
-
LLSD callee_id = mPayload["other_user_id"];
- childSetTextArg("calling", "[CALLEE_NAME]", callee_name);
- childSetTextArg("connecting", "[CALLEE_NAME]", callee_name);
+ // Beautification: Since you know who you called, just show display name
+ std::string title = callee_name;
+ std::string final_callee_name = callee_name;
+ if (mPayload["session_type"].asInteger() == LLIMModel::LLIMSession::P2P_SESSION)
+ {
+ LLAvatarName av_name;
+ if (LLAvatarNameCache::get(callee_id, &av_name))
+ {
+ final_callee_name = av_name.mDisplayName;
+ title = av_name.getCompleteName();
+ }
+ }
+ childSetTextArg("calling", "[CALLEE_NAME]", final_callee_name);
+ childSetTextArg("connecting", "[CALLEE_NAME]", final_callee_name);
+
+ setTitle(title);
// for outgoing group calls callee_id == group id == session id
setIcon(callee_id, callee_id);
@@ -1909,16 +1930,21 @@ BOOL LLIncomingCallDialog::postBuild()
if (caller_name == "anonymous")
{
caller_name = getString("anonymous");
+ setCallerName(caller_name, caller_name, call_type);
}
else if (!is_avatar)
{
caller_name = LLTextUtil::formatPhoneNumber(caller_name);
+ setCallerName(caller_name, caller_name, call_type);
+ }
+ else
+ {
+ // Get the full name information
+ LLAvatarNameCache::get(caller_id,
+ boost::bind(&LLIncomingCallDialog::onAvatarNameCache,
+ this, _1, _2, call_type));
}
- setTitle(caller_name + " " + call_type);
-
- LLUICtrl* caller_name_widget = getChild<LLUICtrl>("caller name");
- caller_name_widget->setValue(caller_name + " " + call_type);
setIcon(session_id, caller_id);
childSetAction("Accept", onAccept, this);
@@ -1946,6 +1972,24 @@ BOOL LLIncomingCallDialog::postBuild()
return TRUE;
}
+void LLIncomingCallDialog::setCallerName(const std::string& ui_title,
+ const std::string& ui_label,
+ const std::string& call_type)
+{
+ setTitle(ui_title);
+
+ // call_type may be a string like " is calling."
+ LLUICtrl* caller_name_widget = getChild<LLUICtrl>("caller name");
+ caller_name_widget->setValue(ui_label + " " + call_type);
+}
+
+void LLIncomingCallDialog::onAvatarNameCache(const LLUUID& agent_id,
+ const LLAvatarName& av_name,
+ const std::string& call_type)
+{
+ std::string title = av_name.getCompleteName();
+ setCallerName(title, av_name.mDisplayName, call_type);
+}
void LLIncomingCallDialog::onOpen(const LLSD& key)
{
@@ -2053,8 +2097,11 @@ void LLIncomingCallDialog::processCallResponse(S32 response)
}
else
{
- if (gCacheName->getFullName(caller_id, correct_session_name))
+ // *NOTE: really should be using callbacks here
+ LLAvatarName av_name;
+ if (LLAvatarNameCache::get(caller_id, &av_name))
{
+ correct_session_name = av_name.mDisplayName + " (" + av_name.mUsername + ")";
correct_session_name.append(ADHOC_NAME_SUFFIX);
}
}
@@ -2575,7 +2622,8 @@ void LLIMMgr::inviteToSession(
{
if (caller_name.empty())
{
- gCacheName->get(caller_id, FALSE, boost::bind(&LLIMMgr::onInviteNameLookup, payload, _1, _2, _3, _4));
+ gCacheName->get(caller_id, false, // voice
+ boost::bind(&LLIMMgr::onInviteNameLookup, payload, _1, _2, _3));
}
else
{
@@ -2585,9 +2633,9 @@ void LLIMMgr::inviteToSession(
}
}
-void LLIMMgr::onInviteNameLookup(LLSD payload, const LLUUID& id, const std::string& first, const std::string& last, BOOL is_group)
+void LLIMMgr::onInviteNameLookup(LLSD payload, const LLUUID& id, const std::string& name, bool is_group)
{
- payload["caller_name"] = first + " " + last;
+ payload["caller_name"] = name;
payload["session_name"] = payload["caller_name"].asString();
std::string notify_box_type = payload["notify_box_type"].asString();
@@ -2808,13 +2856,14 @@ void LLIMMgr::noteOfflineUsers(
for(S32 i = 0; i < count; ++i)
{
info = at.getBuddyInfo(ids.get(i));
- std::string first, last;
- if(info && !info->isOnline()
- && gCacheName->getName(ids.get(i), first, last))
+ LLAvatarName av_name;
+ if (info
+ && !info->isOnline()
+ && LLAvatarNameCache::get(ids.get(i), &av_name))
{
LLUIString offline = LLTrans::getString("offline_message");
- offline.setArg("[FIRST]", first);
- offline.setArg("[LAST]", last);
+ // Use display name only because this user is your friend
+ offline.setArg("[NAME]", av_name.mDisplayName);
im_model.proccessOnlineOfflineNotification(session_id, offline);
}
}
diff --git a/indra/newview/llimview.h b/indra/newview/llimview.h
index ffa8a16797..c132ac328f 100644
--- a/indra/newview/llimview.h
+++ b/indra/newview/llimview.h
@@ -41,7 +41,7 @@
#include "llvoicechannel.h"
-
+class LLAvatarName;
class LLFriendObserver;
class LLCallDialogManager;
class LLIMSpeakerMgr;
@@ -458,7 +458,7 @@ private:
void processIMTypingCore(const LLIMInfo* im_info, BOOL typing);
- static void onInviteNameLookup(LLSD payload, const LLUUID& id, const std::string& first, const std::string& last, BOOL is_group);
+ static void onInviteNameLookup(LLSD payload, const LLUUID& id, const std::string& name, bool is_group);
void notifyObserverSessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id);
void notifyObserverSessionRemoved(const LLUUID& session_id);
@@ -540,6 +540,13 @@ public:
static void onStartIM(void* user_data);
private:
+ void setCallerName(const std::string& ui_title,
+ const std::string& ui_label,
+ const std::string& call_type);
+ void onAvatarNameCache(const LLUUID& agent_id,
+ const LLAvatarName& av_name,
+ const std::string& call_type);
+
/*virtual*/ void onLifetimeExpired();
void processCallResponse(S32 response);
};
diff --git a/indra/newview/llinspectavatar.cpp b/indra/newview/llinspectavatar.cpp
index d9fdc876db..1cd1dcc7f0 100644
--- a/indra/newview/llinspectavatar.cpp
+++ b/indra/newview/llinspectavatar.cpp
@@ -37,6 +37,7 @@
#include "llagent.h"
#include "llagentdata.h"
#include "llavataractions.h"
+#include "llavatarnamecache.h"
#include "llavatarpropertiesprocessor.h"
#include "llcallingcard.h"
#include "lldateutil.h"
@@ -143,17 +144,13 @@ private:
// Is used to determine if "Add friend" option should be enabled in gear menu
bool isNotFriend();
- // Callback for gCacheName to look up avatar name
- void nameUpdatedCallback(
- const LLUUID& id,
- const std::string& first,
- const std::string& last,
- BOOL is_group);
+ void onAvatarNameCache(const LLUUID& agent_id,
+ const LLAvatarName& av_name);
private:
LLUUID mAvatarID;
// Need avatar name information to spawn friend add request
- std::string mAvatarName;
+ LLAvatarName mAvatarName;
// an in-flight request for avatar properties from LLAvatarPropertiesProcessor
// is represented by this object
LLFetchAvatarData* mPropertiesRequest;
@@ -336,6 +333,7 @@ void LLInspectAvatar::requestUpdate()
// Clear out old data so it doesn't flash between old and new
getChild<LLUICtrl>("user_name")->setValue("");
+ getChild<LLUICtrl>("user_slid")->setValue("");
getChild<LLUICtrl>("user_subtitle")->setValue("");
getChild<LLUICtrl>("user_details")->setValue("");
@@ -373,9 +371,9 @@ void LLInspectAvatar::requestUpdate()
childSetValue("avatar_icon", LLSD(mAvatarID) );
- gCacheName->get(mAvatarID, FALSE,
- boost::bind(&LLInspectAvatar::nameUpdatedCallback,
- this, _1, _2, _3, _4));
+ LLAvatarNameCache::get(mAvatarID,
+ boost::bind(&LLInspectAvatar::onAvatarNameCache,
+ this, _1, _2));
}
void LLInspectAvatar::processAvatarData(LLAvatarData* data)
@@ -562,7 +560,7 @@ void LLInspectAvatar::updateVolumeSlider()
LLUICtrl* mute_btn = getChild<LLUICtrl>("mute_btn");
- bool is_linden = LLStringUtil::endsWith(mAvatarName, " Linden");
+ bool is_linden = LLStringUtil::endsWith(mAvatarName.getLegacyName(), " Linden");
mute_btn->setEnabled( !is_linden);
mute_btn->setValue( is_muted );
@@ -593,7 +591,7 @@ void LLInspectAvatar::onClickMuteVolume()
LLMuteList* mute_list = LLMuteList::getInstance();
bool is_muted = mute_list->isMuted(mAvatarID, LLMute::flagVoiceChat);
- LLMute mute(mAvatarID, mAvatarName, LLMute::AGENT);
+ LLMute mute(mAvatarID, mAvatarName.getLegacyName(), LLMute::AGENT);
if (!is_muted)
{
mute_list->add(mute, LLMute::flagVoiceChat);
@@ -612,22 +610,21 @@ void LLInspectAvatar::onVolumeChange(const LLSD& data)
LLVoiceClient::getInstance()->setUserVolume(mAvatarID, volume);
}
-void LLInspectAvatar::nameUpdatedCallback(
- const LLUUID& id,
- const std::string& first,
- const std::string& last,
- BOOL is_group)
+void LLInspectAvatar::onAvatarNameCache(
+ const LLUUID& agent_id,
+ const LLAvatarName& av_name)
{
- if (id == mAvatarID)
+ if (agent_id == mAvatarID)
{
- mAvatarName = first + " " + last;
- childSetValue("user_name", LLSD(mAvatarName) );
+ getChild<LLUICtrl>("user_name")->setValue(av_name.mDisplayName);
+ getChild<LLUICtrl>("user_slid")->setValue(av_name.mUsername);
+ mAvatarName = av_name;
}
}
void LLInspectAvatar::onClickAddFriend()
{
- LLAvatarActions::requestFriendshipDialog(mAvatarID, mAvatarName);
+ LLAvatarActions::requestFriendshipDialog(mAvatarID, mAvatarName.getLegacyName());
closeFloater();
}
@@ -695,7 +692,7 @@ void LLInspectAvatar::onClickShare()
void LLInspectAvatar::onToggleMute()
{
- LLMute mute(mAvatarID, mAvatarName, LLMute::AGENT);
+ LLMute mute(mAvatarID, mAvatarName.getLegacyName(), LLMute::AGENT);
if (LLMuteList::getInstance()->isMuted(mute.mID, mute.mName))
{
@@ -712,7 +709,7 @@ void LLInspectAvatar::onToggleMute()
void LLInspectAvatar::onClickReport()
{
- LLFloaterReporter::showFromAvatar(mAvatarID, mAvatarName);
+ LLFloaterReporter::showFromAvatar(mAvatarID, mAvatarName.getCompleteName());
closeFloater();
}
@@ -736,17 +733,17 @@ void LLInspectAvatar::onClickZoomIn()
void LLInspectAvatar::onClickFindOnMap()
{
- gFloaterWorldMap->trackAvatar(mAvatarID, mAvatarName);
+ gFloaterWorldMap->trackAvatar(mAvatarID, mAvatarName.mDisplayName);
LLFloaterReg::showInstance("world_map");
}
bool LLInspectAvatar::enableMute()
{
- bool is_linden = LLStringUtil::endsWith(mAvatarName, " Linden");
+ bool is_linden = LLStringUtil::endsWith(mAvatarName.getLegacyName(), " Linden");
bool is_self = mAvatarID == gAgent.getID();
- if (!is_linden && !is_self && !LLMuteList::getInstance()->isMuted(mAvatarID, mAvatarName))
+ if (!is_linden && !is_self && !LLMuteList::getInstance()->isMuted(mAvatarID, mAvatarName.getLegacyName()))
{
return true;
}
@@ -758,10 +755,10 @@ bool LLInspectAvatar::enableMute()
bool LLInspectAvatar::enableUnmute()
{
- bool is_linden = LLStringUtil::endsWith(mAvatarName, " Linden");
+ bool is_linden = LLStringUtil::endsWith(mAvatarName.getLegacyName(), " Linden");
bool is_self = mAvatarID == gAgent.getID();
- if (!is_linden && !is_self && LLMuteList::getInstance()->isMuted(mAvatarID, mAvatarName))
+ if (!is_linden && !is_self && LLMuteList::getInstance()->isMuted(mAvatarID, mAvatarName.getLegacyName()))
{
return true;
}
diff --git a/indra/newview/llinspectgroup.cpp b/indra/newview/llinspectgroup.cpp
index 7fd7b69021..fa1640c4c7 100644
--- a/indra/newview/llinspectgroup.cpp
+++ b/indra/newview/llinspectgroup.cpp
@@ -84,9 +84,8 @@ public:
// Callback for gCacheName to look up group name
// Faster than waiting for group properties to return
void nameUpdatedCallback(const LLUUID& id,
- const std::string& first,
- const std::string& last,
- BOOL is_group);
+ const std::string& name,
+ bool is_group);
// Button/menu callbacks
void onClickViewProfile();
@@ -225,21 +224,19 @@ void LLInspectGroup::requestUpdate()
mPropertiesRequest = new LLFetchGroupData(mGroupID, this);
// Name lookup will be faster out of cache, use that
- gCacheName->get(mGroupID, TRUE,
+ gCacheName->getGroup(mGroupID,
boost::bind(&LLInspectGroup::nameUpdatedCallback,
- this, _1, _2, _3, _4));
+ this, _1, _2, _3));
}
void LLInspectGroup::nameUpdatedCallback(
const LLUUID& id,
- const std::string& first,
- const std::string& last,
- BOOL is_group)
+ const std::string& name,
+ bool is_group)
{
if (id == mGroupID)
{
- // group names are returned as a first name
- childSetValue("group_name", LLSD(first) );
+ childSetValue("group_name", LLSD(name) );
}
// Otherwise possibly a request for an older inspector, ignore it
diff --git a/indra/newview/llinspectremoteobject.cpp b/indra/newview/llinspectremoteobject.cpp
index be021df363..5fb918c1aa 100644
--- a/indra/newview/llinspectremoteobject.cpp
+++ b/indra/newview/llinspectremoteobject.cpp
@@ -66,12 +66,12 @@ public:
private:
void update();
- static void nameCallback(const LLUUID& id, const std::string& first, const std::string& last, BOOL is_group, void* data);
+ void onNameCache(const LLUUID& id, const std::string& name, bool is_group);
private:
LLUUID mObjectID;
LLUUID mOwnerID;
- std::string mOwner;
+ std::string mOwnerLegacyName;
std::string mSLurl;
std::string mName;
bool mGroupOwned;
@@ -81,7 +81,7 @@ LLInspectRemoteObject::LLInspectRemoteObject(const LLSD& sd) :
LLInspect(LLSD()),
mObjectID(NULL),
mOwnerID(NULL),
- mOwner(""),
+ mOwnerLegacyName(),
mSLurl(""),
mName(""),
mGroupOwned(false)
@@ -118,10 +118,11 @@ void LLInspectRemoteObject::onOpen(const LLSD& data)
mSLurl = data["slurl"].asString();
// work out the owner's name
- mOwner = "";
+ mOwnerLegacyName = "";
if (gCacheName)
{
- gCacheName->get(mOwnerID, mGroupOwned, nameCallback, this);
+ gCacheName->get(mOwnerID, mGroupOwned, // muting
+ boost::bind(&LLInspectRemoteObject::onNameCache, this, _1, _2, _3));
}
// update the inspector with the current object state
@@ -150,7 +151,7 @@ void LLInspectRemoteObject::onClickMap()
void LLInspectRemoteObject::onClickBlock()
{
LLMute::EType mute_type = mGroupOwned ? LLMute::GROUP : LLMute::AGENT;
- LLMute mute(mOwnerID, mOwner, mute_type);
+ LLMute mute(mOwnerID, mOwnerLegacyName, mute_type);
LLMuteList::getInstance()->add(mute);
LLPanelBlockedList::showPanelAndSelect(mute.mID);
closeFloater();
@@ -161,16 +162,10 @@ void LLInspectRemoteObject::onClickClose()
closeFloater();
}
-//static
-void LLInspectRemoteObject::nameCallback(const LLUUID& id, const std::string& first, const std::string& last, BOOL is_group, void* data)
+void LLInspectRemoteObject::onNameCache(const LLUUID& id, const std::string& name, bool is_group)
{
- LLInspectRemoteObject *self = (LLInspectRemoteObject*)data;
- self->mOwner = first;
- if (!last.empty())
- {
- self->mOwner += " " + last;
- }
- self->update();
+ mOwnerLegacyName = name;
+ update();
}
void LLInspectRemoteObject::update()
@@ -180,7 +175,7 @@ void LLInspectRemoteObject::update()
getChild<LLUICtrl>("object_name")->setValue("<nolink>" + mName + "</nolink>");
// show the object's owner - click it to show profile
- std::string owner = mOwner;
+ std::string owner;
if (! mOwnerID.isNull())
{
if (mGroupOwned)
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index 7ec6440dc3..caea5e9a98 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -35,6 +35,7 @@
// external projects
#include "lltransfersourceasset.h"
+#include "llavatarnamecache.h" // IDEVO
#include "llagent.h"
#include "llagentcamera.h"
@@ -3442,6 +3443,13 @@ void LLCallingCardBridge::performAction(LLInventoryModel* model, std::string act
{
std::string callingcard_name;
gCacheName->getFullName(item->getCreatorUUID(), callingcard_name);
+ // IDEVO
+ LLAvatarName av_name;
+ if (LLAvatarNameCache::useDisplayNames()
+ && LLAvatarNameCache::get(item->getCreatorUUID(), &av_name))
+ {
+ callingcard_name = av_name.mDisplayName + " (" + av_name.mUsername + ")";
+ }
LLUUID session_id = gIMMgr->addSession(callingcard_name, IM_NOTHING_SPECIAL, item->getCreatorUUID());
if (session_id != LLUUID::null)
{
diff --git a/indra/newview/lllogchat.cpp b/indra/newview/lllogchat.cpp
index be8b2363ad..d4ebdd768b 100644
--- a/indra/newview/lllogchat.cpp
+++ b/indra/newview/lllogchat.cpp
@@ -32,13 +32,18 @@
#include "llviewerprecompiledheaders.h"
+#include "lllogchat.h"
+
+// viewer includes
#include "llagent.h"
#include "llagentui.h"
-#include "lllogchat.h"
#include "lltrans.h"
#include "llviewercontrol.h"
+// library includes
+#include "llchat.h"
#include "llinstantmessage.h"
+#include "llsdserialize.h"
#include "llsingleton.h" // for LLSingleton
#include <boost/algorithm/string/trim.hpp>
@@ -62,12 +67,13 @@
const S32 LOG_RECALL_SIZE = 2048;
-const static std::string IM_TIME("time");
-const static std::string IM_TEXT("message");
-const static std::string IM_FROM("from");
-const static std::string IM_FROM_ID("from_id");
-const static std::string IM_SEPARATOR(": ");
+const std::string IM_TIME("time");
+const std::string IM_TEXT("message");
+const std::string IM_FROM("from");
+const std::string IM_FROM_ID("from_id");
+const std::string IM_SOURCE_TYPE("source_type");
+const static std::string IM_SEPARATOR(": ");
const static std::string NEW_LINE("\n");
const static std::string NEW_LINE_SPACE_PREFIX("\n ");
const static std::string TWO_SPACES(" ");
@@ -190,7 +196,8 @@ std::string LLLogChat::makeLogFileName(std::string filename)
{
filename = cleanFileName(filename);
filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_ACCOUNT_CHAT_LOGS,filename);
- filename += ".txt";
+ // new files are llsd notation format
+ filename += ".llsd";
return filename;
}
@@ -240,6 +247,18 @@ void LLLogChat::saveHistory(const std::string& filename,
const LLUUID& from_id,
const std::string& line)
{
+ LLChat chat;
+ chat.mText = line;
+ chat.mFromName = from;
+ chat.mFromID = from_id;
+ // default to being from an agent
+ chat.mSourceType = CHAT_SOURCE_AGENT;
+ saveHistory(filename, chat);
+}
+
+//static
+void LLLogChat::saveHistory(const std::string& filename, const LLChat& chat)
+{
std::string tmp_filename = filename;
LLStringUtil::trim(tmp_filename);
if (tmp_filename.empty())
@@ -260,89 +279,27 @@ void LLLogChat::saveHistory(const std::string& filename,
LLSD item;
if (gSavedPerAccountSettings.getBOOL("LogTimestamp"))
- item["time"] = LLLogChat::timestamp(gSavedPerAccountSettings.getBOOL("LogTimestampDate"));
+ item[IM_TIME] = LLLogChat::timestamp(gSavedPerAccountSettings.getBOOL("LogTimestampDate"));
- item["from_id"] = from_id;
- item["message"] = line;
+ item[IM_FROM_ID] = chat.mFromID;
+ item[IM_TEXT] = chat.mText;
+ item[IM_SOURCE_TYPE] = chat.mSourceType;
//adding "Second Life:" for all system messages to make chat log history parsing more reliable
- if (from.empty() && from_id.isNull())
+ if (chat.mFromName.empty() && chat.mFromID.isNull())
{
- item["from"] = SYSTEM_FROM;
+ item[IM_FROM] = SYSTEM_FROM;
}
else
{
- item["from"] = from;
+ item[IM_FROM] = chat.mFromName;
}
- file << LLChatLogFormatter(item) << std::endl;
+ file << LLSDOStreamer<LLSDNotationFormatter>(item) << std::endl;
file.close();
}
-void LLLogChat::loadHistory(const std::string& filename, void (*callback)(ELogLineType, const LLSD&, void*), void* userdata)
-{
- if(!filename.size())
- {
- llwarns << "Filename is Empty!" << llendl;
- return ;
- }
-
- LLFILE* fptr = LLFile::fopen(makeLogFileName(filename), "r"); /*Flawfinder: ignore*/
- if (!fptr)
- {
- callback(LOG_EMPTY, LLSD(), userdata);
- return; //No previous conversation with this name.
- }
- else
- {
- char buffer[LOG_RECALL_SIZE]; /*Flawfinder: ignore*/
- char *bptr;
- S32 len;
- bool firstline=TRUE;
-
- if ( fseek(fptr, (LOG_RECALL_SIZE - 1) * -1 , SEEK_END) )
- { //File is smaller than recall size. Get it all.
- firstline = FALSE;
- if ( fseek(fptr, 0, SEEK_SET) )
- {
- fclose(fptr);
- return;
- }
- }
-
- while ( fgets(buffer, LOG_RECALL_SIZE, fptr) && !feof(fptr) )
- {
- len = strlen(buffer) - 1; /*Flawfinder: ignore*/
- for ( bptr = (buffer + len); (*bptr == '\n' || *bptr == '\r') && bptr>buffer; bptr--) *bptr='\0';
-
- if (!firstline)
- {
- LLSD item;
- std::string line(buffer);
- std::istringstream iss(line);
-
- if (!LLChatLogParser::parse(line, item))
- {
- item["message"] = line;
- callback(LOG_LINE, item, userdata);
- }
- else
- {
- callback(LOG_LLSD, item, userdata);
- }
- }
- else
- {
- firstline = FALSE;
- }
- }
- callback(LOG_END, LLSD(), userdata);
-
- fclose(fptr);
- }
-}
-
void append_to_last_message(std::list<LLSD>& messages, const std::string& line)
{
if (!messages.size()) return;
@@ -352,6 +309,7 @@ void append_to_last_message(std::list<LLSD>& messages, const std::string& line)
messages.back()[IM_TEXT] = im_text;
}
+// static
void LLLogChat::loadAllHistory(const std::string& file_name, std::list<LLSD>& messages)
{
if (file_name.empty())
@@ -415,53 +373,25 @@ void LLLogChat::loadAllHistory(const std::string& file_name, std::list<LLSD>& me
fclose(fptr);
}
-//*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 writen like "Object <actual_object's_name>"
-void LLChatLogFormatter::format(const LLSD& im, std::ostream& ostr) const
-{
- if (!im.isMap())
- {
- llwarning("invalid LLSD type of an instant message", 0);
- return;
- }
-
- if (im[IM_TIME].isDefined())
- {
- std::string timestamp = im[IM_TIME].asString();
- boost::trim(timestamp);
- ostr << '[' << timestamp << ']' << TWO_SPACES;
- }
-
- //*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 writen like "Object <actual_object's_name>"
- if (im[IM_FROM].isDefined())
- {
- std::string from = im[IM_FROM].asString();
- boost::trim(from);
- if (from.size())
- {
- ostr << from << IM_SEPARATOR;
- }
- }
-
- if (im[IM_TEXT].isDefined())
- {
- std::string im_text = im[IM_TEXT].asString();
-
- //multilined text will be saved with prepended spaces
- boost::replace_all(im_text, NEW_LINE, NEW_LINE_SPACE_PREFIX);
- ostr << im_text;
- }
-}
-
-bool LLChatLogParser::parse(std::string& raw, LLSD& im)
+// static
+bool LLChatLogParser::parse(const std::string& raw, LLSD& im)
{
if (!raw.length()) return false;
im = LLSD::emptyMap();
+ // In Viewer 2.1 we added UUID to chat/IM logging so we can look up
+ // display names
+ if (raw[0] == '{')
+ {
+ // ...this is a viewer 2.1, new-style LLSD notation format log
+ std::istringstream raw_stream(raw);
+ LLPointer<LLSDParser> parser = new LLSDNotationParser();
+ S32 count = parser->parse(raw_stream, im, raw.length());
+ // expect several map items per parsed line
+ return (count != LLSDParser::PARSE_FAILURE);
+ }
+
//matching a timestamp
boost::match_results<std::string::const_iterator> matches;
if (!boost::regex_match(raw, matches, TIMESTAMP_AND_STUFF)) return false;
diff --git a/indra/newview/lllogchat.h b/indra/newview/lllogchat.h
index 4290e4bbc0..674f27407e 100644
--- a/indra/newview/lllogchat.h
+++ b/indra/newview/lllogchat.h
@@ -30,10 +30,11 @@
* $/LicenseInfo$
*/
-
#ifndef LL_LLLOGCHAT_H
#define LL_LLLOGCHAT_H
+class LLChat;
+
class LLLogChat
{
public:
@@ -46,49 +47,22 @@ public:
};
static std::string timestamp(bool withdate = false);
static std::string makeLogFileName(std::string(filename));
+
+ // Log a single line item to the appropriate chat file
+ static void saveHistory(const std::string& filename, const LLChat& chat);
+
+ // Prefer the above version - it saves more metadata about the item
static void saveHistory(const std::string& filename,
const std::string& from,
const LLUUID& from_id,
const std::string& line);
- /** @deprecated @see loadAllHistory() */
- static void loadHistory(const std::string& filename,
- void (*callback)(ELogLineType, const LLSD&, void*),
- void* userdata);
-
static void loadAllHistory(const std::string& file_name, std::list<LLSD>& messages);
private:
static std::string cleanFileName(std::string filename);
};
/**
- * Formatter for the plain text chat log files
- */
-class LLChatLogFormatter
-{
-public:
- LLChatLogFormatter(const LLSD& im) : mIM(im) {}
- virtual ~LLChatLogFormatter() {};
-
- friend std::ostream& operator<<(std::ostream& str, const LLChatLogFormatter& formatter)
- {
- formatter.format(formatter.mIM, str);
- return str;
- }
-
-protected:
-
- /**
- * Format an instant message to a stream
- * Timestamps and sender names are required
- * New lines of multilined messages are prepended with a space
- */
- void format(const LLSD& im, std::ostream& ostr) const;
-
- LLSD mIM;
-};
-
-/**
* Parser for the plain text chat log files
*/
class LLChatLogParser
@@ -106,11 +80,18 @@ public:
*
* @return false if failed to parse mandatory data - message text
*/
- static bool parse(std::string& raw, LLSD& im);
+ static bool parse(const std::string& raw, LLSD& im);
protected:
LLChatLogParser();
virtual ~LLChatLogParser() {};
};
+// LLSD map lookup constants
+extern const std::string IM_TIME; //("time");
+extern const std::string IM_TEXT; //("message");
+extern const std::string IM_FROM; //("from");
+extern const std::string IM_FROM_ID; //("from_id");
+extern const std::string IM_SOURCE_TYPE; //("source_type");
+
#endif
diff --git a/indra/newview/lllogininstance.cpp b/indra/newview/lllogininstance.cpp
index 06f490e8e3..95c366939e 100644
--- a/indra/newview/lllogininstance.cpp
+++ b/indra/newview/lllogininstance.cpp
@@ -142,6 +142,7 @@ void LLLoginInstance::constructAuthParams(LLPointer<LLCredential> user_credentia
requested_options.append("initial-outfit");
requested_options.append("gestures");
+ requested_options.append("display_names");
requested_options.append("event_categories");
requested_options.append("event_notifications");
requested_options.append("classified_categories");
diff --git a/indra/newview/llmutelist.cpp b/indra/newview/llmutelist.cpp
index 7cb192e026..7126914260 100644
--- a/indra/newview/llmutelist.cpp
+++ b/indra/newview/llmutelist.cpp
@@ -118,9 +118,8 @@ LLMute::LLMute(const LLUUID& id, const std::string& name, EType type, U32 flags)
LLNameValue* lastname = mute_object->getNVPair("LastName");
if (firstname && lastname)
{
- mName.assign( firstname->getString() );
- mName.append(" ");
- mName.append( lastname->getString() );
+ mName = LLCacheName::buildFullName(
+ firstname->getString(), lastname->getString());
}
mType = mute_object->isAvatar() ? AGENT : OBJECT;
}
@@ -416,7 +415,7 @@ void LLMuteList::updateRemove(const LLMute& mute)
gAgent.sendReliableMessage();
}
-void notify_automute_callback(const LLUUID& agent_id, const std::string& first_name, const std::string& last_name, BOOL is_group, LLMuteList::EAutoReason reason)
+void notify_automute_callback(const LLUUID& agent_id, const std::string& full_name, bool is_group, LLMuteList::EAutoReason reason)
{
std::string notif_name;
switch (reason)
@@ -434,8 +433,7 @@ void notify_automute_callback(const LLUUID& agent_id, const std::string& first_n
}
LLSD args;
- args["FIRST"] = first_name;
- args["LAST"] = last_name;
+ args["NAME"] = full_name;
LLNotificationPtr notif_ptr = LLNotifications::instance().add(notif_name, args, LLSD());
if (notif_ptr)
@@ -450,7 +448,7 @@ void notify_automute_callback(const LLUUID& agent_id, const std::string& first_n
}
-BOOL LLMuteList::autoRemove(const LLUUID& agent_id, const EAutoReason reason, const std::string& first_name, const std::string& last_name)
+BOOL LLMuteList::autoRemove(const LLUUID& agent_id, const EAutoReason reason)
{
BOOL removed = FALSE;
@@ -460,24 +458,17 @@ BOOL LLMuteList::autoRemove(const LLUUID& agent_id, const EAutoReason reason, co
removed = TRUE;
remove(automute);
- if (first_name.empty() && last_name.empty())
- {
- std::string cache_first, cache_last;
- if (gCacheName->getName(agent_id, cache_first, cache_last))
+ std::string full_name;
+ if (gCacheName->getFullName(agent_id, full_name))
{
// name in cache, call callback directly
- notify_automute_callback(agent_id, cache_first, cache_last, FALSE, reason);
+ notify_automute_callback(agent_id, full_name, false, reason);
}
else
{
// not in cache, lookup name from cache
- gCacheName->get(agent_id, FALSE, boost::bind(&notify_automute_callback, _1, _2, _3, _4, reason));
- }
- }
- else
- {
- // call callback directly
- notify_automute_callback(agent_id, first_name, last_name, FALSE, reason);
+ gCacheName->get(agent_id, false,
+ boost::bind(&notify_automute_callback, _1, _2, _3, reason));
}
}
diff --git a/indra/newview/llmutelist.h b/indra/newview/llmutelist.h
index 79b556bdbb..ad4fd2345d 100644
--- a/indra/newview/llmutelist.h
+++ b/indra/newview/llmutelist.h
@@ -69,7 +69,7 @@ public:
public:
LLUUID mID; // agent or object id
- std::string mName; // agent or object name
+ std::string mName; // agent or object name, does not store last name "Resident"
EType mType; // needed for UI display of existing mutes
U32 mFlags; // flags pertaining to this mute entry
};
@@ -102,7 +102,7 @@ public:
// Remove both normal and legacy mutes, for any or all properties.
BOOL remove(const LLMute& mute, U32 flags = 0);
- BOOL autoRemove(const LLUUID& agent_id, const EAutoReason reason, const std::string& first_name = LLStringUtil::null, const std::string& last_name = LLStringUtil::null);
+ BOOL autoRemove(const LLUUID& agent_id, const EAutoReason reason);
// Name is required to test against legacy text-only mutes.
BOOL isMuted(const LLUUID& id, const std::string& name = LLStringUtil::null, U32 flags = 0) const;
diff --git a/indra/newview/llnamebox.cpp b/indra/newview/llnamebox.cpp
index cd810b9793..da3e95e947 100644
--- a/indra/newview/llnamebox.cpp
+++ b/indra/newview/llnamebox.cpp
@@ -87,26 +87,15 @@ void LLNameBox::setNameID(const LLUUID& name_id, BOOL is_group)
setText(mInitialValue);
}
-void LLNameBox::refresh(const LLUUID& id, const std::string& firstname,
- const std::string& lastname, BOOL is_group)
+void LLNameBox::refresh(const LLUUID& id, const std::string& full_name, bool is_group)
{
if (id == mNameID)
{
- std::string name;
- if (!is_group)
- {
- name = firstname + " " + lastname;
- }
- else
- {
- name = firstname;
- }
- setName(name, is_group);
+ setName(full_name, is_group);
}
}
-void LLNameBox::refreshAll(const LLUUID& id, const std::string& firstname,
- const std::string& lastname, BOOL is_group)
+void LLNameBox::refreshAll(const LLUUID& id, const std::string& full_name, bool is_group)
{
std::set<LLNameBox*>::iterator it;
for (it = LLNameBox::sInstances.begin();
@@ -114,7 +103,7 @@ void LLNameBox::refreshAll(const LLUUID& id, const std::string& firstname,
++it)
{
LLNameBox* box = *it;
- box->refresh(id, firstname, lastname, is_group);
+ box->refresh(id, full_name, is_group);
}
}
diff --git a/indra/newview/llnamebox.h b/indra/newview/llnamebox.h
index 48b54faec8..2fe8990653 100644
--- a/indra/newview/llnamebox.h
+++ b/indra/newview/llnamebox.h
@@ -59,10 +59,9 @@ public:
void setNameID(const LLUUID& name_id, BOOL is_group);
- void refresh(const LLUUID& id, const std::string& first, const std::string& last, BOOL is_group);
+ void refresh(const LLUUID& id, const std::string& full_name, bool is_group);
- static void refreshAll(const LLUUID& id, const std::string& firstname,
- const std::string& lastname, BOOL is_group);
+ static void refreshAll(const LLUUID& id, const std::string& full_name, bool is_group);
protected:
LLNameBox (const Params&);
diff --git a/indra/newview/llnameeditor.cpp b/indra/newview/llnameeditor.cpp
index 65601da7da..0c704a1f56 100644
--- a/indra/newview/llnameeditor.cpp
+++ b/indra/newview/llnameeditor.cpp
@@ -81,26 +81,15 @@ void LLNameEditor::setNameID(const LLUUID& name_id, BOOL is_group)
setText(name);
}
-void LLNameEditor::refresh(const LLUUID& id, const std::string& firstname,
- const std::string& lastname, BOOL is_group)
+void LLNameEditor::refresh(const LLUUID& id, const std::string& full_name, bool is_group)
{
if (id == mNameID)
{
- std::string name;
- if (!is_group)
- {
- name = firstname + " " + lastname;
- }
- else
- {
- name = firstname;
- }
- setText(name);
+ setText(full_name);
}
}
-void LLNameEditor::refreshAll(const LLUUID& id, const std::string& firstname,
- const std::string& lastname, BOOL is_group)
+void LLNameEditor::refreshAll(const LLUUID& id, const std::string& full_name, bool is_group)
{
std::set<LLNameEditor*>::iterator it;
for (it = LLNameEditor::sInstances.begin();
@@ -108,7 +97,7 @@ void LLNameEditor::refreshAll(const LLUUID& id, const std::string& firstname,
++it)
{
LLNameEditor* box = *it;
- box->refresh(id, firstname, lastname, is_group);
+ box->refresh(id, full_name, is_group);
}
}
diff --git a/indra/newview/llnameeditor.h b/indra/newview/llnameeditor.h
index 99e03a1166..a75c492aca 100644
--- a/indra/newview/llnameeditor.h
+++ b/indra/newview/llnameeditor.h
@@ -65,10 +65,9 @@ public:
void setNameID(const LLUUID& name_id, BOOL is_group);
- void refresh(const LLUUID& id, const std::string& first, const std::string& last, BOOL is_group);
+ void refresh(const LLUUID& id, const std::string& full_name, bool is_group);
- static void refreshAll(const LLUUID& id, const std::string& firstname,
- const std::string& lastname, BOOL is_group);
+ static void refreshAll(const LLUUID& id, const std::string& full_name, bool is_group);
// Take/return agent UUIDs
diff --git a/indra/newview/llnamelistctrl.cpp b/indra/newview/llnamelistctrl.cpp
index d09f729943..3d15f8288f 100644
--- a/indra/newview/llnamelistctrl.cpp
+++ b/indra/newview/llnamelistctrl.cpp
@@ -36,6 +36,7 @@
#include <boost/tokenizer.hpp>
+#include "llavatarnamecache.h"
#include "llcachename.h"
#include "llfloaterreg.h"
#include "llinventory.h"
@@ -58,7 +59,8 @@ void LLNameListCtrl::NameTypeNames::declareValues()
LLNameListCtrl::Params::Params()
: name_column(""),
- allow_calling_card_drop("allow_calling_card_drop", false)
+ allow_calling_card_drop("allow_calling_card_drop", false),
+ short_names("short_names", false)
{
name = "name_list";
}
@@ -67,7 +69,8 @@ LLNameListCtrl::LLNameListCtrl(const LLNameListCtrl::Params& p)
: LLScrollListCtrl(p),
mNameColumnIndex(p.name_column.column_index),
mNameColumn(p.name_column.column_name),
- mAllowCallingCardDrop(p.allow_calling_card_drop)
+ mAllowCallingCardDrop(p.allow_calling_card_drop),
+ mShortNames(p.short_names)
{}
// public
@@ -297,10 +300,20 @@ LLScrollListItem* LLNameListCtrl::addNameItemRow(
break;
case INDIVIDUAL:
{
- std::string name;
- if (gCacheName->getFullName(id, name))
+ LLAvatarName av_name;
+ if (LLAvatarNameCache::get(id, &av_name))
{
- fullname = name;
+ if (mShortNames)
+ fullname = av_name.mDisplayName;
+ else
+ fullname = av_name.getCompleteName();
+ }
+ else
+ {
+ // ...schedule a callback
+ LLAvatarNameCache::get(id,
+ boost::bind(&LLNameListCtrl::onAvatarNameCache,
+ this, _1, _2));
}
break;
}
@@ -355,34 +368,25 @@ void LLNameListCtrl::removeNameItem(const LLUUID& agent_id)
}
}
-// public
-void LLNameListCtrl::refresh(const LLUUID& id, const std::string& first,
- const std::string& last, BOOL is_group)
+void LLNameListCtrl::onAvatarNameCache(const LLUUID& agent_id,
+ const LLAvatarName& av_name)
{
- //llinfos << "LLNameListCtrl::refresh " << id << " '" << first << " "
- // << last << "'" << llendl;
-
- std::string fullname;
- if (!is_group)
- {
- fullname = first + " " + last;
- }
+ std::string name;
+ if (mShortNames)
+ name = av_name.mDisplayName;
else
- {
- fullname = first;
- }
+ name = av_name.getCompleteName();
- // TODO: scan items for that ID, fix if necessary
item_list::iterator iter;
for (iter = getItemList().begin(); iter != getItemList().end(); iter++)
{
LLScrollListItem* item = *iter;
- if (item->getUUID() == id)
+ if (item->getUUID() == agent_id)
{
LLScrollListCell* cell = item->getColumn(mNameColumnIndex);
if (cell)
{
- cell->setValue(fullname);
+ cell->setValue(name);
}
}
}
@@ -391,19 +395,6 @@ void LLNameListCtrl::refresh(const LLUUID& id, const std::string& first,
}
-// static
-void LLNameListCtrl::refreshAll(const LLUUID& id, const std::string& first,
- const std::string& last, BOOL is_group)
-{
- LLInstanceTrackerScopedGuard guard;
- LLInstanceTracker<LLNameListCtrl>::instance_iter it;
- for (it = guard.beginInstances(); it != guard.endInstances(); ++it)
- {
- LLNameListCtrl& ctrl = *it;
- ctrl.refresh(id, first, last, is_group);
- }
-}
-
void LLNameListCtrl::updateColumns()
{
LLScrollListCtrl::updateColumns();
diff --git a/indra/newview/llnamelistctrl.h b/indra/newview/llnamelistctrl.h
index ee71db7540..64f595968c 100644
--- a/indra/newview/llnamelistctrl.h
+++ b/indra/newview/llnamelistctrl.h
@@ -37,6 +37,7 @@
#include "llscrolllistctrl.h"
+class LLAvatarName;
class LLNameListCtrl
: public LLScrollListCtrl, protected LLInstanceTracker<LLNameListCtrl>
@@ -80,6 +81,7 @@ public:
{
Optional<NameColumn> name_column;
Optional<bool> allow_calling_card_drop;
+ Optional<bool> short_names;
Params();
};
@@ -105,11 +107,6 @@ public:
void removeNameItem(const LLUUID& agent_id);
- void refresh(const LLUUID& id, const std::string& first, const std::string& last, BOOL is_group);
-
- static void refreshAll(const LLUUID& id, const std::string& firstname,
- const std::string& lastname, BOOL is_group);
-
// LLView interface
/*virtual*/ BOOL handleDragAndDrop(S32 x, S32 y, MASK mask,
BOOL drop, EDragAndDropType cargo_type, void *cargo_data,
@@ -124,11 +121,13 @@ public:
/*virtual*/ void mouseOverHighlightNthItem( S32 index );
private:
void showInspector(const LLUUID& avatar_id, bool is_group);
+ void onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name);
private:
S32 mNameColumnIndex;
std::string mNameColumn;
BOOL mAllowCallingCardDrop;
+ bool mShortNames; // display name only, no SLID
};
/**
diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp
index 1beaaf3cb4..525c648555 100644
--- a/indra/newview/llnearbychat.cpp
+++ b/indra/newview/llnearbychat.cpp
@@ -61,12 +61,6 @@
static const S32 RESIZE_BAR_THICKNESS = 3;
-const static std::string IM_TIME("time");
-const static std::string IM_TEXT("message");
-const static std::string IM_FROM("from");
-const static std::string IM_FROM_ID("from_id");
-
-
LLNearbyChat::LLNearbyChat(const LLSD& key)
: LLDockableFloater(NULL, false, false, key)
,mChatHistory(NULL)
@@ -191,7 +185,7 @@ void LLNearbyChat::addMessage(const LLChat& chat,bool archive,const LLSD &args)
if (gSavedPerAccountSettings.getBOOL("LogNearbyChat"))
{
- LLLogChat::saveHistory("chat", chat.mFromName, chat.mFromID, chat.mText);
+ LLLogChat::saveHistory("chat", chat);
}
}
@@ -281,8 +275,12 @@ void LLNearbyChat::loadHistory()
const LLSD& msg = *it;
std::string from = msg[IM_FROM];
- LLUUID from_id = LLUUID::null;
- if (msg[IM_FROM_ID].isUndefined())
+ LLUUID from_id;
+ if (msg[IM_FROM_ID].isDefined())
+ {
+ from_id = msg[IM_FROM_ID].asUUID();
+ }
+ else
{
gCacheName->getUUID(from, from_id);
}
@@ -294,11 +292,14 @@ void LLNearbyChat::loadHistory()
chat.mTimeStr = msg[IM_TIME].asString();
chat.mChatStyle = CHAT_STYLE_HISTORY;
- chat.mSourceType = CHAT_SOURCE_AGENT;
- if (from_id.isNull() && SYSTEM_FROM == from)
+ if (msg.has(IM_SOURCE_TYPE))
+ {
+ S32 source_type = msg[IM_SOURCE_TYPE].asInteger();
+ chat.mSourceType = (EChatSourceType)source_type;
+ }
+ else if (from_id.isNull() && SYSTEM_FROM == from)
{
chat.mSourceType = CHAT_SOURCE_SYSTEM;
-
}
else if (from_id.isNull())
{
diff --git a/indra/newview/llnetmap.cpp b/indra/newview/llnetmap.cpp
index a8dee8a24a..67b238ad58 100644
--- a/indra/newview/llnetmap.cpp
+++ b/indra/newview/llnetmap.cpp
@@ -37,6 +37,7 @@
// Library includes (should move below)
#include "indra_constants.h"
+#include "llavatarnamecache.h"
#include "llmath.h"
#include "llfloaterreg.h"
#include "llfocusmgr.h"
@@ -555,11 +556,14 @@ BOOL LLNetMap::handleToolTip( S32 x, S32 y, MASK mask )
// mToolTipMsg = "[AGENT][REGION](Double-click to open Map)"
+ bool have_agent = false;
LLStringUtil::format_map_t args;
- std::string fullname;
- if(mClosestAgentToCursor.notNull() && gCacheName->getFullName(mClosestAgentToCursor, fullname))
+ LLAvatarName av_name;
+ if(mClosestAgentToCursor.notNull()
+ && LLAvatarNameCache::get(mClosestAgentToCursor, &av_name))
{
- args["[AGENT]"] = fullname + "\n";
+ args["[AGENT]"] = av_name.getCompleteName() + "\n";
+ have_agent = true;
}
else
{
@@ -567,7 +571,7 @@ BOOL LLNetMap::handleToolTip( S32 x, S32 y, MASK mask )
}
LLViewerRegion* region = LLWorld::getInstance()->getRegionFromPosGlobal( viewPosToGlobal( x, y ) );
- if( region )
+ if( region && !have_agent)
{
args["[REGION]"] = region->getName() + "\n";
}
diff --git a/indra/newview/llnotificationhandlerutil.cpp b/indra/newview/llnotificationhandlerutil.cpp
index 95b946f307..deb0cb6cfa 100644
--- a/indra/newview/llnotificationhandlerutil.cpp
+++ b/indra/newview/llnotificationhandlerutil.cpp
@@ -113,8 +113,11 @@ void LLSysHandler::removeExclusiveNotifications(const LLNotificationPtr& notif)
}
const static std::string GRANTED_MODIFY_RIGHTS("GrantedModifyRights"),
- REVOKED_MODIFY_RIGHTS("RevokedModifyRights"), OBJECT_GIVE_ITEM(
- "ObjectGiveItem"), PAYMENT_RECIVED("PaymentRecived"),
+ REVOKED_MODIFY_RIGHTS("RevokedModifyRights"),
+ OBJECT_GIVE_ITEM("ObjectGiveItem"),
+ OBJECT_GIVE_ITEM_UNKNOWN_USER("ObjectGiveItemUnknownUser"),
+ PAYMENT_RECEIVED("PaymentReceived"),
+ PAYMENT_SENT("PaymentSent"),
ADD_FRIEND_WITH_MESSAGE("AddFriendWithMessage"),
USER_GIVE_ITEM("UserGiveItem"),
INVENTORY_ACCEPTED("InventoryAccepted"),
@@ -136,7 +139,8 @@ bool LLHandlerUtil::canLogToIM(const LLNotificationPtr& notification)
{
return GRANTED_MODIFY_RIGHTS == notification->getName()
|| REVOKED_MODIFY_RIGHTS == notification->getName()
- || PAYMENT_RECIVED == notification->getName()
+ || PAYMENT_RECEIVED == notification->getName()
+ || PAYMENT_SENT == notification->getName()
|| OFFER_FRIENDSHIP == notification->getName()
|| FRIENDSHIP_OFFERED == notification->getName()
|| FRIENDSHIP_ACCEPTED == notification->getName()
@@ -317,34 +321,35 @@ void LLHandlerUtil::logToIMP2P(const LLNotificationPtr& notification)
logToIMP2P(notification, false);
}
+void log_name_callback(const std::string& full_name, const std::string& from_name,
+ const std::string& message, const LLUUID& from_id)
+
+{
+ LLHandlerUtil::logToIM(IM_NOTHING_SPECIAL, full_name, from_name, message,
+ from_id, LLUUID());
+}
+
// static
void LLHandlerUtil::logToIMP2P(const LLNotificationPtr& notification, bool to_file_only)
{
- const std::string name = LLHandlerUtil::getSubstitutionName(notification);
-
- const std::string& session_name = notification->getPayload().has(
- "SESSION_NAME") ? notification->getPayload()["SESSION_NAME"].asString() : name;
-
// don't create IM p2p session with objects, it's necessary condition to log
if (notification->getName() != OBJECT_GIVE_ITEM)
{
LLUUID from_id = notification->getPayload()["from_id"];
- //there still appears a log history file with weird name " .txt"
- if (" " == session_name || "{waiting}" == session_name || "{nobody}" == session_name)
+ if (from_id.isNull())
{
- llwarning("Weird session name (" + session_name + ") for notification " + notification->getName(), 666)
+ llwarns << " from_id for notification " << notification->getName() << " is null " << llendl;
+ return;
}
if(to_file_only)
{
- logToIM(IM_NOTHING_SPECIAL, session_name, "", notification->getMessage(),
- LLUUID(), LLUUID());
+ gCacheName->get(from_id, false, boost::bind(&log_name_callback, _2, "", notification->getMessage(), LLUUID()));
}
else
{
- logToIM(IM_NOTHING_SPECIAL, session_name, INTERACTIVE_SYSTEM_FROM, notification->getMessage(),
- from_id, LLUUID());
+ gCacheName->get(from_id, false, boost::bind(&log_name_callback, _2, INTERACTIVE_SYSTEM_FROM, notification->getMessage(), from_id));
}
}
}
diff --git a/indra/newview/llpanelavatar.cpp b/indra/newview/llpanelavatar.cpp
index 534bb6e3fc..40e7522b9b 100644
--- a/indra/newview/llpanelavatar.cpp
+++ b/indra/newview/llpanelavatar.cpp
@@ -50,7 +50,7 @@
#include "llfloaterreg.h"
#include "llnotificationsutil.h"
#include "llvoiceclient.h"
-#include "llnamebox.h"
+#include "lltextbox.h"
#include "lltrans.h"
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -224,13 +224,8 @@ void LLPanelAvatarNotes::rightsConfirmationCallback(const LLSD& notification,
void LLPanelAvatarNotes::confirmModifyRights(bool grant, S32 rights)
{
- std::string first, last;
LLSD args;
- if (gCacheName->getName(getAvatarId(), first, last))
- {
- args["FIRST_NAME"] = first;
- args["LAST_NAME"] = last;
- }
+ args["NAME"] = LLSLURL("agent", getAvatarId(), "displayname").getSLURLString();
if (grant)
{
@@ -568,8 +563,7 @@ void LLPanelAvatarProfile::resetData()
childSetValue("homepage_edit",LLStringUtil::null);
childSetValue("register_date",LLStringUtil::null);
childSetValue("acc_status_text",LLStringUtil::null);
- childSetTextArg("partner_text", "[FIRST]", LLStringUtil::null);
- childSetTextArg("partner_text", "[LAST]", LLStringUtil::null);
+ childSetValue("partner_text", LLStringUtil::null);
}
void LLPanelAvatarProfile::processProperties(void* data, EAvatarProcessorType type)
@@ -660,15 +654,14 @@ void LLPanelAvatarProfile::fillCommonData(const LLAvatarData* avatar_data)
void LLPanelAvatarProfile::fillPartnerData(const LLAvatarData* avatar_data)
{
- LLNameBox* name_box = getChild<LLNameBox>("partner_text");
+ LLTextBox* partner_text = getChild<LLTextBox>("partner_text");
if (avatar_data->partner_id.notNull())
{
- name_box->setNameID(avatar_data->partner_id, FALSE);
+ partner_text->setText(LLSLURL("agent", avatar_data->partner_id, "inspect").getSLURLString());
}
else
{
- name_box->setNameID(LLUUID::null, FALSE);
- name_box->setText(getString("no_partner_text"));
+ partner_text->setText(getString("no_partner_text"));
}
}
diff --git a/indra/newview/llpanelavatartag.cpp b/indra/newview/llpanelavatartag.cpp
index 7563cc7f61..173fb851ce 100644
--- a/indra/newview/llpanelavatartag.cpp
+++ b/indra/newview/llpanelavatartag.cpp
@@ -86,7 +86,7 @@ void LLPanelAvatarTag::setAvatarId(const LLUUID& avatar_id)
{
mIcon->setValue(avatar_id);
}
- setName(std::string(mIcon->getFirstName()+ " "+ mIcon->getLastName()));
+ setName(std::string(mIcon->getFullName()));
}
boost::signals2::connection LLPanelAvatarTag::setLeftButtonClickCallback(
diff --git a/indra/newview/llpanelblockedlist.cpp b/indra/newview/llpanelblockedlist.cpp
index c72f0f8012..c3c0af6d9e 100644
--- a/indra/newview/llpanelblockedlist.cpp
+++ b/indra/newview/llpanelblockedlist.cpp
@@ -35,6 +35,7 @@
#include "llpanelblockedlist.h"
// library include
+#include "llavatarname.h"
#include "llfloater.h"
#include "llfloaterreg.h"
#include "llnotificationsutil.h"
@@ -186,10 +187,10 @@ void LLPanelBlockedList::onBlockByNameClick()
LLFloaterGetBlockedObjectName::show(&LLPanelBlockedList::callbackBlockByName);
}
-void LLPanelBlockedList::callbackBlockPicked(const std::vector<std::string>& names, const uuid_vec_t& ids)
+void LLPanelBlockedList::callbackBlockPicked(const uuid_vec_t& ids, const std::vector<LLAvatarName> names)
{
if (names.empty() || ids.empty()) return;
- LLMute mute(ids[0], names[0], LLMute::AGENT);
+ LLMute mute(ids[0], names[0].getLegacyName(), LLMute::AGENT);
LLMuteList::getInstance()->add(mute);
showPanelAndSelect(mute.mID);
}
diff --git a/indra/newview/llpanelblockedlist.h b/indra/newview/llpanelblockedlist.h
index a100577e43..88c1edb1f8 100644
--- a/indra/newview/llpanelblockedlist.h
+++ b/indra/newview/llpanelblockedlist.h
@@ -42,7 +42,8 @@
// class LLLineEditor;
// class LLMessageSystem;
// class LLUUID;
- class LLScrollListCtrl;
+class LLAvatarName;
+class LLScrollListCtrl;
class LLPanelBlockedList
: public LLPanel, public LLMuteListObserver
@@ -78,7 +79,7 @@ private:
void onPickBtnClick();
void onBlockByNameClick();
- void callbackBlockPicked(const std::vector<std::string>& names, const uuid_vec_t& ids);
+ void callbackBlockPicked(const uuid_vec_t& ids, const std::vector<LLAvatarName> names);
static void callbackBlockByName(const std::string& text);
private:
diff --git a/indra/newview/llpanelgroupgeneral.cpp b/indra/newview/llpanelgroupgeneral.cpp
index 8e1b7ba4d9..61781eafb1 100644
--- a/indra/newview/llpanelgroupgeneral.cpp
+++ b/indra/newview/llpanelgroupgeneral.cpp
@@ -46,7 +46,6 @@
#include "llavataractions.h"
#include "llgroupactions.h"
#include "lllineeditor.h"
-#include "llnamebox.h"
#include "llnamelistctrl.h"
#include "llnotificationsutil.h"
#include "llscrolllistitem.h"
@@ -213,7 +212,7 @@ void LLPanelGroupGeneral::setupCtrls(LLPanel* panel_group)
{
mInsignia->setCommitCallback(onCommitAny, this);
}
- mFounderName = getChild<LLNameBox>("founder_name");
+ mFounderName = getChild<LLTextBox>("founder_name");
mGroupNameEditor = panel_group->getChild<LLLineEditor>("group_name_editor");
@@ -648,7 +647,7 @@ void LLPanelGroupGeneral::update(LLGroupChange gc)
if (mEditCharter) mEditCharter->setEnabled(mAllowEdit && can_change_ident);
if (mGroupNameEditor) mGroupNameEditor->setVisible(FALSE);
- if (mFounderName) mFounderName->setNameID(gdatap->mFounderID,FALSE);
+ if (mFounderName) mFounderName->setText(LLSLURL("agent", gdatap->mFounderID, "inspect").getSLURLString());
if (mInsignia)
{
if (gdatap->mInsigniaID.notNull())
diff --git a/indra/newview/llpanelgroupgeneral.h b/indra/newview/llpanelgroupgeneral.h
index 6f4fa994da..066c002634 100644
--- a/indra/newview/llpanelgroupgeneral.h
+++ b/indra/newview/llpanelgroupgeneral.h
@@ -43,7 +43,6 @@ class LLButton;
class LLNameListCtrl;
class LLCheckBoxCtrl;
class LLComboBox;
-class LLNameBox;
class LLSpinCtrl;
class LLPanelGroupGeneral : public LLPanelGroupTab
@@ -98,7 +97,7 @@ private:
// Group information (include any updates in updateChanged)
LLLineEditor *mGroupNameEditor;
- LLNameBox *mFounderName;
+ LLTextBox *mFounderName;
LLTextureCtrl *mInsignia;
LLTextEditor *mEditCharter;
diff --git a/indra/newview/llpanelgroupinvite.cpp b/indra/newview/llpanelgroupinvite.cpp
index 11d3768a3d..a28e0c2123 100644
--- a/indra/newview/llpanelgroupinvite.cpp
+++ b/indra/newview/llpanelgroupinvite.cpp
@@ -34,6 +34,7 @@
#include "llpanelgroupinvite.h"
#include "llagent.h"
+#include "llavatarnamecache.h"
#include "llfloateravatarpicker.h"
#include "llbutton.h"
#include "llcallingcard.h"
@@ -68,9 +69,13 @@ public:
static void callbackClickAdd(void* userdata);
static void callbackClickRemove(void* userdata);
static void callbackSelect(LLUICtrl* ctrl, void* userdata);
- static void callbackAddUsers(const std::vector<std::string>& names,
- const uuid_vec_t& agent_ids,
+ static void callbackAddUsers(const uuid_vec_t& agent_ids,
void* user_data);
+
+ static void onAvatarNameCache(const LLUUID& agent_id,
+ const LLAvatarName& av_name,
+ void* user_data);
+
bool inviteOwnerCallback(const LLSD& notification, const LLSD& response);
public:
@@ -293,7 +298,7 @@ void LLPanelGroupInvite::impl::callbackClickAdd(void* userdata)
LLFloater* parentp;
parentp = gFloaterView->getParentFloater(panelp);
- parentp->addDependentFloater(LLFloaterAvatarPicker::show(boost::bind(impl::callbackAddUsers, _1, _2,
+ parentp->addDependentFloater(LLFloaterAvatarPicker::show(boost::bind(impl::callbackAddUsers, _1,
panelp->mImplementation),
TRUE));
}
@@ -359,16 +364,38 @@ void LLPanelGroupInvite::impl::callbackClickOK(void* userdata)
if ( selfp ) selfp->submitInvitations();
}
+
+
//static
-void LLPanelGroupInvite::impl::callbackAddUsers(const std::vector<std::string>& names,
- const uuid_vec_t& ids,
- void* user_data)
+void LLPanelGroupInvite::impl::callbackAddUsers(const uuid_vec_t& agent_ids, void* user_data)
+{
+ std::vector<std::string> names;
+ for (S32 i = 0; i < (S32)agent_ids.size(); i++)
+ {
+ LLAvatarNameCache::get(agent_ids[i],
+ boost::bind(&LLPanelGroupInvite::impl::onAvatarNameCache, _1, _2, user_data));
+ }
+
+}
+
+void LLPanelGroupInvite::impl::onAvatarNameCache(const LLUUID& agent_id,
+ const LLAvatarName& av_name,
+ void* user_data)
{
impl* selfp = (impl*) user_data;
- if ( selfp) selfp->addUsers(names, ids);
+ if (selfp)
+ {
+ std::vector<std::string> names;
+ uuid_vec_t agent_ids;
+ agent_ids.push_back(agent_id);
+ names.push_back(av_name.getCompleteName());
+
+ selfp->addUsers(names, agent_ids);
+ }
}
+
LLPanelGroupInvite::LLPanelGroupInvite(const LLUUID& group_id)
: LLPanel(),
mImplementation(new impl(group_id)),
@@ -404,16 +431,18 @@ void LLPanelGroupInvite::addUsers(uuid_vec_t& agent_ids)
std::vector<std::string> names;
for (S32 i = 0; i < (S32)agent_ids.size(); i++)
{
+ std::string fullname;
LLUUID agent_id = agent_ids[i];
LLViewerObject* dest = gObjectList.findObject(agent_id);
- std::string fullname;
if(dest && dest->isAvatar())
{
LLNameValue* nvfirst = dest->getNVPair("FirstName");
LLNameValue* nvlast = dest->getNVPair("LastName");
if(nvfirst && nvlast)
{
- fullname = std::string(nvfirst->getString()) + " " + std::string(nvlast->getString());
+ fullname = LLCacheName::buildFullName(
+ nvfirst->getString(), nvlast->getString());
+
}
if (!fullname.empty())
{
@@ -436,8 +465,7 @@ void LLPanelGroupInvite::addUsers(uuid_vec_t& agent_ids)
{
// actually it should happen, just in case
gCacheName->get(LLUUID(agent_id), false, boost::bind(
- &LLPanelGroupInvite::addUserCallback, this, _1, _2,
- _3));
+ &LLPanelGroupInvite::addUserCallback, this, _1, _2));
// for this special case!
//when there is no cached name we should remove resident from agent_ids list to avoid breaking of sequence
// removed id will be added in callback
@@ -453,16 +481,16 @@ void LLPanelGroupInvite::addUsers(uuid_vec_t& agent_ids)
mImplementation->addUsers(names, agent_ids);
}
-void LLPanelGroupInvite::addUserCallback(const LLUUID& id, const std::string& first_name, const std::string& last_name)
+void LLPanelGroupInvite::addUserCallback(const LLUUID& id, const std::string& full_name)
{
std::vector<std::string> names;
uuid_vec_t agent_ids;
- std::string full_name = first_name + " " + last_name;
agent_ids.push_back(id);
- names.push_back(first_name + " " + last_name);
+ names.push_back(full_name);
mImplementation->addUsers(names, agent_ids);
}
+
void LLPanelGroupInvite::draw()
{
LLPanel::draw();
diff --git a/indra/newview/llpanelgroupinvite.h b/indra/newview/llpanelgroupinvite.h
index 2ed443ed46..520107c33a 100644
--- a/indra/newview/llpanelgroupinvite.h
+++ b/indra/newview/llpanelgroupinvite.h
@@ -46,7 +46,7 @@ public:
/**
* this callback is being used to add a user whose fullname isn't been loaded before invoking of addUsers().
*/
- void addUserCallback(const LLUUID& id, const std::string& first_name, const std::string& last_name);
+ void addUserCallback(const LLUUID& id, const std::string& full_name);
void clear();
void update();
diff --git a/indra/newview/llpanelgroupnotices.cpp b/indra/newview/llpanelgroupnotices.cpp
index ba50081fb2..18a38880ef 100644
--- a/indra/newview/llpanelgroupnotices.cpp
+++ b/indra/newview/llpanelgroupnotices.cpp
@@ -36,6 +36,7 @@
#include "llview.h"
+#include "llavatarnamecache.h"
#include "llinventory.h"
#include "llviewerinventory.h"
#include "llinventorydefines.h"
@@ -546,6 +547,12 @@ void LLPanelGroupNotices::processNotices(LLMessageSystem* msg)
msg->getU8("Data","AssetType",asset_type,i);
msg->getU32("Data","Timestamp",timestamp,i);
+ // we only have the legacy name here, convert it to a username
+ if (LLAvatarNameCache::useDisplayNames())
+ {
+ name = LLCacheName::buildUsername(name);
+ }
+
LLSD row;
row["id"] = id;
diff --git a/indra/newview/llpanelgrouproles.cpp b/indra/newview/llpanelgrouproles.cpp
index 26e8a932aa..c44baea444 100644
--- a/indra/newview/llpanelgrouproles.cpp
+++ b/indra/newview/llpanelgrouproles.cpp
@@ -1115,11 +1115,7 @@ void LLPanelGroupMembersSubTab::sendEjectNotifications(const LLUUID& group_id, c
for (uuid_vec_t::const_iterator i = selected_members.begin(); i != selected_members.end(); ++i)
{
LLSD args;
- std::string name;
-
- gCacheName->getFullName(*i, name);
-
- args["AVATAR_NAME"] = name;
+ args["AVATAR_NAME"] = LLSLURL("agent", *i, "displayname").getSLURLString();
args["GROUP_NAME"] = group_data->mName;
LLNotifications::instance().add(LLNotification::Params("EjectAvatarFromGroup").substitutions(args));
diff --git a/indra/newview/llpanelimcontrolpanel.cpp b/indra/newview/llpanelimcontrolpanel.cpp
index b79a4f359a..88b8ff324c 100644
--- a/indra/newview/llpanelimcontrolpanel.cpp
+++ b/indra/newview/llpanelimcontrolpanel.cpp
@@ -186,7 +186,7 @@ void LLPanelIMControlPanel::onViewProfileButtonClicked()
void LLPanelIMControlPanel::onAddFriendButtonClicked()
{
LLAvatarIconCtrl* avatar_icon = getChild<LLAvatarIconCtrl>("avatar_icon");
- std::string full_name = avatar_icon->getFirstName() + " " + avatar_icon->getLastName();
+ std::string full_name = avatar_icon->getFullName();
LLAvatarActions::requestFriendshipDialog(mAvatarID, full_name);
}
@@ -237,6 +237,15 @@ void LLPanelIMControlPanel::setSessionId(const LLUUID& session_id)
childSetEnabled("share_btn", FALSE);
childSetEnabled("teleport_btn", FALSE);
childSetEnabled("pay_btn", FALSE);
+
+ getChild<LLTextBox>("avatar_name")->setValue(im_session->mName);
+ getChild<LLTextBox>("avatar_name")->setToolTip(im_session->mName);
+ }
+ else
+ {
+ // If the participant is an avatar, fetch the currect name
+ gCacheName->get(mAvatarID, false,
+ boost::bind(&LLPanelIMControlPanel::onNameCache, this, _1, _2, _3));
}
}
@@ -252,6 +261,16 @@ void LLPanelIMControlPanel::changed(U32 mask)
}
}
+void LLPanelIMControlPanel::onNameCache(const LLUUID& id, const std::string& full_name, bool is_group)
+{
+ if ( id == mAvatarID )
+ {
+ std::string avatar_name = full_name;
+ getChild<LLTextBox>("avatar_name")->setValue(avatar_name);
+ getChild<LLTextBox>("avatar_name")->setToolTip(avatar_name);
+ }
+}
+
LLPanelGroupControlPanel::LLPanelGroupControlPanel(const LLUUID& session_id):
mParticipantList(NULL)
{
diff --git a/indra/newview/llpanelimcontrolpanel.h b/indra/newview/llpanelimcontrolpanel.h
index 0a1fd70c08..4594a0d021 100644
--- a/indra/newview/llpanelimcontrolpanel.h
+++ b/indra/newview/llpanelimcontrolpanel.h
@@ -89,6 +89,9 @@ public:
// LLFriendObserver trigger
virtual void changed(U32 mask);
+protected:
+ void onNameCache(const LLUUID& id, const std::string& full_name, bool is_group);
+
private:
void onViewProfileButtonClicked();
void onAddFriendButtonClicked();
diff --git a/indra/newview/llpanellandmarkinfo.cpp b/indra/newview/llpanellandmarkinfo.cpp
index 4ffd43cb0f..f6c70c82da 100644
--- a/indra/newview/llpanellandmarkinfo.cpp
+++ b/indra/newview/llpanellandmarkinfo.cpp
@@ -45,6 +45,7 @@
#include "llagent.h"
#include "llagentui.h"
#include "lllandmarkactions.h"
+#include "llslurl.h"
#include "llviewerinventory.h"
#include "llviewerparcelmgr.h"
#include "llviewerregion.h"
@@ -231,13 +232,10 @@ void LLPanelLandmarkInfo::displayItemInfo(const LLInventoryItem* pItem)
//////////////////
if (pItem->getCreatorUUID().notNull())
{
- std::string name;
+ // IDEVO
LLUUID creator_id = pItem->getCreatorUUID();
- if (!gCacheName->getFullName(creator_id, name))
- {
- gCacheName->get(creator_id, FALSE,
- boost::bind(&LLPanelPlaceInfo::nameUpdatedCallback, mCreator, _2, _3));
- }
+ std::string name =
+ LLSLURL("agent", creator_id, "inspect").getSLURLString();
mCreator->setText(name);
}
else
@@ -254,20 +252,12 @@ void LLPanelLandmarkInfo::displayItemInfo(const LLInventoryItem* pItem)
if (perm.isGroupOwned())
{
LLUUID group_id = perm.getGroup();
- if (!gCacheName->getGroupName(group_id, name))
- {
- gCacheName->get(group_id, TRUE,
- boost::bind(&LLPanelPlaceInfo::nameUpdatedCallback, mOwner, _2, _3));
- }
+ name = LLSLURL("group", group_id, "inspect").getSLURLString();
}
else
{
LLUUID owner_id = perm.getOwner();
- if (!gCacheName->getFullName(owner_id, name))
- {
- gCacheName->get(owner_id, FALSE,
- boost::bind(&LLPanelPlaceInfo::nameUpdatedCallback, mOwner, _2, _3));
- }
+ name = LLSLURL("agent", owner_id, "inspect").getSLURLString();
}
mOwner->setText(name);
}
diff --git a/indra/newview/llpanellogin.cpp b/indra/newview/llpanellogin.cpp
index 144839b554..d5c640ad25 100644
--- a/indra/newview/llpanellogin.cpp
+++ b/indra/newview/llpanellogin.cpp
@@ -211,7 +211,6 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect,
}
#if !USE_VIEWER_AUTH
- childSetPrevalidate("username_edit", LLTextValidate::validateASCIIPrintableNoPipe);
getChild<LLLineEditor>("password_edit")->setKeystrokeCallback(onPassKey, this);
// change z sort of clickable text to be behind buttons
@@ -514,8 +513,16 @@ void LLPanelLogin::setFields(LLPointer<LLCredential> credential,
LLSD identifier = credential->getIdentifier();
if((std::string)identifier["type"] == "agent")
{
- sInstance->childSetText("username_edit", (std::string)identifier["first_name"] + " " +
- (std::string)identifier["last_name"]);
+ std::string firstname = identifier["first_name"].asString();
+ std::string lastname = identifier["last_name"].asString();
+ std::string login_id = firstname;
+ if (!lastname.empty() && lastname != "Resident")
+ {
+ // support traditional First Last name SLURLs
+ login_id += " ";
+ login_id += lastname;
+ }
+ sInstance->childSetText("username_edit", login_id);
}
else if((std::string)identifier["type"] == "account")
{
@@ -579,7 +586,8 @@ void LLPanelLogin::getFields(LLPointer<LLCredential>& credential,
LL_INFOS2("Credentials", "Authentication") << "retrieving username:" << username << LL_ENDL;
// determine if the username is a first/last form or not.
size_t separator_index = username.find_first_of(' ');
- if (separator_index == username.npos)
+ if (separator_index == username.npos
+ && !LLGridManager::getInstance()->isSystemGrid())
{
LL_INFOS2("Credentials", "Authentication") << "account: " << username << LL_ENDL;
// single username, so this is a 'clear' identifier
@@ -596,9 +604,23 @@ void LLPanelLogin::getFields(LLPointer<LLCredential>& credential,
}
else
{
+ // Be lenient in terms of what separators we allow for two-word names
+ // and allow legacy users to login with firstname.lastname
+ separator_index = username.find_first_of(" ._");
std::string first = username.substr(0, separator_index);
- std::string last = username.substr(separator_index, username.npos);
+ std::string last;
+ if (separator_index != username.npos)
+ {
+ last = username.substr(separator_index+1, username.npos);
LLStringUtil::trim(last);
+ }
+ else
+ {
+ // ...on Linden grids, single username users as considered to have
+ // last name "Resident"
+ // *TODO: Make login.cgi support "account_name" like above
+ last = "Resident";
+ }
if (last.find_first_of(' ') == last.npos)
{
diff --git a/indra/newview/llpanelme.cpp b/indra/newview/llpanelme.cpp
index 3f620869e0..5e8e07b962 100644
--- a/indra/newview/llpanelme.cpp
+++ b/indra/newview/llpanelme.cpp
@@ -32,17 +32,25 @@
#include "llviewerprecompiledheaders.h"
+#include "llpanelme.h"
+
+// Viewer includes
#include "llpanelprofile.h"
#include "llavatarconstants.h"
-#include "llpanelme.h"
#include "llagent.h"
#include "llagentcamera.h"
#include "llagentwearables.h"
-#include "lliconctrl.h"
#include "llsidetray.h"
+#include "llviewercontrol.h"
+#include "llviewerdisplayname.h"
+
+// Linden libraries
+#include "llavatarnamecache.h" // IDEVO
+#include "lliconctrl.h"
+#include "llnotifications.h"
+#include "llnotificationsutil.h" // IDEVO
#include "lltabcontainer.h"
#include "lltexturectrl.h"
-#include "llviewercontrol.h"
#define PICKER_SECOND_LIFE "2nd_life_pic"
#define PICKER_FIRST_LIFE "real_world_pic"
@@ -180,6 +188,13 @@ void LLPanelMyProfileEdit::onOpen(const LLSD& key)
// Disable editing until data is loaded, or edited fields will be overwritten when data
// is loaded.
enableEditing(false);
+
+ // Only allow changing name if this region/grid supports it
+ bool use_display_names = LLAvatarNameCache::useDisplayNames();
+ LLUICtrl* set_name = getChild<LLUICtrl>("set_name");
+ set_name->setVisible(use_display_names);
+ set_name->setEnabled(use_display_names);
+
LLPanelMyProfile::onOpen(getAvatarId());
}
@@ -213,13 +228,14 @@ void LLPanelMyProfileEdit::processProfileProperties(const LLAvatarData* avatar_d
childSetValue("show_in_search_checkbox", (BOOL)(avatar_data->flags & AVATAR_ALLOW_PUBLISH));
- std::string first, last;
- BOOL found = gCacheName->getName(avatar_data->avatar_id, first, last);
- if (found)
- {
- childSetTextArg("name_text", "[FIRST]", first);
- childSetTextArg("name_text", "[LAST]", last);
- }
+ LLAvatarNameCache::get(avatar_data->avatar_id,
+ boost::bind(&LLPanelMyProfileEdit::onNameCache, this, _1, _2));
+}
+
+void LLPanelMyProfileEdit::onNameCache(const LLUUID& agent_id, const LLAvatarName& av_name)
+{
+ getChild<LLUICtrl>("user_name")->setValue( av_name.mDisplayName );
+ getChild<LLUICtrl>("user_slid")->setValue( av_name.mUsername );
}
BOOL LLPanelMyProfileEdit::postBuild()
@@ -229,6 +245,9 @@ BOOL LLPanelMyProfileEdit::postBuild()
childSetTextArg("partner_edit_link", "[URL]", getString("partner_edit_link_url"));
childSetTextArg("my_account_link", "[URL]", getString("my_account_link_url"));
+ getChild<LLUICtrl>("set_name")->setCommitCallback(
+ boost::bind(&LLPanelMyProfileEdit::onClickSetName, this));
+
return LLPanelAvatarProfile::postBuild();
}
/**
@@ -256,8 +275,10 @@ void LLPanelMyProfileEdit::resetData()
{
LLPanelMyProfile::resetData();
- childSetTextArg("name_text", "[FIRST]", LLStringUtil::null);
- childSetTextArg("name_text", "[LAST]", LLStringUtil::null);
+ //childSetTextArg("name_text", "[FIRST]", LLStringUtil::null);
+ //childSetTextArg("name_text", "[LAST]", LLStringUtil::null);
+ getChild<LLUICtrl>("user_name")->setValue( LLSD() );
+ getChild<LLUICtrl>("user_slid")->setValue( LLSD() );
}
void LLPanelMyProfileEdit::onTexturePickerMouseEnter(LLUICtrl* ctrl)
@@ -269,6 +290,144 @@ void LLPanelMyProfileEdit::onTexturePickerMouseLeave(LLUICtrl* ctrl)
mTextureEditIconMap[ctrl->getName()]->setVisible(FALSE);
}
+void LLPanelMyProfileEdit::onCacheSetName(bool success,
+ const std::string& reason,
+ const LLSD& content)
+{
+ if (success)
+ {
+ // Inform the user that the change took place, but will take a while
+ // to percolate.
+ LLSD args;
+ args["DISPLAY_NAME"] = content["display_name"];
+ LLNotificationsUtil::add("SetDisplayNameSuccess", args);
+
+ // Re-fetch my name, as it may have been sanitized by the service
+ LLAvatarNameCache::get(getAvatarId(),
+ boost::bind(&LLPanelMyProfileEdit::onNameCache, this, _1, _2));
+ return;
+ }
+
+ // Request failed, notify the user
+ std::string error_tag = content["error_tag"].asString();
+ llinfos << "set name failure error_tag " << error_tag << llendl;
+
+ // We might have a localized string for this message
+ // error_args will usually be empty from the server.
+ if (!error_tag.empty()
+ && LLNotifications::getInstance()->templateExists(error_tag))
+ {
+ LLNotificationsUtil::add(error_tag);
+ return;
+ }
+
+ // The server error might have a localized message for us
+ std::string lang_code = LLUI::getLanguage();
+ LLSD error_desc = content["error_description"];
+ if (error_desc.has( lang_code ))
+ {
+ LLSD args;
+ args["MESSAGE"] = error_desc[lang_code].asString();
+ LLNotificationsUtil::add("GenericAlert", args);
+ return;
+ }
+
+ // No specific error, throw a generic one
+ LLNotificationsUtil::add("SetDisplayNameFailedGeneric");
+}
+
+void LLPanelMyProfileEdit::onDialogSetName(const LLSD& notification, const LLSD& response)
+{
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+ if (option == 0 || option == 1)
+ {
+ LLUUID agent_id = notification["payload"]["agent_id"];
+ if (agent_id.isNull()) return;
+
+ std::string display_name_utf8;
+ if (option == 0)
+ {
+ // user gave us a name
+ display_name_utf8 = response["display_name"].asString();
+ }
+ else
+ {
+ // reset back to People API default
+ display_name_utf8 = "";
+ }
+
+ const U32 DISPLAY_NAME_MAX_LENGTH = 31; // characters, not bytes
+ LLWString display_name_wstr = utf8string_to_wstring(display_name_utf8);
+ if (display_name_wstr.size() > DISPLAY_NAME_MAX_LENGTH)
+ {
+ LLSD args;
+ args["LENGTH"] = llformat("%d", DISPLAY_NAME_MAX_LENGTH);
+ LLNotificationsUtil::add("SetDisplayNameFailedLength", args);
+ return;
+ }
+
+ LLViewerDisplayName::set(display_name_utf8,
+ boost::bind(&LLPanelMyProfileEdit::onCacheSetName, this,
+ _1, _2, _3));
+ }
+}
+
+void LLPanelMyProfileEdit::onClickSetName()
+{
+ LLUUID agent_id = getAvatarId();
+ std::string display_name;
+ LLAvatarName av_name;
+ if (!LLAvatarNameCache::get(agent_id, &av_name))
+ {
+ // something is wrong, tell user to try again later
+ LLNotificationsUtil::add("SetDisplayNameFailedGeneric");
+ return;
+ }
+
+ display_name = av_name.mDisplayName;
+ if (display_name.empty())
+ {
+ // something is wrong, tell user to try again later
+ LLNotificationsUtil::add("SetDisplayNameFailedGeneric");
+ return;
+ }
+
+ llinfos << "name-change now " << LLDate::now() << " next_update "
+ << LLDate(av_name.mNextUpdate) << llendl;
+ F64 now_secs = LLDate::now().secondsSinceEpoch();
+
+ if (now_secs < av_name.mNextUpdate)
+ {
+ // if the update time is more than a year in the future, it means updates have been blocked
+ // show a more general message
+ const int YEAR = 60*60*24*365;
+ if (now_secs + YEAR < av_name.mNextUpdate)
+ {
+ LLNotificationsUtil::add("SetDisplayNameBlocked");
+ return;
+ }
+
+ // ...can't update until some time in the future
+ F64 next_update_local_secs =
+ av_name.mNextUpdate - LLStringOps::getLocalTimeOffset();
+ LLDate next_update_local(next_update_local_secs);
+ // display as "July 18 12:17 PM"
+ std::string next_update_string =
+ next_update_local.toHTTPDateString("%B %d %I:%M %p");
+ LLSD args;
+ args["TIME"] = next_update_string;
+ LLNotificationsUtil::add("SetDisplayNameFailedLockout", args);
+ return;
+ }
+
+ LLSD args;
+ args["DISPLAY_NAME"] = display_name;
+ LLSD payload;
+ payload["agent_id"] = agent_id;
+ LLNotificationsUtil::add("SetDisplayName", args, payload,
+ boost::bind(&LLPanelMyProfileEdit::onDialogSetName, this, _1, _2));
+}
+
void LLPanelMyProfileEdit::enableEditing(bool enable)
{
childSetEnabled("2nd_life_pic", enable);
diff --git a/indra/newview/llpanelme.h b/indra/newview/llpanelme.h
index f2b38de3d6..f3caf026dc 100644
--- a/indra/newview/llpanelme.h
+++ b/indra/newview/llpanelme.h
@@ -34,8 +34,9 @@
#define LL_LLPANELMEPROFILE_H
#include "llpanel.h"
-#include "llpanelavatar.h"
+#include "llpanelprofile.h"
+class LLAvatarName;
class LLPanelMyProfileEdit;
class LLPanelProfile;
class LLIconCtrl;
@@ -89,11 +90,15 @@ protected:
/*virtual*/void resetData();
void processProfileProperties(const LLAvatarData* avatar_data);
+ void onNameCache(const LLUUID& agent_id, const LLAvatarName& av_name);
private:
void initTexturePickerMouseEvents();
void onTexturePickerMouseEnter(LLUICtrl* ctrl);
void onTexturePickerMouseLeave(LLUICtrl* ctrl);
+ void onClickSetName();
+ void onDialogSetName(const LLSD& notification, const LLSD& response);
+ void onCacheSetName(bool success, const std::string& reason, const LLSD& content);
/**
* Enabled/disables controls to prevent overwriting edited data upon receiving
diff --git a/indra/newview/llpanelmediasettingspermissions.cpp b/indra/newview/llpanelmediasettingspermissions.cpp
index e5caaaaffc..227dbb3da7 100644
--- a/indra/newview/llpanelmediasettingspermissions.cpp
+++ b/indra/newview/llpanelmediasettingspermissions.cpp
@@ -115,7 +115,7 @@ void LLPanelMediaSettingsPermissions::draw()
if(mPermsGroupName)
{
mPermsGroupName->setNameID(LLUUID::null, TRUE);
- mPermsGroupName->refresh(LLUUID::null, LLStringUtil::null, LLStringUtil::null, true);
+ mPermsGroupName->refresh(LLUUID::null, std::string(), true);
mPermsGroupName->setEnabled(false);
};
};
@@ -194,7 +194,7 @@ void LLPanelMediaSettingsPermissions::initValues( void* userdata, const LLSD& me
data_set[ i ].ctrl_ptr->setTentative( media_settings[ tentative_key ].asBoolean() );
};
};
-
+
// *NOTE: If any of a particular flavor is tentative, we have to disable
// them all because of an architectural issue: namely that we represent
// these as a bit field, and we can't selectively apply only one bit to all selected
@@ -238,21 +238,21 @@ void LLPanelMediaSettingsPermissions::getValues( LLSD &fill_me_in, bool include_
{
// moved over from the 'General settings' tab
if (include_tentative || !mControls->getTentative()) fill_me_in[LLMediaEntry::CONTROLS_KEY] = (LLSD::Integer)mControls->getCurrentIndex();
-
- // *NOTE: For some reason, gcc does not like these symbol references in the
- // expressions below (inside the static_casts). I have NO idea why :(.
- // For some reason, assigning them to const temp vars here fixes the link
- // error. Bizarre.
- const U8 none = LLMediaEntry::PERM_NONE;
- const U8 owner = LLMediaEntry::PERM_OWNER;
- const U8 group = LLMediaEntry::PERM_GROUP;
- const U8 anyone = LLMediaEntry::PERM_ANYONE;
- const LLSD::Integer control = static_cast<LLSD::Integer>(
+
+ // *NOTE: For some reason, gcc does not like these symbol references in the
+ // expressions below (inside the static_casts). I have NO idea why :(.
+ // For some reason, assigning them to const temp vars here fixes the link
+ // error. Bizarre.
+ const U8 none = LLMediaEntry::PERM_NONE;
+ const U8 owner = LLMediaEntry::PERM_OWNER;
+ const U8 group = LLMediaEntry::PERM_GROUP;
+ const U8 anyone = LLMediaEntry::PERM_ANYONE;
+ const LLSD::Integer control = static_cast<LLSD::Integer>(
(mPermsOwnerControl->getValue() ? owner : none ) |
(mPermsGroupControl->getValue() ? group: none ) |
(mPermsWorldControl->getValue() ? anyone : none ));
- const LLSD::Integer interact = static_cast<LLSD::Integer>(
- (mPermsOwnerInteract->getValue() ? owner: none ) |
+ const LLSD::Integer interact = static_cast<LLSD::Integer>(
+ (mPermsOwnerInteract->getValue() ? owner: none ) |
(mPermsGroupInteract->getValue() ? group : none ) |
(mPermsWorldInteract->getValue() ? anyone : none ));
@@ -266,15 +266,15 @@ void LLPanelMediaSettingsPermissions::getValues( LLSD &fill_me_in, bool include_
!mPermsGroupControl->getTentative() ||
!mPermsWorldControl->getTentative())
{
- fill_me_in[LLMediaEntry::PERMS_CONTROL_KEY] = control;
+ fill_me_in[LLMediaEntry::PERMS_CONTROL_KEY] = control;
}
if (include_tentative ||
!mPermsOwnerInteract->getTentative() ||
!mPermsGroupInteract->getTentative() ||
!mPermsWorldInteract->getTentative())
{
- fill_me_in[LLMediaEntry::PERMS_INTERACT_KEY] = interact;
- }
+ fill_me_in[LLMediaEntry::PERMS_INTERACT_KEY] = interact;
+}
}
diff --git a/indra/newview/llpaneloutfitedit.cpp b/indra/newview/llpaneloutfitedit.cpp
index 31c427d2ba..937b794686 100644
--- a/indra/newview/llpaneloutfitedit.cpp
+++ b/indra/newview/llpaneloutfitedit.cpp
@@ -71,6 +71,7 @@
#include "llsdutil.h"
#include "llsidepanelappearance.h"
#include "lltoggleablemenu.h"
+#include "llvoavatarself.h"
#include "llwearablelist.h"
#include "llwearableitemslist.h"
#include "llwearabletype.h"
@@ -347,8 +348,8 @@ BOOL LLPanelOutfitEdit::postBuild()
mInventoryItemsPanel = getChild<LLInventoryPanel>("folder_view");
mInventoryItemsPanel->setFilterTypes(ALL_ITEMS_MASK);
mInventoryItemsPanel->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS);
- mInventoryItemsPanel->setSelectCallback(boost::bind(&LLPanelOutfitEdit::onInventorySelectionChange, this));
- mInventoryItemsPanel->getRootFolder()->setReshapeCallback(boost::bind(&LLPanelOutfitEdit::onInventorySelectionChange, this));
+ mInventoryItemsPanel->setSelectCallback(boost::bind(&LLPanelOutfitEdit::updatePlusButton, this));
+ mInventoryItemsPanel->getRootFolder()->setReshapeCallback(boost::bind(&LLPanelOutfitEdit::updatePlusButton, this));
mCOFDragAndDropObserver = new LLCOFDragAndDropObserver(mInventoryItemsPanel->getModel());
@@ -388,7 +389,7 @@ BOOL LLPanelOutfitEdit::postBuild()
mWearablesListViewPanel = getChild<LLPanel>("filtered_wearables_panel");
mWearableItemsList = getChild<LLInventoryItemsList>("list_view");
mWearableItemsList->setCommitOnSelectionChange(true);
- mWearableItemsList->setCommitCallback(boost::bind(&LLPanelOutfitEdit::onInventorySelectionChange, this));
+ mWearableItemsList->setCommitCallback(boost::bind(&LLPanelOutfitEdit::updatePlusButton, this));
mWearableItemsList->setDoubleClickCallback(boost::bind(&LLPanelOutfitEdit::onPlusBtnClicked, this));
mSaveComboBtn.reset(new LLSaveOutfitComboBtn(this));
@@ -442,6 +443,9 @@ void LLPanelOutfitEdit::showAddWearablesPanel(bool show_add_wearables)
mListViewFilterCmbBox->setVisible(false);
showWearablesFilter();
+
+ // Reset mWearableItemsList position to top. See EXT-8180.
+ mWearableItemsList->goToTop();
}
//switching button bars
@@ -619,15 +623,52 @@ void LLPanelOutfitEdit::onShopButtonClicked()
{
static LLShopURLDispatcher url_resolver;
+ // will contain the resultant URL
std::string url;
+
+ if (isAgentAvatarValid())
+ {
+ // try to get wearable type from 'Add More' panel first (EXT-7639)
+ LLWearableType::EType type = getAddMorePanelSelectionType();
+
+ if (type == LLWearableType::WT_NONE)
+ {
+ type = getCOFWearablesSelectionType();
+ }
+
+ ESex sex = gAgentAvatarp->getSex();
+
+ // WT_INVALID comes for attachments
+ if (type != LLWearableType::WT_INVALID && type != LLWearableType::WT_NONE)
+ {
+ url = url_resolver.resolveURL(type, sex);
+ }
+
+ if (url.empty())
+ {
+ url = url_resolver.resolveURL(mCOFWearables->getExpandedAccordionAssetType(), sex);
+ }
+ }
+ else
+ {
+ llwarns << "Agent avatar is invalid" << llendl;
+
+ // the second argument is not important in this case: generic market place will be opened
+ url = url_resolver.resolveURL(LLWearableType::WT_NONE, SEX_FEMALE);
+ }
+
+ LLWeb::loadURLExternal(url);
+}
+
+LLWearableType::EType LLPanelOutfitEdit::getCOFWearablesSelectionType() const
+{
std::vector<LLPanel*> selected_items;
- mCOFWearables->getSelectedItems(selected_items);
+ LLWearableType::EType type = LLWearableType::WT_NONE;
- ESex sex = gSavedSettings.getU32("AvatarSex") ? SEX_MALE : SEX_FEMALE;
+ mCOFWearables->getSelectedItems(selected_items);
if (selected_items.size() == 1)
{
- LLWearableType::EType type = LLWearableType::WT_NONE;
LLPanel* item = selected_items.front();
// LLPanelDummyClothingListItem is lower then LLPanelInventoryListItemBase in hierarchy tree
@@ -639,20 +680,45 @@ void LLPanelOutfitEdit::onShopButtonClicked()
{
type = real_item->getWearableType();
}
+ }
- // WT_INVALID comes for attachments
- if (type != LLWearableType::WT_INVALID)
+ return type;
+}
+
+LLWearableType::EType LLPanelOutfitEdit::getAddMorePanelSelectionType() const
+{
+ LLWearableType::EType type = LLWearableType::WT_NONE;
+
+ if (mAddWearablesPanel != NULL && mAddWearablesPanel->getVisible())
+ {
+ if (mInventoryItemsPanel != NULL && mInventoryItemsPanel->getVisible())
{
- url = url_resolver.resolveURL(type, sex);
+ std::set<LLUUID> selected_uuids = mInventoryItemsPanel->getRootFolder()->getSelectionList();
+
+ if (selected_uuids.size() == 1)
+ {
+ type = getWearableTypeByItemUUID(*(selected_uuids.begin()));
+ }
}
- }
+ else if (mWearableItemsList != NULL && mWearableItemsList->getVisible())
+ {
+ std::vector<LLUUID> selected_uuids;
+ mWearableItemsList->getSelectedUUIDs(selected_uuids);
- if (url.empty())
- {
- url = url_resolver.resolveURL(mCOFWearables->getExpandedAccordionAssetType(), sex);
+ if (selected_uuids.size() == 1)
+ {
+ type = getWearableTypeByItemUUID(selected_uuids.front());
+ }
+ }
}
- LLWeb::loadURLExternal(url);
+ return type;
+}
+
+LLWearableType::EType LLPanelOutfitEdit::getWearableTypeByItemUUID(const LLUUID& item_uuid) const
+{
+ LLViewerInventoryItem* item = gInventory.getLinkedItem(item_uuid);
+ return (item != NULL) ? item->getWearableType() : LLWearableType::WT_NONE;
}
void LLPanelOutfitEdit::onRemoveFromOutfitClicked(void)
@@ -672,7 +738,7 @@ void LLPanelOutfitEdit::onEditWearableClicked(void)
}
}
-void LLPanelOutfitEdit::onInventorySelectionChange()
+void LLPanelOutfitEdit::updatePlusButton()
{
uuid_vec_t selected_items;
getSelectedItemsUUID(selected_items);
@@ -915,6 +981,9 @@ void LLPanelOutfitEdit::updateVerbs()
mStatus->setText(outfit_is_dirty ? getString("unsaved_changes") : getString("now_editing"));
updateCurrentOutfitName();
+
+ //updating state of "Wear Item" button previously known as "Plus" button
+ updatePlusButton();
}
bool LLPanelOutfitEdit::switchPanels(LLPanel* switch_from_panel, LLPanel* switch_to_panel)
@@ -950,9 +1019,6 @@ void LLPanelOutfitEdit::showFilteredWearablesListView(LLWearableType::EType type
showAddWearablesPanel(true);
showWearablesListView();
- // Reset mWearableItemsList position to top. See EXT-8180.
- mWearableItemsList->goToTop();
-
//e_list_view_item_type implicitly contains LLWearableType::EType starting from LVIT_SHAPE
applyListViewFilter((EListViewItemType) (LVIT_SHAPE + type));
}
diff --git a/indra/newview/llpaneloutfitedit.h b/indra/newview/llpaneloutfitedit.h
index 1eef211276..770e2a229b 100644
--- a/indra/newview/llpaneloutfitedit.h
+++ b/indra/newview/llpaneloutfitedit.h
@@ -145,7 +145,7 @@ public:
void onFolderViewFilterCommitted(LLUICtrl* ctrl);
void onListViewFilterCommitted(LLUICtrl* ctrl);
void onSearchEdit(const std::string& string);
- void onInventorySelectionChange();
+ void updatePlusButton();
void onPlusBtnClicked(void);
void onVisibilityChange(const LLSD &in_visible_chain);
@@ -198,6 +198,10 @@ private:
void getCurrentItemUUID(LLUUID& selected_id);
void onCOFChanged();
+ LLWearableType::EType getCOFWearablesSelectionType() const;
+ LLWearableType::EType getAddMorePanelSelectionType() const;
+ LLWearableType::EType getWearableTypeByItemUUID(const LLUUID& item_uuid) const;
+
LLTextBox* mCurrentOutfitName;
LLTextBox* mStatus;
LLInventoryPanel* mInventoryItemsPanel;
diff --git a/indra/newview/llpanelpeople.cpp b/indra/newview/llpanelpeople.cpp
index 6dd800c0c6..08f412721d 100644
--- a/indra/newview/llpanelpeople.cpp
+++ b/indra/newview/llpanelpeople.cpp
@@ -33,6 +33,7 @@
#include "llviewerprecompiledheaders.h"
// libs
+#include "llavatarname.h"
#include "llfloaterreg.h"
#include "llmenugl.h"
#include "llnotificationsutil.h"
@@ -1161,12 +1162,10 @@ void LLPanelPeople::onActivateButtonClicked()
}
// static
-void LLPanelPeople::onAvatarPicked(
- const std::vector<std::string>& names,
- const uuid_vec_t& ids)
+void LLPanelPeople::onAvatarPicked(const uuid_vec_t& ids, const std::vector<LLAvatarName> names)
{
if (!names.empty() && !ids.empty())
- LLAvatarActions::requestFriendshipDialog(ids[0], names[0]);
+ LLAvatarActions::requestFriendshipDialog(ids[0], names[0].getCompleteName());
}
void LLPanelPeople::onGroupPlusButtonClicked()
diff --git a/indra/newview/llpanelpeople.h b/indra/newview/llpanelpeople.h
index 17c45a034b..54b53fc12c 100644
--- a/indra/newview/llpanelpeople.h
+++ b/indra/newview/llpanelpeople.h
@@ -38,10 +38,11 @@
#include "llcallingcard.h" // for avatar tracker
#include "llvoiceclient.h"
-class LLFilterEditor;
-class LLTabContainer;
class LLAvatarList;
+class LLAvatarName;
+class LLFilterEditor;
class LLGroupList;
+class LLTabContainer;
class LLPanelPeople
: public LLPanel
@@ -133,9 +134,7 @@ private:
bool onNearbyViewSortMenuItemCheck(const LLSD& userdata);
// misc callbacks
- static void onAvatarPicked(
- const std::vector<std::string>& names,
- const uuid_vec_t& ids);
+ static void onAvatarPicked(const uuid_vec_t& ids, const std::vector<LLAvatarName> names);
void onFriendsAccordionExpandedCollapsed(LLUICtrl* ctrl, const LLSD& param, LLAvatarList* avatar_list);
diff --git a/indra/newview/llpanelpermissions.cpp b/indra/newview/llpanelpermissions.cpp
index 71d16a08b4..6bac4ae196 100644
--- a/indra/newview/llpanelpermissions.cpp
+++ b/indra/newview/llpanelpermissions.cpp
@@ -385,7 +385,7 @@ void LLPanelPermissions::refresh()
if (mLabelGroupName)
{
mLabelGroupName->setNameID(LLUUID::null, TRUE);
- mLabelGroupName->refresh(LLUUID::null,LLStringUtil::null, LLStringUtil::null, TRUE);
+ mLabelGroupName->refresh(LLUUID::null, std::string(), true);
mLabelGroupName->setEnabled(FALSE);
}
}
diff --git a/indra/newview/llpanelpicks.cpp b/indra/newview/llpanelpicks.cpp
index bde8d02885..291da5fdd2 100644
--- a/indra/newview/llpanelpicks.cpp
+++ b/indra/newview/llpanelpicks.cpp
@@ -235,9 +235,9 @@ void LLPanelPicks::processProperties(void* data, EAvatarProcessorType type)
LLAvatarPicks* avatar_picks = static_cast<LLAvatarPicks*>(data);
if(avatar_picks && getAvatarId() == avatar_picks->target_id)
{
- std::string name, second_name;
- gCacheName->getName(getAvatarId(),name,second_name);
- childSetTextArg("pick_title", "[NAME]",name);
+ std::string full_name;
+ gCacheName->getFullName(getAvatarId(), full_name);
+ childSetTextArg("pick_title", "[NAME]", full_name);
// Save selection, to be able to edit same item after saving changes. See EXT-3023.
LLUUID selected_id = mPicksList->getSelectedValue()[PICK_ID];
diff --git a/indra/newview/llpanelplaceinfo.cpp b/indra/newview/llpanelplaceinfo.cpp
index 8c1f5d0915..148275c81f 100644
--- a/indra/newview/llpanelplaceinfo.cpp
+++ b/indra/newview/llpanelplaceinfo.cpp
@@ -34,6 +34,7 @@
#include "llpanelplaceinfo.h"
+#include "llavatarname.h"
#include "llsdutil.h"
#include "llsdutil_math.h"
@@ -281,9 +282,15 @@ void LLPanelPlaceInfo::createPick(const LLVector3d& pos_global, LLPanelPickEdit*
}
// static
-void LLPanelPlaceInfo::nameUpdatedCallback(LLTextBox* text,
- const std::string& first,
- const std::string& last)
+void LLPanelPlaceInfo::onNameCache(LLTextBox* text, const std::string& full_name)
{
- text->setText(first + " " + last);
+ text->setText(full_name);
+}
+
+// static
+void LLPanelPlaceInfo::onAvatarNameCache(const LLUUID& agent_id,
+ const LLAvatarName& av_name,
+ LLTextBox* text)
+{
+ text->setText( av_name.getCompleteName() );
}
diff --git a/indra/newview/llpanelplaceinfo.h b/indra/newview/llpanelplaceinfo.h
index deedbd2b0f..0c08c5059b 100644
--- a/indra/newview/llpanelplaceinfo.h
+++ b/indra/newview/llpanelplaceinfo.h
@@ -40,6 +40,7 @@
#include "llremoteparcelrequest.h"
+class LLAvatarName;
class LLExpandableTextBox;
class LLIconCtrl;
class LLInventoryItem;
@@ -102,9 +103,10 @@ public:
void createPick(const LLVector3d& pos_global, LLPanelPickEdit* pick_panel);
protected:
- static void nameUpdatedCallback(LLTextBox* text,
- const std::string& first,
- const std::string& last);
+ static void onNameCache(LLTextBox* text, const std::string& full_name);
+ static void onAvatarNameCache(const LLUUID& agent_id,
+ const LLAvatarName& av_name,
+ LLTextBox* text);
/**
* mParcelID is valid only for remote places, in other cases it's null. See resetLocation()
diff --git a/indra/newview/llpanelplaceprofile.cpp b/indra/newview/llpanelplaceprofile.cpp
index 1f979b0ef1..d962b15419 100644
--- a/indra/newview/llpanelplaceprofile.cpp
+++ b/indra/newview/llpanelplaceprofile.cpp
@@ -34,6 +34,7 @@
#include "llpanelplaceprofile.h"
+#include "llavatarnamecache.h"
#include "llparcel.h"
#include "message.h"
@@ -51,6 +52,7 @@
#include "llappviewer.h"
#include "llcallbacklist.h"
#include "llbuycurrencyhtml.h"
+#include "llslurl.h"
#include "llstatusbar.h"
#include "llviewercontrol.h"
#include "llviewerparcelmgr.h"
@@ -429,11 +431,11 @@ void LLPanelPlaceProfile::displaySelectedParcelInfo(LLParcel* parcel,
if(!parcel->getGroupID().isNull())
{
// FIXME: Using parcel group as region group.
- gCacheName->get(parcel->getGroupID(), TRUE,
- boost::bind(&LLPanelPlaceInfo::nameUpdatedCallback, mRegionGroupText, _2, _3));
+ gCacheName->getGroup(parcel->getGroupID(),
+ boost::bind(&LLPanelPlaceInfo::onNameCache, mRegionGroupText, _2));
- gCacheName->get(parcel->getGroupID(), TRUE,
- boost::bind(&LLPanelPlaceInfo::nameUpdatedCallback, mParcelOwner, _2, _3));
+ gCacheName->getGroup(parcel->getGroupID(),
+ boost::bind(&LLPanelPlaceInfo::onNameCache, mParcelOwner, _2));
}
else
{
@@ -445,10 +447,12 @@ void LLPanelPlaceProfile::displaySelectedParcelInfo(LLParcel* parcel,
else
{
// Figure out the owner's name
- gCacheName->get(parcel->getOwnerID(), FALSE,
- boost::bind(&LLPanelPlaceInfo::nameUpdatedCallback, mParcelOwner, _2, _3));
- gCacheName->get(region->getOwner(), FALSE,
- boost::bind(&LLPanelPlaceInfo::nameUpdatedCallback, mRegionOwnerText, _2, _3));
+ std::string parcel_owner =
+ LLSLURL("agent", parcel->getOwnerID(), "inspect").getSLURLString();
+ mParcelOwner->setText(parcel_owner);
+ LLAvatarNameCache::get(region->getOwner(),
+ boost::bind(&LLPanelPlaceInfo::onAvatarNameCache,
+ _1, _2, mRegionOwnerText));
}
if(LLParcel::OS_LEASE_PENDING == parcel->getOwnershipStatus())
@@ -470,9 +474,10 @@ void LLPanelPlaceProfile::displaySelectedParcelInfo(LLParcel* parcel,
const LLUUID& auth_buyer_id = parcel->getAuthorizedBuyerID();
if(auth_buyer_id.notNull())
{
- gCacheName->get(auth_buyer_id, TRUE,
- boost::bind(&LLPanelPlaceInfo::nameUpdatedCallback, mSaleToText, _2, _3));
-
+ LLAvatarNameCache::get(auth_buyer_id,
+ boost::bind(&LLPanelPlaceInfo::onAvatarNameCache,
+ _1, _2, mSaleToText));
+
// Show sales info to a specific person or a group he belongs to.
if (auth_buyer_id != gAgent.getID() && !gAgent.isInGroup(auth_buyer_id))
{
diff --git a/indra/newview/llpanelprofile.h b/indra/newview/llpanelprofile.h
index f1aa3f10f8..be5b440050 100644
--- a/indra/newview/llpanelprofile.h
+++ b/indra/newview/llpanelprofile.h
@@ -33,7 +33,6 @@
#ifndef LL_LLPANELPROFILE_H
#define LL_LLPANELPROFILE_H
-#include "llviewerprecompiledheaders.h"
#include "llpanel.h"
#include "llpanelavatar.h"
diff --git a/indra/newview/llpanelprofileview.cpp b/indra/newview/llpanelprofileview.cpp
index 044036ea50..d22d8d2718 100644
--- a/indra/newview/llpanelprofileview.cpp
+++ b/indra/newview/llpanelprofileview.cpp
@@ -32,11 +32,12 @@
#include "llviewerprecompiledheaders.h"
+#include "llpanelprofileview.h"
+
#include "llavatarconstants.h"
+#include "llavatarnamecache.h" // IDEVO
#include "lluserrelations.h"
-#include "llpanelprofileview.h"
-
#include "llavatarpropertiesprocessor.h"
#include "llcallingcard.h"
#include "llpanelavatar.h"
@@ -104,11 +105,15 @@ void LLPanelProfileView::onOpen(const LLSD& key)
if(id.notNull() && getAvatarId() != id)
{
setAvatarId(id);
+
+ // clear name fields, which might have old data
+ getChild<LLUICtrl>("user_name")->setValue( LLSD() );
+ getChild<LLUICtrl>("user_slid")->setValue( LLSD() );
}
// Update the avatar name.
- gCacheName->get(getAvatarId(), FALSE,
- boost::bind(&LLPanelProfileView::onAvatarNameCached, this, _1, _2, _3, _4));
+ LLAvatarNameCache::get(getAvatarId(),
+ boost::bind(&LLPanelProfileView::onAvatarNameCache, this, _1, _2));
updateOnlineStatus();
@@ -198,10 +203,11 @@ void LLPanelProfileView::processOnlineStatus(bool online)
mStatusText->setValue(status);
}
-void LLPanelProfileView::onAvatarNameCached(const LLUUID& id, const std::string& first_name, const std::string& last_name, BOOL is_group)
+void LLPanelProfileView::onAvatarNameCache(const LLUUID& agent_id,
+ const LLAvatarName& av_name)
{
- llassert(getAvatarId() == id);
- getChild<LLUICtrl>("user_name", FALSE)->setValue(first_name + " " + last_name);
+ getChild<LLUICtrl>("user_name")->setValue( av_name.mDisplayName );
+ getChild<LLUICtrl>("user_slid")->setValue( av_name.mUsername );
}
// EOF
diff --git a/indra/newview/llpanelprofileview.h b/indra/newview/llpanelprofileview.h
index 9b87e146a8..dedb617c27 100644
--- a/indra/newview/llpanelprofileview.h
+++ b/indra/newview/llpanelprofileview.h
@@ -39,6 +39,7 @@
#include "llagent.h"
#include "lltooldraganddrop.h"
+class LLAvatarName;
class LLPanelProfile;
class LLPanelProfileTab;
class LLTextBox;
@@ -99,11 +100,11 @@ protected:
private:
// LLCacheName will call this function when avatar name is loaded from server.
// This is required to display names that have not been cached yet.
- void onAvatarNameCached(
- const LLUUID& id,
- const std::string& first_name,
- const std::string& last_name,
- BOOL is_group);
+// void onNameCache(
+// const LLUUID& id,
+// const std::string& full_name,
+// bool is_group);
+ void onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name);
LLTextBox* mStatusText;
AvatarStatusObserver* mAvatarStatusObserver;
diff --git a/indra/newview/llparticipantlist.cpp b/indra/newview/llparticipantlist.cpp
index f2e6969998..17934afab4 100644
--- a/indra/newview/llparticipantlist.cpp
+++ b/indra/newview/llparticipantlist.cpp
@@ -337,11 +337,18 @@ void LLParticipantList::onAvatarListRefreshed(LLUICtrl* ctrl, const LLSD& param)
if ( item )
{
std::string name = item->getAvatarName();
+ std::string tooltip = item->getAvatarToolTip();
size_t found = name.find(moderator_indicator);
if (found != std::string::npos)
{
name.erase(found, moderator_indicator_len);
- item->setName(name);
+ item->setAvatarName(name);
+ }
+ found = tooltip.find(moderator_indicator);
+ if (found != tooltip.npos)
+ {
+ tooltip.erase(found, moderator_indicator_len);
+ item->setAvatarToolTip(tooltip);
}
}
}
@@ -357,12 +364,20 @@ void LLParticipantList::onAvatarListRefreshed(LLUICtrl* ctrl, const LLSD& param)
if ( item )
{
std::string name = item->getAvatarName();
+ std::string tooltip = item->getAvatarToolTip();
size_t found = name.find(moderator_indicator);
if (found == std::string::npos)
{
name += " ";
name += moderator_indicator;
- item->setName(name);
+ item->setAvatarName(name);
+ }
+ found = tooltip.find(moderator_indicator);
+ if (found == std::string::npos)
+ {
+ tooltip += " ";
+ tooltip += moderator_indicator;
+ item->setAvatarToolTip(tooltip);
}
}
}
diff --git a/indra/newview/llpreviewtexture.cpp b/indra/newview/llpreviewtexture.cpp
index bf18c9e5e7..c4cbbbb791 100644
--- a/indra/newview/llpreviewtexture.cpp
+++ b/indra/newview/llpreviewtexture.cpp
@@ -75,7 +75,8 @@ LLPreviewTexture::LLPreviewTexture(const LLSD& key)
mLastWidth(0),
mAspectRatio(0.f),
mPreviewToSave(FALSE),
- mImage(NULL)
+ mImage(NULL),
+ mImageOldBoostLevel(LLViewerTexture::BOOST_NONE)
{
updateImageID();
if (key.has("save_as"))
@@ -93,7 +94,7 @@ LLPreviewTexture::~LLPreviewTexture()
{
getWindow()->decBusyCount();
}
-
+ mImage->setBoostLevel(mImageOldBoostLevel);
mImage = NULL;
}
@@ -543,6 +544,7 @@ void LLPreviewTexture::onAspectRatioCommit(LLUICtrl* ctrl, void* userdata)
void LLPreviewTexture::loadAsset()
{
mImage = LLViewerTextureManager::getFetchedTexture(mImageID, MIPMAP_TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE);
+ mImageOldBoostLevel = mImage->getBoostLevel();
mImage->setBoostLevel(LLViewerTexture::BOOST_PREVIEW);
mImage->forceToSaveRawImage(0) ;
mAssetStatus = PREVIEW_ASSET_LOADING;
diff --git a/indra/newview/llpreviewtexture.h b/indra/newview/llpreviewtexture.h
index 0f29a741c1..cbdb057781 100644
--- a/indra/newview/llpreviewtexture.h
+++ b/indra/newview/llpreviewtexture.h
@@ -82,9 +82,10 @@ private:
void updateDimensions();
LLUUID mImageID;
LLPointer<LLViewerFetchedTexture> mImage;
- BOOL mLoadingFullImage;
+ S32 mImageOldBoostLevel;
std::string mSaveFileName;
LLFrameTimer mSavedFileTimer;
+ BOOL mLoadingFullImage;
BOOL mShowKeepDiscard;
BOOL mCopyToInv;
@@ -94,11 +95,10 @@ private:
// This is stored off in a member variable, because the save-as
// button and drag and drop functionality need to know.
BOOL mIsCopyable;
-
+ BOOL mUpdateDimensions;
S32 mLastHeight;
S32 mLastWidth;
- F32 mAspectRatio;
- BOOL mUpdateDimensions;
+ F32 mAspectRatio;
LLLoadedCallbackEntry::source_callback_list_t mCallbackTextureList ;
};
diff --git a/indra/newview/llsidepaneliteminfo.cpp b/indra/newview/llsidepaneliteminfo.cpp
index d9870e81c5..153112bc54 100644
--- a/indra/newview/llsidepaneliteminfo.cpp
+++ b/indra/newview/llsidepaneliteminfo.cpp
@@ -281,11 +281,12 @@ void LLSidepanelItemInfo::refreshFromItem(LLViewerInventoryItem* item)
if (item->getCreatorUUID().notNull())
{
- std::string name;
- gCacheName->getFullName(item->getCreatorUUID(), name);
+ LLUUID creator_id = item->getCreatorUUID();
+ std::string name =
+ LLSLURL("agent", creator_id, "completename").getSLURLString();
childSetEnabled("BtnCreator",TRUE);
childSetEnabled("LabelCreatorTitle",TRUE);
- childSetEnabled("LabelCreatorName",TRUE);
+ childSetEnabled("LabelCreatorName",FALSE);
childSetText("LabelCreatorName",name);
}
else
@@ -308,11 +309,12 @@ void LLSidepanelItemInfo::refreshFromItem(LLViewerInventoryItem* item)
}
else
{
- gCacheName->getFullName(perm.getOwner(), name);
+ LLUUID owner_id = perm.getOwner();
+ name = LLSLURL("agent", owner_id, "completename").getSLURLString();
}
childSetEnabled("BtnOwner",TRUE);
childSetEnabled("LabelOwnerTitle",TRUE);
- childSetEnabled("LabelOwnerName",TRUE);
+ childSetEnabled("LabelOwnerName",FALSE);
childSetText("LabelOwnerName",name);
}
else
diff --git a/indra/newview/llsidepaneltaskinfo.cpp b/indra/newview/llsidepaneltaskinfo.cpp
index 3ab71eac64..f71a4a475b 100644
--- a/indra/newview/llsidepaneltaskinfo.cpp
+++ b/indra/newview/llsidepaneltaskinfo.cpp
@@ -351,7 +351,7 @@ void LLSidepanelTaskInfo::refresh()
if (mLabelGroupName)
{
mLabelGroupName->setNameID(LLUUID::null, TRUE);
- mLabelGroupName->refresh(LLUUID::null,LLStringUtil::null, LLStringUtil::null, TRUE);
+ mLabelGroupName->refresh(LLUUID::null, std::string(), true);
mLabelGroupName->setEnabled(FALSE);
}
}
diff --git a/indra/newview/llspeakers.cpp b/indra/newview/llspeakers.cpp
index bf00b47c21..b844d230a1 100644
--- a/indra/newview/llspeakers.cpp
+++ b/indra/newview/llspeakers.cpp
@@ -74,12 +74,13 @@ LLSpeaker::LLSpeaker(const LLUUID& id, const std::string& name, const ESpeakerTy
void LLSpeaker::lookupName()
{
- gCacheName->get(mID, FALSE, boost::bind(&LLSpeaker::onAvatarNameLookup, this, _1, _2, _3, _4));
+ gCacheName->get(mID, false,
+ boost::bind(&LLSpeaker::onNameCache, this, _1, _2, _3));
}
-void LLSpeaker::onAvatarNameLookup(const LLUUID& id, const std::string& first, const std::string& last, BOOL is_group)
+void LLSpeaker::onNameCache(const LLUUID& id, const std::string& full_name, bool is_group)
{
- mDisplayName = first + " " + last;
+ mDisplayName = full_name;
}
bool LLSpeaker::isInVoiceChannel()
diff --git a/indra/newview/llspeakers.h b/indra/newview/llspeakers.h
index 4a250de82f..29638319ad 100644
--- a/indra/newview/llspeakers.h
+++ b/indra/newview/llspeakers.h
@@ -66,7 +66,7 @@ public:
~LLSpeaker() {};
void lookupName();
- void onAvatarNameLookup(const LLUUID& id, const std::string& first, const std::string& last, BOOL is_group);
+ void onNameCache(const LLUUID& id, const std::string& full_name, bool is_group);
bool isInVoiceChannel();
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index 96088fed9c..07e61fcc92 100644
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -52,6 +52,7 @@
#endif
#include "llares.h"
+#include "llavatarnamecache.h"
#include "lllandmark.h"
#include "llcachename.h"
#include "lldir.h"
@@ -269,11 +270,10 @@ void apply_udp_blacklist(const std::string& csv);
bool process_login_success_response();
void transition_back_to_login_panel(const std::string& emsg);
-void callback_cache_name(const LLUUID& id, const std::string& firstname, const std::string& lastname, BOOL is_group)
+void callback_cache_name(const LLUUID& id, const std::string& full_name, bool is_group)
{
- LLNameListCtrl::refreshAll(id, firstname, lastname, is_group);
- LLNameBox::refreshAll(id, firstname, lastname, is_group);
- LLNameEditor::refreshAll(id, firstname, lastname, is_group);
+ LLNameBox::refreshAll(id, full_name, is_group);
+ LLNameEditor::refreshAll(id, full_name, is_group);
// TODO: Actually be intelligent about the refresh.
// For now, just brute force refresh the dialogs.
@@ -1287,16 +1287,7 @@ bool idle_startup()
gXferManager->registerCallbacks(gMessageSystem);
- if ( gCacheName == NULL )
- {
- gCacheName = new LLCacheName(gMessageSystem);
- gCacheName->addObserver(&callback_cache_name);
- gCacheName->LocalizeCacheName("waiting", LLTrans::getString("AvatarNameWaiting"));
- gCacheName->LocalizeCacheName("nobody", LLTrans::getString("AvatarNameNobody"));
- gCacheName->LocalizeCacheName("none", LLTrans::getString("GroupNameNone"));
- // Load stored cache if possible
- LLAppViewer::instance()->loadNameCache();
- }
+ LLStartUp::initNameCache();
// update the voice settings *after* gCacheName initialization
// so that we can construct voice UI that relies on the name cache
@@ -1638,7 +1629,6 @@ bool idle_startup()
LLClassifiedInfo::loadCategories(classified_categories);
}
-
// This method MUST be called before gInventory.findCategoryUUIDForType because of
// gInventory.mIsAgentInvUsable is set to true in the gInventory.buildParentChildMap.
gInventory.buildParentChildMap();
@@ -2689,6 +2679,33 @@ void LLStartUp::fontInit()
LLFontGL::loadDefaultFonts();
}
+void LLStartUp::initNameCache()
+{
+ // Can be called multiple times
+ if ( gCacheName ) return;
+
+ gCacheName = new LLCacheName(gMessageSystem);
+ gCacheName->addObserver(&callback_cache_name);
+ gCacheName->localizeCacheName("waiting", LLTrans::getString("AvatarNameWaiting"));
+ gCacheName->localizeCacheName("nobody", LLTrans::getString("AvatarNameNobody"));
+ gCacheName->localizeCacheName("none", LLTrans::getString("GroupNameNone"));
+ // Load stored cache if possible
+ LLAppViewer::instance()->loadNameCache();
+
+ // Start cache in not-running state until we figure out if we have
+ // capabilities for display name lookup
+ LLAvatarNameCache::initClass(false);
+ LLAvatarNameCache::setUseDisplayNames(gSavedSettings.getBOOL("UseDisplayNames"));
+}
+
+void LLStartUp::cleanupNameCache()
+{
+ LLAvatarNameCache::cleanupClass();
+
+ delete gCacheName;
+ gCacheName = NULL;
+}
+
bool LLStartUp::dispatchURL()
{
// ok, if we've gotten this far and have a startup URL
diff --git a/indra/newview/llstartup.h b/indra/newview/llstartup.h
index cf3c030f08..e73e774a61 100644
--- a/indra/newview/llstartup.h
+++ b/indra/newview/llstartup.h
@@ -93,8 +93,12 @@ public:
// Load default fonts not already loaded at start screen
static void fontInit();
+ static void initNameCache();
+
static void copyLibraryGestures(const std::string& same_gender_gestures);
+ static void cleanupNameCache();
+
// outfit_folder_name can be a folder anywhere in your inventory,
// but the name must be a case-sensitive exact match.
// gender_name is either "male" or "female"
diff --git a/indra/newview/llsyswellwindow.cpp b/indra/newview/llsyswellwindow.cpp
index 1a8c2b8fc0..2020e2aa9f 100644
--- a/indra/newview/llsyswellwindow.cpp
+++ b/indra/newview/llsyswellwindow.cpp
@@ -32,14 +32,15 @@
#include "llviewerprecompiledheaders.h" // must be first include
+#include "llsyswellwindow.h"
+
#include "llagent.h"
+#include "llavatarnamecache.h"
#include "llflatlistview.h"
#include "llfloaterreg.h"
#include "llnotifications.h"
-#include "llsyswellwindow.h"
-
#include "llbottomtray.h"
#include "llscriptfloater.h"
#include "llviewercontrol.h"
@@ -284,14 +285,31 @@ LLIMWellWindow::RowPanel::RowPanel(const LLSysWellWindow* parent, const LLUUID&
mChiclet->setOtherParticipantId(otherParticipantId);
mChiclet->setVisible(true);
- LLTextBox* contactName = getChild<LLTextBox>("contact_name");
- contactName->setValue(name);
+ if (im_chiclet_type == LLIMChiclet::TYPE_IM)
+ {
+ LLAvatarNameCache::get(otherParticipantId,
+ boost::bind(&LLIMWellWindow::RowPanel::onAvatarNameCache,
+ this, _1, _2));
+ }
+ else
+ {
+ LLTextBox* contactName = getChild<LLTextBox>("contact_name");
+ contactName->setValue(name);
+ }
mCloseBtn = getChild<LLButton>("hide_btn");
mCloseBtn->setCommitCallback(boost::bind(&LLIMWellWindow::RowPanel::onClosePanel, this));
}
//---------------------------------------------------------------------------------
+void LLIMWellWindow::RowPanel::onAvatarNameCache(const LLUUID& agent_id,
+ const LLAvatarName& av_name)
+{
+ LLTextBox* contactName = getChild<LLTextBox>("contact_name");
+ contactName->setValue( av_name.getCompleteName() );
+}
+
+//---------------------------------------------------------------------------------
void LLIMWellWindow::RowPanel::onChicletSizeChanged(LLChiclet* ctrl, const LLSD& param)
{
LLTextBox* text = getChild<LLTextBox>("contact_name");
diff --git a/indra/newview/llsyswellwindow.h b/indra/newview/llsyswellwindow.h
index c8215c71ee..9d8fe536e2 100644
--- a/indra/newview/llsyswellwindow.h
+++ b/indra/newview/llsyswellwindow.h
@@ -43,6 +43,7 @@
#include "boost/shared_ptr.hpp"
+class LLAvatarName;
class LLFlatListView;
class LLChiclet;
class LLIMChiclet;
@@ -208,6 +209,7 @@ private:
private:
static const S32 CHICLET_HPAD = 10;
+ void onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name);
void onChicletSizeChanged(LLChiclet* ctrl, const LLSD& param);
void onClosePanel();
public:
diff --git a/indra/newview/lltoastgroupnotifypanel.cpp b/indra/newview/lltoastgroupnotifypanel.cpp
index 7eac3867d5..ab4071110e 100644
--- a/indra/newview/lltoastgroupnotifypanel.cpp
+++ b/indra/newview/lltoastgroupnotifypanel.cpp
@@ -42,6 +42,7 @@
#include "llnotifications.h"
#include "llviewertexteditor.h"
+#include "llavatarnamecache.h"
#include "lluiconstants.h"
#include "llui.h"
#include "llviewercontrol.h"
@@ -73,7 +74,11 @@ LLToastGroupNotifyPanel::LLToastGroupNotifyPanel(LLNotificationPtr& notification
pGroupIcon->setValue(groupData.mInsigniaID);
//header title
- const std::string& from_name = payload["sender_name"].asString();
+ std::string from_name = payload["sender_name"].asString();
+ if (LLAvatarNameCache::useDisplayNames())
+ {
+ from_name = LLCacheName::buildUsername(from_name);
+ }
std::stringstream from;
from << from_name << "/" << groupData.mName;
LLTextBox* pTitleText = getChild<LLTextBox>("title");
diff --git a/indra/newview/lltoastimpanel.cpp b/indra/newview/lltoastimpanel.cpp
index 26d3bd5192..2c5438c47d 100644
--- a/indra/newview/lltoastimpanel.cpp
+++ b/indra/newview/lltoastimpanel.cpp
@@ -147,7 +147,8 @@ void LLToastIMPanel::spawnNameToolTip()
{
// Spawn at right side of the name textbox.
LLRect sticky_rect = mAvatarName->calcScreenRect();
- S32 icon_x = llmin(sticky_rect.mLeft + mAvatarName->getTextPixelWidth() + 3, sticky_rect.mRight - 16);
+ S32 icon_x =
+ llmin(sticky_rect.mLeft + mAvatarName->getTextPixelWidth() + 3, sticky_rect.mRight);
LLCoordGL pos(icon_x, sticky_rect.mTop);
LLToolTip::Params params;
diff --git a/indra/newview/lltoolpie.cpp b/indra/newview/lltoolpie.cpp
index 95c4f01e46..535f41a3aa 100644
--- a/indra/newview/lltoolpie.cpp
+++ b/indra/newview/lltoolpie.cpp
@@ -40,6 +40,7 @@
#include "llagent.h"
#include "llagentcamera.h"
+#include "llavatarnamecache.h"
#include "llviewercontrol.h"
#include "llfocusmgr.h"
//#include "llfirstuse.h"
@@ -861,23 +862,39 @@ BOOL LLToolPie::handleTooltipObject( LLViewerObject* hover_object, std::string l
|| !existing_inspector->getVisible()
|| existing_inspector->getKey()["avatar_id"].asUUID() != hover_object->getID())
{
- std::string avatar_name;
+ // IDEVO: try to get display name + username
+ std::string final_name;
+ std::string full_name;
+ if (!gCacheName->getFullName(hover_object->getID(), full_name))
+ {
LLNameValue* firstname = hover_object->getNVPair("FirstName");
LLNameValue* lastname = hover_object->getNVPair("LastName");
if (firstname && lastname)
{
- avatar_name = llformat("%s %s", firstname->getString(), lastname->getString());
+ full_name = LLCacheName::buildFullName(
+ firstname->getString(), lastname->getString());
+ }
+ else
+ {
+ full_name = LLTrans::getString("TooltipPerson");
+ }
+ }
+ LLAvatarName av_name;
+ if (LLAvatarNameCache::useDisplayNames()
+ && LLAvatarNameCache::get(hover_object->getID(), &av_name))
+ {
+ final_name = av_name.mDisplayName + " (" + av_name.mUsername + ")";
}
else
{
- avatar_name = LLTrans::getString("TooltipPerson");
+ final_name = full_name;
}
// *HACK: We may select this object, so pretend it was clicked
mPick = mHoverPick;
LLInspector::Params p;
p.fillFrom(LLUICtrlFactory::instance().getDefaultParams<LLInspector>());
- p.message(avatar_name);
+ p.message(final_name);
p.image.name("Inspector_I");
p.click_callback(boost::bind(showAvatarInspector, hover_object->getID()));
p.visible_time_near(6.f);
diff --git a/indra/newview/lltracker.cpp b/indra/newview/lltracker.cpp
index cc074287c4..c81a062ade 100644
--- a/indra/newview/lltracker.cpp
+++ b/indra/newview/lltracker.cpp
@@ -570,16 +570,16 @@ void LLTracker::renderBeacon(LLVector3d pos_global,
std::string text;
text = llformat( "%.0f m", to_vec.magVec());
- LLWString wstr;
- wstr += utf8str_to_wstring(label);
- wstr += '\n';
- wstr += utf8str_to_wstring(text);
+ std::string str;
+ str += label;
+ str += '\n';
+ str += text;
hud_textp->setFont(LLFontGL::getFontSansSerif());
hud_textp->setZCompare(FALSE);
hud_textp->setColor(LLColor4(1.f, 1.f, 1.f, llmax(0.2f, llmin(1.f,(dist-FADE_DIST)/FADE_DIST))));
- hud_textp->setString(wstr);
+ hud_textp->setString(str);
hud_textp->setVertAlignment(LLHUDText::ALIGN_VERT_CENTER);
hud_textp->setPositionAgent(pos_agent);
}
diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp
index ab6ff88073..41667007d6 100644
--- a/indra/newview/llviewerdisplay.cpp
+++ b/indra/newview/llviewerdisplay.cpp
@@ -323,7 +323,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
LLImageGL::updateStats(gFrameTimeSeconds);
LLVOAvatar::sRenderName = gSavedSettings.getS32("AvatarNameTagMode");
- LLVOAvatar::sRenderGroupTitles = (gSavedSettings.getBOOL("RenderShowGroupTitleAll") && gSavedSettings.getS32("AvatarNameTagMode"));
+ LLVOAvatar::sRenderGroupTitles = (gSavedSettings.getBOOL("NameTagShowGroupTitles") && gSavedSettings.getS32("AvatarNameTagMode"));
gPipeline.mBackfaceCull = TRUE;
gFrameCount++;
diff --git a/indra/newview/llviewerdisplayname.cpp b/indra/newview/llviewerdisplayname.cpp
new file mode 100644
index 0000000000..bda0fe9737
--- /dev/null
+++ b/indra/newview/llviewerdisplayname.cpp
@@ -0,0 +1,205 @@
+/**
+ * @file llviewerdisplayname.cpp
+ * @brief Wrapper for display name functionality
+ *
+ * $LicenseInfo:firstyear=2010&license=viewergpl$
+ *
+ * Copyright (c) 2010, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+#include "llviewerprecompiledheaders.h"
+
+#include "llviewerdisplayname.h"
+
+// viewer includes
+#include "llagent.h"
+#include "llviewerregion.h"
+#include "llvoavatar.h"
+
+// library includes
+#include "llavatarnamecache.h"
+#include "llhttpclient.h"
+#include "llhttpnode.h"
+#include "llnotificationsutil.h"
+#include "llui.h" // getLanguage()
+
+namespace LLViewerDisplayName
+{
+ // Fired when viewer receives server response to display name change
+ set_name_signal_t sSetDisplayNameSignal;
+}
+
+class LLSetDisplayNameResponder : public LLHTTPClient::Responder
+{
+public:
+ // only care about errors
+ /*virtual*/ void error(U32 status, const std::string& reason)
+ {
+ LLViewerDisplayName::sSetDisplayNameSignal(false, "", LLSD());
+ LLViewerDisplayName::sSetDisplayNameSignal.disconnect_all_slots();
+ }
+};
+
+void LLViewerDisplayName::set(const std::string& display_name, const set_name_slot_t& slot)
+{
+ // TODO: simple validation here
+
+ LLViewerRegion* region = gAgent.getRegion();
+ llassert(region);
+ std::string cap_url = region->getCapability("SetDisplayName");
+ if (cap_url.empty())
+ {
+ // this server does not support display names, report error
+ slot(false, "unsupported", LLSD());
+ return;
+ }
+
+ // People API can return localized error messages. Indicate our
+ // language preference via header.
+ LLSD headers;
+ headers["Accept-Language"] = LLUI::getLanguage();
+
+ // People API requires both the old and new value to change a variable.
+ // Our display name will be in cache before the viewer's UI is available
+ // to request a change, so we can use direct lookup without callback.
+ LLAvatarName av_name;
+ if (!LLAvatarNameCache::get( gAgent.getID(), &av_name))
+ {
+ slot(false, "name unavailable", LLSD());
+ return;
+ }
+
+ // People API expects array of [ "old value", "new value" ]
+ LLSD change_array = LLSD::emptyArray();
+ change_array.append(av_name.mDisplayName);
+ change_array.append(display_name);
+
+ llinfos << "Set name POST to " << cap_url << llendl;
+
+ // Record our caller for when the server sends back a reply
+ sSetDisplayNameSignal.connect(slot);
+
+ // POST the requested change. The sim will not send a response back to
+ // this request directly, rather it will send a separate message after it
+ // communicates with the back-end.
+ LLSD body;
+ body["display_name"] = change_array;
+ LLHTTPClient::post(cap_url, body, new LLSetDisplayNameResponder, headers);
+}
+
+class LLSetDisplayNameReply : public LLHTTPNode
+{
+ LOG_CLASS(LLSetDisplayNameReply);
+public:
+ /*virtual*/ void post(
+ LLHTTPNode::ResponsePtr response,
+ const LLSD& context,
+ const LLSD& input) const
+ {
+ LLSD body = input["body"];
+
+ S32 status = body["status"].asInteger();
+ bool success = (status == 200);
+ std::string reason = body["reason"].asString();
+ LLSD content = body["content"];
+
+ llinfos << "status " << status << " reason " << reason << llendl;
+
+ // If viewer's concept of display name is out-of-date, the set request
+ // will fail with 409 Conflict. If that happens, fetch up-to-date
+ // name information.
+ if (status == 409)
+ {
+ LLUUID agent_id = gAgent.getID();
+ // Flush stale data
+ LLAvatarNameCache::erase( agent_id );
+ // Queue request for new data
+ LLAvatarName ignored;
+ LLAvatarNameCache::get( agent_id, &ignored );
+ // Kill name tag, as it is wrong
+ LLVOAvatar::invalidateNameTag( agent_id );
+ }
+
+ // inform caller of result
+ LLViewerDisplayName::sSetDisplayNameSignal(success, reason, content);
+ LLViewerDisplayName::sSetDisplayNameSignal.disconnect_all_slots();
+ }
+};
+
+
+class LLDisplayNameUpdate : public LLHTTPNode
+{
+ /*virtual*/ void post(
+ LLHTTPNode::ResponsePtr response,
+ const LLSD& context,
+ const LLSD& input) const
+ {
+ LLSD body = input["body"];
+ LLUUID agent_id = body["agent_id"];
+ std::string old_display_name = body["old_display_name"];
+ // By convention this record is called "agent" in the People API
+ LLSD name_data = body["agent"];
+
+ // Inject the new name data into cache
+ LLAvatarName av_name;
+ av_name.fromLLSD( name_data );
+
+ llinfos << "name-update now " << LLDate::now()
+ << " next_update " << LLDate(av_name.mNextUpdate)
+ << llendl;
+
+ // Name expiration time may be provided in headers, or we may use a
+ // default value
+ // *TODO: get actual headers out of ResponsePtr
+ //LLSD headers = response->mHeaders;
+ LLSD headers;
+ av_name.mExpires =
+ LLAvatarNameCache::nameExpirationFromHeaders(headers);
+
+ LLAvatarNameCache::insert(agent_id, av_name);
+
+ // force name tag to update
+ LLVOAvatar::invalidateNameTag(agent_id);
+
+ // Don't show a notification for my name, because we'll show a nicer
+ // dialog
+ if (agent_id != gAgent.getID())
+ {
+ LLSD args;
+ args["OLD_NAME"] = old_display_name;
+ args["SLID"] = av_name.mUsername;
+ args["NEW_NAME"] = av_name.mDisplayName;
+ LLNotificationsUtil::add("DisplayNameUpdate", args);
+ }
+ }
+};
+
+LLHTTPRegistration<LLSetDisplayNameReply>
+ gHTTPRegistrationMessageSetDisplayNameReply(
+ "/message/SetDisplayNameReply");
+
+LLHTTPRegistration<LLDisplayNameUpdate>
+ gHTTPRegistrationMessageDisplayNameUpdate(
+ "/message/DisplayNameUpdate");
diff --git a/indra/newview/llviewerdisplayname.h b/indra/newview/llviewerdisplayname.h
new file mode 100644
index 0000000000..c77388531b
--- /dev/null
+++ b/indra/newview/llviewerdisplayname.h
@@ -0,0 +1,53 @@
+/**
+ * @file llviewerdisplayname.h
+ * @brief Wrapper for display name functionality
+ *
+ * $LicenseInfo:firstyear=2010&license=viewergpl$
+ *
+ * Copyright (c) 2010, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+#ifndef LLVIEWERDISPLAYNAME_H
+#define LLVIEWERDISPLAYNAME_H
+
+#include <boost/signals2.hpp>
+
+class LLSD;
+class LLUUID;
+
+namespace LLViewerDisplayName
+{
+ typedef boost::signals2::signal<
+ void (bool success, const std::string& reason, const LLSD& content)>
+ set_name_signal_t;
+ typedef set_name_signal_t::slot_type set_name_slot_t;
+
+ // Sends an update to the server to change a display name
+ // and call back when done. May not succeed due to service
+ // unavailable or name not available.
+ void set(const std::string& display_name, const set_name_slot_t& slot);
+}
+
+#endif // LLVIEWERDISPLAYNAME_H
diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp
index cbc86c89cc..638d5e8804 100644
--- a/indra/newview/llviewerinventory.cpp
+++ b/indra/newview/llviewerinventory.cpp
@@ -1738,9 +1738,9 @@ PermissionMask LLViewerInventoryItem::getPermissionMask() const
//----------
-void LLViewerInventoryItem::onCallingCardNameLookup(const LLUUID& id, const std::string& first_name, const std::string& last_name)
+void LLViewerInventoryItem::onCallingCardNameLookup(const LLUUID& id, const std::string& name, bool is_group)
{
- rename(first_name + " " + last_name);
+ rename(name);
gInventory.addChangedMask(LLInventoryObserver::LABEL, getUUID());
gInventory.notifyObservers();
}
diff --git a/indra/newview/llviewerinventory.h b/indra/newview/llviewerinventory.h
index 1dd6597388..50d8ea7b6c 100644
--- a/indra/newview/llviewerinventory.h
+++ b/indra/newview/llviewerinventory.h
@@ -163,7 +163,7 @@ public:
PermissionMask getPermissionMask() const;
// callback
- void onCallingCardNameLookup(const LLUUID& id, const std::string& first_name, const std::string& last_name);
+ void onCallingCardNameLookup(const LLUUID& id, const std::string& name, bool is_group);
// If this is a broken link, try to fix it and any other identical link.
BOOL regenerateLink();
diff --git a/indra/newview/llviewerjointattachment.cpp b/indra/newview/llviewerjointattachment.cpp
index 2b4b78d82d..b230203561 100644
--- a/indra/newview/llviewerjointattachment.cpp
+++ b/indra/newview/llviewerjointattachment.cpp
@@ -39,6 +39,7 @@
#include "llviewercontrol.h"
#include "lldrawable.h"
#include "llgl.h"
+#include "llhudtext.h"
#include "llrender.h"
#include "llvoavatar.h"
#include "llvolume.h"
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index 635cc361f3..bf87e58cb6 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -34,6 +34,7 @@
#include "llviewermenu.h"
// linden library includes
+#include "llavatarnamecache.h" // IDEVO
#include "llfloaterreg.h"
#include "llcombobox.h"
#include "llinventorypanel.h"
@@ -2777,9 +2778,8 @@ class LLObjectMute : public view_listener_t
LLNameValue *lastname = avatar->getNVPair("LastName");
if (firstname && lastname)
{
- name = firstname->getString();
- name += " ";
- name += lastname->getString();
+ name = LLCacheName::buildFullName(
+ firstname->getString(), lastname->getString());
}
type = LLMute::AGENT;
@@ -3125,58 +3125,6 @@ bool enable_freeze_eject(const LLSD& avatar_id)
return new_value;
}
-class LLAvatarGiveCard : public view_listener_t
-{
- bool handleEvent(const LLSD& userdata)
- {
- llinfos << "handle_give_card()" << llendl;
- LLViewerObject* dest = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
- if(dest && dest->isAvatar())
- {
- bool found_name = false;
- LLSD args;
- LLSD old_args;
- LLNameValue* nvfirst = dest->getNVPair("FirstName");
- LLNameValue* nvlast = dest->getNVPair("LastName");
- if(nvfirst && nvlast)
- {
- args["FIRST"] = nvfirst->getString();
- args["LAST"] = nvlast->getString();
- old_args["FIRST"] = nvfirst->getString();
- old_args["LAST"] = nvlast->getString();
- found_name = true;
- }
- LLViewerRegion* region = dest->getRegion();
- LLHost dest_host;
- if(region)
- {
- dest_host = region->getHost();
- }
- if(found_name && dest_host.isOk())
- {
- LLMessageSystem* msg = gMessageSystem;
- msg->newMessage("OfferCallingCard");
- msg->nextBlockFast(_PREHASH_AgentData);
- msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
- msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
- msg->nextBlockFast(_PREHASH_AgentBlock);
- msg->addUUIDFast(_PREHASH_DestID, dest->getID());
- LLUUID transaction_id;
- transaction_id.generate();
- msg->addUUIDFast(_PREHASH_TransactionID, transaction_id);
- msg->sendReliable(dest_host);
- LLNotificationsUtil::add("OfferedCard", args);
- }
- else
- {
- LLNotificationsUtil::add("CantOfferCallingCard", old_args);
- }
- }
- return true;
- }
-};
-
-
void login_done(S32 which, void *user)
{
@@ -3586,21 +3534,17 @@ void request_friendship(const LLUUID& dest_id)
LLViewerObject* dest = gObjectList.findObject(dest_id);
if(dest && dest->isAvatar())
{
- std::string fullname;
- LLSD args;
+ std::string full_name;
LLNameValue* nvfirst = dest->getNVPair("FirstName");
LLNameValue* nvlast = dest->getNVPair("LastName");
if(nvfirst && nvlast)
{
- args["FIRST"] = nvfirst->getString();
- args["LAST"] = nvlast->getString();
- fullname = nvfirst->getString();
- fullname += " ";
- fullname += nvlast->getString();
+ full_name = LLCacheName::buildFullName(
+ nvfirst->getString(), nvlast->getString());
}
- if (!fullname.empty())
+ if (!full_name.empty())
{
- LLAvatarActions::requestFriendshipDialog(dest_id, fullname);
+ LLAvatarActions::requestFriendshipDialog(dest_id, full_name);
}
else
{
@@ -7644,6 +7588,16 @@ class LLWorldToggleCameraControls : public view_listener_t
}
};
+void handle_flush_name_caches()
+{
+ // Toggle display names on and off to flush
+ bool use_display_names = LLAvatarNameCache::useDisplayNames();
+ LLAvatarNameCache::setUseDisplayNames(!use_display_names);
+ LLAvatarNameCache::setUseDisplayNames(use_display_names);
+
+ if (gCacheName) gCacheName->clear();
+}
+
class LLUploadCostCalculator : public view_listener_t
{
std::string mCostStr;
@@ -7875,6 +7829,7 @@ void initialize_menus()
view_listener_t::addMenu(new LLAdvancedToggleConsole(), "Advanced.ToggleConsole");
view_listener_t::addMenu(new LLAdvancedCheckConsole(), "Advanced.CheckConsole");
view_listener_t::addMenu(new LLAdvancedDumpInfoToConsole(), "Advanced.DumpInfoToConsole");
+
// Advanced > HUD Info
view_listener_t::addMenu(new LLAdvancedToggleHUDInfo(), "Advanced.ToggleHUDInfo");
view_listener_t::addMenu(new LLAdvancedCheckHUDInfo(), "Advanced.CheckHUDInfo");
@@ -7955,6 +7910,7 @@ void initialize_menus()
view_listener_t::addMenu(new LLAdvancedToggleXUINames(), "Advanced.ToggleXUINames");
view_listener_t::addMenu(new LLAdvancedCheckXUINames(), "Advanced.CheckXUINames");
view_listener_t::addMenu(new LLAdvancedSendTestIms(), "Advanced.SendTestIMs");
+ commit.add("Advanced.FlushNameCaches", boost::bind(&handle_flush_name_caches));
// Advanced > Character > Grab Baked Texture
view_listener_t::addMenu(new LLAdvancedGrabBakedTexture(), "Advanced.GrabBakedTexture");
@@ -8053,7 +8009,6 @@ void initialize_menus()
view_listener_t::addMenu(new LLAvatarDebug(), "Avatar.Debug");
view_listener_t::addMenu(new LLAvatarVisibleDebug(), "Avatar.VisibleDebug");
view_listener_t::addMenu(new LLAvatarInviteToGroup(), "Avatar.InviteToGroup");
- view_listener_t::addMenu(new LLAvatarGiveCard(), "Avatar.GiveCard");
commit.add("Avatar.Eject", boost::bind(&handle_avatar_eject, LLSD()));
view_listener_t::addMenu(new LLAvatarSendIM(), "Avatar.SendIM");
view_listener_t::addMenu(new LLAvatarCall(), "Avatar.Call");
diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp
index 07b6431c92..6c3b165bec 100644
--- a/indra/newview/llviewermessage.cpp
+++ b/indra/newview/llviewermessage.cpp
@@ -34,9 +34,11 @@
#include "llviewermessage.h"
#include "boost/lexical_cast.hpp"
+// Linden libraries
#include "llanimationstates.h"
#include "llaudioengine.h"
#include "llavataractions.h"
+#include "llavatarnamecache.h" // IDEVO HACK
#include "lscript_byteformat.h"
#include "lleconomy.h"
#include "lleventtimer.h"
@@ -84,6 +86,7 @@
#include "llspeakers.h"
#include "lltrans.h"
#include "llviewerfoldertype.h"
+#include "llvoavatar.h" // IDEVO HACK
#include "lluri.h"
#include "llviewergenericmessage.h"
#include "llviewermenu.h"
@@ -132,6 +135,7 @@ extern BOOL gDebugClicks;
// function prototypes
bool check_offer_throttle(const std::string& from_name, bool check_only);
+static void process_money_balance_reply_extended(LLMessageSystem* msg);
//inventory offer throttle globals
LLFrameTimer gThrottleTimer;
@@ -1213,27 +1217,24 @@ bool highlight_offered_object(const LLUUID& obj_id)
}
void inventory_offer_mute_callback(const LLUUID& blocked_id,
- const std::string& first_name,
- const std::string& last_name,
- BOOL is_group, LLOfferInfo* offer = NULL)
+ const std::string& full_name,
+ bool is_group,
+ LLOfferInfo* offer = NULL)
{
- std::string from_name;
+ std::string from_name = full_name;
LLMute::EType type;
if (is_group)
{
type = LLMute::GROUP;
- from_name = first_name;
}
else if(offer && offer->mFromObject)
{
//we have to block object by name because blocked_id is an id of owner
type = LLMute::BY_NAME;
- from_name = offer->mFromName;
}
else
{
type = LLMute::AGENT;
- from_name = first_name + " " + last_name;
}
// id should be null for BY_NAME mute, see LLMuteList::add for details
@@ -1406,7 +1407,7 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD&
// * we can't build two messages at once.
if (2 == button) // Block
{
- gCacheName->get(mFromID, mFromGroup, boost::bind(&inventory_offer_mute_callback,_1,_2,_3,_4,this));
+ gCacheName->get(mFromID, mFromGroup, boost::bind(&inventory_offer_mute_callback,_1,_2,_3,this));
}
std::string from_string; // Used in the pop-up.
@@ -1540,7 +1541,7 @@ bool LLOfferInfo::inventory_task_offer_callback(const LLSD& notification, const
// * we can't build two messages at once.
if (2 == button)
{
- gCacheName->get(mFromID, mFromGroup, boost::bind(&inventory_offer_mute_callback,_1,_2,_3,_4,this));
+ gCacheName->get(mFromID, mFromGroup, boost::bind(&inventory_offer_mute_callback,_1,_2,_3,this));
}
LLMessageSystem* msg = gMessageSystem;
@@ -1588,12 +1589,12 @@ bool LLOfferInfo::inventory_task_offer_callback(const LLSD& notification, const
}
else
{
- std::string first_name, last_name;
- if (gCacheName->getName(mFromID, first_name, last_name))
+ std::string full_name;
+ if (gCacheName->getFullName(mFromID, full_name))
{
from_string = LLTrans::getString("InvOfferAnObjectNamed") + " "+ LLTrans::getString("'") + mFromName
- + LLTrans::getString("'")+" " + LLTrans::getString("InvOfferOwnedBy") + first_name + " " + last_name;
- chatHistory_string = mFromName + " " + LLTrans::getString("InvOfferOwnedBy") + " " + first_name + " " + last_name;
+ + LLTrans::getString("'")+" " + LLTrans::getString("InvOfferOwnedBy") + full_name;
+ chatHistory_string = mFromName + " " + LLTrans::getString("InvOfferOwnedBy") + " " + full_name;
}
else
{
@@ -1797,7 +1798,14 @@ void inventory_offer_handler(LLOfferInfo* info)
payload["give_inventory_notification"] = FALSE;
args["OBJECTFROMNAME"] = info->mFromName;
args["NAME"] = info->mFromName;
- args["NAME_SLURL"] = LLSLURL("agent", info->mFromID, "about").getSLURLString();
+ if (info->mFromGroup)
+ {
+ args["NAME_SLURL"] = LLSLURL("group", info->mFromID, "about").getSLURLString();
+ }
+ else
+ {
+ args["NAME_SLURL"] = LLSLURL("agent", info->mFromID, "about").getSLURLString();
+ }
std::string verb = "select?name=" + LLURI::escape(msg);
args["ITEM_SLURL"] = LLSLURL("inventory", info->mObjectID, verb.c_str()).getSLURLString();
@@ -1917,7 +1925,6 @@ protected:
void modifyNotificationParams()
{
LLSD payload = mParams.payload;
- payload["SESSION_NAME"] = mName;
mParams.payload = payload;
}
};
@@ -1980,6 +1987,99 @@ static bool parse_lure_bucket(const std::string& bucket,
return true;
}
+// Strip out "Resident" for display, but only if the message came from a user
+// (rather than a script)
+static std::string clean_name_from_im(const std::string& name, EInstantMessage type)
+{
+ switch(type)
+ {
+ case IM_NOTHING_SPECIAL:
+ case IM_MESSAGEBOX:
+ case IM_GROUP_INVITATION:
+ case IM_INVENTORY_OFFERED:
+ case IM_INVENTORY_ACCEPTED:
+ case IM_INVENTORY_DECLINED:
+ case IM_GROUP_VOTE:
+ case IM_GROUP_MESSAGE_DEPRECATED:
+ //IM_TASK_INVENTORY_OFFERED
+ //IM_TASK_INVENTORY_ACCEPTED
+ //IM_TASK_INVENTORY_DECLINED
+ case IM_NEW_USER_DEFAULT:
+ case IM_SESSION_INVITE:
+ case IM_SESSION_P2P_INVITE:
+ case IM_SESSION_GROUP_START:
+ case IM_SESSION_CONFERENCE_START:
+ case IM_SESSION_SEND:
+ case IM_SESSION_LEAVE:
+ //IM_FROM_TASK
+ case IM_BUSY_AUTO_RESPONSE:
+ case IM_CONSOLE_AND_CHAT_HISTORY:
+ case IM_LURE_USER:
+ case IM_LURE_ACCEPTED:
+ case IM_LURE_DECLINED:
+ case IM_GODLIKE_LURE_USER:
+ case IM_YET_TO_BE_USED:
+ case IM_GROUP_ELECTION_DEPRECATED:
+ //IM_GOTO_URL
+ //IM_FROM_TASK_AS_ALERT
+ case IM_GROUP_NOTICE:
+ case IM_GROUP_NOTICE_INVENTORY_ACCEPTED:
+ case IM_GROUP_NOTICE_INVENTORY_DECLINED:
+ case IM_GROUP_INVITATION_ACCEPT:
+ case IM_GROUP_INVITATION_DECLINE:
+ case IM_GROUP_NOTICE_REQUESTED:
+ case IM_FRIENDSHIP_OFFERED:
+ case IM_FRIENDSHIP_ACCEPTED:
+ case IM_FRIENDSHIP_DECLINED_DEPRECATED:
+ //IM_TYPING_START
+ //IM_TYPING_STOP
+ return LLCacheName::cleanFullName(name);
+ default:
+ return name;
+ }
+}
+
+static std::string clean_name_from_task_im(const std::string& msg,
+ BOOL from_group)
+{
+ boost::smatch match;
+ static const boost::regex returned_exp(
+ "(.*been returned to your inventory lost and found folder by )(.+)( (from|near).*)");
+ if (boost::regex_match(msg, match, returned_exp))
+ {
+ // match objects are 1-based for groups
+ std::string final = match[1].str();
+ std::string name = match[2].str();
+ // Don't try to clean up group names
+ if (!from_group)
+ {
+ if (LLAvatarNameCache::useDisplayNames())
+ {
+ // ...just convert to username
+ final += LLCacheName::buildUsername(name);
+ }
+ else
+ {
+ // ...strip out legacy "Resident" name
+ final += LLCacheName::cleanFullName(name);
+ }
+ }
+ final += match[3].str();
+ return final;
+ }
+ return msg;
+}
+
+void notification_display_name_callback(const LLUUID& id,
+ const LLAvatarName& av_name,
+ const std::string& name,
+ LLSD& substitutions,
+ const LLSD& payload)
+{
+ substitutions["NAME"] = av_name.mDisplayName;
+ LLNotificationsUtil::add(name, substitutions, payload);
+}
+
class LLPostponedIMSystemTipNotification: public LLPostponedNotification
{
protected:
@@ -1990,8 +2090,28 @@ protected:
payload["SESSION_NAME"] = mName;
mParams.payload = payload;
}
+
};
+// Callback for name resolution of a god/estate message
+void god_message_name_cb(const LLAvatarName& av_name, LLChat chat, std::string message)
+{
+ LLSD args;
+ args["NAME"] = av_name.getCompleteName();
+ args["MESSAGE"] = message;
+ LLNotificationsUtil::add("GodMessage", args);
+
+ // Treat like a system message and put in chat history.
+ chat.mText = av_name.getCompleteName() + ": " + message;
+
+ LLNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance<LLNearbyChat>("nearby_chat", LLSD());
+ if(nearby_chat)
+ {
+ nearby_chat->addMessage(chat);
+ }
+
+}
+
void process_improved_im(LLMessageSystem *msg, void **user_data)
{
if (gNoRender)
@@ -2039,6 +2159,8 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
{
name = LLTrans::getString("Unnamed");
}
+ // IDEVO convert new-style "Resident" names for display
+ name = clean_name_from_im(name, dialog);
BOOL is_busy = gAgent.getBusy();
BOOL is_muted = LLMuteList::getInstance()->isMuted(from_id, name, LLMute::flagTextChat);
@@ -2068,7 +2190,6 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
{
case IM_CONSOLE_AND_CHAT_HISTORY:
args["MESSAGE"] = message;
- args["NAME"] = name;
payload["from_id"] = from_id;
params.name = "IMSystemMessageTip";
@@ -2138,21 +2259,9 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
}
else if (to_id.isNull())
{
- // Message to everyone from GOD
- args["NAME"] = name;
- args["MESSAGE"] = message;
- LLNotificationsUtil::add("GodMessage", args);
-
- // Treat like a system message and put in chat history.
- // Claim to be from a local agent so it doesn't go into
- // console.
- chat.mText = name + separator_string + message;
-
- LLNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance<LLNearbyChat>("nearby_chat", LLSD());
- if(nearby_chat)
- {
- nearby_chat->addMessage(chat);
- }
+ // Message to everyone from GOD, look up the fullname since
+ // server always slams name to legacy names
+ LLAvatarNameCache::get(from_id, boost::bind(god_message_name_cb, _2, chat, message));
}
else
{
@@ -2350,6 +2459,15 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
invite_bucket = (struct invite_bucket_t*) &binary_bucket[0];
S32 membership_fee = ntohl(invite_bucket->membership_fee);
+ // IDEVO Clean up legacy name "Resident" in message constructed in
+ // lldatagroups.cpp
+ U32 pos = message.find(" has invited you to join a group.\n");
+ if (pos != std::string::npos)
+ {
+ // use cleaned-up name from above
+ message = name + message.substr(pos);
+ }
+
LLSD payload;
payload["transaction_id"] = session_id;
payload["group_id"] = from_id;
@@ -2537,6 +2655,9 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
chat.mSourceType = CHAT_SOURCE_SYSTEM;
}
+ // IDEVO Some messages have embedded resident names
+ message = clean_name_from_task_im(message, from_group);
+
LLSD query_string;
query_string["owner"] = from_id;
query_string["slurl"] = location;
@@ -2585,7 +2706,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
params.substitutions = substitutions;
params.payload = payload;
- LLPostponedNotification::add<LLPostponedServerObjectNotification>(params, from_id, false);
+ LLPostponedNotification::add<LLPostponedServerObjectNotification>(params, from_id, from_group);
}
break;
case IM_FROM_TASK_AS_ALERT:
@@ -2745,7 +2866,12 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
args["NAME"] = name;
LLSD payload;
payload["from_id"] = from_id;
- LLNotificationsUtil::add("FriendshipAccepted", args, payload);
+ LLAvatarNameCache::get(from_id, boost::bind(&notification_display_name_callback,
+ _1,
+ _2,
+ "FriendshipAccepted",
+ args,
+ payload));
}
break;
@@ -2849,9 +2975,8 @@ void process_offer_callingcard(LLMessageSystem* msg, void**)
LLNameValue* nvlast = source->getNVPair("LastName");
if (nvfirst && nvlast)
{
- args["FIRST"] = nvfirst->getString();
- args["LAST"] = nvlast->getString();
- source_name = std::string(nvfirst->getString()) + " " + nvlast->getString();
+ source_name = LLCacheName::buildFullName(
+ nvfirst->getString(), nvlast->getString());
}
}
@@ -2884,7 +3009,6 @@ void process_decline_callingcard(LLMessageSystem* msg, void**)
LLNotificationsUtil::add("CallingCardDeclined");
}
-
void process_chat_from_simulator(LLMessageSystem *msg, void **user_data)
{
LLChat chat;
@@ -2900,7 +3024,6 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data)
LLViewerObject* chatter;
msg->getString("ChatData", "FromName", from_name);
- chat.mFromName = from_name;
msg->getUUID("ChatData", "SourceID", from_id);
chat.mFromID = from_id;
@@ -2919,6 +3042,27 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data)
chat.mTime = LLFrameTimer::getElapsedSeconds();
+ // IDEVO Correct for new-style "Resident" names
+ if (chat.mSourceType == CHAT_SOURCE_AGENT)
+ {
+ // I don't know if it's OK to change this here, if
+ // anything downstream does lookups by name, for instance
+ LLAvatarName av_name;
+ if (LLAvatarNameCache::useDisplayNames()
+ && LLAvatarNameCache::get(from_id, &av_name))
+ {
+ chat.mFromName = av_name.mDisplayName;
+ }
+ else
+ {
+ chat.mFromName = LLCacheName::cleanFullName(from_name);
+ }
+ }
+ else
+ {
+ chat.mFromName = from_name;
+ }
+
BOOL is_busy = gAgent.getBusy();
BOOL is_muted = FALSE;
@@ -4775,168 +4919,271 @@ void process_time_dilation(LLMessageSystem *msg, void **user_data)
*/
-
void process_money_balance_reply( LLMessageSystem* msg, void** )
{
S32 balance = 0;
S32 credit = 0;
S32 committed = 0;
std::string desc;
+ LLUUID tid;
+ msg->getUUID("MoneyData", "TransactionID", tid);
msg->getS32("MoneyData", "MoneyBalance", balance);
msg->getS32("MoneyData", "SquareMetersCredit", credit);
msg->getS32("MoneyData", "SquareMetersCommitted", committed);
msg->getStringFast(_PREHASH_MoneyData, _PREHASH_Description, desc);
LL_INFOS("Messaging") << "L$, credit, committed: " << balance << " " << credit << " "
<< committed << LL_ENDL;
-
+
if (gStatusBar)
{
- // S32 old_balance = gStatusBar->getBalance();
-
- // This is an update, not the first transmission of balance
- /* if (old_balance != 0)
- {
- // this is actually an update
- if (balance > old_balance)
- {
- LLFirstUse::useBalanceIncrease(balance - old_balance);
- }
- else if (balance < old_balance)
- {
- LLFirstUse::useBalanceDecrease(balance - old_balance);
- }
- }
- */
gStatusBar->setBalance(balance);
gStatusBar->setLandCredit(credit);
gStatusBar->setLandCommitted(committed);
}
- LLUUID tid;
- msg->getUUID("MoneyData", "TransactionID", tid);
+ if (desc.empty()
+ || !gSavedSettings.getBOOL("NotifyMoneyChange"))
+ {
+ // ...nothing to display
+ return;
+ }
+
+ // Suppress duplicate messages about the same transaction
static std::deque<LLUUID> recent;
- if(!desc.empty() && gSavedSettings.getBOOL("NotifyMoneyChange")
- && (std::find(recent.rbegin(), recent.rend(), tid) == recent.rend()))
+ if (std::find(recent.rbegin(), recent.rend(), tid) != recent.rend())
{
- // Make the user confirm the transaction, since they might
- // have missed something during an event.
- // *TODO: Translate
- LLSD args;
-
+ return;
+ }
- // this is a marker to retrieve avatar name from server message:
- // "<avatar name> paid you L$"
- const std::string marker = "paid you L$";
+ // Once the 'recent' container gets large enough, chop some
+ // off the beginning.
+ const U32 MAX_LOOKBACK = 30;
+ const S32 POP_FRONT_SIZE = 12;
+ if(recent.size() > MAX_LOOKBACK)
+ {
+ LL_DEBUGS("Messaging") << "Removing oldest transaction records" << LL_ENDL;
+ recent.erase(recent.begin(), recent.begin() + POP_FRONT_SIZE);
+ }
+ //LL_DEBUGS("Messaging") << "Pushing back transaction " << tid << LL_ENDL;
+ recent.push_back(tid);
+ if (msg->has("TransactionInfo"))
+ {
+ // ...message has extended info for localization
+ process_money_balance_reply_extended(msg);
+ }
+ else
+ {
+ // Only old dev grids will not supply the TransactionInfo block,
+ // so we can just use the hard-coded English string.
+ LLSD args;
args["MESSAGE"] = desc;
+ LLNotificationsUtil::add("SystemMessage", args);
+ }
+}
- // extract avatar name from system message
- S32 marker_pos = desc.find(marker, 0);
+static std::string reason_from_transaction_type(S32 transaction_type,
+ const std::string& item_desc)
+{
+ // *NOTE: The keys for the reason strings are unusual because
+ // an earlier version of the code used English language strings
+ // extracted from hard-coded server English descriptions.
+ // Keeping them so we don't have to re-localize them.
+ switch (transaction_type)
+ {
+ case TRANS_OBJECT_SALE:
+ {
+ LLStringUtil::format_map_t arg;
+ arg["ITEM"] = item_desc;
+ return LLTrans::getString("for item", arg);
+ }
+ case TRANS_LAND_SALE:
+ return LLTrans::getString("for a parcel of land");
+
+ case TRANS_LAND_PASS_SALE:
+ return LLTrans::getString("for a land access pass");
+
+ case TRANS_GROUP_LAND_DEED:
+ return LLTrans::getString("for deeding land");
+
+ case TRANS_GROUP_CREATE:
+ return LLTrans::getString("to create a group");
+
+ case TRANS_GROUP_JOIN:
+ return LLTrans::getString("to join a group");
+
+ case TRANS_UPLOAD_CHARGE:
+ return LLTrans::getString("to upload");
- std::string base_name = desc.substr(0, marker_pos);
-
- std::string name = base_name;
- LLStringUtil::trim(name);
+ case TRANS_CLASSIFIED_CHARGE:
+ return LLTrans::getString("to publish a classified ad");
+
+ // These have no reason to display, but are expected and should not
+ // generate warnings
+ case TRANS_GIFT:
+ case TRANS_PAY_OBJECT:
+ case TRANS_OBJECT_PAYS:
+ return std::string();
- // if name extracted and name cache contains avatar id send loggable notification
- LLUUID from_id;
- if(name.size() > 0 && gCacheName->getUUID(name, from_id))
- {
- //description always comes not localized. lets fix this
+ default:
+ llwarns << "Unknown transaction type "
+ << transaction_type << llendl;
+ return std::string();
+ }
+}
- //ammount paid
- std::string ammount = desc.substr(marker_pos + marker.length(),desc.length() - marker.length() - marker_pos);
-
- //reform description
- LLStringUtil::format_map_t str_args;
- str_args["NAME"] = base_name;
- str_args["AMOUNT"] = ammount;
- std::string new_description = LLTrans::getString("paid_you_ldollars", str_args);
+static void money_balance_group_notify(const LLUUID& group_id,
+ const std::string& name,
+ bool is_group,
+ std::string notification,
+ LLSD args,
+ LLSD payload)
+{
+ // Message uses name SLURLs, don't actually have to substitute in
+ // the name. We're just making sure it's available.
+ // Notification is either PaymentReceived or PaymentSent
+ LLNotificationsUtil::add(notification, args, payload);
+}
+static void money_balance_avatar_notify(const LLUUID& agent_id,
+ const LLAvatarName& av_name,
+ std::string notification,
+ LLSD args,
+ LLSD payload)
+{
+ // Message uses name SLURLs, don't actually have to substitute in
+ // the name. We're just making sure it's available.
+ // Notification is either PaymentReceived or PaymentSent
+ LLNotificationsUtil::add(notification, args, payload);
+}
- args["MESSAGE"] = new_description;
- args["NAME"] = name;
- LLSD payload;
- payload["from_id"] = from_id;
- LLNotificationsUtil::add("PaymentRecived", args, payload);
+static void process_money_balance_reply_extended(LLMessageSystem* msg)
+{
+ // Added in server 1.40 and viewer 2.1, support for localization
+ // and agent ids for name lookup.
+ S32 transaction_type = 0;
+ LLUUID source_id;
+ BOOL is_source_group = FALSE;
+ LLUUID dest_id;
+ BOOL is_dest_group = FALSE;
+ S32 amount = 0;
+ std::string item_description;
+
+ msg->getS32("TransactionInfo", "TransactionType", transaction_type);
+ msg->getUUID("TransactionInfo", "SourceID", source_id);
+ msg->getBOOL("TransactionInfo", "IsSourceGroup", is_source_group);
+ msg->getUUID("TransactionInfo", "DestID", dest_id);
+ msg->getBOOL("TransactionInfo", "IsDestGroup", is_dest_group);
+ msg->getS32("TransactionInfo", "Amount", amount);
+ msg->getString("TransactionInfo", "ItemDescription", item_description);
+ LL_INFOS("Money") << "MoneyBalanceReply source " << source_id
+ << " dest " << dest_id
+ << " type " << transaction_type
+ << " item " << item_description << LL_ENDL;
+
+ if (source_id.isNull() && dest_id.isNull())
+ {
+ // this is a pure balance update, no notification required
+ return;
+ }
+
+ const char* source_type = (is_source_group ? "group" : "agent");
+ std::string source_slurl =
+ LLSLURL( source_type, source_id, "inspect").getSLURLString();
+
+ const char* dest_type = (is_dest_group ? "group" : "agent");
+ std::string dest_slurl =
+ LLSLURL( dest_type, dest_id, "completename").getSLURLString();
+
+ std::string reason =
+ reason_from_transaction_type(transaction_type, item_description);
+
+ LLStringUtil::format_map_t args;
+ args["REASON"] = reason; // could be empty
+ args["AMOUNT"] = llformat("%d", amount);
+
+ // Need to delay until name looked up, so need to know whether or not
+ // is group
+ bool is_name_group = false;
+ LLUUID name_id;
+ std::string message;
+ std::string notification;
+ LLSD final_args;
+ LLSD payload;
+
+ bool you_paid_someone = (source_id == gAgentID);
+ if (you_paid_someone)
+ {
+ args["NAME"] = dest_slurl;
+ is_name_group = is_dest_group;
+ name_id = dest_id;
+ if (!reason.empty())
+ {
+ if (dest_id.notNull())
+ {
+ message = LLTrans::getString("you_paid_ldollars", args);
+ }
+ else
+ {
+ // transaction fee to the system, eg, to create a group
+ message = LLTrans::getString("you_paid_ldollars_no_name", args);
+ }
}
- //AD *HACK: Parsing incoming string to localize messages that come from server! EXT-5986
- // It's only a temporarily and ineffective measure. It doesn't affect performance much
- // because we get here only for specific type of messages, but anyway it is not right to do it!
- // *TODO: Server-side changes should be made and this code removed.
else
{
- if(desc.find("You paid")==0)
+ if (dest_id.notNull())
{
- // Regular expression for message parsing- change it in case of server-side changes.
- // Each set of parenthesis will later be used to find arguments of message we generate
- // in the end of this if- (.*) gives us name of money receiver, (\\d+)-amount of money we pay
- // and ([^$]*)- reason of payment
- boost::regex expr("You paid (?:.{0}|(.*) )L\\$(\\d+)\\s?([^$]*)\\.");
- boost::match_results <std::string::const_iterator> matches;
- if(boost::regex_match(desc, matches, expr))
- {
- // Name of full localizable notification string
- // there are four types of this string- with name of receiver and reason of payment,
- // without name and without reason (both may also be absent simultaneously).
- // example of string without name - You paid L$100 to create a group.
- // example of string without reason - You paid Smdby Linden L$100.
- // example of string with reason and name - You paid Smbdy Linden L$100 for a land access pass.
- // example of string with no info - You paid L$50.
- std::string line = "you_paid_ldollars_no_name";
-
- // arguments of string which will be in notification
- LLStringUtil::format_map_t str_args;
-
- // extracting amount of money paid (without L$ symbols). It is always present.
- str_args["[AMOUNT]"] = std::string(matches[2]);
-
- // extracting name of person/group you are paying (it may be absent)
- std::string name = std::string(matches[1]);
- if(!name.empty())
- {
- str_args["[NAME]"] = name;
- line = "you_paid_ldollars";
- }
-
- // extracting reason of payment (it may be absent)
- std::string reason = std::string(matches[3]);
- if (reason.empty())
- {
- line = name.empty() ? "you_paid_ldollars_no_info" : "you_paid_ldollars_no_reason";
- }
- else
- {
- std::string localized_reason;
- // if we haven't found localized string for reason of payment leave it as it was
- str_args["[REASON]"] = LLTrans::findString(localized_reason, reason) ? localized_reason : reason;
- }
-
- // forming final message string by retrieving localized version from xml
- // and applying previously found arguments
- line = LLTrans::getString(line, str_args);
- args["MESSAGE"] = line;
- }
+ message = LLTrans::getString("you_paid_ldollars_no_reason", args);
+ }
+ else
+ {
+ // no target, no reason, you just paid money
+ message = LLTrans::getString("you_paid_ldollars_no_info", args);
}
-
- LLNotificationsUtil::add("SystemMessage", args);
}
-
- // Once the 'recent' container gets large enough, chop some
- // off the beginning.
- const U32 MAX_LOOKBACK = 30;
- const S32 POP_FRONT_SIZE = 12;
- if(recent.size() > MAX_LOOKBACK)
+ final_args["MESSAGE"] = message;
+ notification = "PaymentSent";
+ }
+ else {
+ // ...someone paid you
+ args["NAME"] = source_slurl;
+ is_name_group = is_source_group;
+ name_id = source_id;
+ if (!reason.empty())
{
- LL_DEBUGS("Messaging") << "Removing oldest transaction records" << LL_ENDL;
- recent.erase(recent.begin(), recent.begin() + POP_FRONT_SIZE);
+ message = LLTrans::getString("paid_you_ldollars", args);
+ }
+ else {
+ message = LLTrans::getString("paid_you_ldollars_no_reason", args);
}
- //LL_DEBUGS("Messaging") << "Pushing back transaction " << tid << LL_ENDL;
- recent.push_back(tid);
+ final_args["MESSAGE"] = message;
+
+ // make notification loggable
+ payload["from_id"] = source_id;
+ notification = "PaymentReceived";
+ }
+
+ // Despite using SLURLs, wait until the name is available before
+ // showing the notification, otherwise the UI layout is strange and
+ // the user sees a "Loading..." message
+ if (is_name_group)
+ {
+ gCacheName->getGroup(name_id,
+ boost::bind(&money_balance_group_notify,
+ _1, _2, _3,
+ notification, final_args, payload));
+ }
+ else {
+ LLAvatarNameCache::get(name_id,
+ boost::bind(&money_balance_avatar_notify,
+ _1, _2,
+ notification, final_args, payload));
}
}
+
+
bool handle_special_notification_callback(const LLSD& notification, const LLSD& response)
{
S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
@@ -5178,7 +5425,7 @@ void handle_show_mean_events(void *)
//LLFloaterBump::showInstance();
}
-void mean_name_callback(const LLUUID &id, const std::string& first, const std::string& last, BOOL always_false)
+void mean_name_callback(const LLUUID &id, const std::string& full_name, bool is_group)
{
if (gNoRender)
{
@@ -5200,8 +5447,7 @@ void mean_name_callback(const LLUUID &id, const std::string& first, const std::s
LLMeanCollisionData *mcd = *iter;
if (mcd->mPerp == id)
{
- mcd->mFirstName = first;
- mcd->mLastName = last;
+ mcd->mFullName = full_name;
}
}
}
@@ -5255,8 +5501,7 @@ void process_mean_collision_alert_message(LLMessageSystem *msgsystem, void **use
{
LLMeanCollisionData *mcd = new LLMeanCollisionData(gAgentID, perp, time, type, mag);
gMeanCollisionList.push_front(mcd);
- const BOOL is_group = FALSE;
- gCacheName->get(perp, is_group, &mean_name_callback);
+ gCacheName->get(perp, false, boost::bind(&mean_name_callback, _1, _2, _3));
}
}
}
@@ -5478,7 +5723,7 @@ void process_script_question(LLMessageSystem *msg, void **user_data)
// so we'll reuse the same namespace for both throttle types.
std::string throttle_name = owner_name;
std::string self_name;
- LLAgentUI::buildName( self_name );
+ LLAgentUI::buildFullname( self_name );
if( owner_name == self_name )
{
throttle_name = taskid.getString();
@@ -5514,7 +5759,7 @@ void process_script_question(LLMessageSystem *msg, void **user_data)
S32 count = 0;
LLSD args;
args["OBJECTNAME"] = object_name;
- args["NAME"] = owner_name;
+ args["NAME"] = LLCacheName::cleanFullName(owner_name);
// check the received permission flags against each permission
for (S32 i = 0; i < SCRIPT_PERMISSION_EOF; i++)
@@ -5907,15 +6152,14 @@ bool handle_lure_callback(const LLSD& notification, const LLSD& response)
// Record the offer.
{
std::string target_name;
- gCacheName->getFullName(target_id, target_name);
+ gCacheName->getFullName(target_id, target_name); // for im log filenames
LLSD args;
- args["TO_NAME"] = target_name;
+ args["TO_NAME"] = LLSLURL("agent", target_id, "displayname").getSLURLString();;
LLSD payload;
//*TODO please rewrite all keys to the same case, lower or upper
payload["from_id"] = target_id;
- payload["SESSION_NAME"] = target_name;
payload["SUPPRESS_TOAST"] = true;
LLNotificationsUtil::add("TeleportOfferSent", args, payload);
}
@@ -6129,8 +6373,7 @@ void process_script_dialog(LLMessageSystem* msg, void**)
LLNotificationPtr notification;
if (!first_name.empty())
{
- args["FIRST"] = first_name;
- args["LAST"] = last_name;
+ args["NAME"] = LLCacheName::buildFullName(first_name, last_name);
notification = LLNotifications::instance().add(
LLNotification::Params("ScriptDialog").substitutions(args).payload(payload).form_elements(form.asLLSD()));
}
@@ -6163,7 +6406,7 @@ static LLNotificationFunctorRegistration callback_load_url_reg("LoadWebPage", ca
// We've got the name of the person who owns the object hurling the url.
// Display confirmation dialog.
-void callback_load_url_name(const LLUUID& id, const std::string& first, const std::string& last, BOOL is_group)
+void callback_load_url_name(const LLUUID& id, const std::string& full_name, bool is_group)
{
std::vector<LLSD>::iterator it;
for (it = gLoadUrlList.begin(); it != gLoadUrlList.end(); )
@@ -6176,11 +6419,11 @@ void callback_load_url_name(const LLUUID& id, const std::string& first, const st
std::string owner_name;
if (is_group)
{
- owner_name = first + LLTrans::getString("Group");
+ owner_name = full_name + LLTrans::getString("Group");
}
else
{
- owner_name = first + " " + last;
+ owner_name = full_name;
}
// For legacy name-only mutes.
@@ -6240,7 +6483,8 @@ void process_load_url(LLMessageSystem* msg, void**)
// Add to list of pending name lookups
gLoadUrlList.push_back(payload);
- gCacheName->get(owner_id, owner_is_group, &callback_load_url_name);
+ gCacheName->get(owner_id, owner_is_group,
+ boost::bind(&callback_load_url_name, _1, _2, _3));
}
diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp
index 6d93de2383..5655eed5c4 100644
--- a/indra/newview/llviewerobject.cpp
+++ b/indra/newview/llviewerobject.cpp
@@ -69,6 +69,7 @@
#include "llface.h"
#include "llfloaterproperties.h"
#include "llfollowcam.h"
+#include "llhudtext.h"
#include "llselectmgr.h"
#include "llrendersphere.h"
#include "lltooldraganddrop.h"
@@ -79,6 +80,7 @@
#include "llviewerparceloverlay.h"
#include "llviewerpartsource.h"
#include "llviewerregion.h"
+#include "llviewerstats.h"
#include "llviewertextureanim.h"
#include "llviewerwindow.h" // For getSpinAxis
#include "llvoavatar.h"
@@ -1097,7 +1099,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
// alpha was flipped so that it zero encoded better
coloru.mV[3] = 255 - coloru.mV[3];
mText->setColor(LLColor4(coloru));
- mText->setStringUTF8(temp_string);
+ mText->setString(temp_string);
if (mDrawable.notNull())
{
@@ -1489,7 +1491,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
dp->unpackBinaryDataFixed(coloru.mV, 4, "Color");
coloru.mV[3] = 255 - coloru.mV[3];
mText->setColor(LLColor4(coloru));
- mText->setStringUTF8(temp_string);
+ mText->setString(temp_string);
setChanged(TEXTURE);
}
@@ -1916,6 +1918,12 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
avatar->clampAttachmentPositions();
}
+
+ // If we're snapping the position by more than 0.5m, update LLViewerStats::mAgentPositionSnaps
+ if ( asAvatar() && asAvatar()->isSelf() && (mag_sqr > 0.25f) )
+ {
+ LLViewerStats::getInstance()->mAgentPositionSnaps.push( diff.length() );
+ }
}
if (new_rot != mLastRot
@@ -4149,7 +4157,7 @@ void LLViewerObject::setDebugText(const std::string &utf8text)
mText->setOnHUDAttachment(isHUDAttachment());
}
mText->setColor(LLColor4::white);
- mText->setStringUTF8(utf8text);
+ mText->setString(utf8text);
mText->setZCompare(FALSE);
mText->setDoFade(FALSE);
updateText();
diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h
index be83fb7ef8..346f33727f 100644
--- a/indra/newview/llviewerobject.h
+++ b/indra/newview/llviewerobject.h
@@ -37,7 +37,6 @@
#include "llassetstorage.h"
#include "lldarrayptr.h"
-#include "llhudtext.h"
#include "llhudicon.h"
#include "llinventory.h"
#include "llrefcount.h"
@@ -60,6 +59,7 @@ class LLColor4;
class LLFrameTimer;
class LLDrawable;
class LLHost;
+class LLHUDText;
class LLWorld;
class LLNameValue;
class LLNetMap;
diff --git a/indra/newview/llviewerobjectlist.cpp b/indra/newview/llviewerobjectlist.cpp
index fc94fbafac..7e5fa2f84d 100644
--- a/indra/newview/llviewerobjectlist.cpp
+++ b/indra/newview/llviewerobjectlist.cpp
@@ -53,7 +53,7 @@
#include "lltooltip.h"
#include "llworld.h"
#include "llstring.h"
-#include "llhudtext.h"
+#include "llhudnametag.h"
#include "lldrawable.h"
#include "xform.h"
#include "llsky.h"
@@ -1201,7 +1201,7 @@ void LLViewerObjectList::generatePickList(LLCamera &camera)
}
}
- LLHUDText::addPickable(mSelectPickList);
+ LLHUDNameTag::addPickable(mSelectPickList);
for (std::vector<LLCharacter*>::iterator iter = LLCharacter::sInstances.begin();
iter != LLCharacter::sInstances.end(); ++iter)
diff --git a/indra/newview/llviewerparcelmgr.cpp b/indra/newview/llviewerparcelmgr.cpp
index a591cc1e14..8e1ce03964 100644
--- a/indra/newview/llviewerparcelmgr.cpp
+++ b/indra/newview/llviewerparcelmgr.cpp
@@ -2075,10 +2075,7 @@ void LLViewerParcelMgr::deedLandToGroup()
args["GROUP_NAME"] = group_name;
if(mCurrentParcel->getContributeWithDeed())
{
- std::string first_name, last_name;
- gCacheName->getName(mCurrentParcel->getOwnerID(), first_name, last_name);
- args["FIRST_NAME"] = first_name;
- args["LAST_NAME"] = last_name;
+ args["NAME"] = LLSLURL("agent", mCurrentParcel->getOwnerID(), "completename").getSLURLString();
LLNotificationsUtil::add("DeedLandToGroupWithContribution",args, LLSD(), deedAlertCB);
}
else
diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp
index da240cedbb..56bc0b383c 100644
--- a/indra/newview/llviewerregion.cpp
+++ b/indra/newview/llviewerregion.cpp
@@ -34,7 +34,9 @@
#include "llviewerregion.h"
+// linden libraries
#include "indra_constants.h"
+#include "llavatarnamecache.h" // name lookup cap url
#include "llfloaterreg.h"
#include "llmath.h"
#include "llhttpclient.h"
@@ -174,7 +176,9 @@ public:
mRegion->showReleaseNotes();
}
}
-
+
+ mRegion->setCapabilitiesReceived(true);
+
if (STATE_SEED_GRANTED_WAIT == LLStartUp::getStartupState())
{
LLStartUp::setStartupState( STATE_SEED_CAP_GRANTED );
@@ -232,7 +236,8 @@ LLViewerRegion::LLViewerRegion(const U64 &handle,
// LLCapabilityListener binds all the globals it expects to need at
// construction time.
mCapabilityListener(host.getString(), gMessageSystem, *this,
- gAgent.getID(), gAgent.getSessionID())
+ gAgent.getID(), gAgent.getSessionID()),
+ mCapabilitiesReceived(false)
{
mWidth = region_width_meters;
mOriginGlobal = from_region_handle(handle);
@@ -1486,6 +1491,7 @@ void LLViewerRegion::setSeedCapability(const std::string& url)
LLSD capabilityNames = LLSD::emptyArray();
capabilityNames.append("AttachmentResources");
+ capabilityNames.append("AvatarPickerSearch");
capabilityNames.append("ChatSessionRequest");
capabilityNames.append("CopyInventoryFromNotecard");
capabilityNames.append("DispatchRegionInfo");
@@ -1496,6 +1502,7 @@ void LLViewerRegion::setSeedCapability(const std::string& url)
capabilityNames.append("ObjectMediaNavigate");
capabilityNames.append("FetchLib");
capabilityNames.append("FetchLibDescendents");
+ capabilityNames.append("GetDisplayNames");
capabilityNames.append("GetTexture");
capabilityNames.append("GroupProposalBallot");
capabilityNames.append("HomeLocation");
@@ -1517,6 +1524,7 @@ void LLViewerRegion::setSeedCapability(const std::string& url)
capabilityNames.append("SendUserReport");
capabilityNames.append("SendUserReportWithScreenshot");
capabilityNames.append("ServerReleaseNotes");
+ capabilityNames.append("SetDisplayName");
capabilityNames.append("StartGroupProposal");
capabilityNames.append("TextureStats");
capabilityNames.append("UntrustedSimulatorMessage");
@@ -1578,6 +1586,16 @@ std::string LLViewerRegion::getCapability(const std::string& name) const
return iter->second;
}
+bool LLViewerRegion::capabilitiesReceived() const
+{
+ return mCapabilitiesReceived;
+}
+
+void LLViewerRegion::setCapabilitiesReceived(bool received)
+{
+ mCapabilitiesReceived = received;
+}
+
void LLViewerRegion::logActiveCapabilities() const
{
int count = 0;
diff --git a/indra/newview/llviewerregion.h b/indra/newview/llviewerregion.h
index a9e7ef771c..b0169c33c0 100644
--- a/indra/newview/llviewerregion.h
+++ b/indra/newview/llviewerregion.h
@@ -235,6 +235,11 @@ public:
void setCapability(const std::string& name, const std::string& url);
// implements LLCapabilityProvider
virtual std::string getCapability(const std::string& name) const;
+
+ // has region received its final (not seed) capability list?
+ bool capabilitiesReceived() const;
+ void setCapabilitiesReceived(bool received);
+
static bool isSpecialCapabilityName(const std::string &name);
void logActiveCapabilities() const;
@@ -417,6 +422,7 @@ private:
private:
bool mAlive; // can become false if circuit disconnects
+ bool mCapabilitiesReceived;
//spatial partitions for objects in this region
std::vector<LLSpatialPartition*> mObjectPartition;
diff --git a/indra/newview/llviewerstats.cpp b/indra/newview/llviewerstats.cpp
index bdc34d0f18..a706e77f19 100644
--- a/indra/newview/llviewerstats.cpp
+++ b/indra/newview/llviewerstats.cpp
@@ -280,6 +280,8 @@ LLViewerStats::LLViewerStats() :
{
mStats[ST_HAS_BAD_TIMER] = 1.0;
}
+
+ mAgentPositionSnaps.reset();
}
LLViewerStats::~LLViewerStats()
@@ -299,6 +301,8 @@ void LLViewerStats::resetStats()
LLViewerStats::getInstance()->mPacketsOutStat.reset();
LLViewerStats::getInstance()->mFPSStat.reset();
LLViewerStats::getInstance()->mTexturePacketsStat.reset();
+
+ LLViewerStats::getInstance()->mAgentPositionSnaps.reset();
}
@@ -393,6 +397,10 @@ void LLViewerStats::addToMessage(LLSD &body) const
<< llendl;
}
}
+
+ body["AgentPositionSnaps"] = mAgentPositionSnaps.getData();
+ llinfos << "STAT: AgentPositionSnaps: Mean = " << mAgentPositionSnaps.getMean() << "; StdDev = " << mAgentPositionSnaps.getStdDev()
+ << "; Count = " << mAgentPositionSnaps.getCount() << llendl;
}
// static
diff --git a/indra/newview/llviewerstats.h b/indra/newview/llviewerstats.h
index 13d73000d2..694eeaf097 100644
--- a/indra/newview/llviewerstats.h
+++ b/indra/newview/llviewerstats.h
@@ -197,6 +197,61 @@ public:
void addToMessage(LLSD &body) const;
+ struct StatsAccumulator
+ {
+ S32 mCount;
+ F32 mSum;
+ F32 mSumOfSquares;
+ U32 mCountOfNextUpdatesToIgnore;
+
+ inline void push( F32 val )
+ {
+ if ( mCountOfNextUpdatesToIgnore > 0 )
+ {
+ mCountOfNextUpdatesToIgnore--;
+ return;
+ }
+
+ mCount++;
+ mSum += val;
+ mSumOfSquares += val * val;
+ }
+
+ inline F32 getMean() const
+ {
+ return (mCount == 0) ? 0.f : ((F32)mSum)/mCount;
+ }
+
+ inline F32 getStdDev() const
+ {
+ const F32 mean = getMean();
+ return (mCount == 0) ? 0.f : sqrt( mSumOfSquares/mCount - (mean * mean) );
+ }
+
+ inline U32 getCount() const
+ {
+ return mCount;
+ }
+
+ inline void reset()
+ {
+ mCount = 0;
+ mSum = mSumOfSquares = 0.f;
+ mCountOfNextUpdatesToIgnore = 0;
+ }
+
+ inline LLSD getData() const
+ {
+ LLSD data;
+ data["mean"] = getMean();
+ data["std_dev"] = getStdDev();
+ data["count"] = (S32)mCount;
+ return data;
+ }
+ };
+
+ StatsAccumulator mAgentPositionSnaps;
+
private:
F64 mStats[ST_COUNT];
diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp
index 0afbce7d51..75bb9f84e2 100644
--- a/indra/newview/llviewertexture.cpp
+++ b/indra/newview/llviewertexture.cpp
@@ -495,6 +495,7 @@ LLViewerTexture::LLViewerTexture(const U32 width, const U32 height, const U8 com
mFullHeight = height ;
mUseMipMaps = usemipmaps ;
mComponents = components ;
+ setTexelsPerImage();
mID.generate();
sImageCount++;
@@ -522,6 +523,7 @@ void LLViewerTexture::init(bool firstinit)
mFullWidth = 0;
mFullHeight = 0;
+ mTexelsPerImage = 0 ;
mUseMipMaps = FALSE ;
mComponents = 0 ;
@@ -530,7 +532,7 @@ void LLViewerTexture::init(bool firstinit)
mMaxVirtualSize = 0.f;
mNeedsGLTexture = FALSE ;
mMaxVirtualSizeResetInterval = 1;
- mMaxVirtualSizeResetCounter = 1 ;
+ mMaxVirtualSizeResetCounter = mMaxVirtualSizeResetInterval ;
mAdditionalDecodePriority = 0.f ;
mParcelMedia = NULL ;
mNumFaces = 0 ;
@@ -838,7 +840,8 @@ BOOL LLViewerTexture::createGLTexture(S32 discard_level, const LLImageRaw* image
{
mFullWidth = mGLTexturep->getCurrentWidth() ;
mFullHeight = mGLTexturep->getCurrentHeight() ;
- mComponents = mGLTexturep->getComponents() ;
+ mComponents = mGLTexturep->getComponents() ;
+ setTexelsPerImage();
}
return ret ;
@@ -1056,9 +1059,16 @@ void LLViewerTexture::destroyGLTexture()
}
}
+void LLViewerTexture::setTexelsPerImage()
+{
+ S32 fullwidth = llmin(mFullWidth,(S32)MAX_IMAGE_SIZE_DEFAULT);
+ S32 fullheight = llmin(mFullHeight,(S32)MAX_IMAGE_SIZE_DEFAULT);
+ mTexelsPerImage = (F32)fullwidth * fullheight;
+}
+
BOOL LLViewerTexture::isLargeImage()
{
- return mFullWidth * mFullHeight > LLViewerTexture::sMinLargeImageSize ;
+ return (S32)mTexelsPerImage > LLViewerTexture::sMinLargeImageSize ;
}
//virtual
@@ -1415,6 +1425,7 @@ BOOL LLViewerFetchedTexture::createTexture(S32 usename/*= 0*/)
mFullWidth = mRawImage->getWidth();
mFullHeight = mRawImage->getHeight();
+ setTexelsPerImage();
}
else
{
@@ -1619,11 +1630,7 @@ F32 LLViewerFetchedTexture::calcDecodePriority()
{
// priority range = 100,000 - 500,000
S32 desired_discard = mDesiredDiscardLevel;
- if (getDontDiscard())
- {
- desired_discard -= 2;
- }
- else if (!isJustBound() && mCachedRawImageReady)
+ if (!isJustBound() && mCachedRawImageReady)
{
if(mBoostLevel < BOOST_HIGH)
{
@@ -1639,7 +1646,7 @@ F32 LLViewerFetchedTexture::calcDecodePriority()
S32 ddiscard = cur_discard - desired_discard;
ddiscard = llclamp(ddiscard, -1, MAX_DELTA_DISCARD_LEVEL_FOR_PRIORITY);
- priority = (ddiscard + 1) * PRIORITY_DELTA_DISCARD_LEVEL_FACTOR;
+ priority = (ddiscard + 1) * PRIORITY_DELTA_DISCARD_LEVEL_FACTOR;
}
// Priority Formula:
@@ -1647,19 +1654,51 @@ F32 LLViewerFetchedTexture::calcDecodePriority()
// [10,000,000] + [1,000,000-9,000,000] + [100,000-500,000] + [1-20,000] + [0-999]
if (priority > 0.0f)
{
+ bool large_enough = mCachedRawImageReady && ((S32)mTexelsPerImage > sMinLargeImageSize) ;
+ if(large_enough)
+ {
+ //Note:
+ //to give small, low-priority textures some chance to be fetched,
+ //cut the priority in half if the texture size is larger than 256 * 256 and has a 64*64 ready.
+ priority *= 0.5f ;
+ }
+
pixel_priority = llclamp(pixel_priority, 0.0f, MAX_PRIORITY_PIXEL);
priority += pixel_priority + PRIORITY_BOOST_LEVEL_FACTOR * mBoostLevel;
if ( mBoostLevel > BOOST_HIGH)
{
- priority += PRIORITY_BOOST_HIGH_FACTOR;
+ if(mBoostLevel > BOOST_SUPER_HIGH)
+ {
+ //for very important textures, always grant the highest priority.
+ priority += PRIORITY_BOOST_HIGH_FACTOR;
+ }
+ else if(mCachedRawImageReady)
+ {
+ //Note:
+ //to give small, low-priority textures some chance to be fetched,
+ //if high priority texture has a 64*64 ready, lower its fetching priority.
+ setAdditionalDecodePriority(0.5f) ;
+ }
+ else
+ {
+ priority += PRIORITY_BOOST_HIGH_FACTOR;
+ }
}
if(mAdditionalDecodePriority > 0.0f)
{
// priority range += 1,000,000.f-9,000,000.f
- priority += PRIORITY_ADDITIONAL_FACTOR * (1.0 + mAdditionalDecodePriority * MAX_ADDITIONAL_LEVEL_FOR_PRIORITY);
+ F32 additional = PRIORITY_ADDITIONAL_FACTOR * (1.0 + mAdditionalDecodePriority * MAX_ADDITIONAL_LEVEL_FOR_PRIORITY);
+ if(large_enough)
+ {
+ //Note:
+ //to give small, low-priority textures some chance to be fetched,
+ //cut the additional priority to a quarter if the texture size is larger than 256 * 256 and has a 64*64 ready.
+ additional *= 0.25f ;
+ }
+ priority += additional;
}
}
return priority;
@@ -1702,11 +1741,6 @@ void LLViewerFetchedTexture::updateVirtualSize()
addTextureStats(0.f, FALSE) ;//reset
}
- if(mForceToSaveRawImage)
- {
- setAdditionalDecodePriority(0.75f) ; //boost the fetching priority
- }
-
for(U32 i = 0 ; i < mNumFaces ; i++)
{
LLFace* facep = mFaceList[i] ;
@@ -1819,6 +1853,7 @@ bool LLViewerFetchedTexture::updateFetch()
{
mFullWidth = mRawImage->getWidth() << mRawDiscardLevel;
mFullHeight = mRawImage->getHeight() << mRawDiscardLevel;
+ setTexelsPerImage();
if(mFullWidth > MAX_IMAGE_SIZE || mFullHeight > MAX_IMAGE_SIZE)
{
@@ -2887,10 +2922,6 @@ void LLViewerLODTexture::processTextureStats()
//static const F64 log_2 = log(2.0);
static const F64 log_4 = log(4.0);
- S32 fullwidth = llmin(mFullWidth,(S32)MAX_IMAGE_SIZE_DEFAULT);
- S32 fullheight = llmin(mFullHeight,(S32)MAX_IMAGE_SIZE_DEFAULT);
- mTexelsPerImage = (F32)fullwidth * fullheight;
-
F32 discard_level = 0.f;
// If we know the output width and height, we can force the discard
diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h
index 8b69408e4b..b33d04e8dd 100644
--- a/indra/newview/llviewertexture.h
+++ b/indra/newview/llviewertexture.h
@@ -126,15 +126,16 @@ public:
BOOST_HIGH = 10,
BOOST_BUMP ,
BOOST_TERRAIN , // has to be high priority for minimap / low detail
- BOOST_SELECTED ,
- BOOST_HUD ,
+ BOOST_SELECTED ,
BOOST_AVATAR_BAKED_SELF ,
+ BOOST_AVATAR_SELF , // needed for baking avatar
+ BOOST_SUPER_HIGH , //textures higher than this need to be downloaded at the required resolution without delay.
+ BOOST_HUD ,
BOOST_ICON ,
BOOST_UI ,
BOOST_PREVIEW ,
BOOST_MAP ,
- BOOST_MAP_VISIBLE ,
- BOOST_AVATAR_SELF , // needed for baking avatar
+ BOOST_MAP_VISIBLE ,
BOOST_MAX_LEVEL,
//other texture Categories
@@ -268,6 +269,7 @@ protected:
void init(bool firstinit) ;
void reorganizeFaceList() ;
void reorganizeVolumeList() ;
+ void setTexelsPerImage();
private:
//note: do not make this function public.
/*virtual*/ LLImageGL* getGLTexture() const ;
@@ -280,6 +282,7 @@ protected:
S32 mFullHeight;
BOOL mUseMipMaps ;
S8 mComponents;
+ F32 mTexelsPerImage; // Texels per image.
mutable S8 mNeedsGLTexture;
mutable F32 mMaxVirtualSize; // The largest virtual size of the image, in pixels - how much data to we need?
mutable S32 mMaxVirtualSizeResetCounter ;
@@ -598,8 +601,6 @@ private:
void scaleDown() ;
private:
-
- F32 mTexelsPerImage; // Texels per image.
F32 mDiscardVirtualSize; // Virtual size used to calculate desired discard
F32 mCalculatedDiscardLevel; // Last calculated discard level
};
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index 6346ac320b..4cc3902078 100644
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -120,6 +120,7 @@
#include "llglheaders.h"
#include "lltooltip.h"
#include "llhudmanager.h"
+#include "llhudobject.h"
#include "llhudview.h"
#include "llimagebmp.h"
#include "llimagej2c.h"
@@ -1178,12 +1179,8 @@ BOOL LLViewerWindow::handlePaint(LLWindow *window, S32 x, S32 y, S32 width, S
//SetBKColor(hdc, RGB(255, 255, 255));
FillRect(hdc, &wnd_rect, CreateSolidBrush(RGB(255, 255, 255)));
- std::string name_str;
- LLAgentUI::buildName(name_str);
-
std::string temp_str;
- temp_str = llformat( "%s FPS %3.1f Phy FPS %2.1f Time Dil %1.3f", /* Flawfinder: ignore */
- name_str.c_str(),
+ temp_str = llformat( "FPS %3.1f Phy FPS %2.1f Time Dil %1.3f", /* Flawfinder: ignore */
LLViewerStats::getInstance()->mFPSStat.getMeanPerSec(),
LLViewerStats::getInstance()->mSimPhysicsFPS.getPrev(0),
LLViewerStats::getInstance()->mSimTimeDilation.getPrev(0));
@@ -1877,7 +1874,7 @@ void LLViewerWindow::reshape(S32 width, S32 height)
// clear font width caches
if (display_scale_changed)
{
- LLHUDText::reshape();
+ LLHUDObject::reshapeAll();
}
sendShapeToSim();
@@ -4064,7 +4061,7 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei
send_agent_pause();
//rescale fonts
initFonts(scale_factor);
- LLHUDText::reshape();
+ LLHUDObject::reshapeAll();
}
S32 output_buffer_offset_y = 0;
@@ -4193,7 +4190,7 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei
if (high_res)
{
initFonts(1.f);
- LLHUDText::reshape();
+ LLHUDObject::reshapeAll();
}
// Pre-pad image to number of pixels such that the line length is a multiple of 4 bytes (for BMP encoding)
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 47e35ca0c4..d7360d8b3e 100644
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -44,6 +44,7 @@
#include <ctype.h>
#include "llaudioengine.h"
+#include "llcachename.h"
#include "noise.h"
#include "sound_ids.h"
@@ -51,8 +52,10 @@
#include "llagentcamera.h"
#include "llagentwearables.h"
#include "llanimationstates.h"
+#include "llavatarnamecache.h"
#include "llavatarpropertiesprocessor.h"
#include "llviewercontrol.h"
+#include "llcallingcard.h" // IDEVO for LLAvatarTracker
#include "lldrawpoolavatar.h"
#include "lldriverparam.h"
#include "lleditingmotion.h"
@@ -61,6 +64,8 @@
#include "llheadrotmotion.h"
#include "llhudeffecttrail.h"
#include "llhudmanager.h"
+#include "llhudnametag.h"
+#include "llhudtext.h" // for mText/mDebugText
#include "llkeyframefallmotion.h"
#include "llkeyframestandmotion.h"
#include "llkeyframewalkmotion.h"
@@ -659,12 +664,14 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id,
mAppearanceAnimating(FALSE),
mNameString(),
mTitle(),
- mNameAway(FALSE),
- mNameBusy(FALSE),
- mNameMute(FALSE),
+ mNameAway(false),
+ mNameBusy(false),
+ mNameMute(false),
+ mNameAppearance(false),
+ mNameFriend(false),
+ mNameAlpha(0.f),
mRenderGroupTitles(sRenderGroupTitles),
- mNameAppearance(FALSE),
- mNameCloud(FALSE),
+ mNameCloud(false),
mFirstTEMessageReceived( FALSE ),
mFirstAppearanceMessageReceived( FALSE ),
mCulled( FALSE ),
@@ -2782,8 +2789,18 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last)
&& gSavedSettings.getS32("AvatarNameTagMode") ));
}
- if ( render_name )
+ if ( !render_name )
{
+ if (mNameText)
+ {
+ // ...clean up old name tag
+ mNameText->markDead();
+ mNameText = NULL;
+ sNumVisibleChatBubbles--;
+ }
+ return;
+ }
+
BOOL new_name = FALSE;
if (visible_chat != mVisibleChat)
{
@@ -2799,7 +2816,6 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last)
// First Calculate Alpha
// If alpha > 0, create mNameText if necessary, otherwise delete it
- {
F32 alpha = 0.f;
if (mAppAngle > 5.f)
{
@@ -2820,66 +2836,62 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last)
alpha = (mAppAngle-2.f)/3.f;
}
- if (alpha > 0.f)
+ if (alpha <= 0.f)
{
+ if (mNameText)
+ {
+ mNameText->markDead();
+ mNameText = NULL;
+ sNumVisibleChatBubbles--;
+ }
+ return;
+ }
+
if (!mNameText)
{
- mNameText = (LLHUDText *)LLHUDObject::addHUDObject(LLHUDObject::LL_HUD_TEXT);
- mNameText->setMass(10.f);
+ mNameText = static_cast<LLHUDNameTag*>( LLHUDObject::addHUDObject(
+ LLHUDObject::LL_HUD_NAME_TAG) );
+ //mNameText->setMass(10.f);
mNameText->setSourceObject(this);
- mNameText->setVertAlignment(LLHUDText::ALIGN_VERT_TOP);
+ mNameText->setVertAlignment(LLHUDNameTag::ALIGN_VERT_TOP);
mNameText->setVisibleOffScreen(TRUE);
mNameText->setMaxLines(11);
mNameText->setFadeDistance(CHAT_NORMAL_RADIUS, 5.f);
- mNameText->setUseBubble(TRUE);
sNumVisibleChatBubbles++;
new_name = TRUE;
}
- LLColor4 avatar_name_color = LLUIColorTable::instance().getColor( "AvatarNameColor" );
- avatar_name_color.setAlpha(alpha);
- mNameText->setColor(avatar_name_color);
+ LLVector3 name_position = idleUpdateNameTagPosition(root_pos_last);
+ mNameText->setPositionAgent(name_position);
- LLQuaternion root_rot = mRoot.getWorldRotation();
- mNameText->setUsePixelSize(TRUE);
- LLVector3 pixel_right_vec;
- LLVector3 pixel_up_vec;
- LLViewerCamera::getInstance()->getPixelVectors(root_pos_last, pixel_up_vec, pixel_right_vec);
- LLVector3 camera_to_av = root_pos_last - LLViewerCamera::getInstance()->getOrigin();
- camera_to_av.normalize();
- LLVector3 local_camera_at = camera_to_av * ~root_rot;
- LLVector3 local_camera_up = camera_to_av % LLViewerCamera::getInstance()->getLeftAxis();
- local_camera_up.normalize();
- local_camera_up = local_camera_up * ~root_rot;
+ idleUpdateNameTagText(new_name);
- local_camera_up.scaleVec(mBodySize * 0.5f);
- local_camera_at.scaleVec(mBodySize * 0.5f);
+ idleUpdateNameTagAlpha(new_name, alpha);
+}
- LLVector3 name_position = mRoot.getWorldPosition() +
- (local_camera_up * root_rot) -
- (projected_vec(local_camera_at * root_rot, camera_to_av));
- name_position += pixel_up_vec * 15.f;
- mNameText->setPositionAgent(name_position);
- }
- else if (mNameText)
+void LLVOAvatar::idleUpdateNameTagText(BOOL new_name)
{
- mNameText->markDead();
- mNameText = NULL;
- sNumVisibleChatBubbles--;
- }
- }
-
LLNameValue *title = getNVPair("Title");
LLNameValue* firstname = getNVPair("FirstName");
LLNameValue* lastname = getNVPair("LastName");
- if (mNameText.notNull() && firstname && lastname)
+ // Avatars must have a first and last name
+ if (!firstname || !lastname) return;
+
+ bool is_away = mSignaledAnimations.find(ANIM_AGENT_AWAY) != mSignaledAnimations.end();
+ bool is_busy = mSignaledAnimations.find(ANIM_AGENT_BUSY) != mSignaledAnimations.end();
+ bool is_appearance = mSignaledAnimations.find(ANIM_AGENT_CUSTOMIZE) != mSignaledAnimations.end();
+ bool is_muted;
+ if (isSelf())
+ {
+ is_muted = false;
+ }
+ else
{
- const BOOL is_away = mSignaledAnimations.find(ANIM_AGENT_AWAY) != mSignaledAnimations.end();
- const BOOL is_busy = mSignaledAnimations.find(ANIM_AGENT_BUSY) != mSignaledAnimations.end();
- const BOOL is_appearance = mSignaledAnimations.find(ANIM_AGENT_CUSTOMIZE) != mSignaledAnimations.end();
- const BOOL is_muted = isSelf() ? FALSE : LLMuteList::getInstance()->isMuted(getID());
- const BOOL is_cloud = getIsCloud();
+ is_muted = LLMuteList::getInstance()->isMuted(getID());
+ }
+ bool is_friend = LLAvatarTracker::instance().isBuddy(getID());
+ bool is_cloud = getIsCloud();
if (gSavedSettings.getBOOL("DebugAvatarRezTime"))
{
@@ -2904,105 +2916,129 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last)
}
}
- if (mNameString.empty() ||
- new_name ||
- (!title && !mTitle.empty()) ||
- (title && mTitle != title->getString()) ||
- (is_away != mNameAway || is_busy != mNameBusy || is_muted != mNameMute)
+ // Rebuild name tag if state change detected
+ if (mNameString.empty()
+ || new_name
+ || (!title && !mTitle.empty())
+ || (title && mTitle != title->getString())
+ || is_away != mNameAway
+ || is_busy != mNameBusy
+ || is_muted != mNameMute
|| is_appearance != mNameAppearance
- || is_cloud != mNameCloud
- )
- {
- std::string line;
- if (!sRenderGroupTitles)
- {
- // If all group titles are turned off, stack first name
- // on a line above last name
- line += firstname->getString();
- line += "\n";
- }
- else if (title && title->getString() && title->getString()[0] != '\0')
- {
- line += title->getString();
- LLStringFn::replace_ascii_controlchars(line,LL_UNKNOWN_CHAR);
- line += "\n";
- line += firstname->getString();
- }
- else
+ || is_friend != mNameFriend
+ || is_cloud != mNameCloud)
{
- line += firstname->getString();
- }
+ LLColor4 name_tag_color = getNameTagColor(is_friend);
- line += " ";
- line += lastname->getString();
- BOOL need_comma = FALSE;
+ clearNameTag();
- if (is_away || is_muted || is_busy)
+ if (is_away || is_muted || is_busy || is_appearance)
{
- line += " (";
+ std::string line;
if (is_away)
{
line += LLTrans::getString("AvatarAway");
- need_comma = TRUE;
+ line += ", ";
}
if (is_busy)
{
- if (need_comma)
+ line += LLTrans::getString("AvatarBusy");
+ line += ", ";
+ }
+ if (is_muted)
{
+ line += LLTrans::getString("AvatarMuted");
line += ", ";
}
- line += LLTrans::getString("AvatarBusy");
- need_comma = TRUE;
+ if (is_appearance)
+ {
+ line += LLTrans::getString("AvatarEditingAppearance");
+ line += ", ";
}
- if (is_muted)
+ if (is_cloud)
{
- if (need_comma)
+ line += LLTrans::getString("LoadingData");
+ line += ", ";
+ }
+ // trim last ", "
+ line.resize( line.length() - 2 );
+ LLColor4 status_color =
+ LLUIColorTable::getInstance()->getColor("NameTagStatus");
+ addNameTagLine(line, status_color, LLFontGL::NORMAL,
+ LLFontGL::getFontSansSerifSmall());
+ }
+
+ if (sRenderGroupTitles
+ && title && title->getString() && title->getString()[0] != '\0')
{
- line += ", ";
+ LLColor4 group_color =
+ LLUIColorTable::getInstance()->getColor("NameTagGroup");
+ std::string title_str = title->getString();
+ LLStringFn::replace_ascii_controlchars(title_str,LL_UNKNOWN_CHAR);
+ addNameTagLine(title_str, group_color, LLFontGL::NORMAL,
+ LLFontGL::getFontSansSerifSmall());
}
- line += LLTrans::getString("AvatarMuted");
- need_comma = TRUE;
+
+ static LLUICachedControl<bool> show_display_names("NameTagShowDisplayNames");
+ static LLUICachedControl<bool> show_usernames("NameTagShowUsernames");
+
+ if (LLAvatarNameCache::useDisplayNames())
+ {
+ LLAvatarName av_name;
+ if (!LLAvatarNameCache::get(getID(), &av_name))
+ {
+ // ...call this function back when the name arrives
+ // and force a rebuild
+ LLAvatarNameCache::get(getID(),
+ boost::bind(&LLVOAvatar::clearNameTag, this));
}
- line += ")";
+
+ // Might be blank if name not available yet, that's OK
+ if (show_display_names)
+ {
+ addNameTagLine(av_name.mDisplayName, name_tag_color, LLFontGL::NORMAL,
+ LLFontGL::getFontSansSerif());
}
- if (is_cloud)
+ // Suppress SLID display if display name matches exactly (ugh)
+ if (show_usernames && !av_name.mIsDisplayNameDefault)
{
- line += "\n";
- line += "(" + LLTrans::getString("LoadingData") + ")";
+ // *HACK: Desaturate the color
+ LLColor4 username_color = name_tag_color * 0.83f;
+ addNameTagLine(av_name.mUsername, username_color, LLFontGL::NORMAL,
+ LLFontGL::getFontSansSerifSmall());
+ }
}
- else if (is_appearance)
+ else
{
- line += "\n";
- line += LLTrans::getString("AvatarEditingAppearance");
+ const LLFontGL* font = LLFontGL::getFontSansSerif();
+ std::string full_name =
+ LLCacheName::buildFullName( firstname->getString(), lastname->getString() );
+ addNameTagLine(full_name, name_tag_color, LLFontGL::NORMAL, font);
}
+
mNameAway = is_away;
mNameBusy = is_busy;
mNameMute = is_muted;
mNameAppearance = is_appearance;
+ mNameFriend = is_friend;
mNameCloud = is_cloud;
mTitle = title ? title->getString() : "";
LLStringFn::replace_ascii_controlchars(mTitle,LL_UNKNOWN_CHAR);
- mNameString = utf8str_to_wstring(line);
new_name = TRUE;
}
- if (visible_chat)
+ if (mVisibleChat)
{
- mNameText->setDropShadow(TRUE);
mNameText->setFont(LLFontGL::getFontSansSerif());
- mNameText->setTextAlignment(LLHUDText::ALIGN_TEXT_LEFT);
+ mNameText->setTextAlignment(LLHUDNameTag::ALIGN_TEXT_LEFT);
mNameText->setFadeDistance(CHAT_NORMAL_RADIUS * 2.f, 5.f);
- if (new_name)
- {
- mNameText->setLabel(mNameString);
- }
char line[MAX_STRING]; /* Flawfinder: ignore */
line[0] = '\0';
std::deque<LLChat>::iterator chat_iter = mChats.begin();
mNameText->clearString();
- LLColor4 new_chat = LLUIColorTable::instance().getColor( "AvatarNameColor" );
+ LLColor4 new_chat = LLUIColorTable::instance().getColor( "NameTagChat" );
LLColor4 normal_chat = lerp(new_chat, LLColor4(0.8f, 0.8f, 0.8f, 1.f), 0.7f);
LLColor4 old_chat = lerp(normal_chat, LLColor4(0.6f, 0.6f, 0.6f, 1.f), 0.7f);
if (mTyping && mChats.size() >= MAX_BUBBLE_CHAT_UTTERANCES)
@@ -3029,17 +3065,17 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last)
if (chat_fade_amt < 1.f)
{
F32 u = clamp_rescale(chat_fade_amt, 0.9f, 1.f, 0.f, 1.f);
- mNameText->addLine(utf8str_to_wstring(chat_iter->mText), lerp(new_chat, normal_chat, u), style);
+ mNameText->addLine(chat_iter->mText, lerp(new_chat, normal_chat, u), style);
}
else if (chat_fade_amt < 2.f)
{
F32 u = clamp_rescale(chat_fade_amt, 1.9f, 2.f, 0.f, 1.f);
- mNameText->addLine(utf8str_to_wstring(chat_iter->mText), lerp(normal_chat, old_chat, u), style);
+ mNameText->addLine(chat_iter->mText, lerp(normal_chat, old_chat, u), style);
}
else if (chat_fade_amt < 3.f)
{
// *NOTE: only remove lines down to minimum number
- mNameText->addLine(utf8str_to_wstring(chat_iter->mText), old_chat, style);
+ mNameText->addLine(chat_iter->mText, old_chat, style);
}
}
mNameText->setVisibleOffScreen(TRUE);
@@ -3064,24 +3100,129 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last)
}
else
{
- mNameText->setFont(LLFontGL::getFontSansSerif());
- mNameText->setTextAlignment(LLHUDText::ALIGN_TEXT_CENTER);
+ // ...not using chat bubbles, just names
+ mNameText->setTextAlignment(LLHUDNameTag::ALIGN_TEXT_CENTER);
mNameText->setFadeDistance(CHAT_NORMAL_RADIUS, 5.f);
mNameText->setVisibleOffScreen(FALSE);
- if (new_name)
+ }
+}
+
+void LLVOAvatar::addNameTagLine(const std::string& line, const LLColor4& color, S32 style, const LLFontGL* font)
+{
+ llassert(mNameText);
+ if (mVisibleChat)
+ {
+ mNameText->addLabel(line);
+ }
+ else
+ {
+ mNameText->addLine(line, color, (LLFontGL::StyleFlags)style, font);
+ }
+ mNameString += line;
+ mNameString += '\n';
+}
+
+void LLVOAvatar::clearNameTag()
+{
+ mNameString.clear();
+ if (mNameText)
{
mNameText->setLabel("");
- mNameText->setString(mNameString);
+ mNameText->setString( "" );
+ }
+}
+
+//static
+void LLVOAvatar::invalidateNameTag(const LLUUID& agent_id)
+{
+ LLViewerObject* obj = gObjectList.findObject(agent_id);
+ if (!obj) return;
+
+ LLVOAvatar* avatar = dynamic_cast<LLVOAvatar*>(obj);
+ if (!avatar) return;
+
+ avatar->clearNameTag();
+}
+
+//static
+void LLVOAvatar::invalidateNameTags()
+{
+ std::vector<LLCharacter*>::iterator it = LLCharacter::sInstances.begin();
+ for ( ; it != LLCharacter::sInstances.end(); ++it)
+ {
+ LLVOAvatar* avatar = dynamic_cast<LLVOAvatar*>(*it);
+ if (!avatar) continue;
+ if (avatar->isDead()) continue;
+
+ avatar->clearNameTag();
}
}
+
+// Compute name tag position during idle update
+LLVector3 LLVOAvatar::idleUpdateNameTagPosition(const LLVector3& root_pos_last)
+{
+ LLQuaternion root_rot = mRoot.getWorldRotation();
+ LLVector3 pixel_right_vec;
+ LLVector3 pixel_up_vec;
+ LLViewerCamera::getInstance()->getPixelVectors(root_pos_last, pixel_up_vec, pixel_right_vec);
+ LLVector3 camera_to_av = root_pos_last - LLViewerCamera::getInstance()->getOrigin();
+ camera_to_av.normalize();
+ LLVector3 local_camera_at = camera_to_av * ~root_rot;
+ LLVector3 local_camera_up = camera_to_av % LLViewerCamera::getInstance()->getLeftAxis();
+ local_camera_up.normalize();
+ local_camera_up = local_camera_up * ~root_rot;
+
+ local_camera_up.scaleVec(mBodySize * 0.5f);
+ local_camera_at.scaleVec(mBodySize * 0.5f);
+
+ LLVector3 name_position = mRoot.getWorldPosition() +
+ (local_camera_up * root_rot) -
+ (projected_vec(local_camera_at * root_rot, camera_to_av));
+ name_position += pixel_up_vec * 15.f;
+ return name_position;
+ }
+
+void LLVOAvatar::idleUpdateNameTagAlpha(BOOL new_name, F32 alpha)
+{
+ llassert(mNameText);
+
+ if (new_name
+ || alpha != mNameAlpha)
+ {
+ mNameText->setAlpha(alpha);
+ mNameAlpha = alpha;
+ }
+}
+
+LLColor4 LLVOAvatar::getNameTagColor(bool is_friend)
+{
+ static LLUICachedControl<bool> show_friends("NameTagShowFriends");
+ const char* color_name;
+ if (show_friends && is_friend)
+ {
+ color_name = "NameTagFriend";
+ }
+ else if (LLAvatarNameCache::useDisplayNames())
+ {
+ // ...color based on whether username "matches" a computed display
+ // name
+ LLAvatarName av_name;
+ if (LLAvatarNameCache::get(getID(), &av_name)
+ && av_name.mIsDisplayNameDefault)
+ {
+ color_name = "NameTagMatch";
}
+ else
+ {
+ color_name = "NameTagMismatch";
+ }
}
- else if (mNameText)
+ else
{
- mNameText->markDead();
- mNameText = NULL;
- sNumVisibleChatBubbles--;
+ // ...not using display names
+ color_name = "NameTagLegacy";
}
+ return LLUIColorTable::getInstance()->getColor( color_name );
}
//--------------------------------------------------------------------
@@ -3189,29 +3330,26 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
{ // muted avatars update at 16 hz
mUpdatePeriod = 16;
}
- else if (visible && mVisibilityRank <= LLVOAvatar::sMaxVisible)
+ else if (mVisibilityRank <= LLVOAvatar::sMaxVisible)
{ //first 25% of max visible avatars are not impostored
mUpdatePeriod = 1;
}
- else if (visible && mVisibilityRank > LLVOAvatar::sMaxVisible * 4)
+ else if (mVisibilityRank > LLVOAvatar::sMaxVisible * 4)
{ //background avatars are REALLY slow updating impostors
mUpdatePeriod = 16;
}
- else if (visible && mVisibilityRank > LLVOAvatar::sMaxVisible * 3)
+ else if (mVisibilityRank > LLVOAvatar::sMaxVisible * 3)
{ //back 25% of max visible avatars are slow updating impostors
mUpdatePeriod = 8;
}
- else if (visible && mImpostorPixelArea <= impostor_area)
+ else if (mImpostorPixelArea <= impostor_area)
{ // stuff in between gets an update period based on pixel area
mUpdatePeriod = llclamp((S32) sqrtf(impostor_area*4.f/mImpostorPixelArea), 2, 8);
}
- else if (visible && mVisibilityRank > LLVOAvatar::sMaxVisible)
- { // force nearby impostors in ultra crowded areas
- mUpdatePeriod = 2;
- }
else
- { // not impostored
- mUpdatePeriod = 1;
+ {
+ //nearby avatars, update the impostors more frequently.
+ mUpdatePeriod = 4;
}
visible = (LLDrawable::getCurrentFrame()+mID.mData[0])%mUpdatePeriod == 0 ? TRUE : FALSE;
@@ -4274,10 +4412,12 @@ void LLVOAvatar::checkTextureLoading()
return ;
}
+const F32 SELF_ADDITIONAL_PRI = 0.75f ;
+const F32 ADDITIONAL_PRI = 0.5f;
void LLVOAvatar::addBakedTextureStats( LLViewerFetchedTexture* imagep, F32 pixel_area, F32 texel_area_ratio, S32 boost_level)
{
//if this function is not called for the last 512 frames, the texture pipeline will stop fetching this texture.
- static const S32 MAX_TEXTURE_VIRTURE_SIZE_RESET_INTERVAL = 512 ; //frames
+ static const S32 MAX_TEXTURE_VIRTURE_SIZE_RESET_INTERVAL = 512 ; //frames
imagep->resetTextureStats();
imagep->setCanUseHTTP(false) ; //turn off http fetching for baked textures.
@@ -4287,9 +4427,14 @@ void LLVOAvatar::addBakedTextureStats( LLViewerFetchedTexture* imagep, F32 pixel
mMinPixelArea = llmin(pixel_area, mMinPixelArea);
imagep->addTextureStats(pixel_area / texel_area_ratio);
imagep->setBoostLevel(boost_level);
- if(boost_level == LLViewerTexture::BOOST_AVATAR_BAKED_SELF)
+
+ if(boost_level != LLViewerTexture::BOOST_AVATAR_BAKED_SELF)
{
- imagep->setAdditionalDecodePriority(1.0f) ;
+ imagep->setAdditionalDecodePriority(ADDITIONAL_PRI) ;
+ }
+ else
+ {
+ imagep->setAdditionalDecodePriority(SELF_ADDITIONAL_PRI) ;
}
}
@@ -6888,7 +7033,7 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys )
{
releaseComponentTextures();
}
-
+
// parse visual params
S32 num_blocks = mesgsys->getNumberOfBlocksFast(_PREHASH_VisualParam);
bool drop_visual_params_debug = gSavedSettings.getBOOL("BlockSomeAvatarAppearanceVisualParams") && (ll_rand(2) == 0); // pretend that ~12% of AvatarAppearance messages arrived without a VisualParam block, for testing
@@ -6981,9 +7126,9 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys )
// re-request appearance, hoping that it comes back with a shape next time
llinfos << "Re-requesting AvatarAppearance for object: " << getID() << llendl;
LLAvatarPropertiesProcessor::getInstance()->sendAvatarTexturesRequest(getID());
- }
- else
- {
+ }
+ else
+ {
llinfos << "That's okay, we already have a non-default shape for object: " << getID() << llendl;
// we don't really care.
}
@@ -7300,7 +7445,7 @@ void LLVOAvatar::cullAvatarsByPixelArea()
std::sort(LLCharacter::sInstances.begin(), LLCharacter::sInstances.end(), CompareScreenAreaGreater());
// Update the avatars that have changed status
- U32 rank = 0;
+ U32 rank = 2; //1 is reserved for self.
for (std::vector<LLCharacter*>::iterator iter = LLCharacter::sInstances.begin();
iter != LLCharacter::sInstances.end(); ++iter)
{
@@ -7324,7 +7469,7 @@ void LLVOAvatar::cullAvatarsByPixelArea()
if (inst->isSelf())
{
- inst->setVisibilityRank(0);
+ inst->setVisibilityRank(1);
}
else if (inst->mDrawable.notNull() && inst->mDrawable->isVisible())
{
@@ -7875,9 +8020,7 @@ std::string LLVOAvatar::getFullname() const
LLNameValue* last = getNVPair("LastName");
if (first && last)
{
- name += first->getString();
- name += " ";
- name += last->getString();
+ name = LLCacheName::buildFullName( first->getString(), last->getString() );
}
return name;
diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h
index dd7d0bb24d..6798fbbc33 100644
--- a/indra/newview/llvoavatar.h
+++ b/indra/newview/llvoavatar.h
@@ -65,7 +65,7 @@ extern const LLUUID ANIM_AGENT_WALK_ADJUST;
class LLTexLayerSet;
class LLVoiceVisualizer;
-class LLHUDText;
+class LLHUDNameTag;
class LLHUDEffectSpiral;
class LLTexGlobalColor;
class LLVOAvatarBoneInfo;
@@ -213,6 +213,15 @@ public:
void idleUpdateLoadingEffect();
void idleUpdateWindEffect();
void idleUpdateNameTag(const LLVector3& root_pos_last);
+ void idleUpdateNameTagText(BOOL new_name);
+ LLVector3 idleUpdateNameTagPosition(const LLVector3& root_pos_last);
+ void idleUpdateNameTagAlpha(BOOL new_name, F32 alpha);
+ LLColor4 getNameTagColor(bool is_friend);
+ void clearNameTag();
+ static void invalidateNameTag(const LLUUID& agent_id);
+ // force all name tags to rebuild, useful when display names turned on/off
+ static void invalidateNameTags();
+ void addNameTagLine(const std::string& line, const LLColor4& color, S32 style, const LLFontGL* font);
void idleUpdateRenderCost();
void idleUpdateTractorBeam();
void idleUpdateBelowWater();
@@ -832,13 +841,15 @@ protected:
static void getAnimLabels(LLDynamicArray<std::string>* labels);
static void getAnimNames(LLDynamicArray<std::string>* names);
private:
- LLWString mNameString;
+ std::string mNameString; // UTF-8 title + name + status
std::string mTitle;
- BOOL mNameAway;
- BOOL mNameBusy;
- BOOL mNameMute;
- BOOL mNameAppearance;
- BOOL mNameCloud;
+ bool mNameAway;
+ bool mNameBusy;
+ bool mNameMute;
+ bool mNameAppearance;
+ bool mNameFriend;
+ bool mNameCloud;
+ F32 mNameAlpha;
BOOL mRenderGroupTitles;
//--------------------------------------------------------------------
@@ -846,7 +857,7 @@ private:
//--------------------------------------------------------------------
public:
LLFrameTimer mChatTimer;
- LLPointer<LLHUDText> mNameText;
+ LLPointer<LLHUDNameTag> mNameText;
private:
LLFrameTimer mTimeVisible;
std::deque<LLChat> mChats;
@@ -1048,5 +1059,6 @@ protected: // Shared with LLVOAvatarSelf
*******************************************************************************/
}; // LLVOAvatar
+extern const F32 SELF_ADDITIONAL_PRI;
#endif // LL_VO_AVATAR_H
diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp
index 4edbbb7402..b80e47e11a 100644
--- a/indra/newview/llvoavatarself.cpp
+++ b/indra/newview/llvoavatarself.cpp
@@ -2034,7 +2034,7 @@ void LLVOAvatarSelf::addLocalTextureStats( ETextureIndex type, LLViewerFetchedTe
imagep->resetTextureStats();
imagep->setMaxVirtualSizeResetInterval(16);
imagep->addTextureStats( desired_pixels / texel_area_ratio );
- imagep->setAdditionalDecodePriority(1.0f) ;
+ imagep->setAdditionalDecodePriority(SELF_ADDITIONAL_PRI) ;
imagep->forceUpdateBindStats() ;
if (imagep->getDiscardLevel() < 0)
{
diff --git a/indra/newview/llvoicechannel.h b/indra/newview/llvoicechannel.h
index 074f9b8bba..ee843435bc 100644
--- a/indra/newview/llvoicechannel.h
+++ b/indra/newview/llvoicechannel.h
@@ -82,6 +82,9 @@ public:
virtual void getChannelInfo();
virtual BOOL isActive();
virtual BOOL callStarted();
+
+ // Session name is a UI label used for feedback about which person,
+ // group, or phone number you are talking to
const std::string& getSessionName() const { return mSessionName; }
boost::signals2::connection setStateChangedCallback(const state_changed_signal_t::slot_type& callback)
diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp
index 4dc9edb247..25c4914c13 100644
--- a/indra/newview/llvoicevivox.cpp
+++ b/indra/newview/llvoicevivox.cpp
@@ -37,6 +37,8 @@
#include "llsdutil.h"
+// Linden library includes
+#include "llavatarnamecache.h"
#include "llvoavatarself.h"
#include "llbufferstream.h"
#include "llfile.h"
@@ -52,6 +54,8 @@
#include "llviewercontrol.h"
#include "llkeyboard.h"
#include "llappviewer.h" // for gDisconnected, gDisableVoice
+
+// Viewer includes
#include "llmutelist.h" // to check for muted avatars
#include "llagent.h"
#include "llcachename.h"
@@ -2806,12 +2810,16 @@ void LLVivoxVoiceClient::buildLocalAudioUpdates(std::ostringstream &stream)
void LLVivoxVoiceClient::checkFriend(const LLUUID& id)
{
- std::string name;
buddyListEntry *buddy = findBuddy(id);
// Make sure we don't add a name before it's been looked up.
- if(gCacheName->getFullName(id, name))
+ LLAvatarName av_name;
+ if(LLAvatarNameCache::get(id, &av_name))
{
+ // *NOTE: For now, we feed legacy names to Vivox because I don't know
+ // if their service can support a mix of new and old clients with
+ // different sorts of names.
+ std::string name = av_name.getLegacyName();
const LLRelationship* relationInfo = LLAvatarTracker::instance().getBuddyInfo(id);
bool canSeeMeOnline = false;
@@ -6363,16 +6371,18 @@ void LLVivoxVoiceClient::notifyFriendObservers()
void LLVivoxVoiceClient::lookupName(const LLUUID &id)
{
- BOOL is_group = FALSE;
- gCacheName->get(id, is_group, &LLVivoxVoiceClient::onAvatarNameLookup);
+ LLAvatarNameCache::get(id,
+ boost::bind(&LLVivoxVoiceClient::onAvatarNameCache,
+ this, _1, _2));
}
-//static
-void LLVivoxVoiceClient::onAvatarNameLookup(const LLUUID& id, const std::string& first, const std::string& last, BOOL is_group)
+void LLVivoxVoiceClient::onAvatarNameCache(const LLUUID& agent_id,
+ const LLAvatarName& av_name)
{
- std::string name = llformat("%s %s", first.c_str(), last.c_str());
- LLVivoxVoiceClient::getInstance()->avatarNameResolved(id, name);
-
+ // For Vivox, we use the legacy name because I'm uncertain whether or
+ // not their service can tolerate switching to Username or Display Name
+ std::string legacy_name = av_name.getLegacyName();
+ avatarNameResolved(agent_id, legacy_name);
}
void LLVivoxVoiceClient::avatarNameResolved(const LLUUID &id, const std::string &name)
diff --git a/indra/newview/llvoicevivox.h b/indra/newview/llvoicevivox.h
index f858f8f74e..d382cb0a70 100644
--- a/indra/newview/llvoicevivox.h
+++ b/indra/newview/llvoicevivox.h
@@ -51,7 +51,7 @@ class LLVivoxProtocolParser;
#endif
#include "llvoiceclient.h"
-
+class LLAvatarName;
class LLVivoxVoiceAccountProvisionResponder;
class LLVivoxVoiceClientMuteListObserver;
class LLVivoxVoiceClientFriendsObserver;
@@ -655,7 +655,7 @@ protected:
void leaveAudioSession();
void lookupName(const LLUUID &id);
- static void onAvatarNameLookup(const LLUUID& id, const std::string& first, const std::string& last, BOOL is_group);
+ void onAvatarNameCache(const LLUUID& id, const LLAvatarName& av_name);
void avatarNameResolved(const LLUUID &id, const std::string &name);
/////////////////////////////
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index b578cb9f69..4f4679a436 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -70,6 +70,8 @@
#include "llfloaterreg.h"
#include "llgldbg.h"
#include "llhudmanager.h"
+#include "llhudnametag.h"
+#include "llhudtext.h"
#include "lllightconstants.h"
#include "llresmgr.h"
#include "llselectmgr.h"
@@ -2087,6 +2089,7 @@ void LLPipeline::shiftObjects(const LLVector3 &offset)
}
LLHUDText::shiftAll(offset);
+ LLHUDNameTag::shiftAll(offset);
display_update_camera();
}
@@ -5277,7 +5280,8 @@ LLViewerObject* LLPipeline::lineSegmentIntersectInWorld(const LLVector3& start,
++iter)
{
LLVOAvatar* av = (LLVOAvatar*) *iter;
- if (av->mNameText.notNull() && av->mNameText->lineSegmentIntersect(start, local_end, position))
+ if (av->mNameText.notNull()
+ && av->mNameText->lineSegmentIntersect(start, local_end, position))
{
drawable = av->mDrawable;
local_end = position;
diff --git a/indra/newview/skins/default/colors.xml b/indra/newview/skins/default/colors.xml
index 2188c71ff9..2098ad1a39 100644
--- a/indra/newview/skins/default/colors.xml
+++ b/indra/newview/skins/default/colors.xml
@@ -118,9 +118,6 @@
name="AlertTextColor"
value="0.58 0.66 0.84 1" />
<color
- name="AvatarNameColor"
- reference="White" />
- <color
name="AvatarListItemIconDefaultColor"
reference="White" />
<color
@@ -531,6 +528,38 @@
<color
name="MultiSliderTriangleColor"
reference="Unused?" />
+ <!--
+ <color
+ name="NameTagBackground"
+ value="0.85 0.85 0.85 0.80" />
+ -->
+ <color
+ name="NameTagBackground"
+ value="0 0 0 1" />
+ <color
+ name="NameTagChat"
+ reference="White" />
+ <color
+ name="NameTagFriend"
+ value="0.447 0.784 0.663 1" />
+ <color
+ name="NameTagGroup"
+ value="1 1 1 1" />
+ <color
+ name="NameTagLegacy"
+ reference="White" />
+ <color
+ name="NameTagMatch"
+ reference="White" />
+ <color
+ name="NameTagMismatch"
+ reference="White" />
+ <color
+ name="NameTagSLID"
+ value="1 1 1 1" />
+ <color
+ name="NameTagStatus"
+ value="1 1 1 1" />
<color
name="NetMapBackgroundColor"
value="0 0 0 1" />
@@ -565,6 +594,9 @@
name="NotifyTextColor"
reference="White" />
<color
+ name="ObjectBubbleColor"
+ reference="DkGray_66" />
+ <color
name="ObjectChatColor"
reference="EmphasisColor" />
<color
diff --git a/indra/newview/skins/default/textures/Rounded_Rect.png b/indra/newview/skins/default/textures/Rounded_Rect.png
new file mode 100644
index 0000000000..c270c28039
--- /dev/null
+++ b/indra/newview/skins/default/textures/Rounded_Rect.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Person_Check.png b/indra/newview/skins/default/textures/icons/Person_Check.png
new file mode 100644
index 0000000000..f8638540d4
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Person_Check.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Person_Star.png b/indra/newview/skins/default/textures/icons/Person_Star.png
new file mode 100644
index 0000000000..ad10580ac4
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Person_Star.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml
index 082b37d80b..f293bbd1af 100644
--- a/indra/newview/skins/default/textures/textures.xml
+++ b/indra/newview/skins/default/textures/textures.xml
@@ -358,6 +358,8 @@ with the same filename but different name
<texture name="Pause_Off" file_name="icons/Pause_Off.png" preload="false" />
<texture name="Pause_Over" file_name="icons/Pause_Over.png" preload="false" />
<texture name="Pause_Press" file_name="icons/Pause_Press.png" preload="false" />
+ <texture name="Person_Check" file_name="icons/Person_Check.png" preload="false" />
+ <texture name="Person_Star" file_name="icons/Person_Star.png" preload="false" />
<texture name="Play_Off" file_name="icons/Play_Off.png" preload="false" />
<texture name="Play_Over" file_name="icons/Play_Over.png" preload="false" />
<texture name="Play_Press" file_name="icons/Play_Press.png" preload="false" />
@@ -387,6 +389,7 @@ with the same filename but different name
<texture name="Resize_Corner" file_name="windows/Resize_Corner.png" preload="true" />
+ <texture name="Rounded_Rect" file_name="Rounded_Rect.png" preload="true" scale.left="6" scale.top="24" scale.right="58" scale.bottom="6" />
<texture name="Rounded_Square" file_name="rounded_square.j2c" preload="true" scale.left="16" scale.top="16" scale.right="112" scale.bottom="16" />
<texture name="Row_Selection" file_name="navbar/Row_Selection.png" preload="false" />
diff --git a/indra/newview/skins/default/xui/da/floater_windlight_options.xml b/indra/newview/skins/default/xui/da/floater_windlight_options.xml
index 65f3f67a70..56f94b24e9 100644
--- a/indra/newview/skins/default/xui/da/floater_windlight_options.xml
+++ b/indra/newview/skins/default/xui/da/floater_windlight_options.xml
@@ -1,18 +1,18 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater name="WindLight floater" title="AVANCERET OPSÆTNING FOR HIMMEL">
<text name="KeyFramePresetsText">
Faste indstillinger:
</text>
- <button label="Ny" label_selected="Ny" name="WLNewPreset"/>
- <button label="Gem" label_selected="Gem" name="WLSavePreset"/>
- <button label="Slet" label_selected="Slet" name="WLDeletePreset"/>
- <button label="Dags cyklus" label_selected="Dags cyklus" name="WLDayCycleMenuButton"/>
+ <button label="Ny" label_selected="Ny" name="WLNewPreset" />
+ <button label="Gem" label_selected="Gem" name="WLSavePreset" />
+ <button label="Slet" label_selected="Slet" name="WLDeletePreset" />
+ <button label="Dags cyklus" label_selected="Dags cyklus" name="WLDayCycleMenuButton" />
<tab_container name="WindLight Tabs">
<panel label="ATMOSFÆRE" name="Atmosphere">
<text name="BHText">
Blå - horisont
</text>
- <button label="?" name="WLBlueHorizonHelp"/>
+ <button label="?" name="WLBlueHorizonHelp" />
<text name="BHText2">
R
</text>
@@ -25,19 +25,19 @@
<text name="BHText5">
I
</text>
- <slider label="" name="WLBlueHorizonR"/>
- <slider label="" name="WLBlueHorizonG"/>
- <slider label="" name="WLBlueHorizonB"/>
- <slider label="" name="WLBlueHorizonI"/>
+ <slider label="" name="WLBlueHorizonR" />
+ <slider label="" name="WLBlueHorizonG" />
+ <slider label="" name="WLBlueHorizonB" />
+ <slider label="" name="WLBlueHorizonI" />
<text name="BDensText">
Dis - horisont
</text>
- <button label="?" name="WLHazeHorizonHelp"/>
- <slider label="" name="WLHazeHorizon"/>
+ <button label="?" name="WLHazeHorizonHelp" />
+ <slider label="" name="WLHazeHorizon" />
<text name="BDensText2">
Blå - tæthed
</text>
- <button label="?" name="WLBlueDensityHelp"/>
+ <button label="?" name="WLBlueDensityHelp" />
<text name="BHText6">
R
</text>
@@ -50,36 +50,36 @@
<text name="BHText9">
I
</text>
- <slider label="" name="WLBlueDensityR"/>
- <slider label="" name="WLBlueDensityG"/>
- <slider label="" name="WLBlueDensityB"/>
- <slider label="" name="WLBlueDensityI"/>
+ <slider label="" name="WLBlueDensityR" />
+ <slider label="" name="WLBlueDensityG" />
+ <slider label="" name="WLBlueDensityB" />
+ <slider label="" name="WLBlueDensityI" />
<text name="HDText">
Dis - intensitet
</text>
- <button label="?" name="WLHazeDensityHelp"/>
- <slider label="" name="WLHazeDensity"/>
+ <button label="?" name="WLHazeDensityHelp" />
+ <slider label="" name="WLHazeDensity" />
<text name="DensMultText">
Densitet faktor
</text>
- <button label="?" name="WLDensityMultHelp"/>
- <slider label="" name="WLDensityMult"/>
+ <button label="?" name="WLDensityMultHelp" />
+ <slider label="" name="WLDensityMult" />
<text name="WLDistanceMultText">
Distance faktor
</text>
- <button label="?" name="WLDistanceMultHelp"/>
- <slider label="" name="WLDistanceMult"/>
+ <button label="?" name="WLDistanceMultHelp" />
+ <slider label="" name="WLDistanceMult" />
<text name="MaxAltText">
Maximum højde
</text>
- <button label="?" name="WLMaxAltitudeHelp"/>
- <slider label="" name="WLMaxAltitude"/>
+ <button label="?" name="WLMaxAltitudeHelp" />
+ <slider label="" name="WLMaxAltitude" />
</panel>
<panel label="LYS" name="Lighting">
<text name="SLCText">
Sol/Måne farve
</text>
- <button label="?" name="WLSunlightColorHelp"/>
+ <button label="?" name="WLSunlightColorHelp" />
<text name="BHText">
R
</text>
@@ -92,19 +92,19 @@
<text name="BHText4">
I
</text>
- <slider label="" name="WLSunlightR"/>
- <slider label="" name="WLSunlightG"/>
- <slider label="" name="WLSunlightB"/>
- <slider label="" name="WLSunlightI"/>
+ <slider label="" name="WLSunlightR" />
+ <slider label="" name="WLSunlightG" />
+ <slider label="" name="WLSunlightB" />
+ <slider label="" name="WLSunlightI" />
<text name="TODText">
Sol/Måne position
</text>
- <button label="?" name="WLTimeOfDayHelp"/>
- <slider label="" name="WLSunAngle"/>
+ <button label="?" name="WLTimeOfDayHelp" />
+ <slider label="" name="WLSunAngle" />
<text name="WLAmbientText">
Omgivende
</text>
- <button label="?" name="WLAmbientHelp"/>
+ <button label="?" name="WLAmbientHelp" />
<text name="BHText5">
R
</text>
@@ -117,37 +117,37 @@
<text name="BHText8">
I
</text>
- <slider label="" name="WLAmbientR"/>
- <slider label="" name="WLAmbientG"/>
- <slider label="" name="WLAmbientB"/>
- <slider label="" name="WLAmbientI"/>
+ <slider label="" name="WLAmbientR" />
+ <slider label="" name="WLAmbientG" />
+ <slider label="" name="WLAmbientB" />
+ <slider label="" name="WLAmbientI" />
<text name="WLEastAngleText">
Øst vinkel
</text>
- <button label="?" name="WLEastAngleHelp"/>
- <slider label="" name="WLEastAngle"/>
+ <button label="?" name="WLEastAngleHelp" />
+ <slider label="" name="WLEastAngle" />
<text name="SunGlowText">
Sol glød
</text>
- <button label="?" name="WLSunGlowHelp"/>
- <slider label="Fokus " name="WLGlowB"/>
- <slider label="Størr. " name="WLGlowR"/>
+ <button label="?" name="WLSunGlowHelp" />
+ <slider label="Fokus " name="WLGlowB" />
+ <slider label="Størr. " name="WLGlowR" />
<text name="SceneGammaText">
Lysintensitet (gamma)
</text>
- <button label="?" name="WLSceneGammaHelp"/>
- <slider label="" name="WLGamma"/>
+ <button label="?" name="WLSceneGammaHelp" />
+ <slider label="" name="WLGamma" />
<text name="WLStarText">
Stjerne intensitet
</text>
- <button label="?" name="WLStarBrightnessHelp"/>
- <slider label="" name="WLStarAlpha"/>
+ <button label="?" name="WLStarBrightnessHelp" />
+ <slider label="" name="WLStarAlpha" />
</panel>
<panel label="SKYER" name="Clouds">
<text name="WLCloudColorText">
Farve på skyer
</text>
- <button label="?" name="WLCloudColorHelp"/>
+ <button label="?" name="WLCloudColorHelp" />
<text name="BHText">
R
</text>
@@ -160,14 +160,14 @@
<text name="BHText4">
I
</text>
- <slider label="" name="WLCloudColorR"/>
- <slider label="" name="WLCloudColorG"/>
- <slider label="" name="WLCloudColorB"/>
- <slider label="" name="WLCloudColorI"/>
+ <slider label="" name="WLCloudColorR" />
+ <slider label="" name="WLCloudColorG" />
+ <slider label="" name="WLCloudColorB" />
+ <slider label="" name="WLCloudColorI" />
<text name="WLCloudColorText2">
Skyer XY/Tæthed
</text>
- <button label="?" name="WLCloudDensityHelp"/>
+ <button label="?" name="WLCloudDensityHelp" />
<text name="BHText5">
X
</text>
@@ -177,23 +177,23 @@
<text name="BHText7">
T
</text>
- <slider label="" name="WLCloudX"/>
- <slider label="" name="WLCloudY"/>
- <slider label="" name="WLCloudDensity"/>
+ <slider label="" name="WLCloudX" />
+ <slider label="" name="WLCloudY" />
+ <slider label="" name="WLCloudDensity" />
<text name="WLCloudCoverageText">
Skydække
</text>
- <button label="?" name="WLCloudCoverageHelp"/>
- <slider label="" name="WLCloudCoverage"/>
+ <button label="?" name="WLCloudCoverageHelp" />
+ <slider label="" name="WLCloudCoverage" />
<text name="WLCloudScaleText">
Skystørrelse
</text>
- <button label="?" name="WLCloudScaleHelp"/>
- <slider label="" name="WLCloudScale"/>
+ <button label="?" name="WLCloudScaleHelp" />
+ <slider label="" name="WLCloudScale" />
<text name="WLCloudDetailText">
Sky detaljer(XY/tæthed)
</text>
- <button label="?" name="WLCloudDetailHelp"/>
+ <button label="?" name="WLCloudDetailHelp" />
<text name="BHText8">
X
</text>
@@ -203,23 +203,23 @@
<text name="BHText10">
T
</text>
- <slider label="" name="WLCloudDetailX"/>
- <slider label="" name="WLCloudDetailY"/>
- <slider label="" name="WLCloudDetailDensity"/>
+ <slider label="" name="WLCloudDetailX" />
+ <slider label="" name="WLCloudDetailY" />
+ <slider label="" name="WLCloudDetailDensity" />
<text name="WLCloudScrollXText">
Sky drift X
</text>
- <button label="?" name="WLCloudScrollXHelp"/>
- <check_box label="Lås" name="WLCloudLockX"/>
- <slider label="" name="WLCloudScrollX"/>
+ <button label="?" name="WLCloudScrollXHelp" />
+ <check_box label="Lås" name="WLCloudLockX" />
+ <slider label="" name="WLCloudScrollX" />
<text name="WLCloudScrollYText">
Sky drift Y
</text>
- <button label="?" name="WLCloudScrollYHelp"/>
- <check_box label="Lås" name="WLCloudLockY"/>
- <slider label="" name="WLCloudScrollY"/>
- <check_box label="Benyt simple skyer" name="DrawClassicClouds"/>
- <button label="?" name="WLClassicCloudsHelp"/>
+ <button label="?" name="WLCloudScrollYHelp" />
+ <check_box label="Lås" name="WLCloudLockY" />
+ <slider label="" name="WLCloudScrollY" />
+ <check_box label="Benyt simple skyer" name="DrawClassicClouds" />
+ <button label="?" name="WLClassicCloudsHelp" />
</panel>
</tab_container>
<string name="WLDefaultSkyNames">
diff --git a/indra/newview/skins/default/xui/da/panel_classified_info.xml b/indra/newview/skins/default/xui/da/panel_classified_info.xml
index 28f8936457..0bb52b8fa6 100644
--- a/indra/newview/skins/default/xui/da/panel_classified_info.xml
+++ b/indra/newview/skins/default/xui/da/panel_classified_info.xml
@@ -40,7 +40,7 @@
</layout_panel>
<layout_panel name="descr_layout_panel">
<text name="classified_desc_label" value="Beskrivelse:"/>
- <text_editor name="classified_desc" value="[description]"/>
+ <text_editor name="classified_desc" value="[description]"/>
</layout_panel>
</layout_stack>
</panel>
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 68e36ff0b3..f46f00ff12 100644
--- a/indra/newview/skins/default/xui/en/floater_about_land.xml
+++ b/indra/newview/skins/default/xui/en/floater_about_land.xml
@@ -374,7 +374,8 @@ Leyla Linden </text>
left_delta="-199"
name="For sale to"
top_delta="20"
- width="186">
+ use_ellipses="true"
+ width="340">
For sale to: [BUYER]
</text>
<text
@@ -410,7 +411,7 @@ Leyla Linden </text>
right="-10"
name="Cancel Land Sale"
left_pad="5"
- top_pad="-25"
+ top_pad="-15"
width="180" />
<text
type="string"
@@ -541,7 +542,7 @@ Leyla Linden </text>
layout="topleft"
left_delta="0"
name="Reclaim Land..."
- top_delta="-61"
+ top_delta="-50"
width="180" />
<button
enabled="false"
diff --git a/indra/newview/skins/default/xui/en/floater_avatar_picker.xml b/indra/newview/skins/default/xui/en/floater_avatar_picker.xml
index f59badfcb4..a11946d352 100644
--- a/indra/newview/skins/default/xui/en/floater_avatar_picker.xml
+++ b/indra/newview/skins/default/xui/en/floater_avatar_picker.xml
@@ -5,11 +5,11 @@
height="350"
layout="topleft"
min_height="200"
- min_width="265"
+ min_width="400"
name="avatarpicker"
help_topic="avatarpicker"
title="CHOOSE RESIDENT"
- width="265">
+ width="500">
<floater.string
name="not_found">
&apos;[TEXT]&apos; not found
@@ -40,7 +40,7 @@
name="ResidentChooserTabs"
tab_position="top"
top="20"
- width="265">
+ width="500">
<panel
border="none"
height="150"
@@ -83,14 +83,24 @@
left_pad="5"
name="Find"
width="45" />
- <scroll_list
- follows="all"
- height="98"
- layout="topleft"
- left="0"
- name="SearchResults"
- top="52"
- width="132" />
+ <scroll_list
+ draw_heading="true"
+ follows="all"
+ height="98"
+ layout="topleft"
+ left="0"
+ name="SearchResults"
+ top="52"
+ width="132">
+ <columns
+ label="Name"
+ name="name"
+ width="150" />
+ <columns
+ label="Username"
+ name="username"
+ width="150" />
+ </scroll_list>
</panel>
<panel
border="none"
@@ -128,7 +138,7 @@
</button>
<scroll_list
follows="all"
- height="100"
+ height="120"
border="false"
layout="topleft"
left="0"
@@ -194,7 +204,8 @@
width="28"
name="Refresh"
image_overlay="Refresh_Off" />
- <scroll_list
+ <scroll_list
+ draw_heading="true"
follows="all"
height="100"
border="false"
@@ -202,21 +213,30 @@
left="0"
name="NearMe"
sort_column="0"
- top="50"
- width="132" />
+ top="52"
+ width="132">
+ <columns
+ label="Name"
+ name="name"
+ width="150" />
+ <columns
+ label="Username"
+ name="username"
+ width="150" />
+ </scroll_list>
</panel>
</tab_container>
<button
- follows="right|bottom"
+ follows="left|bottom"
height="23"
label="OK"
label_selected="OK"
name="ok_btn"
top_pad="3"
- left="46"
+ left="10"
width="100" />
<button
- follows="right|bottom"
+ follows="left|bottom"
height="23"
label="Cancel"
label_selected="Cancel"
diff --git a/indra/newview/skins/default/xui/en/floater_bumps.xml b/indra/newview/skins/default/xui/en/floater_bumps.xml
index 303c28d7c8..1f2fe62b3c 100644
--- a/indra/newview/skins/default/xui/en/floater_bumps.xml
+++ b/indra/newview/skins/default/xui/en/floater_bumps.xml
@@ -14,23 +14,23 @@
</floater.string>
<floater.string
name="bump">
- [TIME] [FIRST] [LAST] bumped you
+ [TIME] [NAME] bumped you
</floater.string>
<floater.string
name="llpushobject">
- [TIME] [FIRST] [LAST] pushed you with a script
+ [TIME] [NAME] pushed you with a script
</floater.string>
<floater.string
name="selected_object_collide">
- [TIME] [FIRST] [LAST] hit you with an object
+ [TIME] [NAME] hit you with an object
</floater.string>
<floater.string
name="scripted_object_collide">
- [TIME] [FIRST] [LAST] hit you with a scripted object
+ [TIME] [NAME] hit you with a scripted object
</floater.string>
<floater.string
name="physical_object_collide">
- [TIME] [FIRST] [LAST] hit you with a physical object
+ [TIME] [NAME] hit you with a physical object
</floater.string>
<floater.string
name="timeStr">
diff --git a/indra/newview/skins/default/xui/en/floater_buy_land.xml b/indra/newview/skins/default/xui/en/floater_buy_land.xml
index 0ad4fbc967..116f3c49c5 100644
--- a/indra/newview/skins/default/xui/en/floater_buy_land.xml
+++ b/indra/newview/skins/default/xui/en/floater_buy_land.xml
@@ -568,7 +568,7 @@ sold with objects
name="US$6.00/month,billedannually" />
</combo_box>
<locate
- height="10"
+ height="5"
layout="topleft" />
<icon
follows="top|left"
@@ -588,7 +588,7 @@ sold with objects
left="72"
name="land_use_action"
right="438"
- top="284"
+ top="279"
width="218">
Increase your monthly land use fees to US$ 40/month.
</text>
@@ -607,7 +607,7 @@ sold with objects
This parcel is 512 m² of land.
</text>
<locate
- height="10"
+ height="5"
layout="topleft" />
<icon
follows="top|left"
@@ -620,14 +620,15 @@ This parcel is 512 m² of land.
<text
type="string"
length="1"
- bottom_delta="-38"
+ top_delta="10"
follows="top|left"
font="SansSerifBig"
- height="16"
+ height="32"
layout="topleft"
left="72"
name="purchase_action"
- right="438">
+ right="438"
+ wrap="true">
Pay Joe Resident L$ 4000 for the land
</text>
<text
@@ -650,7 +651,7 @@ This parcel is 512 m² of land.
left_delta="0"
name="currency_action"
top_pad="9"
- width="90">
+ width="95">
Buy additional L$
</text>
<locate
@@ -665,7 +666,7 @@ This parcel is 512 m² of land.
layout="topleft"
left="170"
name="currency_amt"
- top="408"
+ top_pad="-25"
width="80">
1000
</line_editor>
diff --git a/indra/newview/skins/default/xui/en/floater_buy_object.xml b/indra/newview/skins/default/xui/en/floater_buy_object.xml
index 3d8f5d678b..db595458c0 100644
--- a/indra/newview/skins/default/xui/en/floater_buy_object.xml
+++ b/indra/newview/skins/default/xui/en/floater_buy_object.xml
@@ -2,7 +2,7 @@
<floater
legacy_header_height="18"
can_resize="true"
- height="290"
+ height="310"
layout="topleft"
min_height="150"
min_width="225"
@@ -84,15 +84,18 @@
length="1"
follows="left|right|bottom"
font="SansSerif"
- height="16"
+ height="35"
layout="topleft"
left_delta="0"
+ line_spacing.pixels="7"
name="buy_text"
text_color="white"
top_pad="5"
use_ellipses="true"
- width="260">
- Buy for L$[AMOUNT] from [NAME]?
+ width="260"
+ word_wrap="true">
+Buy for L$[AMOUNT] from:
+[NAME]?
</text>
<button
follows="right|bottom"
diff --git a/indra/newview/skins/default/xui/en/floater_camera.xml b/indra/newview/skins/default/xui/en/floater_camera.xml
index 8c3aa2c9a4..da2be18db6 100644
--- a/indra/newview/skins/default/xui/en/floater_camera.xml
+++ b/indra/newview/skins/default/xui/en/floater_camera.xml
@@ -71,7 +71,8 @@
image_name="Cam_Preset_Front_Off" />
<panel_camera_item.selected_picture
image_name="Cam_Preset_Front_On" />
- <panel_camera_item.text>
+ <panel_camera_item.text
+ name="front_view_text">
Front View
</panel_camera_item.text>
</panel_camera_item>
@@ -85,7 +86,8 @@
image_name="Cam_Preset_Side_Off" />
<panel_camera_item.selected_picture
image_name="Cam_Preset_Side_On" />
- <panel_camera_item.text>
+ <panel_camera_item.text
+ name="side_view_text">
Side View
</panel_camera_item.text>
</panel_camera_item>
@@ -100,7 +102,8 @@
image_name="Cam_Preset_Back_Off" />
<panel_camera_item.selected_picture
image_name="Cam_Preset_Back_On" />
- <panel_camera_item.text>
+ <panel_camera_item.text
+ name="rear_view_text">
Rear View
</panel_camera_item.text>
</panel_camera_item>
@@ -122,7 +125,8 @@
<panel_camera_item.mousedown_callback
function="CameraPresets.ChangeView"
parameter="object_view" />
- <panel_camera_item.text>
+ <panel_camera_item.text
+ name="object_view_text">
Object View
</panel_camera_item.text>
<panel_camera_item.picture
@@ -136,7 +140,8 @@
<panel_camera_item.mousedown_callback
function="CameraPresets.ChangeView"
parameter="mouselook_view" />
- <panel_camera_item.text>
+ <panel_camera_item.text
+ name="mouselook_view_text">
Mouselook View
</panel_camera_item.text>
<panel_camera_item.picture
diff --git a/indra/newview/skins/default/xui/en/floater_incoming_call.xml b/indra/newview/skins/default/xui/en/floater_incoming_call.xml
index 24fff6d4ae..81194f61cf 100644
--- a/indra/newview/skins/default/xui/en/floater_incoming_call.xml
+++ b/indra/newview/skins/default/xui/en/floater_incoming_call.xml
@@ -8,7 +8,7 @@
layout="topleft"
name="incoming call"
help_topic="incoming_call"
- title="UNKNOWN PERSON IS CALLING"
+ title="Incoming call"
width="410">
<floater.string
name="lifetime">
diff --git a/indra/newview/skins/default/xui/en/floater_pay.xml b/indra/newview/skins/default/xui/en/floater_pay.xml
index 509cffe490..9cb251e167 100644
--- a/indra/newview/skins/default/xui/en/floater_pay.xml
+++ b/indra/newview/skins/default/xui/en/floater_pay.xml
@@ -7,7 +7,7 @@
name="Give Money"
help_topic="give_money"
save_rect="true"
- width="225">
+ width="250">
<string
name="payee_group">
Pay Group
@@ -16,28 +16,7 @@
name="payee_resident">
Pay Resident
</string>
- <text
- type="string"
- length="1"
- follows="left|top"
- height="18"
- layout="topleft"
- left="12"
- name="payee_label"
- top="22"
- width="75">
- Pay:
- </text>
- <icon
- height="16"
- width="16"
- image_name="Generic_Person"
- mouse_opaque="true"
- name="icon_person"
- tool_tip="Person"
- top_pad="0"
- left="10"
- />
+
<text
type="string"
length="1"
@@ -45,17 +24,18 @@
font="SansSerifSmall"
height="16"
layout="topleft"
- left_pad="7"
+ left="10"
name="payee_name"
- width="210">
- [FIRST] [LAST]
+ top="25"
+ width="230">
+ Test Name That Is Extremely Long To Check Clipping
</text>
<button
height="23"
label="L$1"
label_selected="L$1"
layout="topleft"
- left="25"
+ left="35"
name="fastpay 1"
top_pad="8"
width="80" />
@@ -72,7 +52,7 @@
label="L$10"
label_selected="L$10"
layout="topleft"
- left="25"
+ left="35"
name="fastpay 10"
top_pad="8"
width="80" />
@@ -90,7 +70,7 @@
follows="left|top"
height="18"
layout="topleft"
- left="25"
+ left="35"
name="amount text"
top_pad="8"
width="180">
@@ -102,7 +82,7 @@
height="19"
top_pad="0"
layout="topleft"
- left="120"
+ left="130"
max_length="9"
name="amount"
width="80" />
@@ -112,16 +92,16 @@
label="Pay"
label_selected="Pay"
layout="topleft"
- left="10"
+ left="20"
name="pay btn"
- top_pad="5"
+ top_pad="15"
width="100" />
<button
height="23"
label="Cancel"
label_selected="Cancel"
layout="topleft"
- left_pad="5"
+ left_pad="10"
name="cancel btn"
width="100" />
</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_pay_object.xml b/indra/newview/skins/default/xui/en/floater_pay_object.xml
index d09a0a0535..c65dd6e49f 100644
--- a/indra/newview/skins/default/xui/en/floater_pay_object.xml
+++ b/indra/newview/skins/default/xui/en/floater_pay_object.xml
@@ -2,7 +2,7 @@
<floater
legacy_header_height="18"
can_minimize="false"
- height="220"
+ height="225"
layout="topleft"
name="Give Money"
help_topic="give_money"
@@ -16,27 +16,15 @@
name="payee_resident">
Pay Resident
</string>
- <icon
- height="16"
- width="16"
- image_name="Generic_Person"
- mouse_opaque="true"
- name="icon_person"
- tool_tip="Person"
- top_pad="24"
- left="10"
- />
<text
- type="string"
- length="1"
follows="left|top"
height="16"
layout="topleft"
- left_pad="7"
- top_delta="3"
+ left="10"
+ top_pad="24"
name="payee_name"
- width="184">
- [FIRST] [LAST]
+ width="200">
+ Ericacita Moostopolison
</text>
<text
type="string"
@@ -45,9 +33,9 @@
halign="left"
height="14"
layout="topleft"
- left="34"
+ left="10"
name="object_name_label"
- top_pad="0"
+ top_pad="5"
width="180">
Via object:
</text>
@@ -58,7 +46,7 @@
mouse_opaque="true"
name="icon_object"
tool_tip="Objects"
- top_pad="0"
+ top_pad="5"
left="10"
/>
<text
diff --git a/indra/newview/skins/default/xui/en/floater_report_abuse.xml b/indra/newview/skins/default/xui/en/floater_report_abuse.xml
index 21c0bfef48..47383c8010 100644
--- a/indra/newview/skins/default/xui/en/floater_report_abuse.xml
+++ b/indra/newview/skins/default/xui/en/floater_report_abuse.xml
@@ -373,7 +373,6 @@
height="23"
layout="topleft"
left_delta="0"
- max_length="32"
name="abuser_name_edit"
top_pad="0"
width="195" />
diff --git a/indra/newview/skins/default/xui/en/floater_sell_land.xml b/indra/newview/skins/default/xui/en/floater_sell_land.xml
index 4cae42bcfe..619669d28a 100644
--- a/indra/newview/skins/default/xui/en/floater_sell_land.xml
+++ b/indra/newview/skins/default/xui/en/floater_sell_land.xml
@@ -164,7 +164,7 @@
left_delta="0"
name="sell_to_agent"
top_pad="4"
- width="130" />
+ width="170" />
<button
height="20"
label="Select"
diff --git a/indra/newview/skins/default/xui/en/floater_tools.xml b/indra/newview/skins/default/xui/en/floater_tools.xml
index a96dbe3553..691dd79764 100644
--- a/indra/newview/skins/default/xui/en/floater_tools.xml
+++ b/indra/newview/skins/default/xui/en/floater_tools.xml
@@ -253,7 +253,7 @@
height="28"
control_name="EditLinkedParts"
label="Edit linked"
- layout="topleft"
+ layout="topleft"
name="checkbox edit linked parts"
top_pad="0">
<check_box.commit_callback
@@ -770,7 +770,7 @@
name="General"
top="16"
width="295">
-<panel.string
+ <panel.string
name="text deed continued">
Deed
</panel.string>
@@ -862,19 +862,23 @@
height="19"
layout="topleft"
name="Creator:"
+ top_pad="7"
width="90">
Creator:
</text>
+ <!-- *NOTE: Intentionally wide for long names -->
<text
type="string"
length="1"
follows="left|top"
left_pad="0"
- height="19"
+ height="30"
layout="topleft"
name="Creator Name"
- width="175">
- Esbee Linden
+ top_delta="0"
+ width="190"
+ word_wrap="true">
+ Mrs. Esbee Linden (esbee.linden)
</text>
<text
type="string"
@@ -884,19 +888,23 @@
height="19"
layout="topleft"
name="Owner:"
+ top_pad="3"
width="90">
Owner:
</text>
+ <!-- *NOTE: Intentionally wide for long names -->
<text
type="string"
length="1"
follows="left|top"
- height="19"
+ height="30"
layout="topleft"
name="Owner Name"
left_pad="0"
- width="175">
- Erica Linden
+ top_delta="0"
+ width="190"
+ word_wrap="true">
+ Mrs. Erica "Moose" Linden (erica.linden)
</text>
<text
type="string"
@@ -906,7 +914,7 @@
left="10"
height="18"
name="Group:"
- top_pad="4"
+ top_pad="7"
width="75">
Group:
</text>
@@ -1060,8 +1068,8 @@ even though the user gets a free copy.
bg_alpha_color="DkGray"
name="perms_build"
left="0"
- top="241"
- height="130"
+ top_pad="4"
+ height="105"
width="290">
<text
type="string"
@@ -1132,14 +1140,16 @@ even though the user gets a free copy.
top_delta="0"
tool_tip="Next owner can give away or resell this object"
width="100" />
+<!-- *NOTE: These "B/O/G/E/N/F fields may overlap "perm_modify" above,
+ but that's OK, this is used only for debugging. -->
<text
type="string"
text_color="EmphasisColor"
length="1"
- top_pad="5"
+ top="9"
follows="left|top"
layout="topleft"
- left="10"
+ left="230"
name="B:"
height="10"
width="80">
@@ -1151,7 +1161,8 @@ even though the user gets a free copy.
length="1"
follows="left|top"
layout="topleft"
- left_pad="0"
+ left_delta="0"
+ top_pad="2"
name="O:"
height="10"
width="80">
@@ -1163,7 +1174,8 @@ even though the user gets a free copy.
length="1"
follows="left|top"
layout="topleft"
- left_pad="0"
+ left_delta="0"
+ top_pad="2"
name="G:"
height="10"
width="80">
@@ -1174,7 +1186,7 @@ even though the user gets a free copy.
text_color="White"
length="1"
follows="left|top"
- left="10"
+ left_delta="0"
top_pad="2"
layout="topleft"
name="E:"
@@ -1188,7 +1200,8 @@ even though the user gets a free copy.
length="1"
follows="left|top"
layout="topleft"
- left_pad="0"
+ left_delta="0"
+ top_pad="2"
name="N:"
height="10"
width="80">
@@ -1200,7 +1213,8 @@ even though the user gets a free copy.
length="1"
follows="left|top"
layout="topleft"
- left_pad="0"
+ left_delta="0"
+ top_pad="2"
name="F:"
height="10"
width="80">
@@ -1208,6 +1222,7 @@ even though the user gets a free copy.
</text>
</panel>
</panel>
+ <!-- Object tab -->
<panel
border="false"
follows="all"
@@ -2955,4 +2970,5 @@ even though the user gets a free copy.
top_pad="4"
width="125" />
</panel>
+<!-- end of tabs -->
</floater>
diff --git a/indra/newview/skins/default/xui/en/inspect_avatar.xml b/indra/newview/skins/default/xui/en/inspect_avatar.xml
index 194ae151d2..a7ab021225 100644
--- a/indra/newview/skins/default/xui/en/inspect_avatar.xml
+++ b/indra/newview/skins/default/xui/en/inspect_avatar.xml
@@ -9,7 +9,7 @@
bg_opaque_image="Inspector_Background"
can_close="false"
can_minimize="false"
- height="148"
+ height="164"
layout="topleft"
name="inspect_avatar"
single_instance="true"
@@ -47,9 +47,20 @@
follows="top|left"
height="16"
left="8"
+ name="user_slid"
+ font="SansSerifSmall"
+ text_color="White"
+ value="James.pinden"
+ width="175"
+ use_ellipses="true" />
+ <text
+ follows="top|left"
+ height="16"
+ left="8"
name="user_subtitle"
font="SansSerifSmall"
text_color="White"
+ top_pad="0"
value="11 Months, 3 days old"
width="175"
use_ellipses="true" />
@@ -108,7 +119,7 @@
height="20"
label="Add Friend"
left="8"
- top="119"
+ top="135"
name="add_friend_btn"
width="90" />
<button
diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml
index 63ff7047b4..ccdc8266be 100644
--- a/indra/newview/skins/default/xui/en/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/en/menu_viewer.xml
@@ -2653,6 +2653,12 @@
<menu_item_call.on_click
function="Advanced.SendTestIMs" />
</menu_item_call>
+ <menu_item_call
+ label="Flush Names Caches"
+ name="Flush Names Caches">
+ <menu_item_call.on_click
+ function="Advanced.FlushNameCaches" />
+ </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 60d3fb708e..bf2cb636c8 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -257,7 +257,7 @@ Save all changes to clothing/body parts?
name="GrantModifyRights"
type="alertmodal">
Granting modify rights to another Resident allows them to change, delete or take ANY objects you may have in-world. Be VERY careful when handing out this permission.
-Do you want to grant modify rights for [FIRST_NAME] [LAST_NAME]?
+Do you want to grant modify rights for [NAME]?
<usetemplate
name="okcancelbuttons"
notext="No"
@@ -280,7 +280,7 @@ Do you want to grant modify rights for the selected Residents?
icon="alertmodal.tga"
name="RevokeModifyRights"
type="alertmodal">
-Do you want to revoke modify rights for [FIRST_NAME] [LAST_NAME]?
+Do you want to revoke modify rights for [NAME]?
<usetemplate
name="okcancelbuttons"
notext="No"
@@ -819,7 +819,7 @@ Delete pick &lt;nolink&gt;[PICK]&lt;/nolink&gt;?
icon="alertmodal.tga"
name="DeleteOutfits"
type="alertmodal">
- Delete the selected outfit/s?
+ Delete the selected outfit?
<usetemplate
name="okcancelbuttons"
notext="Cancel"
@@ -2021,20 +2021,6 @@ You do not have permission to buy land for your active group.
<notification
icon="alertmodal.tga"
label="Add Friend"
- name="AddFriend"
- type="alertmodal">
-Friends can give permissions to track each other on the map and receive online status updates.
-
-Offer friendship to [NAME]?
- <usetemplate
- name="okcancelbuttons"
- notext="Cancel"
- yestext="OK"/>
- </notification>
-
- <notification
- icon="alertmodal.tga"
- label="Add Friend"
name="AddFriendWithMessage"
type="alertmodal">
Friends can give permissions to track each other on the map and receive online status updates.
@@ -2128,7 +2114,7 @@ Would you be my friend?
icon="alertmodal.tga"
name="RemoveFromFriends"
type="alertmodal">
-Do you want to remove [FIRST_NAME] [LAST_NAME] from your Friends List?
+Do you want to remove [NAME] from your Friends List?
<usetemplate
name="okcancelbuttons"
notext="Cancel"
@@ -2381,7 +2367,7 @@ Deed this [AREA] m² of land to the group &apos;[GROUP_NAME]&apos;?
name="DeedLandToGroupWithContribution"
type="alertmodal">
By deeding this parcel, the group will be required to have and maintain sufficient land use credits.
-The deed will include a simultaneous land contribution to the group from &apos;[FIRST_NAME] [LAST_NAME]&apos;.
+The deed will include a simultaneous land contribution to the group from &apos;[NAME]&apos;.
The purchase price of the land is not refunded to the owner. If a deeded parcel is sold, the sale price will be divided evenly among group members.
Deed this [AREA] m² of land to the group &apos;[GROUP_NAME]&apos;?
@@ -3201,6 +3187,103 @@ You are no longer frozen.
<notification
icon="alertmodal.tga"
+ name="SetDisplayName"
+ type="alert">
+The name above your avatar's head is called a [http://wiki.secondlife.com/wiki/Setting_your_display_name display name]. You can change it periodically.
+
+Press reset to make it the same as your username.
+
+Change your display name?
+ <form name="form">
+ <input name="display_name" type="text">
+[DISPLAY_NAME]
+ </input>
+ <button
+ default="true"
+ index="0"
+ name="Change"
+ text="Change"/>
+ <button
+ index="1"
+ name="Reset"
+ text="Reset"/>
+ <button
+ index="2"
+ name="Cancel"
+ text="Cancel"/>
+ </form>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="SetDisplayNameSuccess"
+ type="alert">
+Hi [DISPLAY_NAME]!
+
+Just like in real life, it takes a while for everyone to learn about a new name. Please allow several days for [http://wiki.secondlife.com/wiki/Setting_your_display_name your name to update] in objects, scripts, search, etc.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="SetDisplayNameFailedLockout"
+ type="alert">
+Sorry, you cannot [http://wiki.secondlife.com/wiki/Setting_your_display_name change your display name] until:
+[TIME]
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="SetDisplayNameBlocked"
+ type="alert">
+Sorry, you cannot change your display name. If you feel this is in error, please contact support.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="SetDisplayNameFailedLength"
+ type="alertmodal">
+Sorry, that name is too long. Display names can have a maximum of [LENGTH] characters.
+
+Please try a shorter name.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="SetDisplayNameFailedGeneric"
+ type="alertmodal">
+ Sorry, we could not set your display name. Please try again later.
+ </notification>
+
+<!-- *NOTE: This should never happen, users should see SetDisplayNameFailedLockout above -->
+ <notification
+ icon="alertmodal.tga"
+ name="AgentDisplayNameUpdateThresholdExceeded"
+ type="alertmodal">
+Sorry, you have to wait longer before you can change your display name.
+
+See http://wiki.secondlife.com/wiki/Setting_your_display_name
+
+Please try again later.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="AgentDisplayNameSetBlocked"
+ type="alertmodal">
+ Sorry, we could not set your requested name because it contains a banned word.
+
+ Please try a different name.
+ </notification>
+
+ <notification
+ icon="notifytip.tga"
+ name="DisplayNameUpdate"
+ type="notifytip">
+ [OLD_NAME] ([SLID]) is now known as [NEW_NAME].
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
name="OfferTeleport"
type="alertmodal">
Offer a teleport to your location with the following message?
@@ -4503,14 +4586,14 @@ Topic: [SUBJECT], Message: [MESSAGE]
icon="notifytip.tga"
name="FriendOnline"
type="notifytip">
-[FIRST] [LAST] is Online
+[NAME] is Online
</notification>
<notification
icon="notifytip.tga"
name="FriendOffline"
type="notifytip">
-[FIRST] [LAST] is Offline
+[NAME] is Offline
</notification>
<notification
@@ -4666,13 +4749,6 @@ You cannot remove protected categories.
<notification
icon="notifytip.tga"
- name="OfferedCard"
- type="notifytip">
-You have offered a calling card to [FIRST] [LAST]
- </notification>
-
- <notification
- icon="notifytip.tga"
name="UnableToBuyWhileDownloading"
type="notifytip">
Unable to buy while downloading object data.
@@ -4826,7 +4902,15 @@ Please select at least one type of content to search (General, Moderate, or Adul
<notification
icon="notify.tga"
- name="PaymentRecived"
+ name="PaymentReceived"
+ persist="true"
+ type="notify">
+[MESSAGE]
+ </notification>
+
+ <notification
+ icon="notify.tga"
+ name="PaymentSent"
persist="true"
type="notify">
[MESSAGE]
@@ -4928,7 +5012,7 @@ The objects you own on the selected parcel of land have been returned back to yo
name="OtherObjectsReturned"
persist="true"
type="notify">
-The objects on the selected parcel of land that is owned by [FIRST] [LAST] have been returned to his or her inventory.
+The objects on the selected parcel of land that is owned by [NAME] have been returned to his or her inventory.
</notification>
<notification
@@ -5593,7 +5677,7 @@ Grant this request?
icon="notify.tga"
name="ScriptDialog"
type="notify">
-[FIRST] [LAST]&apos;s &apos;[TITLE]&apos;
+[NAME]&apos;s &apos;[TITLE]&apos;
[MESSAGE]
<form name="form">
<button
@@ -5823,7 +5907,7 @@ Click Accept to join the call or Decline to decline the invitation. Click Block
name="AutoUnmuteByIM"
persist="true"
type="notify">
-[FIRST] [LAST] was sent an instant message and has been automatically unblocked.
+[NAME] was sent an instant message and has been automatically unblocked.
</notification>
<notification
@@ -5831,7 +5915,7 @@ Click Accept to join the call or Decline to decline the invitation. Click Block
name="AutoUnmuteByMoney"
persist="true"
type="notify">
-[FIRST] [LAST] was given money and has been automatically unblocked.
+[NAME] was given money and has been automatically unblocked.
</notification>
<notification
@@ -5839,7 +5923,7 @@ Click Accept to join the call or Decline to decline the invitation. Click Block
name="AutoUnmuteByInventory"
persist="true"
type="notify">
-[FIRST] [LAST] was offered inventory and has been automatically unblocked.
+[NAME] was offered inventory and has been automatically unblocked.
</notification>
<notification
diff --git a/indra/newview/skins/default/xui/en/panel_activeim_row.xml b/indra/newview/skins/default/xui/en/panel_activeim_row.xml
index 3416b2369d..72f41c62f4 100644
--- a/indra/newview/skins/default/xui/en/panel_activeim_row.xml
+++ b/indra/newview/skins/default/xui/en/panel_activeim_row.xml
@@ -71,7 +71,7 @@
top="10"
left_pad="10"
height="14"
- width="255"
+ width="250"
length="1"
follows="right|left"
use_ellipses="true"
diff --git a/indra/newview/skins/default/xui/en/panel_edit_profile.xml b/indra/newview/skins/default/xui/en/panel_edit_profile.xml
index 5072ec3a66..e3cf25634b 100644
--- a/indra/newview/skins/default/xui/en/panel_edit_profile.xml
+++ b/indra/newview/skins/default/xui/en/panel_edit_profile.xml
@@ -87,12 +87,41 @@
min_height="300"
left="0"
width="292">
+ <text
+ follows="top|left"
+ font="SansSerifBigBold"
+ height="20"
+ layout="topleft"
+ left="10"
+ name="user_name"
+ text_color="white"
+ top="4"
+ value="Hamilton Hitchings"
+ width="280" />
+ <text
+ follows="top|left"
+ height="13"
+ layout="topleft"
+ left="10"
+ name="user_slid"
+ text_color="LtGray"
+ top_pad="5"
+ value="(hamilton.linden)"
+ width="150" />
+ <button
+ follows="top|left"
+ height="20"
+ label="Set Name..."
+ left="170"
+ name="set_name"
+ top_delta="-4"
+ width="110" />
<panel
name="lifes_images_panel"
follows="left|top|right"
height="244"
layout="topleft"
- top="0"
+ top="37"
left="0"
width="292">
<panel
@@ -146,8 +175,8 @@
height="102"
layout="topleft"
left="123"
- top="25"
- max_length="511"
+ top="62"
+ max_length="512"
name="sl_description_edit"
width="157"
word_wrap="true">
@@ -202,8 +231,8 @@
height="102"
layout="topleft"
left="123"
- max_length="254"
- top="157"
+ max_length="512"
+ top="195"
name="fl_description_edit"
width="157"
word_wrap="true">
@@ -301,7 +330,7 @@
left="10"
name="partner_data_panel"
width="200">
- <name_box
+ <text
follows="left|top|right"
height="30"
initial_value="(retrieving)"
diff --git a/indra/newview/skins/default/xui/en/panel_group_general.xml b/indra/newview/skins/default/xui/en/panel_group_general.xml
index 2af1a84400..f48440b34d 100644
--- a/indra/newview/skins/default/xui/en/panel_group_general.xml
+++ b/indra/newview/skins/default/xui/en/panel_group_general.xml
@@ -54,17 +54,15 @@ Hover your mouse over the options for more help.
top_delta="0">
Founder:
</text>
- <name_box
- follows="left|top"
+ <text
+ follows="left|top"
height="16"
- initial_value="(retrieving)"
layout="topleft"
left_delta="0"
- link="true"
name="founder_name"
top_pad="2"
use_ellipses="true"
- width="190" />
+ width="185" />
<text
font="SansSerifMedium"
text_color="EmphasisColor"
@@ -113,6 +111,7 @@ Hover your mouse over the options for more help.
layout="topleft"
left="0"
name="visible_members"
+ short_names="false"
top_pad="2">
<name_list.columns
label="Member"
diff --git a/indra/newview/skins/default/xui/en/panel_group_roles.xml b/indra/newview/skins/default/xui/en/panel_group_roles.xml
index 0eb5c47f85..0255cf80a1 100644
--- a/indra/newview/skins/default/xui/en/panel_group_roles.xml
+++ b/indra/newview/skins/default/xui/en/panel_group_roles.xml
@@ -81,6 +81,7 @@ clicking on their names.
right="-1"
multi_select="true"
name="member_list"
+ short_names="false"
top_pad="5">
<name_list.columns
label="Member"
diff --git a/indra/newview/skins/default/xui/en/panel_im_control_panel.xml b/indra/newview/skins/default/xui/en/panel_im_control_panel.xml
index 33a5e01e4c..a36f078f4f 100644
--- a/indra/newview/skins/default/xui/en/panel_im_control_panel.xml
+++ b/indra/newview/skins/default/xui/en/panel_im_control_panel.xml
@@ -24,25 +24,15 @@
top_pad="5"
width="114">
<layout_panel
- mouse_opaque="false"
- auto_resize="true"
- follows="top|left"
- height="0"
- layout="topleft"
- left="2"
- min_height="0"
- width="109"
- top="0"
- name="spacer"
- user_resize="false" />
- <layout_panel
auto_resize="false"
follows="top|left|right"
height="20"
layout="topleft"
+ left="2"
min_height="20"
width="109"
name="view_profile_btn_panel"
+ top="0"
user_resize="false">
<button
follows="left|top|right"
@@ -171,5 +161,15 @@
name="voice_ctrls_btn"
width="109" />
</layout_panel>
+ <layout_panel
+ mouse_opaque="false"
+ auto_resize="true"
+ follows="top|left"
+ height="0"
+ layout="topleft"
+ min_height="0"
+ width="109"
+ name="spacer"
+ user_resize="false" />
</layout_stack>
</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_instant_message.xml b/indra/newview/skins/default/xui/en/panel_instant_message.xml
index 34fd3352a3..021cf00d03 100644
--- a/indra/newview/skins/default/xui/en/panel_instant_message.xml
+++ b/indra/newview/skins/default/xui/en/panel_instant_message.xml
@@ -67,7 +67,7 @@
top="8"
use_ellipses="true"
value="Erica Vader"
- width="212" />
+ width="205" />
<!-- TIME STAMP -->
<text
font="SansSerifSmall"
diff --git a/indra/newview/skins/default/xui/en/panel_landmarks.xml b/indra/newview/skins/default/xui/en/panel_landmarks.xml
index a7e87f2a1e..8d43cc816c 100644
--- a/indra/newview/skins/default/xui/en/panel_landmarks.xml
+++ b/indra/newview/skins/default/xui/en/panel_landmarks.xml
@@ -3,7 +3,7 @@
name="Landmarks"
top="0"
height="400"
- layout="topleft"
+ layout="topleft"
left="0"
width="313"
help_topic="panel_landmarks"
@@ -88,7 +88,7 @@
</accordion_tab>
</accordion>
<panel
- background_visible="true"
+ background_visible="true"
bevel_style="none"
bottom="0"
follows="left|right|bottom"
diff --git a/indra/newview/skins/default/xui/en/panel_login.xml b/indra/newview/skins/default/xui/en/panel_login.xml
index 185e458a85..48b021efcf 100644
--- a/indra/newview/skins/default/xui/en/panel_login.xml
+++ b/indra/newview/skins/default/xui/en/panel_login.xml
@@ -65,12 +65,13 @@ Username:
<line_editor
follows="left|bottom"
height="22"
-label="Username"
+label="bobsmith12 or Steller Sunshine"
left_delta="0"
-max_length="31"
+max_length="63"
name="username_edit"
+prevalidate_callback="ascii"
select_on_focus="true"
-tool_tip="[SECOND_LIFE] Username"
+tool_tip="The username you chose when you registered, like bobsmith12 or Steller Sunshine"
top_pad="0"
width="150" />
<text
@@ -158,8 +159,8 @@ width="135"
<layout_panel
follows="right|bottom"
name="links"
-width="200"
-min_width="200"
+width="205"
+min_width="205"
user_resize="false"
height="80">
<text
@@ -171,7 +172,7 @@ height="16"
top="12"
right="-10"
name="create_new_account_text"
- width="180">
+ width="200">
Sign up
</text>
<text
@@ -183,8 +184,8 @@ height="16"
name="forgot_password_text"
top_pad="12"
right="-10"
- width="180">
- Forgot your name or password?
+ width="200">
+ Forgot your username or password?
</text>
<text
follows="right|bottom"
@@ -195,7 +196,7 @@ height="16"
name="login_help"
top_pad="2"
right="-10"
- width="180">
+ width="200">
Need help logging in? </text>
<!-- <text
follows="right|bottom"
diff --git a/indra/newview/skins/default/xui/en/panel_my_profile.xml b/indra/newview/skins/default/xui/en/panel_my_profile.xml
index 1083f4d467..ed903ba21e 100644
--- a/indra/newview/skins/default/xui/en/panel_my_profile.xml
+++ b/indra/newview/skins/default/xui/en/panel_my_profile.xml
@@ -285,7 +285,7 @@
name="partner_data_panel"
top_pad="0"
width="300">
- <name_box
+ <text
follows="left|top"
height="10"
initial_value="(retrieving)"
diff --git a/indra/newview/skins/default/xui/en/panel_outfit_edit.xml b/indra/newview/skins/default/xui/en/panel_outfit_edit.xml
index cf174da2f0..dde0db2513 100644
--- a/indra/newview/skins/default/xui/en/panel_outfit_edit.xml
+++ b/indra/newview/skins/default/xui/en/panel_outfit_edit.xml
@@ -57,6 +57,7 @@
<string
name="replace_body_part"
value="Click to replace your existing shape"/>
+
<button
follows="top|left"
@@ -197,19 +198,19 @@ It is calculated as border_size + 2*UIResizeBarOverlap
user_resize="false"
visible="true">
- <!-- List containing items from the COF and Base outfit -->
- <panel
- background_visible="false"
- class="cof_wearables"
- filename="panel_cof_wearables.xml"
+ <!-- List containing items from the COF and Base outfit -->
+ <panel
+ background_visible="false"
+ class="cof_wearables"
+ filename="panel_cof_wearables.xml"
follows="all"
height="129"
- layout="topleft"
- left="1"
- name="cof_wearables_list"
- top="0"
- width="311" />
-
+ layout="topleft"
+ left="1"
+ name="cof_wearables_list"
+ top="0"
+ width="311" />
+
<button
follows="left|bottom"
height="22"
@@ -228,7 +229,7 @@ It is calculated as border_size + 2*UIResizeBarOverlap
<combo_box
follows="left|right|bottom"
height="22"
- layout="topleft"
+ layout="topleft"
left_pad="5"
name="list_view_filter_combobox"
top_delta="0"
@@ -244,20 +245,20 @@ It is calculated as border_size + 2*UIResizeBarOverlap
visible="false"
width="152"/>
- <button
+ <button
follows="bottom|right"
height="22"
- image_overlay="Search_Icon"
+ image_overlay="Search_Icon"
image_pressed="PushButton_Press"
image_pressed_selected="PushButton_Selected_Press"
image_selected="PushButton_Selected_Press"
- is_toggle="true"
- layout="topleft"
- name="filter_button"
+ is_toggle="true"
+ layout="topleft"
+ name="filter_button"
right="-5"
- top_delta="0"
+ top_delta="0"
visible="false"
- width="20" />
+ width="20" />
</layout_panel>
<layout_panel
@@ -286,13 +287,13 @@ It is calculated as border_size + 2*UIResizeBarOverlap
</layout_panel>
</layout_stack>
- </layout_panel>
+ </layout_panel>
- <layout_panel
+ <layout_panel
background_visible="false"
bg_alpha_color="DkGray2"
- auto_resize="true"
+ auto_resize="true"
default_tab_group="3"
height="450"
min_height="53"
@@ -312,44 +313,44 @@ It is calculated as border_size + 2*UIResizeBarOverlap
top_pad="-9"
width="313" />
- <inventory_panel
- allow_multi_select="true"
- background_visible="false"
- border="false"
- follows="left|top|right|bottom"
+ <inventory_panel
+ allow_multi_select="true"
+ background_visible="false"
+ border="false"
+ follows="left|top|right|bottom"
height="418"
- layout="topleft"
- left="0"
- mouse_opaque="false"
+ layout="topleft"
+ left="0"
+ mouse_opaque="false"
name="folder_view"
top_pad="0"
width="313"
- visible="false"/>
- <panel
- name="filtered_wearables_panel"
- background_opaque="true"
- background_visible="false"
- layout="topleft"
- follows="left|top|right|bottom"
- border="false"
+ visible="false"/>
+ <panel
+ name="filtered_wearables_panel"
+ background_opaque="true"
+ background_visible="false"
+ layout="topleft"
+ follows="left|top|right|bottom"
+ border="false"
height="418"
- left="0"
- mouse_opaque="false"
+ left="0"
+ mouse_opaque="false"
width="310"
- top_delta="0"
- visible="true">
- <wearable_items_list
- color="0.107 0.107 0.107 1"
+ top_delta="0"
+ visible="true">
+ <wearable_items_list
+ color="0.107 0.107 0.107 1"
name="list_view"
- allow_select="true"
- layout="topleft"
- follows="all"
- multi_select="true"
+ allow_select="true"
+ layout="topleft"
+ follows="all"
+ multi_select="true"
width="313"
height="418"
- left="0"
- top="0"/>
- </panel>
+ left="0"
+ top="0"/>
+ </panel>
<button
follows="bottom|left"
height="22"
@@ -360,7 +361,7 @@ It is calculated as border_size + 2*UIResizeBarOverlap
top_pad="5"
width="130" />
- </layout_panel>
+ </layout_panel>
</layout_stack>
@@ -461,15 +462,15 @@ It is calculated as border_size + 2*UIResizeBarOverlap
name="list_view_btn"
top="1"
width="31" />
- <icon
- follows="bottom|left|right"
- height="25"
+ <icon
+ follows="bottom|left|right"
+ height="25"
image_name="Toolbar_Middle_Off"
- layout="topleft"
- left_pad="1"
+ layout="topleft"
+ left_pad="1"
name="dummy_right_icon"
width="186" >
- </icon>
+ </icon>
<button
follows="bottom|right"
height="25"
@@ -484,7 +485,7 @@ It is calculated as border_size + 2*UIResizeBarOverlap
tool_tip="Visit the SL Marketplace. You can also select something you are wearing, then click here to see more things like it"
width="31" />
</panel>
-
+
<!-- SAVE AND REVERT BUTTONS -->
<panel
follows="left|right|bottom"
diff --git a/indra/newview/skins/default/xui/en/panel_people.xml b/indra/newview/skins/default/xui/en/panel_people.xml
index 7cd0d5b5f0..1353d401c3 100644
--- a/indra/newview/skins/default/xui/en/panel_people.xml
+++ b/indra/newview/skins/default/xui/en/panel_people.xml
@@ -81,7 +81,7 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M
width="317">
<panel
background_opaque="true"
- background_visible="true"
+ background_visible="true"
bg_alpha_color="DkGray"
bg_opaque_color="DkGray"
follows="all"
@@ -155,7 +155,7 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M
</panel>
<panel
background_opaque="true"
- background_visible="true"
+ background_visible="true"
bg_alpha_color="DkGray"
bg_opaque_color="DkGray"
follows="all"
@@ -280,7 +280,7 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M
</panel>
<panel
background_opaque="true"
- background_visible="true"
+ background_visible="true"
bg_alpha_color="DkGray"
bg_opaque_color="DkGray"
follows="all"
@@ -365,7 +365,7 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M
</panel>
<panel
background_opaque="true"
- background_visible="true"
+ background_visible="true"
bg_alpha_color="DkGray"
bg_opaque_color="DkGray"
follows="all"
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 31d8ea27d9..7d9bd1bf2a 100644
--- a/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml
+++ b/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml
@@ -125,6 +125,7 @@ Automatic position for:
left_pad="30"
name="first_person_avatar_visible"
width="256" />
+
<check_box
control_name="ArrowKeysAlwaysMove"
follows="left|top"
@@ -206,7 +207,7 @@ Automatic position for:
left="80"
name="UI Size:"
top_pad="25"
- width="160">
+ width="300">
UI size
</text>
<slider
@@ -302,6 +303,7 @@ Automatic position for:
halign="center"
height="23"
image_overlay="Refresh_Off"
+ layout="topleft"
tool_tip="Reset to Middle Mouse Button"
mouse_opaque="true"
name="set_voice_middlemouse_button"
@@ -315,7 +317,7 @@ Automatic position for:
label="Other Devices"
left="30"
name="joystick_setup_button"
- top="27"
+ top_pad="27"
width="155">
<button.commit_callback
function="Floater.Show"
diff --git a/indra/newview/skins/default/xui/en/panel_preferences_general.xml b/indra/newview/skins/default/xui/en/panel_preferences_general.xml
index a69e8d29b0..2cf4118e19 100644
--- a/indra/newview/skins/default/xui/en/panel_preferences_general.xml
+++ b/indra/newview/skins/default/xui/en/panel_preferences_general.xml
@@ -222,28 +222,27 @@
</text>
<radio_group
control_name="AvatarNameTagMode"
- height="20"
+ height="45"
layout="topleft"
left="50"
name="Name_Tag_Preference">
<radio_item
label="Off"
- layout="topleft"
name="radio"
value="0"
width="75" />
<radio_item
label="On"
- layout="topleft"
- left_pad="12"
+ left_delta="0"
name="radio2"
+ top_pad="5"
value="1"
width="75" />
<radio_item
label="Show briefly"
- layout="topleft"
- left_pad="12"
+ left_delta="0"
name="radio3"
+ top_pad="5"
value="2"
width="160" />
</radio_group>
@@ -253,18 +252,58 @@
height="16"
label="Show my name"
layout="topleft"
- left="50"
+ left="70"
name="show_my_name_checkbox1"
+ top_pad="4"
width="300" />
<check_box
+ control_name="NameTagShowFriends"
enabled_control="AvatarNameTagMode"
- control_name="RenderShowGroupTitleAll"
height="16"
- label="Show group titles"
+ label="Highlight friends"
+ left_delta="0"
+ name="show_friends"
+ tool_tip="Highlight the name tags of your friends"
+ top_pad="2" />
+ <text
+ follows="left|top"
+ height="15"
layout="topleft"
- left_delta="175"
+ left="250"
+ name="name_tags_textbox"
+ top="175"
+ width="200">
+ Tags show:
+ </text>
+ <check_box
+ control_name="NameTagShowGroupTitles"
+ enabled_control="AvatarNameTagMode"
+ height="16"
+ label="Group titles"
+ left="265"
name="show_all_title_checkbox1"
- width="200" />
+ tool_tip="Show group titles, like Officer or Member"
+ top_pad="5" />
+ <!--
+ <check_box
+ control_name="NameTagShowDisplayNames"
+ enabled_control="AvatarNameTagMode"
+ height="16"
+ label="Display names"
+ left_delta="0"
+ name="show_display_names"
+ tool_tip="Show display names, like José Sanchez"
+ top_pad="5" />
+ -->
+ <check_box
+ control_name="NameTagShowUsernames"
+ enabled_control="AvatarNameTagMode"
+ height="16"
+ label="Usernames"
+ left_delta="0"
+ name="show_slids"
+ tool_tip="Show username, like bobsmith123"
+ top_pad="2" />
<text
type="string"
length="1"
@@ -273,7 +312,7 @@
layout="topleft"
left="30"
name="effects_color_textbox"
- top_pad="15"
+ top="290"
width="200">
My effects:
</text>
@@ -285,6 +324,7 @@
layout="topleft"
left_pad="5"
name="title_afk_text"
+ top_delta="0"
width="190">
Away timeout:
</text>
@@ -353,8 +393,8 @@
bg_writeable_color="LtGray"
use_ellipses="false"
commit_on_focus_lost = "true"
- follows="left|top|right"
- height="60"
+ follows="left|top"
+ height="42"
layout="topleft"
left="50"
name="busy_response"
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 2c6ceeef2e..7148aba00a 100644
--- a/indra/newview/skins/default/xui/en/panel_preferences_setup.xml
+++ b/indra/newview/skins/default/xui/en/panel_preferences_setup.xml
@@ -115,7 +115,7 @@
layout="topleft"
left="77"
name="connection_port_enabled"
- top_pad="20"
+ top_pad="15"
width="256">
<check_box.commit_callback
function="Notification.Show"
@@ -147,7 +147,7 @@
left="80"
mouse_opaque="false"
name="cache_size_label_l"
- top_pad="20"
+ top_pad="10"
width="200">
Cache size
</text>
@@ -375,4 +375,27 @@
name="web_proxy_port"
top_delta="0"
width="145" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left="30"
+ name="Communications:"
+ top_pad="5"
+ width="300">
+ Communications:
+ </text>
+ <check_box
+control_name="UseDisplayNames"
+follows="top|left"
+height="15"
+label="Use Display Names"
+layout="topleft"
+left_delta="50"
+name="display_names_check"
+width="237"
+tool_tip="Check to use display names in chat, IM, name tags, etc."
+top_pad="10"/>
</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_profile.xml b/indra/newview/skins/default/xui/en/panel_profile.xml
index fc33836c79..a931c55dfe 100644
--- a/indra/newview/skins/default/xui/en/panel_profile.xml
+++ b/indra/newview/skins/default/xui/en/panel_profile.xml
@@ -265,7 +265,7 @@
name="partner_data_panel"
top_pad="0"
width="300">
- <name_box
+ <text
follows="left|top"
height="10"
initial_value="(retrieving)"
diff --git a/indra/newview/skins/default/xui/en/panel_profile_view.xml b/indra/newview/skins/default/xui/en/panel_profile_view.xml
index d9030fc0d6..9745f89e31 100644
--- a/indra/newview/skins/default/xui/en/panel_profile_view.xml
+++ b/indra/newview/skins/default/xui/en/panel_profile_view.xml
@@ -50,8 +50,19 @@
height="13"
layout="topleft"
left="45"
+ name="user_slid"
+ text_color="LtGray"
+ value=""
+ width="150" />
+ <text
+ follows="top|left"
+ halign="right"
+ height="13"
+ layout="topleft"
+ left="150"
name="status"
text_color="LtGray_50"
+ top_delta="0"
value="Online"
width="150" />
<tab_container
diff --git a/indra/newview/skins/default/xui/en/panel_region_debug.xml b/indra/newview/skins/default/xui/en/panel_region_debug.xml
index a6b4ddd01e..15df095efa 100644
--- a/indra/newview/skins/default/xui/en/panel_region_debug.xml
+++ b/indra/newview/skins/default/xui/en/panel_region_debug.xml
@@ -103,7 +103,7 @@
mouse_opaque="false"
name="target_avatar_name"
top_delta="-2"
- width="180">
+ width="270">
(none)
</line_editor>
<button
diff --git a/indra/newview/skins/default/xui/en/panel_region_estate.xml b/indra/newview/skins/default/xui/en/panel_region_estate.xml
index 08e36d5e57..1307d807e2 100644
--- a/indra/newview/skins/default/xui/en/panel_region_estate.xml
+++ b/indra/newview/skins/default/xui/en/panel_region_estate.xml
@@ -72,7 +72,8 @@
left_delta="0"
name="estate_owner"
top_delta="16"
- width="150">
+ use_ellipses="true"
+ width="290">
(unknown)
</text>
<view_border
diff --git a/indra/newview/skins/default/xui/en/sidepanel_item_info.xml b/indra/newview/skins/default/xui/en/sidepanel_item_info.xml
index 50df227fbf..79421c0e01 100644
--- a/indra/newview/skins/default/xui/en/sidepanel_item_info.xml
+++ b/indra/newview/skins/default/xui/en/sidepanel_item_info.xml
@@ -164,7 +164,7 @@
left_pad="5"
name="LabelCreatorName"
top_delta="6"
- width="140">
+ width="180">
</text>
<button
follows="top|right"
@@ -206,7 +206,7 @@
left_pad="5"
name="LabelOwnerName"
top_delta="6"
- width="140">
+ width="180">
</text>
<button
follows="top|right"
diff --git a/indra/newview/skins/default/xui/en/sidepanel_task_info.xml b/indra/newview/skins/default/xui/en/sidepanel_task_info.xml
index 843015cb8b..5da449de3d 100644
--- a/indra/newview/skins/default/xui/en/sidepanel_task_info.xml
+++ b/indra/newview/skins/default/xui/en/sidepanel_task_info.xml
@@ -167,7 +167,7 @@
left_pad="0"
name="Creator Name"
top_delta="0"
- width="140">
+ width="225">
Erica Linden
</text>
<text
@@ -191,7 +191,7 @@
left_pad="0"
name="Owner Name"
top_delta="0"
- width="140">
+ width="225">
Erica Linden
</text>
<text
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index b91acbe27d..2e865af1e6 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -89,6 +89,7 @@
<string name="TooltipHttpUrl">Click to view this web page</string>
<string name="TooltipSLURL">Click to view this location's information</string>
<string name="TooltipAgentUrl">Click to view this Resident's profile</string>
+ <string name="TooltipAgentInspect">Learn more about this Resident</string>
<string name="TooltipAgentMute">Click to mute this Resident</string>
<string name="TooltipAgentUnmute">Click to unmute this Resident</string>
<string name="TooltipAgentIM">Click to IM this Resident</string>
@@ -3032,7 +3033,7 @@ If you continue to receive this message, contact the [SUPPORT_SITE].
You are the only user in this session.
</string>
<string name="offline_message">
- [FIRST] [LAST] is offline.
+ [NAME] is offline.
</string>
<string name="invite_message">
Click the [BUTTON NAME] button to accept/connect to this voice chat.
@@ -3118,17 +3119,20 @@ If you continue to receive this message, contact the [SUPPORT_SITE].
<string name="voice_morphing_url">http://secondlife.com/landing/voicemorphing</string>
<!-- Financial operations strings -->
- <string name="paid_you_ldollars">[NAME] paid you L$[AMOUNT]</string>
+ <string name="paid_you_ldollars">[NAME] paid you L$[AMOUNT] [REASON].</string>
+ <string name="paid_you_ldollars_no_reason">[NAME] paid you L$[AMOUNT].</string>
<string name="you_paid_ldollars">You paid [NAME] L$[AMOUNT] [REASON].</string>
<string name="you_paid_ldollars_no_info">You paid L$[AMOUNT].</string>
<string name="you_paid_ldollars_no_reason">You paid [NAME] L$[AMOUNT].</string>
<string name="you_paid_ldollars_no_name">You paid L$[AMOUNT] [REASON].</string>
+ <string name="for item">for [ITEM]</string>
<string name="for a parcel of land">for a parcel of land</string>
<string name="for a land access pass">for a land access pass</string>
<string name="for deeding land">for deeding land</string>
<string name="to create a group">to create a group</string>
<string name="to join a group">to join a group</string>
<string name="to upload">to upload</string>
+ <string name="to publish a classified ad">to publish a classified ad</string>
<string name="giving">Giving L$ [AMOUNT]</string>
<string name="uploading_costs">Uploading costs L$ [AMOUNT]</string>
diff --git a/indra/newview/skins/default/xui/es/notifications.xml b/indra/newview/skins/default/xui/es/notifications.xml
index 88013df8f5..f2ef987d66 100644
--- a/indra/newview/skins/default/xui/es/notifications.xml
+++ b/indra/newview/skins/default/xui/es/notifications.xml
@@ -1419,7 +1419,7 @@ Esta actualización no es obligatoria, pero te sugerimos instalarla para mejorar
</notification>
<notification name="BusyModeSet">
Pasar al modo ocupado.
-Se ocultará el chat y los mensajes instantáneos (éstos recibirán tu Respuesta en el modo ocupado). Se rehusarán todos los ofrecimientos de teleporte. Todas las ofertas de inventario irán a tu Papelera.
+Se ocultará el chat y los mensajes instantáneos (éstos recibirán tu Respuesta en el modo ocupado). Se rehusarán todos los ofrecimientos de teleporte. Todas las ofertas de inventario irán a tu Papelera.
<usetemplate ignoretext="Cambio mi estado al modo ocupado" name="okignore" yestext="OK"/>
</notification>
<notification name="JoinedTooManyGroupsMember">
@@ -1886,7 +1886,7 @@ Linden Lab
</form>
</notification>
<notification name="ConfirmDeleteProtectedCategory">
- La carpeta &apos;[FOLDERNAME]&apos; pertenece al sistema, y borrar carpetas del sistema puede provocar inestabilidad. ¿Estás seguro de que quieres borrarla?
+ La carpeta &apos;[FOLDERNAME]&apos; pertenece al sistema, y borrar carpetas del sistema puede provocar inestabilidad. ¿Estás seguro de que quieres borrarla?
<usetemplate ignoretext="Confirmar antes de borrar una carpeta del sistema" name="okcancelignore" notext="Cancelar" yestext="OK"/>
</notification>
<notification name="ConfirmEmptyTrash">
@@ -2445,7 +2445,7 @@ Esto añadirá un marcador en tu inventario para que puedas enviarle rápidament
Si permaneces en esta región serás desconectado.
</notification>
<notification name="RegionRestartSeconds">
- Esta región se reiniciará en [SECONDS] segundos.
+ Esta región se reiniciará en [SECONDS] segundos.
Si permaneces en esta región serás desconectado.
</notification>
<notification name="LoadWebPage">
@@ -2509,7 +2509,7 @@ Si no confias en este objeto y en su creador, deberías rehusar esta petición.
<notification name="BuyLindenDollarSuccess">
¡Gracias por tu pago!
-Tu saldo de L$ se actualizará cuando se complete el proceso. Si el proceso tarda más de 20 minutos, se cancelará tu transacción, y la cantidad se cargará en tu saldo de US$.
+Tu saldo de L$ se actualizará cuando se complete el proceso. Si el proceso tarda más de 20 minutos, se cancelará tu transacción, y la cantidad se cargará en tu saldo de US$.
Puedes revisar el estado de tu pago en el Historial de transacciones de tu [http://secondlife.com/account/ Panel de Control]
</notification>
diff --git a/indra/newview/skins/default/xui/fr/notifications.xml b/indra/newview/skins/default/xui/fr/notifications.xml
index 59c978bb6b..3dc4f4bd93 100644
--- a/indra/newview/skins/default/xui/fr/notifications.xml
+++ b/indra/newview/skins/default/xui/fr/notifications.xml
@@ -178,7 +178,7 @@ Voulez-vous continuer ?
<notification name="JoinGroupNoCost">
Vous vous apprêtez à rejoindre le groupe [NAME].
Voulez-vous continuer ?
- <usetemplate name="okcancelbuttons" notext="Annuler" yestext="Rejoindre"/>
+ <usetemplate name="okcancelbuttons" notext="Annuler" yestext="Fusionner"/>
</notification>
<notification name="JoinGroupCannotAfford">
Rejoindre ce groupe coûte [COST] L$.
diff --git a/indra/newview/skins/default/xui/fr/panel_group_general.xml b/indra/newview/skins/default/xui/fr/panel_group_general.xml
index ec6d995274..a2655dcd45 100644
--- a/indra/newview/skins/default/xui/fr/panel_group_general.xml
+++ b/indra/newview/skins/default/xui/fr/panel_group_general.xml
@@ -48,7 +48,7 @@ Faites glisser le pointeur de la souris sur les options pour en savoir plus.
<spinner label="L$" name="spin_enrollment_fee" tool_tip="Les nouveaux membres doivent payer ces frais pour rejoindre le groupe quand l&apos;option Frais d&apos;inscription est cochée."/>
<combo_box name="group_mature_check" tool_tip="Définit si votre groupe contient des informations de type Modéré" width="195">
<combo_item name="select_mature">
- - Sélectionner une catégorie de contenu -
+ - Catégorie de contenu -
</combo_item>
<combo_box.item label="Contenu Modéré" name="mature"/>
<combo_box.item label="Contenu Général" name="pg"/>
diff --git a/indra/newview/skins/default/xui/it/floater_about_land.xml b/indra/newview/skins/default/xui/it/floater_about_land.xml
index c9a004be9f..af83a38746 100644
--- a/indra/newview/skins/default/xui/it/floater_about_land.xml
+++ b/indra/newview/skins/default/xui/it/floater_about_land.xml
@@ -320,7 +320,7 @@ Solamente terreni più grandi possono essere abilitati nella ricerca.
<text name="allow_label">
Permetti ad altri residenti di:
</text>
- <check_box label="Modificare il terreno" name="edit land check" tool_tip="Se spuntato, chiunque può terraformare il tuo terreno. E&apos; preferibile lasciare questo quadrato non spuntato, dato che sarai sempre in grado di modificare il tuo terreno."/>
+ <check_box label="Modificare il terreno" name="edit land check" tool_tip="Se spuntata, chiunque può terraformare il tuo terreno. È preferibile lasciare questa opzione non spuntata, dato che sarai comunque in grado di modificare il tuo terreno."/>
<check_box label="Permetti il volo" name="check fly" tool_tip="Se spuntato, gli altri residenti potranno volare sul tuo terreno. Se non spuntato, potranno solamente arrivare in volo o sorvolare il terreno."/>
<text name="allow_label2">
Creare oggetti:
@@ -328,7 +328,7 @@ Solamente terreni più grandi possono essere abilitati nella ricerca.
<check_box label="Tutti i residenti" name="edit objects check"/>
<check_box label="Gruppo" name="edit group objects check"/>
<text name="allow_label3">
- Entrata oggetti:
+ Immissione oggetti:
</text>
<check_box label="Tutti i residenti" name="all object entry check"/>
<check_box label="Gruppo" name="group object entry check"/>
@@ -340,9 +340,9 @@ Solamente terreni più grandi possono essere abilitati nella ricerca.
<text name="land_options_label">
Opzioni per il terreno:
</text>
- <check_box label="Sicuro (senza danno)" name="check safe" tool_tip="Se spuntato, imposta il terreno su &apos;sicuro&apos;, disabilitando i danni da combattimento. Se non spuntato, viene abilitato il combattimento a morte."/>
+ <check_box label="Sicuro (senza danno)" name="check safe" tool_tip="Se spuntato, imposta il terreno su &apos;sicuro&apos;, disabilitando i danni da combattimento. Se non spuntato, viene abilitato il combattimento con danni."/>
<check_box label="Nessuna spinta" name="PushRestrictCheck" tool_tip="Previeni i colpi. Selezionare questa opzione può essere utile per prevenire comportamenti dannosi sul tuo terreno."/>
- <check_box label="Mostra luogo nella ricerca (30 L$/settimana)" name="ShowDirectoryCheck" tool_tip="Lascia che questa terra sia vista dagli altri nei risultati di ricerca"/>
+ <check_box label="Mostra luogo nella ricerca (30 L$/settimana)" name="ShowDirectoryCheck" tool_tip="Consenti che il lotto sia visto nei risultati di ricerca"/>
<combo_box name="land category with adult">
<combo_box.item label="Tutte le categorie" name="item0"/>
<combo_box.item label="Luogo dei Linden" name="item1"/>
@@ -421,7 +421,7 @@ Texture:
<spinner left_delta="104" name="media_size_width" tool_tip="Aumenta larghezza per far vedere meglio i media web, lascia a 0 per impostare il default."/>
<spinner name="media_size_height" tool_tip="Aumenta altezza per far vedere meglio i media web, lascia a 0 per impostare il default."/>
<text name="pixels">
- pixels
+ pixel
</text>
<text name="Options:">
Opzioni
diff --git a/indra/newview/skins/default/xui/it/floater_buy_currency.xml b/indra/newview/skins/default/xui/it/floater_buy_currency.xml
index 1327e8b172..0a499a6c44 100644
--- a/indra/newview/skins/default/xui/it/floater_buy_currency.xml
+++ b/indra/newview/skins/default/xui/it/floater_buy_currency.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<floater name="buy currency" title="ACQUISTA L$">
<floater.string name="buy_currency">
- Acquista [LINDENS] L$ per circa [LOCALAMOUNT]
+ acquistare [LINDENS] L$ per circa [LOCALAMOUNT]
</floater.string>
<text font="SansSerifLarge" left="5" name="info_need_more" right="-5">
Ti servono più L$
@@ -57,8 +57,8 @@
<text bottom_delta="16" name="purchase_warning_notenough">
Non stai acquistando abbastanza L$. Aumenta l&apos;importo.
</text>
- <button label="Acquista adesso" name="buy_btn"/>
- <button label="Cancella" name="cancel_btn"/>
+ <button label="Acquista" name="buy_btn"/>
+ <button label="Annulla" name="cancel_btn"/>
<text left="5" name="info_cannot_buy" right="-5">
Non in grado di acquistare
</text>
diff --git a/indra/newview/skins/default/xui/it/panel_people.xml b/indra/newview/skins/default/xui/it/panel_people.xml
index 056e424436..3d07ff45ba 100644
--- a/indra/newview/skins/default/xui/it/panel_people.xml
+++ b/indra/newview/skins/default/xui/it/panel_people.xml
@@ -3,7 +3,7 @@
<panel label="Persone" name="people_panel">
<string name="no_recent_people" value="Nessuna persona recente. Stai cercando persone da frequentare? Prova la [secondlife:///app/search/people Ricerca] o la [secondlife:///app/worldmap Mappa del mondo]."/>
<string name="no_filtered_recent_people" value="Non riesci a trovare quello che cerchi? Prova [secondlife:///app/search/people/[SEARCH_TERM] Cerca]."/>
- <string name="no_one_near" value="Nessuno vicino. Stai cercando persone da frequentare? Try la [secondlife:///app/search/people Ricerca] o la [secondlife:///app/worldmap Mappa del mondo]."/>
+ <string name="no_one_near" value="Nessuno vicino. Stai cercando persone da frequentare? Prova a vedere la [secondlife:///app/search/people Ricerca] o la [secondlife:///app/worldmap Mappa del mondo]."/>
<string name="no_one_filtered_near" value="Non riesci a trovare quello che cerchi? Prova [secondlife:///app/search/people/[SEARCH_TERM] Cerca]."/>
<string name="no_friends_online" value="Nessun amico online"/>
<string name="no_friends" value="Nessun amico"/>
diff --git a/indra/newview/skins/default/xui/ja/panel_group_land_money.xml b/indra/newview/skins/default/xui/ja/panel_group_land_money.xml
index 4b3a7f880b..016dc97ab6 100644
--- a/indra/newview/skins/default/xui/ja/panel_group_land_money.xml
+++ b/indra/newview/skins/default/xui/ja/panel_group_land_money.xml
@@ -48,7 +48,7 @@
あなたの貢献:
</text>
<text name="your_contribution_units">
- m²
+ 平方メートル
</text>
<text name="your_contribution_max_value">
(最大 [AMOUNT])
diff --git a/indra/newview/skins/default/xui/ja/panel_group_roles.xml b/indra/newview/skins/default/xui/ja/panel_group_roles.xml
index 8a629be910..db6fe268c7 100644
--- a/indra/newview/skins/default/xui/ja/panel_group_roles.xml
+++ b/indra/newview/skins/default/xui/ja/panel_group_roles.xml
@@ -17,7 +17,7 @@ Ctrl キーを押しながらメンバー名をクリックすると
<name_list name="member_list">
<name_list.columns label="メンバー" name="name"/>
<name_list.columns label="寄付" name="donated"/>
- <name_list.columns label="ログイン" name="online"/>
+ <name_list.columns label="ステータス" name="online"/>
</name_list>
<button label="招待" name="member_invite"/>
<button label="追放" name="member_eject"/>
@@ -44,7 +44,7 @@ Ctrl キーを押しながらメンバー名をクリックすると
<filter_editor label="役割を選別" name="filter_input"/>
<scroll_list name="role_list">
<scroll_list.columns label="役割" name="name"/>
- <scroll_list.columns label="タイトル" name="title"/>
+ <scroll_list.columns label="肩書き" name="title"/>
<scroll_list.columns label="#" name="members"/>
</scroll_list>
<button label="新しい役割" name="role_create"/>
diff --git a/indra/newview/skins/default/xui/pt/floater_preview_gesture.xml b/indra/newview/skins/default/xui/pt/floater_preview_gesture.xml
index 364638780a..a01bee94a1 100644
--- a/indra/newview/skins/default/xui/pt/floater_preview_gesture.xml
+++ b/indra/newview/skins/default/xui/pt/floater_preview_gesture.xml
@@ -1,16 +1,16 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<floater name="gesture_preview">
<floater.string name="step_anim">
- Selecionar animação:
+ Executar animação:
</floater.string>
<floater.string name="step_sound">
- Selecionar animação:
+ Executar som:
</floater.string>
<floater.string name="step_chat">
- Diga por bate-papo:
+ Executar bate-papo:
</floater.string>
<floater.string name="step_wait">
- Espere:
+ Pausa
</floater.string>
<floater.string name="stop_txt">
Parar
@@ -31,11 +31,11 @@
Gatilho:
</text>
<text name="replace_text" tool_tip="Substituir a(s) palavra(s) de gatilho por estas palavras. Por exemplo, o gatilho &apos;oi&apos; substituído por &apos;olá&apos;, mudará a conversa de &apos;Eu digo oi&apos; para &apos;Eu digo olá&apos; e também executando o gesto!">
- Substituir por:
+ Trocar por:
</text>
- <line_editor name="replace_editor" tool_tip="Substituir a(s) palavra(s) gatilho por estas palavras.Por exemplo, o gatilho &apos;oi&apos; substituído por &apos;olá&apos;, mudará a conversa de &apos;Eu digo oi&apos; para &apos;Eu digo olá&apos; e também executando o gesto!"/>
+ <line_editor name="replace_editor" tool_tip="Substituir a(s) palavra(s) gatilho por estas palavras. Por exemplo, o gatilho &apos;oi&apos; substituído por &apos;olá&apos;, mudará a conversa de &apos;Eu digo oi&apos; para &apos;Eu digo olá&apos; e também executando o gesto!"/>
<text name="key_label">
- Tecla de Atalho:
+ Atalho:
</text>
<combo_box label="Nenhum" left="116" name="modifier_combo" width="76"/>
<combo_box label="Nenhum" left_delta="80" name="key_combo" width="76"/>
@@ -55,16 +55,16 @@
(opções)
</text>
<radio_group name="animation_trigger_type">
- <radio_item label="OK" name="start"/>
- <radio_item label="Pare" name="stop"/>
+ <radio_item label="Iniciar" name="start"/>
+ <radio_item label="Parar" name="stop"/>
</radio_group>
<check_box bottom_delta="34" label="até que as animações estejam concluídas" name="wait_anim_check"/>
<check_box bottom_delta="-30" label="segundos:" name="wait_time_check"/>
<line_editor left_delta="130" name="wait_time_editor"/>
<text name="help_label">
- Se não incluir etapas de espera, todas as etapas ocorrem ao mesmo tempo.
+ Se não incluir uma pausa, todas as etapas ocorrem ao mesmo tempo.
</text>
- <check_box label="Ativar" name="active_check" tool_tip="Gestos ativos podem ser gatilhados escrevendo suas frases de gatilho no chat ou através de suas teclas de atalho. Gestos normalmente ficam inativos quando existe um conflito nas teclas de atalho."/>
+ <check_box label="Ativar" name="active_check" tool_tip="Gestos podem ser ativados escrevendo suas frases de gatilho no chat ou teclando o atalho. Gestos normalmente ficam inativos quando existe um conflito nas teclas de atalho."/>
<button label="Prévia" name="preview_btn"/>
<button label="Salvar" name="save_btn"/>
</floater>
diff --git a/indra/newview/skins/default/xui/pt/floater_tools.xml b/indra/newview/skins/default/xui/pt/floater_tools.xml
index dbc8b3ffbe..e70bd0575e 100644
--- a/indra/newview/skins/default/xui/pt/floater_tools.xml
+++ b/indra/newview/skins/default/xui/pt/floater_tools.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<floater name="toolbox floater" short_title="BUILD TOOLS" title="" width="288">
<floater.string name="status_rotate">
- Arrastar as bandas coloridas para girar o objeto
+ Arrastar as faixas coloridas para girar o objeto
</floater.string>
<floater.string name="status_scale">
Clicar e arrastar para esticar o lado selecionado
@@ -13,13 +13,13 @@
Clicar e reter para modificar a terra
</floater.string>
<floater.string name="status_camera">
- Clique e arraste para mexer a câmera
+ Clicar e arrastar para mover a câmera
</floater.string>
<floater.string name="status_grab">
- Arraste para mexer, Ctrl para levantar, Ctrl+Shift para girar
+ Arrastar para mexer, Ctrl para levantar, Ctrl+Shift para girar
</floater.string>
<floater.string name="status_place">
- Clique no mundo para construir
+ Clicar em um lugar para construir
</floater.string>
<floater.string name="status_selectland">
Clicar e arrastar para selecionar a terra
@@ -45,7 +45,7 @@
<button label="" label_selected="" name="button create" tool_tip="Criar"/>
<button label="" label_selected="" name="button land" tool_tip="Terra"/>
<text name="text status" width="280">
- Arraste para mover, shift+Arrastar para Copiar
+ Arrastar para mover, shift+Arrastar para copiar
</text>
<radio_group name="focus_radio_group">
<radio_item label="Zoom" name="radio zoom"/>
@@ -58,10 +58,10 @@
<radio_item label="Spin (Ctrl+Shift)" name="radio spin"/>
</radio_group>
<radio_group name="edit_radio_group">
- <radio_item label="Movimentar" name="radio position"/>
+ <radio_item label="Mover" name="radio position"/>
<radio_item label="Rotacionar (Ctrl)" name="radio rotate"/>
- <radio_item label="Stretch (Ctrl+Shift)" name="radio stretch"/>
- <radio_item label="Face selecionada" name="radio select face"/>
+ <radio_item label="Esticar (Ctrl+Shift)" name="radio stretch"/>
+ <radio_item label="Selecionar face" name="radio select face"/>
</radio_group>
<check_box label="Editar partes linkadas" name="checkbox edit linked parts"/>
<text name="RenderingCost" tool_tip="Mostra o cálculo do custo de renderização do objeto">
@@ -73,10 +73,10 @@
</text>
<check_box initial_value="true" label="Esticar texturas" name="checkbox stretch textures"/>
<check_box initial_value="true" label="Mostrar na grade" name="checkbox snap to grid"/>
- <combo_box name="combobox grid mode" tool_tip="Selecione o tipo de régua da grade onde o objeto será colocado">
- <combo_box.item label="Grid SL" name="World"/>
- <combo_box.item label="Grid local" name="Local"/>
- <combo_box.item label="Grid de referência" name="Reference"/>
+ <combo_box name="combobox grid mode" tool_tip="Selecione a régua da grade onde o objeto será colocado">
+ <combo_box.item label="Grade SL" name="World"/>
+ <combo_box.item label="Local" name="Local"/>
+ <combo_box.item label="Referência" name="Reference"/>
</combo_box>
<button label="Opções..." label_selected="Opções..." name="Options..." tool_tip="Mais opções de grade"/>
<button label="" label_selected="" name="ToolCube" tool_tip="Cubo"/>
@@ -99,12 +99,12 @@
<check_box initial_value="true" label="Copiar parte central" name="checkbox copy centers"/>
<check_box label="Girar cópia" name="checkbox copy rotates"/>
<radio_group name="land_radio_group">
- <radio_item label="Selecionar Terra" name="radio select land"/>
+ <radio_item label="Selecionar terra" name="radio select land"/>
<radio_item label="Aplainar" name="radio flatten"/>
- <radio_item label="Subir" name="radio raise"/>
+ <radio_item label="Elevar" name="radio raise"/>
<radio_item label="Abaixar" name="radio lower"/>
- <radio_item label="Suavizar" name="radio smooth"/>
- <radio_item label="Endurecer" name="radio noise"/>
+ <radio_item label="Alisar" name="radio smooth"/>
+ <radio_item label="Irregularizar" name="radio noise"/>
<radio_item label="Reverter" name="radio revert"/>
</radio_group>
<text name="Bulldozer:">
@@ -144,7 +144,7 @@
Você não pode modificar estes objetos
</panel.string>
<panel.string name="text modify warning">
- Selecione o objeto intereiro para configurar as autorizações
+ Selecione o objeto inteiro para configurar as autorizações
</panel.string>
<panel.string name="Cost Default">
Preço: L$
@@ -156,10 +156,10 @@
Preço unitário: L$
</panel.string>
<panel.string name="Cost Mixed">
- Preço Misturado
+ Preço misto
</panel.string>
<panel.string name="Sale Mixed">
- Venda Misturada
+ Venda mista
</panel.string>
<text name="Name:">
Nome:
@@ -193,7 +193,7 @@
<combo_box.item label="Tocar (padrão)" name="Touch/grab(default)"/>
<combo_box.item label="Sentar no objeto" name="Sitonobject"/>
<combo_box.item label="Comprar objeto" name="Buyobject"/>
- <combo_box.item label="Pagar Objeto" name="Payobject"/>
+ <combo_box.item label="Pagar objeto" name="Payobject"/>
<combo_box.item label="Abrir" name="Open"/>
<combo_box.item label="Zoom" name="Zoom"/>
</combo_box>
@@ -358,7 +358,7 @@
</panel>
<panel label="Recursos" name="Features">
<text name="select_single" width="272">
- Selecione apenas uma primitiva para editar suas características.
+ Selecione apenas um prim para editar suas características.
</text>
<text name="edit_object">
Editar características do Objeto:
@@ -480,7 +480,7 @@
<button label="Sobre terrenos" label_selected="Sobre terrenos" name="button about land"/>
<check_box label="Mostrar donos" name="checkbox show owners" tool_tip="Colorir lotes de acordo com seus donos: Green = Sua terra Aqua = Terra do seu grupo Red = Possuída por outros Yellow = À venda Purple = A leilão Grey = Pública"/>
<text name="label_parcel_modify">
- Modificar Lote
+ Modificar lote
</text>
<button label="Subdividir" label_selected="Subdividir" name="button subdivide land"/>
<button label="Juntar" label_selected="Juntar" name="button join land"/>
diff --git a/indra/newview/skins/default/xui/pt/floater_voice_effect.xml b/indra/newview/skins/default/xui/pt/floater_voice_effect.xml
index b9f9677833..cb9b3c8c0d 100644
--- a/indra/newview/skins/default/xui/pt/floater_voice_effect.xml
+++ b/indra/newview/skins/default/xui/pt/floater_voice_effect.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater label="Lugares" name="voice_effects" title="DISTORCENDO VOZ">
+<floater label="Lugares" name="voice_effects" title="EFEITOS DE VOZ">
<string name="no_voice_effect">
(Não distorcer voz)
</string>
diff --git a/indra/newview/skins/default/xui/pt/floater_world_map.xml b/indra/newview/skins/default/xui/pt/floater_world_map.xml
index 3952b80269..77d0c787e7 100644
--- a/indra/newview/skins/default/xui/pt/floater_world_map.xml
+++ b/indra/newview/skins/default/xui/pt/floater_world_map.xml
@@ -20,13 +20,13 @@
</text>
<check_box label="Terra à Venda" name="land_for_sale_chk"/>
<text name="land_sale_label">
- Venda de terreno
+ Terreno à venda
</text>
<text name="by_owner_label">
- o proprietário
+ pelo dono
</text>
<text name="auction_label">
- leilão de terrenos
+ leilão
</text>
<button label="Voltar ao meu início" label_selected="Voltar ao meu início" name="Go Home" tool_tip="Teletransportar para meu início"/>
<text name="Home_label">
@@ -37,7 +37,7 @@
</text>
<check_box label="PG" name="event_chk"/>
<text name="pg_label">
- Público geral
+ Geral
</text>
<check_box label="Mature" name="events_mature_chk"/>
<text name="events_mature_label">
diff --git a/indra/newview/skins/default/xui/pt/menu_inventory.xml b/indra/newview/skins/default/xui/pt/menu_inventory.xml
index d1ab3e976e..1ee197ce30 100644
--- a/indra/newview/skins/default/xui/pt/menu_inventory.xml
+++ b/indra/newview/skins/default/xui/pt/menu_inventory.xml
@@ -16,7 +16,7 @@
<menu label="Novas roupas" name="New Clothes">
<menu_item_call label="Nova camisa" name="New Shirt"/>
<menu_item_call label="Nova calça" name="New Pants"/>
- <menu_item_call label="Novos calçados" name="New Shoes"/>
+ <menu_item_call label="Novos sapatos" name="New Shoes"/>
<menu_item_call label="Novas meias" name="New Socks"/>
<menu_item_call label="Nova jaqueta" name="New Jacket"/>
<menu_item_call label="Nova saia" name="New Skirt"/>
@@ -47,8 +47,8 @@
<menu_item_call label="Teletransporte" name="Landmark Open"/>
<menu_item_call label="Abrir" name="Animation Open"/>
<menu_item_call label="Abrir" name="Sound Open"/>
- <menu_item_call label="Substituir equipamento" name="Replace Outfit"/>
- <menu_item_call label="Adicionar ao equipamento" name="Add To Outfit"/>
+ <menu_item_call label="Substituir look" name="Replace Outfit"/>
+ <menu_item_call label="Adicionar a look" name="Add To Outfit"/>
<menu_item_call label="Tirar do look atual" name="Remove From Outfit"/>
<menu_item_call label="Encontrar original" name="Find Original"/>
<menu_item_call label="Remover item" name="Purge Item"/>
@@ -75,7 +75,7 @@
<menu_item_call label="Ativar" name="Activate"/>
<menu_item_call label="Desativar" name="Deactivate"/>
<menu_item_call label="Salvar como" name="Save As"/>
- <menu_item_call label="Retirar de si mesmo" name="Detach From Yourself"/>
+ <menu_item_call label="Tirar de si mesmo" name="Detach From Yourself"/>
<menu_item_call label="Vestir" name="Wearable And Object Wear"/>
<menu label="Anexar a" name="Attach To"/>
<menu label="Anexar ao HUD" name="Attach To HUD"/>
diff --git a/indra/newview/skins/default/xui/pt/panel_landmark_info.xml b/indra/newview/skins/default/xui/pt/panel_landmark_info.xml
index 6196c06d09..39c19a22d4 100644
--- a/indra/newview/skins/default/xui/pt/panel_landmark_info.xml
+++ b/indra/newview/skins/default/xui/pt/panel_landmark_info.xml
@@ -1,25 +1,25 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<panel name="landmark_info">
- <string name="title_create_landmark" value="Criar Landmark"/>
- <string name="title_edit_landmark" value="Editar Landmark"/>
- <string name="title_landmark" value="Landmark"/>
- <string name="not_available" value="(N\A)"/>
+ <string name="title_create_landmark" value="Criar marco"/>
+ <string name="title_edit_landmark" value="Editar marco"/>
+ <string name="title_landmark" value="Marco"/>
+ <string name="not_available" value="(N/A)"/>
<string name="unknown" value="(desconhecido)"/>
<string name="public" value="(público)"/>
<string name="server_update_text">
Informação do lugar não disponível sem atualização do servidor.
</string>
<string name="server_error_text">
- Informações sobre esta localização não está disponível neste momento, por favor, tente novamente mais tarde.
+ No momento não há informações sobre este lugar; por favor tente novamente mais tarde.
</string>
<string name="server_forbidden_text">
- Informações sobre esta localização está indisponível devido a restrições de acesso. Por favor, verifique as permissões com o proprietário da parcela.
+ Os dados deste lugar não estão indisponíveis devido a restrições de acesso. Verifique as permissões com o proprietário do terreno ou parcela.
</string>
<string name="acquired_date">
[wkday,datetime,local] [mth,datetime,local] [day,datetime,local] [hour,datetime,local]:[min,datetime,local]:[second,datetime,local] [year,datetime,local]
</string>
<button name="back_btn" tool_tip="Atrás"/>
- <text name="title" value="Perfil do Lugar"/>
+ <text name="title" value="Perfil do lugar"/>
<scroll_container name="place_scroll">
<panel name="scrolling_panel">
<text name="maturity_value" value="desconhecido"/>
@@ -31,7 +31,7 @@
<panel name="landmark_edit_panel">
<text name="title_label" value="Título:"/>
<text name="notes_label" value="Minhas notas:"/>
- <text name="folder_label" value="Localização da Landmark:"/>
+ <text name="folder_label" value="Localização do marco:"/>
</panel>
</panel>
</scroll_container>
diff --git a/indra/newview/skins/default/xui/pt/panel_place_profile.xml b/indra/newview/skins/default/xui/pt/panel_place_profile.xml
index 03f997f31b..554c4d897d 100644
--- a/indra/newview/skins/default/xui/pt/panel_place_profile.xml
+++ b/indra/newview/skins/default/xui/pt/panel_place_profile.xml
@@ -36,7 +36,7 @@
Dados sobre o local não disponíveis no momento. Favor tentar mais tarde.
</string>
<string name="server_forbidden_text">
- Dados sobre o local controlados por lista de acesso. Verifique se você está autorizado a acessá-los com o dono do lote.
+ Dados sobre o local controlados por lista de acesso. Verifique se você está autorizado a acessá-los com o dono do lote.
</string>
<string name="acquired_date">
[wkday,datetime,local] [mth,datetime,local] [day,datetime,local] [hour,datetime,local]:[min,datetime,local]:[second,datetime,local] [year,datetime,local]
@@ -53,18 +53,18 @@
<text name="rating_label" value="Classificação:"/>
<text name="rating_value" value="desconhecido"/>
<text name="voice_label" value="Voz:"/>
- <text name="voice_value" value="Ligar"/>
+ <text name="voice_value" value="Ligado"/>
<text name="fly_label" value="Voar:"/>
- <text name="fly_value" value="Ligar"/>
+ <text name="fly_value" value="Ligado"/>
<text name="push_label" value="Empurrar:"/>
- <text name="push_value" value="Desligar"/>
+ <text name="push_value" value="Desligado"/>
<text name="build_label" value="Construir:"/>
- <text name="build_value" value="Ligar"/>
+ <text name="build_value" value="Ligado"/>
<text name="scripts_label" value="Scripts:"/>
- <text name="scripts_value" value="Ligar"/>
+ <text name="scripts_value" value="Ligado"/>
<text name="damage_label" value="Dano:"/>
- <text name="damage_value" value="Desligar"/>
- <button label="Sobre terrenos" name="about_land_btn"/>
+ <text name="damage_value" value="Desligado"/>
+ <button label="Sobre o terreno" name="about_land_btn"/>
</panel>
</accordion_tab>
<accordion_tab name="region_information_tab" title="Região">
diff --git a/indra/newview/skins/default/xui/pt/panel_preferences_privacy.xml b/indra/newview/skins/default/xui/pt/panel_preferences_privacy.xml
index 0cf2b7a4af..ba4ebdb9bf 100644
--- a/indra/newview/skins/default/xui/pt/panel_preferences_privacy.xml
+++ b/indra/newview/skins/default/xui/pt/panel_preferences_privacy.xml
@@ -21,6 +21,6 @@
Localização dos logs:
</text>
<line_editor left="278" name="log_path_string" right="-20"/>
- <button label="Navegar" label_selected="Navegar" name="log_path_button" width="120"/>
- <button label="Lista dos bloqueados" name="block_list"/>
+ <button label="Procurar" label_selected="Procurar" name="log_path_button" width="120"/>
+ <button label="Lista de bloqueados" name="block_list"/>
</panel>
diff --git a/indra/newview/skins/default/xui/pt/role_actions.xml b/indra/newview/skins/default/xui/pt/role_actions.xml
index 2e6e4dd133..88fd4b3ca8 100644
--- a/indra/newview/skins/default/xui/pt/role_actions.xml
+++ b/indra/newview/skins/default/xui/pt/role_actions.xml
@@ -2,7 +2,7 @@
<role_actions>
<action_set description="Esta habilidades incluem poderes de adicionar ou remover membros do grupo e permitir que novos membros se juntem sem um convite." name="Membership">
<action description="Convidar pessoas para este grupo" longdescription="Em Membros &gt; Cargos, use o botão &apos;Convidar&apos; para convidar pessoas para entrar no grupo." name="member invite"/>
- <action description="Expulsar membros deste grupo" longdescription="Em Membros &gt; Cargos, use o botão &apos;Ejetar&apos; para tirar pessoas do grupo. Proprietários podem expulsar qualquer pessoa, menos outro proprietário. Se você não é Proprietário, um membro só pode ser expulso se tiver cargo &apos;Todos&apos; e nenhum outro cargo. Para destituir um membro de seu cargo, você precisa ter a função &apos;Destituir membro com cargo&apos;." name="member eject"/>
+ <action description="Expulsar membros deste grupo" longdescription="Em Membros &gt; Cargos, use o botão &apos;Ejetar&apos; para tirar pessoas do grupo. Proprietários podem expulsar qualquer pessoa, menos outro proprietário. Se você não é Proprietário, um membro só pode ser expulso se tiver cargo &apos;Todos&apos; e nenhum outro cargo. Para destituir um membro de seu cargo, você precisa ter a função &apos;Destituir membro com cargo&apos;." name="member eject"/>
<action description="Alterna entre &apos;Inscrições abertas&apos; e &apos;Taxa de associação&apos;." longdescription="Ative &apos;Inscrições abertas&apos; para que novos membros entrem no grupo sem convite, mude a &apos;Taxa de associação&apos; na seção Geral." name="member options"/>
</action_set>
<action_set description="Estas habilidades incluem poderes de adicionar, remover e mudar funções do grupo; adicionar e remover membros em funções e designar habilidades a funções." name="Roles">
@@ -18,7 +18,7 @@
<action description="Mudar apresentação, insígnia, &apos;Publicar na web&apos;, e quais membros estão publicamente visíveis em Informações do Grupo." longdescription="Modificar o estatuto, símbolo e exibição nos resultados de busca. Use a seção Geral." name="group change identity"/>
</action_set>
<action_set description="Estas funções incluem poderes de transferir, vender e modificar os terrenos do grupo. Para acessar a janela &apos;Sobre terrenos&apos;, clique no chão com o botão direito e selecione &apos;Sobre terrenos&apos;. Ou clique no ícone &apos;i&apos; da barra de navegação." name="Parcel Management">
- <action description="Transferir e comprar terreno para o grupo" longdescription="Transfere e compre terreno para o grupo. É feito em Sobre o terreno &gt; aba Geral." name="land deed"/>
+ <action description="Transferir e comprar terreno para o grupo" longdescription="Transfere e compre terreno para o grupo. É feito em Sobre o terreno &gt; aba Geral." name="land deed"/>
<action description="Abandonar terreno para Governador Linden" longdescription="Abandone terreno para Governador Linden. *AVISO* Qualquer membro em uma função com esta habilidade pode abandonar o terreno pertencente ao grupo em Sobre o terreno &gt; aba Geral, revertendo à posse Linden sem uma venda! Certifique-se de saber o que está fazendo antes de designar esta habilidade." name="land release"/>
<action description="Definir terreno para informação de venda" longdescription="Defina informações de venda para terreno. *AVISO* Qualquer membro em uma função com esta habilidade pode vender terrenos pertencentes ao grupo em Sobre o terreno &gt; aba Geral como quiser! Certifique-se de sabe o que está fazendo antes de designar esta habilidade." name="land set sale info"/>
<action description="Subdividir e unir parcelas" longdescription="Juntar ou dividir lotes. Clique no chão com o botão direito, selecione &apos;Editar terreno&apos; e arraste o mouse sobre o terreno para ver as opções. Para dividir um terreno, selecione a área a ser dividida e clique em &apos;Dividir&apos;. Para juntar terrenos, selecione dois ou mais lotes adjacentes e clique em &apos;Juntar&apos;." name="land divide join"/>
diff --git a/indra/newview/skins/default/xui/pt/strings.xml b/indra/newview/skins/default/xui/pt/strings.xml
index 9d9f33fdc8..95ad41743e 100644
--- a/indra/newview/skins/default/xui/pt/strings.xml
+++ b/indra/newview/skins/default/xui/pt/strings.xml
@@ -1333,10 +1333,10 @@
Script não encontrado no servidor.
</string>
<string name="CompileQueueProblemDownloading">
- Problema no download
+ Problema no download
</string>
<string name="CompileQueueInsufficientPermDownload">
- Permissões insuficientes para fazer o download do script.
+ Permissões insuficientes para fazer o download do script.
</string>
<string name="CompileQueueInsufficientPermFor">
Permissões insuficientes para
@@ -1649,7 +1649,7 @@
(vai atualizar depois de publicado)
</string>
<string name="NoPicksClassifiedsText">
- Você não criou nenhum Destaque ou Anúncio. Clique no botão &quot;+&quot; para criar um Destaque ou Anúncio.
+ Você não criou nenhum Destaque ou Anúncio. Clique no botão &quot;+&quot; para criar um Destaque ou Anúncio.
</string>
<string name="NoAvatarPicksClassifiedsText">
O usuário não tem nenhum destaque ou anúncio
diff --git a/indra/newview/tests/lldateutil_test.cpp b/indra/newview/tests/lldateutil_test.cpp
index 7ba82fbd2c..9ec24eb515 100644
--- a/indra/newview/tests/lldateutil_test.cpp
+++ b/indra/newview/tests/lldateutil_test.cpp
@@ -189,4 +189,14 @@ namespace tut
LLDateUtil::ageFromDate("12/13/2009", now),
"3 weeks old" );
}
+
+ //template<> template<>
+ //void dateutil_object_t::test<6>()
+ //{
+ // set_test_name("ISO dates");
+ // LLDate now(std::string("2010-01-04T12:00:00Z"));
+ // ensure_equals("days",
+ // LLDateUtil::ageFromDateISO("2009-12-13", now),
+ // "3 weeks old" );
+ //}
}