Post-convert merge by convert_monolith.py from /Users/Aimee/Documents/Work/Linden-Lab/Development/viewer/convert/viewer-identity-evolution
commit
ffae589843
1
.hgtags
1
.hgtags
|
|
@ -22,4 +22,3 @@ c6969fe44e58c542bfc6f1bd6c0be2fa860929ac 2-1-beta-4
|
|||
d2382d374139850efa5bb6adfb229e3e656cfc40 howard-demo
|
||||
d40ac9dd949cba6dab1cc386da6a2027690c2519 alpha-5
|
||||
d6781e22543acd7e21b967209f3c6e7003d380e3 fork to viewer-2-0
|
||||
c6e6324f5be1401f077ad18a4a0f6b46451c2f7b last_sprint
|
||||
|
|
|
|||
|
|
@ -370,6 +370,14 @@
|
|||
</map>
|
||||
|
||||
<!-- Server to client -->
|
||||
<key>DisplayNameUpdate</key>
|
||||
<map>
|
||||
<key>flavor</key>
|
||||
<string>llsd</string>
|
||||
<key>trusted-sender</key>
|
||||
<boolean>true</boolean>
|
||||
</map>
|
||||
|
||||
<key>ParcelVoiceInfo</key>
|
||||
<map>
|
||||
<key>flavor</key>
|
||||
|
|
@ -426,6 +434,14 @@
|
|||
<boolean>true</boolean>
|
||||
</map>
|
||||
|
||||
<key>SetDisplayNameReply</key>
|
||||
<map>
|
||||
<key>flavor</key>
|
||||
<string>llsd</string>
|
||||
<key>trusted-sender</key>
|
||||
<boolean>true</boolean>
|
||||
</map>
|
||||
|
||||
<key>DirLandReply</key>
|
||||
<map>
|
||||
<key>flavor</key>
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ myprog somearg otherarg
|
|||
|
||||
$LicenseInfo:firstyear=2009&license=viewerlgpl$
|
||||
Second Life Viewer Source Code
|
||||
Copyright (C) 2010, Linden Research, Inc.
|
||||
Copyright (C) 2009-2010, Linden Research, Inc.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
$LicenseInfo:firstyear=2006&license=viewerlgpl$
|
||||
Second Life Viewer Source Code
|
||||
Copyright (C) 2010, Linden Research, Inc.
|
||||
Copyright (C) 2006-2010, Linden Research, Inc.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -28,7 +28,6 @@
|
|||
#ifndef LL_LLCHAT_H
|
||||
#define LL_LLCHAT_H
|
||||
|
||||
#include "llstring.h"
|
||||
#include "lluuid.h"
|
||||
#include "v3math.h"
|
||||
|
||||
|
|
@ -71,7 +70,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(),
|
||||
|
|
|
|||
|
|
@ -731,14 +731,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;
|
||||
|
|
|
|||
|
|
@ -108,6 +108,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)
|
||||
{
|
||||
|
|
@ -154,6 +157,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 << ".";
|
||||
|
|
|
|||
|
|
@ -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}")
|
||||
|
|
|
|||
|
|
@ -0,0 +1,818 @@
|
|||
/**
|
||||
* @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
|
||||
|
||||
// No longer deleting expired entries, just re-requesting in the get
|
||||
// this way first synchronous get call on an expired entry won't return
|
||||
// legacy name. LF
|
||||
|
||||
//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;
|
||||
}
|
||||
|
||||
// fills in av_name if it has it in the cache, even if expired (can check expiry time)
|
||||
// returns bool specifying if av_name was filled, false otherwise
|
||||
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;
|
||||
|
||||
// re-request name if entry is expired
|
||||
if (av_name->mExpires < LLFrameTimer::getTotalSeconds())
|
||||
{
|
||||
if (!isRequestPending(agent_id))
|
||||
{
|
||||
sAskQueue.insert(agent_id);
|
||||
}
|
||||
}
|
||||
|
||||
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())
|
||||
{
|
||||
const LLAvatarName& av_name = it->second;
|
||||
|
||||
if (av_name.mExpires > LLFrameTimer::getTotalSeconds())
|
||||
{
|
||||
// ...name already exists in cache, fire callback now
|
||||
fireSignal(agent_id, slot, av_name);
|
||||
|
||||
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 an hour
|
||||
const F64 DEFAULT_EXPIRES = 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;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -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
|
||||
|
|
@ -69,6 +69,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;
|
||||
|
|
@ -214,7 +216,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);
|
||||
|
||||
|
|
@ -300,89 +304,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
|
||||
|
|
@ -408,7 +333,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;
|
||||
|
|
@ -457,6 +382,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;
|
||||
|
|
@ -474,7 +400,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())
|
||||
{
|
||||
|
|
@ -483,7 +409,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;
|
||||
|
|
@ -494,16 +420,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;
|
||||
|
|
@ -514,11 +441,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())
|
||||
|
|
@ -555,13 +484,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;
|
||||
|
|
@ -573,6 +502,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
|
||||
|
|
@ -580,7 +558,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;
|
||||
|
||||
|
|
@ -588,7 +566,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;
|
||||
}
|
||||
|
||||
|
|
@ -600,11 +578,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
|
||||
|
|
@ -626,9 +606,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(id, is_group, boost::bind(callback, _1, _2, _3, _4, user_data));
|
||||
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, user_data));
|
||||
}
|
||||
|
||||
void LLCacheName::processPending()
|
||||
|
|
@ -700,7 +686,7 @@ void LLCacheName::dump()
|
|||
{
|
||||
llinfos
|
||||
<< iter->first << " = "
|
||||
<< entry->mFirstName << " " << entry->mLastName
|
||||
<< buildFullName(entry->mFirstName, entry->mLastName)
|
||||
<< " @ " << entry->mCreateTime
|
||||
<< llendl;
|
||||
}
|
||||
|
|
@ -719,12 +705,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);
|
||||
|
|
@ -746,11 +744,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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -921,13 +921,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;
|
||||
}
|
||||
}
|
||||
|
|
@ -956,4 +970,3 @@ void LLCacheName::Impl::handleUUIDGroupNameReply(LLMessageSystem* msg, void** us
|
|||
{
|
||||
((LLCacheName::Impl*)userData)->processUUIDReply(msg, true);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -36,13 +36,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"
|
||||
|
|
@ -65,24 +64,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
|
||||
|
|
@ -94,10 +100,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();
|
||||
|
|
@ -108,9 +119,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:
|
||||
|
||||
|
|
|
|||
|
|
@ -55,7 +55,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)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -89,8 +89,7 @@ public:
|
|||
time_t mTime;
|
||||
EMeanCollisionType mType;
|
||||
F32 mMag;
|
||||
std::string mFirstName;
|
||||
std::string mLastName;
|
||||
std::string mFullName;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -52,8 +52,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");
|
||||
|
|
@ -705,10 +703,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();
|
||||
|
|
|
|||
|
|
@ -43,9 +43,6 @@
|
|||
class LLFontGL;
|
||||
class LLViewBorder;
|
||||
|
||||
extern S32 LLCOMBOBOX_HEIGHT;
|
||||
extern S32 LLCOMBOBOX_WIDTH;
|
||||
|
||||
class LLComboBox
|
||||
: public LLUICtrl, public LLCtrlListInterface
|
||||
{
|
||||
|
|
@ -224,8 +221,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.
|
||||
|
|
|
|||
|
|
@ -28,7 +28,9 @@
|
|||
|
||||
#include "llnotifications.h"
|
||||
|
||||
#include "llavatarnamecache.h"
|
||||
#include "llinstantmessage.h"
|
||||
#include "llcachename.h"
|
||||
#include "llxmlnode.h"
|
||||
#include "lluictrl.h"
|
||||
#include "lluictrlfactory.h"
|
||||
|
|
@ -1481,17 +1483,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)
|
||||
{
|
||||
mName = first + " " + last;
|
||||
|
||||
LLStringUtil::trim(mName);
|
||||
if (mName.empty())
|
||||
if (is_group)
|
||||
{
|
||||
llwarns << "Empty name received for Id: " << id << llendl;
|
||||
mName = SYSTEM_FROM;
|
||||
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)
|
||||
{
|
||||
mName = name;
|
||||
modifyNotificationParams();
|
||||
LLNotifications::instance().add(mParams);
|
||||
cleanup();
|
||||
|
|
|
|||
|
|
@ -98,8 +98,8 @@
|
|||
#include "llinitparam.h"
|
||||
#include "llnotificationslistener.h"
|
||||
#include "llnotificationptr.h"
|
||||
#include "llcachename.h"
|
||||
|
||||
class LLAvatarName;
|
||||
|
||||
typedef enum e_notification_priority
|
||||
{
|
||||
|
|
@ -994,17 +994,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()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -40,7 +40,8 @@ LLStyle::Params::Params()
|
|||
selected_color("selected_color", LLColor4::black),
|
||||
font("font", LLFontGL::getFontMonospace()),
|
||||
image("image"),
|
||||
link_href("href")
|
||||
link_href("href"),
|
||||
is_link("is_link")
|
||||
{}
|
||||
|
||||
|
||||
|
|
@ -51,6 +52,7 @@ LLStyle::LLStyle(const LLStyle::Params& p)
|
|||
mSelectedColor(p.selected_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())
|
||||
{}
|
||||
|
|
@ -73,7 +75,7 @@ void LLStyle::setLinkHREF(const std::string& href)
|
|||
|
||||
BOOL LLStyle::isLink() const
|
||||
{
|
||||
return mLink.size();
|
||||
return mIsLink;
|
||||
}
|
||||
|
||||
BOOL LLStyle::isVisible() const
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ public:
|
|||
Optional<const LLFontGL*> font;
|
||||
Optional<LLUIImage*> image;
|
||||
Optional<std::string> link_href;
|
||||
Optional<bool> is_link;
|
||||
Params();
|
||||
};
|
||||
LLStyle(const Params& p = Params());
|
||||
|
|
@ -106,6 +107,7 @@ private:
|
|||
std::string mFontName;
|
||||
const LLFontGL* mFont;
|
||||
std::string mLink;
|
||||
bool mIsLink;
|
||||
LLUIImagePtr mImagep;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
*
|
||||
* $LicenseInfo:firstyear=2009&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
* Copyright (C) 2009-2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
|
|
@ -475,8 +475,8 @@ void LLTextBase::drawCursor()
|
|||
{
|
||||
LLColor4 text_color;
|
||||
const LLFontGL* fontp;
|
||||
text_color = segmentp->getColor();
|
||||
fontp = segmentp->getStyle()->getFont();
|
||||
text_color = segmentp->getColor();
|
||||
fontp = segmentp->getStyle()->getFont();
|
||||
fontp->render(text, mCursorPos, cursor_rect,
|
||||
LLColor4(1.f - text_color.mV[VRED], 1.f - text_color.mV[VGREEN], 1.f - text_color.mV[VBLUE], alpha),
|
||||
LLFontGL::LEFT, mVAlign,
|
||||
|
|
@ -1602,6 +1602,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);
|
||||
|
|
@ -1614,16 +1628,13 @@ 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)) )
|
||||
{
|
||||
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,20 @@ void LLTextBase::appendTextImpl(const std::string &new_text, const LLStyle::Para
|
|||
// inserts an avatar icon preceding the Url if appropriate
|
||||
LLTextUtil::processUrlMatch(&match,this);
|
||||
|
||||
// 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, match.underlineOnHoverOnly());
|
||||
|
||||
// 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, match.underlineOnHoverOnly());
|
||||
|
||||
// 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())
|
||||
{
|
||||
|
|
@ -1848,8 +1853,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();
|
||||
|
|
@ -1870,7 +1876,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();
|
||||
|
|
@ -1879,6 +1885,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();
|
||||
}
|
||||
|
|
@ -1976,8 +1997,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;
|
||||
|
|
|
|||
|
|
@ -492,7 +492,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, bool underline_on_hover_only = false);
|
||||
|
|
|
|||
|
|
@ -31,18 +31,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()
|
||||
{
|
||||
|
|
@ -53,6 +54,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
|
||||
|
|
@ -130,16 +147,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++);
|
||||
|
|
@ -308,16 +329,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
|
||||
|
|
@ -330,6 +370,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))
|
||||
|
||||
LLAvatarName av_name;
|
||||
if (LLAvatarNameCache::get(agent_id, &av_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 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
|
||||
|
|
@ -791,7 +974,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
|
||||
|
|
@ -805,6 +987,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
|
||||
//
|
||||
|
|
@ -812,7 +1000,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
|
||||
|
|
|
|||
|
|
@ -30,13 +30,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;
|
||||
|
||||
///
|
||||
|
|
@ -71,10 +75,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; }
|
||||
|
|
@ -85,9 +89,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; }
|
||||
|
||||
/// Should this link text be underlined only when mouse is hovered over it?
|
||||
virtual bool underlineOnHoverOnly(const std::string &string) const { return false; }
|
||||
|
||||
|
|
@ -100,7 +101,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;
|
||||
|
|
@ -111,9 +112,7 @@ protected:
|
|||
std::string mIcon;
|
||||
std::string mMenuName;
|
||||
std::string mTooltip;
|
||||
LLUIColor mColor;
|
||||
std::multimap<std::string, LLUrlEntryObserver> mObservers;
|
||||
bool mDisabledLink;
|
||||
};
|
||||
|
||||
///
|
||||
|
|
@ -162,18 +161,78 @@ 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;
|
||||
/*virtual*/ bool underlineOnHoverOnly(const std::string &string) const;
|
||||
protected:
|
||||
/*virtual*/ void callObservers(const std::string &id, const std::string &label, const std::string& icon);
|
||||
private:
|
||||
void onAgentNameReceived(const LLUUID& id, const std::string& first,
|
||||
const std::string& last, BOOL is_group);
|
||||
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:
|
||||
/*virtual*/ std::string getName(const LLAvatarName& avatar_name);
|
||||
};
|
||||
|
||||
///
|
||||
|
|
@ -185,10 +244,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);
|
||||
};
|
||||
|
||||
///
|
||||
|
|
@ -297,6 +356,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;
|
||||
};
|
||||
|
||||
///
|
||||
|
|
|
|||
|
|
@ -37,16 +37,15 @@ LLUrlMatch::LLUrlMatch() :
|
|||
mIcon(""),
|
||||
mMenuName(""),
|
||||
mLocation(""),
|
||||
mDisabledLink(false),
|
||||
mUnderlineOnHoverOnly(false)
|
||||
{
|
||||
}
|
||||
|
||||
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, bool underline_on_hover_only)
|
||||
const LLUUID& id, bool underline_on_hover_only)
|
||||
{
|
||||
mStart = start;
|
||||
mEnd = end;
|
||||
|
|
@ -54,10 +53,10 @@ 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;
|
||||
mUnderlineOnHoverOnly = underline_on_hover_only;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,11 +28,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
|
||||
|
|
@ -69,7 +69,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; }
|
||||
|
|
@ -77,21 +77,17 @@ 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; }
|
||||
|
||||
/// Should this link text be underlined only when mouse is hovered over it?
|
||||
bool underlineOnHoverOnly() const { return mUnderlineOnHoverOnly; }
|
||||
|
||||
/// 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, bool underline_on_hover_only = false );
|
||||
|
||||
const LLUUID& getID() const { return mID;}
|
||||
const LLStyle::Params& style, const std::string &menu,
|
||||
const std::string &location, const LLUUID& id,
|
||||
bool underline_on_hover_only = false );
|
||||
|
||||
const LLUUID& getID() const { return mID; }
|
||||
private:
|
||||
U32 mStart;
|
||||
U32 mEnd;
|
||||
|
|
@ -101,10 +97,8 @@ private:
|
|||
std::string mIcon;
|
||||
std::string mMenuName;
|
||||
std::string mLocation;
|
||||
|
||||
LLUUID mID;
|
||||
LLUIColor mColor;
|
||||
bool mDisabledLink;
|
||||
LLStyle::Params mStyle;
|
||||
bool mUnderlineOnHoverOnly;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -31,18 +31,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());
|
||||
|
|
@ -71,10 +78,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);
|
||||
}
|
||||
}
|
||||
|
|
@ -174,10 +184,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),
|
||||
match_entry->underlineOnHoverOnly(url));
|
||||
return true;
|
||||
|
|
@ -210,10 +219,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(),
|
||||
match.underlineOnHoverOnly());
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -37,7 +37,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
|
||||
|
|
@ -64,7 +66,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
|
||||
|
|
|
|||
|
|
@ -27,11 +27,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
|
||||
//
|
||||
|
|
@ -47,7 +64,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();
|
||||
}
|
||||
|
|
@ -67,3 +89,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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
#include "llurlentry_stub.cpp"
|
||||
#include "lltut.h"
|
||||
#include "../lluicolortable.h"
|
||||
#include "../lluiimage.h"
|
||||
|
||||
#include <boost/regex.hpp>
|
||||
|
||||
|
|
@ -40,6 +41,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
|
||||
|
|
|
|||
|
|
@ -25,14 +25,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
|
||||
|
|
@ -59,7 +181,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());
|
||||
}
|
||||
|
||||
|
|
@ -72,7 +194,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);
|
||||
}
|
||||
|
||||
|
|
@ -85,7 +207,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);
|
||||
}
|
||||
|
||||
|
|
@ -98,10 +220,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(), "");
|
||||
}
|
||||
|
||||
|
|
@ -114,10 +236,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(), "");
|
||||
}
|
||||
|
||||
|
|
@ -130,10 +252,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(), "");
|
||||
}
|
||||
|
||||
|
|
@ -146,10 +268,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(), "");
|
||||
}
|
||||
|
||||
|
|
@ -162,10 +284,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());
|
||||
}
|
||||
|
||||
|
|
@ -178,10 +300,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());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -238,6 +238,7 @@ set(viewer_SOURCE_FILES
|
|||
llhudeffecttrail.cpp
|
||||
llhudicon.cpp
|
||||
llhudmanager.cpp
|
||||
llhudnametag.cpp
|
||||
llhudobject.cpp
|
||||
llhudrender.cpp
|
||||
llhudtext.cpp
|
||||
|
|
@ -476,6 +477,7 @@ set(viewer_SOURCE_FILES
|
|||
llviewercontrol.cpp
|
||||
llviewercontrollistener.cpp
|
||||
llviewerdisplay.cpp
|
||||
llviewerdisplayname.cpp
|
||||
llviewerfloaterreg.cpp
|
||||
llviewerfoldertype.cpp
|
||||
llviewergenericmessage.cpp
|
||||
|
|
@ -762,6 +764,7 @@ set(viewer_HEADER_FILES
|
|||
llhudeffecttrail.h
|
||||
llhudicon.h
|
||||
llhudmanager.h
|
||||
llhudnametag.h
|
||||
llhudobject.h
|
||||
llhudrender.h
|
||||
llhudtext.h
|
||||
|
|
@ -1000,6 +1003,7 @@ set(viewer_HEADER_FILES
|
|||
llviewercontrol.h
|
||||
llviewercontrollistener.h
|
||||
llviewerdisplay.h
|
||||
llviewerdisplayname.h
|
||||
llviewerfloaterreg.h
|
||||
llviewerfoldertype.h
|
||||
llviewergenericmessage.h
|
||||
|
|
|
|||
|
|
@ -7899,7 +7899,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>
|
||||
|
|
@ -7908,7 +7908,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>
|
||||
|
|
@ -10936,6 +10969,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>
|
||||
|
|
|
|||
|
|
@ -39,29 +39,6 @@
|
|||
#include "llvoavatarself.h"
|
||||
#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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -41,7 +41,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);
|
||||
|
|
|
|||
|
|
@ -84,6 +84,7 @@
|
|||
#include "llsecondlifeurls.h"
|
||||
|
||||
// Linden library includes
|
||||
#include "llavatarnamecache.h"
|
||||
#include "llimagej2c.h"
|
||||
#include "llmemory.h"
|
||||
#include "llprimitive.h"
|
||||
|
|
@ -156,7 +157,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"
|
||||
|
|
@ -432,9 +432,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");
|
||||
|
|
@ -1353,8 +1350,7 @@ bool LLAppViewer::cleanup()
|
|||
|
||||
LLPolyMesh::freeAllMeshes();
|
||||
|
||||
delete gCacheName;
|
||||
gCacheName = NULL;
|
||||
LLStartUp::cleanupNameCache();
|
||||
|
||||
// Note: this is where gLocalSpeakerMgr and gActiveSpeakerMgr used to be deleted.
|
||||
|
||||
|
|
@ -3420,6 +3416,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;
|
||||
|
|
@ -3429,19 +3434,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)
|
||||
{
|
||||
gCacheName->importFile(name_cache_fp);
|
||||
fclose(name_cache_fp);
|
||||
}
|
||||
}
|
||||
|
||||
void LLAppViewer::saveNameCache()
|
||||
{
|
||||
{
|
||||
// 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);
|
||||
}
|
||||
|
||||
if (!gCacheName) return;
|
||||
|
||||
std::string name_cache;
|
||||
|
|
@ -3641,6 +3646,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();
|
||||
|
||||
|
|
@ -3978,6 +3984,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
|
||||
//
|
||||
|
|
@ -4003,8 +4063,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
|
||||
|
|
|
|||
|
|
@ -203,6 +203,8 @@ private:
|
|||
|
||||
void idle();
|
||||
void idleShutdown();
|
||||
// update avatar SLID and display name caches
|
||||
void idleNameCache();
|
||||
void idleNetwork();
|
||||
|
||||
void sendLogoutRequest();
|
||||
|
|
|
|||
|
|
@ -31,11 +31,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"
|
||||
|
|
@ -64,6 +64,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)
|
||||
|
|
@ -75,26 +76,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)
|
||||
{
|
||||
|
|
@ -103,9 +100,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
|
||||
|
|
@ -130,11 +125,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";
|
||||
|
|
@ -162,14 +156,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);
|
||||
|
|
@ -184,25 +170,26 @@ void LLAvatarActions::offerTeleport(const uuid_vec_t& ids)
|
|||
handle_lure(ids);
|
||||
}
|
||||
|
||||
static void on_avatar_name_cache_start_im(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);
|
||||
if (session_id != LLUUID::null)
|
||||
{
|
||||
LLIMFloater::show(session_id);
|
||||
}
|
||||
make_ui_sound("UISndStartIM");
|
||||
}
|
||||
|
||||
// static
|
||||
void LLAvatarActions::startIM(const LLUUID& id)
|
||||
{
|
||||
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);
|
||||
if (session_id != LLUUID::null)
|
||||
{
|
||||
LLIMFloater::show(session_id);
|
||||
}
|
||||
make_ui_sound("UISndStartIM");
|
||||
LLAvatarNameCache::get(id,
|
||||
boost::bind(&on_avatar_name_cache_start_im, _1, _2));
|
||||
}
|
||||
|
||||
// static
|
||||
|
|
@ -218,6 +205,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)
|
||||
{
|
||||
|
|
@ -225,15 +224,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
|
||||
|
|
@ -329,14 +321,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");
|
||||
}
|
||||
|
||||
|
|
@ -486,14 +478,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;
|
||||
|
|
@ -530,7 +523,7 @@ namespace action_give_inventory
|
|||
|
||||
struct LLShareInfo : public LLSingleton<LLShareInfo>
|
||||
{
|
||||
std::vector<std::string> mAvatarNames;
|
||||
std::vector<LLAvatarName> mAvatarNames;
|
||||
uuid_vec_t mAvatarUuids;
|
||||
};
|
||||
|
||||
|
|
@ -595,7 +588,7 @@ namespace action_give_inventory
|
|||
}
|
||||
else
|
||||
{
|
||||
LLGiveInventory::doGiveInventoryItem(avatar_uuid, inv_item, session_id);
|
||||
LLGiveInventory::doGiveInventoryItem(avatar_uuid, inv_item, session_id);
|
||||
shared = true;
|
||||
}
|
||||
}
|
||||
|
|
@ -627,11 +620,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)
|
||||
{
|
||||
|
|
@ -677,7 +669,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))
|
||||
|
|
@ -865,23 +857,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)
|
||||
|
|
@ -899,7 +874,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);
|
||||
}
|
||||
|
|
@ -914,16 +888,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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -184,7 +184,6 @@ public:
|
|||
static bool canOfferTeleport(const uuid_vec_t& ids);
|
||||
|
||||
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);
|
||||
|
|
|
|||
|
|
@ -28,17 +28,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
|
||||
|
||||
|
|
@ -227,6 +229,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);
|
||||
|
|
@ -238,10 +243,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()
|
||||
|
|
@ -284,24 +288,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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,6 +31,8 @@
|
|||
#include "llavatarpropertiesprocessor.h"
|
||||
#include "llviewermenu.h"
|
||||
|
||||
class LLAvatarName;
|
||||
|
||||
class LLAvatarIconIDCache: public LLSingleton<LLAvatarIconIDCache>
|
||||
{
|
||||
public:
|
||||
|
|
@ -84,22 +86,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;
|
||||
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@
|
|||
// newview
|
||||
#include "llagentdata.h" // for comparator
|
||||
#include "llavatariconctrl.h"
|
||||
#include "llavatarnamecache.h"
|
||||
#include "llcallingcard.h" // for LLAvatarTracker
|
||||
#include "llcachename.h"
|
||||
#include "lllistcontextmenu.h"
|
||||
|
|
@ -236,12 +237,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)
|
||||
{
|
||||
|
|
@ -250,7 +254,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++;
|
||||
}
|
||||
|
|
@ -272,10 +280,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;
|
||||
|
|
@ -327,14 +335,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;
|
||||
}
|
||||
|
|
@ -368,7 +376,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);
|
||||
|
|
@ -534,11 +542,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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,7 +28,6 @@
|
|||
#define LL_LLAVATARLIST_H
|
||||
|
||||
#include "llflatlistview.h"
|
||||
|
||||
#include "llavatarlistitem.h"
|
||||
|
||||
class LLTimer;
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@
|
|||
#include "lltextutil.h"
|
||||
|
||||
#include "llagent.h"
|
||||
#include "llavatarnamecache.h"
|
||||
#include "llavatariconctrl.h"
|
||||
#include "lloutputmonitorctrl.h"
|
||||
|
||||
|
|
@ -161,11 +162,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);
|
||||
|
|
@ -224,7 +230,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));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -317,23 +324,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()));
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@
|
|||
#include "llcallingcard.h" // for LLFriendObserver
|
||||
|
||||
class LLAvatarIconCtrl;
|
||||
class LLAvatarName;
|
||||
|
||||
class LLAvatarListItem : public LLPanel, public LLFriendObserver
|
||||
{
|
||||
|
|
@ -85,7 +86,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);
|
||||
|
|
@ -98,7 +100,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();
|
||||
|
|
@ -139,7 +142,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);
|
||||
|
||||
|
|
|
|||
|
|
@ -27,13 +27,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"
|
||||
|
|
@ -77,7 +78,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); }
|
||||
|
|
@ -368,9 +370,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)
|
||||
{
|
||||
|
|
@ -415,9 +439,10 @@ void LLCallFloater::initAgentData()
|
|||
{
|
||||
mAgentPanel->getChild<LLUICtrl>("user_icon")->setValue(gAgentID);
|
||||
|
||||
std::string name;
|
||||
gCacheName->getFullName(gAgentID, name);
|
||||
mAgentPanel->getChild<LLUICtrl>("user_text")->setValue(name);
|
||||
// Just use display name, because it's you
|
||||
LLAvatarName av_name;
|
||||
LLAvatarNameCache::get( gAgentID, &av_name );
|
||||
mAgentPanel->getChild<LLUICtrl>("user_text")->setValue(av_name.mDisplayName);
|
||||
|
||||
mSpeakingIndicator = mAgentPanel->getChild<LLOutputMonitorCtrl>("speaking_indicator");
|
||||
mSpeakingIndicator->setSpeakerId(gAgentID);
|
||||
|
|
@ -438,7 +463,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()))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@
|
|||
|
||||
class LLAvatarList;
|
||||
class LLAvatarListItem;
|
||||
class LLAvatarName;
|
||||
class LLNonAvatarCaller;
|
||||
class LLOutputMonitorCtrl;
|
||||
class LLParticipantList;
|
||||
|
|
@ -116,6 +117,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();
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@
|
|||
//#include <iterator>
|
||||
|
||||
#include "indra_constants.h"
|
||||
#include "llavatarnamecache.h"
|
||||
#include "llcachename.h"
|
||||
#include "llstl.h"
|
||||
#include "lltimer.h"
|
||||
|
|
@ -44,6 +45,7 @@
|
|||
#include "message.h"
|
||||
|
||||
#include "llagent.h"
|
||||
#include "llavatarnamecache.h"
|
||||
#include "llbutton.h"
|
||||
#include "llinventoryobserver.h"
|
||||
#include "llinventorymodel.h"
|
||||
|
|
@ -90,8 +92,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
|
||||
|
|
@ -244,7 +248,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)
|
||||
{
|
||||
|
|
@ -254,7 +258,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")
|
||||
|
|
@ -627,12 +632,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)
|
||||
|
|
@ -674,8 +676,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)
|
||||
{
|
||||
|
|
@ -685,17 +685,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
|
||||
{
|
||||
|
|
@ -711,29 +700,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;
|
||||
|
|
@ -742,6 +714,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())
|
||||
|
|
@ -862,10 +865,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);
|
||||
|
|
@ -875,10 +877,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);
|
||||
|
|
@ -888,10 +888,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);
|
||||
|
|
@ -902,5 +902,3 @@ bool LLCollectAllBuddies::operator()(const LLUUID& buddy_id, LLRelationship* bud
|
|||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -235,8 +235,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
|
||||
|
|
@ -248,8 +247,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,
|
||||
|
|
@ -263,8 +261,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
|
||||
|
|
|
|||
|
|
@ -26,10 +26,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"
|
||||
|
|
@ -98,6 +100,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;
|
||||
|
||||
|
|
@ -449,6 +496,7 @@ protected:
|
|||
LLUUID mSessionID;
|
||||
|
||||
S32 mMinUserNameWidth;
|
||||
const LLFontGL* mUserNameFont;
|
||||
};
|
||||
|
||||
LLUICtrl* LLChatHistoryHeader::sInfoCtrl = NULL;
|
||||
|
|
|
|||
|
|
@ -166,3 +166,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());
|
||||
//}
|
||||
|
|
|
|||
|
|
@ -61,6 +61,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
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ class LLCamera;
|
|||
class LLDrawPool;
|
||||
class LLDrawable;
|
||||
class LLFace;
|
||||
class LLFacePool;
|
||||
class LLSpatialGroup;
|
||||
class LLSpatialBridge;
|
||||
class LLSpatialPartition;
|
||||
|
|
|
|||
|
|
@ -35,10 +35,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"
|
||||
|
|
@ -47,6 +51,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)
|
||||
|
|
@ -153,7 +162,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)
|
||||
|
|
@ -161,8 +170,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -198,10 +220,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);
|
||||
|
|
@ -251,15 +273,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;
|
||||
|
|
@ -294,7 +323,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);
|
||||
|
|
@ -346,23 +374,81 @@ 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;
|
||||
|
||||
// in case of invalid characters, the avatar picker returns a 400
|
||||
// just set it to process so it displays 'not found'
|
||||
if (isGoodStatus(status) || status == 400)
|
||||
{
|
||||
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 = getChild<LLUICtrl>("Edit")->getValue().asString();
|
||||
|
||||
mQueryID.generate();
|
||||
|
||||
LLMessageSystem* msg = gMessageSystem;
|
||||
std::string url;
|
||||
url.reserve(128); // avoid a memory allocation or two
|
||||
|
||||
msg->newMessage("AvatarPickerRequest");
|
||||
msg->nextBlock("AgentData");
|
||||
msg->addUUID("AgentID", gAgent.getID());
|
||||
msg->addUUID("SessionID", gAgent.getSessionID());
|
||||
msg->addUUID("QueryID", mQueryID); // not used right now
|
||||
msg->nextBlock("Data");
|
||||
msg->addString("Name", text);
|
||||
|
||||
gAgent.sendReliableMessage();
|
||||
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 += "?page_size=100&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());
|
||||
msg->addUUID("SessionID", gAgent.getSessionID());
|
||||
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"));
|
||||
|
|
@ -503,12 +589,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);
|
||||
}
|
||||
|
|
@ -522,10 +617,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);
|
||||
getChildView("ok_btn")->setEnabled(false);
|
||||
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;
|
||||
}
|
||||
|
||||
getChildView("ok_btn")->setEnabled(true);
|
||||
search_results->setEnabled(true);
|
||||
search_results->selectFirstItem();
|
||||
onList();
|
||||
search_results->setFocus(TRUE);
|
||||
}
|
||||
|
||||
//static
|
||||
void LLFloaterAvatarPicker::editKeystroke(LLLineEditor* caller, void* user_data)
|
||||
{
|
||||
getChildView("Find")->setEnabled(caller->getText().size() >= 3);
|
||||
getChildView("Find")->setEnabled(caller->getText().size() > 0);
|
||||
}
|
||||
|
||||
// virtual
|
||||
|
|
@ -583,8 +729,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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@
|
|||
|
||||
#include <vector>
|
||||
|
||||
class LLAvatarName;
|
||||
class LLScrollListCtrl;
|
||||
|
||||
class LLFloaterAvatarPicker : public LLFloater
|
||||
|
|
@ -40,7 +41,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,
|
||||
|
|
@ -54,6 +55,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,
|
||||
|
|
|
|||
|
|
@ -27,6 +27,9 @@
|
|||
#include "llviewerprecompiledheaders.h"
|
||||
#include "llfloateravatartextures.h"
|
||||
|
||||
// library headers
|
||||
#include "llavatarnamecache.h"
|
||||
|
||||
#include "llagent.h"
|
||||
#include "llagentwearables.h"
|
||||
#include "lltexturectrl.h"
|
||||
|
|
@ -132,10 +135,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++)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -83,7 +83,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;
|
||||
}
|
||||
|
|
@ -121,8 +121,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;
|
||||
|
|
|
|||
|
|
@ -180,9 +180,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();
|
||||
|
||||
|
|
@ -820,28 +819,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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
|
||||
#include "llfloatergodtools.h"
|
||||
|
||||
#include "llavatarnamecache.h"
|
||||
#include "llcoord.h"
|
||||
#include "llfontgl.h"
|
||||
#include "llframetimer.h"
|
||||
|
|
@ -1145,11 +1146,11 @@ void LLPanelObjectTools::onClickSetBySelection(void* data)
|
|||
panelp->getChild<LLUICtrl>("target_avatar_name")->setValue(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];
|
||||
getChild<LLUICtrl>("target_avatar_name")->setValue(names[0]);
|
||||
getChild<LLUICtrl>("target_avatar_name")->setValue(names[0].getCompleteName());
|
||||
refresh();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@
|
|||
#include "llpanel.h"
|
||||
#include <vector>
|
||||
|
||||
class LLAvatarName;
|
||||
class LLButton;
|
||||
class LLCheckBoxCtrl;
|
||||
class LLComboBox;
|
||||
|
|
@ -225,7 +226,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();
|
||||
|
|
|
|||
|
|
@ -31,7 +31,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"
|
||||
|
|
@ -206,8 +206,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";
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@
|
|||
|
||||
#include "llfloaterland.h"
|
||||
|
||||
#include "llcachename.h"
|
||||
#include "llavatarnamecache.h"
|
||||
#include "llfocusmgr.h"
|
||||
#include "llnotificationsutil.h"
|
||||
#include "llparcel.h"
|
||||
|
|
@ -1377,10 +1377,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);
|
||||
|
|
@ -1598,9 +1595,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");
|
||||
|
|
@ -1709,9 +1706,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));
|
||||
}
|
||||
}
|
||||
|
|
@ -1770,10 +1765,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));
|
||||
}
|
||||
}
|
||||
|
|
@ -2764,12 +2756,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();
|
||||
|
|
@ -2808,13 +2800,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();
|
||||
|
|
|
|||
|
|
@ -372,8 +372,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;
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@
|
|||
#include "lllineeditor.h"
|
||||
#include "llmutelist.h"
|
||||
#include "llfloaterreporter.h"
|
||||
#include "llslurl.h"
|
||||
#include "llviewerobject.h"
|
||||
#include "llviewerobjectlist.h"
|
||||
#include "llviewerregion.h"
|
||||
|
|
@ -96,10 +97,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:
|
||||
|
|
@ -152,7 +149,7 @@ BOOL LLFloaterPay::postBuild()
|
|||
mCallbackData.push_back(info);
|
||||
|
||||
childSetAction("fastpay 1",&LLFloaterPay::onGive,info);
|
||||
getChildView("fastpay 1")->setVisible( FALSE);
|
||||
getChildView("fastpay 1")->setVisible(FALSE);
|
||||
|
||||
mQuickPayButton[i] = getChild<LLButton>("fastpay 1");
|
||||
mQuickPayInfo[i] = info;
|
||||
|
|
@ -162,7 +159,7 @@ BOOL LLFloaterPay::postBuild()
|
|||
mCallbackData.push_back(info);
|
||||
|
||||
childSetAction("fastpay 5",&LLFloaterPay::onGive,info);
|
||||
getChildView("fastpay 5")->setVisible( FALSE);
|
||||
getChildView("fastpay 5")->setVisible(FALSE);
|
||||
|
||||
mQuickPayButton[i] = getChild<LLButton>("fastpay 5");
|
||||
mQuickPayInfo[i] = info;
|
||||
|
|
@ -172,7 +169,7 @@ BOOL LLFloaterPay::postBuild()
|
|||
mCallbackData.push_back(info);
|
||||
|
||||
childSetAction("fastpay 10",&LLFloaterPay::onGive,info);
|
||||
getChildView("fastpay 10")->setVisible( FALSE);
|
||||
getChildView("fastpay 10")->setVisible(FALSE);
|
||||
|
||||
mQuickPayButton[i] = getChild<LLButton>("fastpay 10");
|
||||
mQuickPayInfo[i] = info;
|
||||
|
|
@ -182,14 +179,14 @@ BOOL LLFloaterPay::postBuild()
|
|||
mCallbackData.push_back(info);
|
||||
|
||||
childSetAction("fastpay 20",&LLFloaterPay::onGive,info);
|
||||
getChildView("fastpay 20")->setVisible( FALSE);
|
||||
getChildView("fastpay 20")->setVisible(FALSE);
|
||||
|
||||
mQuickPayButton[i] = getChild<LLButton>("fastpay 20");
|
||||
mQuickPayInfo[i] = info;
|
||||
++i;
|
||||
|
||||
|
||||
getChildView("amount text")->setVisible( FALSE);
|
||||
getChildView("amount text")->setVisible(FALSE);
|
||||
|
||||
std::string last_amount;
|
||||
if(sLastAmount > 0)
|
||||
|
|
@ -197,7 +194,7 @@ BOOL LLFloaterPay::postBuild()
|
|||
last_amount = llformat("%d", sLastAmount);
|
||||
}
|
||||
|
||||
getChildView("amount")->setVisible( FALSE);
|
||||
getChildView("amount")->setVisible(FALSE);
|
||||
|
||||
getChild<LLLineEditor>("amount")->setKeystrokeCallback(&LLFloaterPay::onKeystroke, this);
|
||||
getChild<LLUICtrl>("amount")->setValue(last_amount);
|
||||
|
|
@ -208,7 +205,7 @@ BOOL LLFloaterPay::postBuild()
|
|||
|
||||
childSetAction("pay btn",&LLFloaterPay::onGive,info);
|
||||
setDefaultBtn("pay btn");
|
||||
getChildView("pay btn")->setVisible( FALSE);
|
||||
getChildView("pay btn")->setVisible(FALSE);
|
||||
getChildView("pay btn")->setEnabled((sLastAmount > 0));
|
||||
|
||||
childSetAction("cancel btn",&LLFloaterPay::onCancel,this);
|
||||
|
|
@ -243,25 +240,25 @@ void LLFloaterPay::processPayPriceReply(LLMessageSystem* msg, void **userdata)
|
|||
|
||||
if (PAY_PRICE_HIDE == price)
|
||||
{
|
||||
self->getChildView("amount")->setVisible( FALSE);
|
||||
self->getChildView("pay btn")->setVisible( FALSE);
|
||||
self->getChildView("amount text")->setVisible( FALSE);
|
||||
self->getChildView("amount")->setVisible(FALSE);
|
||||
self->getChildView("pay btn")->setVisible(FALSE);
|
||||
self->getChildView("amount text")->setVisible(FALSE);
|
||||
}
|
||||
else if (PAY_PRICE_DEFAULT == price)
|
||||
{
|
||||
self->getChildView("amount")->setVisible( TRUE);
|
||||
self->getChildView("pay btn")->setVisible( TRUE);
|
||||
self->getChildView("amount text")->setVisible( TRUE);
|
||||
self->getChildView("amount")->setVisible(TRUE);
|
||||
self->getChildView("pay btn")->setVisible(TRUE);
|
||||
self->getChildView("amount text")->setVisible(TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
// PAY_PRICE_HIDE and PAY_PRICE_DEFAULT are negative values
|
||||
// So we take the absolute value here after we have checked for those cases
|
||||
|
||||
self->getChildView("amount")->setVisible( TRUE);
|
||||
self->getChildView("pay btn")->setVisible( TRUE);
|
||||
self->getChildView("amount")->setVisible(TRUE);
|
||||
self->getChildView("pay btn")->setVisible(TRUE);
|
||||
self->getChildView("pay btn")->setEnabled(TRUE);
|
||||
self->getChildView("amount text")->setVisible( TRUE);
|
||||
self->getChildView("amount text")->setVisible(TRUE);
|
||||
|
||||
self->getChild<LLUICtrl>("amount")->setValue(llformat("%d", llabs(price)));
|
||||
}
|
||||
|
|
@ -409,9 +406,9 @@ void LLFloaterPay::payDirectly(money_callback callback,
|
|||
floater->setCallback(callback);
|
||||
floater->mObjectSelection = NULL;
|
||||
|
||||
floater->getChildView("amount")->setVisible( TRUE);
|
||||
floater->getChildView("pay btn")->setVisible( TRUE);
|
||||
floater->getChildView("amount text")->setVisible( TRUE);
|
||||
floater->getChildView("amount")->setVisible(TRUE);
|
||||
floater->getChildView("pay btn")->setVisible(TRUE);
|
||||
floater->getChildView("amount text")->setVisible(TRUE);
|
||||
|
||||
floater->getChildView("fastpay text")->setVisible(TRUE);
|
||||
for(S32 i=0;i<MAX_PAY_BUTTONS;++i)
|
||||
|
|
@ -424,33 +421,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
|
||||
|
||||
getChild<LLUICtrl>("amount")->setFocus( 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();
|
||||
}
|
||||
getChild<LLTextBox>("payee_name")->setText(slurl);
|
||||
|
||||
getChild<LLUICtrl>("payee_name")->setTextArg("[FIRST]", firstname);
|
||||
getChild<LLUICtrl>("payee_name")->setTextArg("[LAST]", lastname);
|
||||
// Make sure the amount field has focus
|
||||
|
||||
LLLineEditor* amount = getChild<LLLineEditor>("amount");
|
||||
amount->setFocus(TRUE);
|
||||
amount->selectAll();
|
||||
|
||||
mTargetIsGroup = is_group;
|
||||
}
|
||||
|
||||
// static
|
||||
|
|
|
|||
|
|
@ -76,6 +76,7 @@
|
|||
#include "llvosky.h"
|
||||
|
||||
// linden library includes
|
||||
#include "llavatarnamecache.h"
|
||||
#include "llerror.h"
|
||||
#include "llfontgl.h"
|
||||
#include "llrect.h"
|
||||
|
|
@ -179,6 +180,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);
|
||||
|
|
@ -214,6 +217,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);
|
||||
|
|
@ -307,6 +322,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()
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@
|
|||
|
||||
#include "llagent.h"
|
||||
#include "llappviewer.h"
|
||||
#include "llavatarname.h"
|
||||
#include "llfloateravatarpicker.h"
|
||||
#include "llbutton.h"
|
||||
#include "llcheckboxctrl.h"
|
||||
|
|
@ -600,13 +601,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;
|
||||
|
|
@ -842,11 +843,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];
|
||||
getChild<LLUICtrl>("target_avatar_name")->setValue(LLSD(names[0]));
|
||||
getChild<LLUICtrl>("target_avatar_name")->setValue(LLSD(names[0].getCompleteName()));
|
||||
refreshFromRegion( gAgent.getRegion() );
|
||||
}
|
||||
|
||||
|
|
@ -1513,24 +1514,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));
|
||||
|
|
@ -1696,12 +1690,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;
|
||||
|
|
@ -1957,8 +1951,15 @@ void LLPanelEstateInfo::updateControls(LLViewerRegion* region)
|
|||
getChildView("remove_allowed_avatar_btn")->setEnabled(god || owner || manager);
|
||||
getChildView("add_allowed_group_btn")->setEnabled(god || owner || manager);
|
||||
getChildView("remove_allowed_group_btn")->setEnabled(god || owner || manager);
|
||||
getChildView("add_banned_avatar_btn")->setEnabled(god || owner || manager);
|
||||
getChildView("remove_banned_avatar_btn")->setEnabled(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;
|
||||
getChildView("add_banned_avatar_btn")->setEnabled(enable_ban);
|
||||
getChildView("remove_banned_avatar_btn")->setEnabled(enable_ban);
|
||||
|
||||
getChildView("message_estate_btn")->setEnabled(god || owner || manager);
|
||||
getChildView("kick_user_from_estate_btn")->setEnabled(god || owner || manager);
|
||||
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@
|
|||
#include "llhost.h"
|
||||
#include "llpanel.h"
|
||||
|
||||
class LLAvatarName;
|
||||
class LLDispatcher;
|
||||
class LLLineEditor;
|
||||
class LLMessageSystem;
|
||||
|
|
@ -162,7 +163,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);
|
||||
|
|
@ -187,7 +188,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*);
|
||||
|
|
@ -278,7 +279,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);
|
||||
|
|
@ -290,7 +291,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);
|
||||
|
||||
|
|
|
|||
|
|
@ -33,6 +33,8 @@
|
|||
|
||||
// linden library includes
|
||||
#include "llassetstorage.h"
|
||||
#include "llavatarnamecache.h"
|
||||
#include "llcachename.h"
|
||||
#include "llfontgl.h"
|
||||
#include "llimagej2c.h"
|
||||
#include "llinventory.h"
|
||||
|
|
@ -176,9 +178,8 @@ BOOL LLFloaterReporter::postBuild()
|
|||
childSetAction("cancel_btn", onClickCancel, this);
|
||||
|
||||
// grab the user's name
|
||||
std::string fullname;
|
||||
LLAgentUI::buildFullname(fullname);
|
||||
getChild<LLUICtrl>("reporter_field")->setValue(fullname);
|
||||
std::string reporter = LLSLURL("agent", gAgent.getID(), "inspect").getSLURLString();
|
||||
getChild<LLUICtrl>("reporter_field")->setValue(reporter);
|
||||
|
||||
center();
|
||||
|
||||
|
|
@ -261,22 +262,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
|
||||
{
|
||||
|
|
@ -303,11 +289,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;
|
||||
|
||||
getChild<LLUICtrl>("abuser_name_edit")->setValue(names[0] );
|
||||
getChild<LLUICtrl>("abuser_name_edit")->setValue(names[0].getCompleteName());
|
||||
|
||||
mAbuserID = ids[0];
|
||||
|
||||
|
|
@ -315,18 +301,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();
|
||||
getChild<LLUICtrl>("owner_name")->setValue(avatar_link);
|
||||
getChild<LLUICtrl>("object_name")->setValue(avatar_name);
|
||||
getChild<LLUICtrl>("abuser_name_edit")->setValue(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();
|
||||
getChild<LLUICtrl>("object_name")->setValue(av_name.getCompleteName());
|
||||
getChild<LLUICtrl>("object_name")->setToolTip(av_name.getCompleteName());
|
||||
getChild<LLUICtrl>("abuser_name_edit")->setValue(av_name.getCompleteName());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// static
|
||||
void LLFloaterReporter::onClickSend(void *userdata)
|
||||
{
|
||||
|
|
@ -466,16 +461,15 @@ 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->getChild<LLUICtrl>("reporter_field")->setValue(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;
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@
|
|||
#include "lluuid.h"
|
||||
#include "v3math.h"
|
||||
|
||||
class LLAvatarName;
|
||||
class LLMessageSystem;
|
||||
class LLViewerTexture;
|
||||
class LLInventoryItem;
|
||||
|
|
@ -117,8 +118,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;
|
||||
|
|
|
|||
|
|
@ -28,6 +28,8 @@
|
|||
#include "llviewerprecompiledheaders.h"
|
||||
#include "llfloaterscriptlimits.h"
|
||||
|
||||
// library includes
|
||||
#include "llavatarnamecache.h"
|
||||
#include "llsdutil.h"
|
||||
#include "llsdutil_math.h"
|
||||
#include "message.h"
|
||||
|
|
@ -289,7 +291,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->getChild<LLUICtrl>("loading_text")->setValue(LLSD(std::string("")));
|
||||
|
|
@ -300,9 +302,9 @@ void fetchScriptLimitsRegionSummaryResponder::result(const LLSD& content_ref)
|
|||
btn->setEnabled(true);
|
||||
}
|
||||
|
||||
panel_memory->setRegionSummary(content);
|
||||
}
|
||||
}
|
||||
panel_memory->setRegionSummary(content);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -592,17 +594,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)
|
||||
{
|
||||
|
|
@ -668,6 +677,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;
|
||||
|
|
@ -693,15 +705,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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1303,7 +1327,7 @@ void LLPanelScriptLimitsAttachment::setAttachmentSummary(LLSD content)
|
|||
|
||||
// static
|
||||
void LLPanelScriptLimitsAttachment::onClickRefresh(void* userdata)
|
||||
{
|
||||
{
|
||||
LLFloaterScriptLimits* instance = LLFloaterReg::getTypedInstance<LLFloaterScriptLimits>("script_limits");
|
||||
if(instance)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -164,10 +164,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;
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
|
||||
#include "llfloatersellland.h"
|
||||
|
||||
#include "llavatarnamecache.h"
|
||||
#include "llfloateravatarpicker.h"
|
||||
#include "llfloaterreg.h"
|
||||
#include "llfloaterland.h"
|
||||
|
|
@ -41,6 +42,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);
|
||||
|
|
@ -89,7 +92,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();
|
||||
|
|
@ -224,12 +229,17 @@ void LLFloaterSellLandUI::updateParcelInfo()
|
|||
|
||||
if(mSellToBuyer)
|
||||
{
|
||||
std::string name;
|
||||
gCacheName->getFullName(mAuthorizedBuyer, name);
|
||||
getChild<LLUICtrl>("sell_to_agent")->setValue(name);
|
||||
LLAvatarNameCache::get(mAuthorizedBuyer,
|
||||
boost::bind(&LLFloaterSellLandUI::onBuyerNameCache, this, _2));
|
||||
}
|
||||
}
|
||||
|
||||
void LLFloaterSellLandUI::onBuyerNameCache(const LLAvatarName& av_name)
|
||||
{
|
||||
getChild<LLUICtrl>("sell_to_agent")->setValue(av_name.getCompleteName());
|
||||
getChild<LLUICtrl>("sell_to_agent")->setToolTip(av_name.mUsername);
|
||||
}
|
||||
|
||||
void LLFloaterSellLandUI::setBadge(const char* id, Badge badge)
|
||||
{
|
||||
static std::string badgeOK("badge_ok.j2c");
|
||||
|
|
@ -385,7 +395,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();
|
||||
|
||||
|
|
@ -396,7 +406,7 @@ void LLFloaterSellLandUI::callbackAvatarPick(const std::vector<std::string>& nam
|
|||
|
||||
mAuthorizedBuyer = ids[0];
|
||||
|
||||
getChild<LLUICtrl>("sell_to_agent")->setValue(names[0]);
|
||||
getChild<LLUICtrl>("sell_to_agent")->setValue(names[0].getCompleteName());
|
||||
|
||||
refreshUI();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,7 +28,9 @@
|
|||
|
||||
#include "llfloatertopobjects.h"
|
||||
|
||||
// library includes
|
||||
#include "message.h"
|
||||
#include "llavatarnamecache.h"
|
||||
#include "llfontgl.h"
|
||||
|
||||
#include "llagent.h"
|
||||
|
|
@ -190,37 +192,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";
|
||||
|
||||
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";
|
||||
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);
|
||||
|
||||
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);
|
||||
|
|
|
|||
|
|
@ -115,7 +115,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();
|
||||
|
|
|
|||
|
|
@ -25,7 +25,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"
|
||||
|
|
|
|||
|
|
@ -51,7 +51,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
|
||||
{
|
||||
|
|
|
|||
|
|
@ -26,13 +26,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"
|
||||
|
|
@ -541,8 +542,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
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@
|
|||
#include "lltoolmgr.h"
|
||||
#include "llselectmgr.h"
|
||||
#include "llhudmanager.h"
|
||||
#include "llhudtext.h"
|
||||
#include "llrendersphere.h"
|
||||
#include "llviewerobjectlist.h"
|
||||
#include "lltoolselectrect.h"
|
||||
|
|
@ -888,7 +889,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;
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@
|
|||
// Renders a 2D icon billboard floating at the location specified.
|
||||
class LLDrawable;
|
||||
class LLViewerObject;
|
||||
class LLViewerTexture;
|
||||
|
||||
class LLHUDIcon : public LLHUDObject
|
||||
{
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -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
|
||||
|
|
@ -4,7 +4,7 @@
|
|||
*
|
||||
* $LicenseInfo:firstyear=2002&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
* Copyright (C) 2002-2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
|
|
@ -24,9 +24,6 @@
|
|||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
// llhudobject.cpp
|
||||
// Copyright 2002, Linden Research, Inc.
|
||||
|
||||
#include "llviewerprecompiledheaders.h"
|
||||
|
||||
#include "llhudobject.h"
|
||||
|
|
@ -38,7 +35,7 @@
|
|||
#include "llhudeffecttrail.h"
|
||||
#include "llhudeffectlookat.h"
|
||||
#include "llhudeffectpointat.h"
|
||||
|
||||
#include "llhudnametag.h"
|
||||
#include "llvoicevisualizer.h"
|
||||
|
||||
#include "llagent.h"
|
||||
|
|
@ -66,7 +63,6 @@ LLHUDObject::LLHUDObject(const U8 type) :
|
|||
mVisible = TRUE;
|
||||
mType = type;
|
||||
mDead = FALSE;
|
||||
mOnHUDAttachment = FALSE;
|
||||
}
|
||||
|
||||
LLHUDObject::~LLHUDObject()
|
||||
|
|
@ -145,6 +141,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;
|
||||
}
|
||||
|
|
@ -257,6 +256,7 @@ void LLHUDObject::updateAll()
|
|||
LLFastTimer ftm(FTM_HUD_UPDATE);
|
||||
LLHUDText::updateAll();
|
||||
LLHUDIcon::updateAll();
|
||||
LLHUDNameTag::updateAll();
|
||||
sortObjects();
|
||||
}
|
||||
|
||||
|
|
@ -325,6 +325,14 @@ void LLHUDObject::renderAllForTimer()
|
|||
}
|
||||
}
|
||||
|
||||
// static
|
||||
void LLHUDObject::reshapeAll()
|
||||
{
|
||||
// only hud objects that use fonts care about window size/scale changes
|
||||
LLHUDText::reshape();
|
||||
LLHUDNameTag::reshape();
|
||||
}
|
||||
|
||||
// static
|
||||
void LLHUDObject::sortObjects()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@
|
|||
#include "v4color.h"
|
||||
#include "v3math.h"
|
||||
#include "v3dmath.h"
|
||||
#include "lldrawpool.h"
|
||||
#include "lldrawpool.h" // TODO: eliminate, unused below
|
||||
#include <list>
|
||||
|
||||
class LLViewerCamera;
|
||||
|
|
@ -71,6 +71,9 @@ public:
|
|||
static void renderAllForSelect();
|
||||
static void renderAllForTimer();
|
||||
|
||||
// Some objects may need to update when window shape changes
|
||||
static void reshapeAll();
|
||||
|
||||
static void cleanupHUDObjects();
|
||||
|
||||
enum
|
||||
|
|
@ -91,7 +94,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();
|
||||
|
|
@ -108,7 +112,6 @@ protected:
|
|||
BOOL mDead;
|
||||
BOOL mVisible;
|
||||
LLVector3d mPositionGlobal;
|
||||
BOOL mOnHUDAttachment;
|
||||
LLPointer<LLViewerObject> mSourceObject;
|
||||
LLPointer<LLViewerObject> mTargetObject;
|
||||
|
||||
|
|
|
|||
|
|
@ -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=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
|
|
@ -56,16 +55,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;
|
||||
|
|
@ -74,15 +73,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()),
|
||||
|
|
@ -92,7 +90,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);
|
||||
|
|
@ -100,7 +98,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);
|
||||
|
|
@ -111,112 +108,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)
|
||||
|
|
@ -242,21 +133,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);
|
||||
|
|
@ -284,7 +167,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;
|
||||
|
|
@ -330,178 +213,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
|
||||
|
|
@ -522,15 +244,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)
|
||||
|
|
@ -550,21 +268,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()
|
||||
|
|
@ -573,21 +282,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)
|
||||
LLWString wline = utf8str_to_wstring(text_utf8);
|
||||
if (!wline.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (!wstr.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());
|
||||
|
|
@ -600,8 +307,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());
|
||||
|
|
@ -610,47 +319,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;
|
||||
|
|
@ -672,12 +340,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;
|
||||
|
|
@ -745,7 +418,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;
|
||||
|
|
@ -763,15 +436,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;
|
||||
|
|
@ -786,11 +459,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);
|
||||
|
||||
|
|
@ -821,12 +494,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;
|
||||
|
|
@ -835,17 +508,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;
|
||||
|
|
@ -854,18 +522,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));
|
||||
}
|
||||
|
|
@ -889,146 +547,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()
|
||||
|
|
@ -1079,22 +622,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()
|
||||
|
|
@ -1109,11 +636,6 @@ void LLHUDText::reshape()
|
|||
{
|
||||
segment_iter->clearFontWidthMap();
|
||||
}
|
||||
for(segment_iter = textp->mLabelSegments.begin();
|
||||
segment_iter != textp->mLabelSegments.end(); ++segment_iter )
|
||||
{
|
||||
segment_iter->clearFontWidthMap();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -28,18 +28,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;
|
||||
|
|
@ -56,14 +53,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;
|
||||
|
|
@ -83,20 +85,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; }
|
||||
|
|
@ -110,21 +113,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);
|
||||
|
||||
|
|
@ -132,21 +131,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;
|
||||
|
|
@ -164,11 +159,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 ;
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@
|
|||
|
||||
#include "llagent.h"
|
||||
#include "llappviewer.h"
|
||||
#include "llavatarnamecache.h"
|
||||
#include "llbutton.h"
|
||||
#include "llbottomtray.h"
|
||||
#include "llchannelmanager.h"
|
||||
|
|
@ -275,12 +276,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");
|
||||
|
|
@ -298,6 +293,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)
|
||||
|
||||
|
|
@ -311,6 +319,23 @@ 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);
|
||||
mTypingStart.setArg("[NAME]", ui_title);
|
||||
}
|
||||
|
||||
// virtual
|
||||
void LLIMFloater::draw()
|
||||
{
|
||||
|
|
@ -1071,13 +1096,9 @@ void LLIMFloater::addTypingIndicator(const LLIMInfo* im_info)
|
|||
{
|
||||
mOtherTyping = true;
|
||||
|
||||
// Create typing is started title string
|
||||
LLUIString typing_start(mTypingStart);
|
||||
typing_start.setArg("[NAME]", im_info->mName);
|
||||
|
||||
// Save and set new title
|
||||
mSavedTitle = getTitle();
|
||||
setTitle (typing_start);
|
||||
setTitle (mTypingStart);
|
||||
|
||||
// Update speaker
|
||||
LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID);
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@
|
|||
#include "lltooldraganddrop.h"
|
||||
#include "lltransientdockablefloater.h"
|
||||
|
||||
class LLAvatarName;
|
||||
class LLLineEditor;
|
||||
class LLPanelChatControlPanel;
|
||||
class LLChatHistory;
|
||||
|
|
@ -124,6 +125,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);
|
||||
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
|
||||
#include "llimview.h"
|
||||
|
||||
#include "llavatarnamecache.h" // IDEVO
|
||||
#include "llfloaterreg.h"
|
||||
#include "llfontgl.h"
|
||||
#include "llgl.h"
|
||||
|
|
@ -64,11 +65,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");
|
||||
|
||||
|
|
@ -102,6 +98,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"])
|
||||
|
|
@ -129,14 +139,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)
|
||||
|
|
@ -282,7 +287,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)
|
||||
{
|
||||
|
|
@ -417,13 +422,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];
|
||||
|
||||
|
|
@ -1754,11 +1763,23 @@ void LLOutgoingCallDialog::show(const LLSD& key)
|
|||
callee_name = LLTextUtil::formatPhoneNumber(callee_name);
|
||||
}
|
||||
|
||||
setTitle(callee_name);
|
||||
|
||||
LLSD callee_id = mPayload["other_user_id"];
|
||||
getChild<LLUICtrl>("calling")->setTextArg("[CALLEE_NAME]", callee_name);
|
||||
getChild<LLUICtrl>("connecting")->setTextArg("[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();
|
||||
}
|
||||
}
|
||||
getChild<LLUICtrl>("calling")->setTextArg("[CALLEE_NAME]", final_callee_name);
|
||||
getChild<LLUICtrl>("connecting")->setTextArg("[CALLEE_NAME]", final_callee_name);
|
||||
|
||||
setTitle(title);
|
||||
|
||||
// for outgoing group calls callee_id == group id == session id
|
||||
setIcon(callee_id, callee_id);
|
||||
|
|
@ -1913,16 +1934,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);
|
||||
|
|
@ -1950,6 +1976,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)
|
||||
{
|
||||
|
|
@ -2057,8 +2101,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);
|
||||
}
|
||||
}
|
||||
|
|
@ -2579,7 +2626,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
|
||||
{
|
||||
|
|
@ -2589,9 +2637,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();
|
||||
|
|
@ -2812,13 +2860,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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@
|
|||
#include "llvoicechannel.h"
|
||||
|
||||
|
||||
|
||||
class LLAvatarName;
|
||||
class LLFriendObserver;
|
||||
class LLCallDialogManager;
|
||||
class LLIMSpeakerMgr;
|
||||
|
|
@ -453,7 +453,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);
|
||||
|
|
@ -535,6 +535,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);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@
|
|||
#include "llagent.h"
|
||||
#include "llagentdata.h"
|
||||
#include "llavataractions.h"
|
||||
#include "llavatarnamecache.h"
|
||||
#include "llavatarpropertiesprocessor.h"
|
||||
#include "llcallingcard.h"
|
||||
#include "lldateutil.h"
|
||||
|
|
@ -51,6 +52,7 @@
|
|||
#include "llfloater.h"
|
||||
#include "llfloaterreg.h"
|
||||
#include "llmenubutton.h"
|
||||
#include "lltextbox.h"
|
||||
#include "lltooltip.h" // positionViewNearMouse()
|
||||
#include "lltrans.h"
|
||||
#include "lluictrl.h"
|
||||
|
|
@ -137,17 +139,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;
|
||||
|
|
@ -330,6 +328,8 @@ void LLInspectAvatar::requestUpdate()
|
|||
|
||||
// Clear out old data so it doesn't flash between old and new
|
||||
getChild<LLUICtrl>("user_name")->setValue("");
|
||||
getChild<LLUICtrl>("user_name_small")->setValue("");
|
||||
getChild<LLUICtrl>("user_slid")->setValue("");
|
||||
getChild<LLUICtrl>("user_subtitle")->setValue("");
|
||||
getChild<LLUICtrl>("user_details")->setValue("");
|
||||
|
||||
|
|
@ -367,9 +367,9 @@ void LLInspectAvatar::requestUpdate()
|
|||
|
||||
getChild<LLUICtrl>("avatar_icon")->setValue(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)
|
||||
|
|
@ -556,7 +556,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 );
|
||||
|
|
@ -587,7 +587,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);
|
||||
|
|
@ -606,22 +606,36 @@ 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;
|
||||
getChild<LLUICtrl>("user_name")->setValue(LLSD(mAvatarName) );
|
||||
getChild<LLUICtrl>("user_name")->setValue(av_name.mDisplayName);
|
||||
getChild<LLUICtrl>("user_name_small")->setValue(av_name.mDisplayName);
|
||||
getChild<LLUICtrl>("user_slid")->setValue(av_name.mUsername);
|
||||
mAvatarName = av_name;
|
||||
|
||||
// show smaller display name if too long to display in regular size
|
||||
if (getChild<LLTextBox>("user_name")->getTextPixelWidth() > getChild<LLTextBox>("user_name")->getRect().getWidth())
|
||||
{
|
||||
getChild<LLUICtrl>("user_name_small")->setVisible( true );
|
||||
getChild<LLUICtrl>("user_name")->setVisible( false );
|
||||
}
|
||||
else
|
||||
{
|
||||
getChild<LLUICtrl>("user_name_small")->setVisible( false );
|
||||
getChild<LLUICtrl>("user_name")->setVisible( true );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void LLInspectAvatar::onClickAddFriend()
|
||||
{
|
||||
LLAvatarActions::requestFriendshipDialog(mAvatarID, mAvatarName);
|
||||
LLAvatarActions::requestFriendshipDialog(mAvatarID, mAvatarName.getLegacyName());
|
||||
closeFloater();
|
||||
}
|
||||
|
||||
|
|
@ -689,7 +703,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))
|
||||
{
|
||||
|
|
@ -706,7 +720,7 @@ void LLInspectAvatar::onToggleMute()
|
|||
|
||||
void LLInspectAvatar::onClickReport()
|
||||
{
|
||||
LLFloaterReporter::showFromAvatar(mAvatarID, mAvatarName);
|
||||
LLFloaterReporter::showFromAvatar(mAvatarID, mAvatarName.getCompleteName());
|
||||
closeFloater();
|
||||
}
|
||||
|
||||
|
|
@ -730,17 +744,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;
|
||||
}
|
||||
|
|
@ -752,10 +766,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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -78,9 +78,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();
|
||||
|
|
@ -219,21 +218,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
|
||||
getChild<LLUICtrl>("group_name")->setValue(LLSD(first) );
|
||||
getChild<LLUICtrl>("group_name")->setValue( LLSD(name) );
|
||||
}
|
||||
|
||||
// Otherwise possibly a request for an older inspector, ignore it
|
||||
|
|
|
|||
|
|
@ -60,12 +60,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;
|
||||
|
|
@ -75,7 +75,7 @@ LLInspectRemoteObject::LLInspectRemoteObject(const LLSD& sd) :
|
|||
LLInspect(LLSD()),
|
||||
mObjectID(NULL),
|
||||
mOwnerID(NULL),
|
||||
mOwner(""),
|
||||
mOwnerLegacyName(),
|
||||
mSLurl(""),
|
||||
mName(""),
|
||||
mGroupOwned(false)
|
||||
|
|
@ -112,10 +112,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
|
||||
|
|
@ -144,7 +145,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();
|
||||
|
|
@ -155,16 +156,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()
|
||||
|
|
@ -174,7 +169,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)
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@
|
|||
|
||||
// external projects
|
||||
#include "lltransfersourceasset.h"
|
||||
#include "llavatarnamecache.h" // IDEVO
|
||||
|
||||
#include "llagent.h"
|
||||
#include "llagentcamera.h"
|
||||
|
|
@ -3450,6 +3451,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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -26,13 +26,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>
|
||||
|
|
@ -56,12 +61,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(" ");
|
||||
|
|
@ -184,7 +190,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;
|
||||
}
|
||||
|
||||
|
|
@ -233,6 +240,18 @@ void LLLogChat::saveHistory(const std::string& filename,
|
|||
const std::string& from,
|
||||
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);
|
||||
|
|
@ -254,89 +273,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;
|
||||
|
|
@ -346,6 +303,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())
|
||||
|
|
@ -409,53 +367,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;
|
||||
|
|
|
|||
|
|
@ -24,10 +24,11 @@
|
|||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
|
||||
#ifndef LL_LLLOGCHAT_H
|
||||
#define LL_LLLOGCHAT_H
|
||||
|
||||
class LLChat;
|
||||
|
||||
class LLLogChat
|
||||
{
|
||||
public:
|
||||
|
|
@ -40,48 +41,21 @@ 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
|
||||
*/
|
||||
|
|
@ -100,11 +74,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
|
||||
|
|
|
|||
|
|
@ -137,6 +137,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");
|
||||
|
|
|
|||
|
|
@ -112,9 +112,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;
|
||||
}
|
||||
|
|
@ -410,7 +409,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)
|
||||
|
|
@ -428,8 +427,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)
|
||||
|
|
@ -444,7 +442,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;
|
||||
|
||||
|
|
@ -454,24 +452,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(¬ify_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(¬ify_automute_callback, _1, _2, _3, reason));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue