Merge branch 'lindenlab/release' into viewer/build

master
Kitty Barnett 2019-12-23 01:49:46 +01:00
commit 7a12a8546c
120 changed files with 1560 additions and 4804 deletions

View File

@ -556,6 +556,7 @@ ece699718f163921717bb95a6131e94af4c4138f 6.3.1-release
07f5d5bc9faebb45695853d40a9549773db816c0 6.3.2-release
d9a4bd15e2c852953d6c8e84d6f3b7ca442c0e7f 6.3.3-release
4033b3f57e76f087235145a3016886ccdc87ffa3 6.3.4-release
27ca5834bfe9b80e82db5ea42f08b7eb990b722a 6.3.5-release
0000000000000000000000000000000000000000 v2start
0000000000000000000000000000000000000000 alpha-3
0000000000000000000000000000000000000000 fork to viewer-2-0

View File

@ -3138,9 +3138,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
<key>archive</key>
<map>
<key>hash</key>
<string>42066e2447c7a3359784438d16510992</string>
<string>c5ab9d9d7482e48cd76f4bf391900a8c</string>
<key>url</key>
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/40539/348124/viewer_manager-2.0.529188-darwin64-529188.tar.bz2</string>
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/43369/385585/viewer_manager-2.0.531000-darwin64-531000.tar.bz2</string>
</map>
<key>name</key>
<string>darwin64</string>
@ -3162,9 +3162,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
<key>archive</key>
<map>
<key>hash</key>
<string>ca230428635ce13cb7ace0f9522f8546</string>
<string>6b10d7407686d9e12e63576256581e3e</string>
<key>url</key>
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/40538/348130/viewer_manager-2.0.529188-windows-529188.tar.bz2</string>
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/43370/385592/viewer_manager-2.0.531000-windows-531000.tar.bz2</string>
</map>
<key>name</key>
<string>windows</string>
@ -3175,7 +3175,7 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
<key>source_type</key>
<string>hg</string>
<key>version</key>
<string>2.0.529188</string>
<string>2.0.531000</string>
</map>
<key>vlc-bin</key>
<map>

View File

@ -186,12 +186,17 @@ if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
list(GET LL_BUILD_LIST "${sysroot_idx}" CMAKE_OSX_SYSROOT)
message(STATUS "CMAKE_OSX_SYSROOT = '${CMAKE_OSX_SYSROOT}'")
set(XCODE_VERSION 7.0)
set(CMAKE_XCODE_ATTRIBUTE_GCC_VERSION "com.apple.compilers.llvm.clang.1_0")
set(CMAKE_XCODE_ATTRIBUTE_GCC_STRICT_ALIASING NO)
set(CMAKE_XCODE_ATTRIBUTE_GCC_FAST_MATH NO)
set(CMAKE_XCODE_ATTRIBUTE_CLANG_X86_VECTOR_INSTRUCTIONS ssse3)
# we must hard code this to off for now. xcode's built in signing does not
# handle embedded app bundles such as CEF and others. Any signing for local
# development must be done after the build as we do in viewer_manifest.py for
# released builds
# https://stackoverflow.com/a/54296008
# "-" represents "Sign to Run Locally" and empty string represents "Do Not Sign"
set(CMAKE_XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "")
set(CMAKE_OSX_ARCHITECTURES "${ARCH}")
string(REPLACE "i686" "i386" CMAKE_OSX_ARCHITECTURES "${CMAKE_OSX_ARCHITECTURES}")

View File

@ -107,11 +107,11 @@ BOOL LLGesture::trigger(const std::string& trigger_string)
// NOT endian-neutral
U8 *LLGesture::serialize(U8 *buffer) const
{
htonmemcpy(buffer, &mKey, MVT_S8, 1);
htolememcpy(buffer, &mKey, MVT_S8, 1);
buffer += sizeof(mKey);
htonmemcpy(buffer, &mMask, MVT_U32, 4);
htolememcpy(buffer, &mMask, MVT_U32, 4);
buffer += sizeof(mMask);
htonmemcpy(buffer, mSoundItemID.mData, MVT_LLUUID, 16);
htolememcpy(buffer, mSoundItemID.mData, MVT_LLUUID, 16);
buffer += 16;
memcpy(buffer, mTrigger.c_str(), mTrigger.length() + 1); /* Flawfinder: ignore */
@ -134,11 +134,11 @@ U8 *LLGesture::deserialize(U8 *buffer, S32 max_size)
return buffer;
}
htonmemcpy(&mKey, tmp, MVT_S8, 1);
htolememcpy(&mKey, tmp, MVT_S8, 1);
tmp += sizeof(mKey);
htonmemcpy(&mMask, tmp, MVT_U32, 4);
htolememcpy(&mMask, tmp, MVT_U32, 4);
tmp += sizeof(mMask);
htonmemcpy(mSoundItemID.mData, tmp, MVT_LLUUID, 16);
htolememcpy(mSoundItemID.mData, tmp, MVT_LLUUID, 16);
tmp += 16;
mTrigger.assign((char *)tmp);
@ -284,7 +284,7 @@ U8 *LLGestureList::serialize(U8 *buffer) const
{
// a single S32 serves as the header that tells us how many to read
U32 count = mList.size();
htonmemcpy(buffer, &count, MVT_S32, 4);
htolememcpy(buffer, &count, MVT_S32, 4);
buffer += sizeof(count);
for (S32 i = 0; i < count; i++)
@ -310,7 +310,7 @@ U8 *LLGestureList::deserialize(U8 *buffer, S32 max_size)
return buffer;
}
htonmemcpy(&count, tmp, MVT_S32, 4);
htolememcpy(&count, tmp, MVT_S32, 4);
if (count > MAX_GESTURES)
{

View File

@ -347,7 +347,7 @@ void LLCoros::toplevel(coro::self& self, CoroData* data, const callable_t& calla
// run the code the caller actually wants in the coroutine
try
{
#if LL_WINDOWS
#if LL_WINDOWS && LL_RELEASE_FOR_DOWNLOAD
winlevel(callable);
#else
callable();

View File

@ -2168,19 +2168,27 @@ bool LLImageFormatted::load(const std::string &filename, int load_size)
}
bool res;
U8 *data = allocateData(load_size);
apr_size_t bytes_read = load_size;
apr_status_t s = apr_file_read(apr_file, data, &bytes_read); // modifies bytes_read
if (s != APR_SUCCESS || (S32) bytes_read != load_size)
if (data)
{
deleteData();
setLastError("Unable to read file",filename);
res = false;
apr_size_t bytes_read = load_size;
apr_status_t s = apr_file_read(apr_file, data, &bytes_read); // modifies bytes_read
if (s != APR_SUCCESS || (S32) bytes_read != load_size)
{
deleteData();
setLastError("Unable to read file",filename);
res = false;
}
else
{
res = updateData();
}
}
else
{
res = updateData();
setLastError("Allocation failure", filename);
res = false;
}
return res;
}

View File

@ -2419,7 +2419,7 @@ bool LLVolume::unpackVolumeFaces(std::istream& is, S32 size)
if (idx.empty() || face.mNumIndices < 3)
{ //why is there an empty index list?
LL_WARNS() <<"Empty face present!" << LL_ENDL;
LL_WARNS() << "Empty face present! Face index: " << i << " Total: " << face_count << LL_ENDL;
continue;
}
@ -5236,7 +5236,7 @@ bool LLVolumeFace::cacheOptimize()
LLVCacheLRU cache;
if (mNumVertices < 3)
if (mNumVertices < 3 || mNumIndices < 3)
{ //nothing to do
return true;
}

View File

@ -186,7 +186,7 @@ BOOL LLDataPackerBinaryBuffer::packString(const std::string& value, const char *
if (mWriteEnabled)
{
htonmemcpy(mCurBufferp, value.c_str(), MVT_VARIABLE, length);
htolememcpy(mCurBufferp, value.c_str(), MVT_VARIABLE, length);
}
mCurBufferp += length;
return success;
@ -213,12 +213,12 @@ BOOL LLDataPackerBinaryBuffer::packBinaryData(const U8 *value, S32 size, const c
if (mWriteEnabled)
{
htonmemcpy(mCurBufferp, &size, MVT_S32, 4);
htolememcpy(mCurBufferp, &size, MVT_S32, 4);
}
mCurBufferp += 4;
if (mWriteEnabled)
{
htonmemcpy(mCurBufferp, value, MVT_VARIABLE, size);
htolememcpy(mCurBufferp, value, MVT_VARIABLE, size);
}
mCurBufferp += size;
return success;
@ -229,12 +229,12 @@ BOOL LLDataPackerBinaryBuffer::unpackBinaryData(U8 *value, S32 &size, const char
{
BOOL success = TRUE;
success &= verifyLength(4, name);
htonmemcpy(&size, mCurBufferp, MVT_S32, 4);
htolememcpy(&size, mCurBufferp, MVT_S32, 4);
mCurBufferp += 4;
success &= verifyLength(size, name);
if (success)
{
htonmemcpy(value, mCurBufferp, MVT_VARIABLE, size);
htolememcpy(value, mCurBufferp, MVT_VARIABLE, size);
mCurBufferp += size;
}
else
@ -253,7 +253,7 @@ BOOL LLDataPackerBinaryBuffer::packBinaryDataFixed(const U8 *value, S32 size, co
if (mWriteEnabled)
{
htonmemcpy(mCurBufferp, value, MVT_VARIABLE, size);
htolememcpy(mCurBufferp, value, MVT_VARIABLE, size);
}
mCurBufferp += size;
return success;
@ -264,7 +264,7 @@ BOOL LLDataPackerBinaryBuffer::unpackBinaryDataFixed(U8 *value, S32 size, const
{
BOOL success = TRUE;
success &= verifyLength(size, name);
htonmemcpy(value, mCurBufferp, MVT_VARIABLE, size);
htolememcpy(value, mCurBufferp, MVT_VARIABLE, size);
mCurBufferp += size;
return success;
}
@ -302,7 +302,7 @@ BOOL LLDataPackerBinaryBuffer::packU16(const U16 value, const char *name)
if (mWriteEnabled)
{
htonmemcpy(mCurBufferp, &value, MVT_U16, 2);
htolememcpy(mCurBufferp, &value, MVT_U16, 2);
}
mCurBufferp += 2;
return success;
@ -314,7 +314,7 @@ BOOL LLDataPackerBinaryBuffer::unpackU16(U16 &value, const char *name)
BOOL success = TRUE;
success &= verifyLength(sizeof(U16), name);
htonmemcpy(&value, mCurBufferp, MVT_U16, 2);
htolememcpy(&value, mCurBufferp, MVT_U16, 2);
mCurBufferp += 2;
return success;
}
@ -327,7 +327,7 @@ BOOL LLDataPackerBinaryBuffer::packU32(const U32 value, const char *name)
if (mWriteEnabled)
{
htonmemcpy(mCurBufferp, &value, MVT_U32, 4);
htolememcpy(mCurBufferp, &value, MVT_U32, 4);
}
mCurBufferp += 4;
return success;
@ -339,7 +339,7 @@ BOOL LLDataPackerBinaryBuffer::unpackU32(U32 &value, const char *name)
BOOL success = TRUE;
success &= verifyLength(sizeof(U32), name);
htonmemcpy(&value, mCurBufferp, MVT_U32, 4);
htolememcpy(&value, mCurBufferp, MVT_U32, 4);
mCurBufferp += 4;
return success;
}
@ -352,7 +352,7 @@ BOOL LLDataPackerBinaryBuffer::packS32(const S32 value, const char *name)
if (mWriteEnabled)
{
htonmemcpy(mCurBufferp, &value, MVT_S32, 4);
htolememcpy(mCurBufferp, &value, MVT_S32, 4);
}
mCurBufferp += 4;
return success;
@ -364,7 +364,7 @@ BOOL LLDataPackerBinaryBuffer::unpackS32(S32 &value, const char *name)
BOOL success = TRUE;
success &= verifyLength(sizeof(S32), name);
htonmemcpy(&value, mCurBufferp, MVT_S32, 4);
htolememcpy(&value, mCurBufferp, MVT_S32, 4);
mCurBufferp += 4;
return success;
}
@ -377,7 +377,7 @@ BOOL LLDataPackerBinaryBuffer::packF32(const F32 value, const char *name)
if (mWriteEnabled)
{
htonmemcpy(mCurBufferp, &value, MVT_F32, 4);
htolememcpy(mCurBufferp, &value, MVT_F32, 4);
}
mCurBufferp += 4;
return success;
@ -389,7 +389,7 @@ BOOL LLDataPackerBinaryBuffer::unpackF32(F32 &value, const char *name)
BOOL success = TRUE;
success &= verifyLength(sizeof(F32), name);
htonmemcpy(&value, mCurBufferp, MVT_F32, 4);
htolememcpy(&value, mCurBufferp, MVT_F32, 4);
mCurBufferp += 4;
return success;
}
@ -402,7 +402,7 @@ BOOL LLDataPackerBinaryBuffer::packColor4(const LLColor4 &value, const char *nam
if (mWriteEnabled)
{
htonmemcpy(mCurBufferp, value.mV, MVT_LLVector4, 16);
htolememcpy(mCurBufferp, value.mV, MVT_LLVector4, 16);
}
mCurBufferp += 16;
return success;
@ -414,7 +414,7 @@ BOOL LLDataPackerBinaryBuffer::unpackColor4(LLColor4 &value, const char *name)
BOOL success = TRUE;
success &= verifyLength(16, name);
htonmemcpy(value.mV, mCurBufferp, MVT_LLVector4, 16);
htolememcpy(value.mV, mCurBufferp, MVT_LLVector4, 16);
mCurBufferp += 16;
return success;
}
@ -427,7 +427,7 @@ BOOL LLDataPackerBinaryBuffer::packColor4U(const LLColor4U &value, const char *n
if (mWriteEnabled)
{
htonmemcpy(mCurBufferp, value.mV, MVT_VARIABLE, 4);
htolememcpy(mCurBufferp, value.mV, MVT_VARIABLE, 4);
}
mCurBufferp += 4;
return success;
@ -439,7 +439,7 @@ BOOL LLDataPackerBinaryBuffer::unpackColor4U(LLColor4U &value, const char *name)
BOOL success = TRUE;
success &= verifyLength(4, name);
htonmemcpy(value.mV, mCurBufferp, MVT_VARIABLE, 4);
htolememcpy(value.mV, mCurBufferp, MVT_VARIABLE, 4);
mCurBufferp += 4;
return success;
}
@ -453,8 +453,8 @@ BOOL LLDataPackerBinaryBuffer::packVector2(const LLVector2 &value, const char *n
if (mWriteEnabled)
{
htonmemcpy(mCurBufferp, &value.mV[0], MVT_F32, 4);
htonmemcpy(mCurBufferp+4, &value.mV[1], MVT_F32, 4);
htolememcpy(mCurBufferp, &value.mV[0], MVT_F32, 4);
htolememcpy(mCurBufferp+4, &value.mV[1], MVT_F32, 4);
}
mCurBufferp += 8;
return success;
@ -466,8 +466,8 @@ BOOL LLDataPackerBinaryBuffer::unpackVector2(LLVector2 &value, const char *name)
BOOL success = TRUE;
success &= verifyLength(8, name);
htonmemcpy(&value.mV[0], mCurBufferp, MVT_F32, 4);
htonmemcpy(&value.mV[1], mCurBufferp+4, MVT_F32, 4);
htolememcpy(&value.mV[0], mCurBufferp, MVT_F32, 4);
htolememcpy(&value.mV[1], mCurBufferp+4, MVT_F32, 4);
mCurBufferp += 8;
return success;
}
@ -480,7 +480,7 @@ BOOL LLDataPackerBinaryBuffer::packVector3(const LLVector3 &value, const char *n
if (mWriteEnabled)
{
htonmemcpy(mCurBufferp, value.mV, MVT_LLVector3, 12);
htolememcpy(mCurBufferp, value.mV, MVT_LLVector3, 12);
}
mCurBufferp += 12;
return success;
@ -492,7 +492,7 @@ BOOL LLDataPackerBinaryBuffer::unpackVector3(LLVector3 &value, const char *name)
BOOL success = TRUE;
success &= verifyLength(12, name);
htonmemcpy(value.mV, mCurBufferp, MVT_LLVector3, 12);
htolememcpy(value.mV, mCurBufferp, MVT_LLVector3, 12);
mCurBufferp += 12;
return success;
}
@ -504,7 +504,7 @@ BOOL LLDataPackerBinaryBuffer::packVector4(const LLVector4 &value, const char *n
if (mWriteEnabled)
{
htonmemcpy(mCurBufferp, value.mV, MVT_LLVector4, 16);
htolememcpy(mCurBufferp, value.mV, MVT_LLVector4, 16);
}
mCurBufferp += 16;
return success;
@ -516,7 +516,7 @@ BOOL LLDataPackerBinaryBuffer::unpackVector4(LLVector4 &value, const char *name)
BOOL success = TRUE;
success &= verifyLength(16, name);
htonmemcpy(value.mV, mCurBufferp, MVT_LLVector4, 16);
htolememcpy(value.mV, mCurBufferp, MVT_LLVector4, 16);
mCurBufferp += 16;
return success;
}
@ -528,7 +528,7 @@ BOOL LLDataPackerBinaryBuffer::packUUID(const LLUUID &value, const char *name)
if (mWriteEnabled)
{
htonmemcpy(mCurBufferp, value.mData, MVT_LLUUID, 16);
htolememcpy(mCurBufferp, value.mData, MVT_LLUUID, 16);
}
mCurBufferp += 16;
return success;
@ -540,7 +540,7 @@ BOOL LLDataPackerBinaryBuffer::unpackUUID(LLUUID &value, const char *name)
BOOL success = TRUE;
success &= verifyLength(16, name);
htonmemcpy(value.mData, mCurBufferp, MVT_LLUUID, 16);
htolememcpy(value.mData, mCurBufferp, MVT_LLUUID, 16);
mCurBufferp += 16;
return success;
}

View File

@ -373,7 +373,7 @@ std::string LLMail::encryptIMEmailAddress(const LLUUID& from_agent_id,
// Convert input data into a binary blob
std::vector<U8> data;
data.resize(data_size);
// *NOTE: This may suffer from endian issues. Could be htonmemcpy.
// *NOTE: This may suffer from endian issues. Could be htolememcpy.
memcpy(&data[0], &time, 4);
memcpy(&data[4], &from_agent_id.mData[0], UUID_BYTES);
memcpy(&data[4 + UUID_BYTES], &to_agent_id.mData[0], UUID_BYTES);

View File

@ -47,7 +47,7 @@ void LLMsgVarData::addData(const void *data, S32 size, EMsgVariableType type, S3
{
delete[] mData; // Delete it if it already exists
mData = new U8[size];
htonmemcpy(mData, data, mType, size);
htolememcpy(mData, data, mType, size);
}
}

View File

@ -689,14 +689,14 @@ static S32 buildBlock(U8* buffer, S32 buffer_size, const LLMessageBlock* templat
{
case 1:
sizeb = size;
htonmemcpy(&buffer[result], &sizeb, MVT_U8, 1);
htolememcpy(&buffer[result], &sizeb, MVT_U8, 1);
break;
case 2:
sizeh = size;
htonmemcpy(&buffer[result], &sizeh, MVT_U16, 2);
htolememcpy(&buffer[result], &sizeh, MVT_U16, 2);
break;
case 4:
htonmemcpy(&buffer[result], &size, MVT_S32, 4);
htolememcpy(&buffer[result], &size, MVT_S32, 4);
break;
default:
LL_ERRS() << "Attempting to build variable field with unknown size of " << size << LL_ENDL;

View File

@ -645,15 +645,15 @@ BOOL LLTemplateMessageReader::decodeData(const U8* buffer, const LLHost& sender
switch(data_size)
{
case 1:
htonmemcpy(&tsizeb, &buffer[decode_pos], MVT_U8, 1);
htolememcpy(&tsizeb, &buffer[decode_pos], MVT_U8, 1);
tsize = tsizeb;
break;
case 2:
htonmemcpy(&tsizeh, &buffer[decode_pos], MVT_U16, 2);
htolememcpy(&tsizeh, &buffer[decode_pos], MVT_U16, 2);
tsize = tsizeh;
break;
case 4:
htonmemcpy(&tsize, &buffer[decode_pos], MVT_U32, 4);
htolememcpy(&tsize, &buffer[decode_pos], MVT_U32, 4);
break;
default:
LL_ERRS() << "Attempting to read variable field with unknown size of " << data_size << LL_ENDL;

View File

@ -245,7 +245,7 @@ void LLXfer::sendPacket(S32 packet_num)
num_copy);
}
fdata_size += sizeof(S32);
htonmemcpy(fdata_buf,&mXferSize, MVT_S32, sizeof(S32));
htolememcpy(fdata_buf,&mXferSize, MVT_S32, sizeof(S32));
}
S32 encoded_packetnum = encodePacketNum(packet_num,last_packet);

View File

@ -860,10 +860,10 @@ void null_message_callback(LLMessageSystem *msg, void **data);
//
#if !defined( LL_BIG_ENDIAN ) && !defined( LL_LITTLE_ENDIAN )
#error Unknown endianness for htonmemcpy. Did you miss a common include?
#error Unknown endianness for htolememcpy. Did you miss a common include?
#endif
static inline void *htonmemcpy(void *vs, const void *vct, EMsgVariableType type, size_t n)
static inline void *htolememcpy(void *vs, const void *vct, EMsgVariableType type, size_t n)
{
char *s = (char *)vs;
const char *ct = (const char *)vct;
@ -886,7 +886,7 @@ static inline void *htonmemcpy(void *vs, const void *vct, EMsgVariableType type,
case MVT_S16:
if (n != 2)
{
LL_ERRS() << "Size argument passed to htonmemcpy doesn't match swizzle type size" << LL_ENDL;
LL_ERRS() << "Size argument passed to htolememcpy doesn't match swizzle type size" << LL_ENDL;
}
#ifdef LL_BIG_ENDIAN
*(s + 1) = *(ct);
@ -901,7 +901,7 @@ static inline void *htonmemcpy(void *vs, const void *vct, EMsgVariableType type,
case MVT_F32:
if (n != 4)
{
LL_ERRS() << "Size argument passed to htonmemcpy doesn't match swizzle type size" << LL_ENDL;
LL_ERRS() << "Size argument passed to htolememcpy doesn't match swizzle type size" << LL_ENDL;
}
#ifdef LL_BIG_ENDIAN
*(s + 3) = *(ct);
@ -918,7 +918,7 @@ static inline void *htonmemcpy(void *vs, const void *vct, EMsgVariableType type,
case MVT_F64:
if (n != 8)
{
LL_ERRS() << "Size argument passed to htonmemcpy doesn't match swizzle type size" << LL_ENDL;
LL_ERRS() << "Size argument passed to htolememcpy doesn't match swizzle type size" << LL_ENDL;
}
#ifdef LL_BIG_ENDIAN
*(s + 7) = *(ct);
@ -938,12 +938,12 @@ static inline void *htonmemcpy(void *vs, const void *vct, EMsgVariableType type,
case MVT_LLQuaternion: // We only send x, y, z and infer w (we set x, y, z to ensure that w >= 0)
if (n != 12)
{
LL_ERRS() << "Size argument passed to htonmemcpy doesn't match swizzle type size" << LL_ENDL;
LL_ERRS() << "Size argument passed to htolememcpy doesn't match swizzle type size" << LL_ENDL;
}
#ifdef LL_BIG_ENDIAN
htonmemcpy(s + 8, ct + 8, MVT_F32, 4);
htonmemcpy(s + 4, ct + 4, MVT_F32, 4);
return(htonmemcpy(s, ct, MVT_F32, 4));
htolememcpy(s + 8, ct + 8, MVT_F32, 4);
htolememcpy(s + 4, ct + 4, MVT_F32, 4);
return(htolememcpy(s, ct, MVT_F32, 4));
#else
return(memcpy(s,ct,n)); /* Flawfinder: ignore */
#endif
@ -951,12 +951,12 @@ static inline void *htonmemcpy(void *vs, const void *vct, EMsgVariableType type,
case MVT_LLVector3d:
if (n != 24)
{
LL_ERRS() << "Size argument passed to htonmemcpy doesn't match swizzle type size" << LL_ENDL;
LL_ERRS() << "Size argument passed to htolememcpy doesn't match swizzle type size" << LL_ENDL;
}
#ifdef LL_BIG_ENDIAN
htonmemcpy(s + 16, ct + 16, MVT_F64, 8);
htonmemcpy(s + 8, ct + 8, MVT_F64, 8);
return(htonmemcpy(s, ct, MVT_F64, 8));
htolememcpy(s + 16, ct + 16, MVT_F64, 8);
htolememcpy(s + 8, ct + 8, MVT_F64, 8);
return(htolememcpy(s, ct, MVT_F64, 8));
#else
return(memcpy(s,ct,n)); /* Flawfinder: ignore */
#endif
@ -964,13 +964,13 @@ static inline void *htonmemcpy(void *vs, const void *vct, EMsgVariableType type,
case MVT_LLVector4:
if (n != 16)
{
LL_ERRS() << "Size argument passed to htonmemcpy doesn't match swizzle type size" << LL_ENDL;
LL_ERRS() << "Size argument passed to htolememcpy doesn't match swizzle type size" << LL_ENDL;
}
#ifdef LL_BIG_ENDIAN
htonmemcpy(s + 12, ct + 12, MVT_F32, 4);
htonmemcpy(s + 8, ct + 8, MVT_F32, 4);
htonmemcpy(s + 4, ct + 4, MVT_F32, 4);
return(htonmemcpy(s, ct, MVT_F32, 4));
htolememcpy(s + 12, ct + 12, MVT_F32, 4);
htolememcpy(s + 8, ct + 8, MVT_F32, 4);
htolememcpy(s + 4, ct + 4, MVT_F32, 4);
return(htolememcpy(s, ct, MVT_F32, 4));
#else
return(memcpy(s,ct,n)); /* Flawfinder: ignore */
#endif
@ -978,12 +978,12 @@ static inline void *htonmemcpy(void *vs, const void *vct, EMsgVariableType type,
case MVT_U16Vec3:
if (n != 6)
{
LL_ERRS() << "Size argument passed to htonmemcpy doesn't match swizzle type size" << LL_ENDL;
LL_ERRS() << "Size argument passed to htolememcpy doesn't match swizzle type size" << LL_ENDL;
}
#ifdef LL_BIG_ENDIAN
htonmemcpy(s + 4, ct + 4, MVT_U16, 2);
htonmemcpy(s + 2, ct + 2, MVT_U16, 2);
return(htonmemcpy(s, ct, MVT_U16, 2));
htolememcpy(s + 4, ct + 4, MVT_U16, 2);
htolememcpy(s + 2, ct + 2, MVT_U16, 2);
return(htolememcpy(s, ct, MVT_U16, 2));
#else
return(memcpy(s,ct,n)); /* Flawfinder: ignore */
#endif
@ -991,13 +991,13 @@ static inline void *htonmemcpy(void *vs, const void *vct, EMsgVariableType type,
case MVT_U16Quat:
if (n != 8)
{
LL_ERRS() << "Size argument passed to htonmemcpy doesn't match swizzle type size" << LL_ENDL;
LL_ERRS() << "Size argument passed to htolememcpy doesn't match swizzle type size" << LL_ENDL;
}
#ifdef LL_BIG_ENDIAN
htonmemcpy(s + 6, ct + 6, MVT_U16, 2);
htonmemcpy(s + 4, ct + 4, MVT_U16, 2);
htonmemcpy(s + 2, ct + 2, MVT_U16, 2);
return(htonmemcpy(s, ct, MVT_U16, 2));
htolememcpy(s + 6, ct + 6, MVT_U16, 2);
htolememcpy(s + 4, ct + 4, MVT_U16, 2);
htolememcpy(s + 2, ct + 2, MVT_U16, 2);
return(htolememcpy(s, ct, MVT_U16, 2));
#else
return(memcpy(s,ct,n)); /* Flawfinder: ignore */
#endif
@ -1005,15 +1005,15 @@ static inline void *htonmemcpy(void *vs, const void *vct, EMsgVariableType type,
case MVT_S16Array:
if (n % 2)
{
LL_ERRS() << "Size argument passed to htonmemcpy doesn't match swizzle type size" << LL_ENDL;
LL_ERRS() << "Size argument passed to htolememcpy doesn't match swizzle type size" << LL_ENDL;
}
#ifdef LL_BIG_ENDIAN
length = n % 2;
for (i = 1; i < length; i++)
{
htonmemcpy(s + i*2, ct + i*2, MVT_S16, 2);
htolememcpy(s + i*2, ct + i*2, MVT_S16, 2);
}
return(htonmemcpy(s, ct, MVT_S16, 2));
return(htolememcpy(s, ct, MVT_S16, 2));
#else
return(memcpy(s,ct,n));
#endif
@ -1025,7 +1025,7 @@ static inline void *htonmemcpy(void *vs, const void *vct, EMsgVariableType type,
inline void *ntohmemcpy(void *s, const void *ct, EMsgVariableType type, size_t n)
{
return(htonmemcpy(s,ct,type, n));
return(htolememcpy(s,ct,type, n));
}
inline const LLHost& LLMessageSystem::getReceivingInterface() const {return mLastReceivingIF;}

View File

@ -33,7 +33,7 @@
#include "llpluginmessagepipe.h"
#include "llpluginmessageclasses.h"
static const F32 GOODBYE_SECONDS = 20.0f;
static const F32 GOODBYE_SECONDS = 12.0f; // Do not set it to be bigger than mPluginLockupTimeout or parent will kill LLPluginProcessChild
static const F32 HEARTBEAT_SECONDS = 1.0f;
static const F32 PLUGIN_IDLE_SECONDS = 1.0f / 100.0f; // Each call to idle will give the plugin this much time.
@ -218,6 +218,11 @@ void LLPluginProcessChild::idle(void)
if (mWaitGoodbye.hasExpired())
{
LL_WARNS() << "Wait for goodbye expired. Advancing to UNLOADED" << LL_ENDL;
if (mInstance != NULL)
{
// Something went wrong, at least make sure plugin will terminate
sendMessageToPlugin(LLPluginMessage("base", "force_exit"));
}
setState(STATE_UNLOADED);
}
break;

View File

@ -1013,7 +1013,7 @@ S32 LLPrimitive::packTEField(U8 *cur_ptr, U8 *data_ptr, U8 data_size, U8 last_fa
U64 exception_faces;
U8 *start_loc = cur_ptr;
htonmemcpy(cur_ptr,data_ptr + (last_face_index * data_size), type, data_size);
htolememcpy(cur_ptr,data_ptr + (last_face_index * data_size), type, data_size);
cur_ptr += data_size;
for (face_index = last_face_index-1; face_index >= 0; face_index--)
@ -1072,7 +1072,7 @@ S32 LLPrimitive::packTEField(U8 *cur_ptr, U8 *data_ptr, U8 data_size, U8 last_fa
*cur_ptr++ = (U8)(exception_faces & 0x7F);
htonmemcpy(cur_ptr,data_ptr + (face_index * data_size), type, data_size);
htolememcpy(cur_ptr,data_ptr + (face_index * data_size), type, data_size);
cur_ptr += data_size;
}
}
@ -1083,7 +1083,7 @@ S32 LLPrimitive::unpackTEField(U8 *cur_ptr, U8 *buffer_end, U8 *data_ptr, U8 dat
{
U8 *start_loc = cur_ptr;
U64 i;
htonmemcpy(data_ptr,cur_ptr, type,data_size);
htolememcpy(data_ptr,cur_ptr, type,data_size);
cur_ptr += data_size;
for (i = 1; i < face_count; i++)
@ -1108,7 +1108,7 @@ S32 LLPrimitive::unpackTEField(U8 *cur_ptr, U8 *buffer_end, U8 *data_ptr, U8 dat
{
if (i & 0x01)
{
htonmemcpy(data_ptr+(j*data_size),cur_ptr,type,data_size);
htolememcpy(data_ptr+(j*data_size),cur_ptr,type,data_size);
LL_DEBUGS("TEFieldDecode") << "Assigning " ;
char foo[64];
sprintf(foo,"%x %x",*(data_ptr+(j*data_size)), *(data_ptr+(j*data_size)+1));

View File

@ -94,9 +94,9 @@ void LLTextureAnim::packTAMessage(LLMessageSystem *mesgsys) const
data[1] = mFace;
data[2] = mSizeX;
data[3] = mSizeY;
htonmemcpy(data + 4, &mStart, MVT_F32, sizeof(F32));
htonmemcpy(data + 8, &mLength, MVT_F32, sizeof(F32));
htonmemcpy(data + 12, &mRate, MVT_F32, sizeof(F32));
htolememcpy(data + 4, &mStart, MVT_F32, sizeof(F32));
htolememcpy(data + 8, &mLength, MVT_F32, sizeof(F32));
htolememcpy(data + 12, &mRate, MVT_F32, sizeof(F32));
mesgsys->addBinaryDataFast(_PREHASH_TextureAnim, data, TA_BLOCK_SIZE);
}
@ -109,9 +109,9 @@ void LLTextureAnim::packTAMessage(LLDataPacker &dp) const
data[1] = mFace;
data[2] = mSizeX;
data[3] = mSizeY;
htonmemcpy(data + 4, &mStart, MVT_F32, sizeof(F32));
htonmemcpy(data + 8, &mLength, MVT_F32, sizeof(F32));
htonmemcpy(data + 12, &mRate, MVT_F32, sizeof(F32));
htolememcpy(data + 4, &mStart, MVT_F32, sizeof(F32));
htolememcpy(data + 8, &mLength, MVT_F32, sizeof(F32));
htolememcpy(data + 12, &mRate, MVT_F32, sizeof(F32));
dp.packBinaryData(data, TA_BLOCK_SIZE, "TextureAnimation");
}
@ -146,9 +146,9 @@ void LLTextureAnim::unpackTAMessage(LLMessageSystem *mesgsys, const S32 block_nu
mSizeX = llmax((U8)1, data[2]);
mSizeY = llmax((U8)1, data[3]);
}
htonmemcpy(&mStart, data + 4, MVT_F32, sizeof(F32));
htonmemcpy(&mLength, data + 8, MVT_F32, sizeof(F32));
htonmemcpy(&mRate, data + 12, MVT_F32, sizeof(F32));
htolememcpy(&mStart, data + 4, MVT_F32, sizeof(F32));
htolememcpy(&mLength, data + 8, MVT_F32, sizeof(F32));
htolememcpy(&mRate, data + 12, MVT_F32, sizeof(F32));
}
void LLTextureAnim::unpackTAMessage(LLDataPacker &dp)
@ -170,9 +170,9 @@ void LLTextureAnim::unpackTAMessage(LLDataPacker &dp)
mFace = data[1];
mSizeX = data[2];
mSizeY = data[3];
htonmemcpy(&mStart, data + 4, MVT_F32, sizeof(F32));
htonmemcpy(&mLength, data + 8, MVT_F32, sizeof(F32));
htonmemcpy(&mRate, data + 12, MVT_F32, sizeof(F32));
htolememcpy(&mStart, data + 4, MVT_F32, sizeof(F32));
htolememcpy(&mLength, data + 8, MVT_F32, sizeof(F32));
htolememcpy(&mRate, data + 12, MVT_F32, sizeof(F32));
}
LLSD LLTextureAnim::asLLSD() const

View File

@ -454,13 +454,13 @@ std::string LLUrlEntrySLURL::getLocation(const std::string &url) const
}
//
// LLUrlEntrySeconlifeURL Describes *secondlife.com/ and *lindenlab.com/ urls to substitute icon 'hand.png' before link
// LLUrlEntrySeconlifeURL Describes *secondlife.com/ *lindenlab.com/ and *tilia-inc.com/ urls to substitute icon 'hand.png' before link
//
LLUrlEntrySecondlifeURL::LLUrlEntrySecondlifeURL()
{
mPattern = boost::regex("((http://([-\\w\\.]*\\.)?(secondlife|lindenlab)\\.com)"
mPattern = boost::regex("((http://([-\\w\\.]*\\.)?(secondlife|lindenlab|tilia-inc)\\.com)"
"|"
"(https://([-\\w\\.]*\\.)?(secondlife|lindenlab)\\.com(:\\d{1,5})?))"
"(https://([-\\w\\.]*\\.)?(secondlife|lindenlab|tilia-inc)\\.com(:\\d{1,5})?))"
"\\/\\S*",
boost::regex::perl|boost::regex::icase);
@ -495,11 +495,11 @@ std::string LLUrlEntrySecondlifeURL::getTooltip(const std::string &url) const
}
//
// LLUrlEntrySimpleSecondlifeURL Describes *secondlife.com and *lindenlab.com urls to substitute icon 'hand.png' before link
// LLUrlEntrySimpleSecondlifeURL Describes *secondlife.com *lindenlab.com and *tilia-inc.com urls to substitute icon 'hand.png' before link
//
LLUrlEntrySimpleSecondlifeURL::LLUrlEntrySimpleSecondlifeURL()
{
mPattern = boost::regex("https?://([-\\w\\.]*\\.)?(secondlife|lindenlab)\\.com(?!\\S)",
mPattern = boost::regex("https?://([-\\w\\.]*\\.)?(secondlife|lindenlab|tilia-inc)\\.com(?!\\S)",
boost::regex::perl|boost::regex::icase);
mIcon = "Hand";

View File

@ -875,10 +875,16 @@ BOOL LLView::handleToolTip(S32 x, S32 y, MASK mask)
F32 timeout = LLToolTipMgr::instance().toolTipVisible()
? LLUI::getInstance()->mSettingGroups["config"]->getF32( "ToolTipFastDelay" )
: LLUI::getInstance()->mSettingGroups["config"]->getF32( "ToolTipDelay" );
LLToolTipMgr::instance().show(LLToolTip::Params()
.message(tooltip)
.sticky_rect(calcScreenRect())
.delay_time(timeout));
// Even if we don't show tooltips, consume the event, nothing below should show tooltip
bool allow_ui_tooltips = LLUI::getInstance()->mSettingGroups["config"]->getBOOL("BasicUITooltips");
if (allow_ui_tooltips)
{
LLToolTipMgr::instance().show(LLToolTip::Params()
.message(tooltip)
.sticky_rect(calcScreenRect())
.delay_time(timeout));
}
handled = TRUE;
}

View File

@ -38,6 +38,10 @@ BOOL LLMouseHandler::handleAnyMouseClick(S32 x, S32 y, MASK mask, EClickType cli
case CLICK_RIGHT: handled = handleRightMouseDown(x, y, mask); break;
case CLICK_MIDDLE: handled = handleMiddleMouseDown(x, y, mask); break;
case CLICK_DOUBLELEFT: handled = handleDoubleClick(x, y, mask); break;
case CLICK_BUTTON4:
case CLICK_BUTTON5:
LL_INFOS() << "Handle mouse button " << clicktype + 1 << " down." << LL_ENDL;
break;
default:
LL_WARNS() << "Unhandled enum." << LL_ENDL;
}
@ -50,6 +54,10 @@ BOOL LLMouseHandler::handleAnyMouseClick(S32 x, S32 y, MASK mask, EClickType cli
case CLICK_RIGHT: handled = handleRightMouseUp(x, y, mask); break;
case CLICK_MIDDLE: handled = handleMiddleMouseUp(x, y, mask); break;
case CLICK_DOUBLELEFT: handled = handleDoubleClick(x, y, mask); break;
case CLICK_BUTTON4:
case CLICK_BUTTON5:
LL_INFOS() << "Handle mouse button " << clicktype + 1 << " up." << LL_ENDL;
break;
default:
LL_WARNS() << "Unhandled enum." << LL_ENDL;
}

View File

@ -50,6 +50,8 @@ public:
CLICK_LEFT,
CLICK_MIDDLE,
CLICK_RIGHT,
CLICK_BUTTON4,
CLICK_BUTTON5,
CLICK_DOUBLELEFT
} EClickType;

View File

@ -444,7 +444,7 @@ attributedStringInfo getSegments(NSAttributedString *str)
NSPoint mPoint = gHiDPISupport ? [self convertPointToBacking:[theEvent locationInWindow]] : [theEvent locationInWindow];
mMousePos[0] = mPoint.x;
mMousePos[1] = mPoint.y;
callMiddleMouseDown(mMousePos, [theEvent modifierFlags]);
callOtherMouseDown(mMousePos, [theEvent modifierFlags], [theEvent buttonNumber]);
}
- (void) otherMouseUp:(NSEvent *)theEvent
@ -452,7 +452,7 @@ attributedStringInfo getSegments(NSAttributedString *str)
NSPoint mPoint = gHiDPISupport ? [self convertPointToBacking:[theEvent locationInWindow]] : [theEvent locationInWindow];
mMousePos[0] = mPoint.x;
mMousePos[1] = mPoint.y;
callMiddleMouseUp(mMousePos, [theEvent modifierFlags]);
callOtherMouseUp(mMousePos, [theEvent modifierFlags], [theEvent buttonNumber]);
}
- (void) rightMouseDragged:(NSEvent *)theEvent
@ -816,7 +816,7 @@ attributedStringInfo getSegments(NSAttributedString *str)
[super setMarkedText:aString selectedRange:selectedRange replacementRange:replacementRange];
if ([aString length] == 0) // this means Input Widow becomes empty
{
[_window orderOut:_window]; // Close this to avoid empty Input Window
[self.window orderOut:self.window]; // Close this to avoid empty Input Window
}
}
@ -840,7 +840,7 @@ attributedStringInfo getSegments(NSAttributedString *str)
(mKeyPressed >= 0xF700 && mKeyPressed <= 0xF8FF))
{
// this is case a) of above comment
[_window orderOut:_window]; // to avoid empty Input Window
[self.window orderOut:self.window]; // to avoid empty Input Window
}
}

View File

@ -98,6 +98,16 @@ BOOL LLWindowCallbacks::handleMiddleMouseUp(LLWindow *window, const LLCoordGL po
return FALSE;
}
BOOL LLWindowCallbacks::handleOtherMouseDown(LLWindow *window, const LLCoordGL pos, MASK mask, S32 button)
{
return FALSE;
}
BOOL LLWindowCallbacks::handleOtherMouseUp(LLWindow *window, const LLCoordGL pos, MASK mask, S32 button)
{
return FALSE;
}
BOOL LLWindowCallbacks::handleActivate(LLWindow *window, BOOL activated)
{
return FALSE;

View File

@ -49,6 +49,8 @@ public:
virtual BOOL handleRightMouseUp(LLWindow *window, LLCoordGL pos, MASK mask);
virtual BOOL handleMiddleMouseDown(LLWindow *window, LLCoordGL pos, MASK mask);
virtual BOOL handleMiddleMouseUp(LLWindow *window, LLCoordGL pos, MASK mask);
virtual BOOL handleOtherMouseDown(LLWindow *window, LLCoordGL pos, MASK mask, S32 button);
virtual BOOL handleOtherMouseUp(LLWindow *window, LLCoordGL pos, MASK mask, S32 button);
virtual BOOL handleActivate(LLWindow *window, BOOL activated);
virtual BOOL handleActivateApp(LLWindow *window, BOOL activating);
virtual void handleMouseMove(LLWindow *window, LLCoordGL pos, MASK mask);

View File

@ -150,8 +150,8 @@ void callWindowHide();
void callWindowUnhide();
void callWindowDidChangeScreen();
void callDeltaUpdate(float *delta, unsigned int mask);
void callMiddleMouseDown(float *pos, unsigned int mask);
void callMiddleMouseUp(float *pos, unsigned int mask);
void callOtherMouseDown(float *pos, unsigned int mask, int button);
void callOtherMouseUp(float *pos, unsigned int mask, int button);
void callFocus();
void callFocusLost();
void callModifier(unsigned int mask);

View File

@ -417,7 +417,7 @@ void callDeltaUpdate(float *delta, MASK mask)
gWindowImplementation->updateMouseDeltas(delta);
}
void callMiddleMouseDown(float *pos, MASK mask)
void callOtherMouseDown(float *pos, MASK mask, int button)
{
LLCoordGL outCoords;
outCoords.mX = ll_round(pos[0]);
@ -426,10 +426,18 @@ void callMiddleMouseDown(float *pos, MASK mask)
gWindowImplementation->getMouseDeltas(deltas);
outCoords.mX += deltas[0];
outCoords.mY += deltas[1];
gWindowImplementation->getCallbacks()->handleMiddleMouseDown(gWindowImplementation, outCoords, mask);
if (button == 2)
{
gWindowImplementation->getCallbacks()->handleMiddleMouseDown(gWindowImplementation, outCoords, mask);
}
else
{
gWindowImplementation->getCallbacks()->handleOtherMouseDown(gWindowImplementation, outCoords, mask, button + 1);
}
}
void callMiddleMouseUp(float *pos, MASK mask)
void callOtherMouseUp(float *pos, MASK mask, int button)
{
LLCoordGL outCoords;
outCoords.mX = ll_round(pos[0]);
@ -437,8 +445,15 @@ void callMiddleMouseUp(float *pos, MASK mask)
float deltas[2];
gWindowImplementation->getMouseDeltas(deltas);
outCoords.mX += deltas[0];
outCoords.mY += deltas[1];
gWindowImplementation->getCallbacks()->handleMiddleMouseUp(gWindowImplementation, outCoords, mask);
outCoords.mY += deltas[1];
if (button == 2)
{
gWindowImplementation->getCallbacks()->handleMiddleMouseUp(gWindowImplementation, outCoords, mask);
}
else
{
gWindowImplementation->getCallbacks()->handleOtherMouseUp(gWindowImplementation, outCoords, mask, button + 1);
}
}
void callModifier(MASK mask)

View File

@ -2539,6 +2539,72 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
}
}
break;
case WM_XBUTTONDOWN:
{
window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_MBUTTONDOWN");
LL_RECORD_BLOCK_TIME(FTM_MOUSEHANDLER);
S32 button = GET_XBUTTON_WPARAM(w_param);
if (LLWinImm::isAvailable() && window_imp->mPreeditor)
{
window_imp->interruptLanguageTextInput();
}
// Because we move the cursor position in tllviewerhe app, we need to query
// to find out where the cursor at the time the event is handled.
// If we don't do this, many clicks could get buffered up, and if the
// first click changes the cursor position, all subsequent clicks
// will occur at the wrong location. JC
if (window_imp->mMousePositionModified)
{
LLCoordWindow cursor_coord_window;
window_imp->getCursorPosition(&cursor_coord_window);
gl_coord = cursor_coord_window.convert();
}
else
{
gl_coord = window_coord.convert();
}
MASK mask = gKeyboard->currentMask(TRUE);
// generate move event to update mouse coordinates
window_imp->mCallbacks->handleMouseMove(window_imp, gl_coord, mask);
// Windows uses numbers 1 and 2 for buttons, remap to 4, 5
if (window_imp->mCallbacks->handleOtherMouseDown(window_imp, gl_coord, mask, button + 3))
{
return 0;
}
}
break;
case WM_XBUTTONUP:
{
window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_MBUTTONUP");
LL_RECORD_BLOCK_TIME(FTM_MOUSEHANDLER);
S32 button = GET_XBUTTON_WPARAM(w_param);
// Because we move the cursor position in the llviewer app, we need to query
// to find out where the cursor at the time the event is handled.
// If we don't do this, many clicks could get buffered up, and if the
// first click changes the cursor position, all subsequent clicks
// will occur at the wrong location. JC
if (window_imp->mMousePositionModified)
{
LLCoordWindow cursor_coord_window;
window_imp->getCursorPosition(&cursor_coord_window);
gl_coord = cursor_coord_window.convert();
}
else
{
gl_coord = window_coord.convert();
}
MASK mask = gKeyboard->currentMask(TRUE);
// generate move event to update mouse coordinates
window_imp->mCallbacks->handleMouseMove(window_imp, gl_coord, mask);
// Windows uses numbers 1 and 2 for buttons, remap to 4, 5
if (window_imp->mCallbacks->handleOtherMouseUp(window_imp, gl_coord, mask, button + 3))
{
return 0;
}
}
break;
case WM_MOUSEWHEEL:
{

View File

@ -241,6 +241,7 @@ void MediaPluginCEF::onRequestExitCallback()
LLPluginMessage message("base", "goodbye");
sendMessage(message);
// Will trigger delete on next staticReceiveMessage()
mDeleteMe = true;
}
@ -437,9 +438,13 @@ void MediaPluginCEF::receiveMessage(const char* message_string)
}
else if (message_name == "cleanup")
{
mVolumeCatcher.setVolume(0);
mVolumeCatcher.setVolume(0); // Hack: masks CEF exit issues
mCEFLib->requestExit();
}
else if (message_name == "force_exit")
{
mDeleteMe = true;
}
else if (message_name == "shm_added")
{
SharedSegmentInfo info;

View File

@ -128,6 +128,10 @@ void mediaPluginExample::receiveMessage(const char* message_string)
mDeleteMe = true;
}
else if (message_name == "force_exit")
{
mDeleteMe = true;
}
else if (message_name == "shm_added")
{
SharedSegmentInfo info;

View File

@ -495,6 +495,10 @@ void MediaPluginLibVLC::receiveMessage(const char* message_string)
{
resetVLC();
}
else if (message_name == "force_exit")
{
mDeleteMe = true;
}
else if (message_name == "shm_added")
{
SharedSegmentInfo info;

View File

@ -208,7 +208,6 @@ set(viewer_SOURCE_FILES
llfilteredwearablelist.cpp
llfirstuse.cpp
llflexibleobject.cpp
llflickrconnect.cpp
llfloaterabout.cpp
llfloaterbvhpreview.cpp
llfloaterauction.cpp
@ -244,7 +243,6 @@ set(viewer_SOURCE_FILES
llfloaterexperiencepicker.cpp
llfloaterexperienceprofile.cpp
llfloaterexperiences.cpp
llfloaterflickr.cpp
llfloaterfonttest.cpp
llfloatergesture.cpp
llfloatergodtools.cpp
@ -317,7 +315,6 @@ set(viewer_SOURCE_FILES
llfloatertos.cpp
llfloatertoybox.cpp
llfloatertranslationsettings.cpp
llfloatertwitter.cpp
llfloateruipreview.cpp
llfloaterurlentry.cpp
llfloatervoiceeffect.cpp
@ -615,7 +612,6 @@ set(viewer_SOURCE_FILES
lltransientdockablefloater.cpp
lltransientfloatermgr.cpp
lltranslate.cpp
lltwitterconnect.cpp
lluiavatar.cpp
lluilistener.cpp
lluploaddialog.cpp
@ -833,7 +829,6 @@ set(viewer_HEADER_FILES
llfilteredwearablelist.h
llfirstuse.h
llflexibleobject.h
llflickrconnect.h
llfloaterabout.h
llfloaterbvhpreview.h
llfloaterauction.h
@ -869,7 +864,6 @@ set(viewer_HEADER_FILES
llfloaterexperiencepicker.h
llfloaterexperienceprofile.h
llfloaterexperiences.h
llfloaterflickr.h
llfloaterfonttest.h
llfloatergesture.h
llfloatergodtools.h
@ -945,7 +939,6 @@ set(viewer_HEADER_FILES
llfloatertos.h
llfloatertoybox.h
llfloatertranslationsettings.h
llfloatertwitter.h
llfloateruipreview.h
llfloaterurlentry.h
llfloatervoiceeffect.h
@ -1233,7 +1226,6 @@ set(viewer_HEADER_FILES
lltransientdockablefloater.h
lltransientfloatermgr.h
lltranslate.h
lltwitterconnect.h
lluiconstants.h
lluiavatar.h
lluilistener.h

View File

@ -1 +1 @@
6.3.4
6.3.5

View File

@ -228,26 +228,6 @@
is_running_function="Floater.IsOpen"
is_running_parameters="snapshot"
/>
<command name="flickr"
available_in_toybox="true"
icon="Command_Flickr_Icon"
label_ref="Command_Flickr_Label"
tooltip_ref="Command_Flickr_Tooltip"
execute_function="Floater.ToggleOrBringToFront"
execute_parameters="flickr"
is_running_function="Floater.IsOpen"
is_running_parameters="flickr"
/>
<command name="twitter"
available_in_toybox="true"
icon="Command_Twitter_Icon"
label_ref="Command_Twitter_Label"
tooltip_ref="Command_Twitter_Tooltip"
execute_function="Floater.ToggleOrBringToFront"
execute_parameters="twitter"
is_running_function="Floater.IsOpen"
is_running_parameters="twitter"
/>
<command name="speak"
available_in_toybox="true"
icon="Command_Speak_Icon"

View File

@ -5304,7 +5304,7 @@
<key>Type</key>
<string>String</string>
<key>Value</key>
<string>https://secondlife-status.statuspage.io/history.atom</string>
<string>https://status.secondlifegrid.net/history.atom</string>
</map>
<key>GridStatusUpdateDelay</key>
<map>
@ -11219,6 +11219,17 @@
<key>Value</key>
<integer>1</integer>
</map>
<key>BasicUITooltips</key>
<map>
<key>Comment</key>
<string>Show tooltips for various 2D UI elements like buttons or checkboxes, won't supress tooltips like drag'n'drop, inworld, links or media</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>1</integer>
</map>
<key>ShowHoverTips</key>
<map>
<key>Comment</key>
@ -13133,6 +13144,17 @@
<key>Value</key>
<real>3</real>
</map>
<key>HUDScaleFactor</key>
<map>
<key>Comment</key>
<string>Scale of HUD attachments</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>F32</string>
<key>Value</key>
<real>1.0</real>
</map>
<key>UIScaleFactor</key>
<map>
<key>Comment</key>

View File

@ -807,6 +807,12 @@ void LLAgentCamera::setCameraZoomFraction(F32 fraction)
startCameraAnimation();
}
F32 LLAgentCamera::getAgentHUDTargetZoom()
{
static LLCachedControl<F32> hud_scale_factor(gSavedSettings, "HUDScaleFactor");
LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection();
return (selection->getObjectCount() && selection->getSelectType() == SELECT_TYPE_HUD) ? hud_scale_factor*gAgentCamera.mHUDTargetZoom : hud_scale_factor;
}
//-----------------------------------------------------------------------------
// cameraOrbitAround()
@ -1449,7 +1455,7 @@ void LLAgentCamera::updateCamera()
attachment_iter != attachment->mAttachedObjects.end();
++attachment_iter)
{
LLViewerObject *attached_object = (*attachment_iter);
LLViewerObject *attached_object = attachment_iter->get();
if (attached_object && !attached_object->isDead() && attached_object->mDrawable.notNull())
{
// clear any existing "early" movements of attachment

View File

@ -266,6 +266,7 @@ public:
F32 getCameraZoomFraction(); // Get camera zoom as fraction of minimum and maximum zoom
void setCameraZoomFraction(F32 fraction); // Set camera zoom as fraction of minimum and maximum zoom
F32 calcCameraFOVZoomFactor();
F32 getAgentHUDTargetZoom();
//--------------------------------------------------------------------
// Pan

View File

@ -1323,7 +1323,7 @@ void LLAgentWearables::findAttachmentsAddRemoveInfo(LLInventoryModel::item_array
attachment_iter != attachment->mAttachedObjects.end();
++attachment_iter)
{
LLViewerObject *objectp = (*attachment_iter);
LLViewerObject *objectp = attachment_iter->get();
if (objectp)
{
LLUUID object_item_id = objectp->getAttachmentItemID();
@ -1387,7 +1387,7 @@ std::vector<LLViewerObject*> LLAgentWearables::getTempAttachments()
attachment_iter != attachment->mAttachedObjects.end();
++attachment_iter)
{
LLViewerObject *objectp = (*attachment_iter);
LLViewerObject *objectp = attachment_iter->get();
if (objectp && objectp->isTempAttachment())
{
temp_attachs.push_back(objectp);

View File

@ -2911,7 +2911,7 @@ void LLAppearanceMgr::removeAllAttachmentsFromAvatar()
attachment_iter != attachment->mAttachedObjects.end();
++attachment_iter)
{
LLViewerObject *attached_object = (*attachment_iter);
LLViewerObject *attached_object = attachment_iter->get();
if (attached_object)
{
objects_to_remove.push_back(attached_object);

View File

@ -2125,6 +2125,9 @@ void watchdog_llerrs_callback(const std::string &error_string)
{
gLLErrorActivated = true;
gDebugInfo["FatalMessage"] = error_string;
LLAppViewer::instance()->writeDebugInfo();
#ifdef LL_WINDOWS
RaiseException(0,0,0,0);
#else

View File

@ -1,538 +0,0 @@
/**
* @file llflickrconnect.h
* @author Merov, Cho
* @brief Connection to Flickr 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 "llflickrconnect.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 "llfloaterwebcontent.h"
#include "llfloaterreg.h"
#include "llcorehttputil.h"
boost::scoped_ptr<LLEventPump> LLFlickrConnect::sStateWatcher(new LLEventStream("FlickrConnectState"));
boost::scoped_ptr<LLEventPump> LLFlickrConnect::sInfoWatcher(new LLEventStream("FlickrConnectInfo"));
boost::scoped_ptr<LLEventPump> LLFlickrConnect::sContentWatcher(new LLEventStream("FlickrConnectContent"));
// Local functions
void log_flickr_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("FlickrConnect") << request << " request failed with a " << status << " " << reason << ". Reason: " << code << " (" << description << ")" << LL_ENDL;
}
}
void toast_user_for_flickr_success()
{
LLSD args;
args["MESSAGE"] = LLTrans::getString("flickr_post_success");
LLNotificationsUtil::add("FlickrConnect", args);
}
///////////////////////////////////////////////////////////////////////////////
//
void LLFlickrConnect::flickrConnectCoro(std::string requestToken, std::string oauthVerifier)
{
LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("FlickrConnect", httpPolicy));
LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions);
httpOpts->setWantHeaders(true);
httpOpts->setFollowRedirects(false);
LLSD body;
if (!requestToken.empty())
body["request_token"] = requestToken;
if (!oauthVerifier.empty())
body["oauth_verifier"] = oauthVerifier;
setConnectionState(LLFlickrConnect::FLICKR_CONNECTION_IN_PROGRESS);
LLSD result = httpAdapter->putAndSuspend(httpRequest, getFlickrConnectURL("/connection"), body, httpOpts);
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("FlickrConnect") << "Missing Location header " << LL_ENDL;
}
else
{
openFlickrWeb(location);
}
}
else
{
LL_WARNS("FlickrConnect") << "Connection failed " << status.toString() << LL_ENDL;
setConnectionState(LLFlickrConnect::FLICKR_CONNECTION_FAILED);
log_flickr_connect_error("Connect", status.getStatus(), status.toString(),
result.get("error_code"), result.get("error_description"));
}
}
else
{
LL_DEBUGS("FlickrConnect") << "Connect successful. " << LL_ENDL;
setConnectionState(LLFlickrConnect::FLICKR_CONNECTED);
}
}
///////////////////////////////////////////////////////////////////////////////
//
bool LLFlickrConnect::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("FlickrConnect") << "Missing Location header " << LL_ENDL;
}
else
{
openFlickrWeb(location);
}
}
if (status == LLCore::HttpStatus(HTTP_NOT_FOUND))
{
LL_DEBUGS("FlickrConnect") << "Not connected. " << LL_ENDL;
connectToFlickr();
}
else
{
LL_WARNS("FlickrConnect") << "HTTP Status error " << status.toString() << LL_ENDL;
setConnectionState(LLFlickrConnect::FLICKR_POST_FAILED);
log_flickr_connect_error("Share", status.getStatus(), status.toString(),
result.get("error_code"), result.get("error_description"));
}
return false;
}
void LLFlickrConnect::flickrShareCoro(LLSD share)
{
LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("FlickrConnect", 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, getFlickrConnectURL("/share/photo", true), share, httpOpts);
if (testShareStatus(result))
{
toast_user_for_flickr_success();
LL_DEBUGS("FlickrConnect") << "Post successful. " << LL_ENDL;
setConnectionState(LLFlickrConnect::FLICKR_POSTED);
}
}
void LLFlickrConnect::flickrShareImageCoro(LLPointer<LLImageFormatted> image, std::string title, std::string description, std::string tags, int safetyLevel)
{
LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("FlickrConnect", httpPolicy));
LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
LLCore::HttpHeaders::ptr_t httpHeaders(new LLCore::HttpHeaders);
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()
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=\"title\"\r\n\r\n"
<< title << "\r\n";
body << "--" << boundary << "\r\n"
<< "Content-Disposition: form-data; name=\"description\"\r\n\r\n"
<< description << "\r\n";
body << "--" << boundary << "\r\n"
<< "Content-Disposition: form-data; name=\"tags\"\r\n\r\n"
<< tags << "\r\n";
body << "--" << boundary << "\r\n"
<< "Content-Disposition: form-data; name=\"safety_level\"\r\n\r\n"
<< safetyLevel << "\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";
LLSD result = httpAdapter->postAndSuspend(httpRequest, getFlickrConnectURL("/share/photo", true), raw, httpOpts, httpHeaders);
if (testShareStatus(result))
{
toast_user_for_flickr_success();
LL_DEBUGS("FlickrConnect") << "Post successful. " << LL_ENDL;
setConnectionState(LLFlickrConnect::FLICKR_POSTED);
}
}
///////////////////////////////////////////////////////////////////////////////
//
void LLFlickrConnect::flickrDisconnectCoro()
{
LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("FlickrConnect", httpPolicy));
LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions);
setConnectionState(LLFlickrConnect::FLICKR_DISCONNECTING);
httpOpts->setFollowRedirects(false);
LLSD result = httpAdapter->deleteAndSuspend(httpRequest, getFlickrConnectURL("/connection"), httpOpts);
LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
if (!status && (status != LLCore::HttpStatus(HTTP_NOT_FOUND)))
{
LL_WARNS("FlickrConnect") << "Disconnect failed!" << LL_ENDL;
setConnectionState(LLFlickrConnect::FLICKR_DISCONNECT_FAILED);
log_flickr_connect_error("Disconnect", status.getStatus(), status.toString(),
result.get("error_code"), result.get("error_description"));
}
else
{
LL_DEBUGS("FlickrConnect") << "Disconnect successful. " << LL_ENDL;
clearInfo();
setConnectionState(LLFlickrConnect::FLICKR_NOT_CONNECTED);
}
}
///////////////////////////////////////////////////////////////////////////////
//
void LLFlickrConnect::flickrConnectedCoro(bool autoConnect)
{
LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("FlickrConnect", httpPolicy));
LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions);
setConnectionState(LLFlickrConnect::FLICKR_CONNECTION_IN_PROGRESS);
httpOpts->setFollowRedirects(false);
LLSD result = httpAdapter->getAndSuspend(httpRequest, getFlickrConnectURL("/connection", true), httpOpts);
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("FlickrConnect") << "Not connected. " << LL_ENDL;
if (autoConnect)
{
connectToFlickr();
}
else
{
setConnectionState(LLFlickrConnect::FLICKR_NOT_CONNECTED);
}
}
else
{
LL_WARNS("FlickrConnect") << "Failed to test connection:" << status.toTerseString() << LL_ENDL;
setConnectionState(LLFlickrConnect::FLICKR_CONNECTION_FAILED);
log_flickr_connect_error("Connected", status.getStatus(), status.toString(),
result.get("error_code"), result.get("error_description"));
}
}
else
{
LL_DEBUGS("FlickrConnect") << "Connect successful. " << LL_ENDL;
setConnectionState(LLFlickrConnect::FLICKR_CONNECTED);
}
}
///////////////////////////////////////////////////////////////////////////////
//
void LLFlickrConnect::flickrInfoCoro()
{
LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("FlickrConnect", 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, getFlickrConnectURL("/info", true), httpOpts);
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("FlickrConnect") << "Missing Location header " << LL_ENDL;
}
else
{
openFlickrWeb(location);
}
}
else if (!status)
{
LL_WARNS("FlickrConnect") << "Flickr Info failed: " << status.toString() << LL_ENDL;
log_flickr_connect_error("Info", status.getStatus(), status.toString(),
result.get("error_code"), result.get("error_description"));
}
else
{
LL_INFOS("FlickrConnect") << "Flickr: Info received" << LL_ENDL;
result.erase(LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS);
storeInfo(result);
}
}
///////////////////////////////////////////////////////////////////////////////
//
LLFlickrConnect::LLFlickrConnect()
: mConnectionState(FLICKR_NOT_CONNECTED),
mConnected(false),
mInfo(),
mRefreshInfo(false),
mReadFromMaster(false)
{
}
void LLFlickrConnect::openFlickrWeb(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("flickr_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 "flickr_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.
//flickr_web floater contains the "webbrowser" panel. JIRA: ACME-744
gFocusMgr.setKeyboardFocus( floater );
//LLUrlAction::openURLExternal(url);
}
std::string LLFlickrConnect::getFlickrConnectURL(const std::string& route, bool include_read_from_master)
{
std::string url("");
LLViewerRegion *regionp = gAgent.getRegion();
if (regionp)
{
//url = "http://pdp15.lindenlab.com/flickr/agent/" + gAgentID.asString(); // TEMPORARY FOR TESTING - CHO
url = regionp->getCapability("FlickrConnect");
url += route;
if (include_read_from_master && mReadFromMaster)
{
url += "?read_from_master=true";
}
}
return url;
}
void LLFlickrConnect::connectToFlickr(const std::string& request_token, const std::string& oauth_verifier)
{
LLCoros::instance().launch("LLFlickrConnect::flickrConnectCoro",
boost::bind(&LLFlickrConnect::flickrConnectCoro, this, request_token, oauth_verifier));
}
void LLFlickrConnect::disconnectFromFlickr()
{
LLCoros::instance().launch("LLFlickrConnect::flickrDisconnectCoro",
boost::bind(&LLFlickrConnect::flickrDisconnectCoro, this));
}
void LLFlickrConnect::checkConnectionToFlickr(bool auto_connect)
{
LLCoros::instance().launch("LLFlickrConnect::flickrConnectedCoro",
boost::bind(&LLFlickrConnect::flickrConnectedCoro, this, auto_connect));
}
void LLFlickrConnect::loadFlickrInfo()
{
if(mRefreshInfo)
{
LLCoros::instance().launch("LLFlickrConnect::flickrInfoCoro",
boost::bind(&LLFlickrConnect::flickrInfoCoro, this));
}
}
void LLFlickrConnect::uploadPhoto(const std::string& image_url, const std::string& title, const std::string& description, const std::string& tags, int safety_level)
{
LLSD body;
body["image"] = image_url;
body["title"] = title;
body["description"] = description;
body["tags"] = tags;
body["safety_level"] = safety_level;
setConnectionState(LLFlickrConnect::FLICKR_POSTING);
LLCoros::instance().launch("LLFlickrConnect::flickrShareCoro",
boost::bind(&LLFlickrConnect::flickrShareCoro, this, body));
}
void LLFlickrConnect::uploadPhoto(LLPointer<LLImageFormatted> image, const std::string& title, const std::string& description, const std::string& tags, int safety_level)
{
setConnectionState(LLFlickrConnect::FLICKR_POSTING);
LLCoros::instance().launch("LLFlickrConnect::flickrShareImageCoro",
boost::bind(&LLFlickrConnect::flickrShareImageCoro, this, image,
title, description, tags, safety_level));
}
void LLFlickrConnect::storeInfo(const LLSD& info)
{
mInfo = info;
mRefreshInfo = false;
sInfoWatcher->post(info);
}
const LLSD& LLFlickrConnect::getInfo() const
{
return mInfo;
}
void LLFlickrConnect::clearInfo()
{
mInfo = LLSD();
}
void LLFlickrConnect::setDataDirty()
{
mRefreshInfo = true;
}
void LLFlickrConnect::setConnectionState(LLFlickrConnect::EConnectionState connection_state)
{
if(connection_state == FLICKR_CONNECTED)
{
mReadFromMaster = true;
setConnected(true);
setDataDirty();
}
else if(connection_state == FLICKR_NOT_CONNECTED)
{
setConnected(false);
}
else if(connection_state == FLICKR_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 LLFlickrConnect::setConnected(bool connected)
{
mConnected = connected;
}

View File

@ -1,108 +0,0 @@
/**
* @file llflickrconnect.h
* @author Merov, Cho
* @brief Connection to Flickr 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_LLFLICKRCONNECT_H
#define LL_LLFLICKRCONNECT_H
#include "llsingleton.h"
#include "llimage.h"
#include "llcoros.h"
#include "lleventcoro.h"
class LLEventPump;
/**
* @class LLFlickrConnect
*
* Manages authentication to, and interaction with, a web service allowing the
* the viewer to upload photos to Flickr.
*/
class LLFlickrConnect : public LLSingleton<LLFlickrConnect>
{
LLSINGLETON(LLFlickrConnect);
~LLFlickrConnect() {};
LOG_CLASS(LLFlickrConnect);
public:
enum EConnectionState
{
FLICKR_NOT_CONNECTED = 0,
FLICKR_CONNECTION_IN_PROGRESS = 1,
FLICKR_CONNECTED = 2,
FLICKR_CONNECTION_FAILED = 3,
FLICKR_POSTING = 4,
FLICKR_POSTED = 5,
FLICKR_POST_FAILED = 6,
FLICKR_DISCONNECTING = 7,
FLICKR_DISCONNECT_FAILED = 8
};
void connectToFlickr(const std::string& request_token = "", const std::string& oauth_verifier = ""); // Initiate the complete Flickr connection. Please use checkConnectionToFlickr() in normal use.
void disconnectFromFlickr(); // Disconnect from the Flickr service.
void checkConnectionToFlickr(bool auto_connect = false); // Check if an access token is available on the Flickr service. If not, call connectToFlickr().
void loadFlickrInfo();
void uploadPhoto(const std::string& image_url, const std::string& title, const std::string& description, const std::string& tags, int safety_level);
void uploadPhoto(LLPointer<LLImageFormatted> image, const std::string& title, const std::string& description, const std::string& tags, int safety_level);
void storeInfo(const LLSD& info);
const LLSD& getInfo() const;
void clearInfo();
void setDataDirty();
void setConnectionState(EConnectionState connection_state);
void setConnected(bool connected);
bool isConnected() { return mConnected; }
bool isTransactionOngoing() { return ((mConnectionState == FLICKR_CONNECTION_IN_PROGRESS) || (mConnectionState == FLICKR_POSTING) || (mConnectionState == FLICKR_DISCONNECTING)); }
EConnectionState getConnectionState() { return mConnectionState; }
void openFlickrWeb(std::string url);
private:
std::string getFlickrConnectURL(const std::string& route = "", bool include_read_from_master = false);
EConnectionState mConnectionState;
BOOL mConnected;
LLSD mInfo;
bool mRefreshInfo;
bool mReadFromMaster;
static boost::scoped_ptr<LLEventPump> sStateWatcher;
static boost::scoped_ptr<LLEventPump> sInfoWatcher;
static boost::scoped_ptr<LLEventPump> sContentWatcher;
bool testShareStatus(LLSD &result);
void flickrConnectCoro(std::string requestToken, std::string oauthVerifier);
void flickrShareCoro(LLSD share);
void flickrShareImageCoro(LLPointer<LLImageFormatted> image, std::string title, std::string description, std::string tags, int safetyLevel);
void flickrDisconnectCoro();
void flickrConnectedCoro(bool autoConnect);
void flickrInfoCoro();
};
#endif // LL_LLFLICKRCONNECT_H

View File

@ -1,6 +1,6 @@
/**
* @file llfloaterbigpreview.h
* @brief Display of extended (big) preview for snapshots and SL Share
* @brief Display of extended (big) preview for snapshots
* @author merov@lindenlab.com
*
* $LicenseInfo:firstyear=2013&license=viewerlgpl$

View File

@ -74,10 +74,6 @@ BOOL LLFloaterExperiences::postBuild()
getChild<LLTabContainer>("xp_tabs")->addTabPanel(new LLPanelExperienceLog());
resizeToTabs();
LLEventPumps::instance().obtain("experience_permission").listen("LLFloaterExperiences",
boost::bind(&LLFloaterExperiences::updatePermissions, this, _1));
return TRUE;
}
@ -163,6 +159,10 @@ void LLFloaterExperiences::refreshContents()
void LLFloaterExperiences::onOpen( const LLSD& key )
{
LLEventPumps::instance().obtain("experience_permission").stopListening("LLFloaterExperiences");
LLEventPumps::instance().obtain("experience_permission").listen("LLFloaterExperiences",
boost::bind(&LLFloaterExperiences::updatePermissions, this, _1));
LLViewerRegion* region = gAgent.getRegion();
if(region)
{

View File

@ -1,787 +0,0 @@
/**
* @file llfloaterflickr.cpp
* @brief Implementation of llfloaterflickr
* @author cho@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$
*/
#include "llviewerprecompiledheaders.h"
#include "llfloaterflickr.h"
#include "llagent.h"
#include "llagentui.h"
#include "llcheckboxctrl.h"
#include "llcombobox.h"
#include "llflickrconnect.h"
#include "llfloaterreg.h"
#include "lliconctrl.h"
#include "llimagefiltersmanager.h"
#include "llresmgr.h" // LLLocale
#include "llsdserialize.h"
#include "llloadingindicator.h"
#include "llslurl.h"
#include "lltrans.h"
#include "llsnapshotlivepreview.h"
#include "llfloaterbigpreview.h"
#include "llviewerregion.h"
#include "llviewercontrol.h"
#include "llviewermedia.h"
#include "lltabcontainer.h"
#include "llviewerparcelmgr.h"
#include "llviewerregion.h"
#include <boost/regex.hpp>
static LLPanelInjector<LLFlickrPhotoPanel> t_panel_photo("llflickrphotopanel");
static LLPanelInjector<LLFlickrAccountPanel> t_panel_account("llflickraccountpanel");
const std::string DEFAULT_PHOTO_QUERY_PARAMETERS = "?sourceid=slshare_photo&utm_source=flickr&utm_medium=photo&utm_campaign=slshare";
const std::string DEFAULT_TAG_TEXT = "secondlife ";
const std::string FLICKR_MACHINE_TAGS_NAMESPACE = "secondlife";
///////////////////////////
//LLFlickrPhotoPanel///////
///////////////////////////
LLFlickrPhotoPanel::LLFlickrPhotoPanel() :
mResolutionComboBox(NULL),
mRefreshBtn(NULL),
mBtnPreview(NULL),
mWorkingLabel(NULL),
mThumbnailPlaceholder(NULL),
mTitleTextBox(NULL),
mDescriptionTextBox(NULL),
mLocationCheckbox(NULL),
mTagsTextBox(NULL),
mRatingComboBox(NULL),
mBigPreviewFloater(NULL),
mPostButton(NULL)
{
mCommitCallbackRegistrar.add("SocialSharing.SendPhoto", boost::bind(&LLFlickrPhotoPanel::onSend, this));
mCommitCallbackRegistrar.add("SocialSharing.RefreshPhoto", boost::bind(&LLFlickrPhotoPanel::onClickNewSnapshot, this));
mCommitCallbackRegistrar.add("SocialSharing.BigPreview", boost::bind(&LLFlickrPhotoPanel::onClickBigPreview, this));
}
LLFlickrPhotoPanel::~LLFlickrPhotoPanel()
{
if(mPreviewHandle.get())
{
mPreviewHandle.get()->die();
}
}
BOOL LLFlickrPhotoPanel::postBuild()
{
setVisibleCallback(boost::bind(&LLFlickrPhotoPanel::onVisibilityChange, this, _2));
mResolutionComboBox = getChild<LLUICtrl>("resolution_combobox");
mResolutionComboBox->setCommitCallback(boost::bind(&LLFlickrPhotoPanel::updateResolution, this, TRUE));
mFilterComboBox = getChild<LLUICtrl>("filters_combobox");
mFilterComboBox->setCommitCallback(boost::bind(&LLFlickrPhotoPanel::updateResolution, this, TRUE));
mRefreshBtn = getChild<LLUICtrl>("new_snapshot_btn");
mBtnPreview = getChild<LLButton>("big_preview_btn");
mWorkingLabel = getChild<LLUICtrl>("working_lbl");
mThumbnailPlaceholder = getChild<LLUICtrl>("thumbnail_placeholder");
mTitleTextBox = getChild<LLUICtrl>("photo_title");
mDescriptionTextBox = getChild<LLUICtrl>("photo_description");
mLocationCheckbox = getChild<LLUICtrl>("add_location_cb");
mTagsTextBox = getChild<LLUICtrl>("photo_tags");
mTagsTextBox->setValue(DEFAULT_TAG_TEXT);
mRatingComboBox = getChild<LLUICtrl>("rating_combobox");
mPostButton = getChild<LLUICtrl>("post_photo_btn");
mCancelButton = getChild<LLUICtrl>("cancel_photo_btn");
mBigPreviewFloater = dynamic_cast<LLFloaterBigPreview*>(LLFloaterReg::getInstance("big_preview"));
// Update filter list
std::vector<std::string> filter_list = LLImageFiltersManager::getInstance()->getFiltersList();
LLComboBox* filterbox = static_cast<LLComboBox *>(mFilterComboBox);
for (U32 i = 0; i < filter_list.size(); i++)
{
filterbox->add(filter_list[i]);
}
return LLPanel::postBuild();
}
// virtual
S32 LLFlickrPhotoPanel::notify(const LLSD& info)
{
if (info.has("snapshot-updating"))
{
// Disable the Post button and whatever else while the snapshot is not updated
// updateControls();
return 1;
}
if (info.has("snapshot-updated"))
{
// Enable the send/post/save buttons.
updateControls();
// The refresh button is initially hidden. We show it after the first update,
// i.e. after snapshot is taken
LLUICtrl * refresh_button = getRefreshBtn();
if (!refresh_button->getVisible())
{
refresh_button->setVisible(true);
}
return 1;
}
return 0;
}
void LLFlickrPhotoPanel::draw()
{
LLSnapshotLivePreview * previewp = static_cast<LLSnapshotLivePreview *>(mPreviewHandle.get());
// Enable interaction only if no transaction with the service is on-going (prevent duplicated posts)
bool no_ongoing_connection = !(LLFlickrConnect::instance().isTransactionOngoing());
mCancelButton->setEnabled(no_ongoing_connection);
mTitleTextBox->setEnabled(no_ongoing_connection);
mDescriptionTextBox->setEnabled(no_ongoing_connection);
mTagsTextBox->setEnabled(no_ongoing_connection);
mRatingComboBox->setEnabled(no_ongoing_connection);
mResolutionComboBox->setEnabled(no_ongoing_connection);
mFilterComboBox->setEnabled(no_ongoing_connection);
mRefreshBtn->setEnabled(no_ongoing_connection);
mBtnPreview->setEnabled(no_ongoing_connection);
mLocationCheckbox->setEnabled(no_ongoing_connection);
// Reassign the preview floater if we have the focus and the preview exists
if (hasFocus() && isPreviewVisible())
{
attachPreview();
}
// Toggle the button state as appropriate
bool preview_active = (isPreviewVisible() && mBigPreviewFloater->isFloaterOwner(getParentByType<LLFloater>()));
mBtnPreview->setToggleState(preview_active);
// Display the preview if one is available
if (previewp && previewp->getThumbnailImage())
{
const LLRect& thumbnail_rect = mThumbnailPlaceholder->getRect();
const S32 thumbnail_w = previewp->getThumbnailWidth();
const S32 thumbnail_h = previewp->getThumbnailHeight();
// calc preview offset within the preview rect
const S32 local_offset_x = (thumbnail_rect.getWidth() - thumbnail_w) / 2 ;
const S32 local_offset_y = (thumbnail_rect.getHeight() - thumbnail_h) / 2 ;
S32 offset_x = thumbnail_rect.mLeft + local_offset_x;
S32 offset_y = thumbnail_rect.mBottom + local_offset_y;
gGL.matrixMode(LLRender::MM_MODELVIEW);
// Apply floater transparency to the texture unless the floater is focused.
F32 alpha = getTransparencyType() == TT_ACTIVE ? 1.0f : getCurrentTransparency();
LLColor4 color = LLColor4::white;
gl_draw_scaled_image(offset_x, offset_y,
thumbnail_w, thumbnail_h,
previewp->getThumbnailImage(), color % alpha);
}
// Update the visibility of the working (computing preview) label
mWorkingLabel->setVisible(!(previewp && previewp->getSnapshotUpToDate()));
// Enable Post if we have a preview to send and no on going connection being processed
mPostButton->setEnabled(no_ongoing_connection && (previewp && previewp->getSnapshotUpToDate()));
// Draw the rest of the panel on top of it
LLPanel::draw();
}
LLSnapshotLivePreview* LLFlickrPhotoPanel::getPreviewView()
{
LLSnapshotLivePreview* previewp = (LLSnapshotLivePreview*)mPreviewHandle.get();
return previewp;
}
void LLFlickrPhotoPanel::onVisibilityChange(BOOL visible)
{
if (visible)
{
if (mPreviewHandle.get())
{
LLSnapshotLivePreview* preview = getPreviewView();
if(preview)
{
LL_DEBUGS() << "opened, updating snapshot" << LL_ENDL;
preview->updateSnapshot(TRUE);
}
}
else
{
LLRect full_screen_rect = getRootView()->getRect();
LLSnapshotLivePreview::Params p;
p.rect(full_screen_rect);
LLSnapshotLivePreview* previewp = new LLSnapshotLivePreview(p);
mPreviewHandle = previewp->getHandle();
previewp->setContainer(this);
previewp->setSnapshotType(LLSnapshotModel::SNAPSHOT_WEB);
previewp->setSnapshotFormat(LLSnapshotModel::SNAPSHOT_FORMAT_PNG);
previewp->setThumbnailSubsampled(TRUE); // We want the preview to reflect the *saved* image
previewp->setAllowRenderUI(FALSE); // We do not want the rendered UI in our snapshots
previewp->setAllowFullScreenPreview(FALSE); // No full screen preview in SL Share mode
previewp->setThumbnailPlaceholderRect(mThumbnailPlaceholder->getRect());
updateControls();
}
}
}
void LLFlickrPhotoPanel::onClickNewSnapshot()
{
LLSnapshotLivePreview* previewp = getPreviewView();
if (previewp)
{
previewp->updateSnapshot(TRUE);
}
}
void LLFlickrPhotoPanel::onClickBigPreview()
{
// Toggle the preview
if (isPreviewVisible())
{
LLFloaterReg::hideInstance("big_preview");
}
else
{
attachPreview();
LLFloaterReg::showInstance("big_preview");
}
}
bool LLFlickrPhotoPanel::isPreviewVisible()
{
return (mBigPreviewFloater && mBigPreviewFloater->getVisible());
}
void LLFlickrPhotoPanel::attachPreview()
{
if (mBigPreviewFloater)
{
LLSnapshotLivePreview* previewp = getPreviewView();
mBigPreviewFloater->setPreview(previewp);
mBigPreviewFloater->setFloaterOwner(getParentByType<LLFloater>());
}
}
void LLFlickrPhotoPanel::onSend()
{
LLEventPumps::instance().obtain("FlickrConnectState").stopListening("LLFlickrPhotoPanel"); // just in case it is already listening
LLEventPumps::instance().obtain("FlickrConnectState").listen("LLFlickrPhotoPanel", boost::bind(&LLFlickrPhotoPanel::onFlickrConnectStateChange, this, _1));
// Connect to Flickr if necessary and then post
if (LLFlickrConnect::instance().isConnected())
{
sendPhoto();
}
else
{
LLFlickrConnect::instance().checkConnectionToFlickr(true);
}
}
bool LLFlickrPhotoPanel::onFlickrConnectStateChange(const LLSD& data)
{
switch (data.get("enum").asInteger())
{
case LLFlickrConnect::FLICKR_CONNECTED:
sendPhoto();
break;
case LLFlickrConnect::FLICKR_POSTED:
LLEventPumps::instance().obtain("FlickrConnectState").stopListening("LLFlickrPhotoPanel");
clearAndClose();
break;
}
return false;
}
void LLFlickrPhotoPanel::sendPhoto()
{
// Get the title, description, and tags
std::string title = mTitleTextBox->getValue().asString();
std::string description = mDescriptionTextBox->getValue().asString();
std::string tags = mTagsTextBox->getValue().asString();
// Add the location if required
bool add_location = mLocationCheckbox->getValue().asBoolean();
if (add_location)
{
// Get the SLURL for the location
LLSLURL slurl;
LLAgentUI::buildSLURL(slurl);
std::string slurl_string = slurl.getSLURLString();
// Add query parameters so Google Analytics can track incoming clicks!
slurl_string += DEFAULT_PHOTO_QUERY_PARAMETERS;
std::string photo_link_text = "Visit this location";// at [] in Second Life";
std::string parcel_name = LLViewerParcelMgr::getInstance()->getAgentParcelName();
if (!parcel_name.empty())
{
boost::regex pattern = boost::regex("\\S\\.[a-zA-Z]{2,}");
boost::match_results<std::string::const_iterator> matches;
if(!boost::regex_search(parcel_name, matches, pattern))
{
photo_link_text += " at " + parcel_name;
}
}
photo_link_text += " in Second Life";
slurl_string = "<a href=\"" + slurl_string + "\">" + photo_link_text + "</a>";
// Add it to the description (pretty crude, but we don't have a better option with photos)
if (description.empty())
description = slurl_string;
else
description = description + "\n\n" + slurl_string;
// Also add special "machine tags" with location metadata
const LLVector3& agent_pos_region = gAgent.getPositionAgent();
LLViewerRegion* region = gAgent.getRegion();
LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
if (region && parcel)
{
S32 pos_x = S32(agent_pos_region.mV[VX]);
S32 pos_y = S32(agent_pos_region.mV[VY]);
S32 pos_z = S32(agent_pos_region.mV[VZ]);
std::string parcel_name = LLViewerParcelMgr::getInstance()->getAgentParcelName();
std::string region_name = region->getName();
if (!region_name.empty())
{
tags += llformat(" \"%s:region=%s\"", FLICKR_MACHINE_TAGS_NAMESPACE.c_str(), region_name.c_str());
}
if (!parcel_name.empty())
{
tags += llformat(" \"%s:parcel=%s\"", FLICKR_MACHINE_TAGS_NAMESPACE.c_str(), parcel_name.c_str());
}
tags += llformat(" \"%s:x=%d\"", FLICKR_MACHINE_TAGS_NAMESPACE.c_str(), pos_x);
tags += llformat(" \"%s:y=%d\"", FLICKR_MACHINE_TAGS_NAMESPACE.c_str(), pos_y);
tags += llformat(" \"%s:z=%d\"", FLICKR_MACHINE_TAGS_NAMESPACE.c_str(), pos_z);
}
}
// Get the content rating
int content_rating = mRatingComboBox->getValue().asInteger();
// Get the image
LLSnapshotLivePreview* previewp = getPreviewView();
// Post to Flickr
LLFlickrConnect::instance().uploadPhoto(previewp->getFormattedImage(), title, description, tags, content_rating);
updateControls();
}
void LLFlickrPhotoPanel::clearAndClose()
{
mTitleTextBox->setValue("");
mDescriptionTextBox->setValue("");
LLFloater* floater = getParentByType<LLFloater>();
if (floater)
{
floater->closeFloater();
if (mBigPreviewFloater)
{
mBigPreviewFloater->closeOnFloaterOwnerClosing(floater);
}
}
}
void LLFlickrPhotoPanel::updateControls()
{
LLSnapshotLivePreview* previewp = getPreviewView();
BOOL got_snap = previewp && previewp->getSnapshotUpToDate();
// *TODO: Separate maximum size for Web images from postcards
LL_DEBUGS() << "Is snapshot up-to-date? " << got_snap << LL_ENDL;
updateResolution(FALSE);
}
void LLFlickrPhotoPanel::updateResolution(BOOL do_update)
{
LLComboBox* combobox = static_cast<LLComboBox *>(mResolutionComboBox);
LLComboBox* filterbox = static_cast<LLComboBox *>(mFilterComboBox);
std::string sdstring = combobox->getSelectedValue();
LLSD sdres;
std::stringstream sstream(sdstring);
LLSDSerialize::fromNotation(sdres, sstream, sdstring.size());
S32 width = sdres[0];
S32 height = sdres[1];
// Note : index 0 of the filter drop down is assumed to be "No filter" in whichever locale
std::string filter_name = (filterbox->getCurrentIndex() ? filterbox->getSimple() : "");
LLSnapshotLivePreview * previewp = static_cast<LLSnapshotLivePreview *>(mPreviewHandle.get());
if (previewp && combobox->getCurrentIndex() >= 0)
{
S32 original_width = 0 , original_height = 0 ;
previewp->getSize(original_width, original_height) ;
if (width == 0 || height == 0)
{
// take resolution from current window size
LL_DEBUGS() << "Setting preview res from window: " << gViewerWindow->getWindowWidthRaw() << "x" << gViewerWindow->getWindowHeightRaw() << LL_ENDL;
previewp->setSize(gViewerWindow->getWindowWidthRaw(), gViewerWindow->getWindowHeightRaw());
}
else
{
// use the resolution from the selected pre-canned drop-down choice
LL_DEBUGS() << "Setting preview res selected from combo: " << width << "x" << height << LL_ENDL;
previewp->setSize(width, height);
}
checkAspectRatio(width);
previewp->getSize(width, height);
if ((original_width != width) || (original_height != height))
{
previewp->setSize(width, height);
if (do_update)
{
previewp->updateSnapshot(TRUE);
updateControls();
}
}
// Get the old filter, compare to the current one "filter_name" and set if changed
std::string original_filter = previewp->getFilter();
if (original_filter != filter_name)
{
previewp->setFilter(filter_name);
if (do_update)
{
previewp->updateSnapshot(FALSE, TRUE);
updateControls();
}
}
}
}
void LLFlickrPhotoPanel::checkAspectRatio(S32 index)
{
LLSnapshotLivePreview *previewp = getPreviewView() ;
BOOL keep_aspect = FALSE;
if (0 == index) // current window size
{
keep_aspect = TRUE;
}
else // predefined resolution
{
keep_aspect = FALSE;
}
if (previewp)
{
previewp->mKeepAspectRatio = keep_aspect;
}
}
LLUICtrl* LLFlickrPhotoPanel::getRefreshBtn()
{
return mRefreshBtn;
}
///////////////////////////
//LLFlickrAccountPanel//////
///////////////////////////
LLFlickrAccountPanel::LLFlickrAccountPanel() :
mAccountCaptionLabel(NULL),
mAccountNameLabel(NULL),
mPanelButtons(NULL),
mConnectButton(NULL),
mDisconnectButton(NULL)
{
mCommitCallbackRegistrar.add("SocialSharing.Connect", boost::bind(&LLFlickrAccountPanel::onConnect, this));
mCommitCallbackRegistrar.add("SocialSharing.Disconnect", boost::bind(&LLFlickrAccountPanel::onDisconnect, this));
setVisibleCallback(boost::bind(&LLFlickrAccountPanel::onVisibilityChange, this, _2));
}
BOOL LLFlickrAccountPanel::postBuild()
{
mAccountCaptionLabel = getChild<LLTextBox>("account_caption_label");
mAccountNameLabel = getChild<LLTextBox>("account_name_label");
mPanelButtons = getChild<LLUICtrl>("panel_buttons");
mConnectButton = getChild<LLUICtrl>("connect_btn");
mDisconnectButton = getChild<LLUICtrl>("disconnect_btn");
return LLPanel::postBuild();
}
void LLFlickrAccountPanel::draw()
{
LLFlickrConnect::EConnectionState connection_state = LLFlickrConnect::instance().getConnectionState();
//Disable the 'disconnect' button and the 'use another account' button when disconnecting in progress
bool disconnecting = connection_state == LLFlickrConnect::FLICKR_DISCONNECTING;
mDisconnectButton->setEnabled(!disconnecting);
//Disable the 'connect' button when a connection is in progress
bool connecting = connection_state == LLFlickrConnect::FLICKR_CONNECTION_IN_PROGRESS;
mConnectButton->setEnabled(!connecting);
LLPanel::draw();
}
void LLFlickrAccountPanel::onVisibilityChange(BOOL visible)
{
if(visible)
{
LLEventPumps::instance().obtain("FlickrConnectState").stopListening("LLFlickrAccountPanel");
LLEventPumps::instance().obtain("FlickrConnectState").listen("LLFlickrAccountPanel", boost::bind(&LLFlickrAccountPanel::onFlickrConnectStateChange, this, _1));
LLEventPumps::instance().obtain("FlickrConnectInfo").stopListening("LLFlickrAccountPanel");
LLEventPumps::instance().obtain("FlickrConnectInfo").listen("LLFlickrAccountPanel", boost::bind(&LLFlickrAccountPanel::onFlickrConnectInfoChange, this));
//Connected
if(LLFlickrConnect::instance().isConnected())
{
showConnectedLayout();
}
//Check if connected (show disconnected layout in meantime)
else
{
showDisconnectedLayout();
}
if ((LLFlickrConnect::instance().getConnectionState() == LLFlickrConnect::FLICKR_NOT_CONNECTED) ||
(LLFlickrConnect::instance().getConnectionState() == LLFlickrConnect::FLICKR_CONNECTION_FAILED))
{
LLFlickrConnect::instance().checkConnectionToFlickr();
}
}
else
{
LLEventPumps::instance().obtain("FlickrConnectState").stopListening("LLFlickrAccountPanel");
LLEventPumps::instance().obtain("FlickrConnectInfo").stopListening("LLFlickrAccountPanel");
}
}
bool LLFlickrAccountPanel::onFlickrConnectStateChange(const LLSD& data)
{
if(LLFlickrConnect::instance().isConnected())
{
//In process of disconnecting so leave the layout as is
if(data.get("enum").asInteger() != LLFlickrConnect::FLICKR_DISCONNECTING)
{
showConnectedLayout();
}
}
else
{
showDisconnectedLayout();
}
return false;
}
bool LLFlickrAccountPanel::onFlickrConnectInfoChange()
{
LLSD info = LLFlickrConnect::instance().getInfo();
std::string clickable_name;
//Strings of format [http://www.somewebsite.com Click Me] become clickable text
if(info.has("link") && info.has("name"))
{
clickable_name = "[" + info["link"].asString() + " " + info["name"].asString() + "]";
}
mAccountNameLabel->setText(clickable_name);
return false;
}
void LLFlickrAccountPanel::showConnectButton()
{
if(!mConnectButton->getVisible())
{
mConnectButton->setVisible(TRUE);
mDisconnectButton->setVisible(FALSE);
}
}
void LLFlickrAccountPanel::hideConnectButton()
{
if(mConnectButton->getVisible())
{
mConnectButton->setVisible(FALSE);
mDisconnectButton->setVisible(TRUE);
}
}
void LLFlickrAccountPanel::showDisconnectedLayout()
{
mAccountCaptionLabel->setText(getString("flickr_disconnected"));
mAccountNameLabel->setText(std::string(""));
showConnectButton();
}
void LLFlickrAccountPanel::showConnectedLayout()
{
LLFlickrConnect::instance().loadFlickrInfo();
mAccountCaptionLabel->setText(getString("flickr_connected"));
hideConnectButton();
}
void LLFlickrAccountPanel::onConnect()
{
LLFlickrConnect::instance().checkConnectionToFlickr(true);
}
void LLFlickrAccountPanel::onDisconnect()
{
LLFlickrConnect::instance().disconnectFromFlickr();
}
////////////////////////
//LLFloaterFlickr///////
////////////////////////
LLFloaterFlickr::LLFloaterFlickr(const LLSD& key) : LLFloater(key),
mFlickrPhotoPanel(NULL),
mStatusErrorText(NULL),
mStatusLoadingText(NULL),
mStatusLoadingIndicator(NULL)
{
mCommitCallbackRegistrar.add("SocialSharing.Cancel", boost::bind(&LLFloaterFlickr::onCancel, this));
}
void LLFloaterFlickr::onClose(bool app_quitting)
{
LLFloaterBigPreview* big_preview_floater = dynamic_cast<LLFloaterBigPreview*>(LLFloaterReg::getInstance("big_preview"));
if (big_preview_floater)
{
big_preview_floater->closeOnFloaterOwnerClosing(this);
}
LLFloater::onClose(app_quitting);
}
void LLFloaterFlickr::onCancel()
{
LLFloaterBigPreview* big_preview_floater = dynamic_cast<LLFloaterBigPreview*>(LLFloaterReg::getInstance("big_preview"));
if (big_preview_floater)
{
big_preview_floater->closeOnFloaterOwnerClosing(this);
}
closeFloater();
}
BOOL LLFloaterFlickr::postBuild()
{
// Keep tab of the Photo Panel
mFlickrPhotoPanel = static_cast<LLFlickrPhotoPanel*>(getChild<LLUICtrl>("panel_flickr_photo"));
// Connection status widgets
mStatusErrorText = getChild<LLTextBox>("connection_error_text");
mStatusLoadingText = getChild<LLTextBox>("connection_loading_text");
mStatusLoadingIndicator = getChild<LLUICtrl>("connection_loading_indicator");
return LLFloater::postBuild();
}
void LLFloaterFlickr::showPhotoPanel()
{
LLTabContainer* parent = dynamic_cast<LLTabContainer*>(mFlickrPhotoPanel->getParent());
if (!parent)
{
LL_WARNS() << "Cannot find panel container" << LL_ENDL;
return;
}
parent->selectTabPanel(mFlickrPhotoPanel);
}
void LLFloaterFlickr::draw()
{
if (mStatusErrorText && mStatusLoadingText && mStatusLoadingIndicator)
{
mStatusErrorText->setVisible(false);
mStatusLoadingText->setVisible(false);
mStatusLoadingIndicator->setVisible(false);
LLFlickrConnect::EConnectionState connection_state = LLFlickrConnect::instance().getConnectionState();
std::string status_text;
switch (connection_state)
{
case LLFlickrConnect::FLICKR_NOT_CONNECTED:
// No status displayed when first opening the panel and no connection done
case LLFlickrConnect::FLICKR_CONNECTED:
// When successfully connected, no message is displayed
case LLFlickrConnect::FLICKR_POSTED:
// No success message to show since we actually close the floater after successful posting completion
break;
case LLFlickrConnect::FLICKR_CONNECTION_IN_PROGRESS:
// Connection loading indicator
mStatusLoadingText->setVisible(true);
status_text = LLTrans::getString("SocialFlickrConnecting");
mStatusLoadingText->setValue(status_text);
mStatusLoadingIndicator->setVisible(true);
break;
case LLFlickrConnect::FLICKR_POSTING:
// Posting indicator
mStatusLoadingText->setVisible(true);
status_text = LLTrans::getString("SocialFlickrPosting");
mStatusLoadingText->setValue(status_text);
mStatusLoadingIndicator->setVisible(true);
break;
case LLFlickrConnect::FLICKR_CONNECTION_FAILED:
// Error connecting to the service
mStatusErrorText->setVisible(true);
status_text = LLTrans::getString("SocialFlickrErrorConnecting");
mStatusErrorText->setValue(status_text);
break;
case LLFlickrConnect::FLICKR_POST_FAILED:
// Error posting to the service
mStatusErrorText->setVisible(true);
status_text = LLTrans::getString("SocialFlickrErrorPosting");
mStatusErrorText->setValue(status_text);
break;
case LLFlickrConnect::FLICKR_DISCONNECTING:
// Disconnecting loading indicator
mStatusLoadingText->setVisible(true);
status_text = LLTrans::getString("SocialFlickrDisconnecting");
mStatusLoadingText->setValue(status_text);
mStatusLoadingIndicator->setVisible(true);
break;
case LLFlickrConnect::FLICKR_DISCONNECT_FAILED:
// Error disconnecting from the service
mStatusErrorText->setVisible(true);
status_text = LLTrans::getString("SocialFlickrErrorDisconnecting");
mStatusErrorText->setValue(status_text);
break;
}
}
LLFloater::draw();
}

View File

@ -1,134 +0,0 @@
/**
* @file llfloaterflickr.h
* @brief Header file for llfloaterflickr
* @author cho@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_LLFLOATERFLICKR_H
#define LL_LLFLOATERFLICKR_H
#include "llfloater.h"
#include "lltextbox.h"
#include "llviewertexture.h"
class LLIconCtrl;
class LLCheckBoxCtrl;
class LLSnapshotLivePreview;
class LLFloaterBigPreview;
class LLFlickrPhotoPanel : public LLPanel
{
public:
LLFlickrPhotoPanel();
~LLFlickrPhotoPanel();
BOOL postBuild();
S32 notify(const LLSD& info);
void draw();
LLSnapshotLivePreview* getPreviewView();
void onVisibilityChange(BOOL new_visibility);
void onClickNewSnapshot();
void onClickBigPreview();
void onSend();
bool onFlickrConnectStateChange(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 * mTitleTextBox;
LLUICtrl * mDescriptionTextBox;
LLUICtrl * mLocationCheckbox;
LLUICtrl * mTagsTextBox;
LLUICtrl * mRatingComboBox;
LLUICtrl * mPostButton;
LLUICtrl * mCancelButton;
LLButton * mBtnPreview;
LLFloaterBigPreview * mBigPreviewFloater;
};
class LLFlickrAccountPanel : public LLPanel
{
public:
LLFlickrAccountPanel();
BOOL postBuild();
void draw();
private:
void onVisibilityChange(BOOL new_visibility);
bool onFlickrConnectStateChange(const LLSD& data);
bool onFlickrConnectInfoChange();
void onConnect();
void onUseAnotherAccount();
void onDisconnect();
void showConnectButton();
void hideConnectButton();
void showDisconnectedLayout();
void showConnectedLayout();
LLTextBox * mAccountCaptionLabel;
LLTextBox * mAccountNameLabel;
LLUICtrl * mPanelButtons;
LLUICtrl * mConnectButton;
LLUICtrl * mDisconnectButton;
};
class LLFloaterFlickr : public LLFloater
{
public:
LLFloaterFlickr(const LLSD& key);
BOOL postBuild();
void draw();
void onClose(bool app_quitting);
void onCancel();
void showPhotoPanel();
private:
LLFlickrPhotoPanel* mFlickrPhotoPanel;
LLTextBox* mStatusErrorText;
LLTextBox* mStatusLoadingText;
LLUICtrl* mStatusLoadingIndicator;
};
#endif // LL_LLFLOATERFLICKR_H

View File

@ -41,6 +41,7 @@
#include "llkeyboard.h"
#include "llmenugl.h"
#include "llmultigesture.h"
#include "llnotificationsutil.h"
#include "llpreviewgesture.h"
#include "llscrolllistctrl.h"
#include "lltrans.h"
@ -125,6 +126,7 @@ LLFloaterGesture::LLFloaterGesture(const LLSD& key)
mCommitCallbackRegistrar.add("Gesture.Action.ShowPreview", boost::bind(&LLFloaterGesture::onClickEdit, this));
mCommitCallbackRegistrar.add("Gesture.Action.CopyPaste", boost::bind(&LLFloaterGesture::onCopyPasteAction, this, _2));
mCommitCallbackRegistrar.add("Gesture.Action.SaveToCOF", boost::bind(&LLFloaterGesture::addToCurrentOutFit, this));
mCommitCallbackRegistrar.add("Gesture.Action.Rename", boost::bind(&LLFloaterGesture::onRenameSelected, this));
mEnableCallbackRegistrar.add("Gesture.EnableAction", boost::bind(&LLFloaterGesture::isActionEnabled, this, _2));
}
@ -430,6 +432,19 @@ bool LLFloaterGesture::isActionEnabled(const LLSD& command)
{
return mGestureList->getAllSelected().size() == 1;
}
else if ("rename_gesture" == command_name)
{
if (mGestureList->getAllSelected().size() == 1)
{
LLViewerInventoryItem* item = gInventory.getItem(mGestureList->getCurrentID());
if (item && item->getPermissions().allowModifyBy(gAgentID))
{
return true;
}
}
return false;
}
return true;
}
@ -514,6 +529,44 @@ void LLFloaterGesture::onActivateBtnClick()
}
}
void LLFloaterGesture::onRenameSelected()
{
LLViewerInventoryItem* gesture = gInventory.getItem(mGestureList->getCurrentID());
if (!gesture)
{
return;
}
LLSD args;
args["NAME"] = gesture->getName();
LLSD payload;
payload["gesture_id"] = mGestureList->getCurrentID();
LLNotificationsUtil::add("RenameGesture", args, payload, boost::bind(onGestureRename, _1, _2));
}
void LLFloaterGesture::onGestureRename(const LLSD& notification, const LLSD& response)
{
S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
if (option != 0) return; // canceled
std::string new_name = response["new_name"].asString();
LLInventoryObject::correctInventoryName(new_name);
if (!new_name.empty())
{
LLUUID item_id = notification["payload"]["gesture_id"].asUUID();
LLViewerInventoryItem* gesture = gInventory.getItem(item_id);
if (gesture && (gesture->getName() != new_name))
{
LLSD updates;
updates["name"] = new_name;
update_inventory_item(item_id, updates, NULL);
}
}
}
void LLFloaterGesture::onCopyPasteAction(const LLSD& command)
{
std::string command_name = command.asString();

View File

@ -95,6 +95,9 @@ private:
void onCommitList();
void onCopyPasteAction(const LLSD& command);
void onDeleteSelected();
void onRenameSelected();
static void onGestureRename(const LLSD& notification, const LLSD& response);
LLUUID mSelectedID;
LLUUID mGestureFolderID;

View File

@ -39,7 +39,7 @@
#include "llxmltree.h"
std::map<std::string, std::string> LLFloaterGridStatus::sItemsMap;
const std::string DEFAULT_GRID_STATUS_URL = "http://secondlife-status.statuspage.io/";
const std::string DEFAULT_GRID_STATUS_URL = "http://status.secondlifegrid.net/";
LLFloaterGridStatus::LLFloaterGridStatus(const Params& key) :
LLFloaterWebContent(key),

View File

@ -3014,6 +3014,15 @@ void LLModelPreview::updateStatusMessages()
{
mFMP->childDisable("ok_btn");
}
if (mModelNoErrors && mLodsWithParsingError.empty())
{
mFMP->childEnable("calculate_btn");
}
else
{
mFMP->childDisable("calculate_btn");
}
//add up physics triangles etc
S32 phys_tris = 0;

View File

@ -31,8 +31,6 @@
#include "llagent.h"
#include "llfloaterreg.h"
#include "llfloaterflickr.h"
#include "llfloatertwitter.h"
#include "llimagefiltersmanager.h"
#include "llcheckboxctrl.h"
#include "llcombobox.h"

View File

@ -124,7 +124,9 @@ char const* const VISIBILITY_DEFAULT = "default";
char const* const VISIBILITY_HIDDEN = "hidden";
//control value for middle mouse as talk2push button
const static std::string MIDDLE_MOUSE_CV = "MiddleMouse";
const static std::string MIDDLE_MOUSE_CV = "MiddleMouse"; // for voice client and redability
const static std::string MOUSE_BUTTON_4_CV = "MouseButton4";
const static std::string MOUSE_BUTTON_5_CV = "MouseButton5";
/// This must equal the maximum value set for the IndirectMaxComplexity slider in panel_preferences_graphics1.xml
static const U32 INDIRECT_MAX_ARC_OFF = 101; // all the way to the right == disabled
@ -168,6 +170,7 @@ public:
void setParent(LLFloaterPreference* parent) { mParent = parent; }
BOOL handleKeyHere(KEY key, MASK mask);
BOOL handleAnyMouseClick(S32 x, S32 y, MASK mask, LLMouseHandler::EClickType clicktype, BOOL down);
static void onCancel(void* user_data);
private:
@ -211,6 +214,25 @@ BOOL LLVoiceSetKeyDialog::handleKeyHere(KEY key, MASK mask)
return result;
}
BOOL LLVoiceSetKeyDialog::handleAnyMouseClick(S32 x, S32 y, MASK mask, LLMouseHandler::EClickType clicktype, BOOL down)
{
BOOL result = FALSE;
if (down
&& (clicktype == LLMouseHandler::CLICK_MIDDLE || clicktype == LLMouseHandler::CLICK_BUTTON4 || clicktype == LLMouseHandler::CLICK_BUTTON5)
&& mask == 0)
{
mParent->setMouse(clicktype);
result = TRUE;
closeFloater();
}
else
{
result = LLMouseHandler::handleAnyMouseClick(x, y, mask, clicktype, down);
}
return result;
}
//static
void LLVoiceSetKeyDialog::onCancel(void* user_data)
{
@ -1694,6 +1716,41 @@ void LLFloaterPreference::setKey(KEY key)
getChild<LLUICtrl>("modifier_combo")->onCommit();
}
void LLFloaterPreference::setMouse(LLMouseHandler::EClickType click)
{
std::string bt_name;
std::string ctrl_value;
switch (click)
{
case LLMouseHandler::CLICK_MIDDLE:
bt_name = "middle_mouse";
ctrl_value = MIDDLE_MOUSE_CV;
break;
case LLMouseHandler::CLICK_BUTTON4:
bt_name = "button4_mouse";
ctrl_value = MOUSE_BUTTON_4_CV;
break;
case LLMouseHandler::CLICK_BUTTON5:
bt_name = "button5_mouse";
ctrl_value = MOUSE_BUTTON_5_CV;
break;
default:
break;
}
if (!ctrl_value.empty())
{
LLUICtrl* p2t_line_editor = getChild<LLUICtrl>("modifier_combo");
// We are using text control names for readability and compatibility with voice
p2t_line_editor->setControlValue(ctrl_value);
LLPanel* advanced_preferences = dynamic_cast<LLPanel*>(p2t_line_editor->getParent());
if (advanced_preferences)
{
p2t_line_editor->setValue(advanced_preferences->getString(bt_name));
}
}
}
void LLFloaterPreference::onClickSetMiddleMouse()
{
LLUICtrl* p2t_line_editor = getChild<LLUICtrl>("modifier_combo");
@ -2431,10 +2488,19 @@ BOOL LLPanelPreference::postBuild()
if (hasChild("modifier_combo", TRUE))
{
//localizing if push2talk button is set to middle mouse
if (MIDDLE_MOUSE_CV == getChild<LLUICtrl>("modifier_combo")->getValue().asString())
std::string modifier_value = getChild<LLUICtrl>("modifier_combo")->getValue().asString();
if (MIDDLE_MOUSE_CV == modifier_value)
{
getChild<LLUICtrl>("modifier_combo")->setValue(getString("middle_mouse"));
}
else if (MOUSE_BUTTON_4_CV == modifier_value)
{
getChild<LLUICtrl>("modifier_combo")->setValue(getString("button4_mouse"));
}
else if (MOUSE_BUTTON_5_CV == modifier_value)
{
getChild<LLUICtrl>("modifier_combo")->setValue(getString("button5_mouse"));
}
}
//////////////////////PanelSetup ///////////////////

View File

@ -148,6 +148,7 @@ public:
void onSelectSkin();
void onClickSetKey();
void setKey(KEY key);
void setMouse(LLMouseHandler::EClickType click);
void onClickSetMiddleMouse();
void onClickSetSounds();
void onClickEnablePopup();

View File

@ -85,7 +85,7 @@ public:
}
virtual void changed(U32 mask);
private:
LLFloaterProperties* mFloater;
LLFloaterProperties* mFloater; // Not a handle because LLFloaterProperties is managing LLPropertiesObserver
};
void LLPropertiesObserver::changed(U32 mask)

View File

@ -29,8 +29,6 @@
#include "llfloatersnapshot.h"
#include "llfloaterreg.h"
#include "llfloaterflickr.h"
#include "llfloatertwitter.h"
#include "llimagefiltersmanager.h"
#include "llcheckboxctrl.h"
#include "llcombobox.h"
@ -1240,10 +1238,7 @@ BOOL LLFloaterSnapshot::isWaitingState()
BOOL LLFloaterSnapshotBase::ImplBase::updatePreviewList(bool initialized)
{
LLFloaterFlickr* floater_flickr = LLFloaterReg::findTypedInstance<LLFloaterFlickr>("flickr");
LLFloaterTwitter* floater_twitter = LLFloaterReg::findTypedInstance<LLFloaterTwitter>("twitter");
if (!initialized && !floater_flickr && !floater_twitter)
if (!initialized)
return FALSE;
BOOL changed = FALSE;

View File

@ -1,810 +0,0 @@
/**
* @file llfloatertwitter.cpp
* @brief Implementation of llfloatertwitter
* @author cho@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$
*/
#include "llviewerprecompiledheaders.h"
#include "llfloatertwitter.h"
#include "llagent.h"
#include "llagentui.h"
#include "llcheckboxctrl.h"
#include "llcombobox.h"
#include "lltwitterconnect.h"
#include "llfloaterbigpreview.h"
#include "llfloaterreg.h"
#include "lliconctrl.h"
#include "llimagefiltersmanager.h"
#include "llresmgr.h" // LLLocale
#include "llsdserialize.h"
#include "llloadingindicator.h"
#include "llslurl.h"
#include "lltrans.h"
#include "llsnapshotlivepreview.h"
#include "llviewerregion.h"
#include "llviewercontrol.h"
#include "llviewermedia.h"
#include "lltabcontainer.h"
#include "lltexteditor.h"
static LLPanelInjector<LLTwitterPhotoPanel> t_panel_photo("lltwitterphotopanel");
static LLPanelInjector<LLTwitterAccountPanel> t_panel_account("lltwitteraccountpanel");
const std::string DEFAULT_PHOTO_LOCATION_URL = "http://maps.secondlife.com/";
const std::string DEFAULT_PHOTO_QUERY_PARAMETERS = "?sourceid=slshare_photo&utm_source=twitter&utm_medium=photo&utm_campaign=slshare";
const std::string DEFAULT_STATUS_TEXT = " #SecondLife";
///////////////////////////
//LLTwitterPhotoPanel///////
///////////////////////////
LLTwitterPhotoPanel::LLTwitterPhotoPanel() :
mResolutionComboBox(NULL),
mRefreshBtn(NULL),
mBtnPreview(NULL),
mWorkingLabel(NULL),
mThumbnailPlaceholder(NULL),
mStatusCounterLabel(NULL),
mStatusTextBox(NULL),
mLocationCheckbox(NULL),
mPhotoCheckbox(NULL),
mBigPreviewFloater(NULL),
mPostButton(NULL)
{
mCommitCallbackRegistrar.add("SocialSharing.SendPhoto", boost::bind(&LLTwitterPhotoPanel::onSend, this));
mCommitCallbackRegistrar.add("SocialSharing.RefreshPhoto", boost::bind(&LLTwitterPhotoPanel::onClickNewSnapshot, this));
mCommitCallbackRegistrar.add("SocialSharing.BigPreview", boost::bind(&LLTwitterPhotoPanel::onClickBigPreview, this));
}
LLTwitterPhotoPanel::~LLTwitterPhotoPanel()
{
if(mPreviewHandle.get())
{
mPreviewHandle.get()->die();
}
}
BOOL LLTwitterPhotoPanel::postBuild()
{
setVisibleCallback(boost::bind(&LLTwitterPhotoPanel::onVisibilityChange, this, _2));
mResolutionComboBox = getChild<LLUICtrl>("resolution_combobox");
mResolutionComboBox->setValue("[i800,i600]"); // hardcoded defaults ftw!
mResolutionComboBox->setCommitCallback(boost::bind(&LLTwitterPhotoPanel::updateResolution, this, TRUE));
mFilterComboBox = getChild<LLUICtrl>("filters_combobox");
mFilterComboBox->setCommitCallback(boost::bind(&LLTwitterPhotoPanel::updateResolution, this, TRUE));
mRefreshBtn = getChild<LLUICtrl>("new_snapshot_btn");
mBtnPreview = getChild<LLButton>("big_preview_btn");
mWorkingLabel = getChild<LLUICtrl>("working_lbl");
mThumbnailPlaceholder = getChild<LLUICtrl>("thumbnail_placeholder");
mStatusCounterLabel = getChild<LLUICtrl>("status_counter_label");
mStatusTextBox = getChild<LLUICtrl>("photo_status");
mStatusTextBox->setValue(DEFAULT_STATUS_TEXT);
mLocationCheckbox = getChild<LLUICtrl>("add_location_cb");
mLocationCheckbox->setCommitCallback(boost::bind(&LLTwitterPhotoPanel::onAddLocationToggled, this));
mPhotoCheckbox = getChild<LLUICtrl>("add_photo_cb");
mPhotoCheckbox->setCommitCallback(boost::bind(&LLTwitterPhotoPanel::onAddPhotoToggled, this));
mPostButton = getChild<LLUICtrl>("post_photo_btn");
mCancelButton = getChild<LLUICtrl>("cancel_photo_btn");
mBigPreviewFloater = dynamic_cast<LLFloaterBigPreview*>(LLFloaterReg::getInstance("big_preview"));
// Update filter list
std::vector<std::string> filter_list = LLImageFiltersManager::getInstance()->getFiltersList();
LLComboBox* filterbox = static_cast<LLComboBox *>(mFilterComboBox);
for (U32 i = 0; i < filter_list.size(); i++)
{
filterbox->add(filter_list[i]);
}
return LLPanel::postBuild();
}
// virtual
S32 LLTwitterPhotoPanel::notify(const LLSD& info)
{
if (info.has("snapshot-updating"))
{
// Disable the Post button and whatever else while the snapshot is not updated
// updateControls();
return 1;
}
if (info.has("snapshot-updated"))
{
// Enable the send/post/save buttons.
updateControls();
// The refresh button is initially hidden. We show it after the first update,
// i.e. after snapshot is taken
LLUICtrl * refresh_button = getRefreshBtn();
if (!refresh_button->getVisible())
{
refresh_button->setVisible(true);
}
return 1;
}
return 0;
}
void LLTwitterPhotoPanel::draw()
{
LLSnapshotLivePreview * previewp = static_cast<LLSnapshotLivePreview *>(mPreviewHandle.get());
// Enable interaction only if no transaction with the service is on-going (prevent duplicated posts)
bool no_ongoing_connection = !(LLTwitterConnect::instance().isTransactionOngoing());
bool photo_checked = mPhotoCheckbox->getValue().asBoolean();
mCancelButton->setEnabled(no_ongoing_connection);
mStatusTextBox->setEnabled(no_ongoing_connection);
mResolutionComboBox->setEnabled(no_ongoing_connection && photo_checked);
mFilterComboBox->setEnabled(no_ongoing_connection && photo_checked);
mRefreshBtn->setEnabled(no_ongoing_connection && photo_checked);
mBtnPreview->setEnabled(no_ongoing_connection);
mLocationCheckbox->setEnabled(no_ongoing_connection);
mPhotoCheckbox->setEnabled(no_ongoing_connection);
bool add_location = mLocationCheckbox->getValue().asBoolean();
bool add_photo = mPhotoCheckbox->getValue().asBoolean();
updateStatusTextLength(false);
// Reassign the preview floater if we have the focus and the preview exists
if (hasFocus() && isPreviewVisible())
{
attachPreview();
}
// Toggle the button state as appropriate
bool preview_active = (isPreviewVisible() && mBigPreviewFloater->isFloaterOwner(getParentByType<LLFloater>()));
mBtnPreview->setToggleState(preview_active);
// Display the preview if one is available
if (previewp && previewp->getThumbnailImage())
{
const LLRect& thumbnail_rect = mThumbnailPlaceholder->getRect();
const S32 thumbnail_w = previewp->getThumbnailWidth();
const S32 thumbnail_h = previewp->getThumbnailHeight();
// calc preview offset within the preview rect
const S32 local_offset_x = (thumbnail_rect.getWidth() - thumbnail_w) / 2 ;
const S32 local_offset_y = (thumbnail_rect.getHeight() - thumbnail_h) / 2 ;
S32 offset_x = thumbnail_rect.mLeft + local_offset_x;
S32 offset_y = thumbnail_rect.mBottom + local_offset_y;
gGL.matrixMode(LLRender::MM_MODELVIEW);
// Apply floater transparency to the texture unless the floater is focused.
F32 alpha = (add_photo ? (getTransparencyType() == TT_ACTIVE ? 1.0f : getCurrentTransparency()) : 0.5f);
LLColor4 color = LLColor4::white;
gl_draw_scaled_image(offset_x, offset_y,
thumbnail_w, thumbnail_h,
previewp->getThumbnailImage(), color % alpha);
}
// Update the visibility of the working (computing preview) label
mWorkingLabel->setVisible(!(previewp && previewp->getSnapshotUpToDate()));
// Enable Post if we have a preview to send and no on going connection being processed
mPostButton->setEnabled(no_ongoing_connection && (previewp && previewp->getSnapshotUpToDate()) && (add_photo || add_location || !mStatusTextBox->getValue().asString().empty()));
// Draw the rest of the panel on top of it
LLPanel::draw();
}
LLSnapshotLivePreview* LLTwitterPhotoPanel::getPreviewView()
{
LLSnapshotLivePreview* previewp = (LLSnapshotLivePreview*)mPreviewHandle.get();
return previewp;
}
void LLTwitterPhotoPanel::onVisibilityChange(BOOL visible)
{
if (visible)
{
if (mPreviewHandle.get())
{
LLSnapshotLivePreview* preview = getPreviewView();
if(preview)
{
LL_DEBUGS() << "opened, updating snapshot" << LL_ENDL;
preview->updateSnapshot(TRUE);
}
}
else
{
LLRect full_screen_rect = getRootView()->getRect();
LLSnapshotLivePreview::Params p;
p.rect(full_screen_rect);
LLSnapshotLivePreview* previewp = new LLSnapshotLivePreview(p);
mPreviewHandle = previewp->getHandle();
previewp->setContainer(this);
previewp->setSnapshotType(LLSnapshotModel::SNAPSHOT_WEB);
previewp->setSnapshotFormat(LLSnapshotModel::SNAPSHOT_FORMAT_JPEG);
previewp->setThumbnailSubsampled(TRUE); // We want the preview to reflect the *saved* image
previewp->setAllowRenderUI(FALSE); // We do not want the rendered UI in our snapshots
previewp->setAllowFullScreenPreview(FALSE); // No full screen preview in SL Share mode
previewp->setThumbnailPlaceholderRect(mThumbnailPlaceholder->getRect());
updateControls();
}
}
}
void LLTwitterPhotoPanel::onAddLocationToggled()
{
bool add_location = mLocationCheckbox->getValue().asBoolean();
updateStatusTextLength(!add_location);
}
void LLTwitterPhotoPanel::onAddPhotoToggled()
{
bool add_photo = mPhotoCheckbox->getValue().asBoolean();
updateStatusTextLength(!add_photo);
}
void LLTwitterPhotoPanel::onClickNewSnapshot()
{
LLSnapshotLivePreview* previewp = getPreviewView();
if (previewp)
{
previewp->updateSnapshot(TRUE);
}
}
void LLTwitterPhotoPanel::onClickBigPreview()
{
// Toggle the preview
if (isPreviewVisible())
{
LLFloaterReg::hideInstance("big_preview");
}
else
{
attachPreview();
LLFloaterReg::showInstance("big_preview");
}
}
bool LLTwitterPhotoPanel::isPreviewVisible()
{
return (mBigPreviewFloater && mBigPreviewFloater->getVisible());
}
void LLTwitterPhotoPanel::attachPreview()
{
if (mBigPreviewFloater)
{
LLSnapshotLivePreview* previewp = getPreviewView();
mBigPreviewFloater->setPreview(previewp);
mBigPreviewFloater->setFloaterOwner(getParentByType<LLFloater>());
}
}
void LLTwitterPhotoPanel::onSend()
{
LLEventPumps::instance().obtain("TwitterConnectState").stopListening("LLTwitterPhotoPanel"); // just in case it is already listening
LLEventPumps::instance().obtain("TwitterConnectState").listen("LLTwitterPhotoPanel", boost::bind(&LLTwitterPhotoPanel::onTwitterConnectStateChange, this, _1));
// Connect to Twitter if necessary and then post
if (LLTwitterConnect::instance().isConnected())
{
sendPhoto();
}
else
{
LLTwitterConnect::instance().checkConnectionToTwitter(true);
}
}
bool LLTwitterPhotoPanel::onTwitterConnectStateChange(const LLSD& data)
{
switch (data.get("enum").asInteger())
{
case LLTwitterConnect::TWITTER_CONNECTED:
sendPhoto();
break;
case LLTwitterConnect::TWITTER_POSTED:
LLEventPumps::instance().obtain("TwitterConnectState").stopListening("LLTwitterPhotoPanel");
clearAndClose();
break;
}
return false;
}
void LLTwitterPhotoPanel::sendPhoto()
{
// Get the status text
std::string status = mStatusTextBox->getValue().asString();
// Add the location if required
bool add_location = mLocationCheckbox->getValue().asBoolean();
if (add_location)
{
// Get the SLURL for the location
LLSLURL slurl;
LLAgentUI::buildSLURL(slurl);
std::string slurl_string = slurl.getSLURLString();
// Use a valid http:// URL if the scheme is secondlife://
LLURI slurl_uri(slurl_string);
if (slurl_uri.scheme() == LLSLURL::SLURL_SECONDLIFE_SCHEME)
{
slurl_string = DEFAULT_PHOTO_LOCATION_URL;
}
// Add query parameters so Google Analytics can track incoming clicks!
slurl_string += DEFAULT_PHOTO_QUERY_PARAMETERS;
// Add it to the status (pretty crude, but we don't have a better option with photos)
if (status.empty())
status = slurl_string;
else
status = status + " " + slurl_string;
}
// Add the photo if required
bool add_photo = mPhotoCheckbox->getValue().asBoolean();
if (add_photo)
{
// Get the image
LLSnapshotLivePreview* previewp = getPreviewView();
// Post to Twitter
LLTwitterConnect::instance().uploadPhoto(previewp->getFormattedImage(), status);
}
else
{
// Just post the status to Twitter
LLTwitterConnect::instance().updateStatus(status);
}
updateControls();
}
void LLTwitterPhotoPanel::clearAndClose()
{
mStatusTextBox->setValue(DEFAULT_STATUS_TEXT);
LLFloater* floater = getParentByType<LLFloater>();
if (floater)
{
floater->closeFloater();
if (mBigPreviewFloater)
{
mBigPreviewFloater->closeOnFloaterOwnerClosing(floater);
}
}
}
void LLTwitterPhotoPanel::updateStatusTextLength(BOOL restore_old_status_text)
{
bool add_location = mLocationCheckbox->getValue().asBoolean();
// Restrict the status text length to Twitter's character limit
LLTextEditor* status_text_box = dynamic_cast<LLTextEditor*>(mStatusTextBox);
if (status_text_box)
{
int max_status_length = 280 - (add_location ? 40 : 0);
status_text_box->setMaxTextLength(max_status_length);
if (restore_old_status_text)
{
if (mOldStatusText.length() > status_text_box->getText().length() && status_text_box->getText() == mOldStatusText.substr(0, status_text_box->getText().length()))
{
status_text_box->setText(mOldStatusText);
}
if (mOldStatusText.length() <= max_status_length)
{
mOldStatusText = "";
}
}
if (status_text_box->getText().length() > max_status_length)
{
if (mOldStatusText.length() < status_text_box->getText().length() || status_text_box->getText() != mOldStatusText.substr(0, status_text_box->getText().length()))
{
mOldStatusText = status_text_box->getText();
}
status_text_box->setText(mOldStatusText.substr(0, max_status_length));
}
// Update the status character counter
int characters_remaining = max_status_length - status_text_box->getText().length();
mStatusCounterLabel->setValue(characters_remaining);
}
}
void LLTwitterPhotoPanel::updateControls()
{
LLSnapshotLivePreview* previewp = getPreviewView();
BOOL got_snap = previewp && previewp->getSnapshotUpToDate();
// *TODO: Separate maximum size for Web images from postcards
LL_DEBUGS() << "Is snapshot up-to-date? " << got_snap << LL_ENDL;
updateResolution(FALSE);
}
void LLTwitterPhotoPanel::updateResolution(BOOL do_update)
{
LLComboBox* combobox = static_cast<LLComboBox *>(mResolutionComboBox);
LLComboBox* filterbox = static_cast<LLComboBox *>(mFilterComboBox);
std::string sdstring = combobox->getSelectedValue();
LLSD sdres;
std::stringstream sstream(sdstring);
LLSDSerialize::fromNotation(sdres, sstream, sdstring.size());
S32 width = sdres[0];
S32 height = sdres[1];
// Note : index 0 of the filter drop down is assumed to be "No filter" in whichever locale
std::string filter_name = (filterbox->getCurrentIndex() ? filterbox->getSimple() : "");
LLSnapshotLivePreview * previewp = static_cast<LLSnapshotLivePreview *>(mPreviewHandle.get());
if (previewp && combobox->getCurrentIndex() >= 0)
{
S32 original_width = 0 , original_height = 0 ;
previewp->getSize(original_width, original_height) ;
if (width == 0 || height == 0)
{
// take resolution from current window size
LL_DEBUGS() << "Setting preview res from window: " << gViewerWindow->getWindowWidthRaw() << "x" << gViewerWindow->getWindowHeightRaw() << LL_ENDL;
previewp->setSize(gViewerWindow->getWindowWidthRaw(), gViewerWindow->getWindowHeightRaw());
}
else
{
// use the resolution from the selected pre-canned drop-down choice
LL_DEBUGS() << "Setting preview res selected from combo: " << width << "x" << height << LL_ENDL;
previewp->setSize(width, height);
}
checkAspectRatio(width);
previewp->getSize(width, height);
if (original_width != width || original_height != height)
{
previewp->setSize(width, height);
if (do_update)
{
previewp->updateSnapshot(TRUE);
updateControls();
}
}
// Get the old filter, compare to the current one "filter_name" and set if changed
std::string original_filter = previewp->getFilter();
if (original_filter != filter_name)
{
previewp->setFilter(filter_name);
if (do_update)
{
previewp->updateSnapshot(FALSE, TRUE);
updateControls();
}
}
}
}
void LLTwitterPhotoPanel::checkAspectRatio(S32 index)
{
LLSnapshotLivePreview *previewp = getPreviewView() ;
BOOL keep_aspect = FALSE;
if (0 == index) // current window size
{
keep_aspect = TRUE;
}
else // predefined resolution
{
keep_aspect = FALSE;
}
if (previewp)
{
previewp->mKeepAspectRatio = keep_aspect;
}
}
LLUICtrl* LLTwitterPhotoPanel::getRefreshBtn()
{
return mRefreshBtn;
}
///////////////////////////
//LLTwitterAccountPanel//////
///////////////////////////
LLTwitterAccountPanel::LLTwitterAccountPanel() :
mAccountCaptionLabel(NULL),
mAccountNameLabel(NULL),
mPanelButtons(NULL),
mConnectButton(NULL),
mDisconnectButton(NULL)
{
mCommitCallbackRegistrar.add("SocialSharing.Connect", boost::bind(&LLTwitterAccountPanel::onConnect, this));
mCommitCallbackRegistrar.add("SocialSharing.Disconnect", boost::bind(&LLTwitterAccountPanel::onDisconnect, this));
setVisibleCallback(boost::bind(&LLTwitterAccountPanel::onVisibilityChange, this, _2));
}
BOOL LLTwitterAccountPanel::postBuild()
{
mAccountCaptionLabel = getChild<LLTextBox>("account_caption_label");
mAccountNameLabel = getChild<LLTextBox>("account_name_label");
mPanelButtons = getChild<LLUICtrl>("panel_buttons");
mConnectButton = getChild<LLUICtrl>("connect_btn");
mDisconnectButton = getChild<LLUICtrl>("disconnect_btn");
return LLPanel::postBuild();
}
void LLTwitterAccountPanel::draw()
{
LLTwitterConnect::EConnectionState connection_state = LLTwitterConnect::instance().getConnectionState();
//Disable the 'disconnect' button and the 'use another account' button when disconnecting in progress
bool disconnecting = connection_state == LLTwitterConnect::TWITTER_DISCONNECTING;
mDisconnectButton->setEnabled(!disconnecting);
//Disable the 'connect' button when a connection is in progress
bool connecting = connection_state == LLTwitterConnect::TWITTER_CONNECTION_IN_PROGRESS;
mConnectButton->setEnabled(!connecting);
LLPanel::draw();
}
void LLTwitterAccountPanel::onVisibilityChange(BOOL visible)
{
if(visible)
{
LLEventPumps::instance().obtain("TwitterConnectState").stopListening("LLTwitterAccountPanel");
LLEventPumps::instance().obtain("TwitterConnectState").listen("LLTwitterAccountPanel", boost::bind(&LLTwitterAccountPanel::onTwitterConnectStateChange, this, _1));
LLEventPumps::instance().obtain("TwitterConnectInfo").stopListening("LLTwitterAccountPanel");
LLEventPumps::instance().obtain("TwitterConnectInfo").listen("LLTwitterAccountPanel", boost::bind(&LLTwitterAccountPanel::onTwitterConnectInfoChange, this));
//Connected
if(LLTwitterConnect::instance().isConnected())
{
showConnectedLayout();
}
//Check if connected (show disconnected layout in meantime)
else
{
showDisconnectedLayout();
}
if ((LLTwitterConnect::instance().getConnectionState() == LLTwitterConnect::TWITTER_NOT_CONNECTED) ||
(LLTwitterConnect::instance().getConnectionState() == LLTwitterConnect::TWITTER_CONNECTION_FAILED))
{
LLTwitterConnect::instance().checkConnectionToTwitter();
}
}
else
{
LLEventPumps::instance().obtain("TwitterConnectState").stopListening("LLTwitterAccountPanel");
LLEventPumps::instance().obtain("TwitterConnectInfo").stopListening("LLTwitterAccountPanel");
}
}
bool LLTwitterAccountPanel::onTwitterConnectStateChange(const LLSD& data)
{
if(LLTwitterConnect::instance().isConnected())
{
//In process of disconnecting so leave the layout as is
if(data.get("enum").asInteger() != LLTwitterConnect::TWITTER_DISCONNECTING)
{
showConnectedLayout();
}
}
else
{
showDisconnectedLayout();
}
return false;
}
bool LLTwitterAccountPanel::onTwitterConnectInfoChange()
{
LLSD info = LLTwitterConnect::instance().getInfo();
std::string clickable_name;
//Strings of format [http://www.somewebsite.com Click Me] become clickable text
if(info.has("link") && info.has("name"))
{
clickable_name = "[" + info["link"].asString() + " " + info["name"].asString() + "]";
}
mAccountNameLabel->setText(clickable_name);
return false;
}
void LLTwitterAccountPanel::showConnectButton()
{
if(!mConnectButton->getVisible())
{
mConnectButton->setVisible(TRUE);
mDisconnectButton->setVisible(FALSE);
}
}
void LLTwitterAccountPanel::hideConnectButton()
{
if(mConnectButton->getVisible())
{
mConnectButton->setVisible(FALSE);
mDisconnectButton->setVisible(TRUE);
}
}
void LLTwitterAccountPanel::showDisconnectedLayout()
{
mAccountCaptionLabel->setText(getString("twitter_disconnected"));
mAccountNameLabel->setText(std::string(""));
showConnectButton();
}
void LLTwitterAccountPanel::showConnectedLayout()
{
LLTwitterConnect::instance().loadTwitterInfo();
mAccountCaptionLabel->setText(getString("twitter_connected"));
hideConnectButton();
}
void LLTwitterAccountPanel::onConnect()
{
LLTwitterConnect::instance().checkConnectionToTwitter(true);
}
void LLTwitterAccountPanel::onDisconnect()
{
LLTwitterConnect::instance().disconnectFromTwitter();
}
////////////////////////
//LLFloaterTwitter///////
////////////////////////
LLFloaterTwitter::LLFloaterTwitter(const LLSD& key) : LLFloater(key),
mTwitterPhotoPanel(NULL),
mStatusErrorText(NULL),
mStatusLoadingText(NULL),
mStatusLoadingIndicator(NULL)
{
mCommitCallbackRegistrar.add("SocialSharing.Cancel", boost::bind(&LLFloaterTwitter::onCancel, this));
}
void LLFloaterTwitter::onClose(bool app_quitting)
{
LLFloaterBigPreview* big_preview_floater = dynamic_cast<LLFloaterBigPreview*>(LLFloaterReg::getInstance("big_preview"));
if (big_preview_floater)
{
big_preview_floater->closeOnFloaterOwnerClosing(this);
}
LLFloater::onClose(app_quitting);
}
void LLFloaterTwitter::onCancel()
{
LLFloaterBigPreview* big_preview_floater = dynamic_cast<LLFloaterBigPreview*>(LLFloaterReg::getInstance("big_preview"));
if (big_preview_floater)
{
big_preview_floater->closeOnFloaterOwnerClosing(this);
}
closeFloater();
}
BOOL LLFloaterTwitter::postBuild()
{
// Keep tab of the Photo Panel
mTwitterPhotoPanel = static_cast<LLTwitterPhotoPanel*>(getChild<LLUICtrl>("panel_twitter_photo"));
// Connection status widgets
mStatusErrorText = getChild<LLTextBox>("connection_error_text");
mStatusLoadingText = getChild<LLTextBox>("connection_loading_text");
mStatusLoadingIndicator = getChild<LLUICtrl>("connection_loading_indicator");
return LLFloater::postBuild();
}
void LLFloaterTwitter::showPhotoPanel()
{
LLTabContainer* parent = dynamic_cast<LLTabContainer*>(mTwitterPhotoPanel->getParent());
if (!parent)
{
LL_WARNS() << "Cannot find panel container" << LL_ENDL;
return;
}
parent->selectTabPanel(mTwitterPhotoPanel);
}
void LLFloaterTwitter::draw()
{
if (mStatusErrorText && mStatusLoadingText && mStatusLoadingIndicator)
{
mStatusErrorText->setVisible(false);
mStatusLoadingText->setVisible(false);
mStatusLoadingIndicator->setVisible(false);
LLTwitterConnect::EConnectionState connection_state = LLTwitterConnect::instance().getConnectionState();
std::string status_text;
switch (connection_state)
{
case LLTwitterConnect::TWITTER_NOT_CONNECTED:
// No status displayed when first opening the panel and no connection done
case LLTwitterConnect::TWITTER_CONNECTED:
// When successfully connected, no message is displayed
case LLTwitterConnect::TWITTER_POSTED:
// No success message to show since we actually close the floater after successful posting completion
break;
case LLTwitterConnect::TWITTER_CONNECTION_IN_PROGRESS:
// Connection loading indicator
mStatusLoadingText->setVisible(true);
status_text = LLTrans::getString("SocialTwitterConnecting");
mStatusLoadingText->setValue(status_text);
mStatusLoadingIndicator->setVisible(true);
break;
case LLTwitterConnect::TWITTER_POSTING:
// Posting indicator
mStatusLoadingText->setVisible(true);
status_text = LLTrans::getString("SocialTwitterPosting");
mStatusLoadingText->setValue(status_text);
mStatusLoadingIndicator->setVisible(true);
break;
case LLTwitterConnect::TWITTER_CONNECTION_FAILED:
// Error connecting to the service
mStatusErrorText->setVisible(true);
status_text = LLTrans::getString("SocialTwitterErrorConnecting");
mStatusErrorText->setValue(status_text);
break;
case LLTwitterConnect::TWITTER_POST_FAILED:
// Error posting to the service
mStatusErrorText->setVisible(true);
status_text = LLTrans::getString("SocialTwitterErrorPosting");
mStatusErrorText->setValue(status_text);
break;
case LLTwitterConnect::TWITTER_DISCONNECTING:
// Disconnecting loading indicator
mStatusLoadingText->setVisible(true);
status_text = LLTrans::getString("SocialTwitterDisconnecting");
mStatusLoadingText->setValue(status_text);
mStatusLoadingIndicator->setVisible(true);
break;
case LLTwitterConnect::TWITTER_DISCONNECT_FAILED:
// Error disconnecting from the service
mStatusErrorText->setVisible(true);
status_text = LLTrans::getString("SocialTwitterErrorDisconnecting");
mStatusErrorText->setValue(status_text);
break;
}
}
LLFloater::draw();
}

View File

@ -1,138 +0,0 @@
/**
* @file llfloatertwitter.h
* @brief Header file for llfloatertwitter
* @author cho@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_LLFLOATERTWITTER_H
#define LL_LLFLOATERTWITTER_H
#include "llfloater.h"
#include "lltextbox.h"
#include "llviewertexture.h"
class LLIconCtrl;
class LLCheckBoxCtrl;
class LLSnapshotLivePreview;
class LLFloaterBigPreview;
class LLTwitterPhotoPanel : public LLPanel
{
public:
LLTwitterPhotoPanel();
~LLTwitterPhotoPanel();
BOOL postBuild();
void draw();
LLSnapshotLivePreview* getPreviewView();
void onVisibilityChange(BOOL new_visibility);
void onAddLocationToggled();
void onAddPhotoToggled();
void onClickBigPreview();
void onClickNewSnapshot();
void onSend();
S32 notify(const LLSD& info);
bool onTwitterConnectStateChange(const LLSD& data);
void sendPhoto();
void clearAndClose();
void updateStatusTextLength(BOOL restore_old_status_text);
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 * mStatusCounterLabel;
LLUICtrl * mStatusTextBox;
LLUICtrl * mLocationCheckbox;
LLUICtrl * mPhotoCheckbox;
LLUICtrl * mPostButton;
LLUICtrl * mCancelButton;
LLButton * mBtnPreview;
LLFloaterBigPreview * mBigPreviewFloater;
std::string mOldStatusText;
};
class LLTwitterAccountPanel : public LLPanel
{
public:
LLTwitterAccountPanel();
BOOL postBuild();
void draw();
private:
void onVisibilityChange(BOOL new_visibility);
bool onTwitterConnectStateChange(const LLSD& data);
bool onTwitterConnectInfoChange();
void onConnect();
void onUseAnotherAccount();
void onDisconnect();
void showConnectButton();
void hideConnectButton();
void showDisconnectedLayout();
void showConnectedLayout();
LLTextBox * mAccountCaptionLabel;
LLTextBox * mAccountNameLabel;
LLUICtrl * mPanelButtons;
LLUICtrl * mConnectButton;
LLUICtrl * mDisconnectButton;
};
class LLFloaterTwitter : public LLFloater
{
public:
LLFloaterTwitter(const LLSD& key);
BOOL postBuild();
void draw();
void onClose(bool app_quitting);
void onCancel();
void showPhotoPanel();
private:
LLTwitterPhotoPanel* mTwitterPhotoPanel;
LLTextBox* mStatusErrorText;
LLTextBox* mStatusLoadingText;
LLUICtrl* mStatusLoadingIndicator;
};
#endif // LL_LLFLOATERTWITTER_H

View File

@ -30,8 +30,6 @@
#include "lliconctrl.h"
#include "llfloaterreg.h"
#include "llhttpconstants.h"
#include "llflickrconnect.h"
#include "lltwitterconnect.h"
#include "lllayoutstack.h"
#include "llpluginclassmedia.h"
#include "llprogressbar.h"
@ -288,26 +286,6 @@ void LLFloaterWebContent::onOpen(const LLSD& key)
//virtual
void LLFloaterWebContent::onClose(bool app_quitting)
{
// 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)
{
if (!LLFlickrConnect::instance().isConnected())
{
LLFlickrConnect::instance().setConnectionState(LLFlickrConnect::FLICKR_CONNECTION_FAILED);
}
}
// 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)
{
if (!LLTwitterConnect::instance().isConnected())
{
LLTwitterConnect::instance().setConnectionState(LLTwitterConnect::TWITTER_CONNECTION_FAILED);
}
}
LLViewerMedia::getInstance()->proxyWindowClosed(mUUID);
destroy();
}

View File

@ -90,7 +90,7 @@ void LLHUDEffectBeam::packData(LLMessageSystem *mesgsys)
memset(packed_data, 0, 41);
if (mSourceObject)
{
htonmemcpy(packed_data, mSourceObject->mID.mData, MVT_LLUUID, 16);
htolememcpy(packed_data, mSourceObject->mID.mData, MVT_LLUUID, 16);
}
if (mTargetObject)
@ -104,11 +104,11 @@ void LLHUDEffectBeam::packData(LLMessageSystem *mesgsys)
if (mTargetObject)
{
htonmemcpy(&(packed_data[17]), mTargetObject->mID.mData, MVT_LLUUID, 16);
htolememcpy(&(packed_data[17]), mTargetObject->mID.mData, MVT_LLUUID, 16);
}
else
{
htonmemcpy(&(packed_data[17]), mTargetPos.mdV, MVT_LLVector3d, 24);
htolememcpy(&(packed_data[17]), mTargetPos.mdV, MVT_LLVector3d, 24);
}
mesgsys->addBinaryDataFast(_PREHASH_TypeData, packed_data, 41);
}
@ -131,7 +131,7 @@ void LLHUDEffectBeam::unpackData(LLMessageSystem *mesgsys, S32 blocknum)
}
mesgsys->getBinaryDataFast(_PREHASH_Effect, _PREHASH_TypeData, packed_data, 41, blocknum);
htonmemcpy(source_id.mData, packed_data, MVT_LLUUID, 16);
htolememcpy(source_id.mData, packed_data, MVT_LLUUID, 16);
LLViewerObject *objp = gObjectList.findObject(source_id);
if (objp)
@ -143,7 +143,7 @@ void LLHUDEffectBeam::unpackData(LLMessageSystem *mesgsys, S32 blocknum)
if (use_target_object)
{
htonmemcpy(target_id.mData, &packed_data[17], MVT_LLUUID, 16);
htolememcpy(target_id.mData, &packed_data[17], MVT_LLUUID, 16);
LLViewerObject *objp = gObjectList.findObject(target_id);
if (objp)
@ -153,7 +153,7 @@ void LLHUDEffectBeam::unpackData(LLMessageSystem *mesgsys, S32 blocknum)
}
else
{
htonmemcpy(new_target.mdV, &(packed_data[17]), MVT_LLVector3d, 24);
htolememcpy(new_target.mdV, &(packed_data[17]), MVT_LLVector3d, 24);
setTargetPos(new_target);
}

View File

@ -269,29 +269,29 @@ void LLHUDEffectLookAt::packData(LLMessageSystem *mesgsys)
if (mSourceObject)
{
htonmemcpy(&(packed_data[SOURCE_AVATAR]), mSourceObject->mID.mData, MVT_LLUUID, 16);
htolememcpy(&(packed_data[SOURCE_AVATAR]), mSourceObject->mID.mData, MVT_LLUUID, 16);
}
else
{
htonmemcpy(&(packed_data[SOURCE_AVATAR]), LLUUID::null.mData, MVT_LLUUID, 16);
htolememcpy(&(packed_data[SOURCE_AVATAR]), LLUUID::null.mData, MVT_LLUUID, 16);
}
// pack both target object and position
// position interpreted as offset if target object is non-null
if (mTargetObject)
{
htonmemcpy(&(packed_data[TARGET_OBJECT]), mTargetObject->mID.mData, MVT_LLUUID, 16);
htolememcpy(&(packed_data[TARGET_OBJECT]), mTargetObject->mID.mData, MVT_LLUUID, 16);
}
else
{
htonmemcpy(&(packed_data[TARGET_OBJECT]), LLUUID::null.mData, MVT_LLUUID, 16);
htolememcpy(&(packed_data[TARGET_OBJECT]), LLUUID::null.mData, MVT_LLUUID, 16);
}
htonmemcpy(&(packed_data[TARGET_POS]), mTargetOffsetGlobal.mdV, MVT_LLVector3d, 24);
htolememcpy(&(packed_data[TARGET_POS]), mTargetOffsetGlobal.mdV, MVT_LLVector3d, 24);
U8 lookAtTypePacked = (U8)mTargetType;
htonmemcpy(&(packed_data[LOOKAT_TYPE]), &lookAtTypePacked, MVT_U8, 1);
htolememcpy(&(packed_data[LOOKAT_TYPE]), &lookAtTypePacked, MVT_U8, 1);
mesgsys->addBinaryDataFast(_PREHASH_TypeData, packed_data, PKT_SIZE);
@ -325,7 +325,7 @@ void LLHUDEffectLookAt::unpackData(LLMessageSystem *mesgsys, S32 blocknum)
}
mesgsys->getBinaryDataFast(_PREHASH_Effect, _PREHASH_TypeData, packed_data, PKT_SIZE, blocknum);
htonmemcpy(source_id.mData, &(packed_data[SOURCE_AVATAR]), MVT_LLUUID, 16);
htolememcpy(source_id.mData, &(packed_data[SOURCE_AVATAR]), MVT_LLUUID, 16);
LLViewerObject *objp = gObjectList.findObject(source_id);
if (objp && objp->isAvatar())
@ -338,11 +338,11 @@ void LLHUDEffectLookAt::unpackData(LLMessageSystem *mesgsys, S32 blocknum)
return;
}
htonmemcpy(target_id.mData, &(packed_data[TARGET_OBJECT]), MVT_LLUUID, 16);
htolememcpy(target_id.mData, &(packed_data[TARGET_OBJECT]), MVT_LLUUID, 16);
objp = gObjectList.findObject(target_id);
htonmemcpy(new_target.mdV, &(packed_data[TARGET_POS]), MVT_LLVector3d, 24);
htolememcpy(new_target.mdV, &(packed_data[TARGET_POS]), MVT_LLVector3d, 24);
if (objp)
{
@ -358,7 +358,7 @@ void LLHUDEffectLookAt::unpackData(LLMessageSystem *mesgsys, S32 blocknum)
}
U8 lookAtTypeUnpacked = 0;
htonmemcpy(&lookAtTypeUnpacked, &(packed_data[LOOKAT_TYPE]), MVT_U8, 1);
htolememcpy(&lookAtTypeUnpacked, &(packed_data[LOOKAT_TYPE]), MVT_U8, 1);
mTargetType = (ELookAtType)lookAtTypeUnpacked;
if (mTargetType == LOOKAT_TARGET_NONE)

View File

@ -107,28 +107,28 @@ void LLHUDEffectPointAt::packData(LLMessageSystem *mesgsys)
if (mSourceObject)
{
htonmemcpy(&(packed_data[SOURCE_AVATAR]), mSourceObject->mID.mData, MVT_LLUUID, 16);
htolememcpy(&(packed_data[SOURCE_AVATAR]), mSourceObject->mID.mData, MVT_LLUUID, 16);
}
else
{
htonmemcpy(&(packed_data[SOURCE_AVATAR]), LLUUID::null.mData, MVT_LLUUID, 16);
htolememcpy(&(packed_data[SOURCE_AVATAR]), LLUUID::null.mData, MVT_LLUUID, 16);
}
// pack both target object and position
// position interpreted as offset if target object is non-null
if (mTargetObject)
{
htonmemcpy(&(packed_data[TARGET_OBJECT]), mTargetObject->mID.mData, MVT_LLUUID, 16);
htolememcpy(&(packed_data[TARGET_OBJECT]), mTargetObject->mID.mData, MVT_LLUUID, 16);
}
else
{
htonmemcpy(&(packed_data[TARGET_OBJECT]), LLUUID::null.mData, MVT_LLUUID, 16);
htolememcpy(&(packed_data[TARGET_OBJECT]), LLUUID::null.mData, MVT_LLUUID, 16);
}
htonmemcpy(&(packed_data[TARGET_POS]), mTargetOffsetGlobal.mdV, MVT_LLVector3d, 24);
htolememcpy(&(packed_data[TARGET_POS]), mTargetOffsetGlobal.mdV, MVT_LLVector3d, 24);
U8 pointAtTypePacked = (U8)mTargetType;
htonmemcpy(&(packed_data[POINTAT_TYPE]), &pointAtTypePacked, MVT_U8, 1);
htolememcpy(&(packed_data[POINTAT_TYPE]), &pointAtTypePacked, MVT_U8, 1);
mesgsys->addBinaryDataFast(_PREHASH_TypeData, packed_data, PKT_SIZE);
@ -164,10 +164,10 @@ void LLHUDEffectPointAt::unpackData(LLMessageSystem *mesgsys, S32 blocknum)
}
mesgsys->getBinaryDataFast(_PREHASH_Effect, _PREHASH_TypeData, packed_data, PKT_SIZE, blocknum);
htonmemcpy(source_id.mData, &(packed_data[SOURCE_AVATAR]), MVT_LLUUID, 16);
htonmemcpy(target_id.mData, &(packed_data[TARGET_OBJECT]), MVT_LLUUID, 16);
htonmemcpy(new_target.mdV, &(packed_data[TARGET_POS]), MVT_LLVector3d, 24);
htonmemcpy(&pointAtTypeUnpacked, &(packed_data[POINTAT_TYPE]), MVT_U8, 1);
htolememcpy(source_id.mData, &(packed_data[SOURCE_AVATAR]), MVT_LLUUID, 16);
htolememcpy(target_id.mData, &(packed_data[TARGET_OBJECT]), MVT_LLUUID, 16);
htolememcpy(new_target.mdV, &(packed_data[TARGET_POS]), MVT_LLVector3d, 24);
htolememcpy(&pointAtTypeUnpacked, &(packed_data[POINTAT_TYPE]), MVT_U8, 1);
LLViewerObject *objp = gObjectList.findObject(source_id);
if (objp && objp->isAvatar())

View File

@ -87,15 +87,15 @@ void LLHUDEffectSpiral::packData(LLMessageSystem *mesgsys)
if (mSourceObject)
{
htonmemcpy(packed_data, mSourceObject->mID.mData, MVT_LLUUID, 16);
htolememcpy(packed_data, mSourceObject->mID.mData, MVT_LLUUID, 16);
}
if (mTargetObject)
{
htonmemcpy(packed_data + 16, mTargetObject->mID.mData, MVT_LLUUID, 16);
htolememcpy(packed_data + 16, mTargetObject->mID.mData, MVT_LLUUID, 16);
}
if (!mPositionGlobal.isExactlyZero())
{
htonmemcpy(packed_data + 32, mPositionGlobal.mdV, MVT_LLVector3d, 24);
htolememcpy(packed_data + 32, mPositionGlobal.mdV, MVT_LLVector3d, 24);
}
mesgsys->addBinaryDataFast(_PREHASH_TypeData, packed_data, 56);
}
@ -116,9 +116,9 @@ void LLHUDEffectSpiral::unpackData(LLMessageSystem *mesgsys, S32 blocknum)
mesgsys->getBinaryDataFast(_PREHASH_Effect, _PREHASH_TypeData,
packed_data, EFFECT_SIZE, blocknum, EFFECT_SIZE);
htonmemcpy(object_id.mData, packed_data, MVT_LLUUID, 16);
htonmemcpy(target_object_id.mData, packed_data + 16, MVT_LLUUID, 16);
htonmemcpy(mPositionGlobal.mdV, packed_data + 32, MVT_LLVector3d, 24);
htolememcpy(object_id.mData, packed_data, MVT_LLUUID, 16);
htolememcpy(target_object_id.mData, packed_data + 16, MVT_LLUUID, 16);
htolememcpy(mPositionGlobal.mdV, packed_data + 32, MVT_LLVector3d, 24);
LLViewerObject *objp = NULL;

View File

@ -1,6 +1,6 @@
/**
* @file llimagefiltersmanager.cpp
* @brief Load image filters list and retrieve their path. Mostly used for Flickr UI at the moment.
* @brief Load image filters list and retrieve their path.
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code

View File

@ -1,6 +1,6 @@
/**
* @file llimagefiltersmanager.h
* @brief Load image filters list and retrieve their path. Mostly used for Flickr UI at the moment.
* @brief Load image filters list and retrieve their path.
*
* $LicenseInfo:firstyear=2000&license=viewerlgpl$
* Second Life Viewer Source Code

View File

@ -715,7 +715,7 @@ void LLIMProcessing::processNewMessage(LLUUID from_id,
{
info = new LLOfferInfo();
info->mIM = IM_GROUP_NOTICE;
info->mIM = dialog;
info->mFromID = from_id;
info->mFromGroup = from_group;
info->mTransactionID = session_id;
@ -896,12 +896,18 @@ void LLIMProcessing::processNewMessage(LLUUID from_id,
if (is_muted)
{
// Prefetch the offered item so that it can be discarded by the appropriate observer. (EXT-4331)
LLInventoryFetchItemsObserver* fetch_item = new LLInventoryFetchItemsObserver(info->mObjectID);
fetch_item->startFetch();
delete fetch_item;
// Same as closing window
info->forceResponse(IOR_DECLINE);
if (IM_INVENTORY_OFFERED == dialog)
{
LLInventoryFetchItemsObserver* fetch_item = new LLInventoryFetchItemsObserver(info->mObjectID);
fetch_item->startFetch();
delete fetch_item;
// Same as closing window
info->forceResponse(IOR_DECLINE);
}
else
{
info->forceResponse(IOR_MUTE);
}
}
// old logic: busy mode must not affect interaction with objects (STORM-565)
// new logic: inventory offers from in-world objects should be auto-declined (CHUI-519)

View File

@ -4662,7 +4662,7 @@ bool move_task_inventory_callback(const LLSD& notification, const LLSD& response
{
LLInventoryObject::object_list_t inventory_objects;
object->getInventoryContents(inventory_objects);
int contents_count = inventory_objects.size()-1; //subtract one for containing folder
int contents_count = inventory_objects.size();
LLInventoryCopyAndWearObserver* inventoryObserver = new LLInventoryCopyAndWearObserver(cat_and_wear->mCatID, contents_count, cat_and_wear->mFolderResponded,
cat_and_wear->mReplace);

View File

@ -42,7 +42,7 @@
#include "llviewerfoldertype.h"
#include "llradiogroup.h"
#include "llstartup.h"
#include <boost/regex.hpp>
// linden library includes
#include "llclipboard.h"
#include "lltrans.h"
@ -116,7 +116,39 @@ bool LLInventoryFilter::check(const LLFolderViewModelItem* item)
break;
}
bool passed = (mFilterSubString.size() ? desc.find(mFilterSubString) != std::string::npos : true);
bool passed = true;
if (!mExactToken.empty() && (mSearchType == SEARCHTYPE_NAME))
{
passed = false;
typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
boost::char_separator<char> sep(" ");
tokenizer tokens(desc, sep);
for (auto token_iter : tokens)
{
if (token_iter == mExactToken)
{
passed = true;
break;
}
}
}
else if ((mFilterTokens.size() > 0) && (mSearchType == SEARCHTYPE_NAME))
{
for (auto token_iter : mFilterTokens)
{
if (desc.find(token_iter) == std::string::npos)
{
return false;
}
}
}
else
{
passed = (mFilterSubString.size() ? desc.find(mFilterSubString) != std::string::npos : true);
}
passed = passed && checkAgainstFilterType(listener);
passed = passed && checkAgainstPermissions(listener);
passed = passed && checkAgainstFilterLinks(listener);
@ -693,6 +725,38 @@ void LLInventoryFilter::setFilterSubString(const std::string& string)
if (mFilterSubString != filter_sub_string_new)
{
mFilterTokens.clear();
if (filter_sub_string_new.find_first_of("+") != std::string::npos)
{
typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
boost::char_separator<char> sep("+");
tokenizer tokens(filter_sub_string_new, sep);
for (auto token_iter : tokens)
{
mFilterTokens.push_back(token_iter);
}
}
std::string old_token = mExactToken;
mExactToken.clear();
bool exact_token_changed = false;
if (mFilterTokens.empty() && filter_sub_string_new.size() > 2)
{
boost::regex mPattern = boost::regex("\"\\s*([^<]*)?\\s*\"",
boost::regex::perl | boost::regex::icase);
boost::match_results<std::string::const_iterator> matches;
mExactToken = (boost::regex_match(filter_sub_string_new, matches, mPattern) && matches[1].matched)
? matches[1]
: LLStringUtil::null;
if ((old_token.empty() && !mExactToken.empty())
|| (!old_token.empty() && mExactToken.empty()))
{
exact_token_changed = true;
}
}
// hitting BACKSPACE, for example
const BOOL less_restrictive = mFilterSubString.size() >= filter_sub_string_new.size()
&& !mFilterSubString.substr(0, filter_sub_string_new.size()).compare(filter_sub_string_new);
@ -702,7 +766,11 @@ void LLInventoryFilter::setFilterSubString(const std::string& string)
&& !filter_sub_string_new.substr(0, mFilterSubString.size()).compare(mFilterSubString);
mFilterSubString = filter_sub_string_new;
if (less_restrictive)
if (exact_token_changed)
{
setModified(FILTER_RESTART);
}
else if (less_restrictive)
{
setModified(FILTER_LESS_RESTRICTIVE);
}

View File

@ -327,6 +327,9 @@ private:
std::string mEmptyLookupMessage;
ESearchType mSearchType;
std::vector<std::string> mFilterTokens;
std::string mExactToken;
};
#endif

View File

@ -262,6 +262,7 @@ std::set<std::string> LLTransactionNotificationListItem::getTypes()
std::set<std::string> types;
types.insert("PaymentReceived");
types.insert("PaymentSent");
types.insert("UploadPayment");
return types;
}

View File

@ -32,8 +32,6 @@
#include "llfloatersnapshot.h" // FIXME: create a snapshot model
#include "llfloaterreg.h"
#include "llfloaterflickr.h"
#include "llfloatertwitter.h"
/**
* Provides several ways to save a snapshot.
@ -58,8 +56,6 @@ private:
void onSaveToEmail();
void onSaveToInventory();
void onSaveToComputer();
void onSendToTwitter();
void onSendToFlickr();
LLFloaterSnapshotBase* mSnapshotFloater;
};
@ -72,8 +68,7 @@ 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.SendToTwitter", boost::bind(&LLPanelSnapshotOptions::onSendToTwitter, this));
mCommitCallbackRegistrar.add("Snapshot.SendToFlickr", boost::bind(&LLPanelSnapshotOptions::onSendToFlickr, this));
LLGlobalEconomy::getInstance()->addObserver(this);
}
@ -135,26 +130,3 @@ void LLPanelSnapshotOptions::onSaveToComputer()
openPanel("panel_snapshot_local");
}
void LLPanelSnapshotOptions::onSendToTwitter()
{
LLFloaterReg::hideInstance("snapshot");
LLFloaterTwitter* twitter_floater = dynamic_cast<LLFloaterTwitter*>(LLFloaterReg::getInstance("twitter"));
if (twitter_floater)
{
twitter_floater->showPhotoPanel();
}
LLFloaterReg::showInstance("twitter");
}
void LLPanelSnapshotOptions::onSendToFlickr()
{
LLFloaterReg::hideInstance("snapshot");
LLFloaterFlickr* flickr_floater = dynamic_cast<LLFloaterFlickr*>(LLFloaterReg::getInstance("flickr"));
if (flickr_floater)
{
flickr_floater->showPhotoPanel();
}
LLFloaterReg::showInstance("flickr");
}

View File

@ -153,6 +153,53 @@ struct LLDeRezInfo
// Imports
//
//-----------------------------------------------------------------------------
// ~LLSelectionCallbackData()
//-----------------------------------------------------------------------------
LLSelectionCallbackData::LLSelectionCallbackData()
{
LLSelectMgr *instance = LLSelectMgr::getInstance();
LLObjectSelectionHandle selection = instance->getSelection();
if (!selection->getNumNodes())
{
return;
}
mSelectedObjects = new LLObjectSelection();
for (LLObjectSelection::iterator iter = selection->begin();
iter != selection->end();)
{
LLObjectSelection::iterator curiter = iter++;
LLSelectNode *nodep = *curiter;
LLViewerObject* objectp = nodep->getObject();
if (!objectp)
{
mSelectedObjects->mSelectType = SELECT_TYPE_WORLD;
}
else
{
LLSelectNode* new_nodep = new LLSelectNode(*nodep);
mSelectedObjects->addNode(new_nodep);
if (objectp->isHUDAttachment())
{
mSelectedObjects->mSelectType = SELECT_TYPE_HUD;
}
else if (objectp->isAttachment())
{
mSelectedObjects->mSelectType = SELECT_TYPE_ATTACHMENT;
}
else
{
mSelectedObjects->mSelectType = SELECT_TYPE_WORLD;
}
}
}
}
//
// Functions
@ -4119,20 +4166,20 @@ void LLSelectMgr::packMultipleUpdate(LLSelectNode* node, void *user_data)
if (type & UPD_POSITION)
{
htonmemcpy(&data[offset], &(object->getPosition().mV), MVT_LLVector3, 12);
htolememcpy(&data[offset], &(object->getPosition().mV), MVT_LLVector3, 12);
offset += 12;
}
if (type & UPD_ROTATION)
{
LLQuaternion quat = object->getRotation();
LLVector3 vec = quat.packToVector3();
htonmemcpy(&data[offset], &(vec.mV), MVT_LLQuaternion, 12);
htolememcpy(&data[offset], &(vec.mV), MVT_LLQuaternion, 12);
offset += 12;
}
if (type & UPD_SCALE)
{
//LL_INFOS() << "Sending object scale " << object->getScale() << LL_ENDL;
htonmemcpy(&data[offset], &(object->getScale().mV), MVT_LLVector3, 12);
htolememcpy(&data[offset], &(object->getScale().mV), MVT_LLVector3, 12);
offset += 12;
}
gMessageSystem->addBinaryDataFast(_PREHASH_Data, data, offset);
@ -4475,9 +4522,19 @@ void LLSelectMgr::selectionSetObjectSaleInfo(const LLSaleInfo& sale_info)
void LLSelectMgr::sendAttach(U8 attachment_point, bool replace)
{
LLViewerObject* attach_object = mSelectedObjects->getFirstRootObject();
sendAttach(mSelectedObjects, attachment_point, replace);
}
if (!attach_object || !isAgentAvatarValid() || mSelectedObjects->mSelectType != SELECT_TYPE_WORLD)
void LLSelectMgr::sendAttach(LLObjectSelectionHandle selection_handle, U8 attachment_point, bool replace)
{
if (selection_handle.isNull())
{
return;
}
LLViewerObject* attach_object = selection_handle->getFirstRootObject();
if (!attach_object || !isAgentAvatarValid() || selection_handle->mSelectType != SELECT_TYPE_WORLD)
{
return;
}
@ -4495,6 +4552,7 @@ void LLSelectMgr::sendAttach(U8 attachment_point, bool replace)
}
sendListToRegions(
selection_handle,
"ObjectAttach",
packAgentIDAndSessionAndAttachment,
packObjectIDAndRotation,
@ -4506,6 +4564,7 @@ void LLSelectMgr::sendAttach(U8 attachment_point, bool replace)
// After "ObjectAttach" server will unsubscribe us from properties updates
// so either deselect objects or resend selection after attach packet reaches server
// In case of build_mode LLPanelObjectInventory::refresh() will deal with selection
// Still unsubscribe even in case selection_handle is not current selection
deselectAll();
}
}
@ -5047,7 +5106,17 @@ void LLSelectMgr::packPermissions(LLSelectNode* node, void *user_data)
void LLSelectMgr::sendListToRegions(const std::string& message_name,
void (*pack_header)(void *user_data),
void (*pack_body)(LLSelectNode* node, void *user_data),
void (*log_func)(LLSelectNode* node, void *user_data),
void (*log_func)(LLSelectNode* node, void *user_data),
void *user_data,
ESendType send_type)
{
sendListToRegions(mSelectedObjects, message_name, pack_header, pack_body, log_func, user_data, send_type);
}
void LLSelectMgr::sendListToRegions(LLObjectSelectionHandle selected_handle,
const std::string& message_name,
void (*pack_header)(void *user_data),
void (*pack_body)(LLSelectNode* node, void *user_data),
void (*log_func)(LLSelectNode* node, void *user_data),
void *user_data,
ESendType send_type)
{
@ -5073,7 +5142,7 @@ void LLSelectMgr::sendListToRegions(const std::string& message_name,
return true;
}
} func;
getSelection()->applyToNodes(&func);
selected_handle->applyToNodes(&func);
std::queue<LLSelectNode*> nodes_to_send;
@ -5116,25 +5185,25 @@ void LLSelectMgr::sendListToRegions(const std::string& message_name,
{
case SEND_ONLY_ROOTS:
if(message_name == "ObjectBuy")
getSelection()->applyToRootNodes(&pushroots);
selected_handle->applyToRootNodes(&pushroots);
else
getSelection()->applyToRootNodes(&pushall);
selected_handle->applyToRootNodes(&pushall);
break;
case SEND_INDIVIDUALS:
getSelection()->applyToNodes(&pushall);
selected_handle->applyToNodes(&pushall);
break;
case SEND_ROOTS_FIRST:
// first roots...
getSelection()->applyToNodes(&pushroots);
selected_handle->applyToNodes(&pushroots);
// then children...
getSelection()->applyToNodes(&pushnonroots);
selected_handle->applyToNodes(&pushnonroots);
break;
case SEND_CHILDREN_FIRST:
// first children...
getSelection()->applyToNodes(&pushnonroots);
selected_handle->applyToNodes(&pushnonroots);
// then roots...
getSelection()->applyToNodes(&pushroots);
selected_handle->applyToNodes(&pushroots);
break;
default:
@ -6686,8 +6755,7 @@ void LLSelectMgr::updateSelectionCenter()
if (mSelectedObjects->mSelectType != SELECT_TYPE_HUD && isAgentAvatarValid())
{
// reset hud ZOOM
gAgentCamera.mHUDTargetZoom = 1.f;
gAgentCamera.mHUDCurZoom = 1.f;
resetAgentHUDZoom();
}
mShowSelection = FALSE;
@ -7060,8 +7128,11 @@ BOOL LLSelectMgr::setForceSelection(BOOL force)
void LLSelectMgr::resetAgentHUDZoom()
{
gAgentCamera.mHUDTargetZoom = 1.f;
gAgentCamera.mHUDCurZoom = 1.f;
if (gAgentCamera.mHUDTargetZoom != 1)
{
gAgentCamera.mHUDTargetZoom = 1.f;
gAgentCamera.mHUDCurZoom = 1.f;
}
}
void LLSelectMgr::getAgentHUDZoom(F32 &target_zoom, F32 &current_zoom) const

View File

@ -239,6 +239,7 @@ class LLObjectSelection : public LLRefCount
{
friend class LLSelectMgr;
friend class LLSafeHandle<LLObjectSelection>;
friend class LLSelectionCallbackData;
protected:
~LLObjectSelection();
@ -396,6 +397,16 @@ extern template class LLSelectMgr* LLSingleton<class LLSelectMgr>::getInstance()
// For use with getFirstTest()
struct LLSelectGetFirstTest;
// temporary storage, Ex: to attach objects after autopilot
class LLSelectionCallbackData
{
public:
LLSelectionCallbackData();
LLObjectSelectionHandle getSelection() { return mSelectedObjects; }
private:
LLObjectSelectionHandle mSelectedObjects;
};
class LLSelectMgr : public LLEditMenuHandler, public LLSingleton<LLSelectMgr>
{
LLSINGLETON(LLSelectMgr);
@ -740,6 +751,7 @@ public:
// canceled
void sendBuy(const LLUUID& buyer_id, const LLUUID& category_id, const LLSaleInfo sale_info);
void sendAttach(U8 attachment_point, bool replace);
void sendAttach(LLObjectSelectionHandle selection_handle, U8 attachment_point, bool replace);
void sendDetach();
void sendDropAttachment();
void sendLink();
@ -787,6 +799,13 @@ private:
void (*log_func)(LLSelectNode* node, void *user_data),
void *user_data,
ESendType send_type);
void sendListToRegions( LLObjectSelectionHandle selected_handle,
const std::string& message_name,
void (*pack_header)(void *user_data),
void (*pack_body)(LLSelectNode* node, void *user_data),
void (*log_func)(LLSelectNode* node, void *user_data),
void *user_data,
ESendType send_type);
static void packAgentID( void *);

View File

@ -485,7 +485,7 @@ void LLSidepanelAppearance::fetchInventory()
attachment_iter != attachment->mAttachedObjects.end();
++attachment_iter)
{
LLViewerObject* attached_object = (*attachment_iter);
LLViewerObject* attached_object = attachment_iter->get();
if (!attached_object) continue;
const LLUUID& item_id = attached_object->getAttachmentItemID();
if (item_id.isNull()) continue;

View File

@ -49,6 +49,29 @@
#include "llviewerregion.h"
class PropertiesChangedCallback : public LLInventoryCallback
{
public:
PropertiesChangedCallback(LLHandle<LLPanel> sidepanel_handle, LLUUID &item_id, S32 id)
: mHandle(sidepanel_handle), mItemId(item_id), mId(id)
{}
void fire(const LLUUID &inv_item)
{
// inv_item can be null for some reason
LLSidepanelItemInfo* sidepanel = dynamic_cast<LLSidepanelItemInfo*>(mHandle.get());
if (sidepanel)
{
// sidepanel waits only for most recent update
sidepanel->onUpdateCallback(mItemId, mId);
}
}
private:
LLHandle<LLPanel> mHandle;
LLUUID mItemId;
S32 mId;
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Class LLItemPropertiesObserver
//
@ -68,7 +91,7 @@ public:
}
virtual void changed(U32 mask);
private:
LLSidepanelItemInfo* mFloater;
LLSidepanelItemInfo* mFloater; // Not a handle because LLSidepanelItemInfo is managing LLItemPropertiesObserver
};
void LLItemPropertiesObserver::changed(U32 mask)
@ -115,7 +138,7 @@ public:
S32 serial_num,
void* user_data);
private:
LLSidepanelItemInfo* mFloater;
LLSidepanelItemInfo* mFloater; // Not a handle because LLSidepanelItemInfo is managing LLObjectInventoryObserver
};
/*virtual*/
@ -138,6 +161,7 @@ LLSidepanelItemInfo::LLSidepanelItemInfo(const LLPanel::Params& p)
: LLSidepanelInventorySubpanel(p)
, mItemID(LLUUID::null)
, mObjectInventoryObserver(NULL)
, mUpdatePendingId(-1)
{
mPropertiesObserver = new LLItemPropertiesObserver(this);
}
@ -168,19 +192,19 @@ BOOL LLSidepanelItemInfo::postBuild()
// owner permissions
// Permissions debug text
// group permissions
getChild<LLUICtrl>("CheckShareWithGroup")->setCommitCallback(boost::bind(&LLSidepanelItemInfo::onCommitPermissions, this));
getChild<LLUICtrl>("CheckShareWithGroup")->setCommitCallback(boost::bind(&LLSidepanelItemInfo::onCommitPermissions, this, _1));
// everyone permissions
getChild<LLUICtrl>("CheckEveryoneCopy")->setCommitCallback(boost::bind(&LLSidepanelItemInfo::onCommitPermissions, this));
getChild<LLUICtrl>("CheckEveryoneCopy")->setCommitCallback(boost::bind(&LLSidepanelItemInfo::onCommitPermissions, this, _1));
// next owner permissions
getChild<LLUICtrl>("CheckNextOwnerModify")->setCommitCallback(boost::bind(&LLSidepanelItemInfo::onCommitPermissions, this));
getChild<LLUICtrl>("CheckNextOwnerCopy")->setCommitCallback(boost::bind(&LLSidepanelItemInfo::onCommitPermissions, this));
getChild<LLUICtrl>("CheckNextOwnerTransfer")->setCommitCallback(boost::bind(&LLSidepanelItemInfo::onCommitPermissions, this));
getChild<LLUICtrl>("CheckNextOwnerModify")->setCommitCallback(boost::bind(&LLSidepanelItemInfo::onCommitPermissions, this, _1));
getChild<LLUICtrl>("CheckNextOwnerCopy")->setCommitCallback(boost::bind(&LLSidepanelItemInfo::onCommitPermissions, this, _1));
getChild<LLUICtrl>("CheckNextOwnerTransfer")->setCommitCallback(boost::bind(&LLSidepanelItemInfo::onCommitPermissions, this, _1));
// Mark for sale or not, and sale info
getChild<LLUICtrl>("CheckPurchase")->setCommitCallback(boost::bind(&LLSidepanelItemInfo::onCommitSaleInfo, this));
getChild<LLUICtrl>("CheckPurchase")->setCommitCallback(boost::bind(&LLSidepanelItemInfo::onCommitSaleInfo, this, _1));
// Change sale type, and sale info
getChild<LLUICtrl>("ComboBoxSaleType")->setCommitCallback(boost::bind(&LLSidepanelItemInfo::onCommitSaleInfo, this));
getChild<LLUICtrl>("ComboBoxSaleType")->setCommitCallback(boost::bind(&LLSidepanelItemInfo::onCommitSaleInfo, this, _1));
// "Price" label for edit
getChild<LLUICtrl>("Edit Cost")->setCommitCallback(boost::bind(&LLSidepanelItemInfo::onCommitSaleInfo, this));
getChild<LLUICtrl>("Edit Cost")->setCommitCallback(boost::bind(&LLSidepanelItemInfo::onCommitSaleInfo, this, _1));
refresh();
return TRUE;
}
@ -192,11 +216,16 @@ void LLSidepanelItemInfo::setObjectID(const LLUUID& object_id)
// Start monitoring changes in the object inventory to update
// selected inventory item properties in Item Profile panel. See STORM-148.
startObjectInventoryObserver();
mUpdatePendingId = -1;
}
void LLSidepanelItemInfo::setItemID(const LLUUID& item_id)
{
mItemID = item_id;
if (mItemID != item_id)
{
mItemID = item_id;
mUpdatePendingId = -1;
}
}
const LLUUID& LLSidepanelItemInfo::getObjectID() const
@ -209,6 +238,15 @@ const LLUUID& LLSidepanelItemInfo::getItemID() const
return mItemID;
}
void LLSidepanelItemInfo::onUpdateCallback(const LLUUID& item_id, S32 received_update_id)
{
if (mItemID == item_id && mUpdatePendingId == received_update_id)
{
mUpdatePendingId = -1;
refresh();
}
}
void LLSidepanelItemInfo::reset()
{
LLSidepanelInventorySubpanel::reset();
@ -242,24 +280,16 @@ void LLSidepanelItemInfo::refresh()
"LabelItemName",
"LabelItemDesc",
"LabelCreatorName",
"LabelOwnerName",
"CheckOwnerModify",
"CheckOwnerCopy",
"CheckOwnerTransfer",
"CheckShareWithGroup",
"CheckEveryoneCopy",
"CheckNextOwnerModify",
"CheckNextOwnerCopy",
"CheckNextOwnerTransfer",
"CheckPurchase",
"Edit Cost"
"LabelOwnerName"
};
for(size_t t=0; t<LL_ARRAY_SIZE(no_item_names); ++t)
{
getChildView(no_item_names[t])->setEnabled(false);
}
setPropertiesFieldsEnabled(false);
const std::string hide_names[]={
"BaseMaskDebug",
"OwnerMaskDebug",
@ -297,6 +327,11 @@ void LLSidepanelItemInfo::refreshFromItem(LLViewerInventoryItem* item)
llassert(item);
if (!item) return;
if (mUpdatePendingId != -1)
{
return;
}
// do not enable the UI for incomplete items.
BOOL is_complete = item->isFinished();
const BOOL cannot_restrict_permissions = LLInventoryType::cannotRestrictPermissions(item->getInventoryType());
@ -726,6 +761,26 @@ void LLSidepanelItemInfo::stopObjectInventoryObserver()
mObjectInventoryObserver = NULL;
}
void LLSidepanelItemInfo::setPropertiesFieldsEnabled(bool enabled)
{
const std::string fields[] = {
"CheckOwnerModify",
"CheckOwnerCopy",
"CheckOwnerTransfer",
"CheckShareWithGroup",
"CheckEveryoneCopy",
"CheckNextOwnerModify",
"CheckNextOwnerCopy",
"CheckNextOwnerTransfer",
"CheckPurchase",
"Edit Cost"
};
for (size_t t = 0; t<LL_ARRAY_SIZE(fields); ++t)
{
getChildView(fields[t])->setEnabled(false);
}
}
void LLSidepanelItemInfo::onClickCreator()
{
LLViewerInventoryItem* item = findItem();
@ -793,10 +848,18 @@ void LLSidepanelItemInfo::onCommitDescription()
}
}
// static
void LLSidepanelItemInfo::onCommitPermissions()
void LLSidepanelItemInfo::onCommitPermissions(LLUICtrl* ctrl)
{
if (ctrl)
{
// will be enabled by response from server
ctrl->setEnabled(false);
}
updatePermissions();
}
void LLSidepanelItemInfo::updatePermissions()
{
//LL_INFOS() << "LLSidepanelItemInfo::onCommitPermissions()" << LL_ENDL;
LLViewerInventoryItem* item = findItem();
if(!item) return;
@ -884,19 +947,17 @@ void LLSidepanelItemInfo::onCommitPermissions()
}
// static
void LLSidepanelItemInfo::onCommitSaleInfo()
void LLSidepanelItemInfo::onCommitSaleInfo(LLUICtrl* ctrl)
{
if (ctrl)
{
// will be enabled by response from server
ctrl->setEnabled(false);
}
//LL_INFOS() << "LLSidepanelItemInfo::onCommitSaleInfo()" << LL_ENDL;
updateSaleInfo();
}
// static
void LLSidepanelItemInfo::onCommitSaleType()
{
//LL_INFOS() << "LLSidepanelItemInfo::onCommitSaleType()" << LL_ENDL;
updateSaleInfo();
}
void LLSidepanelItemInfo::updateSaleInfo()
{
LLViewerInventoryItem* item = findItem();
@ -977,7 +1038,12 @@ void LLSidepanelItemInfo::onCommitChanges(LLPointer<LLViewerInventoryItem> item)
if (mObjectID.isNull())
{
// This is in the agent's inventory.
item->updateServer(FALSE);
// Mark update as pending and wait only for most recent one in case user requested for couple
// Once update arrives or any of ids change drop pending id.
mUpdatePendingId++;
LLPointer<LLInventoryCallback> callback = new PropertiesChangedCallback(getHandle(), mItemID, mUpdatePendingId);
update_inventory_item(item.get(), callback);
//item->updateServer(FALSE);
gInventory.updateItem(item);
gInventory.notifyObservers();
}
@ -1002,6 +1068,7 @@ void LLSidepanelItemInfo::onCommitChanges(LLPointer<LLViewerInventoryItem> item)
// prevents flashing in content tab and some duplicated request.
object->dirtyInventory();
}
setPropertiesFieldsEnabled(false);
}
}
}
@ -1030,7 +1097,6 @@ void LLSidepanelItemInfo::save()
{
onCommitName();
onCommitDescription();
onCommitPermissions();
onCommitSaleInfo();
onCommitSaleType();
updatePermissions();
updateSaleInfo();
}

View File

@ -57,6 +57,9 @@ public:
const LLUUID& getObjectID() const;
const LLUUID& getItemID() const;
// if received update and item id (from callback) matches internal ones, update UI
void onUpdateCallback(const LLUUID& item_id, S32 received_update_id);
protected:
/*virtual*/ void refresh();
/*virtual*/ void save();
@ -71,12 +74,16 @@ private:
void startObjectInventoryObserver();
void stopObjectInventoryObserver();
void setPropertiesFieldsEnabled(bool enabled);
LLUUID mItemID; // inventory UUID for the inventory item.
LLUUID mObjectID; // in-world task UUID, or null if in agent inventory.
LLItemPropertiesObserver* mPropertiesObserver; // for syncing changes to item
LLObjectInventoryObserver* mObjectInventoryObserver; // for syncing changes to items inside an object
// We can send multiple properties updates simultaneously, make sure only last response counts and there won't be a race condition.
S32 mUpdatePendingId;
//
// UI Elements
//
@ -85,9 +92,9 @@ protected:
void onClickOwner();
void onCommitName();
void onCommitDescription();
void onCommitPermissions();
void onCommitSaleInfo();
void onCommitSaleType();
void onCommitPermissions(LLUICtrl* ctrl);
void updatePermissions();
void onCommitSaleInfo(LLUICtrl* ctrl);
void updateSaleInfo();
void onCommitChanges(LLPointer<LLViewerInventoryItem> item);
};

View File

@ -174,9 +174,6 @@ BOOL LLSidepanelTaskInfo::postBuild()
void LLSidepanelTaskInfo::disableAll()
{
mDAPermModify->setEnabled(FALSE);
mDAPermModify->setValue(LLStringUtil::null);
mDACreatorName->setValue(LLStringUtil::null);
mDACreatorName->setEnabled(FALSE);
@ -184,18 +181,42 @@ void LLSidepanelTaskInfo::disableAll()
mDAOwnerName->setValue(LLStringUtil::null);
mDAOwnerName->setEnabled(FALSE);
mDAButtonSetGroup->setEnabled(FALSE);
mDAObjectName->setValue(LLStringUtil::null);
mDAObjectName->setEnabled(FALSE);
mDAName->setEnabled(FALSE);
mDADescription->setEnabled(FALSE);
mDAObjectDescription->setValue(LLStringUtil::null);
mDAObjectDescription->setEnabled(FALSE);
mDAPathfindingAttributes->setEnabled(FALSE);
mDAPathfindingAttributes->setValue(LLStringUtil::null);
mDAButtonSetGroup->setEnabled(FALSE);
mDAButtonDeed->setEnabled(FALSE);
mDAPermModify->setEnabled(FALSE);
mDAPermModify->setValue(LLStringUtil::null);
mDAEditCost->setValue(LLStringUtil::null);
mDAComboSaleType->setValue(LLSaleInfo::FS_COPY);
disablePermissions();
mDAB->setVisible(FALSE);
mDAO->setVisible(FALSE);
mDAG->setVisible(FALSE);
mDAE->setVisible(FALSE);
mDAN->setVisible(FALSE);
mDAF->setVisible(FALSE);
mOpenBtn->setEnabled(FALSE);
mPayBtn->setEnabled(FALSE);
mBuyBtn->setEnabled(FALSE);
}
void LLSidepanelTaskInfo::disablePermissions()
{
mDACheckboxShareWithGroup->setValue(FALSE);
mDACheckboxShareWithGroup->setEnabled(FALSE);
mDAButtonDeed->setEnabled(FALSE);
mDACheckboxAllowEveryoneMove->setValue(FALSE);
mDACheckboxAllowEveryoneMove->setEnabled(FALSE);
@ -217,33 +238,17 @@ void LLSidepanelTaskInfo::disableAll()
//checkbox include in search
mDASearchCheck->setValue(FALSE);
mDASearchCheck->setEnabled(FALSE);
mDAComboSaleType->setValue(LLSaleInfo::FS_COPY);
mDAComboSaleType->setEnabled(FALSE);
mDAEditCost->setValue(LLStringUtil::null);
mDAEditCost->setEnabled(FALSE);
mDALabelClickAction->setEnabled(FALSE);
if (mDAComboClickAction)
{
mDAComboClickAction->setEnabled(FALSE);
mDAComboClickAction->clear();
}
mDAPathfindingAttributes->setEnabled(FALSE);
mDAPathfindingAttributes->setValue(LLStringUtil::null);
mDAB->setVisible(FALSE);
mDAO->setVisible(FALSE);
mDAG->setVisible(FALSE);
mDAE->setVisible(FALSE);
mDAN->setVisible(FALSE);
mDAF->setVisible(FALSE);
mOpenBtn->setEnabled(FALSE);
mPayBtn->setEnabled(FALSE);
mBuyBtn->setEnabled(FALSE);
}
void LLSidepanelTaskInfo::refresh()
@ -972,6 +977,12 @@ void LLSidepanelTaskInfo::onCommitPerm(LLUICtrl *ctrl, void *data, U8 field, U32
BOOL new_state = check->get();
LLSelectMgr::getInstance()->selectionSetObjectPermissions(field, new_state, perm);
LLSidepanelTaskInfo* self = (LLSidepanelTaskInfo*)data;
if (self)
{
self->disablePermissions();
}
}
// static

View File

@ -95,6 +95,7 @@ protected:
static void doClickAction(U8 click_action);
void disableAll();
void disablePermissions();
private:
LLNameBox* mLabelGroupName; // group name

View File

@ -34,8 +34,6 @@
#include "lleconomy.h"
#include "llfloaterperms.h"
#include "llfloaterreg.h"
#include "llfloaterflickr.h"
#include "llfloatertwitter.h"
#include "llimagefilter.h"
#include "llimagefiltersmanager.h"
#include "llimagebmp.h"

View File

@ -1632,7 +1632,14 @@ bool idle_startup()
if (!gAgentMovementCompleted && timeout.getElapsedTimeF32() > STATE_AGENT_WAIT_TIMEOUT)
{
LL_WARNS("AppInit") << "Backing up to login screen!" << LL_ENDL;
LLNotificationsUtil::add("LoginPacketNeverReceived", LLSD(), LLSD(), login_alert_status);
if (gRememberPassword)
{
LLNotificationsUtil::add("LoginPacketNeverReceived", LLSD(), LLSD(), login_alert_status);
}
else
{
LLNotificationsUtil::add("LoginPacketNeverReceivedNoTP", LLSD(), LLSD(), login_alert_status);
}
reset_login();
}
return FALSE;
@ -2367,7 +2374,14 @@ void use_circuit_callback(void**, S32 result)
{
// Make sure user knows something bad happened. JC
LL_WARNS("AppInit") << "Backing up to login screen!" << LL_ENDL;
LLNotificationsUtil::add("LoginPacketNeverReceived", LLSD(), LLSD(), login_alert_status);
if (gRememberPassword)
{
LLNotificationsUtil::add("LoginPacketNeverReceived", LLSD(), LLSD(), login_alert_status);
}
else
{
LLNotificationsUtil::add("LoginPacketNeverReceivedNoTP", LLSD(), LLSD(), login_alert_status);
}
reset_login();
}
else

View File

@ -243,16 +243,24 @@ BOOL LLStatusBar::postBuild()
mPanelNearByMedia->setFollows(FOLLOWS_TOP|FOLLOWS_RIGHT);
mPanelNearByMedia->setVisible(FALSE);
updateBalancePanelPosition();
// Hook up and init for filtering
mFilterEdit = getChild<LLSearchEditor>( "search_menu_edit" );
mSearchPanel = getChild<LLPanel>( "menu_search_panel" );
mSearchPanel->setVisible(gSavedSettings.getBOOL("MenuSearch"));
BOOL search_panel_visible = gSavedSettings.getBOOL("MenuSearch");
mSearchPanel->setVisible(search_panel_visible);
mFilterEdit->setKeystrokeCallback(boost::bind(&LLStatusBar::onUpdateFilterTerm, this));
mFilterEdit->setCommitCallback(boost::bind(&LLStatusBar::onUpdateFilterTerm, this));
collectSearchableItems();
gSavedSettings.getControl("MenuSearch")->getCommitSignal()->connect(boost::bind(&LLStatusBar::updateMenuSearchVisibility, this, _2));
if (search_panel_visible)
{
updateMenuSearchPosition();
}
return TRUE;
}
@ -363,17 +371,7 @@ void LLStatusBar::setBalance(S32 balance)
std::string label_str = getString("buycurrencylabel", string_args);
mBoxBalance->setValue(label_str);
// Resize the L$ balance background to be wide enough for your balance plus the buy button
{
const S32 HPAD = 24;
LLRect balance_rect = mBoxBalance->getTextBoundingRect();
LLRect buy_rect = getChildView("buyL")->getRect();
LLRect shop_rect = getChildView("goShop")->getRect();
LLView* balance_bg_view = getChildView("balance_bg");
LLRect balance_bg_rect = balance_bg_view->getRect();
balance_bg_rect.mLeft = balance_bg_rect.mRight - (buy_rect.getWidth() + shop_rect.getWidth() + balance_rect.getWidth() + HPAD);
balance_bg_view->setShape(balance_bg_rect);
}
updateBalancePanelPosition();
// If the search panel is shown, move this according to the new balance width. Parcel text will reshape itself in setParcelInfoText
if (mSearchPanel && mSearchPanel->getVisible())
@ -661,6 +659,19 @@ void LLStatusBar::updateMenuSearchPosition()
mSearchPanel->setShape( searchRect );
}
void LLStatusBar::updateBalancePanelPosition()
{
// Resize the L$ balance background to be wide enough for your balance plus the buy button
const S32 HPAD = 24;
LLRect balance_rect = mBoxBalance->getTextBoundingRect();
LLRect buy_rect = getChildView("buyL")->getRect();
LLRect shop_rect = getChildView("goShop")->getRect();
LLView* balance_bg_view = getChildView("balance_bg");
LLRect balance_bg_rect = balance_bg_view->getRect();
balance_bg_rect.mLeft = balance_bg_rect.mRight - (buy_rect.getWidth() + shop_rect.getWidth() + balance_rect.getWidth() + HPAD);
balance_bg_view->setShape(balance_bg_rect);
}
// Implements secondlife:///app/balance/request to request a L$ balance
// update via UDP message system. JC

View File

@ -114,7 +114,8 @@ private:
std::unique_ptr< ll::statusbar::SearchData > mSearchData;
void collectSearchableItems();
void updateMenuSearchVisibility( const LLSD& data );
void updateMenuSearchPosition();
void updateMenuSearchPosition(); // depends onto balance position
void updateBalancePanelPosition();
private:
LLTextBox *mTextTime;

View File

@ -53,6 +53,7 @@ const F32 TEXTURE_CACHE_PURGE_AMOUNT = .20f; // % amount to reduce the cache by
const F32 TEXTURE_CACHE_LRU_SIZE = .10f; // % amount for LRU list (low overhead to regenerate)
const S32 TEXTURE_FAST_CACHE_ENTRY_OVERHEAD = sizeof(S32) * 4; //w, h, c, level
const S32 TEXTURE_FAST_CACHE_ENTRY_SIZE = 16 * 16 * 4 + TEXTURE_FAST_CACHE_ENTRY_OVERHEAD;
const F32 TEXTURE_LAZY_PURGE_TIME_LIMIT = .004f; // 4ms. Would be better to autoadjust, but there is a major cache rework in progress.
class LLTextureCacheWorker : public LLWorkerClass
{
@ -837,6 +838,7 @@ LLTextureCache::LLTextureCache(bool threaded)
mFastCachePoolp(NULL),
mFastCachePadBuffer(NULL)
{
mHeaderAPRFilePoolp = new LLVolatileAPRPool(); // is_local = true, because this pool is for headers, headers are under own mutex
}
LLTextureCache::~LLTextureCache()
@ -845,6 +847,7 @@ LLTextureCache::~LLTextureCache()
writeUpdatedEntries() ;
delete mFastCachep;
delete mFastCachePoolp;
delete mHeaderAPRFilePoolp;
ll_aligned_free_16(mFastCachePadBuffer);
}
@ -1013,10 +1016,11 @@ void LLTextureCache::purgeCache(ELLPath location, bool remove_dir)
if(LLFile::isdir(mTexturesDirName))
{
std::string file_name = gDirUtilp->getExpandedFilename(location, entries_filename);
LLAPRFile::remove(file_name, getLocalAPRFilePool());
// mHeaderAPRFilePoolp because we are under header mutex, and can be in main thread
LLAPRFile::remove(file_name, mHeaderAPRFilePoolp);
file_name = gDirUtilp->getExpandedFilename(location, cache_filename);
LLAPRFile::remove(file_name, getLocalAPRFilePool());
LLAPRFile::remove(file_name, mHeaderAPRFilePoolp);
purgeAllTextures(true);
}
@ -1093,7 +1097,7 @@ LLAPRFile* LLTextureCache::openHeaderEntriesFile(bool readonly, S32 offset)
{
llassert_always(mHeaderAPRFile == NULL);
apr_int32_t flags = readonly ? APR_READ|APR_BINARY : APR_READ|APR_WRITE|APR_BINARY;
mHeaderAPRFile = new LLAPRFile(mHeaderEntriesFileName, flags, getLocalAPRFilePool());
mHeaderAPRFile = new LLAPRFile(mHeaderEntriesFileName, flags, mHeaderAPRFilePoolp);
if(offset > 0)
{
mHeaderAPRFile->seek(APR_SET, offset);
@ -1116,10 +1120,10 @@ void LLTextureCache::readEntriesHeader()
{
// mHeaderEntriesInfo initializes to default values so safe not to read it
llassert_always(mHeaderAPRFile == NULL);
if (LLAPRFile::isExist(mHeaderEntriesFileName, getLocalAPRFilePool()))
if (LLAPRFile::isExist(mHeaderEntriesFileName, mHeaderAPRFilePoolp))
{
LLAPRFile::readEx(mHeaderEntriesFileName, (U8*)&mHeaderEntriesInfo, 0, sizeof(EntriesInfo),
getLocalAPRFilePool());
mHeaderAPRFilePoolp);
}
else //create an empty entries header.
{
@ -1151,7 +1155,7 @@ void LLTextureCache::writeEntriesHeader()
if (!mReadOnly)
{
LLAPRFile::writeEx(mHeaderEntriesFileName, (U8*)&mHeaderEntriesInfo, 0, sizeof(EntriesInfo),
getLocalAPRFilePool());
mHeaderAPRFilePoolp);
}
}
@ -1669,6 +1673,91 @@ void LLTextureCache::purgeAllTextures(bool purge_directories)
LL_INFOS() << "The entire texture cache is cleared." << LL_ENDL ;
}
void LLTextureCache::purgeTexturesLazy(F32 time_limit_sec)
{
if (mReadOnly)
{
return;
}
if (!mThreaded)
{
LLAppViewer::instance()->pauseMainloopTimeout();
}
// time_limit doesn't account for lock time
LLMutexLock lock(&mHeaderMutex);
if (mPurgeEntryList.empty())
{
// Read the entries list and form list of textures to purge
std::vector<Entry> entries;
U32 num_entries = openAndReadEntries(entries);
if (!num_entries)
{
return; // nothing to purge
}
// Use mTexturesSizeMap to collect UUIDs of textures with bodies
typedef std::set<std::pair<U32, S32> > time_idx_set_t;
std::set<std::pair<U32, S32> > time_idx_set;
for (size_map_t::iterator iter1 = mTexturesSizeMap.begin();
iter1 != mTexturesSizeMap.end(); ++iter1)
{
if (iter1->second > 0)
{
id_map_t::iterator iter2 = mHeaderIDMap.find(iter1->first);
if (iter2 != mHeaderIDMap.end())
{
S32 idx = iter2->second;
time_idx_set.insert(std::make_pair(entries[idx].mTime, idx));
}
else
{
LL_ERRS("TextureCache") << "mTexturesSizeMap / mHeaderIDMap corrupted." << LL_ENDL;
}
}
}
S64 cache_size = mTexturesSizeTotal;
S64 purged_cache_size = (sCacheMaxTexturesSize * (S64)((1.f - TEXTURE_CACHE_PURGE_AMOUNT) * 100)) / 100;
for (time_idx_set_t::iterator iter = time_idx_set.begin();
iter != time_idx_set.end(); ++iter)
{
S32 idx = iter->second;
if (cache_size >= purged_cache_size)
{
cache_size -= entries[idx].mBodySize;
mPurgeEntryList.push_back(std::pair<S32, Entry>(idx, entries[idx]));
}
else
{
break;
}
}
LL_DEBUGS("TextureCache") << "Formed Purge list of " << mPurgeEntryList.size() << " entries" << LL_ENDL;
}
else
{
// Remove collected entried
LLTimer timer;
while (!mPurgeEntryList.empty() && timer.getElapsedTimeF32() < time_limit_sec)
{
S32 idx = mPurgeEntryList.back().first;
Entry entry = mPurgeEntryList.back().second;
mPurgeEntryList.pop_back();
// make sure record is still valid
id_map_t::iterator iter_header = mHeaderIDMap.find(entry.mID);
if (iter_header != mHeaderIDMap.end() && iter_header->second == idx)
{
std::string tex_filename = getTextureFileName(entry.mID);
removeEntry(idx, entry, tex_filename);
writeEntryToHeaderImmediately(idx, entry);
}
}
}
}
void LLTextureCache::purgeTextures(bool validate)
{
if (mReadOnly)
@ -1746,7 +1835,8 @@ void LLTextureCache::purgeTextures(bool validate)
if (uuididx == validate_idx)
{
LL_DEBUGS("TextureCache") << "Validating: " << filename << "Size: " << entries[idx].mBodySize << LL_ENDL;
S32 bodysize = LLAPRFile::size(filename, getLocalAPRFilePool());
// mHeaderAPRFilePoolp because this is under header mutex in main thread
S32 bodysize = LLAPRFile::size(filename, mHeaderAPRFilePoolp);
if (bodysize != entries[idx].mBodySize)
{
LL_WARNS("TextureCache") << "TEXTURE CACHE BODY HAS BAD SIZE: " << bodysize << " != " << entries[idx].mBodySize
@ -1928,11 +2018,10 @@ LLTextureCache::handle_t LLTextureCache::writeToCache(const LLUUID& id, U32 prio
}
if (mDoPurge)
{
// NOTE: This may cause an occasional hiccup,
// but it really needs to be done on the control thread
// (i.e. here)
purgeTextures(false);
mDoPurge = FALSE;
// NOTE: Needs to be done on the control thread
// (i.e. here)
purgeTexturesLazy(TEXTURE_LAZY_PURGE_TIME_LIMIT);
mDoPurge = !mPurgeEntryList.empty();
}
LLMutexLock lock(&mWorkersMutex);
LLTextureCacheWorker* worker = new LLTextureCacheRemoteWorker(this, priority, id,
@ -2146,7 +2235,7 @@ void LLTextureCache::openFastCache(bool first_time)
{
mFastCachePadBuffer = (U8*)ll_aligned_malloc_16(TEXTURE_FAST_CACHE_ENTRY_SIZE);
}
mFastCachePoolp = new LLVolatileAPRPool();
mFastCachePoolp = new LLVolatileAPRPool(); // is_local= true by default, so not thread safe by default
if (LLAPRFile::isExist(mFastCacheFileName, mFastCachePoolp))
{
mFastCachep = new LLAPRFile(mFastCacheFileName, APR_READ|APR_WRITE|APR_BINARY, mFastCachePoolp) ;
@ -2230,7 +2319,9 @@ void LLTextureCache::removeCachedTexture(const LLUUID& id)
mTexturesSizeMap.erase(id);
}
mHeaderIDMap.erase(id);
LLAPRFile::remove(getTextureFileName(id), getLocalAPRFilePool());
// We are inside header's mutex so mHeaderAPRFilePoolp is safe to use,
// but getLocalAPRFilePool() is not safe, it might be in use by worker
LLAPRFile::remove(getTextureFileName(id), mHeaderAPRFilePoolp);
}
//called after mHeaderMutex is locked.
@ -2242,7 +2333,10 @@ void LLTextureCache::removeEntry(S32 idx, Entry& entry, std::string& filename)
{
if (entry.mBodySize == 0) // Always attempt to remove when mBodySize > 0.
{
if (LLAPRFile::isExist(filename, getLocalAPRFilePool())) // Sanity check. Shouldn't exist when body size is 0.
// Sanity check. Shouldn't exist when body size is 0.
// We are inside header's mutex so mHeaderAPRFilePoolp is safe to use,
// but getLocalAPRFilePool() is not safe, it might be in use by worker
if (LLAPRFile::isExist(filename, mHeaderAPRFilePoolp))
{
LL_WARNS("TextureCache") << "Entry has body size of zero but file " << filename << " exists. Deleting this file, too." << LL_ENDL;
}
@ -2262,7 +2356,7 @@ void LLTextureCache::removeEntry(S32 idx, Entry& entry, std::string& filename)
if (file_maybe_exists)
{
LLAPRFile::remove(filename, getLocalAPRFilePool());
LLAPRFile::remove(filename, mHeaderAPRFilePoolp);
}
}

View File

@ -139,7 +139,7 @@ public:
U32 getEntries() { return mHeaderEntriesInfo.mEntries; }
U32 getMaxEntries() { return sCacheMaxEntries; };
BOOL isInCache(const LLUUID& id) ;
BOOL isInLocal(const LLUUID& id) ;
BOOL isInLocal(const LLUUID& id) ; //not thread safe at the moment
protected:
// Accessed by LLTextureCacheWorker
@ -155,6 +155,7 @@ private:
void readHeaderCache();
void clearCorruptedCache();
void purgeAllTextures(bool purge_directories);
void purgeTexturesLazy(F32 time_limit_sec);
void purgeTextures(bool validate);
LLAPRFile* openHeaderEntriesFile(bool readonly, S32 offset);
void closeHeaderEntriesFile();
@ -189,6 +190,11 @@ private:
LLMutex mFastCacheMutex;
LLAPRFile* mHeaderAPRFile;
LLVolatileAPRPool* mFastCachePoolp;
// mLocalAPRFilePoolp is not thread safe and is meant only for workers
// howhever mHeaderEntriesFileName is accessed not from workers' threads
// so it needs own pool (not thread safe by itself, relies onto header's mutex)
LLVolatileAPRPool* mHeaderAPRFilePoolp;
typedef std::map<handle_t, LLTextureCacheWorker*> handle_map_t;
handle_map_t mReaders;
@ -225,6 +231,8 @@ private:
typedef std::map<S32, Entry> idx_entry_map_t;
idx_entry_map_t mUpdatedEntryMap;
typedef std::vector<std::pair<S32, Entry> > idx_entry_vector_t;
idx_entry_vector_t mPurgeEntryList;
// Statics
static F32 sHeaderCacheVersion;

View File

@ -721,9 +721,14 @@ void LLToolGrabBase::handleHoverActive(S32 x, S32 y, MASK mask)
!objectp->isHUDAttachment() &&
objectp->getRoot() == gAgentAvatarp->getRoot())
{
// force focus to point in space where we were looking previously
gAgentCamera.setFocusGlobal(gAgentCamera.calcFocusPositionTargetGlobal(), LLUUID::null);
gAgentCamera.setFocusOnAvatar(FALSE, ANIMATE);
// we are essentially editing object position
if (!gSavedSettings.getBOOL("EditCameraMovement"))
{
// force focus to point in space where we were looking previously
// Example of use: follow cam scripts shouldn't affect you when movng objects arouns
gAgentCamera.setFocusGlobal(gAgentCamera.calcFocusPositionTargetGlobal(), LLUUID::null);
gAgentCamera.setFocusOnAvatar(FALSE, ANIMATE);
}
}
else
{

View File

@ -874,37 +874,9 @@ BOOL LLToolPie::handleDoubleClick(S32 x, S32 y, MASK mask)
static bool needs_tooltip(LLSelectNode* nodep)
{
if (!nodep)
if (!nodep || !nodep->mValid)
return false;
LLViewerObject* object = nodep->getObject();
LLViewerObject *parent = (LLViewerObject *)object->getParent();
if (object->flagHandleTouch()
|| (parent && parent->flagHandleTouch())
|| object->flagTakesMoney()
|| (parent && parent->flagTakesMoney())
|| object->flagAllowInventoryAdd()
)
{
return true;
}
U8 click_action = final_click_action(object);
if (click_action != 0)
{
return true;
}
if (nodep->mValid)
{
bool anyone_copy = anyone_copy_selection(nodep);
bool for_sale = for_sale_selection(nodep);
if (anyone_copy || for_sale)
{
return true;
}
}
return false;
return true;
}

View File

@ -1,576 +0,0 @@
/**
* @file lltwitterconnect.h
* @author Merov, Cho
* @brief Connection to Twitter 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 "lltwitterconnect.h"
#include "llflickrconnect.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 "llfloaterwebcontent.h"
#include "llfloaterreg.h"
#include "llcorehttputil.h"
boost::scoped_ptr<LLEventPump> LLTwitterConnect::sStateWatcher(new LLEventStream("TwitterConnectState"));
boost::scoped_ptr<LLEventPump> LLTwitterConnect::sInfoWatcher(new LLEventStream("TwitterConnectInfo"));
boost::scoped_ptr<LLEventPump> LLTwitterConnect::sContentWatcher(new LLEventStream("TwitterConnectContent"));
// Local functions
void log_twitter_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("TwitterConnect") << request << " request failed with a " << status << " " << reason << ". Reason: " << code << " (" << description << ")" << LL_ENDL;
}
}
void toast_user_for_twitter_success()
{
LLSD args;
args["MESSAGE"] = LLTrans::getString("twitter_post_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)
{
LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("TwitterConnect", httpPolicy));
LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions);
httpOpts->setWantHeaders(true);
httpOpts->setFollowRedirects(false);
LLSD body;
if (!requestToken.empty())
body["request_token"] = requestToken;
if (!oauthVerifier.empty())
body["oauth_verifier"] = oauthVerifier;
LLSD result = httpAdapter->putAndSuspend(httpRequest, getTwitterConnectURL("/connection"), body, httpOpts);
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("FlickrConnect") << "Missing Location header " << LL_ENDL;
}
else
{
openTwitterWeb(location);
}
}
else
{
LL_WARNS("TwitterConnect") << "Connection failed " << status.toString() << LL_ENDL;
setConnectionState(LLTwitterConnect::TWITTER_CONNECTION_FAILED);
log_twitter_connect_error("Connect", status.getStatus(), status.toString(),
result.get("error_code"), result.get("error_description"));
}
}
else
{
LL_DEBUGS("TwitterConnect") << "Connect successful. " << LL_ENDL;
setConnectionState(LLTwitterConnect::TWITTER_CONNECTED);
}
}
///////////////////////////////////////////////////////////////////////////////
//
bool LLTwitterConnect::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("TwitterConnect") << "Missing Location header " << LL_ENDL;
}
else
{
openTwitterWeb(location);
}
}
if (status == LLCore::HttpStatus(HTTP_NOT_FOUND))
{
LL_DEBUGS("TwitterConnect") << "Not connected. " << LL_ENDL;
connectToTwitter();
}
else
{
LL_WARNS("TwitterConnect") << "HTTP Status error " << status.toString() << LL_ENDL;
setConnectionState(LLTwitterConnect::TWITTER_POST_FAILED);
log_twitter_connect_error("Share", status.getStatus(), status.toString(),
result.get("error_code"), result.get("error_description"));
}
return false;
}
void LLTwitterConnect::twitterShareCoro(std::string route, LLSD share)
{
LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("TwitterConnect", 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, getTwitterConnectURL(route, true), share, httpOpts);
if (testShareStatus(result))
{
toast_user_for_twitter_success();
LL_DEBUGS("TwitterConnect") << "Post successful. " << LL_ENDL;
setConnectionState(LLTwitterConnect::TWITTER_POSTED);
}
}
void LLTwitterConnect::twitterShareImageCoro(LLPointer<LLImageFormatted> image, std::string status)
{
LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("FlickrConnect", httpPolicy));
LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
LLCore::HttpHeaders::ptr_t httpHeaders(new LLCore::HttpHeaders);
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()
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=\"status\"\r\n\r\n"
<< status << "\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";
LLSD result = httpAdapter->postAndSuspend(httpRequest, getTwitterConnectURL("/share/photo", true), raw, httpOpts, httpHeaders);
if (testShareStatus(result))
{
toast_user_for_twitter_success();
LL_DEBUGS("TwitterConnect") << "Post successful. " << LL_ENDL;
setConnectionState(LLTwitterConnect::TWITTER_POSTED);
}
}
///////////////////////////////////////////////////////////////////////////////
//
void LLTwitterConnect::twitterDisconnectCoro()
{
LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("TwitterConnect", 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, getTwitterConnectURL("/connection"), httpOpts);
LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
if (!status && (status != LLCore::HttpStatus(HTTP_NOT_FOUND)))
{
LL_WARNS("TwitterConnect") << "Disconnect failed!" << LL_ENDL;
setConnectionState(LLTwitterConnect::TWITTER_DISCONNECT_FAILED);
log_twitter_connect_error("Disconnect", status.getStatus(), status.toString(),
result.get("error_code"), result.get("error_description"));
}
else
{
LL_DEBUGS("TwitterConnect") << "Disconnect successful. " << LL_ENDL;
clearInfo();
setConnectionState(LLTwitterConnect::TWITTER_NOT_CONNECTED);
}
}
///////////////////////////////////////////////////////////////////////////////
//
void LLTwitterConnect::twitterConnectedCoro(bool autoConnect)
{
LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("TwitterConnect", httpPolicy));
LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions);
httpOpts->setFollowRedirects(false);
setConnectionState(LLTwitterConnect::TWITTER_CONNECTION_IN_PROGRESS);
LLSD result = httpAdapter->getAndSuspend(httpRequest, getTwitterConnectURL("/connection", true), httpOpts);
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("TwitterConnect") << "Not connected. " << LL_ENDL;
if (autoConnect)
{
connectToTwitter();
}
else
{
setConnectionState(LLTwitterConnect::TWITTER_NOT_CONNECTED);
}
}
else
{
LL_WARNS("TwitterConnect") << "Failed to test connection:" << status.toTerseString() << LL_ENDL;
setConnectionState(LLTwitterConnect::TWITTER_CONNECTION_FAILED);
log_twitter_connect_error("Connected", status.getStatus(), status.toString(),
result.get("error_code"), result.get("error_description"));
}
}
else
{
LL_DEBUGS("TwitterConnect") << "Connect successful. " << LL_ENDL;
setConnectionState(LLTwitterConnect::TWITTER_CONNECTED);
}
}
///////////////////////////////////////////////////////////////////////////////
//
void LLTwitterConnect::twitterInfoCoro()
{
LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("TwitterConnect", 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, getTwitterConnectURL("/info", true), httpOpts);
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("TwitterConnect") << "Missing Location header " << LL_ENDL;
}
else
{
openTwitterWeb(location);
}
}
else if (!status)
{
LL_WARNS("TwitterConnect") << "Twitter Info failed: " << status.toString() << LL_ENDL;
log_twitter_connect_error("Info", status.getStatus(), status.toString(),
result.get("error_code"), result.get("error_description"));
}
else
{
LL_INFOS("TwitterConnect") << "Twitter: Info received" << LL_ENDL;
result.erase(LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS);
storeInfo(result);
}
}
///////////////////////////////////////////////////////////////////////////////
//
LLTwitterConnect::LLTwitterConnect()
: mConnectionState(TWITTER_NOT_CONNECTED),
mConnected(false),
mInfo(),
mRefreshInfo(false),
mReadFromMaster(false)
{
}
void LLTwitterConnect::openTwitterWeb(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("twitter_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 "twitter_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.
//twitter_web floater contains the "webbrowser" panel. JIRA: ACME-744
gFocusMgr.setKeyboardFocus( floater );
//LLUrlAction::openURLExternal(url);
}
std::string LLTwitterConnect::getTwitterConnectURL(const std::string& route, bool include_read_from_master)
{
std::string url("");
LLViewerRegion *regionp = gAgent.getRegion();
if (regionp)
{
//url = "http://pdp15.lindenlab.com/twitter/agent/" + gAgentID.asString(); // TEMPORARY FOR TESTING - CHO
url = regionp->getCapability("TwitterConnect");
url += route;
if (include_read_from_master && mReadFromMaster)
{
url += "?read_from_master=true";
}
}
return url;
}
void LLTwitterConnect::connectToTwitter(const std::string& request_token, const std::string& oauth_verifier)
{
setConnectionState(LLTwitterConnect::TWITTER_CONNECTION_IN_PROGRESS);
LLCoros::instance().launch("LLTwitterConnect::twitterConnectCoro",
boost::bind(&LLTwitterConnect::twitterConnectCoro, this, request_token, oauth_verifier));
}
void LLTwitterConnect::disconnectFromTwitter()
{
setConnectionState(LLTwitterConnect::TWITTER_DISCONNECTING);
LLCoros::instance().launch("LLTwitterConnect::twitterDisconnectCoro",
boost::bind(&LLTwitterConnect::twitterDisconnectCoro, this));
}
void LLTwitterConnect::checkConnectionToTwitter(bool auto_connect)
{
LLCoros::instance().launch("LLTwitterConnect::twitterConnectedCoro",
boost::bind(&LLTwitterConnect::twitterConnectedCoro, this, auto_connect));
}
void LLTwitterConnect::loadTwitterInfo()
{
if(mRefreshInfo)
{
LLCoros::instance().launch("LLTwitterConnect::twitterInfoCoro",
boost::bind(&LLTwitterConnect::twitterInfoCoro, this));
}
}
void LLTwitterConnect::uploadPhoto(const std::string& image_url, const std::string& status)
{
LLSD body;
body["image"] = image_url;
body["status"] = status;
setConnectionState(LLTwitterConnect::TWITTER_POSTING);
LLCoros::instance().launch("LLTwitterConnect::twitterShareCoro",
boost::bind(&LLTwitterConnect::twitterShareCoro, this, "/share/photo", body));
}
void LLTwitterConnect::uploadPhoto(LLPointer<LLImageFormatted> image, const std::string& status)
{
setConnectionState(LLTwitterConnect::TWITTER_POSTING);
LLCoros::instance().launch("LLTwitterConnect::twitterShareImageCoro",
boost::bind(&LLTwitterConnect::twitterShareImageCoro, this, image, status));
}
void LLTwitterConnect::updateStatus(const std::string& status)
{
LLSD body;
body["status"] = status;
setConnectionState(LLTwitterConnect::TWITTER_POSTING);
LLCoros::instance().launch("LLTwitterConnect::twitterShareCoro",
boost::bind(&LLTwitterConnect::twitterShareCoro, this, "/share/status", body));
}
void LLTwitterConnect::storeInfo(const LLSD& info)
{
mInfo = info;
mRefreshInfo = false;
sInfoWatcher->post(info);
}
const LLSD& LLTwitterConnect::getInfo() const
{
return mInfo;
}
void LLTwitterConnect::clearInfo()
{
mInfo = LLSD();
}
void LLTwitterConnect::setDataDirty()
{
mRefreshInfo = true;
}
void LLTwitterConnect::setConnectionState(LLTwitterConnect::EConnectionState connection_state)
{
if(connection_state == TWITTER_CONNECTED)
{
mReadFromMaster = true;
setConnected(true);
setDataDirty();
}
else if(connection_state == TWITTER_NOT_CONNECTED)
{
setConnected(false);
}
else if(connection_state == TWITTER_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 LLTwitterConnect::setConnected(bool connected)
{
mConnected = connected;
}

View File

@ -1,107 +0,0 @@
/**
* @file lltwitterconnect.h
* @author Merov, Cho
* @brief Connection to Twitter 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_LLTWITTERCONNECT_H
#define LL_LLTWITTERCONNECT_H
#include "llsingleton.h"
#include "llimage.h"
#include "llcoros.h"
#include "lleventcoro.h"
class LLEventPump;
/**
* @class LLTwitterConnect
*
* Manages authentication to, and interaction with, a web service allowing the
* the viewer to post status updates and upload photos to Twitter.
*/
class LLTwitterConnect : public LLSingleton<LLTwitterConnect>
{
LLSINGLETON(LLTwitterConnect);
LOG_CLASS(LLTwitterConnect);
public:
enum EConnectionState
{
TWITTER_NOT_CONNECTED = 0,
TWITTER_CONNECTION_IN_PROGRESS = 1,
TWITTER_CONNECTED = 2,
TWITTER_CONNECTION_FAILED = 3,
TWITTER_POSTING = 4,
TWITTER_POSTED = 5,
TWITTER_POST_FAILED = 6,
TWITTER_DISCONNECTING = 7,
TWITTER_DISCONNECT_FAILED = 8
};
void connectToTwitter(const std::string& request_token = "", const std::string& oauth_verifier = ""); // Initiate the complete Twitter connection. Please use checkConnectionToTwitter() in normal use.
void disconnectFromTwitter(); // Disconnect from the Twitter service.
void checkConnectionToTwitter(bool auto_connect = false); // Check if an access token is available on the Twitter service. If not, call connectToTwitter().
void loadTwitterInfo();
void uploadPhoto(const std::string& image_url, const std::string& status);
void uploadPhoto(LLPointer<LLImageFormatted> image, const std::string& status);
void updateStatus(const std::string& status);
void storeInfo(const LLSD& info);
const LLSD& getInfo() const;
void clearInfo();
void setDataDirty();
void setConnectionState(EConnectionState connection_state);
void setConnected(bool connected);
bool isConnected() { return mConnected; }
bool isTransactionOngoing() { return ((mConnectionState == TWITTER_CONNECTION_IN_PROGRESS) || (mConnectionState == TWITTER_POSTING) || (mConnectionState == TWITTER_DISCONNECTING)); }
EConnectionState getConnectionState() { return mConnectionState; }
void openTwitterWeb(std::string url);
private:
std::string getTwitterConnectURL(const std::string& route = "", bool include_read_from_master = false);
EConnectionState mConnectionState;
BOOL mConnected;
LLSD mInfo;
bool mRefreshInfo;
bool mReadFromMaster;
static boost::scoped_ptr<LLEventPump> sStateWatcher;
static boost::scoped_ptr<LLEventPump> sInfoWatcher;
static boost::scoped_ptr<LLEventPump> sContentWatcher;
bool testShareStatus(LLSD &result);
void twitterConnectCoro(std::string requestToken, std::string oauthVerifier);
void twitterDisconnectCoro();
void twitterConnectedCoro(bool autoConnect);
void twitterInfoCoro();
void twitterShareCoro(std::string route, LLSD share);
void twitterShareImageCoro(LLPointer<LLImageFormatted> image, std::string status);
};
#endif // LL_LLTWITTERCONNECT_H

View File

@ -1087,7 +1087,7 @@ void render_hud_attachments()
// clamp target zoom level to reasonable values
gAgentCamera.mHUDTargetZoom = llclamp(gAgentCamera.mHUDTargetZoom, 0.1f, 1.f);
// smoothly interpolate current zoom level
gAgentCamera.mHUDCurZoom = lerp(gAgentCamera.mHUDCurZoom, gAgentCamera.mHUDTargetZoom, LLSmoothInterpolation::getInterpolant(0.03f));
gAgentCamera.mHUDCurZoom = lerp(gAgentCamera.mHUDCurZoom, gAgentCamera.getAgentHUDTargetZoom(), LLSmoothInterpolation::getInterpolant(0.03f));
if (LLPipeline::sShowHUDAttachments && !gDisconnected && setup_hud_matrices())
{

View File

@ -67,7 +67,6 @@
#include "llfloaterexperiences.h"
#include "llfloaterexperiencepicker.h"
#include "llfloaterevent.h"
#include "llfloaterflickr.h"
#include "llfloaterfonttest.h"
#include "llfloatergesture.h"
#include "llfloatergodtools.h"
@ -132,7 +131,6 @@
#include "llfloatertos.h"
#include "llfloatertoybox.h"
#include "llfloatertranslationsettings.h"
#include "llfloatertwitter.h"
#include "llfloateruipreview.h"
#include "llfloatervoiceeffect.h"
#include "llfloaterwebcontent.h"
@ -352,11 +350,6 @@ 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("flickr_web", "floater_fbc_web.xml", (LLFloaterBuildFunc)&LLFloaterWebContent::create);
LLFloaterReg::add("twitter_web", "floater_fbc_web.xml", (LLFloaterBuildFunc)&LLFloaterWebContent::create);
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>);
LLFloaterUIPreviewUtil::registerFloater();

View File

@ -225,7 +225,7 @@ void LLViewerJointAttachment::removeObject(LLViewerObject *object)
iter != mAttachedObjects.end();
++iter)
{
LLViewerObject *attached_object = (*iter);
LLViewerObject *attached_object = iter->get();
if (attached_object == object)
{
break;
@ -327,7 +327,7 @@ void LLViewerJointAttachment::setAttachmentVisibility(BOOL visible)
iter != mAttachedObjects.end();
++iter)
{
LLViewerObject *attached_obj = (*iter);
LLViewerObject *attached_obj = iter->get();
if (!attached_obj || attached_obj->mDrawable.isNull() ||
!(attached_obj->mDrawable->getSpatialBridge()))
continue;
@ -366,7 +366,7 @@ S32 LLViewerJointAttachment::getNumAnimatedObjects() const
iter != mAttachedObjects.end();
++iter)
{
const LLViewerObject *attached_object = *iter;
const LLViewerObject *attached_object = iter->get();
if (attached_object->isAnimatedObject())
{
count++;
@ -384,7 +384,7 @@ void LLViewerJointAttachment::clampObjectPosition()
iter != mAttachedObjects.end();
++iter)
{
if (LLViewerObject *attached_object = (*iter))
if (LLViewerObject *attached_object = iter->get())
{
// *NOTE: object can drift when hitting maximum radius
LLVector3 attachmentPos = attached_object->getPosition();
@ -406,7 +406,7 @@ void LLViewerJointAttachment::calcLOD()
iter != mAttachedObjects.end();
++iter)
{
if (LLViewerObject *attached_object = (*iter))
if (LLViewerObject *attached_object = iter->get())
{
maxarea = llmax(maxarea,attached_object->getMaxScale() * attached_object->getMidScale());
LLViewerObject::const_child_list_t& child_list = attached_object->getChildren();
@ -445,7 +445,7 @@ BOOL LLViewerJointAttachment::isObjectAttached(const LLViewerObject *viewer_obje
iter != mAttachedObjects.end();
++iter)
{
const LLViewerObject* attached_object = (*iter);
const LLViewerObject* attached_object = iter->get();
if (attached_object == viewer_object)
{
return TRUE;
@ -460,7 +460,7 @@ const LLViewerObject *LLViewerJointAttachment::getAttachedObject(const LLUUID &o
iter != mAttachedObjects.end();
++iter)
{
const LLViewerObject* attached_object = (*iter);
const LLViewerObject* attached_object = iter->get();
if (attached_object->getAttachmentItemID() == object_id)
{
return attached_object;
@ -475,7 +475,7 @@ LLViewerObject *LLViewerJointAttachment::getAttachedObject(const LLUUID &object_
iter != mAttachedObjects.end();
++iter)
{
LLViewerObject* attached_object = (*iter);
LLViewerObject* attached_object = iter->get();
if (attached_object->getAttachmentItemID() == object_id)
{
return attached_object;

View File

@ -95,7 +95,7 @@ public:
LLViewerObject *getAttachedObject(const LLUUID &object_id);
// list of attachments for this joint
typedef std::vector<LLViewerObject *> attachedobjs_vec_t;
typedef std::vector<LLPointer<LLViewerObject> > attachedobjs_vec_t;
attachedobjs_vec_t mAttachedObjects;
protected:

View File

@ -6672,10 +6672,10 @@ private:
static void onNearAttachObject(BOOL success, void *user_data);
void confirmReplaceAttachment(S32 option, LLViewerJointAttachment* attachment_point);
struct CallbackData
class CallbackData : public LLSelectionCallbackData
{
CallbackData(LLViewerJointAttachment* point, bool replace) : mAttachmentPoint(point), mReplace(replace) {}
public:
CallbackData(LLViewerJointAttachment* point, bool replace) : LLSelectionCallbackData(), mAttachmentPoint(point), mReplace(replace) {}
LLViewerJointAttachment* mAttachmentPoint;
bool mReplace;
@ -6716,8 +6716,8 @@ void LLObjectAttachToAvatar::onNearAttachObject(BOOL success, void *user_data)
// interpret 0 as "default location"
attachment_id = 0;
}
LLSelectMgr::getInstance()->sendAttach(attachment_id, cb_data->mReplace);
}
LLSelectMgr::getInstance()->sendAttach(cb_data->getSelection(), attachment_id, cb_data->mReplace);
}
LLObjectAttachToAvatar::setObjectSelection(NULL);
delete cb_data;
@ -6840,7 +6840,7 @@ class LLAttachmentDetachFromPoint : public view_listener_t
iter != attachment->mAttachedObjects.end();
iter++)
{
LLViewerObject *attached_object = (*iter);
LLViewerObject *attached_object = iter->get();
ids_to_remove.push_back(attached_object->getAttachmentItemID());
}
}
@ -6866,7 +6866,7 @@ static bool onEnableAttachmentLabel(LLUICtrl* ctrl, const LLSD& data)
attachment_iter != attachment->mAttachedObjects.end();
++attachment_iter)
{
const LLViewerObject* attached_object = (*attachment_iter);
const LLViewerObject* attached_object = attachment_iter->get();
if (attached_object)
{
LLViewerInventoryItem* itemp = gInventory.getItem(attached_object->getAttachmentItemID());
@ -6979,7 +6979,7 @@ class LLAttachmentEnableDrop : public view_listener_t
{
// make sure item is in your inventory (it could be a delayed attach message being sent from the sim)
// so check to see if the item is in the inventory already
item = gInventory.getItem((*attachment_iter)->getAttachmentItemID());
item = gInventory.getItem(attachment_iter->get()->getAttachmentItemID());
if (!item)
{
// Item does not exist, make an observer to enable the pie menu
@ -7361,7 +7361,7 @@ void handle_dump_attachments(void*)
attachment_iter != attachment->mAttachedObjects.end();
++attachment_iter)
{
LLViewerObject *attached_object = (*attachment_iter);
LLViewerObject *attached_object = attachment_iter->get();
BOOL visible = (attached_object != NULL &&
attached_object->mDrawable.notNull() &&
!attached_object->mDrawable->isRenderType(0));

View File

@ -1671,8 +1671,20 @@ void LLOfferInfo::fromLLSD(const LLSD& params)
*this = params;
}
void LLOfferInfo::send_auto_receive_response(void)
{
void LLOfferInfo::sendReceiveResponse(bool accept, const LLUUID &destination_folder_id)
{
if(IM_INVENTORY_OFFERED == mIM)
{
// add buddy to recent people list
LLRecentPeople::instance().add(mFromID);
}
if (mTransactionID.isNull())
{
// Not provided, message won't work
return;
}
LLMessageSystem* msg = gMessageSystem;
msg->newMessageFast(_PREHASH_ImprovedInstantMessage);
msg->nextBlockFast(_PREHASH_AgentData);
@ -1691,23 +1703,42 @@ void LLOfferInfo::send_auto_receive_response(void)
msg->addU32Fast(_PREHASH_ParentEstateID, 0);
msg->addUUIDFast(_PREHASH_RegionID, LLUUID::null);
msg->addVector3Fast(_PREHASH_Position, gAgent.getPositionAgent());
// Auto Receive Message. The math for the dialog works, because the accept
// ACCEPT. The math for the dialog works, because the accept
// for inventory_offered, task_inventory_offer or
// group_notice_inventory is 1 greater than the offer integer value.
// Generates IM_INVENTORY_ACCEPTED, IM_TASK_INVENTORY_ACCEPTED,
// or IM_GROUP_NOTICE_INVENTORY_ACCEPTED
msg->addU8Fast(_PREHASH_Dialog, (U8)(mIM + 1));
msg->addBinaryDataFast(_PREHASH_BinaryBucket, &(mFolderID.mData),
sizeof(mFolderID.mData));
// Decline for inventory_offered, task_inventory_offer or
// group_notice_inventory is 2 greater than the offer integer value.
EInstantMessage im = mIM;
if (mIM == IM_GROUP_NOTICE_REQUESTED)
{
// Request has no responder dialogs
im = IM_GROUP_NOTICE;
}
if (accept)
{
msg->addU8Fast(_PREHASH_Dialog, (U8)(im + 1));
msg->addBinaryDataFast(_PREHASH_BinaryBucket, &(destination_folder_id.mData),
sizeof(destination_folder_id.mData));
}
else
{
msg->addU8Fast(_PREHASH_Dialog, (U8)(im + 2));
msg->addBinaryDataFast(_PREHASH_BinaryBucket, EMPTY_BINARY_BUCKET, EMPTY_BINARY_BUCKET_SIZE);
}
// send the message
msg->sendReliable(mHost);
if(IM_INVENTORY_OFFERED == mIM)
{
// add buddy to recent people list
LLRecentPeople::instance().add(mFromID);
}
// transaction id is usable only once
// Note: a bit of a hack, clicking group notice attachment will not close notice
// so we reset no longer usable transaction id to know not to send message again
// Once capabilities for responses will be implemented LLOfferInfo will have to
// remember that it already responded in another way and ignore IOR_DECLINE
mTransactionID.setNull();
}
void LLOfferInfo::handleRespond(const LLSD& notification, const LLSD& response)
@ -1767,7 +1798,10 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD&
// TODO: when task inventory offers can also be handled the new way, migrate the code that sets these strings here:
from_string = chatHistory_string = mFromName;
// accept goes to proper folder, decline gets accepted to trash, muted gets declined
bool accept_to_trash = true;
LLNotificationFormPtr modified_form(notification_ptr ? new LLNotificationForm(*notification_ptr->getForm()) : new LLNotificationForm());
switch(button)
@ -1799,11 +1833,11 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD&
}
break;
case IM_GROUP_NOTICE:
case IM_GROUP_NOTICE_REQUESTED:
opener = new LLOpenTaskGroupOffer;
send_auto_receive_response();
sendReceiveResponse(true, mFolderID);
break;
case IM_TASK_INVENTORY_OFFERED:
case IM_GROUP_NOTICE_REQUESTED:
// This is an offer from a task or group.
// We don't use a new instance of an opener
// We instead use the singular observer gOpenTaskOffer
@ -1838,6 +1872,7 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD&
{
modified_form->setElementEnabled("Mute", false);
}
accept_to_trash = false; // for notices, but IOR_MUTE normally doesn't happen for notices
// MUTE falls through to decline
case IOR_DECLINE:
{
@ -1851,21 +1886,32 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD&
if( LLMuteList::getInstance()->isMuted(mFromID ) && ! LLMuteList::getInstance()->isLinden(mFromName) ) // muting for SL-42269
{
chat.mMuted = TRUE;
accept_to_trash = false; // will send decline message
}
// *NOTE dzaporozhan
// Disabled logging to old chat floater to fix crash in group notices - EXT-4149
// LLFloaterChat::addChatHistory(chat);
LLDiscardAgentOffer* discard_agent_offer = new LLDiscardAgentOffer(mFolderID, mObjectID);
discard_agent_offer->startFetch();
if ((catp && gInventory.isCategoryComplete(mObjectID)) || (itemp && itemp->isFinished()))
if (mObjectID.notNull()) //make sure we can discard
{
discard_agent_offer->done();
LLDiscardAgentOffer* discard_agent_offer = new LLDiscardAgentOffer(mFolderID, mObjectID);
discard_agent_offer->startFetch();
if ((catp && gInventory.isCategoryComplete(mObjectID)) || (itemp && itemp->isFinished()))
{
discard_agent_offer->done();
}
else
{
opener = discard_agent_offer;
}
}
else
else if (mIM == IM_GROUP_NOTICE)
{
opener = discard_agent_offer;
// group notice needs to request object to trash so that user will see it later
// Note: muted agent offers go to trash, not sure if we should do same for notices
LLUUID trash = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH);
sendReceiveResponse(accept_to_trash, trash);
}
if (modified_form != NULL)
@ -1878,9 +1924,14 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD&
}
default:
// close button probably
// The item has already been fetched and is in your inventory, we simply won't highlight it
// In case of agent offers item has already been fetched and is in your inventory, we simply won't highlight it
// OR delete it if the notification gets killed, since we don't want that to be a vector for
// losing inventory offers.
if (mIM == IM_GROUP_NOTICE)
{
LLUUID trash = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH);
sendReceiveResponse(true, trash);
}
break;
}
@ -1925,29 +1976,10 @@ bool LLOfferInfo::inventory_task_offer_callback(const LLSD& notification, const
}
}
}
LLMessageSystem* msg = gMessageSystem;
msg->newMessageFast(_PREHASH_ImprovedInstantMessage);
msg->nextBlockFast(_PREHASH_AgentData);
msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
msg->nextBlockFast(_PREHASH_MessageBlock);
msg->addBOOLFast(_PREHASH_FromGroup, FALSE);
msg->addUUIDFast(_PREHASH_ToAgentID, mFromID);
msg->addU8Fast(_PREHASH_Offline, IM_ONLINE);
msg->addUUIDFast(_PREHASH_ID, mTransactionID);
msg->addU32Fast(_PREHASH_Timestamp, NO_TIMESTAMP); // no timestamp necessary
std::string name;
LLAgentUI::buildFullname(name);
msg->addStringFast(_PREHASH_FromAgentName, name);
msg->addStringFast(_PREHASH_Message, "");
msg->addU32Fast(_PREHASH_ParentEstateID, 0);
msg->addUUIDFast(_PREHASH_RegionID, LLUUID::null);
msg->addVector3Fast(_PREHASH_Position, gAgent.getPositionAgent());
LLInventoryObserver* opener = NULL;
std::string from_string; // Used in the pop-up.
std::string chatHistory_string; // Used in chat history.
if (mFromObject == TRUE)
{
if (mFromGroup)
@ -1991,23 +2023,15 @@ bool LLOfferInfo::inventory_task_offer_callback(const LLSD& notification, const
from_string = chatHistory_string = mFromName;
}
bool is_do_not_disturb = gAgent.isDoNotDisturb();
LLUUID destination;
bool accept = true;
// If user accepted, accept to proper folder, if user discarded, accept to trash.
switch(button)
{
case IOR_ACCEPT:
// ACCEPT. The math for the dialog works, because the accept
// for inventory_offered, task_inventory_offer or
// group_notice_inventory is 1 greater than the offer integer value.
// Generates IM_INVENTORY_ACCEPTED, IM_TASK_INVENTORY_ACCEPTED,
// or IM_GROUP_NOTICE_INVENTORY_ACCEPTED
msg->addU8Fast(_PREHASH_Dialog, (U8)(mIM + 1));
msg->addBinaryDataFast(_PREHASH_BinaryBucket, &(mFolderID.mData),
sizeof(mFolderID.mData));
// send the message
msg->sendReliable(mHost);
//don't spam them if they are getting flooded
destination = mFolderID;
//don't spam user if flooded
if (check_offer_throttle(mFromName, true))
{
log_message = "<nolink>" + chatHistory_string + "</nolink> " + LLTrans::getString("InvOfferGaveYou") + " " + getSanitizedDescription() + LLTrans::getString(".");
@ -2015,66 +2039,24 @@ bool LLOfferInfo::inventory_task_offer_callback(const LLSD& notification, const
args["MESSAGE"] = log_message;
LLNotificationsUtil::add("SystemMessageTip", args);
}
// we will want to open this item when it comes back.
LL_DEBUGS("Messaging") << "Initializing an opener for tid: " << mTransactionID
<< LL_ENDL;
switch (mIM)
{
case IM_TASK_INVENTORY_OFFERED:
case IM_GROUP_NOTICE:
case IM_GROUP_NOTICE_REQUESTED:
{
// This is an offer from a task or group.
// We don't use a new instance of an opener
// We instead use the singular observer gOpenTaskOffer
// Since it already exists, we don't need to actually do anything
}
break;
default:
LL_WARNS("Messaging") << "inventory_offer_callback: unknown offer type" << LL_ENDL;
break;
} // end switch (mIM)
break;
case IOR_MUTE:
// MUTE falls through to decline
accept = false;
case IOR_DECLINE:
// DECLINE. The math for the dialog works, because the decline
// for inventory_offered, task_inventory_offer or
// group_notice_inventory is 2 greater than the offer integer value.
// Generates IM_INVENTORY_DECLINED, IM_TASK_INVENTORY_DECLINED,
// or IM_GROUP_NOTICE_INVENTORY_DECLINED
default:
// close button probably (or any of the fall-throughs from above)
msg->addU8Fast(_PREHASH_Dialog, (U8)(mIM + 2));
msg->addBinaryDataFast(_PREHASH_BinaryBucket, EMPTY_BINARY_BUCKET, EMPTY_BINARY_BUCKET_SIZE);
// send the message
msg->sendReliable(mHost);
if (gSavedSettings.getBOOL("LogInventoryDecline"))
destination = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH);
if (accept && LLMuteList::getInstance()->isMuted(mFromID, mFromName))
{
LLStringUtil::format_map_t log_message_args;
log_message_args["DESC"] = mDesc;
log_message_args["NAME"] = mFromName;
log_message = LLTrans::getString("InvOfferDecline", log_message_args);
LLSD args;
args["MESSAGE"] = log_message;
LLNotificationsUtil::add("SystemMessageTip", args);
}
if (is_do_not_disturb && (!mFromGroup && !mFromObject))
{
send_do_not_disturb_message(msg,mFromID);
// Note: muted offers are usually declined automatically,
// but user can mute object after receiving message
accept = false;
}
break;
}
if(opener)
{
gInventory.addObserver(opener);
}
sendReceiveResponse(accept, destination);
if(!mPersist)
{
@ -4045,6 +4027,8 @@ void process_avatar_animation(LLMessageSystem *mesgsys, void **user_data)
S32 num_blocks = mesgsys->getNumberOfBlocksFast(_PREHASH_AnimationList);
S32 num_source_blocks = mesgsys->getNumberOfBlocksFast(_PREHASH_AnimationSourceList);
LL_DEBUGS("Messaging", "Motion") << "Processing " << num_blocks << " Animations" << LL_ENDL;
//clear animation flags
avatarp->mSignaledAnimations.clear();
@ -4057,8 +4041,6 @@ void process_avatar_animation(LLMessageSystem *mesgsys, void **user_data)
mesgsys->getUUIDFast(_PREHASH_AnimationList, _PREHASH_AnimID, animation_id, i);
mesgsys->getS32Fast(_PREHASH_AnimationList, _PREHASH_AnimSequenceID, anim_sequence_id, i);
LL_DEBUGS("Messaging") << "Anim sequence ID: " << anim_sequence_id << LL_ENDL;
avatarp->mSignaledAnimations[animation_id] = anim_sequence_id;
// *HACK: Disabling flying mode if it has been enabled shortly before the agent
@ -4097,6 +4079,14 @@ void process_avatar_animation(LLMessageSystem *mesgsys, void **user_data)
avatarp->mAnimationSources.insert(LLVOAvatar::AnimationSourceMap::value_type(object_id, animation_id));
}
}
LL_DEBUGS("Messaging", "Motion") << "Anim sequence ID: " << anim_sequence_id
<< " Animation id: " << animation_id
<< " From block: " << object_id << LL_ENDL;
}
else
{
LL_DEBUGS("Messaging", "Motion") << "Anim sequence ID: " << anim_sequence_id
<< " Animation id: " << animation_id << LL_ENDL;
}
}
}
@ -5163,12 +5153,27 @@ bool attempt_standard_notification(LLMessageSystem* msgsystem)
}
}
// Error Notification can come with and without reason
if (notificationID == "JoinGroupError" && llsdBlock.has("reason"))
{
LLNotificationsUtil::add("JoinGroupErrorReason", llsdBlock);
return true;
}
// Error Notification can come with and without reason
if (notificationID == "JoinGroupError")
{
if (llsdBlock.has("reason"))
{
LLNotificationsUtil::add("JoinGroupErrorReason", llsdBlock);
return true;
}
if (llsdBlock.has("group_id"))
{
LLGroupData agent_gdatap;
bool is_member = gAgent.getGroupData(llsdBlock["group_id"].asUUID(), agent_gdatap);
if (is_member)
{
LLSD args;
args["reason"] = LLTrans::getString("AlreadyInGroup");
LLNotificationsUtil::add("JoinGroupErrorReason", args);
return true;
}
}
}
LLNotificationsUtil::add(notificationID, llsdBlock);
return true;

View File

@ -254,7 +254,7 @@ public:
/*virtual*/ void fromLLSD(const LLSD& params);
/*virtual*/ void handleRespond(const LLSD& notification, const LLSD& response);
void send_auto_receive_response(void);
void send_auto_receive_response() { sendReceiveResponse(true, mFolderID); }
// TODO - replace all references with handleRespond()
bool inventory_offer_callback(const LLSD& notification, const LLSD& response);
@ -264,6 +264,7 @@ private:
void initRespondFunctionMap();
std::string getSanitizedDescription();
void sendReceiveResponse(bool accept, const LLUUID &destination_folder_id);
typedef boost::function<bool (const LLSD&, const LLSD&)> respond_function_t;
typedef std::map<std::string, respond_function_t> respond_function_map_t;

View File

@ -142,6 +142,9 @@ const F32 PHYSICS_TIMESTEP = 1.f / 45.f;
const U32 MAX_INV_FILE_READ_FAILS = 25;
const S32 MAX_OBJECT_BINARY_DATA_SIZE = 60 + 16;
const F64 INVENTORY_UPDATE_WAIT_TIME_DESYNC = 5; // seconds
const F64 INVENTORY_UPDATE_WAIT_TIME_OUTDATED = 1;
static LLTrace::BlockTimerStatHandle FTM_CREATE_OBJECT("Create Object");
// static
@ -269,6 +272,7 @@ LLViewerObject::LLViewerObject(const LLUUID &id, const LLPCode pcode, LLViewerRe
mPixelArea(1024.f),
mInventory(NULL),
mInventorySerialNum(0),
mExpectedInventorySerialNum(0),
mInvRequestState(INVENTORY_REQUEST_STOPPED),
mInvRequestXFerId(0),
mInventoryDirty(FALSE),
@ -1279,7 +1283,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
{
case (60 + 16):
// pull out collision normal for avatar
htonmemcpy(collision_plane.mV, &data[count], MVT_LLVector4, sizeof(LLVector4));
htolememcpy(collision_plane.mV, &data[count], MVT_LLVector4, sizeof(LLVector4));
((LLVOAvatar*)this)->setFootPlane(collision_plane);
count += sizeof(LLVector4);
// fall through
@ -1287,23 +1291,23 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
this_update_precision = 32;
// this is a terse update
// pos
htonmemcpy(new_pos_parent.mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
htolememcpy(new_pos_parent.mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
count += sizeof(LLVector3);
// vel
htonmemcpy((void*)getVelocity().mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
htolememcpy((void*)getVelocity().mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
count += sizeof(LLVector3);
// acc
htonmemcpy((void*)getAcceleration().mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
htolememcpy((void*)getAcceleration().mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
count += sizeof(LLVector3);
// theta
{
LLVector3 vec;
htonmemcpy(vec.mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
htolememcpy(vec.mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
new_rot.unpackFromVector3(vec);
}
count += sizeof(LLVector3);
// omega
htonmemcpy((void*)new_angv.mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
htolememcpy((void*)new_angv.mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
if (new_angv.isExactlyZero())
{
// reset rotation time
@ -1319,7 +1323,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
break;
case(32 + 16):
// pull out collision normal for avatar
htonmemcpy(collision_plane.mV, &data[count], MVT_LLVector4, sizeof(LLVector4));
htolememcpy(collision_plane.mV, &data[count], MVT_LLVector4, sizeof(LLVector4));
((LLVOAvatar*)this)->setFootPlane(collision_plane);
count += sizeof(LLVector4);
// fall through
@ -1329,7 +1333,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
// This is a terse 16 update, so treat data as an array of U16's.
#ifdef LL_BIG_ENDIAN
htonmemcpy(valswizzle, &data[count], MVT_U16Vec3, 6);
htolememcpy(valswizzle, &data[count], MVT_U16Vec3, 6);
val = valswizzle;
#else
val = (U16 *) &data[count];
@ -1340,7 +1344,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
new_pos_parent.mV[VZ] = U16_to_F32(val[VZ], MIN_HEIGHT, MAX_HEIGHT);
#ifdef LL_BIG_ENDIAN
htonmemcpy(valswizzle, &data[count], MVT_U16Vec3, 6);
htolememcpy(valswizzle, &data[count], MVT_U16Vec3, 6);
val = valswizzle;
#else
val = (U16 *) &data[count];
@ -1351,7 +1355,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
U16_to_F32(val[VZ], -size, size)));
#ifdef LL_BIG_ENDIAN
htonmemcpy(valswizzle, &data[count], MVT_U16Vec3, 6);
htolememcpy(valswizzle, &data[count], MVT_U16Vec3, 6);
val = valswizzle;
#else
val = (U16 *) &data[count];
@ -1362,7 +1366,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
U16_to_F32(val[VZ], -size, size)));
#ifdef LL_BIG_ENDIAN
htonmemcpy(valswizzle, &data[count], MVT_U16Quat, 4);
htolememcpy(valswizzle, &data[count], MVT_U16Quat, 4);
val = valswizzle;
#else
val = (U16 *) &data[count];
@ -1374,7 +1378,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
new_rot.mQ[VW] = U16_to_F32(val[VW], -1.f, 1.f);
#ifdef LL_BIG_ENDIAN
htonmemcpy(valswizzle, &data[count], MVT_U16Vec3, 6);
htolememcpy(valswizzle, &data[count], MVT_U16Vec3, 6);
val = valswizzle;
#else
val = (U16 *) &data[count];
@ -1570,7 +1574,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
{
case(60 + 16):
// pull out collision normal for avatar
htonmemcpy(collision_plane.mV, &data[count], MVT_LLVector4, sizeof(LLVector4));
htolememcpy(collision_plane.mV, &data[count], MVT_LLVector4, sizeof(LLVector4));
((LLVOAvatar*)this)->setFootPlane(collision_plane);
count += sizeof(LLVector4);
// fall through
@ -1578,23 +1582,23 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
// this is a terse 32 update
// pos
this_update_precision = 32;
htonmemcpy(new_pos_parent.mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
htolememcpy(new_pos_parent.mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
count += sizeof(LLVector3);
// vel
htonmemcpy((void*)getVelocity().mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
htolememcpy((void*)getVelocity().mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
count += sizeof(LLVector3);
// acc
htonmemcpy((void*)getAcceleration().mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
htolememcpy((void*)getAcceleration().mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
count += sizeof(LLVector3);
// theta
{
LLVector3 vec;
htonmemcpy(vec.mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
htolememcpy(vec.mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
new_rot.unpackFromVector3(vec);
}
count += sizeof(LLVector3);
// omega
htonmemcpy((void*)new_angv.mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
htolememcpy((void*)new_angv.mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
if (new_angv.isExactlyZero())
{
// reset rotation time
@ -1610,7 +1614,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
break;
case(32 + 16):
// pull out collision normal for avatar
htonmemcpy(collision_plane.mV, &data[count], MVT_LLVector4, sizeof(LLVector4));
htolememcpy(collision_plane.mV, &data[count], MVT_LLVector4, sizeof(LLVector4));
((LLVOAvatar*)this)->setFootPlane(collision_plane);
count += sizeof(LLVector4);
// fall through
@ -1620,7 +1624,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
test_pos_parent.quantize16(-0.5f*size, 1.5f*size, MIN_HEIGHT, MAX_HEIGHT);
#ifdef LL_BIG_ENDIAN
htonmemcpy(valswizzle, &data[count], MVT_U16Vec3, 6);
htolememcpy(valswizzle, &data[count], MVT_U16Vec3, 6);
val = valswizzle;
#else
val = (U16 *) &data[count];
@ -1631,7 +1635,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
new_pos_parent.mV[VZ] = U16_to_F32(val[VZ], MIN_HEIGHT, MAX_HEIGHT);
#ifdef LL_BIG_ENDIAN
htonmemcpy(valswizzle, &data[count], MVT_U16Vec3, 6);
htolememcpy(valswizzle, &data[count], MVT_U16Vec3, 6);
val = valswizzle;
#else
val = (U16 *) &data[count];
@ -1642,7 +1646,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
U16_to_F32(val[VZ], -size, size));
#ifdef LL_BIG_ENDIAN
htonmemcpy(valswizzle, &data[count], MVT_U16Vec3, 6);
htolememcpy(valswizzle, &data[count], MVT_U16Vec3, 6);
val = valswizzle;
#else
val = (U16 *) &data[count];
@ -1653,7 +1657,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
U16_to_F32(val[VZ], -size, size));
#ifdef LL_BIG_ENDIAN
htonmemcpy(valswizzle, &data[count], MVT_U16Quat, 8);
htolememcpy(valswizzle, &data[count], MVT_U16Quat, 8);
val = valswizzle;
#else
val = (U16 *) &data[count];
@ -1665,7 +1669,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
new_rot.mQ[VW] = U16_to_F32(val[VW], -1.f, 1.f);
#ifdef LL_BIG_ENDIAN
htonmemcpy(valswizzle, &data[count], MVT_U16Vec3, 6);
htolememcpy(valswizzle, &data[count], MVT_U16Vec3, 6);
val = valswizzle;
#else
val = (U16 *) &data[count];
@ -2802,13 +2806,13 @@ void LLViewerObject::doUpdateInventory(
{
// best guess.
perm.setOwnerAndGroup(LLUUID::null, gAgent.getID(), item->getPermissions().getGroup(), is_atomic);
--mInventorySerialNum;
--mExpectedInventorySerialNum;
}
else
{
// dummy it up.
perm.setOwnerAndGroup(LLUUID::null, LLUUID::null, LLUUID::null, is_atomic);
--mInventorySerialNum;
--mExpectedInventorySerialNum;
}
}
LLViewerInventoryItem* oldItem = item;
@ -2816,7 +2820,11 @@ void LLViewerObject::doUpdateInventory(
new_item->setPermissions(perm);
mInventory->push_front(new_item);
doInventoryCallback();
++mInventorySerialNum;
++mExpectedInventorySerialNum;
}
else if (is_new)
{
++mExpectedInventorySerialNum;
}
}
@ -2883,7 +2891,7 @@ void LLViewerObject::moveInventory(const LLUUID& folder_id,
if(!item->getPermissions().allowCopyBy(gAgent.getID()))
{
deleteInventoryItem(item_id);
++mInventorySerialNum;
++mExpectedInventorySerialNum;
}
}
}
@ -2974,6 +2982,8 @@ void LLViewerObject::fetchInventoryFromServer()
if (!isInventoryPending())
{
delete mInventory;
// Results in processTaskInv
LLMessageSystem* msg = gMessageSystem;
msg->newMessageFast(_PREHASH_RequestTaskInventory);
msg->nextBlockFast(_PREHASH_AgentData);
@ -2983,11 +2993,44 @@ void LLViewerObject::fetchInventoryFromServer()
msg->addU32Fast(_PREHASH_LocalID, mLocalID);
msg->sendReliable(mRegionp->getHost());
// this will get reset by dirtyInventory or doInventoryCallback
// This will get reset by doInventoryCallback or processTaskInv
mInvRequestState = INVENTORY_REQUEST_PENDING;
}
}
void LLViewerObject::fetchInventoryDelayed(const F64 &time_seconds)
{
// unless already waiting, drop previous request and shedule an update
if (mInvRequestState != INVENTORY_REQUEST_WAIT)
{
if (mInvRequestXFerId != 0)
{
// abort download.
gXferManager->abortRequestById(mInvRequestXFerId, -1);
mInvRequestXFerId = 0;
}
mInvRequestState = INVENTORY_REQUEST_WAIT; // affects isInventoryPending()
LLCoros::instance().launch("LLViewerObject::fetchInventoryDelayedCoro()",
boost::bind(&LLViewerObject::fetchInventoryDelayedCoro, mID, time_seconds));
}
}
//static
void LLViewerObject::fetchInventoryDelayedCoro(const LLUUID task_inv, const F64 time_seconds)
{
llcoro::suspendUntilTimeout(time_seconds);
LLViewerObject *obj = gObjectList.findObject(task_inv);
if (obj)
{
// Might be good idea to prolong delay here in case expected serial changed.
// As it is, it will get a response with obsolete serial and will delay again.
// drop waiting state to unlock isInventoryPending()
obj->mInvRequestState = INVENTORY_REQUEST_STOPPED;
obj->fetchInventoryFromServer();
}
}
LLControlAvatar *LLViewerObject::getControlAvatar()
{
return getRootEdit()->mControlAvatar.get();
@ -3146,74 +3189,97 @@ S32 LLFilenameAndTask::sCount = 0;
// static
void LLViewerObject::processTaskInv(LLMessageSystem* msg, void** user_data)
{
LLUUID task_id;
msg->getUUIDFast(_PREHASH_InventoryData, _PREHASH_TaskID, task_id);
LLViewerObject* object = gObjectList.findObject(task_id);
if(!object)
{
LL_WARNS() << "LLViewerObject::processTaskInv object "
<< task_id << " does not exist." << LL_ENDL;
return;
}
LLUUID task_id;
msg->getUUIDFast(_PREHASH_InventoryData, _PREHASH_TaskID, task_id);
LLViewerObject* object = gObjectList.findObject(task_id);
if (!object)
{
LL_WARNS() << "LLViewerObject::processTaskInv object "
<< task_id << " does not exist." << LL_ENDL;
return;
}
LLFilenameAndTask* ft = new LLFilenameAndTask;
ft->mTaskID = task_id;
// we can receive multiple task updates simultaneously, make sure we will not rewrite newer with older update
msg->getS16Fast(_PREHASH_InventoryData, _PREHASH_Serial, ft->mSerial);
LLFilenameAndTask* ft = new LLFilenameAndTask;
ft->mTaskID = task_id;
// we can receive multiple task updates simultaneously, make sure we will not rewrite newer with older update
msg->getS16Fast(_PREHASH_InventoryData, _PREHASH_Serial, ft->mSerial);
if (ft->mSerial < object->mInventorySerialNum)
{
// viewer did some changes to inventory that were not saved yet.
LL_DEBUGS() << "Task inventory serial might be out of sync, server serial: " << ft->mSerial << " client serial: " << object->mInventorySerialNum << LL_ENDL;
object->mInventorySerialNum = ft->mSerial;
}
if (ft->mSerial == object->mInventorySerialNum
&& ft->mSerial < object->mExpectedInventorySerialNum)
{
// Loop Protection.
// We received same serial twice.
// Viewer did some changes to inventory that couldn't be saved server side
// or something went wrong to cause serial to be out of sync.
// Drop xfer and restart after some time, assign server's value as expected
LL_WARNS() << "Task inventory serial might be out of sync, server serial: " << ft->mSerial << " client expected serial: " << object->mExpectedInventorySerialNum << LL_ENDL;
object->mExpectedInventorySerialNum = ft->mSerial;
object->fetchInventoryDelayed(INVENTORY_UPDATE_WAIT_TIME_DESYNC);
}
else if (ft->mSerial < object->mExpectedInventorySerialNum)
{
// Out of date message, record to current serial for loop protection, but do not load it
// Drop xfer and restart after some time
if (ft->mSerial < object->mInventorySerialNum)
{
LL_WARNS() << "Task serial decreased. Potentially out of order packet or desync." << LL_ENDL;
}
object->mInventorySerialNum = ft->mSerial;
object->fetchInventoryDelayed(INVENTORY_UPDATE_WAIT_TIME_OUTDATED);
}
else if (ft->mSerial >= object->mExpectedInventorySerialNum)
{
// We received version we expected or newer. Load it.
object->mInventorySerialNum = ft->mSerial;
object->mExpectedInventorySerialNum = ft->mSerial;
std::string unclean_filename;
msg->getStringFast(_PREHASH_InventoryData, _PREHASH_Filename, unclean_filename);
ft->mFilename = LLDir::getScrubbedFileName(unclean_filename);
std::string unclean_filename;
msg->getStringFast(_PREHASH_InventoryData, _PREHASH_Filename, unclean_filename);
ft->mFilename = LLDir::getScrubbedFileName(unclean_filename);
if(ft->mFilename.empty())
{
LL_DEBUGS() << "Task has no inventory" << LL_ENDL;
// mock up some inventory to make a drop target.
if(object->mInventory)
{
object->mInventory->clear(); // will deref and delete it
}
else
{
object->mInventory = new LLInventoryObject::object_list_t();
}
LLPointer<LLInventoryObject> obj;
obj = new LLInventoryObject(object->mID, LLUUID::null,
LLAssetType::AT_CATEGORY,
"Contents");
object->mInventory->push_front(obj);
object->doInventoryCallback();
delete ft;
return;
}
U64 new_id = gXferManager->requestFile(gDirUtilp->getExpandedFilename(LL_PATH_CACHE, ft->mFilename),
ft->mFilename, LL_PATH_CACHE,
object->mRegionp->getHost(),
TRUE,
&LLViewerObject::processTaskInvFile,
(void**)ft,
LLXferManager::HIGH_PRIORITY);
if (object->mInvRequestState == INVENTORY_XFER)
{
if (new_id > 0 && new_id != object->mInvRequestXFerId)
{
// we started new download.
gXferManager->abortRequestById(object->mInvRequestXFerId, -1);
object->mInvRequestXFerId = new_id;
}
}
else
{
object->mInvRequestState = INVENTORY_XFER;
object->mInvRequestXFerId = new_id;
}
if (ft->mFilename.empty())
{
LL_DEBUGS() << "Task has no inventory" << LL_ENDL;
// mock up some inventory to make a drop target.
if (object->mInventory)
{
object->mInventory->clear(); // will deref and delete it
}
else
{
object->mInventory = new LLInventoryObject::object_list_t();
}
LLPointer<LLInventoryObject> obj;
obj = new LLInventoryObject(object->mID, LLUUID::null,
LLAssetType::AT_CATEGORY,
"Contents");
object->mInventory->push_front(obj);
object->doInventoryCallback();
delete ft;
return;
}
U64 new_id = gXferManager->requestFile(gDirUtilp->getExpandedFilename(LL_PATH_CACHE, ft->mFilename),
ft->mFilename, LL_PATH_CACHE,
object->mRegionp->getHost(),
TRUE,
&LLViewerObject::processTaskInvFile,
(void**)ft,
LLXferManager::HIGH_PRIORITY);
if (object->mInvRequestState == INVENTORY_XFER)
{
if (new_id > 0 && new_id != object->mInvRequestXFerId)
{
// we started new download.
gXferManager->abortRequestById(object->mInvRequestXFerId, -1);
object->mInvRequestXFerId = new_id;
}
}
else
{
object->mInvRequestState = INVENTORY_XFER;
object->mInvRequestXFerId = new_id;
}
}
}
void LLViewerObject::processTaskInvFile(void** user_data, S32 error_code, LLExtStat ext_status)
@ -3227,6 +3293,13 @@ void LLViewerObject::processTaskInvFile(void** user_data, S32 error_code, LLExtS
&& ft->mSerial >= object->mInventorySerialNum)
{
object->mInventorySerialNum = ft->mSerial;
LL_DEBUGS() << "Receiving inventory task file for serial " << object->mInventorySerialNum << " taskid: " << ft->mTaskID << LL_ENDL;
if (ft->mSerial < object->mExpectedInventorySerialNum)
{
// User managed to change something while inventory was loading
LL_DEBUGS() << "Processing file that is potentially out of date for task: " << ft->mTaskID << LL_ENDL;
}
if (object->loadTaskInvFile(ft->mFilename))
{
@ -3376,7 +3449,7 @@ void LLViewerObject::removeInventory(const LLUUID& item_id)
msg->addUUIDFast(_PREHASH_ItemID, item_id);
msg->sendReliable(mRegionp->getHost());
deleteInventoryItem(item_id);
++mInventorySerialNum;
++mExpectedInventorySerialNum;
}
bool LLViewerObject::isTextureInInventory(LLViewerInventoryItem* item)

View File

@ -474,6 +474,8 @@ public:
void updateInventoryLocal(LLInventoryItem* item, U8 key); // Update without messaging.
void updateTextureInventory(LLViewerInventoryItem* item, U8 key, bool is_new);
LLInventoryObject* getInventoryObject(const LLUUID& item_id);
// Get content except for root category
void getInventoryContents(LLInventoryObject::object_list_t& objects);
LLInventoryObject* getInventoryRoot();
LLViewerInventoryItem* getInventoryItemByAsset(const LLUUID& asset_id);
@ -623,9 +625,13 @@ private:
static void initObjectDataMap();
// forms task inventory request if none are pending
// forms task inventory request if none are pending, marks request as pending
void fetchInventoryFromServer();
// forms task inventory request after some time passed, marks request as pending
void fetchInventoryDelayed(const F64 &time_seconds);
static void fetchInventoryDelayedCoro(const LLUUID task_inv, const F64 time_seconds);
public:
//
// Viewer-side only types - use the LL_PCODE_APP mask.
@ -804,12 +810,14 @@ protected:
typedef std::list<LLInventoryCallbackInfo*> callback_list_t;
callback_list_t mInventoryCallbacks;
S16 mInventorySerialNum;
S16 mExpectedInventorySerialNum;
enum EInventoryRequestState
{
INVENTORY_REQUEST_STOPPED,
INVENTORY_REQUEST_PENDING,
INVENTORY_XFER
INVENTORY_REQUEST_WAIT, // delay before requesting
INVENTORY_REQUEST_PENDING, // just did fetchInventoryFromServer()
INVENTORY_XFER // processed response from 'fetch', now doing an xfer
};
EInventoryRequestState mInvRequestState;
U64 mInvRequestXFerId;

View File

@ -1921,7 +1921,7 @@ void LLViewerObjectList::generatePickList(LLCamera &camera)
attachment_iter != attachment->mAttachedObjects.end();
++attachment_iter)
{
if (LLViewerObject* attached_object = (*attachment_iter))
if (LLViewerObject* attached_object = attachment_iter->get())
{
mSelectPickList.insert(attached_object);
LLViewerObject::const_child_list_t& child_list = attached_object->getChildren();

View File

@ -2895,8 +2895,6 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames)
capabilityNames.append("EstateAccess");
capabilityNames.append("EstateChangeInfo");
capabilityNames.append("EventQueueGet");
capabilityNames.append("FlickrConnect");
capabilityNames.append("TwitterConnect");
capabilityNames.append("FetchLib2");
capabilityNames.append("FetchLibDescendents2");

View File

@ -938,6 +938,12 @@ BOOL LLViewerWindow::handleAnyMouseClick(LLWindow *window, LLCoordGL pos, MASK
mLeftMouseDown = down;
buttonname = "Left Double Click";
break;
case LLMouseHandler::CLICK_BUTTON4:
buttonname = "Button 4";
break;
case LLMouseHandler::CLICK_BUTTON5:
buttonname = "Button 5";
break;
}
LLView::sMouseHandlerMessage.clear();
@ -1115,7 +1121,7 @@ BOOL LLViewerWindow::handleRightMouseUp(LLWindow *window, LLCoordGL pos, MASK m
BOOL LLViewerWindow::handleMiddleMouseDown(LLWindow *window, LLCoordGL pos, MASK mask)
{
BOOL down = TRUE;
LLVoiceClient::getInstance()->middleMouseState(true);
LLVoiceClient::getInstance()->updateMouseState(LLMouseHandler::CLICK_MIDDLE, true);
handleAnyMouseClick(window,pos,mask,LLMouseHandler::CLICK_MIDDLE,down);
// Always handled as far as the OS is concerned.
@ -1267,17 +1273,47 @@ LLWindowCallbacks::DragNDropResult LLViewerWindow::handleDragNDrop( LLWindow *wi
return result;
}
BOOL LLViewerWindow::handleMiddleMouseUp(LLWindow *window, LLCoordGL pos, MASK mask)
{
BOOL down = FALSE;
LLVoiceClient::getInstance()->middleMouseState(false);
LLVoiceClient::getInstance()->updateMouseState(LLMouseHandler::CLICK_MIDDLE, false);
handleAnyMouseClick(window,pos,mask,LLMouseHandler::CLICK_MIDDLE,down);
// Always handled as far as the OS is concerned.
return TRUE;
}
BOOL LLViewerWindow::handleOtherMouse(LLWindow *window, LLCoordGL pos, MASK mask, S32 button, bool down)
{
switch (button)
{
case 4:
LLVoiceClient::getInstance()->updateMouseState(LLMouseHandler::CLICK_BUTTON4, down);
handleAnyMouseClick(window, pos, mask, LLMouseHandler::CLICK_BUTTON4, down);
break;
case 5:
LLVoiceClient::getInstance()->updateMouseState(LLMouseHandler::CLICK_BUTTON5, down);
handleAnyMouseClick(window, pos, mask, LLMouseHandler::CLICK_BUTTON5, down);
break;
default:
break;
}
// Always handled as far as the OS is concerned.
return TRUE;
}
BOOL LLViewerWindow::handleOtherMouseDown(LLWindow *window, LLCoordGL pos, MASK mask, S32 button)
{
return handleOtherMouse(window, pos, mask, button, TRUE);
}
BOOL LLViewerWindow::handleOtherMouseUp(LLWindow *window, LLCoordGL pos, MASK mask, S32 button)
{
return handleOtherMouse(window, pos, mask, button, FALSE);
}
// WARNING: this is potentially called multiple times per frame
void LLViewerWindow::handleMouseMove(LLWindow *window, LLCoordGL pos, MASK mask)
{
@ -3329,7 +3365,8 @@ void LLViewerWindow::updateUI()
LLRect screen_sticky_rect = mRootView->getLocalRect();
S32 local_x, local_y;
if (gSavedSettings.getBOOL("DebugShowXUINames"))
static LLCachedControl<bool> debug_show_xui_names(gSavedSettings, "DebugShowXUINames", 0);
if (debug_show_xui_names)
{
LLToolTip::Params params;

View File

@ -192,7 +192,10 @@ public:
/*virtual*/ BOOL handleRightMouseDown(LLWindow *window, LLCoordGL pos, MASK mask);
/*virtual*/ BOOL handleRightMouseUp(LLWindow *window, LLCoordGL pos, MASK mask);
/*virtual*/ BOOL handleMiddleMouseDown(LLWindow *window, LLCoordGL pos, MASK mask);
/*virtual*/ BOOL handleMiddleMouseUp(LLWindow *window, LLCoordGL pos, MASK mask);
/*virtual*/ BOOL handleMiddleMouseUp(LLWindow *window, LLCoordGL pos, MASK mask);
/*virtual*/ BOOL handleOtherMouseDown(LLWindow *window, LLCoordGL pos, MASK mask, S32 button);
/*virtual*/ BOOL handleOtherMouseUp(LLWindow *window, LLCoordGL pos, MASK mask, S32 button);
BOOL handleOtherMouse(LLWindow *window, LLCoordGL pos, MASK mask, S32 button, bool down);
/*virtual*/ LLWindowCallbacks::DragNDropResult handleDragNDrop(LLWindow *window, LLCoordGL pos, MASK mask, LLWindowCallbacks::DragNDropAction action, std::string data);
void handleMouseMove(LLWindow *window, LLCoordGL pos, MASK mask);
void handleMouseDragged(LLWindow *window, LLCoordGL pos, MASK mask);

View File

@ -78,6 +78,7 @@
#include "llselectmgr.h"
#include "llsprite.h"
#include "lltargetingmotion.h"
#include "lltoolmgr.h"
#include "lltoolmorph.h"
#include "llviewercamera.h"
#include "llviewertexlayer.h"
@ -1376,7 +1377,7 @@ void LLVOAvatar::calculateSpatialExtents(LLVector4a& newMin, LLVector4a& newMax)
++attachment_iter)
{
// Don't we need to look at children of attached_object as well?
const LLViewerObject* attached_object = (*attachment_iter);
const LLViewerObject* attached_object = attachment_iter->get();
if (attached_object && !attached_object->isHUDAttachment())
{
const LLVOVolume *vol = dynamic_cast<const LLVOVolume*>(attached_object);
@ -1799,7 +1800,7 @@ BOOL LLVOAvatar::lineSegmentIntersect(const LLVector4a& start, const LLVector4a&
attachment_iter != attachment->mAttachedObjects.end();
++attachment_iter)
{
LLViewerObject* attached_object = (*attachment_iter);
LLViewerObject* attached_object = attachment_iter->get();
if (attached_object && !attached_object->isDead() && attachment->getValid())
{
@ -1863,7 +1864,7 @@ LLViewerObject* LLVOAvatar::lineSegmentIntersectRiggedAttachments(const LLVector
attachment_iter != attachment->mAttachedObjects.end();
++attachment_iter)
{
LLViewerObject* attached_object = (*attachment_iter);
LLViewerObject* attached_object = attachment_iter->get();
if (attached_object->lineSegmentIntersect(start, local_end, face, pick_transparent, pick_rigged, face_hit, &local_intersection, tex_coord, normal, tangent))
{
@ -2687,7 +2688,7 @@ void LLVOAvatar::idleUpdateMisc(bool detailed_update)
attachment_iter != attachment->mAttachedObjects.end();
++attachment_iter)
{
LLViewerObject* attached_object = (*attachment_iter);
LLViewerObject* attached_object = attachment_iter->get();
BOOL visibleAttachment = visible || (attached_object &&
!(attached_object->mDrawable->getSpatialBridge() &&
attached_object->mDrawable->getSpatialBridge()->getRadius() < 2.0));
@ -4568,7 +4569,7 @@ void LLVOAvatar::updateVisibility()
attachment_iter != attachment->mAttachedObjects.end();
++attachment_iter)
{
if (LLViewerObject *attached_object = (*attachment_iter))
if (LLViewerObject *attached_object = attachment_iter->get())
{
if(attached_object->mDrawable->isVisible())
{
@ -5646,7 +5647,7 @@ BOOL LLVOAvatar::processSingleAnimationStateChange( const LLUUID& anim_id, BOOL
}
else
{
LL_WARNS() << "Failed to start motion!" << LL_ENDL;
LL_WARNS("Motion") << "Failed to start motion!" << LL_ENDL;
}
}
else //stop animation
@ -5753,13 +5754,13 @@ LLUUID LLVOAvatar::remapMotionID(const LLUUID& id)
//-----------------------------------------------------------------------------
BOOL LLVOAvatar::startMotion(const LLUUID& id, F32 time_offset)
{
LL_DEBUGS() << "motion requested " << id.asString() << " " << gAnimLibrary.animationName(id) << LL_ENDL;
LL_DEBUGS("Motion") << "motion requested " << id.asString() << " " << gAnimLibrary.animationName(id) << LL_ENDL;
LLUUID remap_id = remapMotionID(id);
if (remap_id != id)
{
LL_DEBUGS() << "motion resultant " << remap_id.asString() << " " << gAnimLibrary.animationName(remap_id) << LL_ENDL;
LL_DEBUGS("Motion") << "motion resultant " << remap_id.asString() << " " << gAnimLibrary.animationName(remap_id) << LL_ENDL;
}
if (isSelf() && remap_id == ANIM_AGENT_AWAY)
@ -5775,13 +5776,13 @@ BOOL LLVOAvatar::startMotion(const LLUUID& id, F32 time_offset)
//-----------------------------------------------------------------------------
BOOL LLVOAvatar::stopMotion(const LLUUID& id, BOOL stop_immediate)
{
LL_DEBUGS() << "motion requested " << id.asString() << " " << gAnimLibrary.animationName(id) << LL_ENDL;
LL_DEBUGS("Motion") << "Motion requested " << id.asString() << " " << gAnimLibrary.animationName(id) << LL_ENDL;
LLUUID remap_id = remapMotionID(id);
if (remap_id != id)
{
LL_DEBUGS() << "motion resultant " << remap_id.asString() << " " << gAnimLibrary.animationName(remap_id) << LL_ENDL;
LL_DEBUGS("Motion") << "motion resultant " << remap_id.asString() << " " << gAnimLibrary.animationName(remap_id) << LL_ENDL;
}
if (isSelf())
@ -5992,7 +5993,7 @@ void LLVOAvatar::rebuildAttachmentOverrides()
for (LLViewerJointAttachment::attachedobjs_vec_t::iterator at_it = attachment_pt->mAttachedObjects.begin();
at_it != attachment_pt->mAttachedObjects.end(); ++at_it)
{
LLViewerObject *vo = *at_it;
LLViewerObject *vo = at_it->get();
// Attached animated objects affect joints in their control
// avs, not the avs to which they are attached.
if (vo && !vo->isAnimatedObject())
@ -6043,7 +6044,7 @@ void LLVOAvatar::updateAttachmentOverrides()
for (LLViewerJointAttachment::attachedobjs_vec_t::iterator at_it = attachment_pt->mAttachedObjects.begin();
at_it != attachment_pt->mAttachedObjects.end(); ++at_it)
{
LLViewerObject *vo = *at_it;
LLViewerObject *vo = at_it->get();
// Attached animated objects affect joints in their control
// avs, not the avs to which they are attached.
if (vo && !vo->isAnimatedObject())
@ -7146,29 +7147,33 @@ void LLVOAvatar::lazyAttach()
for (U32 i = 0; i < mPendingAttachment.size(); i++)
{
LLPointer<LLViewerObject> cur_attachment = mPendingAttachment[i];
if (cur_attachment->mDrawable)
// Object might have died while we were waiting for drawable
if (!cur_attachment->isDead())
{
if (isSelf())
if (cur_attachment->mDrawable)
{
const LLUUID& item_id = cur_attachment->getAttachmentItemID();
LLViewerInventoryItem *item = gInventory.getItem(item_id);
LL_DEBUGS("Avatar") << "ATT attaching object "
<< (item ? item->getName() : "UNKNOWN") << " id " << item_id << LL_ENDL;
if (isSelf())
{
const LLUUID& item_id = cur_attachment->getAttachmentItemID();
LLViewerInventoryItem *item = gInventory.getItem(item_id);
LL_DEBUGS("Avatar") << "ATT attaching object "
<< (item ? item->getName() : "UNKNOWN") << " id " << item_id << LL_ENDL;
}
if (!attachObject(cur_attachment))
{ // Drop it
LL_WARNS() << "attachObject() failed for "
<< cur_attachment->getID()
<< " item " << cur_attachment->getAttachmentItemID()
<< LL_ENDL;
// MAINT-3312 backout
//still_pending.push_back(cur_attachment);
}
}
if (!attachObject(cur_attachment))
{ // Drop it
LL_WARNS() << "attachObject() failed for "
<< cur_attachment->getID()
<< " item " << cur_attachment->getAttachmentItemID()
<< LL_ENDL;
// MAINT-3312 backout
//still_pending.push_back(cur_attachment);
else
{
still_pending.push_back(cur_attachment);
}
}
else
{
still_pending.push_back(cur_attachment);
}
}
mPendingAttachment = still_pending;
@ -7188,7 +7193,7 @@ void LLVOAvatar::resetHUDAttachments()
attachment_iter != attachment->mAttachedObjects.end();
++attachment_iter)
{
const LLViewerObject* attached_object = (*attachment_iter);
const LLViewerObject* attached_object = attachment_iter->get();
if (attached_object && attached_object->mDrawable.notNull())
{
gPipeline.markMoved(attached_object->mDrawable);
@ -7320,6 +7325,19 @@ void LLVOAvatar::sitOnObject(LLViewerObject *sit_object)
{
gAgentCamera.changeCameraToMouselook();
}
if (gAgentCamera.getFocusOnAvatar() && LLToolMgr::getInstance()->inEdit())
{
LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstRootNode();
if (node && node->mValid)
{
LLViewerObject* root_object = node->getObject();
if (root_object == sit_object)
{
LLFloaterTools::sPreviousFocusOnAvatar = true;
}
}
}
}
if (mDrawable.isNull())
@ -7505,7 +7523,7 @@ LLViewerObject * LLVOAvatar::findAttachmentByID( const LLUUID & target_id ) cons
attachment_iter != attachment->mAttachedObjects.end();
++attachment_iter)
{
LLViewerObject *attached_object = (*attachment_iter);
LLViewerObject *attached_object = attachment_iter->get();
if (attached_object &&
attached_object->getID() == target_id)
{
@ -7927,7 +7945,7 @@ void LLVOAvatar::updateMeshVisibility()
attachment_iter != attachment->mAttachedObjects.end();
++attachment_iter)
{
LLViewerObject *objectp = (*attachment_iter);
LLViewerObject *objectp = attachment_iter->get();
if (objectp)
{
for (int face_index = 0; face_index < objectp->getNumTEs(); face_index++)
@ -8244,7 +8262,7 @@ void LLVOAvatar::updateMeshTextures()
attachment_iter != attachment->mAttachedObjects.end();
++attachment_iter)
{
LLViewerObject* attached_object = (*attachment_iter);
LLViewerObject* attached_object = attachment_iter->get();
if (attached_object && !attached_object->isDead())
{
attached_object->refreshBakeTexture();
@ -8482,7 +8500,7 @@ LLBBox LLVOAvatar::getHUDBBox() const
attachment_iter != attachment->mAttachedObjects.end();
++attachment_iter)
{
const LLViewerObject* attached_object = (*attachment_iter);
const LLViewerObject* attached_object = attachment_iter->get();
if (attached_object == NULL)
{
LL_WARNS() << "HUD attached object is NULL!" << LL_ENDL;
@ -9848,7 +9866,7 @@ void LLVOAvatar::getAssociatedVolumes(std::vector<LLVOVolume*>& volumes)
for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attach_iter = attachment->mAttachedObjects.begin();
attach_iter != attach_end; ++attach_iter)
{
LLViewerObject* attached_object = *attach_iter;
LLViewerObject* attached_object = attach_iter->get();
LLVOVolume *volume = dynamic_cast<LLVOVolume*>(attached_object);
if (volume)
{
@ -10366,7 +10384,7 @@ void LLVOAvatar::calculateUpdateRenderComplexity()
attachment_iter != attachment->mAttachedObjects.end();
++attachment_iter)
{
const LLViewerObject* attached_object = (*attachment_iter);
const LLViewerObject* attached_object = attachment_iter->get();
accountRenderComplexityForObject(attached_object, max_attachment_complexity,
textures, cost, hud_complexity_list);
}

Some files were not shown because too many files have changed in this diff Show More