Merge viewer-release 6.3.6 into viewwer-eep repo
commit
f61a5c4642
1
.hgtags
1
.hgtags
|
|
@ -556,3 +556,4 @@ 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
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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}")
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2418,7 +2418,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;
|
||||
}
|
||||
|
||||
|
|
@ -5272,7 +5272,7 @@ bool LLVolumeFace::cacheOptimize()
|
|||
|
||||
LLVCacheLRU cache;
|
||||
|
||||
if (mNumVertices < 3)
|
||||
if (mNumVertices < 3 || mNumIndices < 3)
|
||||
{ //nothing to do
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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";
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,6 +50,8 @@ public:
|
|||
CLICK_LEFT,
|
||||
CLICK_MIDDLE,
|
||||
CLICK_RIGHT,
|
||||
CLICK_BUTTON4,
|
||||
CLICK_BUTTON5,
|
||||
CLICK_DOUBLELEFT
|
||||
} EClickType;
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -207,7 +207,6 @@ set(viewer_SOURCE_FILES
|
|||
llfilteredwearablelist.cpp
|
||||
llfirstuse.cpp
|
||||
llflexibleobject.cpp
|
||||
llflickrconnect.cpp
|
||||
llfloaterabout.cpp
|
||||
llfloaterbvhpreview.cpp
|
||||
llfloaterauction.cpp
|
||||
|
|
@ -241,7 +240,6 @@ set(viewer_SOURCE_FILES
|
|||
llfloaterexperienceprofile.cpp
|
||||
llfloaterexperiences.cpp
|
||||
llfloaterfixedenvironment.cpp
|
||||
llfloaterflickr.cpp
|
||||
llfloaterfonttest.cpp
|
||||
llfloatergesture.cpp
|
||||
llfloatergodtools.cpp
|
||||
|
|
@ -315,7 +313,6 @@ set(viewer_SOURCE_FILES
|
|||
llfloatertos.cpp
|
||||
llfloatertoybox.cpp
|
||||
llfloatertranslationsettings.cpp
|
||||
llfloatertwitter.cpp
|
||||
llfloateruipreview.cpp
|
||||
llfloaterurlentry.cpp
|
||||
llfloatervoiceeffect.cpp
|
||||
|
|
@ -621,7 +618,6 @@ set(viewer_SOURCE_FILES
|
|||
lltransientdockablefloater.cpp
|
||||
lltransientfloatermgr.cpp
|
||||
lltranslate.cpp
|
||||
lltwitterconnect.cpp
|
||||
lluiavatar.cpp
|
||||
lluilistener.cpp
|
||||
lluploaddialog.cpp
|
||||
|
|
@ -832,7 +828,6 @@ set(viewer_HEADER_FILES
|
|||
llfilteredwearablelist.h
|
||||
llfirstuse.h
|
||||
llflexibleobject.h
|
||||
llflickrconnect.h
|
||||
llfloaterabout.h
|
||||
llfloaterbvhpreview.h
|
||||
llfloaterauction.h
|
||||
|
|
@ -866,7 +861,6 @@ set(viewer_HEADER_FILES
|
|||
llfloaterexperienceprofile.h
|
||||
llfloaterexperiences.h
|
||||
llfloaterfixedenvironment.h
|
||||
llfloaterflickr.h
|
||||
llfloaterfonttest.h
|
||||
llfloatergesture.h
|
||||
llfloatergodtools.h
|
||||
|
|
@ -943,7 +937,6 @@ set(viewer_HEADER_FILES
|
|||
llfloatertos.h
|
||||
llfloatertoybox.h
|
||||
llfloatertranslationsettings.h
|
||||
llfloatertwitter.h
|
||||
llfloateruipreview.h
|
||||
llfloaterurlentry.h
|
||||
llfloatervoiceeffect.h
|
||||
|
|
@ -1238,7 +1231,6 @@ set(viewer_HEADER_FILES
|
|||
lltransientdockablefloater.h
|
||||
lltransientfloatermgr.h
|
||||
lltranslate.h
|
||||
lltwitterconnect.h
|
||||
lluiconstants.h
|
||||
lluiavatar.h
|
||||
lluilistener.h
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -5326,7 +5326,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>
|
||||
|
|
@ -11285,6 +11285,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>
|
||||
|
|
@ -13247,6 +13258,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>
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -1321,7 +1321,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();
|
||||
|
|
@ -1385,7 +1385,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);
|
||||
|
|
|
|||
|
|
@ -2910,7 +2910,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);
|
||||
|
|
|
|||
|
|
@ -2131,6 +2131,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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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$
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
@ -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
|
||||
|
||||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
@ -1705,6 +1727,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");
|
||||
|
|
@ -2442,10 +2499,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 ///////////////////
|
||||
|
|
|
|||
|
|
@ -148,6 +148,7 @@ public:
|
|||
void onSelectSkin();
|
||||
void onClickSetKey();
|
||||
void setKey(KEY key);
|
||||
void setMouse(LLMouseHandler::EClickType click);
|
||||
void onClickSetMiddleMouse();
|
||||
void onClickSetSounds();
|
||||
void onClickEnablePopup();
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
@ -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
|
||||
|
||||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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())
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -4683,7 +4683,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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
@ -117,7 +117,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);
|
||||
|
|
@ -714,6 +746,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);
|
||||
|
|
@ -723,7 +787,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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -334,6 +334,9 @@ private:
|
|||
std::string mEmptyLookupMessage;
|
||||
|
||||
ESearchType mSearchType;
|
||||
|
||||
std::vector<std::string> mFilterTokens;
|
||||
std::string mExactToken;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 ¤t_zoom) const
|
||||
|
|
|
|||
|
|
@ -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 *);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
|
|
@ -746,6 +781,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();
|
||||
|
|
@ -813,10 +868,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;
|
||||
|
||||
|
|
@ -904,19 +967,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();
|
||||
|
|
@ -997,7 +1058,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();
|
||||
}
|
||||
|
|
@ -1022,6 +1088,7 @@ void LLSidepanelItemInfo::onCommitChanges(LLPointer<LLViewerInventoryItem> item)
|
|||
// prevents flashing in content tab and some duplicated request.
|
||||
object->dirtyInventory();
|
||||
}
|
||||
setPropertiesFieldsEnabled(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1050,7 +1117,6 @@ void LLSidepanelItemInfo::save()
|
|||
{
|
||||
onCommitName();
|
||||
onCommitDescription();
|
||||
onCommitPermissions();
|
||||
onCommitSaleInfo();
|
||||
onCommitSaleType();
|
||||
updatePermissions();
|
||||
updateSaleInfo();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -95,6 +95,7 @@ protected:
|
|||
|
||||
static void doClickAction(U8 click_action);
|
||||
void disableAll();
|
||||
void disablePermissions();
|
||||
|
||||
private:
|
||||
LLNameBox* mLabelGroupName; // group name
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -1615,7 +1615,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;
|
||||
|
|
@ -2350,7 +2357,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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
@ -1742,7 +1831,8 @@ void LLTextureCache::purgeTextures(bool validate)
|
|||
{
|
||||
std::string filename = getTextureFileName(entries[idx].mID);
|
||||
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 << filename << LL_ENDL;
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -147,7 +147,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
|
||||
|
|
@ -163,6 +163,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();
|
||||
|
|
@ -197,6 +198,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;
|
||||
|
|
@ -233,6 +239,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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -1092,7 +1092,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())
|
||||
{
|
||||
|
|
|
|||
|
|
@ -65,7 +65,6 @@
|
|||
#include "llfloaterexperiencepicker.h"
|
||||
#include "llfloaterevent.h"
|
||||
#include "llfloaterfixedenvironment.h"
|
||||
#include "llfloaterflickr.h"
|
||||
#include "llfloaterfonttest.h"
|
||||
#include "llfloatergesture.h"
|
||||
#include "llfloatergodtools.h"
|
||||
|
|
@ -131,7 +130,6 @@
|
|||
#include "llfloatertos.h"
|
||||
#include "llfloatertoybox.h"
|
||||
#include "llfloatertranslationsettings.h"
|
||||
#include "llfloatertwitter.h"
|
||||
#include "llfloateruipreview.h"
|
||||
#include "llfloatervoiceeffect.h"
|
||||
#include "llfloaterwebcontent.h"
|
||||
|
|
@ -354,11 +352,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();
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -6669,10 +6669,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;
|
||||
|
|
@ -6713,8 +6713,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;
|
||||
|
|
@ -6837,7 +6837,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());
|
||||
}
|
||||
}
|
||||
|
|
@ -6863,7 +6863,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());
|
||||
|
|
@ -6976,7 +6976,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
|
||||
|
|
@ -7372,7 +7372,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));
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
@ -4044,6 +4026,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();
|
||||
|
||||
|
|
@ -4056,8 +4040,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
|
||||
|
|
@ -4096,6 +4078,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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -5162,12 +5152,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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -2897,8 +2897,6 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames)
|
|||
capabilityNames.append("EstateChangeInfo");
|
||||
capabilityNames.append("EventQueueGet");
|
||||
capabilityNames.append("ExtEnvironment");
|
||||
capabilityNames.append("FlickrConnect");
|
||||
capabilityNames.append("TwitterConnect");
|
||||
|
||||
capabilityNames.append("FetchLib2");
|
||||
capabilityNames.append("FetchLibDescendents2");
|
||||
|
|
|
|||
|
|
@ -954,6 +954,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();
|
||||
|
|
@ -1131,7 +1137,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.
|
||||
|
|
@ -1283,17 +1289,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)
|
||||
{
|
||||
|
|
@ -3345,7 +3381,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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -125,7 +125,7 @@ LLVoiceClient::LLVoiceClient(LLPumpIO *pump)
|
|||
mPTTDirty(true),
|
||||
mPTT(true),
|
||||
mUsePTT(true),
|
||||
mPTTIsMiddleMouse(false),
|
||||
mPTTMouseButton(0),
|
||||
mPTTKey(0),
|
||||
mPTTIsToggle(false),
|
||||
mUserPTTState(false),
|
||||
|
|
@ -639,13 +639,22 @@ bool LLVoiceClient::getPTTIsToggle()
|
|||
|
||||
void LLVoiceClient::setPTTKey(std::string &key)
|
||||
{
|
||||
// Value is stored as text for readability
|
||||
if(key == "MiddleMouse")
|
||||
{
|
||||
mPTTIsMiddleMouse = true;
|
||||
mPTTMouseButton = LLMouseHandler::CLICK_MIDDLE;
|
||||
}
|
||||
else if(key == "MouseButton4")
|
||||
{
|
||||
mPTTMouseButton = LLMouseHandler::CLICK_BUTTON4;
|
||||
}
|
||||
else if (key == "MouseButton5")
|
||||
{
|
||||
mPTTMouseButton = LLMouseHandler::CLICK_BUTTON5;
|
||||
}
|
||||
else
|
||||
{
|
||||
mPTTIsMiddleMouse = false;
|
||||
mPTTMouseButton = 0;
|
||||
if(!LLKeyboard::keyFromString(key, &mPTTKey))
|
||||
{
|
||||
// If the call failed, don't match any key.
|
||||
|
|
@ -682,7 +691,7 @@ void LLVoiceClient::keyDown(KEY key, MASK mask)
|
|||
return;
|
||||
}
|
||||
|
||||
if (!mPTTIsMiddleMouse && LLAgent::isActionAllowed("speak") && (key == mPTTKey))
|
||||
if (mPTTMouseButton == 0 && LLAgent::isActionAllowed("speak") && (key == mPTTKey))
|
||||
{
|
||||
bool down = gKeyboard->getKeyDown(mPTTKey);
|
||||
if (down)
|
||||
|
|
@ -694,7 +703,7 @@ void LLVoiceClient::keyDown(KEY key, MASK mask)
|
|||
}
|
||||
void LLVoiceClient::keyUp(KEY key, MASK mask)
|
||||
{
|
||||
if (!mPTTIsMiddleMouse && (key == mPTTKey))
|
||||
if (mPTTMouseButton == 0 && (key == mPTTKey))
|
||||
{
|
||||
bool down = gKeyboard->getKeyDown(mPTTKey);
|
||||
if (!down)
|
||||
|
|
@ -703,9 +712,9 @@ void LLVoiceClient::keyUp(KEY key, MASK mask)
|
|||
}
|
||||
}
|
||||
}
|
||||
void LLVoiceClient::middleMouseState(bool down)
|
||||
void LLVoiceClient::updateMouseState(S32 click, bool down)
|
||||
{
|
||||
if(mPTTIsMiddleMouse && LLAgent::isActionAllowed("speak"))
|
||||
if(mPTTMouseButton == click && LLAgent::isActionAllowed("speak"))
|
||||
{
|
||||
inputUserControlState(down);
|
||||
}
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue