Merged in lindenlab/viewer-release
commit
37eb735ba7
1
.hgtags
1
.hgtags
|
|
@ -552,3 +552,4 @@ ec09daf1899c1c01c4ba0ba950fae572f2a612a8 6.2.2-release
|
|||
ab2ec5c5423b277d23fd0511ce50c15123ff2e03 6.2.3-release
|
||||
67297f9902857e357570c44722ad84de3aff974e 6.2.4-release
|
||||
9777aec6dc4a30a24537297ac040861ce16b82ae 6.3.0-release
|
||||
ece699718f163921717bb95a6131e94af4c4138f 6.3.1-release
|
||||
|
|
|
|||
|
|
@ -1073,6 +1073,7 @@ Nicky Dasmijn
|
|||
MAINT-6665
|
||||
SL-10291
|
||||
SL-10293
|
||||
SL-11061
|
||||
Nicky Perian
|
||||
OPEN-1
|
||||
STORM-1087
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@
|
|||
# cmake_minimum_required should appear before any
|
||||
# other commands to guarantee full compatibility
|
||||
# with the version specified
|
||||
## prior to 3.4, the Windows manifest handling was missing
|
||||
cmake_minimum_required(VERSION 3.4.0 FATAL_ERROR)
|
||||
## 3.8 added VS_DEBUGGER_WORKING_DIRECTORY support
|
||||
cmake_minimum_required(VERSION 3.8.0 FATAL_ERROR)
|
||||
|
||||
set(ROOT_PROJECT_NAME "SecondLife" CACHE STRING
|
||||
"The root project/makefile/solution name. Defaults to SecondLife.")
|
||||
|
|
@ -83,6 +83,12 @@ add_dependencies(viewer secondlife-bin)
|
|||
|
||||
add_subdirectory(${VIEWER_PREFIX}doxygen EXCLUDE_FROM_ALL)
|
||||
|
||||
# sets the 'startup project' for debugging from visual studio.
|
||||
set_property(
|
||||
DIRECTORY ${VIEWER_PREFIX}
|
||||
PROPERTY VS_STARTUP_PROJECT secondlife-bin
|
||||
)
|
||||
|
||||
if (LL_TESTS)
|
||||
# Define after the custom targets are created so
|
||||
# individual apps can add themselves as dependencies
|
||||
|
|
|
|||
|
|
@ -151,6 +151,8 @@ endif (LINUX)
|
|||
|
||||
|
||||
if (DARWIN)
|
||||
# Warnings should be fatal -- thanks, Nicky Perian, for spotting reversed default
|
||||
set(CLANG_DISABLE_FATAL_WARNINGS OFF)
|
||||
set(CMAKE_CXX_LINK_FLAGS "-Wl,-headerpad_max_install_names,-search_paths_first")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_CXX_LINK_FLAGS}")
|
||||
set(DARWIN_extra_cstar_flags "-Wno-unused-local-typedef -Wno-deprecated-declarations")
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ const S32 LLVORBISENC_UNSUPPORTED_WORD_SIZE = 9; // unsupported word size
|
|||
const S32 LLVORBISENC_CLIP_TOO_LONG = 10; // source file is too long
|
||||
const S32 LLVORBISENC_CHUNK_SIZE_ERR = 11; // chunk size is wrong
|
||||
|
||||
const F32 LLVORBIS_CLIP_MAX_TIME = 10.0f;
|
||||
const F32 LLVORBIS_CLIP_MAX_TIME = 30.0f;
|
||||
const U8 LLVORBIS_CLIP_MAX_CHANNELS = 2;
|
||||
const U32 LLVORBIS_CLIP_SAMPLE_RATE = 44100;
|
||||
const U32 LLVORBIS_CLIP_MAX_SAMPLES_PER_CHANNEL = (U32)(LLVORBIS_CLIP_MAX_TIME * LLVORBIS_CLIP_SAMPLE_RATE);
|
||||
|
|
|
|||
|
|
@ -1735,7 +1735,8 @@ bool LLStringUtilBase<T>::startsWith(
|
|||
const string_type& substr)
|
||||
{
|
||||
if(string.empty() || (substr.empty())) return false;
|
||||
if(0 == string.find(substr)) return true;
|
||||
if (substr.length() > string.length()) return false;
|
||||
if (0 == string.compare(0, substr.length(), substr)) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -1746,9 +1747,11 @@ bool LLStringUtilBase<T>::endsWith(
|
|||
const string_type& substr)
|
||||
{
|
||||
if(string.empty() || (substr.empty())) return false;
|
||||
std::string::size_type idx = string.rfind(substr);
|
||||
if(std::string::npos == idx) return false;
|
||||
return (idx == (string.size() - substr.size()));
|
||||
size_t sub_len = substr.length();
|
||||
size_t str_len = string.length();
|
||||
if (sub_len > str_len) return false;
|
||||
if (0 == string.compare(str_len - sub_len, sub_len, substr)) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
// static
|
||||
|
|
|
|||
|
|
@ -173,6 +173,19 @@ namespace
|
|||
"-._~";
|
||||
return s;
|
||||
}
|
||||
const std::string path()
|
||||
{
|
||||
static const std::string s =
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"abcdefghijklmnopqrstuvwxyz"
|
||||
"0123456789"
|
||||
"$-_.+"
|
||||
"!*'(),"
|
||||
"{}|\\^~[]`"
|
||||
"<>#%"
|
||||
";/?:@&=";
|
||||
return s;
|
||||
}
|
||||
const std::string sub_delims()
|
||||
{
|
||||
static const std::string s = "!$&'()*+,;=";
|
||||
|
|
@ -187,6 +200,12 @@ namespace
|
|||
{ return LLURI::escape(s, unreserved() + ":@!$'()*+,"); } // sub_delims - "&;=" + ":@"
|
||||
std::string escapeQueryValue(const std::string& s)
|
||||
{ return LLURI::escape(s, unreserved() + ":@!$'()*+,="); } // sub_delims - "&;" + ":@"
|
||||
std::string escapeUriQuery(const std::string& s)
|
||||
{ return LLURI::escape(s, unreserved() + ":@?&$;*+=%/"); }
|
||||
std::string escapeUriData(const std::string& s)
|
||||
{ return LLURI::escape(s, unreserved() + "%"); }
|
||||
std::string escapeUriPath(const std::string& s)
|
||||
{ return LLURI::escape(s, path()); }
|
||||
}
|
||||
|
||||
//static
|
||||
|
|
@ -202,6 +221,85 @@ std::string LLURI::escape(const std::string& str)
|
|||
return escape(str, default_allowed, true);
|
||||
}
|
||||
|
||||
//static
|
||||
std::string LLURI::escapePathAndData(const std::string &str)
|
||||
{
|
||||
std::string result;
|
||||
|
||||
const std::string data_marker = "data:";
|
||||
if (str.compare(0, data_marker.length(), data_marker) == 0)
|
||||
{
|
||||
// This is not url, but data, data part needs to be properly escaped
|
||||
// data part is separated by ',' from header. Minimal data uri is "data:,"
|
||||
// See "data URI scheme"
|
||||
size_t separator = str.find(',');
|
||||
if (separator != std::string::npos)
|
||||
{
|
||||
size_t header_size = separator + 1;
|
||||
std::string header = str.substr(0, header_size);
|
||||
// base64 is url-safe
|
||||
if (header.find("base64") != std::string::npos)
|
||||
{
|
||||
// assume url-safe data
|
||||
result = str;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string data = str.substr(header_size, str.length() - header_size);
|
||||
|
||||
// Notes: File can be partially pre-escaped, that's why escaping ignores '%'
|
||||
// It somewhat limits user from displaying strings like "%20" in text
|
||||
// but that's how viewer worked for a while and user can double-escape it
|
||||
|
||||
|
||||
// Header doesn't need escaping
|
||||
result = header + escapeUriData(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// try processing it as path with query separator
|
||||
// The query component is indicated by the first question
|
||||
// mark("?") character and terminated by a number sign("#")
|
||||
size_t delim_pos = str.find('?');
|
||||
if (delim_pos == std::string::npos)
|
||||
{
|
||||
// alternate separator
|
||||
delim_pos = str.find(';');
|
||||
}
|
||||
|
||||
if (delim_pos != std::string::npos)
|
||||
{
|
||||
size_t path_size = delim_pos + 1;
|
||||
std::string query;
|
||||
std::string fragment;
|
||||
|
||||
size_t fragment_pos = str.find('#');
|
||||
if (fragment_pos != std::string::npos)
|
||||
{
|
||||
query = str.substr(path_size, fragment_pos - path_size);
|
||||
fragment = str.substr(fragment_pos);
|
||||
}
|
||||
else
|
||||
{
|
||||
query = str.substr(path_size);
|
||||
}
|
||||
|
||||
std::string path = str.substr(0, path_size);
|
||||
|
||||
result = escapeUriPath(path) + escapeUriQuery(query) + escapeUriPath(fragment);
|
||||
}
|
||||
}
|
||||
|
||||
if (result.empty())
|
||||
{
|
||||
// Not a known scheme or no data part, try just escaping as Uri path
|
||||
result = escapeUriPath(str);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
LLURI::LLURI()
|
||||
{
|
||||
}
|
||||
|
|
|
|||
|
|
@ -157,6 +157,14 @@ public:
|
|||
const std::string& allowed,
|
||||
bool is_allowed_sorted = false);
|
||||
|
||||
/**
|
||||
* @brief Break string into data part and path or sheme
|
||||
* and escape path (if present) and data.
|
||||
* Data part is not allowed to have path related symbols
|
||||
* @param str The raw URI to escape.
|
||||
*/
|
||||
static std::string escapePathAndData(const std::string &str);
|
||||
|
||||
/**
|
||||
* @brief unescape an escaped URI string.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -383,6 +383,41 @@ namespace tut
|
|||
ensure_equals("query", u.query(), "redirect-http-hack=secondlife:///app/login?first_name=Callum&last_name=Linden&location=specify&grid=vaak®ion=/Morris/128/128&web_login_key=efaa4795-c2aa-4c58-8966-763c27931e78");
|
||||
ensure_equals("query map element", u.queryMap()["redirect-http-hack"].asString(), "secondlife:///app/login?first_name=Callum&last_name=Linden&location=specify&grid=vaak®ion=/Morris/128/128&web_login_key=efaa4795-c2aa-4c58-8966-763c27931e78");
|
||||
}
|
||||
|
||||
template<> template<>
|
||||
void URITestObject::test<20>()
|
||||
{
|
||||
set_test_name("escapePathAndData uri test");
|
||||
|
||||
// Basics scheme:[//authority]path[?query][#fragment]
|
||||
ensure_equals(LLURI::escapePathAndData("dirname?query"),
|
||||
"dirname?query");
|
||||
ensure_equals(LLURI::escapePathAndData("dirname?query=data"),
|
||||
"dirname?query=data");
|
||||
ensure_equals(LLURI::escapePathAndData("host://dirname/subdir name?query#fragment"),
|
||||
"host://dirname/subdir%20name?query#fragment");
|
||||
ensure_equals(LLURI::escapePathAndData("host://dirname/subdir name?query=some@>data#fragment"),
|
||||
"host://dirname/subdir%20name?query=some@%3Edata#fragment");
|
||||
ensure_equals(LLURI::escapePathAndData("host://dir[name/subdir name?query=some[data#fra[gment"),
|
||||
"host://dir[name/subdir%20name?query=some%5Bdata#fra[gment");
|
||||
ensure_equals(LLURI::escapePathAndData("mailto:zero@ll.com"),
|
||||
"mailto:zero@ll.com");
|
||||
// pre-escaped
|
||||
ensure_equals(LLURI::escapePathAndData("host://dirname/subdir%20name"),
|
||||
"host://dirname/subdir%20name");
|
||||
|
||||
// data:[<mediatype>][;base64],<data>
|
||||
ensure_equals(LLURI::escapePathAndData("data:,Hello, World!"),
|
||||
"data:,Hello%2C%20World%21");
|
||||
ensure_equals(LLURI::escapePathAndData("data:text/html,<h1>Hello, World!</h1>"),
|
||||
"data:text/html,%3Ch1%3EHello%2C%20World%21%3C%2Fh1%3E");
|
||||
// pre-escaped
|
||||
ensure_equals(LLURI::escapePathAndData("data:text/html,%3Ch1%3EHello%2C%20World!</h1>"),
|
||||
"data:text/html,%3Ch1%3EHello%2C%20World%21%3C%2Fh1%3E");
|
||||
// assume that base64 does not need escaping
|
||||
ensure_equals(LLURI::escapePathAndData("data:image;base64,SGVs/bG8sIFd/vcmxkIQ%3D%3D!-&*?="),
|
||||
"data:image;base64,SGVs/bG8sIFd/vcmxkIQ%3D%3D!-&*?=");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -355,7 +355,8 @@ bool HttpLibcurl::completeRequest(CURLM * multi_handle, CURL * handle, CURLcode
|
|||
}
|
||||
if (op->mStatus)
|
||||
{
|
||||
int http_status(HTTP_OK);
|
||||
// note: CURLINFO_RESPONSE_CODE requires a long - https://curl.haxx.se/libcurl/c/CURLINFO_RESPONSE_CODE.html
|
||||
long http_status(HTTP_OK);
|
||||
|
||||
if (handle)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -181,7 +181,7 @@ bool LLImageBMP::updateData()
|
|||
}
|
||||
}
|
||||
else
|
||||
if( 12 <= header.mSize && 64 <= header.mSize )
|
||||
if( 12 <= header.mSize && header.mSize <= 64 )
|
||||
{
|
||||
setLastError("OS/2 2.x BMP files are not supported");
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -401,7 +401,7 @@ public:
|
|||
child->insert(data);
|
||||
}
|
||||
}
|
||||
else
|
||||
else if (parent)
|
||||
{
|
||||
//it's not in here, give it to the root
|
||||
OCT_ERRS << "Octree insertion failed, starting over from root!" << LL_ENDL;
|
||||
|
|
@ -416,6 +416,13 @@ public:
|
|||
|
||||
node->insert(data);
|
||||
}
|
||||
else
|
||||
{
|
||||
// It's not in here, and we are root.
|
||||
// LLOctreeRoot::insert() should have expanded
|
||||
// root by now, something is wrong
|
||||
OCT_ERRS << "Octree insertion failed! Root expansion failed." << LL_ENDL;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
@ -763,10 +770,15 @@ public:
|
|||
{
|
||||
LLOctreeNode<T>::insert(data);
|
||||
}
|
||||
else
|
||||
else if (node->isInside(data->getPositionGroup()))
|
||||
{
|
||||
node->insert(data);
|
||||
}
|
||||
else
|
||||
{
|
||||
// calling node->insert(data) will return us to root
|
||||
OCT_ERRS << "Failed to insert data at child node" << LL_ENDL;
|
||||
}
|
||||
}
|
||||
else if (this->getChildCount() == 0)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -265,7 +265,7 @@ LLSocket::~LLSocket()
|
|||
void LLSocket::setBlocking(S32 timeout)
|
||||
{
|
||||
// set up the socket options
|
||||
ll_apr_warn_status(apr_socket_timeout_set(mSocket, timeout));
|
||||
ll_apr_warn_status(apr_socket_timeout_set(mSocket, timeout)); // Sets both receive and send timeout SO_RCVTIMEO, SO_SNDTIMEO
|
||||
ll_apr_warn_status(apr_socket_opt_set(mSocket, APR_SO_NONBLOCK, 0));
|
||||
ll_apr_warn_status(apr_socket_opt_set(mSocket, APR_SO_SNDBUF, LL_SEND_BUFFER_SIZE));
|
||||
ll_apr_warn_status(apr_socket_opt_set(mSocket, APR_SO_RCVBUF, LL_RECV_BUFFER_SIZE));
|
||||
|
|
|
|||
|
|
@ -476,7 +476,8 @@ static apr_status_t tcp_blocking_handshake(LLSocket::ptr_t handle, char * dataou
|
|||
rv = apr_socket_send(apr_socket, dataout, &outlen);
|
||||
if (APR_SUCCESS != rv)
|
||||
{
|
||||
LL_WARNS("Proxy") << "Error sending data to proxy control channel, status: " << rv << LL_ENDL;
|
||||
char buf[MAX_STRING];
|
||||
LL_WARNS("Proxy") << "Error sending data to proxy control channel, status: " << rv << " " << apr_strerror(rv, buf, MAX_STRING) << LL_ENDL;
|
||||
ll_apr_warn_status(rv);
|
||||
}
|
||||
else if (expected_len != outlen)
|
||||
|
|
@ -486,13 +487,16 @@ static apr_status_t tcp_blocking_handshake(LLSocket::ptr_t handle, char * dataou
|
|||
rv = -1;
|
||||
}
|
||||
|
||||
ms_sleep(1);
|
||||
|
||||
if (APR_SUCCESS == rv)
|
||||
{
|
||||
expected_len = maxinlen;
|
||||
rv = apr_socket_recv(apr_socket, datain, &maxinlen);
|
||||
if (rv != APR_SUCCESS)
|
||||
{
|
||||
LL_WARNS("Proxy") << "Error receiving data from proxy control channel, status: " << rv << LL_ENDL;
|
||||
char buf[MAX_STRING];
|
||||
LL_WARNS("Proxy") << "Error receiving data from proxy control channel, status: " << rv << " " << apr_strerror(rv, buf, MAX_STRING) << LL_ENDL;
|
||||
ll_apr_warn_status(rv);
|
||||
}
|
||||
else if (expected_len < maxinlen)
|
||||
|
|
|
|||
|
|
@ -157,7 +157,7 @@ void ft_close_cb(FT_Stream stream) {
|
|||
}
|
||||
#endif
|
||||
|
||||
BOOL LLFontFreetype::loadFace(const std::string& filename, F32 point_size, F32 vert_dpi, F32 horz_dpi, S32 components, BOOL is_fallback)
|
||||
BOOL LLFontFreetype::loadFace(const std::string& filename, F32 point_size, F32 vert_dpi, F32 horz_dpi, S32 components, BOOL is_fallback, S32 face_n)
|
||||
{
|
||||
// Don't leak face objects. This is also needed to deal with
|
||||
// changed font file names.
|
||||
|
|
@ -168,40 +168,8 @@ BOOL LLFontFreetype::loadFace(const std::string& filename, F32 point_size, F32 v
|
|||
}
|
||||
|
||||
int error;
|
||||
|
||||
#ifdef LL_WINDOWS
|
||||
pFileStream = new llifstream(filename, std::ios::binary);
|
||||
if (pFileStream->is_open())
|
||||
{
|
||||
std::streampos beg = pFileStream->tellg();
|
||||
pFileStream->seekg(0, std::ios::end);
|
||||
std::streampos end = pFileStream->tellg();
|
||||
std::size_t file_size = end - beg;
|
||||
pFileStream->seekg(0, std::ios::beg);
|
||||
|
||||
pFtStream = new LLFT_Stream();
|
||||
pFtStream->base = 0;
|
||||
pFtStream->pos = 0;
|
||||
pFtStream->size = file_size;
|
||||
pFtStream->descriptor.pointer = pFileStream;
|
||||
pFtStream->read = ft_read_cb;
|
||||
pFtStream->close = ft_close_cb;
|
||||
|
||||
FT_Open_Args args;
|
||||
args.flags = FT_OPEN_STREAM;
|
||||
args.stream = (FT_StreamRec*)pFtStream;
|
||||
|
||||
error = FT_Open_Face(gFTLibrary,
|
||||
&args,
|
||||
0,
|
||||
&mFTFace);
|
||||
}
|
||||
else
|
||||
{
|
||||
delete pFileStream;
|
||||
pFileStream = NULL;
|
||||
return FALSE;
|
||||
}
|
||||
error = ftOpenFace(filename, face_n);
|
||||
#else
|
||||
error = FT_New_Face( gFTLibrary,
|
||||
filename.c_str(),
|
||||
|
|
@ -212,11 +180,7 @@ BOOL LLFontFreetype::loadFace(const std::string& filename, F32 point_size, F32 v
|
|||
if (error)
|
||||
{
|
||||
#ifdef LL_WINDOWS
|
||||
pFileStream->close();
|
||||
delete pFileStream;
|
||||
delete pFtStream;
|
||||
pFileStream = NULL;
|
||||
pFtStream = NULL;
|
||||
clearFontStreams();
|
||||
#endif
|
||||
return FALSE;
|
||||
}
|
||||
|
|
@ -235,11 +199,7 @@ BOOL LLFontFreetype::loadFace(const std::string& filename, F32 point_size, F32 v
|
|||
// Clean up freetype libs.
|
||||
FT_Done_Face(mFTFace);
|
||||
#ifdef LL_WINDOWS
|
||||
pFileStream->close();
|
||||
delete pFileStream;
|
||||
delete pFtStream;
|
||||
pFileStream = NULL;
|
||||
pFtStream = NULL;
|
||||
clearFontStreams();
|
||||
#endif
|
||||
mFTFace = NULL;
|
||||
return FALSE;
|
||||
|
|
@ -285,18 +245,88 @@ BOOL LLFontFreetype::loadFace(const std::string& filename, F32 point_size, F32 v
|
|||
if(mFTFace->style_flags & FT_STYLE_FLAG_BOLD)
|
||||
{
|
||||
mStyle |= LLFontGL::BOLD;
|
||||
mStyle &= ~LLFontGL::NORMAL;
|
||||
}
|
||||
|
||||
if(mFTFace->style_flags & FT_STYLE_FLAG_ITALIC)
|
||||
{
|
||||
mStyle |= LLFontGL::ITALIC;
|
||||
mStyle &= ~LLFontGL::NORMAL;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
S32 LLFontFreetype::getNumFaces(const std::string& filename)
|
||||
{
|
||||
if (mFTFace)
|
||||
{
|
||||
FT_Done_Face(mFTFace);
|
||||
mFTFace = NULL;
|
||||
}
|
||||
|
||||
S32 num_faces = 1;
|
||||
|
||||
#ifdef LL_WINDOWS
|
||||
int error = ftOpenFace(filename, 0);
|
||||
|
||||
if (error)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
num_faces = mFTFace->num_faces;
|
||||
}
|
||||
|
||||
FT_Done_Face(mFTFace);
|
||||
clearFontStreams();
|
||||
mFTFace = NULL;
|
||||
#endif
|
||||
|
||||
return num_faces;
|
||||
}
|
||||
|
||||
#ifdef LL_WINDOWS
|
||||
S32 LLFontFreetype::ftOpenFace(const std::string& filename, S32 face_n)
|
||||
{
|
||||
S32 error = -1;
|
||||
pFileStream = new llifstream(filename, std::ios::binary);
|
||||
if (pFileStream->is_open())
|
||||
{
|
||||
std::streampos beg = pFileStream->tellg();
|
||||
pFileStream->seekg(0, std::ios::end);
|
||||
std::streampos end = pFileStream->tellg();
|
||||
std::size_t file_size = end - beg;
|
||||
pFileStream->seekg(0, std::ios::beg);
|
||||
|
||||
pFtStream = new LLFT_Stream();
|
||||
pFtStream->base = 0;
|
||||
pFtStream->pos = 0;
|
||||
pFtStream->size = file_size;
|
||||
pFtStream->descriptor.pointer = pFileStream;
|
||||
pFtStream->read = ft_read_cb;
|
||||
pFtStream->close = ft_close_cb;
|
||||
|
||||
FT_Open_Args args;
|
||||
args.flags = FT_OPEN_STREAM;
|
||||
args.stream = (FT_StreamRec*)pFtStream;
|
||||
error = FT_Open_Face(gFTLibrary, &args, face_n, &mFTFace);
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
void LLFontFreetype::clearFontStreams()
|
||||
{
|
||||
if (pFileStream)
|
||||
{
|
||||
pFileStream->close();
|
||||
}
|
||||
delete pFileStream;
|
||||
delete pFtStream;
|
||||
pFileStream = NULL;
|
||||
pFtStream = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
void LLFontFreetype::setFallbackFonts(const font_vector_t &font)
|
||||
{
|
||||
mFallbackFonts = font;
|
||||
|
|
|
|||
|
|
@ -84,7 +84,14 @@ public:
|
|||
|
||||
// is_fallback should be true for fallback fonts that aren't used
|
||||
// to render directly (Unicode backup, primarily)
|
||||
BOOL loadFace(const std::string& filename, F32 point_size, F32 vert_dpi, F32 horz_dpi, S32 components, BOOL is_fallback);
|
||||
BOOL loadFace(const std::string& filename, F32 point_size, F32 vert_dpi, F32 horz_dpi, S32 components, BOOL is_fallback, S32 face_n = 0);
|
||||
|
||||
S32 getNumFaces(const std::string& filename);
|
||||
|
||||
#ifdef LL_WINDOWS
|
||||
S32 ftOpenFace(const std::string& filename, S32 face_n);
|
||||
void clearFontStreams();
|
||||
#endif
|
||||
|
||||
typedef std::vector<LLPointer<LLFontFreetype> > font_vector_t;
|
||||
|
||||
|
|
|
|||
|
|
@ -89,14 +89,24 @@ void LLFontGL::destroyGL()
|
|||
mFontFreetype->destroyGL();
|
||||
}
|
||||
|
||||
BOOL LLFontGL::loadFace(const std::string& filename, F32 point_size, F32 vert_dpi, F32 horz_dpi, S32 components, BOOL is_fallback)
|
||||
BOOL LLFontGL::loadFace(const std::string& filename, F32 point_size, F32 vert_dpi, F32 horz_dpi, S32 components, BOOL is_fallback, S32 face_n)
|
||||
{
|
||||
if(mFontFreetype == reinterpret_cast<LLFontFreetype*>(NULL))
|
||||
{
|
||||
mFontFreetype = new LLFontFreetype;
|
||||
}
|
||||
|
||||
return mFontFreetype->loadFace(filename, point_size, vert_dpi, horz_dpi, components, is_fallback);
|
||||
return mFontFreetype->loadFace(filename, point_size, vert_dpi, horz_dpi, components, is_fallback, face_n);
|
||||
}
|
||||
|
||||
S32 LLFontGL::getNumFaces(const std::string& filename)
|
||||
{
|
||||
if (mFontFreetype == reinterpret_cast<LLFontFreetype*>(NULL))
|
||||
{
|
||||
mFontFreetype = new LLFontFreetype;
|
||||
}
|
||||
|
||||
return mFontFreetype->getNumFaces(filename);
|
||||
}
|
||||
|
||||
static LLTrace::BlockTimerStatHandle FTM_RENDER_FONTS("Fonts");
|
||||
|
|
@ -860,10 +870,6 @@ void LLFontGL::destroyAllGL()
|
|||
U8 LLFontGL::getStyleFromString(const std::string &style)
|
||||
{
|
||||
S32 ret = 0;
|
||||
if (style.find("NORMAL") != style.npos)
|
||||
{
|
||||
ret |= NORMAL;
|
||||
}
|
||||
if (style.find("BOLD") != style.npos)
|
||||
{
|
||||
ret |= BOLD;
|
||||
|
|
@ -883,7 +889,7 @@ U8 LLFontGL::getStyleFromString(const std::string &style)
|
|||
std::string LLFontGL::getStringFromStyle(U8 style)
|
||||
{
|
||||
std::string style_string;
|
||||
if (style & NORMAL)
|
||||
if (style == NORMAL)
|
||||
{
|
||||
style_string += "|NORMAL";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -87,7 +87,9 @@ public:
|
|||
|
||||
void destroyGL();
|
||||
|
||||
BOOL loadFace(const std::string& filename, F32 point_size, const F32 vert_dpi, const F32 horz_dpi, const S32 components, BOOL is_fallback);
|
||||
BOOL loadFace(const std::string& filename, F32 point_size, const F32 vert_dpi, const F32 horz_dpi, const S32 components, BOOL is_fallback, S32 face_n = 0);
|
||||
|
||||
S32 getNumFaces(const std::string& filename);
|
||||
|
||||
S32 render(const LLWString &text, S32 begin_offset,
|
||||
const LLRect& rect,
|
||||
|
|
|
|||
|
|
@ -44,6 +44,8 @@ using std::map;
|
|||
bool font_desc_init_from_xml(LLXMLNodePtr node, LLFontDescriptor& desc);
|
||||
bool init_from_xml(LLFontRegistry* registry, LLXMLNodePtr node);
|
||||
|
||||
const std::string MACOSX_FONT_PATH_LIBRARY = "/Library/Fonts/";
|
||||
|
||||
LLFontDescriptor::LLFontDescriptor():
|
||||
mStyle(0)
|
||||
{
|
||||
|
|
@ -60,6 +62,16 @@ LLFontDescriptor::LLFontDescriptor(const std::string& name,
|
|||
{
|
||||
}
|
||||
|
||||
LLFontDescriptor::LLFontDescriptor(const std::string& name,
|
||||
const std::string& size,
|
||||
const U8 style,
|
||||
const string_vec_t& file_names,
|
||||
const string_vec_t& ft_collection_listections) :
|
||||
LLFontDescriptor(name, size, style, file_names)
|
||||
{
|
||||
mFontCollectionsList = ft_collection_listections;
|
||||
}
|
||||
|
||||
LLFontDescriptor::LLFontDescriptor(const std::string& name,
|
||||
const std::string& size,
|
||||
const U8 style):
|
||||
|
|
@ -162,7 +174,7 @@ LLFontDescriptor LLFontDescriptor::normalize() const
|
|||
if (removeSubString(new_name,"Italic"))
|
||||
new_style |= LLFontGL::ITALIC;
|
||||
|
||||
return LLFontDescriptor(new_name,new_size,new_style,getFileNames());
|
||||
return LLFontDescriptor(new_name,new_size,new_style,getFileNames(),getFontCollectionsList());
|
||||
}
|
||||
|
||||
LLFontRegistry::LLFontRegistry(bool create_gl_textures)
|
||||
|
|
@ -213,6 +225,7 @@ bool LLFontRegistry::parseFontInfo(const std::string& xml_filename)
|
|||
success = success || init_succ;
|
||||
}
|
||||
}
|
||||
|
||||
//if (success)
|
||||
// dump();
|
||||
|
||||
|
|
@ -260,6 +273,16 @@ bool font_desc_init_from_xml(LLXMLNodePtr node, LLFontDescriptor& desc)
|
|||
{
|
||||
std::string font_file_name = child->getTextContents();
|
||||
desc.getFileNames().push_back(font_file_name);
|
||||
|
||||
if (child->hasAttribute("load_collection"))
|
||||
{
|
||||
BOOL col = FALSE;
|
||||
child->getAttributeBOOL("load_collection", col);
|
||||
if (col)
|
||||
{
|
||||
desc.getFontCollectionsList().push_back(font_file_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (child->hasName("os"))
|
||||
{
|
||||
|
|
@ -306,8 +329,15 @@ bool init_from_xml(LLFontRegistry* registry, LLXMLNodePtr node)
|
|||
match_file_names.insert(match_file_names.begin(),
|
||||
desc.getFileNames().begin(),
|
||||
desc.getFileNames().end());
|
||||
|
||||
string_vec_t collections_list = match_desc->getFontCollectionsList();
|
||||
collections_list.insert(collections_list.begin(),
|
||||
desc.getFontCollectionsList().begin(),
|
||||
desc.getFontCollectionsList().end());
|
||||
|
||||
LLFontDescriptor new_desc = *match_desc;
|
||||
new_desc.getFileNames() = match_file_names;
|
||||
new_desc.getFontCollectionsList() = collections_list;
|
||||
registry->mFontMap.erase(*match_desc);
|
||||
registry->mFontMap[new_desc] = NULL;
|
||||
}
|
||||
|
|
@ -393,6 +423,7 @@ LLFontGL *LLFontRegistry::createFont(const LLFontDescriptor& desc)
|
|||
// Build list of font names to look for.
|
||||
// Files specified for this font come first, followed by those from the default descriptor.
|
||||
string_vec_t file_names = match_desc->getFileNames();
|
||||
string_vec_t ft_collection_list = match_desc->getFontCollectionsList();
|
||||
string_vec_t default_file_names;
|
||||
LLFontDescriptor default_desc("default",s_template_string,0);
|
||||
const LLFontDescriptor *match_default_desc = getMatchingFontDesc(default_desc);
|
||||
|
|
@ -401,6 +432,9 @@ LLFontGL *LLFontRegistry::createFont(const LLFontDescriptor& desc)
|
|||
file_names.insert(file_names.end(),
|
||||
match_default_desc->getFileNames().begin(),
|
||||
match_default_desc->getFileNames().end());
|
||||
ft_collection_list.insert(ft_collection_list.end(),
|
||||
match_default_desc->getFontCollectionsList().begin(),
|
||||
match_default_desc->getFontCollectionsList().end());
|
||||
}
|
||||
|
||||
// Add ultimate fallback list - generated dynamically on linux,
|
||||
|
|
@ -433,39 +467,62 @@ LLFontGL *LLFontRegistry::createFont(const LLFontDescriptor& desc)
|
|||
file_name_it != file_names.end();
|
||||
++file_name_it)
|
||||
{
|
||||
LLFontGL *fontp = new LLFontGL;
|
||||
std::string font_path = local_path + *file_name_it;
|
||||
LLFontGL *fontp = NULL;
|
||||
string_vec_t font_paths;
|
||||
font_paths.push_back(local_path + *file_name_it);
|
||||
font_paths.push_back(sys_path + *file_name_it);
|
||||
#if LL_DARWIN
|
||||
font_paths.push_back(MACOSX_FONT_PATH_LIBRARY + *file_name_it);
|
||||
#endif
|
||||
|
||||
bool is_ft_collection = (std::find(ft_collection_list.begin(), ft_collection_list.end(), *file_name_it) != ft_collection_list.end());
|
||||
// *HACK: Fallback fonts don't render, so we can use that to suppress
|
||||
// creation of OpenGL textures for test apps. JC
|
||||
BOOL is_fallback = !is_first_found || !mCreateGLTextures;
|
||||
F32 extra_scale = (is_fallback)?fallback_scale:1.0;
|
||||
if (!fontp->loadFace(font_path, extra_scale * point_size,
|
||||
LLFontGL::sVertDPI, LLFontGL::sHorizDPI, 2, is_fallback))
|
||||
F32 point_size_scale = extra_scale * point_size;
|
||||
bool is_font_loaded = false;
|
||||
for(string_vec_t::iterator font_paths_it = font_paths.begin();
|
||||
font_paths_it != font_paths.end();
|
||||
++font_paths_it)
|
||||
{
|
||||
font_path = sys_path + *file_name_it;
|
||||
|
||||
if (!fontp->loadFace(font_path, extra_scale * point_size,
|
||||
LLFontGL::sVertDPI, LLFontGL::sHorizDPI, 2, is_fallback))
|
||||
fontp = new LLFontGL;
|
||||
S32 num_faces = is_ft_collection ? fontp->getNumFaces(*font_paths_it) : 1;
|
||||
for (S32 i = 0; i < num_faces; i++)
|
||||
{
|
||||
LL_INFOS_ONCE("LLFontRegistry") << "Couldn't load font " << *file_name_it << " from path " << local_path << LL_ENDL;
|
||||
delete fontp;
|
||||
fontp = NULL;
|
||||
if (fontp == NULL)
|
||||
{
|
||||
fontp = new LLFontGL;
|
||||
}
|
||||
if (fontp->loadFace(*font_paths_it, point_size_scale,
|
||||
LLFontGL::sVertDPI, LLFontGL::sHorizDPI, 2, is_fallback, i))
|
||||
{
|
||||
is_font_loaded = true;
|
||||
if (is_first_found)
|
||||
{
|
||||
result = fontp;
|
||||
is_first_found = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
fontlist.push_back(fontp->mFontFreetype);
|
||||
delete fontp;
|
||||
fontp = NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
delete fontp;
|
||||
fontp = NULL;
|
||||
}
|
||||
}
|
||||
if (is_font_loaded) break;
|
||||
}
|
||||
|
||||
if(fontp)
|
||||
if(!is_font_loaded)
|
||||
{
|
||||
if (is_first_found)
|
||||
{
|
||||
result = fontp;
|
||||
is_first_found = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
fontlist.push_back(fontp->mFontFreetype);
|
||||
delete fontp;
|
||||
fontp = NULL;
|
||||
}
|
||||
LL_INFOS_ONCE("LLFontRegistry") << "Couldn't load font " << *file_name_it << LL_ENDL;
|
||||
delete fontp;
|
||||
fontp = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ public:
|
|||
LLFontDescriptor();
|
||||
LLFontDescriptor(const std::string& name, const std::string& size, const U8 style);
|
||||
LLFontDescriptor(const std::string& name, const std::string& size, const U8 style, const string_vec_t& file_names);
|
||||
LLFontDescriptor(const std::string& name, const std::string& size, const U8 style, const string_vec_t& file_names, const string_vec_t& font_collections);
|
||||
LLFontDescriptor normalize() const;
|
||||
|
||||
bool operator<(const LLFontDescriptor& b) const;
|
||||
|
|
@ -52,6 +53,8 @@ public:
|
|||
void setSize(const std::string& size) { mSize = size; }
|
||||
const std::vector<std::string>& getFileNames() const { return mFileNames; }
|
||||
std::vector<std::string>& getFileNames() { return mFileNames; }
|
||||
const std::vector<std::string>& getFontCollectionsList() const { return mFontCollectionsList; }
|
||||
std::vector<std::string>& getFontCollectionsList() { return mFontCollectionsList; }
|
||||
const U8 getStyle() const { return mStyle; }
|
||||
void setStyle(U8 style) { mStyle = style; }
|
||||
|
||||
|
|
@ -59,6 +62,7 @@ private:
|
|||
std::string mName;
|
||||
std::string mSize;
|
||||
string_vec_t mFileNames;
|
||||
string_vec_t mFontCollectionsList;
|
||||
U8 mStyle;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -122,6 +122,7 @@ void LLTextBox::setEnabled(BOOL enabled)
|
|||
LLTextBase::setReadOnly(read_only);
|
||||
updateSegments();
|
||||
}
|
||||
LLTextBase::setEnabled(enabled);
|
||||
}
|
||||
|
||||
void LLTextBox::setText(const LLStringExplicit& text , const LLStyle::Params& input_params )
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ bool LLTransUtil::parseStrings(const std::string& xml_filename, const std::set<s
|
|||
bool success = LLUICtrlFactory::getLayeredXMLNode(xml_filename, root, LLDir::ALL_SKINS);
|
||||
if (!success)
|
||||
{
|
||||
LL_ERRS() << "Couldn't load string table " << xml_filename << LL_ENDL;
|
||||
LL_ERRS() << "Couldn't load string table " << xml_filename << ". Please reinstall viewer from https://secondlife.com/support/downloads/ and contact https://support.secondlife.com if issue persists after reinstall." << LL_ENDL;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -110,9 +110,9 @@ void glSwapBuffers(void* context);
|
|||
CGLContextObj getCGLContextObj(GLViewRef view);
|
||||
unsigned long getVramSize(GLViewRef view);
|
||||
float getDeviceUnitSize(GLViewRef view);
|
||||
const CGPoint getContentViewBoundsPosition(NSWindowRef window);
|
||||
const CGSize getContentViewBoundsSize(NSWindowRef window);
|
||||
const CGSize getDeviceContentViewSize(NSWindowRef window, GLViewRef view);
|
||||
CGPoint getContentViewBoundsPosition(NSWindowRef window);
|
||||
CGSize getContentViewBoundsSize(NSWindowRef window);
|
||||
CGSize getDeviceContentViewSize(NSWindowRef window, GLViewRef view);
|
||||
void getWindowSize(NSWindowRef window, float* size);
|
||||
void setWindowSize(NSWindowRef window, int width, int height);
|
||||
void getCursorPos(NSWindowRef window, float* pos);
|
||||
|
|
|
|||
|
|
@ -258,17 +258,17 @@ float getDeviceUnitSize(GLViewRef view)
|
|||
return [(LLOpenGLView*)view convertSizeToBacking:NSMakeSize(1, 1)].width;
|
||||
}
|
||||
|
||||
const CGPoint getContentViewBoundsPosition(NSWindowRef window)
|
||||
CGPoint getContentViewBoundsPosition(NSWindowRef window)
|
||||
{
|
||||
return [[(LLNSWindow*)window contentView] bounds].origin;
|
||||
}
|
||||
|
||||
const CGSize getContentViewBoundsSize(NSWindowRef window)
|
||||
CGSize getContentViewBoundsSize(NSWindowRef window)
|
||||
{
|
||||
return [[(LLNSWindow*)window contentView] bounds].size;
|
||||
}
|
||||
|
||||
const CGSize getDeviceContentViewSize(NSWindowRef window, GLViewRef view)
|
||||
CGSize getDeviceContentViewSize(NSWindowRef window, GLViewRef view)
|
||||
{
|
||||
return [(NSOpenGLView*)view convertRectToBacking:[[(LLNSWindow*)window contentView] bounds]].size;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -382,7 +382,10 @@ void callWindowFocus()
|
|||
|
||||
void callWindowUnfocus()
|
||||
{
|
||||
gWindowImplementation->getCallbacks()->handleFocusLost(gWindowImplementation);
|
||||
if ( gWindowImplementation && gWindowImplementation->getCallbacks() )
|
||||
{
|
||||
gWindowImplementation->getCallbacks()->handleFocusLost(gWindowImplementation);
|
||||
}
|
||||
}
|
||||
|
||||
void callWindowHide()
|
||||
|
|
|
|||
|
|
@ -741,6 +741,17 @@ void LLWindowWin32::restore()
|
|||
SetFocus(mWindowHandle);
|
||||
}
|
||||
|
||||
bool destroy_window_handler(HWND &hWnd)
|
||||
{
|
||||
__try
|
||||
{
|
||||
return DestroyWindow(hWnd);
|
||||
}
|
||||
__except (EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// close() destroys all OS-specific code associated with a window.
|
||||
// Usually called from LLWindowManager::destroyWindow()
|
||||
|
|
@ -814,7 +825,7 @@ void LLWindowWin32::close()
|
|||
ShowWindow(mWindowHandle, SW_HIDE);
|
||||
|
||||
// This causes WM_DESTROY to be sent *immediately*
|
||||
if (!DestroyWindow(mWindowHandle))
|
||||
if (!destroy_window_handler(mWindowHandle))
|
||||
{
|
||||
OSMessageBox(mCallbacks->translateString("MBDestroyWinFailed"),
|
||||
mCallbacks->translateString("MBShutdownErr"),
|
||||
|
|
|
|||
|
|
@ -531,7 +531,12 @@ void MediaPluginCEF::receiveMessage(const char* message_string)
|
|||
}
|
||||
|
||||
// now we can set page zoom factor
|
||||
mCEFLib->setPageZoom(message_in.getValueReal("factor"));
|
||||
F32 factor = (F32)message_in.getValueReal("factor");
|
||||
#if LL_DARWIN
|
||||
//temporary fix for SL-10473: issue with displaying checkboxes on Mojave
|
||||
factor*=1.001;
|
||||
#endif
|
||||
mCEFLib->setPageZoom(factor);
|
||||
|
||||
// Plugin gets to decide the texture parameters to use.
|
||||
mDepth = 4;
|
||||
|
|
@ -736,6 +741,10 @@ void MediaPluginCEF::receiveMessage(const char* message_string)
|
|||
if (message_name == "set_page_zoom_factor")
|
||||
{
|
||||
F32 factor = (F32)message_in.getValueReal("factor");
|
||||
#if LL_DARWIN
|
||||
//temporary fix for SL-10473: issue with displaying checkboxes on Mojave
|
||||
factor*=1.001;
|
||||
#endif
|
||||
mCEFLib->setPageZoom(factor);
|
||||
}
|
||||
if (message_name == "browse_stop")
|
||||
|
|
@ -813,7 +822,8 @@ void MediaPluginCEF::keyEvent(dullahan::EKeyEvent key_event, LLSD native_key_dat
|
|||
// adding new code below in unicodeInput means we don't send ascii chars
|
||||
// here too or we get double key presses on a mac.
|
||||
bool esc_key = (event_umodchars == 27);
|
||||
if (esc_key || ((unsigned char)event_chars < 0x10 || (unsigned char)event_chars >= 0x7f ))
|
||||
bool tab_key_up = (event_umodchars == 9) && (key_event == dullahan::EKeyEvent::KE_KEY_UP);
|
||||
if ((esc_key || ((unsigned char)event_chars < 0x10 || (unsigned char)event_chars >= 0x7f )) && !tab_key_up)
|
||||
{
|
||||
mCEFLib->nativeKeyboardEventOSX(key_event, event_modifiers,
|
||||
event_keycode, event_chars,
|
||||
|
|
|
|||
|
|
@ -201,7 +201,6 @@ set(viewer_SOURCE_FILES
|
|||
llexperiencelog.cpp
|
||||
llexternaleditor.cpp
|
||||
llface.cpp
|
||||
llfacebookconnect.cpp
|
||||
llfasttimerview.cpp
|
||||
llfavoritesbar.cpp
|
||||
llfeaturemanager.cpp
|
||||
|
|
@ -245,7 +244,6 @@ set(viewer_SOURCE_FILES
|
|||
llfloaterexperiencepicker.cpp
|
||||
llfloaterexperienceprofile.cpp
|
||||
llfloaterexperiences.cpp
|
||||
llfloaterfacebook.cpp
|
||||
llfloaterflickr.cpp
|
||||
llfloaterfonttest.cpp
|
||||
llfloatergesture.cpp
|
||||
|
|
@ -828,7 +826,6 @@ set(viewer_HEADER_FILES
|
|||
llexperiencelog.h
|
||||
llexternaleditor.h
|
||||
llface.h
|
||||
llfacebookconnect.h
|
||||
llfasttimerview.h
|
||||
llfavoritesbar.h
|
||||
llfeaturemanager.h
|
||||
|
|
@ -872,7 +869,6 @@ set(viewer_HEADER_FILES
|
|||
llfloaterexperiencepicker.h
|
||||
llfloaterexperienceprofile.h
|
||||
llfloaterexperiences.h
|
||||
llfloaterfacebook.h
|
||||
llfloaterflickr.h
|
||||
llfloaterfonttest.h
|
||||
llfloatergesture.h
|
||||
|
|
@ -1885,12 +1881,12 @@ if (WINDOWS)
|
|||
|
||||
# sets the 'working directory' for debugging from visual studio.
|
||||
# Condition for version can be moved to requirements once build agents will be updated (see TOOL-3865)
|
||||
if ((NOT UNATTENDED) AND (${CMAKE_VERSION} VERSION_GREATER "3.7.2"))
|
||||
if (NOT UNATTENDED)
|
||||
set_property(
|
||||
TARGET ${VIEWER_BINARY_NAME}
|
||||
PROPERTY VS_DEBUGGER_WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||
)
|
||||
endif ((NOT UNATTENDED) AND (${CMAKE_VERSION} VERSION_GREATER "3.7.2"))
|
||||
endif (NOT UNATTENDED)
|
||||
|
||||
if (PACKAGE)
|
||||
add_custom_command(
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
6.3.1
|
||||
6.3.2
|
||||
|
|
|
|||
|
|
@ -228,16 +228,6 @@
|
|||
is_running_function="Floater.IsOpen"
|
||||
is_running_parameters="snapshot"
|
||||
/>
|
||||
<command name="facebook"
|
||||
available_in_toybox="true"
|
||||
icon="Command_Facebook_Icon"
|
||||
label_ref="Command_Facebook_Label"
|
||||
tooltip_ref="Command_Facebook_Tooltip"
|
||||
execute_function="Floater.ToggleOrBringToFront"
|
||||
execute_parameters="facebook"
|
||||
is_running_function="Floater.IsOpen"
|
||||
is_running_parameters="facebook"
|
||||
/>
|
||||
<command name="flickr"
|
||||
available_in_toybox="true"
|
||||
icon="Command_Flickr_Icon"
|
||||
|
|
|
|||
|
|
@ -414,5 +414,16 @@
|
|||
<key>Value</key>
|
||||
<string>Snapshot</string>
|
||||
</map>
|
||||
<key>ExperienceSearchMaturity</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Setting for the user's preferred Max Content rating for Experiences search (Default rating is General)</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>U32</string>
|
||||
<key>Value</key>
|
||||
<integer>2</integer>
|
||||
</map>
|
||||
</map>
|
||||
</llsd>
|
||||
|
|
|
|||
|
|
@ -21,7 +21,6 @@
|
|||
<command name="voice"/>
|
||||
<command name="minimap"/>
|
||||
<command name="snapshot"/>
|
||||
<command name="facebook"/>
|
||||
</left_toolbar>
|
||||
<right_toolbar
|
||||
button_display_mode="icons_only">
|
||||
|
|
|
|||
|
|
@ -346,6 +346,11 @@ Call CheckWillUninstallV2 # Check if Second Life is already installed
|
|||
StrCmp $DO_UNINSTALL_V2 "" PRESERVE_DONE
|
||||
PRESERVE_DONE:
|
||||
|
||||
# Viewer had "SLLauncher" for some time and we was seting "IsHostApp" for viewer, make sure to clean it up
|
||||
DeleteRegValue HKEY_CLASSES_ROOT "Applications\$VIEWER_EXE" "IsHostApp"
|
||||
DeleteRegValue HKEY_CLASSES_ROOT "Applications\$VIEWER_EXE" "NoStartPage"
|
||||
ClearErrors
|
||||
|
||||
Call RemoveProgFilesOnInst # Remove existing files to prevent certain errors when running the new version of the viewer
|
||||
|
||||
# This placeholder is replaced by the complete list of all the files in the installer, by viewer_manifest.py
|
||||
|
|
@ -417,7 +422,7 @@ WriteRegStr HKEY_CLASSES_ROOT "x-grid-location-info\DefaultIcon" "" '"$INSTDIR\$
|
|||
# URL param must be last item passed to viewer, it ignores subsequent params to avoid parameter injection attacks.
|
||||
WriteRegExpandStr HKEY_CLASSES_ROOT "x-grid-location-info\shell\open\command" "" '"$INSTDIR\$VIEWER_EXE" -url "%1"'
|
||||
|
||||
WriteRegStr HKEY_CLASSES_ROOT "Applications\$VIEWER_EXE" "IsHostApp" ""
|
||||
WriteRegStr HKEY_CLASSES_ROOT "Applications\$INSTEXE" "IsHostApp" ""
|
||||
##WriteRegStr HKEY_CLASSES_ROOT "Applications\${VIEWER_EXE}" "NoStartPage" ""
|
||||
|
||||
# Write out uninstaller
|
||||
|
|
@ -464,7 +469,7 @@ DeleteRegKey SHELL_CONTEXT "${INSTNAME_KEY}"
|
|||
DeleteRegKey SHELL_CONTEXT "${MSCURRVER_KEY}\Uninstall\$INSTNAME"
|
||||
# BUG-2707 Remove entry that disabled SEHOP
|
||||
DeleteRegKey SHELL_CONTEXT "${MSNTCURRVER_KEY}\Image File Execution Options\$VIEWER_EXE"
|
||||
##DeleteRegKey HKEY_CLASSES_ROOT "Applications\$INSTEXE"
|
||||
DeleteRegKey HKEY_CLASSES_ROOT "Applications\$INSTEXE"
|
||||
DeleteRegKey HKEY_CLASSES_ROOT "Applications\${VIEWER_EXE}"
|
||||
|
||||
# Clean up shortcuts
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -743,7 +743,7 @@ BOOL LLAgent::getFlying() const
|
|||
//-----------------------------------------------------------------------------
|
||||
// setFlying()
|
||||
//-----------------------------------------------------------------------------
|
||||
void LLAgent::setFlying(BOOL fly)
|
||||
void LLAgent::setFlying(BOOL fly, BOOL fail_sound)
|
||||
{
|
||||
if (isAgentAvatarValid())
|
||||
{
|
||||
|
|
@ -772,7 +772,10 @@ void LLAgent::setFlying(BOOL fly)
|
|||
// parcel doesn't let you start fly
|
||||
// gods can always fly
|
||||
// and it's OK if you're already flying
|
||||
make_ui_sound("UISndBadKeystroke");
|
||||
if (fail_sound)
|
||||
{
|
||||
make_ui_sound("UISndBadKeystroke");
|
||||
}
|
||||
return;
|
||||
}
|
||||
if( !was_flying )
|
||||
|
|
|
|||
|
|
@ -337,7 +337,7 @@ private:
|
|||
//--------------------------------------------------------------------
|
||||
public:
|
||||
BOOL getFlying() const;
|
||||
void setFlying(BOOL fly);
|
||||
void setFlying(BOOL fly, BOOL fail_sound = FALSE);
|
||||
static void toggleFlying();
|
||||
static bool enableFlying();
|
||||
BOOL canFly(); // Does this parcel allow you to fly?
|
||||
|
|
|
|||
|
|
@ -2419,9 +2419,9 @@ bool LLAppViewer::initConfiguration()
|
|||
bool set_defaults = true;
|
||||
if(!loadSettingsFromDirectory("Default", set_defaults))
|
||||
{
|
||||
std::ostringstream msg;
|
||||
msg << "Unable to load default settings file. The installation may be corrupted.";
|
||||
OSMessageBox(msg.str(),LLStringUtil::null,OSMB_OK);
|
||||
OSMessageBox(
|
||||
"Unable to load default settings file. The installation may be corrupted.",
|
||||
LLStringUtil::null,OSMB_OK);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -2542,7 +2542,7 @@ bool LLAppViewer::initConfiguration()
|
|||
if(gSavedSettings.getBOOL("DisableCrashLogger"))
|
||||
{
|
||||
LL_WARNS() << "Crashes will be handled by system, stack trace logs and crash logger are both disabled" << LL_ENDL;
|
||||
LLAppViewer::instance()->disableCrashlogger();
|
||||
disableCrashlogger();
|
||||
}
|
||||
|
||||
// Handle initialization from settings.
|
||||
|
|
@ -2559,7 +2559,7 @@ bool LLAppViewer::initConfiguration()
|
|||
LL_INFOS() << msg.str() << LL_ENDL;
|
||||
|
||||
OSMessageBox(
|
||||
msg.str().c_str(),
|
||||
msg.str(),
|
||||
LLStringUtil::null,
|
||||
OSMB_OK);
|
||||
|
||||
|
|
@ -2669,7 +2669,34 @@ bool LLAppViewer::initConfiguration()
|
|||
ll_init_fail_log(gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "test_failures.log"));
|
||||
}
|
||||
|
||||
const LLControlVariable* skinfolder = gSavedSettings.getControl("SkinCurrent");
|
||||
if(skinfolder && LLStringUtil::null != skinfolder->getValue().asString())
|
||||
{
|
||||
// Examining "Language" may not suffice -- see LLUI::getLanguage()
|
||||
// logic. Unfortunately LLUI::getLanguage() doesn't yet do us much
|
||||
// good because we haven't yet called LLUI::initClass().
|
||||
gDirUtilp->setSkinFolder(skinfolder->getValue().asString(),
|
||||
gSavedSettings.getString("Language"));
|
||||
}
|
||||
|
||||
if (gSavedSettings.getBOOL("SpellCheck"))
|
||||
{
|
||||
std::list<std::string> dict_list;
|
||||
std::string dict_setting = gSavedSettings.getString("SpellCheckDictionary");
|
||||
boost::split(dict_list, dict_setting, boost::is_any_of(std::string(",")));
|
||||
if (!dict_list.empty())
|
||||
{
|
||||
LLSpellChecker::setUseSpellCheck(dict_list.front());
|
||||
dict_list.pop_front();
|
||||
LLSpellChecker::instance().setSecondaryDictionaries(dict_list);
|
||||
}
|
||||
}
|
||||
|
||||
// Handle slurl use. NOTE: Don't let SL-55321 reappear.
|
||||
// This initial-SLURL logic, up through the call to
|
||||
// sendURLToOtherInstance(), must precede LLSplashScreen::show() --
|
||||
// because if sendURLToOtherInstance() succeeds, we take a fast exit,
|
||||
// SKIPPING the splash screen and everything else.
|
||||
|
||||
// *FIX: This init code should be made more robust to prevent
|
||||
// the issue SL-55321 from returning. One thought is to allow
|
||||
|
|
@ -2714,6 +2741,27 @@ bool LLAppViewer::initConfiguration()
|
|||
}
|
||||
}
|
||||
|
||||
// NextLoginLocation is set as a side effect of LLStartUp::setStartSLURL()
|
||||
std::string nextLoginLocation = gSavedSettings.getString( "NextLoginLocation" );
|
||||
if ( !nextLoginLocation.empty() )
|
||||
{
|
||||
LL_DEBUGS("AppInit")<<"set start from NextLoginLocation: "<<nextLoginLocation<<LL_ENDL;
|
||||
LLStartUp::setStartSLURL(LLSLURL(nextLoginLocation));
|
||||
}
|
||||
else if ( ( clp.hasOption("login") || clp.hasOption("autologin"))
|
||||
&& gSavedSettings.getString("CmdLineLoginLocation").empty())
|
||||
{
|
||||
// If automatic login from command line with --login switch
|
||||
// init StartSLURL location.
|
||||
std::string start_slurl_setting = gSavedSettings.getString("LoginLocation");
|
||||
LL_DEBUGS("AppInit") << "start slurl setting '" << start_slurl_setting << "'" << LL_ENDL;
|
||||
LLStartUp::setStartSLURL(LLSLURL(start_slurl_setting));
|
||||
}
|
||||
else
|
||||
{
|
||||
// the login location will be set by the login panel (see LLPanelLogin)
|
||||
}
|
||||
|
||||
//RN: if we received a URL, hand it off to the existing instance.
|
||||
// don't call anotherInstanceRunning() when doing URL handoff, as
|
||||
// it relies on checking a marker file which will not work when running
|
||||
|
|
@ -2729,30 +2777,6 @@ bool LLAppViewer::initConfiguration()
|
|||
}
|
||||
}
|
||||
|
||||
const LLControlVariable* skinfolder = gSavedSettings.getControl("SkinCurrent");
|
||||
if(skinfolder && LLStringUtil::null != skinfolder->getValue().asString())
|
||||
{
|
||||
// Examining "Language" may not suffice -- see LLUI::getLanguage()
|
||||
// logic. Unfortunately LLUI::getLanguage() doesn't yet do us much
|
||||
// good because we haven't yet called LLUI::initClass().
|
||||
gDirUtilp->setSkinFolder(skinfolder->getValue().asString(),
|
||||
gSavedSettings.getString("Language"));
|
||||
}
|
||||
|
||||
if (gSavedSettings.getBOOL("SpellCheck"))
|
||||
{
|
||||
std::list<std::string> dict_list;
|
||||
std::string dict_setting = gSavedSettings.getString("SpellCheckDictionary");
|
||||
boost::split(dict_list, dict_setting, boost::is_any_of(std::string(",")));
|
||||
if (!dict_list.empty())
|
||||
{
|
||||
LLSpellChecker::setUseSpellCheck(dict_list.front());
|
||||
dict_list.pop_front();
|
||||
LLSpellChecker::instance().setSecondaryDictionaries(dict_list);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Display splash screen. Must be after above check for previous
|
||||
// crash as this dialog is always frontmost.
|
||||
std::string splash_msg;
|
||||
|
|
@ -2784,30 +2808,15 @@ bool LLAppViewer::initConfiguration()
|
|||
}
|
||||
LLStringUtil::truncate(gWindowTitle, 255);
|
||||
|
||||
//RN: if we received a URL, hand it off to the existing instance.
|
||||
// don't call anotherInstanceRunning() when doing URL handoff, as
|
||||
// it relies on checking a marker file which will not work when running
|
||||
// out of different directories
|
||||
|
||||
if (LLStartUp::getStartSLURL().isValid() &&
|
||||
(gSavedSettings.getBOOL("SLURLPassToOtherInstance")))
|
||||
{
|
||||
if (sendURLToOtherInstance(LLStartUp::getStartSLURL().getSLURLString()))
|
||||
{
|
||||
// successfully handed off URL to existing instance, exit
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Check for another instance of the app running
|
||||
// This happens AFTER LLSplashScreen::show(). That may or may not be
|
||||
// important.
|
||||
//
|
||||
if (mSecondInstance && !gSavedSettings.getBOOL("AllowMultipleViewers"))
|
||||
{
|
||||
std::ostringstream msg;
|
||||
msg << LLTrans::getString("MBAlreadyRunning");
|
||||
OSMessageBox(
|
||||
msg.str(),
|
||||
LLTrans::getString("MBAlreadyRunning"),
|
||||
LLStringUtil::null,
|
||||
OSMB_OK);
|
||||
return false;
|
||||
|
|
@ -2825,27 +2834,6 @@ bool LLAppViewer::initConfiguration()
|
|||
}
|
||||
}
|
||||
|
||||
// NextLoginLocation is set from the command line option
|
||||
std::string nextLoginLocation = gSavedSettings.getString( "NextLoginLocation" );
|
||||
if ( !nextLoginLocation.empty() )
|
||||
{
|
||||
LL_DEBUGS("AppInit")<<"set start from NextLoginLocation: "<<nextLoginLocation<<LL_ENDL;
|
||||
LLStartUp::setStartSLURL(LLSLURL(nextLoginLocation));
|
||||
}
|
||||
else if ( ( clp.hasOption("login") || clp.hasOption("autologin"))
|
||||
&& gSavedSettings.getString("CmdLineLoginLocation").empty())
|
||||
{
|
||||
// If automatic login from command line with --login switch
|
||||
// init StartSLURL location.
|
||||
std::string start_slurl_setting = gSavedSettings.getString("LoginLocation");
|
||||
LL_DEBUGS("AppInit") << "start slurl setting '" << start_slurl_setting << "'" << LL_ENDL;
|
||||
LLStartUp::setStartSLURL(LLSLURL(start_slurl_setting));
|
||||
}
|
||||
else
|
||||
{
|
||||
// the login location will be set by the login panel (see LLPanelLogin)
|
||||
}
|
||||
|
||||
gLastRunVersion = gSavedSettings.getString("LastRunVersion");
|
||||
|
||||
loadColorSettings();
|
||||
|
|
@ -2869,7 +2857,14 @@ bool LLAppViewer::initConfiguration()
|
|||
// keeps growing, necessitating a method all its own.
|
||||
void LLAppViewer::initStrings()
|
||||
{
|
||||
LLTransUtil::parseStrings("strings.xml", default_trans_args);
|
||||
std::string strings_file = "strings.xml";
|
||||
std::string strings_path_full = gDirUtilp->findSkinnedFilenameBaseLang(LLDir::XUI, strings_file);
|
||||
if (strings_path_full.empty() || !LLFile::isfile(strings_path_full))
|
||||
{
|
||||
// initial check to make sure files are there failed
|
||||
LL_ERRS() << "Viewer failed to find localization and UI files. Please reinstall viewer from https://secondlife.com/support/downloads/ and contact https://support.secondlife.com if issue persists after reinstall." << LL_ENDL;
|
||||
}
|
||||
LLTransUtil::parseStrings(strings_file, default_trans_args);
|
||||
LLTransUtil::parseLanguageStrings("language_settings.xml");
|
||||
|
||||
// parseStrings() sets up the LLTrans substitution table. Add this one item.
|
||||
|
|
@ -3154,6 +3149,10 @@ LLSD LLAppViewer::getViewerInfo() const
|
|||
substitution["datetime"] = (S32)(gVFS ? gVFS->creationTime() : 0);
|
||||
info["VFS_TIME"] = LLTrans::getString("AboutTime", substitution);
|
||||
|
||||
#if LL_DARWIN
|
||||
info["HIDPI"] = gHiDPISupport;
|
||||
#endif
|
||||
|
||||
// Libraries
|
||||
|
||||
info["J2C_VERSION"] = LLImageJ2C::getEngineInfo();
|
||||
|
|
@ -3296,6 +3295,9 @@ std::string LLAppViewer::getViewerInfoString(bool default_string) const
|
|||
}
|
||||
support << "\n" << LLTrans::getString("AboutOGL", args, default_string);
|
||||
support << "\n\n" << LLTrans::getString("AboutSettings", args, default_string);
|
||||
#if LL_DARWIN
|
||||
support << "\n" << LLTrans::getString("AboutOSXHiDPI", args, default_string);
|
||||
#endif
|
||||
support << "\n\n" << LLTrans::getString("AboutLibs", args, default_string);
|
||||
if (info.has("COMPILER"))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -374,12 +374,40 @@ bool LLCommandLineParser::parseCommandLine(int argc, char **argv)
|
|||
|
||||
bool LLCommandLineParser::parseCommandLineString(const std::string& str)
|
||||
{
|
||||
std::string cmd_line_string("");
|
||||
if (!str.empty())
|
||||
{
|
||||
bool add_last_c = true;
|
||||
S32 last_c_pos = str.size() - 1; //don't get out of bounds on pos+1, last char will be processed separately
|
||||
for (S32 pos = 0; pos < last_c_pos; ++pos)
|
||||
{
|
||||
cmd_line_string.append(&str[pos], 1);
|
||||
if (str[pos] == '\\')
|
||||
{
|
||||
cmd_line_string.append("\\", 1);
|
||||
if (str[pos + 1] == '\\')
|
||||
{
|
||||
++pos;
|
||||
add_last_c = (pos != last_c_pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (add_last_c)
|
||||
{
|
||||
cmd_line_string.append(&str[last_c_pos], 1);
|
||||
if (str[last_c_pos] == '\\')
|
||||
{
|
||||
cmd_line_string.append("\\", 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Split the string content into tokens
|
||||
const char* escape_chars = "\\";
|
||||
const char* separator_chars = "\r\n ";
|
||||
const char* quote_chars = "\"'";
|
||||
const char* escape_chars = "\\";
|
||||
const char* separator_chars = "\r\n ";
|
||||
const char* quote_chars = "\"'";
|
||||
boost::escaped_list_separator<char> sep(escape_chars, separator_chars, quote_chars);
|
||||
boost::tokenizer< boost::escaped_list_separator<char> > tok(str, sep);
|
||||
boost::tokenizer< boost::escaped_list_separator<char> > tok(cmd_line_string, sep);
|
||||
std::vector<std::string> tokens;
|
||||
// std::copy(tok.begin(), tok.end(), std::back_inserter(tokens));
|
||||
for(boost::tokenizer< boost::escaped_list_separator<char> >::iterator i = tok.begin();
|
||||
|
|
|
|||
|
|
@ -566,27 +566,49 @@ LLViewerObject* LLControlAvatar::lineSegmentIntersectRiggedAttachments(const LLV
|
|||
LLVector4a* normal,
|
||||
LLVector4a* tangent)
|
||||
{
|
||||
LLViewerObject* hit = NULL;
|
||||
if (!mRootVolp)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (lineSegmentBoundingBox(start, end))
|
||||
{
|
||||
LLVector4a local_end = end;
|
||||
LLVector4a local_intersection;
|
||||
LLViewerObject* hit = NULL;
|
||||
|
||||
if (mRootVolp &&
|
||||
mRootVolp->lineSegmentIntersect(start, local_end, face, pick_transparent, pick_rigged, face_hit, &local_intersection, tex_coord, normal, tangent))
|
||||
if (lineSegmentBoundingBox(start, end))
|
||||
{
|
||||
LLVector4a local_end = end;
|
||||
LLVector4a local_intersection;
|
||||
if (mRootVolp->lineSegmentIntersect(start, local_end, face, pick_transparent, pick_rigged, face_hit, &local_intersection, tex_coord, normal, tangent))
|
||||
{
|
||||
local_end = local_intersection;
|
||||
if (intersection)
|
||||
{
|
||||
*intersection = local_intersection;
|
||||
}
|
||||
|
||||
hit = mRootVolp;
|
||||
}
|
||||
}
|
||||
|
||||
return hit;
|
||||
else
|
||||
{
|
||||
std::vector<LLVOVolume*> volumes;
|
||||
getAnimatedVolumes(volumes);
|
||||
|
||||
for (std::vector<LLVOVolume*>::iterator vol_it = volumes.begin(); vol_it != volumes.end(); ++vol_it)
|
||||
{
|
||||
LLVOVolume *volp = *vol_it;
|
||||
if (mRootVolp != volp && volp->lineSegmentIntersect(start, local_end, face, pick_transparent, pick_rigged, face_hit, &local_intersection, tex_coord, normal, tangent))
|
||||
{
|
||||
local_end = local_intersection;
|
||||
if (intersection)
|
||||
{
|
||||
*intersection = local_intersection;
|
||||
}
|
||||
hit = volp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return hit;
|
||||
}
|
||||
|
||||
// virtual
|
||||
|
|
|
|||
|
|
@ -1,714 +0,0 @@
|
|||
/**
|
||||
* @file llfacebookconnect.h
|
||||
* @author Merov, Cho, Gil
|
||||
* @brief Connection to Facebook Service
|
||||
*
|
||||
* $LicenseInfo:firstyear=2013&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2013, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#include "llviewerprecompiledheaders.h"
|
||||
|
||||
#include "llfacebookconnect.h"
|
||||
#include "llflickrconnect.h"
|
||||
#include "lltwitterconnect.h"
|
||||
|
||||
#include "llagent.h"
|
||||
#include "llcallingcard.h" // for LLAvatarTracker
|
||||
#include "llcommandhandler.h"
|
||||
#include "llnotificationsutil.h"
|
||||
#include "llurlaction.h"
|
||||
#include "llimagepng.h"
|
||||
#include "llimagejpeg.h"
|
||||
#include "lltrans.h"
|
||||
#include "llevents.h"
|
||||
#include "llviewerregion.h"
|
||||
#include "llviewercontrol.h"
|
||||
|
||||
#include "llfloaterwebcontent.h"
|
||||
#include "llfloaterreg.h"
|
||||
#include "llcorehttputil.h"
|
||||
|
||||
boost::scoped_ptr<LLEventPump> LLFacebookConnect::sStateWatcher(new LLEventStream("FacebookConnectState"));
|
||||
boost::scoped_ptr<LLEventPump> LLFacebookConnect::sInfoWatcher(new LLEventStream("FacebookConnectInfo"));
|
||||
boost::scoped_ptr<LLEventPump> LLFacebookConnect::sContentWatcher(new LLEventStream("FacebookConnectContent"));
|
||||
|
||||
// Local functions
|
||||
void log_facebook_connect_error(const std::string& request, U32 status, const std::string& reason, const std::string& code, const std::string& description)
|
||||
{
|
||||
// Note: 302 (redirect) is *not* an error that warrants logging
|
||||
if (status != 302)
|
||||
{
|
||||
LL_WARNS("FacebookConnect") << request << " request failed with a " << status << " " << reason << ". Reason: " << code << " (" << description << ")" << LL_ENDL;
|
||||
}
|
||||
}
|
||||
|
||||
void toast_user_for_facebook_success()
|
||||
{
|
||||
LLSD args;
|
||||
args["MESSAGE"] = LLTrans::getString("facebook_post_success");
|
||||
LLNotificationsUtil::add("FacebookConnect", args);
|
||||
}
|
||||
|
||||
LLCore::HttpHeaders::ptr_t get_headers()
|
||||
{
|
||||
LLCore::HttpHeaders::ptr_t httpHeaders(new LLCore::HttpHeaders);
|
||||
// The DebugSlshareLogTag mechanism is intended to trigger slshare-service
|
||||
// debug logging. slshare-service is coded to respond to an X-debug-tag
|
||||
// header by engaging debug logging for that request only. This way a
|
||||
// developer need not muck with the slshare-service image to engage debug
|
||||
// logging. Moreover, the value of X-debug-tag is embedded in each such
|
||||
// log line so the developer can quickly find the log lines pertinent to
|
||||
// THIS session.
|
||||
std::string logtag(gSavedSettings.getString("DebugSlshareLogTag"));
|
||||
if (! logtag.empty())
|
||||
{
|
||||
httpHeaders->append("X-debug-tag", logtag);
|
||||
}
|
||||
return httpHeaders;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
class LLFacebookConnectHandler : public LLCommandHandler
|
||||
{
|
||||
public:
|
||||
LLFacebookConnectHandler() : LLCommandHandler("fbc", UNTRUSTED_THROTTLE) { }
|
||||
|
||||
bool handle(const LLSD& tokens, const LLSD& query_map, LLMediaCtrl* web)
|
||||
{
|
||||
if (tokens.size() >= 1)
|
||||
{
|
||||
if (tokens[0].asString() == "connect")
|
||||
{
|
||||
if (tokens.size() >= 2 && tokens[1].asString() == "flickr")
|
||||
{
|
||||
// this command probably came from the flickr_web browser, so close it
|
||||
LLFloaterReg::hideInstance("flickr_web");
|
||||
|
||||
// connect to flickr
|
||||
if (query_map.has("oauth_token"))
|
||||
{
|
||||
LLFlickrConnect::instance().connectToFlickr(query_map["oauth_token"], query_map.get("oauth_verifier"));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else if (tokens.size() >= 2 && tokens[1].asString() == "twitter")
|
||||
{
|
||||
// this command probably came from the twitter_web browser, so close it
|
||||
LLFloaterReg::hideInstance("twitter_web");
|
||||
|
||||
// connect to twitter
|
||||
if (query_map.has("oauth_token"))
|
||||
{
|
||||
LLTwitterConnect::instance().connectToTwitter(query_map["oauth_token"], query_map.get("oauth_verifier"));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else //if (tokens.size() >= 2 && tokens[1].asString() == "facebook")
|
||||
{
|
||||
// this command probably came from the fbc_web browser, so close it
|
||||
LLFloaterReg::hideInstance("fbc_web");
|
||||
|
||||
// connect to facebook
|
||||
if (query_map.has("code"))
|
||||
{
|
||||
LLFacebookConnect::instance().connectToFacebook(query_map["code"], query_map.get("state"));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
LLFacebookConnectHandler gFacebookConnectHandler;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
void LLFacebookConnect::facebookConnectCoro(std::string authCode, std::string authState)
|
||||
{
|
||||
LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
|
||||
LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
|
||||
httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("FacebookConnect", httpPolicy));
|
||||
LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
|
||||
LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions);
|
||||
|
||||
LLSD putData;
|
||||
if (!authCode.empty())
|
||||
{
|
||||
putData["code"] = authCode;
|
||||
}
|
||||
if (!authState.empty())
|
||||
{
|
||||
putData["state"] = authState;
|
||||
}
|
||||
|
||||
httpOpts->setWantHeaders(true);
|
||||
httpOpts->setFollowRedirects(false);
|
||||
|
||||
LLSD result = httpAdapter->putAndSuspend(httpRequest, getFacebookConnectURL("/connection"), putData, httpOpts, get_headers());
|
||||
|
||||
LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
|
||||
LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
|
||||
if (!status)
|
||||
{
|
||||
if (status == LLCore::HttpStatus(HTTP_FOUND))
|
||||
{
|
||||
std::string location = httpResults[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS_HEADERS][HTTP_IN_HEADER_LOCATION];
|
||||
if (location.empty())
|
||||
{
|
||||
LL_WARNS("FacebookConnect") << "Missing Location header " << LL_ENDL;
|
||||
}
|
||||
else
|
||||
{
|
||||
openFacebookWeb(location);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_INFOS("FacebookConnect") << "Connect successful. " << LL_ENDL;
|
||||
setConnectionState(LLFacebookConnect::FB_CONNECTED);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
bool LLFacebookConnect::testShareStatus(LLSD &result)
|
||||
{
|
||||
LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
|
||||
LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
|
||||
|
||||
if (status)
|
||||
return true;
|
||||
|
||||
if (status == LLCore::HttpStatus(HTTP_FOUND))
|
||||
{
|
||||
std::string location = httpResults[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS_HEADERS][HTTP_IN_HEADER_LOCATION];
|
||||
if (location.empty())
|
||||
{
|
||||
LL_WARNS("FacebookConnect") << "Missing Location header " << LL_ENDL;
|
||||
}
|
||||
else
|
||||
{
|
||||
openFacebookWeb(location);
|
||||
}
|
||||
}
|
||||
if (status == LLCore::HttpStatus(HTTP_NOT_FOUND))
|
||||
{
|
||||
LL_DEBUGS("FacebookConnect") << "Not connected. " << LL_ENDL;
|
||||
connectToFacebook();
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS("FacebookConnect") << "HTTP Status error " << status.toString() << LL_ENDL;
|
||||
setConnectionState(LLFacebookConnect::FB_POST_FAILED);
|
||||
log_facebook_connect_error("Share", status.getStatus(), status.toString(),
|
||||
result.get("error_code"), result.get("error_description"));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void LLFacebookConnect::facebookShareCoro(std::string route, LLSD share)
|
||||
{
|
||||
LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
|
||||
LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
|
||||
httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("FacebookConnect", httpPolicy));
|
||||
LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
|
||||
LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions);
|
||||
|
||||
httpOpts->setWantHeaders(true);
|
||||
httpOpts->setFollowRedirects(false);
|
||||
|
||||
LLSD result = httpAdapter->postAndSuspend(httpRequest, getFacebookConnectURL(route, true), share, httpOpts, get_headers());
|
||||
|
||||
if (testShareStatus(result))
|
||||
{
|
||||
toast_user_for_facebook_success();
|
||||
LL_DEBUGS("FacebookConnect") << "Post successful. " << LL_ENDL;
|
||||
setConnectionState(LLFacebookConnect::FB_POSTED);
|
||||
}
|
||||
}
|
||||
|
||||
void LLFacebookConnect::facebookShareImageCoro(std::string route, LLPointer<LLImageFormatted> image, std::string caption)
|
||||
{
|
||||
LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
|
||||
LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
|
||||
httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("FacebookConnect", httpPolicy));
|
||||
LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
|
||||
LLCore::HttpHeaders::ptr_t httpHeaders(get_headers());
|
||||
LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions);
|
||||
|
||||
httpOpts->setWantHeaders(true);
|
||||
httpOpts->setFollowRedirects(false);
|
||||
|
||||
std::string imageFormat;
|
||||
if (dynamic_cast<LLImagePNG*>(image.get()))
|
||||
{
|
||||
imageFormat = "png";
|
||||
}
|
||||
else if (dynamic_cast<LLImageJPEG*>(image.get()))
|
||||
{
|
||||
imageFormat = "jpg";
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS() << "Image to upload is not a PNG or JPEG" << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
|
||||
// All this code is mostly copied from LLWebProfile::post()
|
||||
static const std::string boundary = "----------------------------0123abcdefab";
|
||||
|
||||
std::string contentType = "multipart/form-data; boundary=" + boundary;
|
||||
httpHeaders->append("Content-Type", contentType.c_str());
|
||||
|
||||
LLCore::BufferArray::ptr_t raw = LLCore::BufferArray::ptr_t(new LLCore::BufferArray()); //
|
||||
LLCore::BufferArrayStream body(raw.get());
|
||||
|
||||
// *NOTE: The order seems to matter.
|
||||
body << "--" << boundary << "\r\n"
|
||||
<< "Content-Disposition: form-data; name=\"caption\"\r\n\r\n"
|
||||
<< caption << "\r\n";
|
||||
|
||||
body << "--" << boundary << "\r\n"
|
||||
<< "Content-Disposition: form-data; name=\"image\"; filename=\"Untitled." << imageFormat << "\"\r\n"
|
||||
<< "Content-Type: image/" << imageFormat << "\r\n\r\n";
|
||||
|
||||
// Insert the image data.
|
||||
// *FIX: Treating this as a string will probably screw it up ...
|
||||
U8* image_data = image->getData();
|
||||
for (S32 i = 0; i < image->getDataSize(); ++i)
|
||||
{
|
||||
body << image_data[i];
|
||||
}
|
||||
|
||||
body << "\r\n--" << boundary << "--\r\n";
|
||||
|
||||
setConnectionState(LLFacebookConnect::FB_POSTING);
|
||||
|
||||
LLSD result = httpAdapter->postAndSuspend(httpRequest, getFacebookConnectURL(route, true), raw, httpOpts, httpHeaders);
|
||||
|
||||
if (testShareStatus(result))
|
||||
{
|
||||
toast_user_for_facebook_success();
|
||||
LL_DEBUGS("FacebookConnect") << "Post successful. " << LL_ENDL;
|
||||
setConnectionState(LLFacebookConnect::FB_POSTED);
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
void LLFacebookConnect::facebookDisconnectCoro()
|
||||
{
|
||||
LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
|
||||
LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
|
||||
httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("FacebookConnect", httpPolicy));
|
||||
LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
|
||||
LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions);
|
||||
|
||||
httpOpts->setFollowRedirects(false);
|
||||
|
||||
LLSD result = httpAdapter->deleteAndSuspend(httpRequest, getFacebookConnectURL("/connection"), httpOpts, get_headers());
|
||||
|
||||
LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
|
||||
LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
|
||||
if (!status && (status != LLCore::HttpStatus(HTTP_FOUND)))
|
||||
{
|
||||
LL_WARNS("FacebookConnect") << "Failed to disconnect:" << status.toTerseString() << LL_ENDL;
|
||||
setConnectionState(LLFacebookConnect::FB_DISCONNECT_FAILED);
|
||||
log_facebook_connect_error("Disconnect", status.getStatus(), status.toString(),
|
||||
result.get("error_code"), result.get("error_description"));
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_DEBUGS("FacebookConnect") << "Facebook Disconnect successful. " << LL_ENDL;
|
||||
clearInfo();
|
||||
clearContent();
|
||||
//Notify state change
|
||||
setConnectionState(LLFacebookConnect::FB_NOT_CONNECTED);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
void LLFacebookConnect::facebookConnectedCheckCoro(bool autoConnect)
|
||||
{
|
||||
LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
|
||||
LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
|
||||
httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("FacebookConnect", httpPolicy));
|
||||
LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
|
||||
LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions);
|
||||
|
||||
setConnectionState(LLFacebookConnect::FB_CONNECTION_IN_PROGRESS);
|
||||
|
||||
httpOpts->setFollowRedirects(false);
|
||||
|
||||
LLSD result = httpAdapter->getAndSuspend(httpRequest, getFacebookConnectURL("/connection", true), httpOpts, get_headers());
|
||||
|
||||
LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
|
||||
LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
|
||||
|
||||
if (!status)
|
||||
{
|
||||
if ( status == LLCore::HttpStatus(HTTP_NOT_FOUND) )
|
||||
{
|
||||
LL_DEBUGS("FacebookConnect") << "Not connected. " << LL_ENDL;
|
||||
if (autoConnect)
|
||||
{
|
||||
connectToFacebook();
|
||||
}
|
||||
else
|
||||
{
|
||||
setConnectionState(LLFacebookConnect::FB_NOT_CONNECTED);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS("FacebookConnect") << "Failed to test connection:" << status.toTerseString() << LL_ENDL;
|
||||
|
||||
setConnectionState(LLFacebookConnect::FB_DISCONNECT_FAILED);
|
||||
log_facebook_connect_error("Connected", status.getStatus(), status.toString(),
|
||||
result.get("error_code"), result.get("error_description"));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_DEBUGS("FacebookConnect") << "Connect successful. " << LL_ENDL;
|
||||
setConnectionState(LLFacebookConnect::FB_CONNECTED);
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
void LLFacebookConnect::facebookConnectInfoCoro()
|
||||
{
|
||||
LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
|
||||
LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
|
||||
httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("FacebookConnect", httpPolicy));
|
||||
LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
|
||||
LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions);
|
||||
|
||||
httpOpts->setWantHeaders(true);
|
||||
httpOpts->setFollowRedirects(false);
|
||||
|
||||
LLSD result = httpAdapter->getAndSuspend(httpRequest, getFacebookConnectURL("/info", true), httpOpts, get_headers());
|
||||
|
||||
LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
|
||||
LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
|
||||
|
||||
if (status == LLCore::HttpStatus(HTTP_FOUND))
|
||||
{
|
||||
std::string location = httpResults[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS_HEADERS][HTTP_IN_HEADER_LOCATION];
|
||||
if (location.empty())
|
||||
{
|
||||
LL_WARNS("FacebookConnect") << "Missing Location header " << LL_ENDL;
|
||||
}
|
||||
else
|
||||
{
|
||||
openFacebookWeb(location);
|
||||
}
|
||||
}
|
||||
else if (!status)
|
||||
{
|
||||
LL_WARNS("FacebookConnect") << "Facebook Info failed: " << status.toString() << LL_ENDL;
|
||||
log_facebook_connect_error("Info", status.getStatus(), status.toString(),
|
||||
result.get("error_code"), result.get("error_description"));
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_INFOS("FacebookConnect") << "Facebook: Info received" << LL_ENDL;
|
||||
result.erase(LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS);
|
||||
storeInfo(result);
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
void LLFacebookConnect::facebookConnectFriendsCoro()
|
||||
{
|
||||
LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
|
||||
LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
|
||||
httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("FacebookConnect", httpPolicy));
|
||||
LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
|
||||
LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions);
|
||||
|
||||
httpOpts->setFollowRedirects(false);
|
||||
|
||||
LLSD result = httpAdapter->getAndSuspend(httpRequest, getFacebookConnectURL("/friends", true), httpOpts, get_headers());
|
||||
|
||||
LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
|
||||
LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
|
||||
|
||||
if (status == LLCore::HttpStatus(HTTP_FOUND))
|
||||
{
|
||||
std::string location = httpResults[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS_HEADERS][HTTP_IN_HEADER_LOCATION];
|
||||
if (location.empty())
|
||||
{
|
||||
LL_WARNS("FacebookConnect") << "Missing Location header " << LL_ENDL;
|
||||
}
|
||||
else
|
||||
{
|
||||
openFacebookWeb(location);
|
||||
}
|
||||
}
|
||||
else if (!status)
|
||||
{
|
||||
LL_WARNS("FacebookConnect") << "Facebook Friends failed: " << status.toString() << LL_ENDL;
|
||||
log_facebook_connect_error("Info", status.getStatus(), status.toString(),
|
||||
result.get("error_code"), result.get("error_description"));
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_INFOS("FacebookConnect") << "Facebook: Friends received" << LL_ENDL;
|
||||
result.erase(LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS);
|
||||
LLSD content = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS_CONTENT];
|
||||
storeContent(content);
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
LLFacebookConnect::LLFacebookConnect()
|
||||
: mConnectionState(FB_NOT_CONNECTED),
|
||||
mConnected(false),
|
||||
mInfo(),
|
||||
mContent(),
|
||||
mRefreshInfo(false),
|
||||
mRefreshContent(false),
|
||||
mReadFromMaster(false)
|
||||
{
|
||||
}
|
||||
|
||||
void LLFacebookConnect::openFacebookWeb(std::string url)
|
||||
{
|
||||
LLFloaterWebContent::Params p;
|
||||
p.url(url);
|
||||
p.show_chrome(true);
|
||||
p.allow_back_forward_navigation(false);
|
||||
p.clean_browser(true);
|
||||
LLFloater *floater = LLFloaterReg::showInstance("fbc_web", p);
|
||||
//the internal web browser has a bug that prevents it from gaining focus unless a mouse event occurs first (it seems).
|
||||
//So when showing the internal web browser, set focus to it's containing floater "fbc_web". When a mouse event
|
||||
//occurs on the "webbrowser" panel part of the floater, a mouse cursor will properly show and the "webbrowser" will gain focus.
|
||||
//fbc_web floater contains the "webbrowser" panel. JIRA: ACME-744
|
||||
gFocusMgr.setKeyboardFocus( floater );
|
||||
|
||||
//LLUrlAction::openURLExternal(url);
|
||||
}
|
||||
|
||||
std::string LLFacebookConnect::getFacebookConnectURL(const std::string& route, bool include_read_from_master)
|
||||
{
|
||||
std::string url("");
|
||||
LLViewerRegion *regionp = gAgent.getRegion();
|
||||
if (regionp)
|
||||
{
|
||||
//url = "http://pdp15.lindenlab.com/fbc/agent/" + gAgentID.asString(); // TEMPORARY FOR TESTING - CHO
|
||||
url = regionp->getCapability("FacebookConnect");
|
||||
url += route;
|
||||
|
||||
if (include_read_from_master && mReadFromMaster)
|
||||
{
|
||||
url += "?read_from_master=true";
|
||||
}
|
||||
}
|
||||
return url;
|
||||
}
|
||||
|
||||
void LLFacebookConnect::connectToFacebook(const std::string& auth_code, const std::string& auth_state)
|
||||
{
|
||||
setConnectionState(LLFacebookConnect::FB_CONNECTION_IN_PROGRESS);
|
||||
|
||||
LLCoros::instance().launch("LLFacebookConnect::facebookConnectCoro",
|
||||
boost::bind(&LLFacebookConnect::facebookConnectCoro, this, auth_code, auth_state));
|
||||
}
|
||||
|
||||
void LLFacebookConnect::disconnectFromFacebook()
|
||||
{
|
||||
LLCoros::instance().launch("LLFacebookConnect::facebookDisconnectCoro",
|
||||
boost::bind(&LLFacebookConnect::facebookDisconnectCoro, this));
|
||||
}
|
||||
|
||||
void LLFacebookConnect::checkConnectionToFacebook(bool auto_connect)
|
||||
{
|
||||
setConnectionState(LLFacebookConnect::FB_DISCONNECTING);
|
||||
|
||||
LLCoros::instance().launch("LLFacebookConnect::facebookConnectedCheckCoro",
|
||||
boost::bind(&LLFacebookConnect::facebookConnectedCheckCoro, this, auto_connect));
|
||||
}
|
||||
|
||||
void LLFacebookConnect::loadFacebookInfo()
|
||||
{
|
||||
if(mRefreshInfo)
|
||||
{
|
||||
LLCoros::instance().launch("LLFacebookConnect::facebookConnectInfoCoro",
|
||||
boost::bind(&LLFacebookConnect::facebookConnectInfoCoro, this));
|
||||
}
|
||||
}
|
||||
|
||||
void LLFacebookConnect::loadFacebookFriends()
|
||||
{
|
||||
if(mRefreshContent)
|
||||
{
|
||||
LLCoros::instance().launch("LLFacebookConnect::facebookConnectFriendsCoro",
|
||||
boost::bind(&LLFacebookConnect::facebookConnectFriendsCoro, this));
|
||||
}
|
||||
}
|
||||
|
||||
void LLFacebookConnect::postCheckin(const std::string& location, const std::string& name,
|
||||
const std::string& description, const std::string& image, const std::string& message)
|
||||
{
|
||||
setConnectionState(LLFacebookConnect::FB_POSTING);
|
||||
|
||||
LLSD body;
|
||||
if (!location.empty())
|
||||
{
|
||||
body["location"] = location;
|
||||
}
|
||||
if (!name.empty())
|
||||
{
|
||||
body["name"] = name;
|
||||
}
|
||||
if (!description.empty())
|
||||
{
|
||||
body["description"] = description;
|
||||
}
|
||||
if (!image.empty())
|
||||
{
|
||||
body["image"] = image;
|
||||
}
|
||||
if (!message.empty())
|
||||
{
|
||||
body["message"] = message;
|
||||
}
|
||||
|
||||
LLCoros::instance().launch("LLFacebookConnect::facebookShareCoro",
|
||||
boost::bind(&LLFacebookConnect::facebookShareCoro, this, "/share/checkin", body));
|
||||
}
|
||||
|
||||
void LLFacebookConnect::sharePhoto(const std::string& image_url, const std::string& caption)
|
||||
{
|
||||
setConnectionState(LLFacebookConnect::FB_POSTING);
|
||||
|
||||
LLSD body;
|
||||
body["image"] = image_url;
|
||||
body["caption"] = caption;
|
||||
|
||||
LLCoros::instance().launch("LLFacebookConnect::facebookShareCoro",
|
||||
boost::bind(&LLFacebookConnect::facebookShareCoro, this, "/share/photo", body));
|
||||
}
|
||||
|
||||
void LLFacebookConnect::sharePhoto(LLPointer<LLImageFormatted> image, const std::string& caption)
|
||||
{
|
||||
setConnectionState(LLFacebookConnect::FB_POSTING);
|
||||
|
||||
LLCoros::instance().launch("LLFacebookConnect::facebookShareImageCoro",
|
||||
boost::bind(&LLFacebookConnect::facebookShareImageCoro, this, "/share/photo", image, caption));
|
||||
}
|
||||
|
||||
void LLFacebookConnect::updateStatus(const std::string& message)
|
||||
{
|
||||
LLSD body;
|
||||
body["message"] = message;
|
||||
|
||||
setConnectionState(LLFacebookConnect::FB_POSTING);
|
||||
|
||||
LLCoros::instance().launch("LLFacebookConnect::facebookShareCoro",
|
||||
boost::bind(&LLFacebookConnect::facebookShareCoro, this, "/share/wall", body));
|
||||
}
|
||||
|
||||
void LLFacebookConnect::storeInfo(const LLSD& info)
|
||||
{
|
||||
mInfo = info;
|
||||
mRefreshInfo = false;
|
||||
|
||||
sInfoWatcher->post(info);
|
||||
}
|
||||
|
||||
const LLSD& LLFacebookConnect::getInfo() const
|
||||
{
|
||||
return mInfo;
|
||||
}
|
||||
|
||||
void LLFacebookConnect::clearInfo()
|
||||
{
|
||||
mInfo = LLSD();
|
||||
}
|
||||
|
||||
void LLFacebookConnect::storeContent(const LLSD& content)
|
||||
{
|
||||
mContent = content;
|
||||
mRefreshContent = false;
|
||||
|
||||
sContentWatcher->post(content);
|
||||
}
|
||||
|
||||
const LLSD& LLFacebookConnect::getContent() const
|
||||
{
|
||||
return mContent;
|
||||
}
|
||||
|
||||
void LLFacebookConnect::clearContent()
|
||||
{
|
||||
mContent = LLSD();
|
||||
}
|
||||
|
||||
void LLFacebookConnect::setDataDirty()
|
||||
{
|
||||
mRefreshInfo = true;
|
||||
mRefreshContent = true;
|
||||
}
|
||||
|
||||
void LLFacebookConnect::setConnectionState(LLFacebookConnect::EConnectionState connection_state)
|
||||
{
|
||||
if(connection_state == FB_CONNECTED)
|
||||
{
|
||||
mReadFromMaster = true;
|
||||
setConnected(true);
|
||||
setDataDirty();
|
||||
}
|
||||
else if(connection_state == FB_NOT_CONNECTED)
|
||||
{
|
||||
setConnected(false);
|
||||
}
|
||||
else if(connection_state == FB_POSTED)
|
||||
{
|
||||
mReadFromMaster = false;
|
||||
}
|
||||
|
||||
if (mConnectionState != connection_state)
|
||||
{
|
||||
// set the connection state before notifying watchers
|
||||
mConnectionState = connection_state;
|
||||
|
||||
LLSD state_info;
|
||||
state_info["enum"] = connection_state;
|
||||
sStateWatcher->post(state_info);
|
||||
}
|
||||
}
|
||||
|
||||
void LLFacebookConnect::setConnected(bool connected)
|
||||
{
|
||||
mConnected = connected;
|
||||
}
|
||||
|
|
@ -1,116 +0,0 @@
|
|||
/**
|
||||
* @file llfacebookconnect.h
|
||||
* @author Merov, Cho, Gil
|
||||
* @brief Connection to Facebook Service
|
||||
*
|
||||
* $LicenseInfo:firstyear=2013&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2013, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#ifndef LL_LLFACEBOOKCONNECT_H
|
||||
#define LL_LLFACEBOOKCONNECT_H
|
||||
|
||||
#include "llsingleton.h"
|
||||
#include "llimage.h"
|
||||
#include "llcoros.h"
|
||||
#include "lleventcoro.h"
|
||||
|
||||
class LLEventPump;
|
||||
|
||||
/**
|
||||
* @class LLFacebookConnect
|
||||
*
|
||||
* Manages authentication to, and interaction with, a web service allowing the
|
||||
* the viewer to get Facebook OpenGraph data.
|
||||
*/
|
||||
class LLFacebookConnect : public LLSingleton<LLFacebookConnect>
|
||||
{
|
||||
LLSINGLETON(LLFacebookConnect);
|
||||
~LLFacebookConnect() {};
|
||||
LOG_CLASS(LLFacebookConnect);
|
||||
public:
|
||||
enum EConnectionState
|
||||
{
|
||||
FB_NOT_CONNECTED = 0,
|
||||
FB_CONNECTION_IN_PROGRESS = 1,
|
||||
FB_CONNECTED = 2,
|
||||
FB_CONNECTION_FAILED = 3,
|
||||
FB_POSTING = 4,
|
||||
FB_POSTED = 5,
|
||||
FB_POST_FAILED = 6,
|
||||
FB_DISCONNECTING = 7,
|
||||
FB_DISCONNECT_FAILED = 8
|
||||
};
|
||||
|
||||
void connectToFacebook(const std::string& auth_code = "", const std::string& auth_state = ""); // Initiate the complete FB connection. Please use checkConnectionToFacebook() in normal use.
|
||||
void disconnectFromFacebook(); // Disconnect from the FBC service.
|
||||
void checkConnectionToFacebook(bool auto_connect = false); // Check if an access token is available on the FBC service. If not, call connectToFacebook().
|
||||
|
||||
void loadFacebookInfo();
|
||||
void loadFacebookFriends();
|
||||
void postCheckin(const std::string& location, const std::string& name, const std::string& description, const std::string& picture, const std::string& message);
|
||||
void sharePhoto(const std::string& image_url, const std::string& caption);
|
||||
void sharePhoto(LLPointer<LLImageFormatted> image, const std::string& caption);
|
||||
void updateStatus(const std::string& message);
|
||||
|
||||
void storeInfo(const LLSD& info);
|
||||
const LLSD& getInfo() const;
|
||||
void clearInfo();
|
||||
void storeContent(const LLSD& content);
|
||||
const LLSD& getContent() const;
|
||||
void clearContent();
|
||||
void setDataDirty();
|
||||
|
||||
void setConnectionState(EConnectionState connection_state);
|
||||
void setConnected(bool connected);
|
||||
bool isConnected() { return mConnected; }
|
||||
bool isTransactionOngoing() { return ((mConnectionState == FB_CONNECTION_IN_PROGRESS) || (mConnectionState == FB_POSTING) || (mConnectionState == FB_DISCONNECTING)); }
|
||||
EConnectionState getConnectionState() { return mConnectionState; }
|
||||
|
||||
void openFacebookWeb(std::string url);
|
||||
|
||||
private:
|
||||
|
||||
std::string getFacebookConnectURL(const std::string& route = "", bool include_read_from_master = false);
|
||||
|
||||
EConnectionState mConnectionState;
|
||||
BOOL mConnected;
|
||||
LLSD mInfo;
|
||||
LLSD mContent;
|
||||
bool mRefreshInfo;
|
||||
bool mRefreshContent;
|
||||
bool mReadFromMaster;
|
||||
|
||||
static boost::scoped_ptr<LLEventPump> sStateWatcher;
|
||||
static boost::scoped_ptr<LLEventPump> sInfoWatcher;
|
||||
static boost::scoped_ptr<LLEventPump> sContentWatcher;
|
||||
|
||||
bool testShareStatus(LLSD &results);
|
||||
void facebookConnectCoro(std::string authCode, std::string authState);
|
||||
void facebookConnectedCheckCoro(bool autoConnect);
|
||||
void facebookDisconnectCoro();
|
||||
void facebookShareCoro(std::string route, LLSD share);
|
||||
void facebookShareImageCoro(std::string route, LLPointer<LLImageFormatted> image, std::string caption);
|
||||
void facebookConnectInfoCoro();
|
||||
void facebookConnectFriendsCoro();
|
||||
};
|
||||
|
||||
#endif // LL_LLFACEBOOKCONNECT_H
|
||||
|
|
@ -43,6 +43,7 @@
|
|||
#include "llsdserialize.h"
|
||||
#include "lltooltip.h"
|
||||
#include "llbutton.h"
|
||||
#include "llscrollbar.h"
|
||||
|
||||
#include "llappviewer.h"
|
||||
#include "llviewertexturelist.h"
|
||||
|
|
@ -128,7 +129,8 @@ void LLFastTimerView::setPauseState(bool pause_state)
|
|||
BOOL LLFastTimerView::postBuild()
|
||||
{
|
||||
LLButton& pause_btn = getChildRef<LLButton>("pause_btn");
|
||||
|
||||
mScrollBar = getChild<LLScrollbar>("scroll_vert");
|
||||
|
||||
pause_btn.setCommitCallback(boost::bind(&LLFastTimerView::onPause, this));
|
||||
return TRUE;
|
||||
}
|
||||
|
|
@ -183,7 +185,7 @@ BOOL LLFastTimerView::handleDoubleClick(S32 x, S32 y, MASK mask)
|
|||
|
||||
BOOL LLFastTimerView::handleMouseDown(S32 x, S32 y, MASK mask)
|
||||
{
|
||||
if (x < mBarRect.mLeft)
|
||||
if (x < mScrollBar->getRect().mLeft)
|
||||
{
|
||||
BlockTimerStatHandle* idp = getLegendID(y);
|
||||
if (idp)
|
||||
|
|
@ -284,7 +286,7 @@ BOOL LLFastTimerView::handleHover(S32 x, S32 y, MASK mask)
|
|||
}
|
||||
}
|
||||
}
|
||||
else if (x < mBarRect.mLeft)
|
||||
else if (x < mScrollBar->getRect().mLeft)
|
||||
{
|
||||
BlockTimerStatHandle* timer_id = getLegendID(y);
|
||||
if (timer_id)
|
||||
|
|
@ -335,7 +337,7 @@ BOOL LLFastTimerView::handleToolTip(S32 x, S32 y, MASK mask)
|
|||
else
|
||||
{
|
||||
// tooltips for timer legend
|
||||
if (x < mBarRect.mLeft)
|
||||
if (x < mScrollBar->getRect().mLeft)
|
||||
{
|
||||
BlockTimerStatHandle* idp = getLegendID(y);
|
||||
if (idp)
|
||||
|
|
@ -352,11 +354,19 @@ BOOL LLFastTimerView::handleToolTip(S32 x, S32 y, MASK mask)
|
|||
|
||||
BOOL LLFastTimerView::handleScrollWheel(S32 x, S32 y, S32 clicks)
|
||||
{
|
||||
setPauseState(true);
|
||||
mScrollIndex = llclamp( mScrollIndex + clicks,
|
||||
0,
|
||||
llmin((S32)mRecording.getNumRecordedPeriods(), (S32)mRecording.getNumRecordedPeriods() - MAX_VISIBLE_HISTORY));
|
||||
return TRUE;
|
||||
if (x < mBarRect.mLeft)
|
||||
{
|
||||
// Inside mScrollBar and list of timers
|
||||
mScrollBar->handleScrollWheel(x,y,clicks);
|
||||
}
|
||||
else
|
||||
{
|
||||
setPauseState(true);
|
||||
mScrollIndex = llclamp(mScrollIndex + clicks,
|
||||
0,
|
||||
llmin((S32)mRecording.getNumRecordedPeriods(), (S32)mRecording.getNumRecordedPeriods() - MAX_VISIBLE_HISTORY));
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BlockTimerStatHandle FTM_RENDER_TIMER("Timers");
|
||||
|
|
@ -1197,6 +1207,7 @@ void LLFastTimerView::drawLegend()
|
|||
{
|
||||
LLLocalClipRect clip(mLegendRect);
|
||||
S32 cur_line = 0;
|
||||
S32 scroll_offset = 0; // element's y offset from top of the inner scroll's rect
|
||||
ft_display_idx.clear();
|
||||
std::map<BlockTimerStatHandle*, S32> display_line;
|
||||
for (block_timer_tree_df_iterator_t it = LLTrace::begin_block_timer_tree_df(FTM_FRAME);
|
||||
|
|
@ -1204,10 +1215,24 @@ void LLFastTimerView::drawLegend()
|
|||
++it)
|
||||
{
|
||||
BlockTimerStatHandle* idp = (*it);
|
||||
// Needed to figure out offsets and parenting
|
||||
display_line[idp] = cur_line;
|
||||
ft_display_idx.push_back(idp);
|
||||
cur_line++;
|
||||
if (scroll_offset < mScrollBar->getDocPos())
|
||||
{
|
||||
// only offset for visible items
|
||||
scroll_offset += TEXT_HEIGHT + 2;
|
||||
if (idp->getTreeNode().mCollapsed)
|
||||
{
|
||||
it.skipDescendants();
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// used for mouse clicks
|
||||
ft_display_idx.push_back(idp);
|
||||
|
||||
// Actual draw, first bar (square), then text
|
||||
x = MARGIN;
|
||||
|
||||
LLRect bar_rect(x, y, x + TEXT_HEIGHT, y - TEXT_HEIGHT);
|
||||
|
|
@ -1281,11 +1306,14 @@ void LLFastTimerView::drawLegend()
|
|||
|
||||
y -= (TEXT_HEIGHT + 2);
|
||||
|
||||
scroll_offset += TEXT_HEIGHT + 2;
|
||||
if (idp->getTreeNode().mCollapsed)
|
||||
{
|
||||
it.skipDescendants();
|
||||
}
|
||||
}
|
||||
// Recalculate scroll size
|
||||
mScrollBar->setDocSize(scroll_offset - mLegendRect.getHeight());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -33,6 +33,8 @@
|
|||
#include "lltracerecording.h"
|
||||
#include <deque>
|
||||
|
||||
class LLScrollbar;
|
||||
|
||||
class LLFastTimerView : public LLFloater
|
||||
{
|
||||
public:
|
||||
|
|
@ -142,6 +144,8 @@ private:
|
|||
mLegendRect;
|
||||
LLFrameTimer mHighlightTimer;
|
||||
LLTrace::PeriodicRecording mRecording;
|
||||
|
||||
LLScrollbar* mScrollBar;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,185 +0,0 @@
|
|||
/**
|
||||
* @file llfloaterfacebook.h
|
||||
* @brief Header file for llfloaterfacebook
|
||||
* @author Gilbert@lindenlab.com
|
||||
*
|
||||
* $LicenseInfo:firstyear=2013&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2013, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
#ifndef LL_LLFLOATERFACEBOOK_H
|
||||
#define LL_LLFLOATERFACEBOOK_H
|
||||
|
||||
#include "llcallingcard.h"
|
||||
#include "llfloater.h"
|
||||
#include "lltextbox.h"
|
||||
#include "llviewertexture.h"
|
||||
|
||||
class LLIconCtrl;
|
||||
class LLCheckBoxCtrl;
|
||||
class LLSnapshotLivePreview;
|
||||
class LLAvatarList;
|
||||
class LLFloaterBigPreview;
|
||||
|
||||
class LLFacebookStatusPanel : public LLPanel
|
||||
{
|
||||
public:
|
||||
LLFacebookStatusPanel();
|
||||
BOOL postBuild();
|
||||
void draw();
|
||||
void onSend();
|
||||
bool onFacebookConnectStateChange(const LLSD& data);
|
||||
bool onFacebookConnectAccountStateChange(const LLSD& data);
|
||||
|
||||
void sendStatus();
|
||||
void clearAndClose();
|
||||
|
||||
private:
|
||||
void onVisibilityChange(BOOL new_visibility);
|
||||
bool onFacebookConnectInfoChange();
|
||||
void onConnect();
|
||||
void onUseAnotherAccount();
|
||||
void onDisconnect();
|
||||
|
||||
void showConnectButton();
|
||||
void hideConnectButton();
|
||||
void showDisconnectedLayout();
|
||||
void showConnectedLayout();
|
||||
|
||||
LLTextBox * mAccountCaptionLabel;
|
||||
LLTextBox * mAccountNameLabel;
|
||||
LLUICtrl * mPanelButtons;
|
||||
LLUICtrl * mConnectButton;
|
||||
LLUICtrl * mDisconnectButton;
|
||||
LLUICtrl* mMessageTextEditor;
|
||||
LLUICtrl* mPostButton;
|
||||
LLUICtrl* mCancelButton;
|
||||
};
|
||||
|
||||
class LLFacebookPhotoPanel : public LLPanel
|
||||
{
|
||||
public:
|
||||
LLFacebookPhotoPanel();
|
||||
~LLFacebookPhotoPanel();
|
||||
|
||||
BOOL postBuild();
|
||||
void draw();
|
||||
|
||||
LLSnapshotLivePreview* getPreviewView();
|
||||
void onVisibilityChange(BOOL new_visibility);
|
||||
void onClickBigPreview();
|
||||
void onClickNewSnapshot();
|
||||
void onSend();
|
||||
S32 notify(const LLSD& info);
|
||||
bool onFacebookConnectStateChange(const LLSD& data);
|
||||
|
||||
void sendPhoto();
|
||||
void clearAndClose();
|
||||
|
||||
void updateControls();
|
||||
void updateResolution(BOOL do_update);
|
||||
void checkAspectRatio(S32 index);
|
||||
LLUICtrl* getRefreshBtn();
|
||||
|
||||
private:
|
||||
bool isPreviewVisible();
|
||||
void attachPreview();
|
||||
|
||||
LLHandle<LLView> mPreviewHandle;
|
||||
|
||||
LLUICtrl * mResolutionComboBox;
|
||||
LLUICtrl * mFilterComboBox;
|
||||
LLUICtrl * mRefreshBtn;
|
||||
LLUICtrl * mWorkingLabel;
|
||||
LLUICtrl * mThumbnailPlaceholder;
|
||||
LLUICtrl * mCaptionTextBox;
|
||||
LLUICtrl * mPostButton;
|
||||
LLUICtrl * mCancelButton;
|
||||
LLButton * mBtnPreview;
|
||||
|
||||
LLFloaterBigPreview * mBigPreviewFloater;
|
||||
|
||||
S32 mQuality; // Compression quality
|
||||
};
|
||||
|
||||
class LLFacebookCheckinPanel : public LLPanel
|
||||
{
|
||||
public:
|
||||
LLFacebookCheckinPanel();
|
||||
BOOL postBuild();
|
||||
void draw();
|
||||
void onSend();
|
||||
bool onFacebookConnectStateChange(const LLSD& data);
|
||||
|
||||
void sendCheckin();
|
||||
void clearAndClose();
|
||||
|
||||
private:
|
||||
std::string mMapUrl;
|
||||
LLPointer<LLViewerFetchedTexture> mMapTexture;
|
||||
LLUICtrl* mPostButton;
|
||||
LLUICtrl* mCancelButton;
|
||||
LLUICtrl* mMessageTextEditor;
|
||||
LLUICtrl* mMapLoadingIndicator;
|
||||
LLIconCtrl* mMapPlaceholder;
|
||||
LLIconCtrl* mMapDefault;
|
||||
LLCheckBoxCtrl* mMapCheckBox;
|
||||
bool mReloadingMapTexture;
|
||||
};
|
||||
|
||||
class LLFacebookFriendsPanel : public LLPanel, public LLFriendObserver
|
||||
{
|
||||
public:
|
||||
LLFacebookFriendsPanel();
|
||||
~LLFacebookFriendsPanel();
|
||||
BOOL postBuild();
|
||||
virtual void changed(U32 mask);
|
||||
|
||||
private:
|
||||
bool updateSuggestedFriendList();
|
||||
void showFriendsAccordionsIfNeeded();
|
||||
void updateFacebookList(bool visible);
|
||||
bool onConnectedToFacebook(const LLSD& data);
|
||||
|
||||
LLTextBox * mFriendsStatusCaption;
|
||||
LLAvatarList* mSecondLifeFriends;
|
||||
LLAvatarList* mSuggestedFriends;
|
||||
};
|
||||
|
||||
class LLFloaterFacebook : public LLFloater
|
||||
{
|
||||
public:
|
||||
LLFloaterFacebook(const LLSD& key);
|
||||
BOOL postBuild();
|
||||
void draw();
|
||||
void onClose(bool app_quitting);
|
||||
void onCancel();
|
||||
|
||||
void showPhotoPanel();
|
||||
|
||||
private:
|
||||
LLFacebookPhotoPanel* mFacebookPhotoPanel;
|
||||
LLTextBox* mStatusErrorText;
|
||||
LLTextBox* mStatusLoadingText;
|
||||
LLUICtrl* mStatusLoadingIndicator;
|
||||
};
|
||||
|
||||
#endif // LL_LLFLOATERFACEBOOK_H
|
||||
|
||||
|
|
@ -1877,6 +1877,7 @@ LLPanelLandOptions::LLPanelLandOptions(LLParcelSelectionHandle& parcel)
|
|||
mLandingTypeCombo(NULL),
|
||||
mSnapshotCtrl(NULL),
|
||||
mLocationText(NULL),
|
||||
mSeeAvatarsText(NULL),
|
||||
mSetBtn(NULL),
|
||||
mClearBtn(NULL),
|
||||
mMatureCtrl(NULL),
|
||||
|
|
@ -1923,6 +1924,14 @@ BOOL LLPanelLandOptions::postBuild()
|
|||
mSeeAvatarsCtrl = getChild<LLCheckBoxCtrl>( "SeeAvatarsCheck");
|
||||
childSetCommitCallback("SeeAvatarsCheck", onCommitAny, this);
|
||||
|
||||
mSeeAvatarsText = getChild<LLTextBox>("allow_see_label");
|
||||
if (mSeeAvatarsText)
|
||||
{
|
||||
mSeeAvatarsText->setShowCursorHand(false);
|
||||
mSeeAvatarsText->setSoundFlags(LLView::MOUSE_UP);
|
||||
mSeeAvatarsText->setClickedCallback(boost::bind(&toggleSeeAvatars, this));
|
||||
}
|
||||
|
||||
mCheckShowDirectory = getChild<LLCheckBoxCtrl>( "ShowDirectoryCheck");
|
||||
childSetCommitCallback("ShowDirectoryCheck", onCommitAny, this);
|
||||
|
||||
|
|
@ -2016,6 +2025,7 @@ void LLPanelLandOptions::refresh()
|
|||
|
||||
mSeeAvatarsCtrl->set(TRUE);
|
||||
mSeeAvatarsCtrl->setEnabled(FALSE);
|
||||
mSeeAvatarsText->setEnabled(FALSE);
|
||||
|
||||
mLandingTypeCombo->setCurrentByIndex(0);
|
||||
mLandingTypeCombo->setEnabled(FALSE);
|
||||
|
|
@ -2074,6 +2084,7 @@ void LLPanelLandOptions::refresh()
|
|||
|
||||
mSeeAvatarsCtrl->set(parcel->getSeeAVs());
|
||||
mSeeAvatarsCtrl->setEnabled(can_change_options && parcel->getHaveNewParcelLimitData());
|
||||
mSeeAvatarsText->setEnabled(can_change_options && parcel->getHaveNewParcelLimitData());
|
||||
|
||||
BOOL can_change_landing_point = LLViewerParcelMgr::isParcelModifiableByAgent(parcel,
|
||||
GP_LAND_SET_LANDING_POINT);
|
||||
|
|
@ -2364,7 +2375,16 @@ void LLPanelLandOptions::onClickClear(void* userdata)
|
|||
self->refresh();
|
||||
}
|
||||
|
||||
|
||||
void LLPanelLandOptions::toggleSeeAvatars(void* userdata)
|
||||
{
|
||||
LLPanelLandOptions* self = (LLPanelLandOptions*)userdata;
|
||||
if (self)
|
||||
{
|
||||
self->getChild<LLCheckBoxCtrl>("SeeAvatarsCheck")->toggle();
|
||||
self->getChild<LLCheckBoxCtrl>("SeeAvatarsCheck")->setBtnFocus();
|
||||
self->onCommitAny(NULL, userdata);
|
||||
}
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
// LLPanelLandAccess
|
||||
//---------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -327,6 +327,7 @@ private:
|
|||
static void onCommitAny(LLUICtrl* ctrl, void *userdata);
|
||||
static void onClickSet(void* userdata);
|
||||
static void onClickClear(void* userdata);
|
||||
static void toggleSeeAvatars(void* userdata);
|
||||
|
||||
private:
|
||||
LLCheckBoxCtrl* mCheckEditObjects;
|
||||
|
|
@ -345,6 +346,7 @@ private:
|
|||
LLTextureCtrl* mSnapshotCtrl;
|
||||
|
||||
LLTextBox* mLocationText;
|
||||
LLTextBox* mSeeAvatarsText;
|
||||
LLButton* mSetBtn;
|
||||
LLButton* mClearBtn;
|
||||
|
||||
|
|
|
|||
|
|
@ -325,6 +325,8 @@ BOOL LLFloaterModelPreview::postBuild()
|
|||
childSetCommitCallback("import_scale", onImportScaleCommit, this);
|
||||
childSetCommitCallback("pelvis_offset", onPelvisOffsetCommit, this);
|
||||
|
||||
getChild<LLLineEditor>("description_form")->setKeystrokeCallback(boost::bind(&LLFloaterModelPreview::onDescriptionKeystroke, this, _1), NULL);
|
||||
|
||||
getChild<LLCheckBoxCtrl>("show_edges")->setCommitCallback(boost::bind(&LLFloaterModelPreview::onViewOptionChecked, this, _1));
|
||||
getChild<LLCheckBoxCtrl>("show_physics")->setCommitCallback(boost::bind(&LLFloaterModelPreview::onViewOptionChecked, this, _1));
|
||||
getChild<LLCheckBoxCtrl>("show_textures")->setCommitCallback(boost::bind(&LLFloaterModelPreview::onViewOptionChecked, this, _1));
|
||||
|
|
@ -520,6 +522,16 @@ void LLFloaterModelPreview::onClickCalculateBtn()
|
|||
mUploadBtn->setEnabled(false);
|
||||
}
|
||||
|
||||
void LLFloaterModelPreview::onDescriptionKeystroke(LLUICtrl* ctrl)
|
||||
{
|
||||
// Workaround for SL-4186, server doesn't allow name changes after 'calculate' stage
|
||||
LLLineEditor* input = static_cast<LLLineEditor*>(ctrl);
|
||||
if (input->isDirty()) // dirty will be reset after commit
|
||||
{
|
||||
toggleCalculateButton(true);
|
||||
}
|
||||
}
|
||||
|
||||
//static
|
||||
void LLFloaterModelPreview::onImportScaleCommit(LLUICtrl*,void* userdata)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -137,7 +137,9 @@ protected:
|
|||
friend class LLModelPreview;
|
||||
friend class LLMeshFilePicker;
|
||||
friend class LLPhysicsDecomp;
|
||||
|
||||
|
||||
void onDescriptionKeystroke(LLUICtrl*);
|
||||
|
||||
static void onImportScaleCommit(LLUICtrl*, void*);
|
||||
static void onPelvisOffsetCommit(LLUICtrl*, void*);
|
||||
static void onUploadJointsCommit(LLUICtrl*,void*);
|
||||
|
|
|
|||
|
|
@ -30,9 +30,7 @@
|
|||
#include "llfloateroutfitsnapshot.h"
|
||||
|
||||
#include "llagent.h"
|
||||
#include "llfacebookconnect.h"
|
||||
#include "llfloaterreg.h"
|
||||
#include "llfloaterfacebook.h"
|
||||
#include "llfloaterflickr.h"
|
||||
#include "llfloatertwitter.h"
|
||||
#include "llimagefiltersmanager.h"
|
||||
|
|
|
|||
|
|
@ -28,9 +28,7 @@
|
|||
|
||||
#include "llfloatersnapshot.h"
|
||||
|
||||
#include "llfacebookconnect.h"
|
||||
#include "llfloaterreg.h"
|
||||
#include "llfloaterfacebook.h"
|
||||
#include "llfloaterflickr.h"
|
||||
#include "llfloatertwitter.h"
|
||||
#include "llimagefiltersmanager.h"
|
||||
|
|
@ -1242,11 +1240,10 @@ BOOL LLFloaterSnapshot::isWaitingState()
|
|||
|
||||
BOOL LLFloaterSnapshotBase::ImplBase::updatePreviewList(bool initialized)
|
||||
{
|
||||
LLFloaterFacebook* floater_facebook = LLFloaterReg::findTypedInstance<LLFloaterFacebook>("facebook");
|
||||
LLFloaterFlickr* floater_flickr = LLFloaterReg::findTypedInstance<LLFloaterFlickr>("flickr");
|
||||
LLFloaterTwitter* floater_twitter = LLFloaterReg::findTypedInstance<LLFloaterTwitter>("twitter");
|
||||
|
||||
if (!initialized && !floater_facebook && !floater_flickr && !floater_twitter)
|
||||
if (!initialized && !floater_flickr && !floater_twitter)
|
||||
return FALSE;
|
||||
|
||||
BOOL changed = FALSE;
|
||||
|
|
|
|||
|
|
@ -514,11 +514,6 @@ void LLFloaterTools::refresh()
|
|||
selection_info << getString("status_selectcount", selection_args);
|
||||
|
||||
getChild<LLTextBox>("selection_count")->setText(selection_info.str());
|
||||
|
||||
bool have_selection = !LLSelectMgr::getInstance()->getSelection()->isEmpty();
|
||||
childSetVisible("selection_count", have_selection);
|
||||
childSetVisible("remaining_capacity", have_selection);
|
||||
childSetVisible("selection_empty", !have_selection);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -30,7 +30,6 @@
|
|||
#include "lliconctrl.h"
|
||||
#include "llfloaterreg.h"
|
||||
#include "llhttpconstants.h"
|
||||
#include "llfacebookconnect.h"
|
||||
#include "llflickrconnect.h"
|
||||
#include "lltwitterconnect.h"
|
||||
#include "lllayoutstack.h"
|
||||
|
|
@ -289,17 +288,7 @@ void LLFloaterWebContent::onOpen(const LLSD& key)
|
|||
//virtual
|
||||
void LLFloaterWebContent::onClose(bool app_quitting)
|
||||
{
|
||||
// If we close the web browsing window showing the facebook login, we need to signal to this object that the connection will not happen
|
||||
// MAINT-3440 note change here to use findInstance and not getInstance - latter creates an instance if it's not there which is bad.
|
||||
LLFloater* fbc_web = LLFloaterReg::findInstance("fbc_web");
|
||||
if (fbc_web == this)
|
||||
{
|
||||
if (!LLFacebookConnect::instance().isConnected())
|
||||
{
|
||||
LLFacebookConnect::instance().setConnectionState(LLFacebookConnect::FB_CONNECTION_FAILED);
|
||||
}
|
||||
}
|
||||
// Same with Flickr
|
||||
// If we close the web browsing window showing the Flickr login, we need to signal to this object that the connection will not happen
|
||||
// MAINT-3440 note change here to use findInstance and not getInstance - latter creates an instance if it's not there which is bad.
|
||||
LLFloater* flickr_web = LLFloaterReg::findInstance("flickr_web");
|
||||
if (flickr_web == this)
|
||||
|
|
@ -309,7 +298,7 @@ void LLFloaterWebContent::onClose(bool app_quitting)
|
|||
LLFlickrConnect::instance().setConnectionState(LLFlickrConnect::FLICKR_CONNECTION_FAILED);
|
||||
}
|
||||
}
|
||||
// And Twitter
|
||||
// Same with Twitter
|
||||
// MAINT-3440 note change here to use findInstance and not getInstance - latter creates an instance if it's not there which is bad.
|
||||
LLFloater* twitter_web = LLFloaterReg::findInstance("twitter_web");
|
||||
if (twitter_web == this)
|
||||
|
|
@ -380,13 +369,6 @@ void LLFloaterWebContent::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent
|
|||
// The browser instance wants its window closed.
|
||||
closeFloater();
|
||||
}
|
||||
else if(event == MEDIA_EVENT_GEOMETRY_CHANGE)
|
||||
{
|
||||
if (mCurrentURL.find("facebook.com/dialog/oauth") == std::string::npos) // HACK to fix ACME-1317 - Cho
|
||||
{
|
||||
geometryChanged(self->getGeometryX(), self->getGeometryY(), self->getGeometryWidth(), self->getGeometryHeight());
|
||||
}
|
||||
}
|
||||
else if(event == MEDIA_EVENT_STATUS_TEXT_CHANGED )
|
||||
{
|
||||
const std::string text = self->getStatusText();
|
||||
|
|
|
|||
|
|
@ -1005,7 +1005,10 @@ F32 gpu_benchmark()
|
|||
|
||||
//number of samples to take
|
||||
const S32 samples = 64;
|
||||
|
||||
|
||||
//time limit, allocation operations shouldn't take longer then 30 seconds, same for actual benchmark.
|
||||
const F32 time_limit = 30;
|
||||
|
||||
ShaderProfileHelper initProfile;
|
||||
|
||||
std::vector<LLRenderTarget> dest(count);
|
||||
|
|
@ -1023,12 +1026,14 @@ F32 gpu_benchmark()
|
|||
gGL.setColorMask(true, true);
|
||||
LLGLDepthTest depth(GL_FALSE);
|
||||
|
||||
LLTimer alloc_timer;
|
||||
alloc_timer.start();
|
||||
for (U32 i = 0; i < count; ++i)
|
||||
{
|
||||
//allocate render targets and textures
|
||||
if (!dest[i].allocate(res, res, GL_RGBA, false, false, LLTexUnit::TT_TEXTURE, true))
|
||||
{
|
||||
LL_WARNS() << "Failed to allocate render target." << LL_ENDL;
|
||||
LL_WARNS("Benchmark") << "Failed to allocate render target." << LL_ENDL;
|
||||
// abandon the benchmark test
|
||||
delete[] pixels;
|
||||
return -1.f;
|
||||
|
|
@ -1040,12 +1045,20 @@ F32 gpu_benchmark()
|
|||
if (!texHolder.bind(i))
|
||||
{
|
||||
// can use a dummy value mDummyTexUnit = new LLTexUnit(-1);
|
||||
LL_WARNS() << "Failed to bind tex unit." << LL_ENDL;
|
||||
LL_WARNS("Benchmark") << "Failed to bind tex unit." << LL_ENDL;
|
||||
// abandon the benchmark test
|
||||
delete[] pixels;
|
||||
return -1.f;
|
||||
}
|
||||
LLImageGL::setManualImage(GL_TEXTURE_2D, 0, GL_RGBA, res,res,GL_RGBA, GL_UNSIGNED_BYTE, pixels);
|
||||
|
||||
if (alloc_timer.getElapsedTimeF32() > time_limit)
|
||||
{
|
||||
// abandon the benchmark test
|
||||
LL_WARNS("Benchmark") << "Allocation operation took longer then 30 seconds, stopping." << LL_ENDL;
|
||||
delete[] pixels;
|
||||
return -1.f;
|
||||
}
|
||||
}
|
||||
|
||||
delete [] pixels;
|
||||
|
|
@ -1055,7 +1068,7 @@ F32 gpu_benchmark()
|
|||
|
||||
if (!buff->allocateBuffer(3, 0, true))
|
||||
{
|
||||
LL_WARNS() << "Failed to allocate buffer during benchmark." << LL_ENDL;
|
||||
LL_WARNS("Benchmark") << "Failed to allocate buffer during benchmark." << LL_ENDL;
|
||||
// abandon the benchmark test
|
||||
return -1.f;
|
||||
}
|
||||
|
|
@ -1065,7 +1078,7 @@ F32 gpu_benchmark()
|
|||
|
||||
if (! buff->getVertexStrider(v))
|
||||
{
|
||||
LL_WARNS() << "GL LLVertexBuffer::getVertexStrider() returned false, "
|
||||
LL_WARNS("Benchmark") << "GL LLVertexBuffer::getVertexStrider() returned false, "
|
||||
<< "buff->getMappedData() is"
|
||||
<< (buff->getMappedData()? " not" : "")
|
||||
<< " NULL" << LL_ENDL;
|
||||
|
|
@ -1086,7 +1099,8 @@ F32 gpu_benchmark()
|
|||
buff->setBuffer(LLVertexBuffer::MAP_VERTEX);
|
||||
glFinish();
|
||||
|
||||
for (S32 c = -1; c < samples; ++c)
|
||||
F32 time_passed = 0; // seconds
|
||||
for (S32 c = -1; c < samples && time_passed < time_limit; ++c)
|
||||
{
|
||||
LLTimer timer;
|
||||
timer.start();
|
||||
|
|
@ -1103,6 +1117,7 @@ F32 gpu_benchmark()
|
|||
glFinish();
|
||||
|
||||
F32 time = timer.getElapsedTimeF32();
|
||||
time_passed += time;
|
||||
|
||||
if (c >= 0) // <-- ignore the first sample as it tends to be artificially slow
|
||||
{
|
||||
|
|
@ -1117,12 +1132,12 @@ F32 gpu_benchmark()
|
|||
|
||||
F32 gbps = results[results.size()/2];
|
||||
|
||||
LL_INFOS() << "Memory bandwidth is " << llformat("%.3f", gbps) << "GB/sec according to CPU timers" << LL_ENDL;
|
||||
|
||||
LL_INFOS("Benchmark") << "Memory bandwidth is " << llformat("%.3f", gbps) << "GB/sec according to CPU timers, " << (F32)results.size() << " tests took " << time_passed << " seconds" << LL_ENDL;
|
||||
|
||||
#if LL_DARWIN
|
||||
if (gbps > 512.f)
|
||||
{
|
||||
LL_WARNS() << "Memory bandwidth is improbably high and likely incorrect; discarding result." << LL_ENDL;
|
||||
LL_WARNS("Benchmark") << "Memory bandwidth is improbably high and likely incorrect; discarding result." << LL_ENDL;
|
||||
//OSX is probably lying, discard result
|
||||
return -1.f;
|
||||
}
|
||||
|
|
@ -1131,11 +1146,11 @@ F32 gpu_benchmark()
|
|||
F32 ms = gBenchmarkProgram.mTimeElapsed/1000000.f;
|
||||
F32 seconds = ms/1000.f;
|
||||
|
||||
F64 samples_drawn = res*res*count*samples;
|
||||
F64 samples_drawn = res*res*count*results.size();
|
||||
F32 samples_sec = (samples_drawn/1000000000.0)/seconds;
|
||||
gbps = samples_sec*8;
|
||||
|
||||
LL_INFOS() << "Memory bandwidth is " << llformat("%.3f", gbps) << "GB/sec according to ARB_timer_query" << LL_ENDL;
|
||||
LL_INFOS("Benchmark") << "Memory bandwidth is " << llformat("%.3f", gbps) << "GB/sec according to ARB_timer_query, total time " << seconds << " seconds" << LL_ENDL;
|
||||
|
||||
return gbps;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2137,6 +2137,7 @@ void LLGroupMgr::sendCapGroupMembersRequest(const LLUUID& group_id)
|
|||
static U32 lastGroupMemberRequestFrame = 0;
|
||||
|
||||
// Have we requested the information already this frame?
|
||||
// Todo: make this per group, we can invite to one group and simultaneously be checking another one
|
||||
if ((lastGroupMemberRequestFrame == gFrameCount) || (mMemberRequestInFlight))
|
||||
return;
|
||||
|
||||
|
|
@ -2166,6 +2167,9 @@ void LLGroupMgr::sendCapGroupMembersRequest(const LLUUID& group_id)
|
|||
return;
|
||||
}
|
||||
|
||||
LLGroupMgrGroupData* group_datap = createGroupData(group_id); //make sure group exists
|
||||
group_datap->mMemberRequestID.generate(); // mark as pending
|
||||
|
||||
lastGroupMemberRequestFrame = gFrameCount;
|
||||
|
||||
LLCoros::instance().launch("LLGroupMgr::groupMembersRequestCoro",
|
||||
|
|
|
|||
|
|
@ -258,6 +258,11 @@ public:
|
|||
bool isRoleMemberDataComplete() { return mRoleMemberDataComplete; }
|
||||
bool isGroupPropertiesDataComplete() { return mGroupPropertiesDataComplete; }
|
||||
|
||||
bool isMemberDataPending() { return mMemberRequestID.notNull(); }
|
||||
bool isRoleDataPending() { return mRoleDataRequestID.notNull(); }
|
||||
bool isRoleMemberDataPending() { return (mRoleMembersRequestID.notNull() || mPendingRoleMemberRequest); }
|
||||
bool isGroupTitlePending() { return mTitlesRequestID.notNull(); }
|
||||
|
||||
bool isSingleMemberNotOwner();
|
||||
|
||||
F32 getAccessTime() const { return mAccessTime; }
|
||||
|
|
|
|||
|
|
@ -1399,13 +1399,6 @@ LLInvFVBridge* LLInvFVBridge::createBridge(LLAssetType::EType asset_type,
|
|||
// Only should happen for broken links.
|
||||
new_listener = new LLLinkItemBridge(inventory, root, uuid);
|
||||
break;
|
||||
case LLAssetType::AT_MESH:
|
||||
if(!(inv_type == LLInventoryType::IT_MESH))
|
||||
{
|
||||
LL_WARNS() << LLAssetType::lookup(asset_type) << " asset has inventory type " << LLInventoryType::lookupHumanReadable(inv_type) << " on uuid " << uuid << LL_ENDL;
|
||||
}
|
||||
new_listener = new LLMeshBridge(inventory, root, uuid);
|
||||
break;
|
||||
case LLAssetType::AT_UNKNOWN:
|
||||
new_listener = new LLUnknownItemBridge(inventory, root, uuid);
|
||||
break;
|
||||
|
|
@ -2101,7 +2094,9 @@ BOOL LLItemBridge::isItemCopyable() const
|
|||
LLViewerInventoryItem* item = getItem();
|
||||
if (item)
|
||||
{
|
||||
// Can't copy worn objects. DEV-15183
|
||||
// Can't copy worn objects.
|
||||
// Worn objects are tied to their inworld conterparts
|
||||
// Copy of modified worn object will return object with obsolete asset and inventory
|
||||
if(get_is_item_worn(mUUID))
|
||||
{
|
||||
return FALSE;
|
||||
|
|
@ -6830,58 +6825,6 @@ void LLLinkItemBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
|
|||
hide_context_entries(menu, items, disabled_items);
|
||||
}
|
||||
|
||||
// +=================================================+
|
||||
// | LLMeshBridge |
|
||||
// +=================================================+
|
||||
|
||||
LLUIImagePtr LLMeshBridge::getIcon() const
|
||||
{
|
||||
return LLInventoryIcon::getIcon(LLAssetType::AT_MESH, LLInventoryType::IT_MESH, 0, FALSE);
|
||||
}
|
||||
|
||||
void LLMeshBridge::openItem()
|
||||
{
|
||||
LLViewerInventoryItem* item = getItem();
|
||||
|
||||
if (item)
|
||||
{
|
||||
// open mesh
|
||||
}
|
||||
}
|
||||
|
||||
void LLMeshBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
|
||||
{
|
||||
LL_DEBUGS() << "LLMeshBridge::buildContextMenu()" << LL_ENDL;
|
||||
std::vector<std::string> items;
|
||||
std::vector<std::string> disabled_items;
|
||||
|
||||
if(isItemInTrash())
|
||||
{
|
||||
items.push_back(std::string("Purge Item"));
|
||||
if (!isItemRemovable())
|
||||
{
|
||||
disabled_items.push_back(std::string("Purge Item"));
|
||||
}
|
||||
|
||||
items.push_back(std::string("Restore Item"));
|
||||
}
|
||||
else if (isMarketplaceListingsFolder())
|
||||
{
|
||||
addMarketplaceContextMenuOptions(flags, items, disabled_items);
|
||||
items.push_back(std::string("Properties"));
|
||||
getClipboardEntries(false, items, disabled_items, flags);
|
||||
}
|
||||
else
|
||||
{
|
||||
items.push_back(std::string("Properties"));
|
||||
|
||||
getClipboardEntries(true, items, disabled_items, flags);
|
||||
}
|
||||
|
||||
addLinkReplaceMenuOption(items, disabled_items);
|
||||
hide_context_entries(menu, items, disabled_items);
|
||||
}
|
||||
|
||||
|
||||
// +=================================================+
|
||||
// | LLLinkBridge |
|
||||
|
|
@ -7358,8 +7301,7 @@ bool LLFolderViewGroupedItemBridge::canWearSelected(uuid_vec_t item_ids)
|
|||
for (uuid_vec_t::const_iterator it = item_ids.begin(); it != item_ids.end(); ++it)
|
||||
{
|
||||
LLViewerInventoryItem* item = gInventory.getItem(*it);
|
||||
LLAssetType::EType asset_type = item->getType();
|
||||
if (!item || (asset_type >= LLAssetType::AT_COUNT) || (asset_type <= LLAssetType::AT_NONE))
|
||||
if (!item || (item->getType() >= LLAssetType::AT_COUNT) || (item->getType() <= LLAssetType::AT_NONE))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -603,23 +603,6 @@ protected:
|
|||
static std::string sPrefix;
|
||||
};
|
||||
|
||||
|
||||
class LLMeshBridge : public LLItemBridge
|
||||
{
|
||||
friend class LLInvFVBridge;
|
||||
public:
|
||||
virtual LLUIImagePtr getIcon() const;
|
||||
virtual void openItem();
|
||||
virtual void buildContextMenu(LLMenuGL& menu, U32 flags);
|
||||
|
||||
protected:
|
||||
LLMeshBridge(LLInventoryPanel* inventory,
|
||||
LLFolderView* root,
|
||||
const LLUUID& uuid) :
|
||||
LLItemBridge(inventory, root, uuid) {}
|
||||
};
|
||||
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// Class LLInvFVBridgeAction
|
||||
//
|
||||
|
|
@ -650,17 +633,6 @@ protected:
|
|||
LLInventoryModel* mModel;
|
||||
};
|
||||
|
||||
class LLMeshBridgeAction: public LLInvFVBridgeAction
|
||||
{
|
||||
friend class LLInvFVBridgeAction;
|
||||
public:
|
||||
virtual void doIt() ;
|
||||
virtual ~LLMeshBridgeAction(){}
|
||||
protected:
|
||||
LLMeshBridgeAction(const LLUUID& id,LLInventoryModel* model):LLInvFVBridgeAction(id,model){}
|
||||
|
||||
};
|
||||
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// Recent Inventory Panel related classes
|
||||
|
|
|
|||
|
|
@ -58,6 +58,7 @@ LLInventoryFilter::FilterOps::FilterOps(const Params& p)
|
|||
mHoursAgo(p.hours_ago),
|
||||
mDateSearchDirection(p.date_search_direction),
|
||||
mShowFolderState(p.show_folder_state),
|
||||
mFilterCreatorType(p.creator_type),
|
||||
mPermissions(p.permissions),
|
||||
mFilterTypes(p.types),
|
||||
mFilterUUID(p.uuid),
|
||||
|
|
@ -78,8 +79,7 @@ LLInventoryFilter::LLInventoryFilter(const Params& p)
|
|||
mCurrentGeneration(0),
|
||||
mFirstRequiredGeneration(0),
|
||||
mFirstSuccessGeneration(0),
|
||||
mSearchType(SEARCHTYPE_NAME),
|
||||
mFilterCreatorType(FILTERCREATOR_ALL)
|
||||
mSearchType(SEARCHTYPE_NAME)
|
||||
{
|
||||
// copy mFilterOps into mDefaultFilterOps
|
||||
markDefault();
|
||||
|
|
@ -489,7 +489,7 @@ bool LLInventoryFilter::checkAgainstCreator(const LLFolderViewModelItemInventory
|
|||
{
|
||||
if (!listener) return TRUE;
|
||||
const BOOL is_folder = listener->getInventoryType() == LLInventoryType::IT_CATEGORY;
|
||||
switch(mFilterCreatorType)
|
||||
switch (mFilterOps.mFilterCreatorType)
|
||||
{
|
||||
case FILTERCREATOR_SELF:
|
||||
if(is_folder) return FALSE;
|
||||
|
|
@ -601,9 +601,9 @@ void LLInventoryFilter::setSearchType(ESearchType type)
|
|||
|
||||
void LLInventoryFilter::setFilterCreator(EFilterCreatorType type)
|
||||
{
|
||||
if(mFilterCreatorType != type)
|
||||
if (mFilterOps.mFilterCreatorType != type)
|
||||
{
|
||||
mFilterCreatorType = type;
|
||||
mFilterOps.mFilterCreatorType = type;
|
||||
setModified();
|
||||
}
|
||||
}
|
||||
|
|
@ -1194,6 +1194,7 @@ void LLInventoryFilter::toParams(Params& params) const
|
|||
params.filter_ops.hours_ago = getHoursAgo();
|
||||
params.filter_ops.date_search_direction = getDateSearchDirection();
|
||||
params.filter_ops.show_folder_state = getShowFolderState();
|
||||
params.filter_ops.creator_type = getFilterCreatorType();
|
||||
params.filter_ops.permissions = getFilterPermissions();
|
||||
params.substring = getFilterSubString();
|
||||
params.since_logoff = isSinceLogoff();
|
||||
|
|
@ -1216,6 +1217,7 @@ void LLInventoryFilter::fromParams(const Params& params)
|
|||
setHoursAgo(params.filter_ops.hours_ago);
|
||||
setDateSearchDirection(params.filter_ops.date_search_direction);
|
||||
setShowFolderState(params.filter_ops.show_folder_state);
|
||||
setFilterCreator(params.filter_ops.creator_type);
|
||||
setFilterPermissions(params.filter_ops.permissions);
|
||||
setFilterSubString(params.substring);
|
||||
setDateRangeLastLogoff(params.since_logoff);
|
||||
|
|
@ -1278,6 +1280,11 @@ LLInventoryFilter::EFolderShow LLInventoryFilter::getShowFolderState() const
|
|||
return mFilterOps.mShowFolderState;
|
||||
}
|
||||
|
||||
LLInventoryFilter::EFilterCreatorType LLInventoryFilter::getFilterCreatorType() const
|
||||
{
|
||||
return mFilterOps.mFilterCreatorType;
|
||||
}
|
||||
|
||||
bool LLInventoryFilter::isTimedOut()
|
||||
{
|
||||
return mFilterTime.hasExpired();
|
||||
|
|
|
|||
|
|
@ -126,6 +126,7 @@ public:
|
|||
Optional<U32> date_search_direction;
|
||||
Optional<EFolderShow> show_folder_state;
|
||||
Optional<PermissionMask> permissions;
|
||||
Optional<EFilterCreatorType> creator_type;
|
||||
|
||||
Params()
|
||||
: types("filter_types", FILTERTYPE_OBJECT),
|
||||
|
|
@ -138,6 +139,7 @@ public:
|
|||
hours_ago("hours_ago", 0),
|
||||
date_search_direction("date_search_direction", FILTERDATEDIRECTION_NEWER),
|
||||
show_folder_state("show_folder_state", SHOW_NON_EMPTY_FOLDERS),
|
||||
creator_type("creator_type", FILTERCREATOR_ALL),
|
||||
permissions("permissions", PERM_NONE)
|
||||
{}
|
||||
};
|
||||
|
|
@ -156,8 +158,9 @@ public:
|
|||
U32 mHoursAgo;
|
||||
U32 mDateSearchDirection;
|
||||
|
||||
EFolderShow mShowFolderState;
|
||||
PermissionMask mPermissions;
|
||||
EFolderShow mShowFolderState;
|
||||
PermissionMask mPermissions;
|
||||
EFilterCreatorType mFilterCreatorType;
|
||||
};
|
||||
|
||||
struct Params : public LLInitParam::Block<Params>
|
||||
|
|
@ -202,7 +205,6 @@ public:
|
|||
void setSearchType(ESearchType type);
|
||||
ESearchType getSearchType() { return mSearchType; }
|
||||
void setFilterCreator(EFilterCreatorType type);
|
||||
EFilterCreatorType getFilterCreator() { return mFilterCreatorType; }
|
||||
|
||||
void setFilterSubString(const std::string& string);
|
||||
const std::string& getFilterSubString(BOOL trim = FALSE) const;
|
||||
|
|
@ -243,8 +245,9 @@ public:
|
|||
// +-------------------------------------------------------------------+
|
||||
// + Presentation
|
||||
// +-------------------------------------------------------------------+
|
||||
void setShowFolderState( EFolderShow state);
|
||||
EFolderShow getShowFolderState() const;
|
||||
void setShowFolderState( EFolderShow state);
|
||||
EFolderShow getShowFolderState() const;
|
||||
EFilterCreatorType getFilterCreatorType() const;
|
||||
|
||||
void setEmptyLookupMessage(const std::string& message);
|
||||
std::string getEmptyLookupMessage() const;
|
||||
|
|
@ -324,7 +327,6 @@ private:
|
|||
std::string mEmptyLookupMessage;
|
||||
|
||||
ESearchType mSearchType;
|
||||
EFilterCreatorType mFilterCreatorType;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -888,14 +888,6 @@ U32 LLInventoryModel::updateItem(const LLViewerInventoryItem* item, U32 mask)
|
|||
return mask;
|
||||
}
|
||||
|
||||
// We're hiding mesh types
|
||||
#if 0
|
||||
if (item->getType() == LLAssetType::AT_MESH)
|
||||
{
|
||||
return mask;
|
||||
}
|
||||
#endif
|
||||
|
||||
LLPointer<LLViewerInventoryItem> old_item = getItem(item->getUUID());
|
||||
LLPointer<LLViewerInventoryItem> new_item;
|
||||
if(old_item)
|
||||
|
|
|
|||
|
|
@ -65,11 +65,11 @@ public:
|
|||
|
||||
S32 LLMachineID::init()
|
||||
{
|
||||
memset(static_unique_id,0,sizeof(static_unique_id));
|
||||
size_t len = sizeof(static_unique_id);
|
||||
memset(static_unique_id, 0, len);
|
||||
S32 ret_code = 0;
|
||||
#if LL_WINDOWS
|
||||
# pragma comment(lib, "wbemuuid.lib")
|
||||
size_t len = sizeof(static_unique_id);
|
||||
|
||||
// algorithm to detect BIOS serial number found at:
|
||||
// http://msdn.microsoft.com/en-us/library/aa394077%28VS.85%29.aspx
|
||||
|
|
@ -217,17 +217,27 @@ S32 LLMachineID::init()
|
|||
|
||||
// Get the value of the Name property
|
||||
hr = pclsObj->Get(L"SerialNumber", 0, &vtProp, 0, 0);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
LL_WARNS() << "Failed to get SerialNumber. Error code = 0x" << hex << hres << LL_ENDL;
|
||||
pclsObj->Release();
|
||||
pclsObj = NULL;
|
||||
continue;
|
||||
}
|
||||
LL_INFOS("AppInit") << " Serial Number : " << vtProp.bstrVal << LL_ENDL;
|
||||
|
||||
// use characters in the returned Serial Number to create a byte array of size len
|
||||
BSTR serialNumber ( vtProp.bstrVal);
|
||||
unsigned int serial_size = SysStringLen(serialNumber);
|
||||
unsigned int j = 0;
|
||||
while( vtProp.bstrVal[j] != 0)
|
||||
|
||||
while (j < serial_size && vtProp.bstrVal[j] != 0)
|
||||
{
|
||||
for (unsigned int i = 0; i < len; i++)
|
||||
{
|
||||
if (vtProp.bstrVal[j] == 0)
|
||||
if (j >= serial_size || vtProp.bstrVal[j] == 0)
|
||||
break;
|
||||
|
||||
|
||||
static_unique_id[i] = (unsigned int)(static_unique_id[i] + serialNumber[j]);
|
||||
j++;
|
||||
}
|
||||
|
|
@ -254,6 +264,21 @@ S32 LLMachineID::init()
|
|||
ret_code = LLUUID::getNodeID(staticPtr);
|
||||
#endif
|
||||
has_static_unique_id = true;
|
||||
|
||||
LL_INFOS("AppInit") << "UniqueID: 0x";
|
||||
// Code between here and LL_ENDL is not executed unless the LL_DEBUGS
|
||||
// actually produces output
|
||||
for (size_t i = 0; i < len; ++i)
|
||||
{
|
||||
// Copy each char to unsigned int to hexify. Sending an unsigned
|
||||
// char to a std::ostream tries to represent it as a char, not
|
||||
// what we want here.
|
||||
unsigned byte = static_unique_id[i];
|
||||
LL_CONT << std::hex << std::setw(2) << std::setfill('0') << byte;
|
||||
}
|
||||
// Reset default output formatting to avoid nasty surprises!
|
||||
LL_CONT << std::dec << std::setw(0) << std::setfill(' ') << LL_ENDL;
|
||||
|
||||
return ret_code;
|
||||
}
|
||||
|
||||
|
|
@ -263,19 +288,6 @@ S32 LLMachineID::getUniqueID(unsigned char *unique_id, size_t len)
|
|||
if (has_static_unique_id)
|
||||
{
|
||||
memcpy ( unique_id, &static_unique_id, len);
|
||||
LL_INFOS_ONCE("AppInit") << "UniqueID: 0x";
|
||||
// Code between here and LL_ENDL is not executed unless the LL_DEBUGS
|
||||
// actually produces output
|
||||
for (size_t i = 0; i < len; ++i)
|
||||
{
|
||||
// Copy each char to unsigned int to hexify. Sending an unsigned
|
||||
// char to a std::ostream tries to represent it as a char, not
|
||||
// what we want here.
|
||||
unsigned byte = unique_id[i];
|
||||
LL_CONT << std::hex << std::setw(2) << std::setfill('0') << byte;
|
||||
}
|
||||
// Reset default output formatting to avoid nasty surprises!
|
||||
LL_CONT << std::dec << std::setw(0) << std::setfill(' ') << LL_ENDL;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@
|
|||
#include "llcachename.h"
|
||||
#include "llfloater.h"
|
||||
#include "llfloaterreg.h"
|
||||
#include "llfloatersnapshot.h" // gSnapshotFloaterView
|
||||
#include "llinventory.h"
|
||||
#include "llscrolllistitem.h"
|
||||
#include "llscrolllistcell.h"
|
||||
|
|
@ -236,24 +237,30 @@ BOOL LLNameListCtrl::handleToolTip(S32 x, S32 y, MASK mask)
|
|||
|
||||
// Spawn at right side of cell
|
||||
LLPointer<LLUIImage> icon = LLUI::getUIImage("Info_Small");
|
||||
LLCoordGL pos( sticky_rect.mRight - info_icon_size, sticky_rect.mTop - (sticky_rect.getHeight() - icon->getHeight())/2 );
|
||||
S32 screenX = sticky_rect.mRight - info_icon_size;
|
||||
S32 screenY = sticky_rect.mTop - (sticky_rect.getHeight() - icon->getHeight()) / 2;
|
||||
LLCoordGL pos(screenX, screenY);
|
||||
|
||||
// Should we show a group or an avatar inspector?
|
||||
bool is_group = hit_item->isGroup();
|
||||
bool is_experience = hit_item->isExperience();
|
||||
LLFloater* snapshot_floatr = gSnapshotFloaterView->getFrontmostClosableFloater();
|
||||
if (!snapshot_floatr || !snapshot_floatr->getRect().pointInRect(screenX + icon->getWidth(), screenY))
|
||||
{
|
||||
// Should we show a group or an avatar inspector?
|
||||
bool is_group = hit_item->isGroup();
|
||||
bool is_experience = hit_item->isExperience();
|
||||
|
||||
LLToolTip::Params params;
|
||||
params.background_visible( false );
|
||||
params.click_callback( boost::bind(&LLNameListCtrl::showInspector, this, avatar_id, is_group, is_experience) );
|
||||
params.delay_time(0.0f); // spawn instantly on hover
|
||||
params.image( icon );
|
||||
params.message("");
|
||||
params.padding(0);
|
||||
params.pos(pos);
|
||||
params.sticky_rect(sticky_rect);
|
||||
LLToolTip::Params params;
|
||||
params.background_visible(false);
|
||||
params.click_callback(boost::bind(&LLNameListCtrl::showInspector, this, avatar_id, is_group, is_experience));
|
||||
params.delay_time(0.0f); // spawn instantly on hover
|
||||
params.image(icon);
|
||||
params.message("");
|
||||
params.padding(0);
|
||||
params.pos(pos);
|
||||
params.sticky_rect(sticky_rect);
|
||||
|
||||
LLToolTipMgr::getInstance()->show(params);
|
||||
handled = TRUE;
|
||||
LLToolTipMgr::getInstance()->show(params);
|
||||
handled = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,7 +35,6 @@
|
|||
#include "llnotificationmanager.h"
|
||||
#include "llnotifications.h"
|
||||
#include "llscriptfloater.h"
|
||||
#include "llfacebookconnect.h"
|
||||
#include "llavatarname.h"
|
||||
#include "llavatarnamecache.h"
|
||||
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ BOOL LLPanelExperiencePicker::postBuild()
|
|||
childSetAction(BTN_PROFILE, boost::bind(&LLPanelExperiencePicker::onBtnProfile, this));
|
||||
getChildView(BTN_PROFILE)->setEnabled(FALSE);
|
||||
|
||||
getChild<LLComboBox>(TEXT_MATURITY)->setCurrentByIndex(2);
|
||||
getChild<LLComboBox>(TEXT_MATURITY)->setCurrentByIndex(gSavedPerAccountSettings.getU32("ExperienceSearchMaturity"));
|
||||
getChild<LLComboBox>(TEXT_MATURITY)->setCommitCallback(boost::bind(&LLPanelExperiencePicker::onMaturity, this));
|
||||
getChild<LLUICtrl>(TEXT_EDIT)->setFocus(TRUE);
|
||||
|
||||
|
|
@ -381,6 +381,7 @@ void LLPanelExperiencePicker::filterContent()
|
|||
|
||||
void LLPanelExperiencePicker::onMaturity()
|
||||
{
|
||||
gSavedPerAccountSettings.setU32("ExperienceSearchMaturity", getChild<LLComboBox>(TEXT_MATURITY)->getCurrentIndex());
|
||||
if(mResponse.has("experience_keys") && mResponse["experience_keys"].beginArray() != mResponse["experience_keys"].endArray())
|
||||
{
|
||||
filterContent();
|
||||
|
|
|
|||
|
|
@ -606,11 +606,30 @@ void LLPanelGroupInvite::updateLists()
|
|||
{
|
||||
if (!mPendingUpdate)
|
||||
{
|
||||
// Note: this will partially fail if some requests are already in progress
|
||||
LLGroupMgr::getInstance()->sendGroupPropertiesRequest(mImplementation->mGroupID);
|
||||
LLGroupMgr::getInstance()->sendGroupRoleDataRequest(mImplementation->mGroupID);
|
||||
LLGroupMgr::getInstance()->sendGroupRoleMembersRequest(mImplementation->mGroupID);
|
||||
LLGroupMgr::getInstance()->sendCapGroupMembersRequest(mImplementation->mGroupID);
|
||||
}
|
||||
else if (gdatap)
|
||||
{
|
||||
// restart requests that were interrupted/dropped/failed to start
|
||||
if (!gdatap->isRoleDataPending() && !gdatap->isRoleDataComplete())
|
||||
{
|
||||
LLGroupMgr::getInstance()->sendGroupRoleDataRequest(mImplementation->mGroupID);
|
||||
}
|
||||
if (!gdatap->isRoleMemberDataPending() && !gdatap->isRoleMemberDataComplete())
|
||||
{
|
||||
LLGroupMgr::getInstance()->sendGroupRoleMembersRequest(mImplementation->mGroupID);
|
||||
}
|
||||
// sendCapGroupMembersRequest has a per frame send limitation that could have
|
||||
// interrupted previous request
|
||||
if (!gdatap->isMemberDataPending() && !gdatap->isMemberDataComplete())
|
||||
{
|
||||
LLGroupMgr::getInstance()->sendCapGroupMembersRequest(mImplementation->mGroupID);
|
||||
}
|
||||
}
|
||||
mPendingUpdate = TRUE;
|
||||
}
|
||||
else
|
||||
|
|
|
|||
|
|
@ -1962,6 +1962,7 @@ LLPanelGroupRolesSubTab::LLPanelGroupRolesSubTab()
|
|||
mRoleDescription(NULL),
|
||||
mMemberVisibleCheck(NULL),
|
||||
mDeleteRoleButton(NULL),
|
||||
mCopyRoleButton(NULL),
|
||||
mCreateRoleButton(NULL),
|
||||
mFirstOpen(TRUE),
|
||||
mHasRoleChange(FALSE)
|
||||
|
|
@ -2012,6 +2013,14 @@ BOOL LLPanelGroupRolesSubTab::postBuildSubTab(LLView* root)
|
|||
mCreateRoleButton->setClickedCallback(onCreateRole, this);
|
||||
mCreateRoleButton->setEnabled(FALSE);
|
||||
}
|
||||
|
||||
mCopyRoleButton =
|
||||
parent->getChild<LLButton>("role_copy", recurse);
|
||||
if ( mCopyRoleButton )
|
||||
{
|
||||
mCopyRoleButton->setClickedCallback(onCopyRole, this);
|
||||
mCopyRoleButton->setEnabled(FALSE);
|
||||
}
|
||||
|
||||
mDeleteRoleButton =
|
||||
parent->getChild<LLButton>("role_delete", recurse);
|
||||
|
|
@ -2226,6 +2235,7 @@ void LLPanelGroupRolesSubTab::update(LLGroupChange gc)
|
|||
mRoleTitle->clear();
|
||||
setFooterEnabled(FALSE);
|
||||
mDeleteRoleButton->setEnabled(FALSE);
|
||||
mCopyRoleButton->setEnabled(FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2336,6 +2346,7 @@ void LLPanelGroupRolesSubTab::handleRoleSelect()
|
|||
mSelectedRole = item->getUUID();
|
||||
buildMembersList();
|
||||
|
||||
mCopyRoleButton->setEnabled(gAgent.hasPowerInGroup(mGroupID, GP_ROLE_CREATE));
|
||||
can_delete = can_delete && gAgent.hasPowerInGroup(mGroupID,
|
||||
GP_ROLE_DELETE);
|
||||
mDeleteRoleButton->setEnabled(can_delete);
|
||||
|
|
@ -2661,6 +2672,57 @@ void LLPanelGroupRolesSubTab::handleCreateRole()
|
|||
notifyObservers();
|
||||
}
|
||||
|
||||
// static
|
||||
void LLPanelGroupRolesSubTab::onCopyRole(void* user_data)
|
||||
{
|
||||
LLPanelGroupRolesSubTab* self = static_cast<LLPanelGroupRolesSubTab*>(user_data);
|
||||
if (!self) return;
|
||||
|
||||
self->handleCopyRole();
|
||||
}
|
||||
|
||||
void LLPanelGroupRolesSubTab::handleCopyRole()
|
||||
{
|
||||
LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mGroupID);
|
||||
|
||||
if (!gdatap) return;
|
||||
|
||||
LLScrollListItem* role_item = mRolesList->getFirstSelected();
|
||||
if (!role_item || role_item->getUUID().isNull())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
LLRoleData rd;
|
||||
if (!gdatap->getRoleData(role_item->getUUID(), rd))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
LLUUID new_role_id;
|
||||
new_role_id.generate();
|
||||
rd.mRoleName += "(Copy)";
|
||||
gdatap->createRole(new_role_id,rd);
|
||||
|
||||
mRolesList->deselectAllItems(TRUE);
|
||||
LLSD row;
|
||||
row["id"] = new_role_id;
|
||||
row["columns"][0]["column"] = "name";
|
||||
row["columns"][0]["value"] = rd.mRoleName;
|
||||
mRolesList->addElement(row, ADD_BOTTOM, this);
|
||||
mRolesList->selectByID(new_role_id);
|
||||
|
||||
// put focus on name field and select its contents
|
||||
if(mRoleName)
|
||||
{
|
||||
mRoleName->setFocus(TRUE);
|
||||
mRoleName->onTabInto();
|
||||
gFocusMgr.triggerFocusFlash();
|
||||
}
|
||||
|
||||
notifyObservers();
|
||||
}
|
||||
|
||||
// static
|
||||
void LLPanelGroupRolesSubTab::onDeleteRole(void* user_data)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -269,6 +269,9 @@ public:
|
|||
static void onCreateRole(void*);
|
||||
void handleCreateRole();
|
||||
|
||||
static void onCopyRole(void*);
|
||||
void handleCopyRole();
|
||||
|
||||
static void onDeleteRole(void*);
|
||||
void handleDeleteRole();
|
||||
|
||||
|
|
@ -296,6 +299,7 @@ protected:
|
|||
LLCheckBoxCtrl* mMemberVisibleCheck;
|
||||
LLButton* mDeleteRoleButton;
|
||||
LLButton* mCreateRoleButton;
|
||||
LLButton* mCopyRoleButton;
|
||||
|
||||
LLUUID mSelectedRole;
|
||||
BOOL mHasRoleChange;
|
||||
|
|
|
|||
|
|
@ -178,7 +178,7 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect,
|
|||
|
||||
mPasswordModified = FALSE;
|
||||
|
||||
LLPanelLogin::sInstance = this;
|
||||
sInstance = this;
|
||||
|
||||
LLView* login_holder = gViewerWindow->getLoginPanelHolder();
|
||||
if (login_holder)
|
||||
|
|
@ -234,29 +234,44 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect,
|
|||
server_choice_combo->add(LLGridManager::getInstance()->getGridLabel(),
|
||||
current_grid,
|
||||
ADD_TOP);
|
||||
server_choice_combo->selectFirstItem();
|
||||
server_choice_combo->selectFirstItem();
|
||||
|
||||
LLSLURL start_slurl(LLStartUp::getStartSLURL());
|
||||
// The StartSLURL might have been set either by an explicit command-line
|
||||
// argument (CmdLineLoginLocation) or by default.
|
||||
// current_grid might have been set either by an explicit command-line
|
||||
// argument (CmdLineGridChoice) or by default.
|
||||
// If the grid specified by StartSLURL is the same as current_grid, the
|
||||
// distinction is moot.
|
||||
// If we have an explicit command-line SLURL, use that.
|
||||
// If we DON'T have an explicit command-line SLURL but we DO have an
|
||||
// explicit command-line grid, which is different from the default SLURL's
|
||||
// -- do NOT override the explicit command-line grid with the grid from
|
||||
// the default SLURL!
|
||||
bool force_grid{ start_slurl.getGrid() != current_grid &&
|
||||
gSavedSettings.getString("CmdLineLoginLocation").empty() &&
|
||||
! gSavedSettings.getString("CmdLineGridChoice").empty() };
|
||||
if ( !start_slurl.isSpatial() ) // has a start been established by the command line or NextLoginLocation ?
|
||||
{
|
||||
// no, so get the preference setting
|
||||
std::string defaultStartLocation = gSavedSettings.getString("LoginLocation");
|
||||
LL_INFOS("AppInit")<<"default LoginLocation '"<<defaultStartLocation<<"'"<<LL_ENDL;
|
||||
LLSLURL defaultStart(defaultStartLocation);
|
||||
if ( defaultStart.isSpatial() )
|
||||
if ( defaultStart.isSpatial() && ! force_grid )
|
||||
{
|
||||
LLStartUp::setStartSLURL(defaultStart);
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_INFOS("AppInit")<<"no valid LoginLocation, using home"<<LL_ENDL;
|
||||
LL_INFOS("AppInit") << (force_grid? "--grid specified" : "no valid LoginLocation")
|
||||
<< ", using home" << LL_ENDL;
|
||||
LLSLURL homeStart(LLSLURL::SIM_LOCATION_HOME);
|
||||
LLStartUp::setStartSLURL(homeStart);
|
||||
}
|
||||
}
|
||||
else
|
||||
else if (! force_grid)
|
||||
{
|
||||
LLPanelLogin::onUpdateStartSLURL(start_slurl); // updates grid if needed
|
||||
onUpdateStartSLURL(start_slurl); // updates grid if needed
|
||||
}
|
||||
|
||||
childSetAction("connect_btn", onClickConnect, this);
|
||||
|
|
@ -380,7 +395,7 @@ void LLPanelLogin::setFocus(BOOL b)
|
|||
{
|
||||
if(b)
|
||||
{
|
||||
LLPanelLogin::giveFocus();
|
||||
giveFocus();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -748,7 +763,10 @@ void LLPanelLogin::closePanel()
|
|||
{
|
||||
if (sInstance)
|
||||
{
|
||||
LLPanelLogin::sInstance->getParent()->removeChild( LLPanelLogin::sInstance );
|
||||
if (LLPanelLogin::sInstance->getParent())
|
||||
{
|
||||
LLPanelLogin::sInstance->getParent()->removeChild(LLPanelLogin::sInstance);
|
||||
}
|
||||
|
||||
delete sInstance;
|
||||
sInstance = NULL;
|
||||
|
|
|
|||
|
|
@ -885,7 +885,7 @@ void LLFloaterInventoryFinder::updateElementsFromFilter()
|
|||
U32 hours = mFilter->getHoursAgo();
|
||||
U32 date_search_direction = mFilter->getDateSearchDirection();
|
||||
|
||||
LLInventoryFilter::EFilterCreatorType filter_creator = mFilter->getFilterCreator();
|
||||
LLInventoryFilter::EFilterCreatorType filter_creator = mFilter->getFilterCreatorType();
|
||||
bool show_created_by_me = ((filter_creator == LLInventoryFilter::FILTERCREATOR_ALL) || (filter_creator == LLInventoryFilter::FILTERCREATOR_SELF));
|
||||
bool show_created_by_others = ((filter_creator == LLInventoryFilter::FILTERCREATOR_ALL) || (filter_creator == LLInventoryFilter::FILTERCREATOR_OTHERS));
|
||||
|
||||
|
|
@ -898,7 +898,6 @@ void LLFloaterInventoryFinder::updateElementsFromFilter()
|
|||
getChild<LLUICtrl>("check_clothing")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_WEARABLE));
|
||||
getChild<LLUICtrl>("check_gesture")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_GESTURE));
|
||||
getChild<LLUICtrl>("check_landmark")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_LANDMARK));
|
||||
getChild<LLUICtrl>("check_mesh")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_MESH));
|
||||
getChild<LLUICtrl>("check_notecard")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_NOTECARD));
|
||||
getChild<LLUICtrl>("check_object")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_OBJECT));
|
||||
getChild<LLUICtrl>("check_script")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_LSL));
|
||||
|
|
@ -954,12 +953,6 @@ void LLFloaterInventoryFinder::draw()
|
|||
filtered_by_all_types = FALSE;
|
||||
}
|
||||
|
||||
if (!getChild<LLUICtrl>("check_mesh")->getValue())
|
||||
{
|
||||
filter &= ~(0x1 << LLInventoryType::IT_MESH);
|
||||
filtered_by_all_types = FALSE;
|
||||
}
|
||||
|
||||
if (!getChild<LLUICtrl>("check_notecard")->getValue())
|
||||
{
|
||||
filter &= ~(0x1 << LLInventoryType::IT_NOTECARD);
|
||||
|
|
@ -1108,7 +1101,6 @@ void LLFloaterInventoryFinder::selectAllTypes(void* user_data)
|
|||
self->getChild<LLUICtrl>("check_clothing")->setValue(TRUE);
|
||||
self->getChild<LLUICtrl>("check_gesture")->setValue(TRUE);
|
||||
self->getChild<LLUICtrl>("check_landmark")->setValue(TRUE);
|
||||
self->getChild<LLUICtrl>("check_mesh")->setValue(TRUE);
|
||||
self->getChild<LLUICtrl>("check_notecard")->setValue(TRUE);
|
||||
self->getChild<LLUICtrl>("check_object")->setValue(TRUE);
|
||||
self->getChild<LLUICtrl>("check_script")->setValue(TRUE);
|
||||
|
|
@ -1128,7 +1120,6 @@ void LLFloaterInventoryFinder::selectNoTypes(void* user_data)
|
|||
self->getChild<LLUICtrl>("check_clothing")->setValue(FALSE);
|
||||
self->getChild<LLUICtrl>("check_gesture")->setValue(FALSE);
|
||||
self->getChild<LLUICtrl>("check_landmark")->setValue(FALSE);
|
||||
self->getChild<LLUICtrl>("check_mesh")->setValue(FALSE);
|
||||
self->getChild<LLUICtrl>("check_notecard")->setValue(FALSE);
|
||||
self->getChild<LLUICtrl>("check_object")->setValue(FALSE);
|
||||
self->getChild<LLUICtrl>("check_script")->setValue(FALSE);
|
||||
|
|
|
|||
|
|
@ -1121,92 +1121,6 @@ LLUIImagePtr LLTaskWearableBridge::getIcon() const
|
|||
return LLInventoryIcon::getIcon(mAssetType, mInventoryType, mFlags, FALSE );
|
||||
}
|
||||
|
||||
///----------------------------------------------------------------------------
|
||||
/// Class LLTaskMeshBridge
|
||||
///----------------------------------------------------------------------------
|
||||
|
||||
class LLTaskMeshBridge : public LLTaskInvFVBridge
|
||||
{
|
||||
public:
|
||||
LLTaskMeshBridge(
|
||||
LLPanelObjectInventory* panel,
|
||||
const LLUUID& uuid,
|
||||
const std::string& name);
|
||||
|
||||
virtual LLUIImagePtr getIcon() const;
|
||||
virtual void openItem();
|
||||
virtual void performAction(LLInventoryModel* model, std::string action);
|
||||
virtual void buildContextMenu(LLMenuGL& menu, U32 flags);
|
||||
};
|
||||
|
||||
LLTaskMeshBridge::LLTaskMeshBridge(
|
||||
LLPanelObjectInventory* panel,
|
||||
const LLUUID& uuid,
|
||||
const std::string& name) :
|
||||
LLTaskInvFVBridge(panel, uuid, name)
|
||||
{
|
||||
}
|
||||
|
||||
LLUIImagePtr LLTaskMeshBridge::getIcon() const
|
||||
{
|
||||
return LLInventoryIcon::getIcon(LLAssetType::AT_MESH, LLInventoryType::IT_MESH, 0, FALSE);
|
||||
}
|
||||
|
||||
void LLTaskMeshBridge::openItem()
|
||||
{
|
||||
// open mesh
|
||||
}
|
||||
|
||||
|
||||
// virtual
|
||||
void LLTaskMeshBridge::performAction(LLInventoryModel* model, std::string action)
|
||||
{
|
||||
if (action == "mesh action")
|
||||
{
|
||||
LLInventoryItem* item = findItem();
|
||||
if(item)
|
||||
{
|
||||
// do action
|
||||
}
|
||||
}
|
||||
LLTaskInvFVBridge::performAction(model, action);
|
||||
}
|
||||
|
||||
void LLTaskMeshBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
|
||||
{
|
||||
LLInventoryItem* item = findItem();
|
||||
std::vector<std::string> items;
|
||||
std::vector<std::string> disabled_items;
|
||||
if(!item)
|
||||
{
|
||||
hide_context_entries(menu, items, disabled_items);
|
||||
return;
|
||||
}
|
||||
|
||||
items.push_back(std::string("Task Open"));
|
||||
if (!isItemCopyable())
|
||||
{
|
||||
disabled_items.push_back(std::string("Task Open"));
|
||||
}
|
||||
|
||||
items.push_back(std::string("Task Properties"));
|
||||
if ((flags & FIRST_SELECTED_ITEM) == 0)
|
||||
{
|
||||
disabled_items.push_back(std::string("Task Properties"));
|
||||
}
|
||||
if(isItemRenameable())
|
||||
{
|
||||
items.push_back(std::string("Task Rename"));
|
||||
}
|
||||
if(isItemRemovable())
|
||||
{
|
||||
items.push_back(std::string("Task Remove"));
|
||||
}
|
||||
|
||||
|
||||
hide_context_entries(menu, items, disabled_items);
|
||||
}
|
||||
|
||||
///----------------------------------------------------------------------------
|
||||
/// LLTaskInvFVBridge impl
|
||||
//----------------------------------------------------------------------------
|
||||
|
|
@ -1288,11 +1202,6 @@ LLTaskInvFVBridge* LLTaskInvFVBridge::createObjectBridge(LLPanelObjectInventory*
|
|||
object_id,
|
||||
object_name);
|
||||
break;
|
||||
case LLAssetType::AT_MESH:
|
||||
new_bridge = new LLTaskMeshBridge(panel,
|
||||
object_id,
|
||||
object_name);
|
||||
break;
|
||||
default:
|
||||
LL_INFOS() << "Unhandled inventory type (llassetstorage.h): "
|
||||
<< (S32)type << LL_ENDL;
|
||||
|
|
@ -1498,7 +1407,14 @@ void LLPanelObjectInventory::updateInventory()
|
|||
mIsInventoryEmpty = TRUE;
|
||||
}
|
||||
|
||||
mHaveInventory = TRUE;
|
||||
mHaveInventory = !mIsInventoryEmpty || !objectp->isInventoryDirty();
|
||||
if (objectp->isInventoryDirty())
|
||||
{
|
||||
// Inventory is dirty, yet we received inventoryChanged() callback.
|
||||
// User changed something during ongoing request.
|
||||
// Rerequest. It will clear dirty flag and won't create dupplicate requests.
|
||||
objectp->requestInventory();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -1768,7 +1684,7 @@ void LLPanelObjectInventory::deleteAllChildren()
|
|||
|
||||
BOOL LLPanelObjectInventory::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EDragAndDropType cargo_type, void *cargo_data, EAcceptance *accept, std::string& tooltip_msg)
|
||||
{
|
||||
if (mFolders && mHaveInventory)
|
||||
if (mFolders)
|
||||
{
|
||||
LLFolderViewItem* folderp = mFolders->getNextFromChild(NULL);
|
||||
if (!folderp)
|
||||
|
|
|
|||
|
|
@ -106,9 +106,9 @@ private:
|
|||
|
||||
LLUUID mTaskUUID;
|
||||
LLUUID mAttachmentUUID;
|
||||
BOOL mHaveInventory;
|
||||
BOOL mIsInventoryEmpty;
|
||||
BOOL mInventoryNeedsUpdate;
|
||||
BOOL mHaveInventory; // 'Loading' label and used for initial request
|
||||
BOOL mIsInventoryEmpty; // 'Empty' label
|
||||
BOOL mInventoryNeedsUpdate; // for idle, set on changed callback
|
||||
LLFolderViewModelInventory mInventoryViewModel;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -54,7 +54,6 @@
|
|||
#include "llcallingcard.h" // for LLAvatarTracker
|
||||
#include "llcallbacklist.h"
|
||||
#include "llerror.h"
|
||||
#include "llfacebookconnect.h"
|
||||
#include "llfloateravatarpicker.h"
|
||||
#include "llfriendcard.h"
|
||||
#include "llgroupactions.h"
|
||||
|
|
@ -537,7 +536,6 @@ public:
|
|||
|
||||
LLPanelPeople::LLPanelPeople()
|
||||
: LLPanel(),
|
||||
mTryToConnectToFacebook(true),
|
||||
mTabContainer(NULL),
|
||||
mOnlineFriendList(NULL),
|
||||
mAllFriendList(NULL),
|
||||
|
|
@ -645,11 +643,9 @@ BOOL LLPanelPeople::postBuild()
|
|||
// updater is active only if panel is visible to user.
|
||||
friends_tab->setVisibleCallback(boost::bind(&Updater::setActive, mFriendListUpdater, _2));
|
||||
friends_tab->setVisibleCallback(boost::bind(&LLPanelPeople::removePicker, this));
|
||||
friends_tab->setVisibleCallback(boost::bind(&LLPanelPeople::updateFacebookList, this, _2));
|
||||
|
||||
mOnlineFriendList = friends_tab->getChild<LLAvatarList>("avatars_online");
|
||||
mAllFriendList = friends_tab->getChild<LLAvatarList>("avatars_all");
|
||||
mSuggestedFriends = friends_tab->getChild<LLAvatarList>("suggested_friends");
|
||||
mOnlineFriendList->setNoItemsCommentText(getString("no_friends_online"));
|
||||
mOnlineFriendList->setShowIcons("FriendsListShowIcons");
|
||||
mOnlineFriendList->showPermissions("FriendsListShowPermissions");
|
||||
|
|
@ -685,7 +681,6 @@ BOOL LLPanelPeople::postBuild()
|
|||
mRecentList->setContextMenu(&LLPanelPeopleMenus::gPeopleContextMenu);
|
||||
mAllFriendList->setContextMenu(&LLPanelPeopleMenus::gPeopleContextMenu);
|
||||
mOnlineFriendList->setContextMenu(&LLPanelPeopleMenus::gPeopleContextMenu);
|
||||
mSuggestedFriends->setContextMenu(&LLPanelPeopleMenus::gSuggestedFriendsContextMenu);
|
||||
|
||||
setSortOrder(mRecentList, (ESortOrder)gSavedSettings.getU32("RecentPeopleSortOrder"), false);
|
||||
setSortOrder(mAllFriendList, (ESortOrder)gSavedSettings.getU32("FriendsSortOrder"), false);
|
||||
|
|
@ -764,7 +759,7 @@ void LLPanelPeople::updateFriendListHelpText()
|
|||
|
||||
// Seems sometimes all_friends can be empty because of issue with Inventory loading (clear cache, slow connection...)
|
||||
// So, lets check all lists to avoid overlapping the text with online list. See EXT-6448.
|
||||
bool any_friend_exists = mAllFriendList->filterHasMatches() || mOnlineFriendList->filterHasMatches() || mSuggestedFriends->filterHasMatches();
|
||||
bool any_friend_exists = mAllFriendList->filterHasMatches() || mOnlineFriendList->filterHasMatches();
|
||||
no_friends_text->setVisible(!any_friend_exists);
|
||||
if (no_friends_text->getVisible())
|
||||
{
|
||||
|
|
@ -831,40 +826,9 @@ void LLPanelPeople::updateFriendList()
|
|||
mAllFriendList->setDirty(true, !mAllFriendList->filterHasMatches());
|
||||
//update trash and other buttons according to a selected item
|
||||
updateButtons();
|
||||
updateSuggestedFriendList();
|
||||
showFriendsAccordionsIfNeeded();
|
||||
}
|
||||
|
||||
bool LLPanelPeople::updateSuggestedFriendList()
|
||||
{
|
||||
const LLAvatarTracker& av_tracker = LLAvatarTracker::instance();
|
||||
uuid_vec_t& suggested_friends = mSuggestedFriends->getIDs();
|
||||
suggested_friends.clear();
|
||||
|
||||
//Add suggested friends
|
||||
LLSD friends = LLFacebookConnect::instance().getContent();
|
||||
for (LLSD::array_const_iterator i = friends.beginArray(); i != friends.endArray(); ++i)
|
||||
{
|
||||
LLUUID agent_id = (*i).asUUID();
|
||||
bool second_life_buddy = agent_id.notNull() ? av_tracker.isBuddy(agent_id) : false;
|
||||
|
||||
if(!second_life_buddy)
|
||||
{
|
||||
//FB+SL but not SL friend
|
||||
if (agent_id.notNull())
|
||||
{
|
||||
suggested_friends.push_back(agent_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Force a refresh when there aren't any filter matches (prevent displaying content that shouldn't display)
|
||||
mSuggestedFriends->setDirty(true, !mSuggestedFriends->filterHasMatches());
|
||||
showFriendsAccordionsIfNeeded();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void LLPanelPeople::updateNearbyList()
|
||||
{
|
||||
if (!mNearbyList)
|
||||
|
|
@ -888,51 +852,6 @@ void LLPanelPeople::updateRecentList()
|
|||
mRecentList->setDirty();
|
||||
}
|
||||
|
||||
bool LLPanelPeople::onConnectedToFacebook(const LLSD& data)
|
||||
{
|
||||
LLSD::Integer connection_state = data.get("enum").asInteger();
|
||||
|
||||
if (connection_state == LLFacebookConnect::FB_CONNECTED)
|
||||
{
|
||||
LLFacebookConnect::instance().loadFacebookFriends();
|
||||
}
|
||||
else if(connection_state == LLFacebookConnect::FB_NOT_CONNECTED)
|
||||
{
|
||||
updateSuggestedFriendList();
|
||||
};
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void LLPanelPeople::updateFacebookList(bool visible)
|
||||
{
|
||||
if (visible)
|
||||
{
|
||||
LLEventPumps::instance().obtain("FacebookConnectContent").stopListening("LLPanelPeople"); // just in case it is already listening
|
||||
LLEventPumps::instance().obtain("FacebookConnectContent").listen("LLPanelPeople", boost::bind(&LLPanelPeople::updateSuggestedFriendList, this));
|
||||
|
||||
LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLPanelPeople"); // just in case it is already listening
|
||||
LLEventPumps::instance().obtain("FacebookConnectState").listen("LLPanelPeople", boost::bind(&LLPanelPeople::onConnectedToFacebook, this, _1));
|
||||
|
||||
if (LLFacebookConnect::instance().isConnected())
|
||||
{
|
||||
LLFacebookConnect::instance().loadFacebookFriends();
|
||||
}
|
||||
else if(mTryToConnectToFacebook)
|
||||
{
|
||||
LLFacebookConnect::instance().checkConnectionToFacebook();
|
||||
mTryToConnectToFacebook = false;
|
||||
}
|
||||
|
||||
updateSuggestedFriendList();
|
||||
}
|
||||
else
|
||||
{
|
||||
LLEventPumps::instance().obtain("FacebookConnectState").stopListening("LLPanelPeople");
|
||||
LLEventPumps::instance().obtain("FacebookConnectContent").stopListening("LLPanelPeople");
|
||||
}
|
||||
}
|
||||
|
||||
void LLPanelPeople::updateButtons()
|
||||
{
|
||||
std::string cur_tab = getActiveTabName();
|
||||
|
|
@ -1151,11 +1070,9 @@ void LLPanelPeople::onFilterEdit(const std::string& search_string)
|
|||
|
||||
mOnlineFriendList->setNameFilter(filter);
|
||||
mAllFriendList->setNameFilter(filter);
|
||||
mSuggestedFriends->setNameFilter(filter);
|
||||
|
||||
setAccordionCollapsedByUser("tab_online", false);
|
||||
setAccordionCollapsedByUser("tab_all", false);
|
||||
setAccordionCollapsedByUser("tab_suggested_friends", false);
|
||||
showFriendsAccordionsIfNeeded();
|
||||
|
||||
// restore accordion tabs state _after_ all manipulations
|
||||
|
|
@ -1600,7 +1517,6 @@ void LLPanelPeople::showFriendsAccordionsIfNeeded()
|
|||
// Expand and show accordions if needed, else - hide them
|
||||
showAccordion("tab_online", mOnlineFriendList->filterHasMatches());
|
||||
showAccordion("tab_all", mAllFriendList->filterHasMatches());
|
||||
showAccordion("tab_suggested_friends", mSuggestedFriends->filterHasMatches());
|
||||
|
||||
// Rearrange accordions
|
||||
LLAccordionCtrl* accordion = getChild<LLAccordionCtrl>("friends_accordion");
|
||||
|
|
|
|||
|
|
@ -57,8 +57,6 @@ public:
|
|||
// when voice is available
|
||||
/*virtual*/ void onChange(EStatusType status, const std::string &channelURI, bool proximal);
|
||||
|
||||
bool mTryToConnectToFacebook;
|
||||
|
||||
// internals
|
||||
class Updater;
|
||||
|
||||
|
|
@ -80,10 +78,8 @@ private:
|
|||
// methods indirectly called by the updaters
|
||||
void updateFriendListHelpText();
|
||||
void updateFriendList();
|
||||
bool updateSuggestedFriendList();
|
||||
void updateNearbyList();
|
||||
void updateRecentList();
|
||||
void updateFacebookList(bool visible);
|
||||
|
||||
bool isItemsFreeOfFriends(const uuid_vec_t& uuids);
|
||||
|
||||
|
|
@ -131,8 +127,6 @@ private:
|
|||
|
||||
void onFriendListRefreshComplete(LLUICtrl*ctrl, const LLSD& param);
|
||||
|
||||
bool onConnectedToFacebook(const LLSD& data);
|
||||
|
||||
void setAccordionCollapsedByUser(LLUICtrl* acc_tab, bool collapsed);
|
||||
void setAccordionCollapsedByUser(const std::string& name, bool collapsed);
|
||||
bool isAccordionCollapsedByUser(LLUICtrl* acc_tab);
|
||||
|
|
@ -141,7 +135,6 @@ private:
|
|||
LLTabContainer* mTabContainer;
|
||||
LLAvatarList* mOnlineFriendList;
|
||||
LLAvatarList* mAllFriendList;
|
||||
LLAvatarList* mSuggestedFriends;
|
||||
LLAvatarList* mNearbyList;
|
||||
LLAvatarList* mRecentList;
|
||||
LLGroupList* mGroupList;
|
||||
|
|
|
|||
|
|
@ -52,7 +52,6 @@ namespace LLPanelPeopleMenus
|
|||
|
||||
PeopleContextMenu gPeopleContextMenu;
|
||||
NearbyPeopleContextMenu gNearbyPeopleContextMenu;
|
||||
SuggestedFriendsContextMenu gSuggestedFriendsContextMenu;
|
||||
|
||||
//== PeopleContextMenu ===============================================================
|
||||
|
||||
|
|
@ -413,36 +412,4 @@ void NearbyPeopleContextMenu::buildContextMenu(class LLMenuGL& menu, U32 flags)
|
|||
hide_context_entries(menu, items, disabled_items);
|
||||
}
|
||||
|
||||
//== SuggestedFriendsContextMenu ===============================================================
|
||||
|
||||
LLContextMenu* SuggestedFriendsContextMenu::createMenu()
|
||||
{
|
||||
// set up the callbacks for all of the avatar menu items
|
||||
LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
|
||||
LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar;
|
||||
LLContextMenu* menu;
|
||||
|
||||
// Set up for one person selected menu
|
||||
const LLUUID& id = mUUIDs.front();
|
||||
registrar.add("Avatar.Profile", boost::bind(&LLAvatarActions::showProfile, id));
|
||||
registrar.add("Avatar.AddFriend", boost::bind(&LLAvatarActions::requestFriendshipDialog, id));
|
||||
|
||||
// create the context menu from the XUI
|
||||
menu = createFromFile("menu_people_nearby.xml");
|
||||
buildContextMenu(*menu, 0x0);
|
||||
|
||||
return menu;
|
||||
}
|
||||
|
||||
void SuggestedFriendsContextMenu::buildContextMenu(class LLMenuGL& menu, U32 flags)
|
||||
{
|
||||
menuentry_vec_t items;
|
||||
menuentry_vec_t disabled_items;
|
||||
|
||||
items.push_back(std::string("view_profile"));
|
||||
items.push_back(std::string("add_friend"));
|
||||
|
||||
hide_context_entries(menu, items, disabled_items);
|
||||
}
|
||||
|
||||
} // namespace LLPanelPeopleMenus
|
||||
|
|
|
|||
|
|
@ -62,21 +62,8 @@ protected:
|
|||
/*virtual*/ void buildContextMenu(class LLMenuGL& menu, U32 flags);
|
||||
};
|
||||
|
||||
/**
|
||||
* Menu used in the suggested friends list.
|
||||
*/
|
||||
class SuggestedFriendsContextMenu : public PeopleContextMenu
|
||||
{
|
||||
public:
|
||||
/*virtual*/ LLContextMenu * createMenu();
|
||||
|
||||
protected:
|
||||
/*virtual*/ void buildContextMenu(class LLMenuGL& menu, U32 flags);
|
||||
};
|
||||
|
||||
extern PeopleContextMenu gPeopleContextMenu;
|
||||
extern NearbyPeopleContextMenu gNearbyPeopleContextMenu;
|
||||
extern SuggestedFriendsContextMenu gSuggestedFriendsContextMenu;
|
||||
|
||||
} // namespace LLPanelPeopleMenus
|
||||
|
||||
|
|
|
|||
|
|
@ -563,11 +563,8 @@ void LLPanelPlaceProfile::displaySelectedParcelInfo(LLParcel* parcel,
|
|||
mSaleToText->setText(getString("anyone"));
|
||||
}
|
||||
|
||||
const U8* sign = (U8*)getString("price_text").c_str();
|
||||
const U8* sqm = (U8*)getString("area_text").c_str();
|
||||
|
||||
mSalesPriceText->setText(llformat("%s%d ", sign, parcel->getSalePrice()));
|
||||
mAreaText->setText(llformat("%d %s", area, sqm));
|
||||
mSalesPriceText->setText(llformat("%s%d ", getString("price_text").c_str(), parcel->getSalePrice()));
|
||||
mAreaText->setText(llformat("%d %s", area, getString("area_text").c_str()));
|
||||
mTrafficText->setText(llformat("%.0f", dwell));
|
||||
|
||||
// Can't have more than region max tasks, regardless of parcel
|
||||
|
|
@ -575,10 +572,7 @@ void LLPanelPlaceProfile::displaySelectedParcelInfo(LLParcel* parcel,
|
|||
S32 primitives = llmin(ll_round(parcel->getMaxPrimCapacity() * parcel->getParcelPrimBonus()),
|
||||
(S32)region->getMaxTasks());
|
||||
|
||||
const U8* available = (U8*)getString("available").c_str();
|
||||
const U8* allocated = (U8*)getString("allocated").c_str();
|
||||
|
||||
mPrimitivesText->setText(llformat("%d %s, %d %s", primitives, available, parcel->getPrimCount(), allocated));
|
||||
mPrimitivesText->setText(llformat("%d %s, %d %s", primitives, getString("available").c_str(), parcel->getPrimCount(), getString("allocated").c_str()));
|
||||
|
||||
if (parcel->getAllowOtherScripts())
|
||||
{
|
||||
|
|
|
|||
|
|
@ -32,7 +32,6 @@
|
|||
|
||||
#include "llfloatersnapshot.h" // FIXME: create a snapshot model
|
||||
#include "llfloaterreg.h"
|
||||
#include "llfloaterfacebook.h"
|
||||
#include "llfloaterflickr.h"
|
||||
#include "llfloatertwitter.h"
|
||||
|
||||
|
|
@ -59,7 +58,6 @@ private:
|
|||
void onSaveToEmail();
|
||||
void onSaveToInventory();
|
||||
void onSaveToComputer();
|
||||
void onSendToFacebook();
|
||||
void onSendToTwitter();
|
||||
void onSendToFlickr();
|
||||
|
||||
|
|
@ -74,7 +72,6 @@ LLPanelSnapshotOptions::LLPanelSnapshotOptions()
|
|||
mCommitCallbackRegistrar.add("Snapshot.SaveToEmail", boost::bind(&LLPanelSnapshotOptions::onSaveToEmail, this));
|
||||
mCommitCallbackRegistrar.add("Snapshot.SaveToInventory", boost::bind(&LLPanelSnapshotOptions::onSaveToInventory, this));
|
||||
mCommitCallbackRegistrar.add("Snapshot.SaveToComputer", boost::bind(&LLPanelSnapshotOptions::onSaveToComputer, this));
|
||||
mCommitCallbackRegistrar.add("Snapshot.SendToFacebook", boost::bind(&LLPanelSnapshotOptions::onSendToFacebook, this));
|
||||
mCommitCallbackRegistrar.add("Snapshot.SendToTwitter", boost::bind(&LLPanelSnapshotOptions::onSendToTwitter, this));
|
||||
mCommitCallbackRegistrar.add("Snapshot.SendToFlickr", boost::bind(&LLPanelSnapshotOptions::onSendToFlickr, this));
|
||||
LLGlobalEconomy::getInstance()->addObserver(this);
|
||||
|
|
@ -138,18 +135,6 @@ void LLPanelSnapshotOptions::onSaveToComputer()
|
|||
openPanel("panel_snapshot_local");
|
||||
}
|
||||
|
||||
void LLPanelSnapshotOptions::onSendToFacebook()
|
||||
{
|
||||
LLFloaterReg::hideInstance("snapshot");
|
||||
|
||||
LLFloaterFacebook* facebook_floater = dynamic_cast<LLFloaterFacebook*>(LLFloaterReg::getInstance("facebook"));
|
||||
if (facebook_floater)
|
||||
{
|
||||
facebook_floater->showPhotoPanel();
|
||||
}
|
||||
LLFloaterReg::showInstance("facebook");
|
||||
}
|
||||
|
||||
void LLPanelSnapshotOptions::onSendToTwitter()
|
||||
{
|
||||
LLFloaterReg::hideInstance("snapshot");
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@
|
|||
|
||||
#include "llagent.h"
|
||||
#include "lldraghandle.h"
|
||||
#include "llexternaleditor.h"
|
||||
#include "llviewerwindow.h"
|
||||
#include "llbutton.h"
|
||||
#include "llfloaterreg.h"
|
||||
|
|
@ -43,6 +44,7 @@
|
|||
#include "roles_constants.h"
|
||||
#include "llscrollbar.h"
|
||||
#include "llselectmgr.h"
|
||||
#include "lltrans.h"
|
||||
#include "llviewertexteditor.h"
|
||||
#include "llvfile.h"
|
||||
#include "llviewerinventory.h"
|
||||
|
|
@ -63,7 +65,8 @@
|
|||
|
||||
// Default constructor
|
||||
LLPreviewNotecard::LLPreviewNotecard(const LLSD& key) //const LLUUID& item_id,
|
||||
: LLPreview( key )
|
||||
: LLPreview( key ),
|
||||
mLiveFile(NULL)
|
||||
{
|
||||
const LLInventoryItem *item = getItem();
|
||||
if (item)
|
||||
|
|
@ -74,13 +77,14 @@ LLPreviewNotecard::LLPreviewNotecard(const LLSD& key) //const LLUUID& item_id,
|
|||
|
||||
LLPreviewNotecard::~LLPreviewNotecard()
|
||||
{
|
||||
delete mLiveFile;
|
||||
}
|
||||
|
||||
BOOL LLPreviewNotecard::postBuild()
|
||||
{
|
||||
LLViewerTextEditor *ed = getChild<LLViewerTextEditor>("Notecard Editor");
|
||||
ed->setNotecardInfo(mItemUUID, mObjectID, getKey());
|
||||
ed->makePristine();
|
||||
mEditor = getChild<LLViewerTextEditor>("Notecard Editor");
|
||||
mEditor->setNotecardInfo(mItemUUID, mObjectID, getKey());
|
||||
mEditor->makePristine();
|
||||
|
||||
childSetAction("Save", onClickSave, this);
|
||||
getChildView("lock")->setVisible( FALSE);
|
||||
|
|
@ -88,6 +92,8 @@ BOOL LLPreviewNotecard::postBuild()
|
|||
childSetAction("Delete", onClickDelete, this);
|
||||
getChildView("Delete")->setEnabled(false);
|
||||
|
||||
childSetAction("Edit", onClickEdit, this);
|
||||
|
||||
const LLInventoryItem* item = getItem();
|
||||
|
||||
childSetCommitCallback("desc", LLPreview::onText, this);
|
||||
|
|
@ -408,6 +414,16 @@ void LLPreviewNotecard::onClickDelete(void* user_data)
|
|||
}
|
||||
}
|
||||
|
||||
// static
|
||||
void LLPreviewNotecard::onClickEdit(void* user_data)
|
||||
{
|
||||
LLPreviewNotecard* preview = (LLPreviewNotecard*)user_data;
|
||||
if (preview)
|
||||
{
|
||||
preview->openInExternalEditor();
|
||||
}
|
||||
}
|
||||
|
||||
struct LLSaveNotecardInfo
|
||||
{
|
||||
LLPreviewNotecard* mSelf;
|
||||
|
|
@ -468,7 +484,7 @@ void LLPreviewNotecard::finishTaskUpload(LLUUID itemId, LLUUID newAssetId, LLUUI
|
|||
}
|
||||
}
|
||||
|
||||
bool LLPreviewNotecard::saveIfNeeded(LLInventoryItem* copyitem)
|
||||
bool LLPreviewNotecard::saveIfNeeded(LLInventoryItem* copyitem, bool sync)
|
||||
{
|
||||
LLViewerTextEditor* editor = getChild<LLViewerTextEditor>("Notecard Editor");
|
||||
|
||||
|
|
@ -487,7 +503,10 @@ bool LLPreviewNotecard::saveIfNeeded(LLInventoryItem* copyitem)
|
|||
}
|
||||
|
||||
editor->makePristine();
|
||||
|
||||
if (sync)
|
||||
{
|
||||
syncExternal();
|
||||
}
|
||||
const LLInventoryItem* item = getItem();
|
||||
// save it out to database
|
||||
if (item)
|
||||
|
|
@ -566,6 +585,18 @@ bool LLPreviewNotecard::saveIfNeeded(LLInventoryItem* copyitem)
|
|||
return true;
|
||||
}
|
||||
|
||||
void LLPreviewNotecard::syncExternal()
|
||||
{
|
||||
// Sync with external editor.
|
||||
std::string tmp_file = getTmpFileName();
|
||||
llstat s;
|
||||
if (LLFile::stat(tmp_file, &s) == 0) // file exists
|
||||
{
|
||||
if (mLiveFile) mLiveFile->ignoreNextUpdate();
|
||||
writeToFile(tmp_file);
|
||||
}
|
||||
}
|
||||
|
||||
void LLPreviewNotecard::deleteNotecard()
|
||||
{
|
||||
LLNotificationsUtil::add("DeleteNotecard", LLSD(), LLSD(), boost::bind(&LLPreviewNotecard::handleConfirmDeleteDialog,this, _1, _2));
|
||||
|
|
@ -714,4 +745,128 @@ bool LLPreviewNotecard::handleConfirmDeleteDialog(const LLSD& notification, cons
|
|||
return false;
|
||||
}
|
||||
|
||||
void LLPreviewNotecard::openInExternalEditor()
|
||||
{
|
||||
delete mLiveFile; // deletes file
|
||||
|
||||
// Save the notecard to a temporary file.
|
||||
std::string filename = getTmpFileName();
|
||||
writeToFile(filename);
|
||||
|
||||
// Start watching file changes.
|
||||
mLiveFile = new LLLiveLSLFile(filename, boost::bind(&LLPreviewNotecard::onExternalChange, this, _1));
|
||||
mLiveFile->addToEventTimer();
|
||||
|
||||
// Open it in external editor.
|
||||
{
|
||||
LLExternalEditor ed;
|
||||
LLExternalEditor::EErrorCode status;
|
||||
std::string msg;
|
||||
|
||||
status = ed.setCommand("LL_SCRIPT_EDITOR");
|
||||
if (status != LLExternalEditor::EC_SUCCESS)
|
||||
{
|
||||
if (status == LLExternalEditor::EC_NOT_SPECIFIED) // Use custom message for this error.
|
||||
{
|
||||
msg = LLTrans::getString("ExternalEditorNotSet");
|
||||
}
|
||||
else
|
||||
{
|
||||
msg = LLExternalEditor::getErrorMessage(status);
|
||||
}
|
||||
|
||||
LLNotificationsUtil::add("GenericAlert", LLSD().with("MESSAGE", msg));
|
||||
return;
|
||||
}
|
||||
|
||||
status = ed.run(filename);
|
||||
if (status != LLExternalEditor::EC_SUCCESS)
|
||||
{
|
||||
msg = LLExternalEditor::getErrorMessage(status);
|
||||
LLNotificationsUtil::add("GenericAlert", LLSD().with("MESSAGE", msg));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool LLPreviewNotecard::onExternalChange(const std::string& filename)
|
||||
{
|
||||
if (!loadNotecardText(filename))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Disable sync to avoid recursive load->save->load calls.
|
||||
saveIfNeeded(NULL, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LLPreviewNotecard::loadNotecardText(const std::string& filename)
|
||||
{
|
||||
if (filename.empty())
|
||||
{
|
||||
LL_WARNS() << "Empty file name" << LL_ENDL;
|
||||
return false;
|
||||
}
|
||||
|
||||
LLFILE* file = LLFile::fopen(filename, "rb"); /*Flawfinder: ignore*/
|
||||
if (!file)
|
||||
{
|
||||
LL_WARNS() << "Error opening " << filename << LL_ENDL;
|
||||
return false;
|
||||
}
|
||||
|
||||
// read in the whole file
|
||||
fseek(file, 0L, SEEK_END);
|
||||
size_t file_length = (size_t)ftell(file);
|
||||
fseek(file, 0L, SEEK_SET);
|
||||
char* buffer = new char[file_length + 1];
|
||||
size_t nread = fread(buffer, 1, file_length, file);
|
||||
if (nread < file_length)
|
||||
{
|
||||
LL_WARNS() << "Short read" << LL_ENDL;
|
||||
}
|
||||
buffer[nread] = '\0';
|
||||
fclose(file);
|
||||
|
||||
mEditor->setText(LLStringExplicit(buffer));
|
||||
delete[] buffer;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LLPreviewNotecard::writeToFile(const std::string& filename)
|
||||
{
|
||||
LLFILE* fp = LLFile::fopen(filename, "wb");
|
||||
if (!fp)
|
||||
{
|
||||
LL_WARNS() << "Unable to write to " << filename << LL_ENDL;
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string utf8text = mEditor->getText();
|
||||
|
||||
if (utf8text.size() == 0)
|
||||
{
|
||||
utf8text = " ";
|
||||
}
|
||||
|
||||
fputs(utf8text.c_str(), fp);
|
||||
fclose(fp);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
std::string LLPreviewNotecard::getTmpFileName()
|
||||
{
|
||||
std::string notecard_id = mObjectID.asString() + "_" + mItemUUID.asString();
|
||||
|
||||
// Use MD5 sum to make the file name shorter and not exceed maximum path length.
|
||||
char notecard_id_hash_str[33]; /* Flawfinder: ignore */
|
||||
LLMD5 notecard_id_hash((const U8 *)notecard_id.c_str());
|
||||
notecard_id_hash.hex_digest(notecard_id_hash_str);
|
||||
|
||||
return std::string(LLFile::tmpdir()) + "sl_notecard_" + notecard_id_hash_str + ".txt";
|
||||
}
|
||||
|
||||
|
||||
// EOF
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@
|
|||
|
||||
#include "llpreview.h"
|
||||
#include "llassetstorage.h"
|
||||
#include "llpreviewscript.h"
|
||||
#include "lliconctrl.h"
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
|
@ -47,18 +48,18 @@ public:
|
|||
virtual ~LLPreviewNotecard();
|
||||
|
||||
bool saveItem();
|
||||
void setObjectID(const LLUUID& object_id);
|
||||
void setObjectID(const LLUUID& object_id) override;
|
||||
|
||||
// llview
|
||||
virtual void draw();
|
||||
virtual BOOL handleKeyHere(KEY key, MASK mask);
|
||||
virtual void setEnabled( BOOL enabled );
|
||||
void draw() override;
|
||||
BOOL handleKeyHere(KEY key, MASK mask) override;
|
||||
void setEnabled( BOOL enabled ) override;
|
||||
|
||||
// llfloater
|
||||
virtual BOOL canClose();
|
||||
BOOL canClose() override;
|
||||
|
||||
// llpanel
|
||||
virtual BOOL postBuild();
|
||||
BOOL postBuild() override;
|
||||
|
||||
// reach into the text editor, and grab the drag item
|
||||
const LLInventoryItem* getDragItem();
|
||||
|
|
@ -72,11 +73,13 @@ public:
|
|||
// asset system. :(
|
||||
void refreshFromInventory(const LLUUID& item_id = LLUUID::null);
|
||||
|
||||
void syncExternal();
|
||||
|
||||
protected:
|
||||
|
||||
void updateTitleButtons();
|
||||
virtual void loadAsset();
|
||||
bool saveIfNeeded(LLInventoryItem* copyitem = NULL);
|
||||
void updateTitleButtons() override;
|
||||
void loadAsset() override;
|
||||
bool saveIfNeeded(LLInventoryItem* copyitem = NULL, bool sync = true);
|
||||
|
||||
void deleteNotecard();
|
||||
|
||||
|
|
@ -89,6 +92,8 @@ protected:
|
|||
|
||||
static void onClickDelete(void* data);
|
||||
|
||||
static void onClickEdit(void* data);
|
||||
|
||||
static void onSaveComplete(const LLUUID& asset_uuid,
|
||||
void* user_data,
|
||||
S32 status, LLExtStat ext_status);
|
||||
|
|
@ -99,6 +104,12 @@ protected:
|
|||
static void finishInventoryUpload(LLUUID itemId, LLUUID newAssetId, LLUUID newItemId);
|
||||
static void finishTaskUpload(LLUUID itemId, LLUUID newAssetId, LLUUID taskId);
|
||||
|
||||
void openInExternalEditor();
|
||||
bool onExternalChange(const std::string& filename);
|
||||
bool loadNotecardText(const std::string& filename);
|
||||
bool writeToFile(const std::string& filename);
|
||||
std::string getTmpFileName();
|
||||
|
||||
protected:
|
||||
LLViewerTextEditor* mEditor;
|
||||
LLButton* mSaveBtn;
|
||||
|
|
@ -106,6 +117,8 @@ protected:
|
|||
LLUUID mAssetID;
|
||||
|
||||
LLUUID mObjectID;
|
||||
|
||||
LLLiveLSLFile* mLiveFile;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -41,7 +41,6 @@
|
|||
#include "llinventorymodel.h"
|
||||
#include "llkeyboard.h"
|
||||
#include "lllineeditor.h"
|
||||
#include "lllivefile.h"
|
||||
#include "llhelp.h"
|
||||
#include "llnotificationsutil.h"
|
||||
#include "llresmgr.h"
|
||||
|
|
@ -120,22 +119,6 @@ static bool have_script_upload_cap(LLUUID& object_id)
|
|||
/// ---------------------------------------------------------------------------
|
||||
/// LLLiveLSLFile
|
||||
/// ---------------------------------------------------------------------------
|
||||
class LLLiveLSLFile : public LLLiveFile
|
||||
{
|
||||
public:
|
||||
typedef boost::function<bool (const std::string& filename)> change_callback_t;
|
||||
|
||||
LLLiveLSLFile(std::string file_path, change_callback_t change_cb);
|
||||
~LLLiveLSLFile();
|
||||
|
||||
void ignoreNextUpdate() { mIgnoreNextUpdate = true; }
|
||||
|
||||
protected:
|
||||
/*virtual*/ bool loadFile();
|
||||
|
||||
change_callback_t mOnChangeCallback;
|
||||
bool mIgnoreNextUpdate;
|
||||
};
|
||||
|
||||
LLLiveLSLFile::LLLiveLSLFile(std::string file_path, change_callback_t change_cb)
|
||||
: mOnChangeCallback(change_cb)
|
||||
|
|
@ -1069,7 +1052,7 @@ void LLScriptEdCore::openInExternalEditor()
|
|||
{
|
||||
if (status == LLExternalEditor::EC_NOT_SPECIFIED) // Use custom message for this error.
|
||||
{
|
||||
msg = getString("external_editor_not_set");
|
||||
msg = LLTrans::getString("ExternalEditorNotSet");
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@
|
|||
#include "lliconctrl.h"
|
||||
#include "llframetimer.h"
|
||||
#include "llfloatergotoline.h"
|
||||
#include "lllivefile.h"
|
||||
#include "llsyntaxid.h"
|
||||
|
||||
class LLLiveLSLFile;
|
||||
|
|
@ -53,6 +54,23 @@ class LLScriptEdContainer;
|
|||
class LLFloaterGotoLine;
|
||||
class LLFloaterExperienceProfile;
|
||||
|
||||
class LLLiveLSLFile : public LLLiveFile
|
||||
{
|
||||
public:
|
||||
typedef boost::function<bool(const std::string& filename)> change_callback_t;
|
||||
|
||||
LLLiveLSLFile(std::string file_path, change_callback_t change_cb);
|
||||
~LLLiveLSLFile();
|
||||
|
||||
void ignoreNextUpdate() { mIgnoreNextUpdate = true; }
|
||||
|
||||
protected:
|
||||
/*virtual*/ bool loadFile();
|
||||
|
||||
change_callback_t mOnChangeCallback;
|
||||
bool mIgnoreNextUpdate;
|
||||
};
|
||||
|
||||
// Inner, implementation class. LLPreviewScript and LLLiveLSLEditor each own one of these.
|
||||
class LLScriptEdCore : public LLPanel
|
||||
{
|
||||
|
|
|
|||
|
|
@ -125,17 +125,13 @@ void ll::statusbar::SearchableItem::setNotHighlighted( )
|
|||
}
|
||||
}
|
||||
|
||||
bool ll::statusbar::SearchableItem::hightlightAndHide( LLWString const &aFilter )
|
||||
bool ll::statusbar::SearchableItem::hightlightAndHide(LLWString const &aFilter, bool hide)
|
||||
{
|
||||
if( mMenu && !mMenu->getVisible() && !mWasHiddenBySearch )
|
||||
if ((mMenu && !mMenu->getVisible() && !mWasHiddenBySearch) || dynamic_cast<LLMenuItemTearOffGL*>(mMenu))
|
||||
return false;
|
||||
|
||||
setNotHighlighted( );
|
||||
|
||||
bool bVisible(false);
|
||||
for( tSearchableItemList::iterator itr = mChildren.begin(); itr != mChildren.end(); ++itr )
|
||||
bVisible |= (*itr)->hightlightAndHide( aFilter );
|
||||
|
||||
if( aFilter.empty() )
|
||||
{
|
||||
if( mCtrl )
|
||||
|
|
@ -143,17 +139,22 @@ bool ll::statusbar::SearchableItem::hightlightAndHide( LLWString const &aFilter
|
|||
return true;
|
||||
}
|
||||
|
||||
bool bHighlighted(!hide);
|
||||
if( mLabel.find( aFilter ) != LLWString::npos )
|
||||
{
|
||||
if( mCtrl )
|
||||
mCtrl->setHighlighted( true );
|
||||
return true;
|
||||
bHighlighted = true;
|
||||
}
|
||||
|
||||
if( mCtrl && !bVisible )
|
||||
bool bVisible(false);
|
||||
for (tSearchableItemList::iterator itr = mChildren.begin(); itr != mChildren.end(); ++itr)
|
||||
bVisible |= (*itr)->hightlightAndHide(aFilter, !bHighlighted);
|
||||
|
||||
if (mCtrl && !bVisible && !bHighlighted)
|
||||
{
|
||||
mWasHiddenBySearch = true;
|
||||
mMenu->setVisible(FALSE);
|
||||
}
|
||||
return bVisible;
|
||||
return bVisible || bHighlighted;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -107,7 +107,7 @@ namespace ll
|
|||
SearchableItem();
|
||||
|
||||
void setNotHighlighted( );
|
||||
bool hightlightAndHide( LLWString const &aFilter );
|
||||
bool hightlightAndHide( LLWString const &aFilter, bool hide = true );
|
||||
};
|
||||
|
||||
struct SearchData
|
||||
|
|
|
|||
|
|
@ -3864,6 +3864,14 @@ BOOL LLSelectMgr::selectGetAggregateTexturePermissions(LLAggregatePermissions& r
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL LLSelectMgr::isSelfAvatarSelected()
|
||||
{
|
||||
if (mAllowSelectAvatar)
|
||||
{
|
||||
return (getSelection()->getObjectCount() == 1) && (getSelection()->getFirstRootObject() == gAgentAvatarp);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Duplicate objects
|
||||
|
|
@ -3886,6 +3894,17 @@ void LLSelectMgr::selectDuplicate(const LLVector3& offset, BOOL select_copy)
|
|||
make_ui_sound("UISndInvalidOp");
|
||||
return;
|
||||
}
|
||||
if (!canDuplicate())
|
||||
{
|
||||
LLSelectNode* node = getSelection()->getFirstRootNode(NULL, true);
|
||||
if (node)
|
||||
{
|
||||
LLSD args;
|
||||
args["OBJ_NAME"] = node->mName;
|
||||
LLNotificationsUtil::add("NoCopyPermsNoObject", args);
|
||||
return;
|
||||
}
|
||||
}
|
||||
LLDuplicateData data;
|
||||
|
||||
data.offset = offset;
|
||||
|
|
@ -6765,8 +6784,28 @@ void LLSelectMgr::pauseAssociatedAvatars()
|
|||
|
||||
mSelectedObjects->mSelectType = getSelectTypeForObject(object);
|
||||
|
||||
bool is_attached = false;
|
||||
if (mSelectedObjects->mSelectType == SELECT_TYPE_ATTACHMENT &&
|
||||
isAgentAvatarValid() && object->getParent() != NULL)
|
||||
isAgentAvatarValid())
|
||||
{
|
||||
// Selection can be obsolete, confirm that this is an attachment
|
||||
LLViewerObject* parent = (LLViewerObject*)object->getParent();
|
||||
while (parent != NULL)
|
||||
{
|
||||
if (parent->isAvatar())
|
||||
{
|
||||
is_attached = true;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
parent = (LLViewerObject*)parent->getParent();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (is_attached)
|
||||
{
|
||||
if (object->isAnimatedObject())
|
||||
{
|
||||
|
|
@ -6784,14 +6823,12 @@ void LLSelectMgr::pauseAssociatedAvatars()
|
|||
mPauseRequests.push_back(gAgentAvatarp->requestPause());
|
||||
}
|
||||
}
|
||||
else
|
||||
else if (object && object->isAnimatedObject() && object->getControlAvatar())
|
||||
{
|
||||
if (object && object->isAnimatedObject() && object->getControlAvatar())
|
||||
{
|
||||
// Is a non-attached animated object. Pause the control avatar.
|
||||
mPauseRequests.push_back(object->getControlAvatar()->requestPause());
|
||||
}
|
||||
// Is a non-attached animated object. Pause the control avatar.
|
||||
mPauseRequests.push_back(object->getControlAvatar()->requestPause());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -714,6 +714,8 @@ public:
|
|||
|
||||
LLPermissions* findObjectPermissions(const LLViewerObject* object);
|
||||
|
||||
BOOL isSelfAvatarSelected();
|
||||
|
||||
void selectDelete(); // Delete on simulator
|
||||
void selectForceDelete(); // just delete, no into trash
|
||||
void selectDuplicate(const LLVector3& offset, BOOL select_copy); // Duplicate on simulator
|
||||
|
|
|
|||
|
|
@ -564,6 +564,7 @@ void LLSidepanelInventory::updateVerbs()
|
|||
mWearBtn->setEnabled(FALSE);
|
||||
mPlayBtn->setVisible(FALSE);
|
||||
mPlayBtn->setEnabled(FALSE);
|
||||
mPlayBtn->setToolTip(std::string(""));
|
||||
mTeleportBtn->setVisible(FALSE);
|
||||
mTeleportBtn->setEnabled(FALSE);
|
||||
mShopBtn->setVisible(TRUE);
|
||||
|
|
@ -588,11 +589,23 @@ void LLSidepanelInventory::updateVerbs()
|
|||
mShopBtn->setVisible(FALSE);
|
||||
break;
|
||||
case LLInventoryType::IT_SOUND:
|
||||
mPlayBtn->setVisible(TRUE);
|
||||
mPlayBtn->setEnabled(TRUE);
|
||||
mPlayBtn->setToolTip(LLTrans::getString("InventoryPlaySoundTooltip"));
|
||||
mShopBtn->setVisible(FALSE);
|
||||
break;
|
||||
case LLInventoryType::IT_GESTURE:
|
||||
mPlayBtn->setVisible(TRUE);
|
||||
mPlayBtn->setEnabled(TRUE);
|
||||
mPlayBtn->setToolTip(LLTrans::getString("InventoryPlayGestureTooltip"));
|
||||
mShopBtn->setVisible(FALSE);
|
||||
break;
|
||||
case LLInventoryType::IT_ANIMATION:
|
||||
mPlayBtn->setVisible(TRUE);
|
||||
mPlayBtn->setEnabled(TRUE);
|
||||
mShopBtn->setVisible(FALSE);
|
||||
mPlayBtn->setEnabled(TRUE);
|
||||
mPlayBtn->setToolTip(LLTrans::getString("InventoryPlayAnimationTooltip"));
|
||||
mShopBtn->setVisible(FALSE);
|
||||
break;
|
||||
case LLInventoryType::IT_LANDMARK:
|
||||
mTeleportBtn->setVisible(TRUE);
|
||||
|
|
|
|||
|
|
@ -34,7 +34,6 @@
|
|||
#include "lleconomy.h"
|
||||
#include "llfloaterperms.h"
|
||||
#include "llfloaterreg.h"
|
||||
#include "llfloaterfacebook.h"
|
||||
#include "llfloaterflickr.h"
|
||||
#include "llfloatertwitter.h"
|
||||
#include "llimagefilter.h"
|
||||
|
|
@ -572,7 +571,7 @@ void LLSnapshotLivePreview::generateThumbnailImage(BOOL force_update)
|
|||
|
||||
if (mThumbnailSubsampled)
|
||||
{
|
||||
// The thumbnail is be a subsampled version of the preview (used in SL Share previews, i.e. Flickr, Twitter, Facebook)
|
||||
// The thumbnail is be a subsampled version of the preview (used in SL Share previews, i.e. Flickr, Twitter)
|
||||
raw->resize( mPreviewImage->getWidth(),
|
||||
mPreviewImage->getHeight(),
|
||||
mPreviewImage->getComponents());
|
||||
|
|
@ -638,7 +637,7 @@ LLViewerTexture* LLSnapshotLivePreview::getBigThumbnailImage()
|
|||
|
||||
if (raw)
|
||||
{
|
||||
// The big thumbnail is a new filtered version of the preview (used in SL Share previews, i.e. Flickr, Twitter, Facebook)
|
||||
// The big thumbnail is a new filtered version of the preview (used in SL Share previews, i.e. Flickr, Twitter)
|
||||
mBigThumbnailWidth = mPreviewImage->getWidth();
|
||||
mBigThumbnailHeight = mPreviewImage->getHeight();
|
||||
raw->resize( mBigThumbnailWidth,
|
||||
|
|
|
|||
|
|
@ -99,7 +99,7 @@ void LLSurfacePatch::dirty()
|
|||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS() << "No viewer object for this surface patch!" << LL_ENDL;
|
||||
LL_WARNS("Terrain") << "No viewer object for this surface patch!" << LL_ENDL;
|
||||
}
|
||||
|
||||
mDirtyZStats = TRUE;
|
||||
|
|
|
|||
|
|
@ -66,6 +66,7 @@ bool LLTextureFetchDebugger::sDebuggerEnabled = false ;
|
|||
|
||||
LLTrace::CountStatHandle<F64> LLTextureFetch::sCacheHit("texture_cache_hit");
|
||||
LLTrace::CountStatHandle<F64> LLTextureFetch::sCacheAttempt("texture_cache_attempt");
|
||||
LLTrace::EventStatHandle<LLUnit<F32, LLUnits::Percent> > LLTextureFetch::sCacheHitRate("texture_cache_hits");
|
||||
|
||||
LLTrace::SampleStatHandle<F32Seconds> LLTextureFetch::sCacheReadLatency("texture_cache_read_latency");
|
||||
LLTrace::SampleStatHandle<F32Seconds> LLTextureFetch::sTexDecodeLatency("texture_decode_latency");
|
||||
|
|
@ -1311,6 +1312,7 @@ bool LLTextureFetchWorker::doWork(S32 param)
|
|||
LL_DEBUGS(LOG_TXT) << mID << ": Cached. Bytes: " << mFormattedImage->getDataSize()
|
||||
<< " Size: " << llformat("%dx%d",mFormattedImage->getWidth(),mFormattedImage->getHeight())
|
||||
<< " Desired Discard: " << mDesiredDiscard << " Desired Size: " << mDesiredSize << LL_ENDL;
|
||||
record(LLTextureFetch::sCacheHitRate, LLUnits::Ratio::fromValue(1));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -1326,7 +1328,7 @@ bool LLTextureFetchWorker::doWork(S32 param)
|
|||
LL_DEBUGS(LOG_TXT) << mID << ": Not in Cache" << LL_ENDL;
|
||||
setState(LOAD_FROM_NETWORK);
|
||||
}
|
||||
|
||||
record(LLTextureFetch::sCacheHitRate, LLUnits::Ratio::fromValue(0));
|
||||
// fall through
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -312,6 +312,7 @@ public:
|
|||
static LLTrace::SampleStatHandle<F32Seconds> sCacheReadLatency;
|
||||
static LLTrace::SampleStatHandle<F32Seconds> sTexDecodeLatency;
|
||||
static LLTrace::SampleStatHandle<F32Seconds> sTexFetchLatency;
|
||||
static LLTrace::EventStatHandle<LLUnit<F32, LLUnits::Percent> > sCacheHitRate;
|
||||
|
||||
private:
|
||||
LLMutex mQueueMutex; //to protect mRequestMap and mCommands only
|
||||
|
|
|
|||
|
|
@ -267,7 +267,7 @@ BOOL LLToolCompTranslate::handleHover(S32 x, S32 y, MASK mask)
|
|||
BOOL LLToolCompTranslate::handleMouseDown(S32 x, S32 y, MASK mask)
|
||||
{
|
||||
mMouseDown = TRUE;
|
||||
gViewerWindow->pickAsync(x, y, mask, pickCallback, /*BOOL pick_transparent*/ TRUE);
|
||||
gViewerWindow->pickAsync(x, y, mask, pickCallback, /*BOOL pick_transparent*/ TRUE, LLFloaterReg::instanceVisible("build"));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -111,9 +111,64 @@ BOOL LLToolPie::handleMouseDown(S32 x, S32 y, MASK mask)
|
|||
mMouseOutsideSlop = FALSE;
|
||||
mMouseDownX = x;
|
||||
mMouseDownY = y;
|
||||
LLTimer pick_timer;
|
||||
BOOL pick_rigged = false; //gSavedSettings.getBOOL("AnimatedObjectsAllowLeftClick");
|
||||
LLPickInfo transparent_pick = gViewerWindow->pickImmediate(x, y, TRUE /*includes transparent*/, pick_rigged);
|
||||
LLPickInfo visible_pick = gViewerWindow->pickImmediate(x, y, FALSE, pick_rigged);
|
||||
LLViewerObject *transp_object = transparent_pick.getObject();
|
||||
LLViewerObject *visible_object = visible_pick.getObject();
|
||||
|
||||
// Current set of priorities
|
||||
// 1. Transparent attachment pick
|
||||
// 2. Transparent actionable pick
|
||||
// 3. Visible attachment pick (e.x we click on attachment under invisible floor)
|
||||
// 4. Visible actionable pick
|
||||
// 5. Transparent pick (e.x. movement on transparent object/floor, our default pick)
|
||||
// left mouse down always picks transparent (but see handleMouseUp).
|
||||
// Also see LLToolPie::handleHover() - priorities are a bit different there.
|
||||
// Todo: we need a more consistent set of rules to work with
|
||||
if (transp_object == visible_object || !visible_object)
|
||||
{
|
||||
// Note: if transparent object is null, then visible object is also null
|
||||
// since transparent pick includes non-tranpsarent one.
|
||||
// !transparent_object check will be covered by transparent_object == visible_object.
|
||||
mPick = transparent_pick;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Select between two non-null picks
|
||||
LLViewerObject *transp_parent = transp_object->getRootEdit();
|
||||
LLViewerObject *visible_parent = visible_object->getRootEdit();
|
||||
if (transp_object->isAttachment())
|
||||
{
|
||||
// 1. Transparent attachment
|
||||
mPick = transparent_pick;
|
||||
}
|
||||
else if (transp_object->getClickAction() != CLICK_ACTION_DISABLED
|
||||
&& (useClickAction(mask, transp_object, transp_parent) || transp_object->flagHandleTouch() || (transp_parent && transp_parent->flagHandleTouch())))
|
||||
{
|
||||
// 2. Transparent actionable pick
|
||||
mPick = transparent_pick;
|
||||
}
|
||||
else if (visible_object->isAttachment())
|
||||
{
|
||||
// 3. Visible attachment pick
|
||||
mPick = visible_pick;
|
||||
}
|
||||
else if (visible_object->getClickAction() != CLICK_ACTION_DISABLED
|
||||
&& (useClickAction(mask, visible_object, visible_parent) || visible_object->flagHandleTouch() || (visible_parent && visible_parent->flagHandleTouch())))
|
||||
{
|
||||
// 4. Visible actionable pick
|
||||
mPick = visible_pick;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 5. Default: transparent
|
||||
mPick = transparent_pick;
|
||||
}
|
||||
}
|
||||
LL_INFOS() << "pick_rigged is " << (S32) pick_rigged << " pick time elapsed " << pick_timer.getElapsedTimeF32() << LL_ENDL;
|
||||
|
||||
//left mouse down always picks transparent (but see handleMouseUp)
|
||||
mPick = gViewerWindow->pickImmediate(x, y, TRUE, FALSE);
|
||||
mPick.mKeyMask = mask;
|
||||
|
||||
mMouseButtonDown = true;
|
||||
|
|
|
|||
|
|
@ -38,8 +38,12 @@
|
|||
#include "llcoros.h"
|
||||
#include "reader.h"
|
||||
#include "llcorehttputil.h"
|
||||
#include "llurlregistry.h"
|
||||
|
||||
|
||||
static const std::string BING_NOTRANSLATE_OPENING_TAG("<div class=\"notranslate\">");
|
||||
static const std::string BING_NOTRANSLATE_CLOSING_TAG("</div>");
|
||||
|
||||
/**
|
||||
* Handler of an HTTP machine translation service.
|
||||
*
|
||||
|
|
@ -99,6 +103,8 @@ public:
|
|||
*/
|
||||
virtual bool isConfigured() const = 0;
|
||||
|
||||
virtual LLTranslate::EService getCurrentService() = 0;
|
||||
|
||||
virtual void verifyKey(const std::string &key, LLTranslate::KeyVerificationResult_fn fnc) = 0;
|
||||
virtual void translateMessage(LanguagePair_t fromTo, std::string msg, LLTranslate::TranslationSuccess_fn success, LLTranslate::TranslationFailure_fn failure);
|
||||
|
||||
|
|
@ -248,6 +254,8 @@ public:
|
|||
std::string& err_msg) const;
|
||||
/*virtual*/ bool isConfigured() const;
|
||||
|
||||
/*virtual*/ LLTranslate::EService getCurrentService() { return LLTranslate::EService::SERVICE_GOOGLE; }
|
||||
|
||||
/*virtual*/ void verifyKey(const std::string &key, LLTranslate::KeyVerificationResult_fn fnc);
|
||||
|
||||
private:
|
||||
|
|
@ -409,6 +417,8 @@ public:
|
|||
std::string& err_msg) const;
|
||||
/*virtual*/ bool isConfigured() const;
|
||||
|
||||
/*virtual*/ LLTranslate::EService getCurrentService() { return LLTranslate::EService::SERVICE_BING; }
|
||||
|
||||
/*virtual*/ void verifyKey(const std::string &key, LLTranslate::KeyVerificationResult_fn fnc);
|
||||
private:
|
||||
static std::string getAPIKey();
|
||||
|
|
@ -520,7 +530,59 @@ void LLTranslate::translateMessage(const std::string &from_lang, const std::stri
|
|||
{
|
||||
LLTranslationAPIHandler& handler = getPreferredHandler();
|
||||
|
||||
handler.translateMessage(LLTranslationAPIHandler::LanguagePair_t(from_lang, to_lang), mesg, success, failure);
|
||||
handler.translateMessage(LLTranslationAPIHandler::LanguagePair_t(from_lang, to_lang), addNoTranslateTags(mesg), success, failure);
|
||||
}
|
||||
|
||||
std::string LLTranslate::addNoTranslateTags(std::string mesg)
|
||||
{
|
||||
if (getPreferredHandler().getCurrentService() != SERVICE_BING)
|
||||
{
|
||||
return mesg;
|
||||
}
|
||||
|
||||
std::string upd_msg(mesg);
|
||||
LLUrlMatch match;
|
||||
S32 dif = 0;
|
||||
//surround all links (including SLURLs) with 'no-translate' tags to prevent unnecessary translation
|
||||
while (LLUrlRegistry::instance().findUrl(mesg, match))
|
||||
{
|
||||
upd_msg.insert(dif + match.getStart(), BING_NOTRANSLATE_OPENING_TAG);
|
||||
upd_msg.insert(dif + BING_NOTRANSLATE_OPENING_TAG.size() + match.getEnd() + 1, BING_NOTRANSLATE_CLOSING_TAG);
|
||||
mesg.erase(match.getStart(), match.getEnd() - match.getStart());
|
||||
dif += match.getEnd() - match.getStart() + BING_NOTRANSLATE_OPENING_TAG.size() + BING_NOTRANSLATE_CLOSING_TAG.size();
|
||||
}
|
||||
return upd_msg;
|
||||
}
|
||||
|
||||
std::string LLTranslate::removeNoTranslateTags(std::string mesg)
|
||||
{
|
||||
if (getPreferredHandler().getCurrentService() != SERVICE_BING)
|
||||
{
|
||||
return mesg;
|
||||
}
|
||||
std::string upd_msg(mesg);
|
||||
LLUrlMatch match;
|
||||
S32 opening_tag_size = BING_NOTRANSLATE_OPENING_TAG.size();
|
||||
S32 closing_tag_size = BING_NOTRANSLATE_CLOSING_TAG.size();
|
||||
S32 dif = 0;
|
||||
//remove 'no-translate' tags we added to the links before
|
||||
while (LLUrlRegistry::instance().findUrl(mesg, match))
|
||||
{
|
||||
if (upd_msg.substr(dif + match.getStart() - opening_tag_size, opening_tag_size) == BING_NOTRANSLATE_OPENING_TAG)
|
||||
{
|
||||
upd_msg.erase(dif + match.getStart() - opening_tag_size, opening_tag_size);
|
||||
dif -= opening_tag_size;
|
||||
|
||||
if (upd_msg.substr(dif + match.getEnd() + 1, closing_tag_size) == BING_NOTRANSLATE_CLOSING_TAG)
|
||||
{
|
||||
upd_msg.replace(dif + match.getEnd() + 1, closing_tag_size, " ");
|
||||
dif -= closing_tag_size - 1;
|
||||
}
|
||||
}
|
||||
mesg.erase(match.getStart(), match.getUrl().size());
|
||||
dif += match.getUrl().size();
|
||||
}
|
||||
return upd_msg;
|
||||
}
|
||||
|
||||
/*static*/
|
||||
|
|
|
|||
|
|
@ -91,6 +91,9 @@ public :
|
|||
*/
|
||||
static bool isTranslationConfigured();
|
||||
|
||||
static std::string addNoTranslateTags(std::string mesg);
|
||||
static std::string removeNoTranslateTags(std::string mesg);
|
||||
|
||||
private:
|
||||
static LLTranslationAPIHandler& getPreferredHandler();
|
||||
static LLTranslationAPIHandler& getHandler(EService service);
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
#include "llviewerprecompiledheaders.h"
|
||||
|
||||
#include "lltwitterconnect.h"
|
||||
#include "llflickrconnect.h"
|
||||
|
||||
#include "llagent.h"
|
||||
#include "llcallingcard.h" // for LLAvatarTracker
|
||||
|
|
@ -65,6 +66,49 @@ void toast_user_for_twitter_success()
|
|||
LLNotificationsUtil::add("TwitterConnect", args);
|
||||
}
|
||||
|
||||
class LLTwitterConnectHandler : public LLCommandHandler
|
||||
{
|
||||
public:
|
||||
LLTwitterConnectHandler() : LLCommandHandler("fbc", UNTRUSTED_THROTTLE) {}
|
||||
|
||||
bool handle(const LLSD& tokens, const LLSD& query_map, LLMediaCtrl* web)
|
||||
{
|
||||
if (tokens.size() >= 1)
|
||||
{
|
||||
if (tokens[0].asString() == "connect")
|
||||
{
|
||||
if (tokens.size() >= 2 && tokens[1].asString() == "twitter")
|
||||
{
|
||||
// this command probably came from the twitter_web browser, so close it
|
||||
LLFloaterReg::hideInstance("twitter_web");
|
||||
|
||||
// connect to twitter
|
||||
if (query_map.has("oauth_token"))
|
||||
{
|
||||
LLTwitterConnect::instance().connectToTwitter(query_map["oauth_token"], query_map.get("oauth_verifier"));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else if (tokens.size() >= 2 && tokens[1].asString() == "flickr")
|
||||
{
|
||||
// this command probably came from the flickr_web browser, so close it
|
||||
LLFloaterReg::hideInstance("flickr_web");
|
||||
|
||||
// connect to flickr
|
||||
if (query_map.has("oauth_token"))
|
||||
{
|
||||
LLFlickrConnect::instance().connectToFlickr(query_map["oauth_token"], query_map.get("oauth_verifier"));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
LLTwitterConnectHandler gTwitterConnectHandler;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
void LLTwitterConnect::twitterConnectCoro(std::string requestToken, std::string oauthVerifier)
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@
|
|||
// library includes
|
||||
#include "llnotificationsutil.h"
|
||||
#include "llsd.h"
|
||||
#include "stringize.h"
|
||||
|
||||
static LLURLDispatcherListener sURLDispatcherListener;
|
||||
|
||||
|
|
@ -255,14 +256,23 @@ void LLURLDispatcherImpl::regionHandleCallback(U64 region_handle, const LLSLURL&
|
|||
// Teleportation links are handled here because they are tightly coupled
|
||||
// to SLURL parsing and sim-fragment parsing
|
||||
|
||||
class LLTeleportHandler : public LLCommandHandler
|
||||
class LLTeleportHandler : public LLCommandHandler, public LLEventAPI
|
||||
{
|
||||
public:
|
||||
// Teleport requests *must* come from a trusted browser
|
||||
// inside the app, otherwise a malicious web page could
|
||||
// cause a constant teleport loop. JC
|
||||
LLTeleportHandler() : LLCommandHandler("teleport", UNTRUSTED_THROTTLE) { }
|
||||
|
||||
LLTeleportHandler() :
|
||||
LLCommandHandler("teleport", UNTRUSTED_THROTTLE),
|
||||
LLEventAPI("LLTeleportHandler", "Low-level teleport API")
|
||||
{
|
||||
LLEventAPI::add("teleport",
|
||||
"Teleport to specified [\"regionname\"] at\n"
|
||||
"specified region-relative [\"x\"], [\"y\"], [\"z\"].\n"
|
||||
"If [\"regionname\"] omitted, teleport to GLOBAL\n"
|
||||
"coordinates [\"x\"], [\"y\"], [\"z\"].",
|
||||
&LLTeleportHandler::from_event);
|
||||
}
|
||||
|
||||
bool handle(const LLSD& tokens, const LLSD& query_map,
|
||||
LLMediaCtrl* web)
|
||||
|
|
@ -293,6 +303,41 @@ public:
|
|||
return true;
|
||||
}
|
||||
|
||||
void from_event(const LLSD& params) const
|
||||
{
|
||||
Response response(LLSD(), params);
|
||||
if (params.has("regionname"))
|
||||
{
|
||||
// region specified, coordinates (if any) are region-local
|
||||
LLVector3 local_pos(
|
||||
params.has("x")? params["x"].asReal() : 128,
|
||||
params.has("y")? params["y"].asReal() : 128,
|
||||
params.has("z")? params["z"].asReal() : 0);
|
||||
std::string regionname(params["regionname"]);
|
||||
std::string destination(LLSLURL(regionname, local_pos).getSLURLString());
|
||||
// have to resolve region's global coordinates first
|
||||
teleport_via_slapp(regionname, destination);
|
||||
response["message"] = "Teleporting to " + destination;
|
||||
}
|
||||
else // no regionname
|
||||
{
|
||||
// coordinates are global, and at least (x, y) are required
|
||||
if (! (params.has("x") && params.has("y")))
|
||||
{
|
||||
return response.error("Specify either regionname or global (x, y)");
|
||||
}
|
||||
LLVector3d global_pos(params["x"].asReal(), params["y"].asReal(),
|
||||
params["z"].asReal());
|
||||
gAgent.teleportViaLocation(global_pos);
|
||||
LLFloaterWorldMap* instance = LLFloaterWorldMap::getInstance();
|
||||
if (instance)
|
||||
{
|
||||
instance->trackLocation(global_pos);
|
||||
}
|
||||
response["message"] = STRINGIZE("Teleporting to global " << global_pos);
|
||||
}
|
||||
}
|
||||
|
||||
static void teleport_via_slapp(std::string region_name, std::string callback_url)
|
||||
{
|
||||
|
||||
|
|
|
|||
|
|
@ -237,6 +237,7 @@ void display_stats()
|
|||
|
||||
static LLTrace::BlockTimerStatHandle FTM_PICK("Picking");
|
||||
static LLTrace::BlockTimerStatHandle FTM_RENDER("Render");
|
||||
static LLTrace::BlockTimerStatHandle FTM_RENDER_HUD("Render HUD");
|
||||
static LLTrace::BlockTimerStatHandle FTM_UPDATE_SKY("Update Sky");
|
||||
static LLTrace::BlockTimerStatHandle FTM_UPDATE_DYNAMIC_TEXTURES("Update Dynamic Textures");
|
||||
static LLTrace::BlockTimerStatHandle FTM_IMAGE_UPDATE("Update Images");
|
||||
|
|
@ -568,6 +569,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
|
|||
if (gDisconnected)
|
||||
{
|
||||
LLAppViewer::instance()->pingMainloopTimeout("Display:Disconnected");
|
||||
LL_RECORD_BLOCK_TIME(FTM_RENDER_UI);
|
||||
render_ui();
|
||||
swap();
|
||||
}
|
||||
|
|
@ -1293,7 +1295,8 @@ void render_ui(F32 zoom_factor, int subfield)
|
|||
{
|
||||
gPipeline.renderBloom(gSnapshot, zoom_factor, subfield);
|
||||
}
|
||||
|
||||
|
||||
LL_RECORD_BLOCK_TIME(FTM_RENDER_HUD);
|
||||
render_hud_elements();
|
||||
render_hud_attachments();
|
||||
}
|
||||
|
|
@ -1308,8 +1311,6 @@ void render_ui(F32 zoom_factor, int subfield)
|
|||
gGL.color4f(1,1,1,1);
|
||||
if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI))
|
||||
{
|
||||
LL_RECORD_BLOCK_TIME(FTM_RENDER_UI);
|
||||
|
||||
if (!gDisconnected)
|
||||
{
|
||||
render_ui_3d();
|
||||
|
|
|
|||
|
|
@ -67,7 +67,6 @@
|
|||
#include "llfloaterexperiences.h"
|
||||
#include "llfloaterexperiencepicker.h"
|
||||
#include "llfloaterevent.h"
|
||||
#include "llfloaterfacebook.h"
|
||||
#include "llfloaterflickr.h"
|
||||
#include "llfloaterfonttest.h"
|
||||
#include "llfloatergesture.h"
|
||||
|
|
@ -353,11 +352,9 @@ void LLViewerFloaterReg::registerFloaters()
|
|||
LLFloaterReg::add("profile", "floater_web_profile.xml", (LLFloaterBuildFunc)&LLFloaterWebProfile::create);
|
||||
LLFloaterReg::add("how_to", "floater_how_to.xml", (LLFloaterBuildFunc)&LLFloaterWebContent::create);
|
||||
|
||||
LLFloaterReg::add("fbc_web", "floater_fbc_web.xml", (LLFloaterBuildFunc)&LLFloaterWebContent::create);
|
||||
LLFloaterReg::add("flickr_web", "floater_fbc_web.xml", (LLFloaterBuildFunc)&LLFloaterWebContent::create);
|
||||
LLFloaterReg::add("twitter_web", "floater_fbc_web.xml", (LLFloaterBuildFunc)&LLFloaterWebContent::create);
|
||||
|
||||
LLFloaterReg::add("facebook", "floater_facebook.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterFacebook>);
|
||||
LLFloaterReg::add("flickr", "floater_flickr.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterFlickr>);
|
||||
LLFloaterReg::add("twitter", "floater_twitter.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterTwitter>);
|
||||
LLFloaterReg::add("big_preview", "floater_big_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterBigPreview>);
|
||||
|
|
|
|||
|
|
@ -64,7 +64,12 @@ LLViewerKeyboard gViewerKeyboard;
|
|||
|
||||
void agent_jump( EKeystate s )
|
||||
{
|
||||
if( KEYSTATE_UP == s ) return;
|
||||
static BOOL first_fly_attempt(TRUE);
|
||||
if (KEYSTATE_UP == s)
|
||||
{
|
||||
first_fly_attempt = TRUE;
|
||||
return;
|
||||
}
|
||||
F32 time = gKeyboard->getCurKeyElapsedTime();
|
||||
S32 frame_count = ll_round(gKeyboard->getCurKeyElapsedFrameCount());
|
||||
|
||||
|
|
@ -77,7 +82,8 @@ void agent_jump( EKeystate s )
|
|||
}
|
||||
else
|
||||
{
|
||||
gAgent.setFlying(TRUE);
|
||||
gAgent.setFlying(TRUE, first_fly_attempt);
|
||||
first_fly_attempt = FALSE;
|
||||
gAgent.moveUp(1);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue