Merge branch 'master' into sunshine

Conflicts:
	indra/llimage/llimage.cpp
	indra/llui/llui.cpp
	indra/newview/llvoavatar.cpp
This commit is contained in:
Shyotl
2013-01-08 17:05:29 -06:00
1085 changed files with 11207 additions and 4376 deletions

View File

@@ -378,6 +378,14 @@
<boolean>true</boolean> <boolean>true</boolean>
</map> </map>
<key>WindLightRefresh</key>
<map>
<key>flavor</key>
<string>llsd</string>
<key>trusted-sender</key>
<boolean>true</boolean>
</map>
<key>ParcelVoiceInfo</key> <key>ParcelVoiceInfo</key>
<map> <map>
<key>flavor</key> <key>flavor</key>
@@ -386,7 +394,6 @@
<boolean>true</boolean> <boolean>true</boolean>
</map> </map>
<key>ParcelNavigateMedia</key> <key>ParcelNavigateMedia</key>
<map> <map>
<key>flavor</key> <key>flavor</key>

View File

@@ -17,15 +17,25 @@ find_library(FMODEX_LIBRARY
if (NOT FMODEX_LIBRARY) if (NOT FMODEX_LIBRARY)
set(FMODEX_SDK_DIR CACHE PATH "Path to the FMOD Ex SDK.") set(FMODEX_SDK_DIR CACHE PATH "Path to the FMOD Ex SDK.")
if (FMODEX_SDK_DIR) if (FMODEX_SDK_DIR)
find_library(FMODEX_LIBRARY if(WORD_SIZE EQUAL 32)
fmodex_vc fmodexL_vc fmodex fmodexL fmodex64 fmodexL64 find_library(FMODEX_LIBRARY
PATHS fmodex_vc fmodexL_vc fmodex fmodexL
${FMODEX_SDK_DIR}/api/lib PATHS
${FMODEX_SDK_DIR}/api ${FMODEX_SDK_DIR}/api/lib
${FMODEX_SDK_DIR}/lib ${FMODEX_SDK_DIR}/api
${FMODEX_SDK_DIR} ${FMODEX_SDK_DIR}/lib
) ${FMODEX_SDK_DIR}
)
elseif(WORD_SIZE EQUAL 64)
find_library(FMODEX_LIBRARY
fmodex64 fmodexL64
PATHS
${FMODEX_SDK_DIR}/api/lib
${FMODEX_SDK_DIR}/api
${FMODEX_SDK_DIR}/lib
${FMODEX_SDK_DIR}
)
endif(WORD_SIZE EQUAL 32)
endif(FMODEX_SDK_DIR) endif(FMODEX_SDK_DIR)
if(WINDOWS AND NOT FMODEX_LIBRARY) if(WINDOWS AND NOT FMODEX_LIBRARY)
set(FMODEX_PROG_DIR "$ENV{PROGRAMFILES}/FMOD SoundSystem/FMOD Programmers API Windows") set(FMODEX_PROG_DIR "$ENV{PROGRAMFILES}/FMOD SoundSystem/FMOD Programmers API Windows")

View File

@@ -4,9 +4,9 @@ include(Prebuilt)
set(OpenSSL_FIND_QUIETLY ON) set(OpenSSL_FIND_QUIETLY ON)
set(OpenSSL_FIND_REQUIRED ON) set(OpenSSL_FIND_REQUIRED ON)
if (STANDALONE) if (STANDALONE OR USE_SYSTEM_OPENSSL)
include(FindOpenSSL) include(FindOpenSSL)
else (STANDALONE) else (STANDALONE OR USE_SYSTEM_OPENSSL)
use_prebuilt_binary(openSSL) use_prebuilt_binary(openSSL)
if (WINDOWS) if (WINDOWS)
set(OPENSSL_LIBRARIES ssleay32 libeay32) set(OPENSSL_LIBRARIES ssleay32 libeay32)
@@ -14,7 +14,7 @@ else (STANDALONE)
set(OPENSSL_LIBRARIES ssl) set(OPENSSL_LIBRARIES ssl)
endif (WINDOWS) endif (WINDOWS)
set(OPENSSL_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include) set(OPENSSL_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include)
endif (STANDALONE) endif (STANDALONE OR USE_SYSTEM_OPENSSL)
if (LINUX OR DARWIN) if (LINUX OR DARWIN)
set(CRYPTO_LIBRARIES crypto) set(CRYPTO_LIBRARIES crypto)

View File

@@ -236,8 +236,9 @@ void stop_recording_backtraces(void)
channel_ct backtrace DDCN("BACKTRACE"); //!< This debug channel is used for backtraces. channel_ct backtrace DDCN("BACKTRACE"); //!< This debug channel is used for backtraces.
channel_ct statemachine DDCN("STATEMACHINE"); //!< This debug channel is used for output related to class AIStateMachine. channel_ct statemachine DDCN("STATEMACHINE"); //!< This debug channel is used for output related to class AIStateMachine.
channel_ct caps DDCN("CAPS"); //!< This debug channel is used for output related to Capabilities. channel_ct caps DDCN("CAPS"); //!< This debug channel is used for output related to Capabilities.
channel_ct curl DDCN("CURL"); //!< This debug channel is used for output related to Curl. channel_ct curl DDCN("CURL"); //!< This debug channel is used for output related to AICurl.
channel_ct curlio DDCN("CURLIO"); //!< This debug channel is used to print debug output of libcurl. channel_ct curlio DDCN("CURLIO"); //!< This debug channel is used to print debug output of libcurl. This includes all HTTP network traffic.
channel_ct curltr DDCN("CURLTR"); //!< This debug channel is used to print libcurl API calls.
} // namespace dc } // namespace dc
} // namespace DEBUGCHANNELS } // namespace DEBUGCHANNELS

View File

@@ -207,6 +207,7 @@ extern CWD_API channel_ct statemachine;
extern CWD_API channel_ct caps; extern CWD_API channel_ct caps;
extern CWD_API channel_ct curl; extern CWD_API channel_ct curl;
extern CWD_API channel_ct curlio; extern CWD_API channel_ct curlio;
extern CWD_API channel_ct curltr;
#endif #endif

View File

@@ -256,11 +256,6 @@ U64 totalTime()
// No wrapping, we're all okay. // No wrapping, we're all okay.
gTotalTimeClockCount += current_clock_count - gLastTotalTimeClockCount; gTotalTimeClockCount += current_clock_count - gLastTotalTimeClockCount;
} }
else if((gLastTotalTimeClockCount - current_clock_count)<0xFFFF)
{
//clock is glitching and walking backwards - ignore it
gTotalTimeClockCount = gLastTotalTimeClockCount;
}
else else
{ {
// We've wrapped. Compensate correctly // We've wrapped. Compensate correctly

View File

@@ -210,6 +210,19 @@ U8* LLImageBase::allocateData(S32 size)
// virtual // virtual
U8* LLImageBase::reallocateData(S32 size) U8* LLImageBase::reallocateData(S32 size)
{ {
if (size == -1)
{
size = mWidth * mHeight * mComponents;
if (size <= 0)
{
llerrs << llformat("LLImageBase::reallocateData called with bad dimensions: %dx%dx%d", mWidth, mHeight, (S32)mComponents) << llendl;
}
}
else if (size <= 0 || (size > 4096 * 4096 * 16 && !mAllowOverSize))
{
llerrs << "LLImageBase::reallocateData: bad size: " << size << llendl;
}
if(mData && (mDataSize == size)) if(mData && (mDataSize == size))
return mData; return mData;
@@ -304,6 +317,32 @@ LLImageRaw::LLImageRaw(U8 *data, U16 width, U16 height, S8 components)
++sRawImageCount; ++sRawImageCount;
} }
LLImageRaw::LLImageRaw(LLImageRaw const* src, U16 width, U16 height, U16 crop_offset, bool crop_vertically) : mCacheEntries(0)
{
mMemType = LLMemType::MTYPE_IMAGERAW;
llassert_always(src);
S8 const components = src->getComponents();
U8 const* const data = src->getData();
if (allocateDataSize(width, height, components))
{
if (crop_vertically)
{
llassert_always(width == src->getWidth());
memcpy(getData(), data + width * crop_offset * components, width * height * components);
}
else
{
llassert_always(height == src->getHeight());
U16 const src_width = src->getWidth();
for (U16 row = 0; row < height; ++row)
{
memcpy(getData() + width * row * components, data + (src_width * row + crop_offset) * components, width * components);
}
}
}
++sRawImageCount;
}
/*LLImageRaw::LLImageRaw(const std::string& filename, bool j2c_lowest_mip_only) /*LLImageRaw::LLImageRaw(const std::string& filename, bool j2c_lowest_mip_only)
: LLImageBase(), mCacheEntries(0) : LLImageBase(), mCacheEntries(0)
{ {
@@ -522,7 +561,7 @@ void LLImageRaw::contractToPowerOfTwo(S32 max_dim, BOOL scale_image)
scale( new_width, new_height, scale_image ); scale( new_width, new_height, scale_image );
} }
void LLImageRaw::biasedScaleToPowerOfTwo(S32 max_dim) void LLImageRaw::biasedScaleToPowerOfTwo(S32 target_width, S32 target_height, S32 max_dim)
{ {
// Strong bias towards rounding down (to save bandwidth) // Strong bias towards rounding down (to save bandwidth)
// No bias would mean THRESHOLD == 1.5f; // No bias would mean THRESHOLD == 1.5f;
@@ -531,22 +570,22 @@ void LLImageRaw::biasedScaleToPowerOfTwo(S32 max_dim)
// Find new sizes // Find new sizes
S32 larger_w = max_dim; // 2^n >= mWidth S32 larger_w = max_dim; // 2^n >= mWidth
S32 smaller_w = max_dim; // 2^(n-1) <= mWidth S32 smaller_w = max_dim; // 2^(n-1) <= mWidth
while( (smaller_w > getWidth()) && (smaller_w > MIN_IMAGE_SIZE) ) while( (smaller_w > target_width) && (smaller_w > MIN_IMAGE_SIZE) )
{ {
larger_w = smaller_w; larger_w = smaller_w;
smaller_w >>= 1; smaller_w >>= 1;
} }
S32 new_width = ( (F32)getWidth() / smaller_w > THRESHOLD ) ? larger_w : smaller_w; S32 new_width = ( (F32)target_width / smaller_w > THRESHOLD ) ? larger_w : smaller_w;
S32 larger_h = max_dim; // 2^m >= mHeight S32 larger_h = max_dim; // 2^m >= mHeight
S32 smaller_h = max_dim; // 2^(m-1) <= mHeight S32 smaller_h = max_dim; // 2^(m-1) <= mHeight
while( (smaller_h > getHeight()) && (smaller_h > MIN_IMAGE_SIZE) ) while( (smaller_h > target_height) && (smaller_h > MIN_IMAGE_SIZE) )
{ {
larger_h = smaller_h; larger_h = smaller_h;
smaller_h >>= 1; smaller_h >>= 1;
} }
S32 new_height = ( (F32)getHeight() / smaller_h > THRESHOLD ) ? larger_h : smaller_h; S32 new_height = ( (F32)target_height / smaller_h > THRESHOLD ) ? larger_h : smaller_h;
scale( new_width, new_height ); scale( new_width, new_height );
@@ -951,75 +990,66 @@ BOOL LLImageRaw::scale( S32 new_width, S32 new_height, BOOL scale_image_data )
return TRUE; // Nothing to do. return TRUE; // Nothing to do.
} }
// Reallocate the data buffer. U8* old_buffer = NULL;
U8* new_buffer;
S32 const old_width_bytes = old_width * getComponents();
S32 const new_width_bytes = new_width * getComponents();
S32 const min_height = llmin(old_height, new_height);
S32 const min_width_bytes = llmin(old_width_bytes, new_width_bytes);
if (scale_image_data) if (scale_image_data)
{ {
S32 temp_data_size = old_width * new_height * getComponents(); if (new_height != old_height)
llassert_always(temp_data_size > 0);
try
{ {
std::vector<U8> temp_buffer(temp_data_size); // Resize vertically.
old_buffer = LLImageBase::release();
// Vertical new_buffer = allocateDataSize(old_width, new_height, getComponents());
for( S32 col = 0; col < old_width; col++ ) for (S32 col = 0; col < old_width; ++col)
{ {
copyLineScaled( getData() + (getComponents() * col), &temp_buffer[0] + (getComponents() * col), old_height, new_height, old_width, old_width ); copyLineScaled(old_buffer + getComponents() * col, new_buffer + getComponents() * col, old_height, new_height, old_width, old_width);
}
LLImageBase::deleteData(old_buffer);
} }
if (new_width != old_width)
deleteData();
U8* new_buffer = allocateDataSize(new_width, new_height, getComponents());
// Horizontal
for( S32 row = 0; row < new_height; row++ )
{ {
copyLineScaled( &temp_buffer[0] + (getComponents() * old_width * row), new_buffer + (getComponents() * new_width * row), old_width, new_width, 1, 1 ); // Resize horizontally.
} old_buffer = LLImageBase::release();
} new_buffer = allocateDataSize(new_width, new_height, getComponents());
catch(std::bad_alloc) for (S32 row = 0; row < new_height; ++row)
{ {
llerrs << "Out of memory in LLImageRaw::scale()" << llendl; copyLineScaled(old_buffer + old_width_bytes * row, new_buffer + new_width_bytes * row, old_width, new_width, 1, 1);
}
LLImageBase::deleteData(old_buffer);
} }
} }
else else
{ {
// copy out existing image data if (new_width == old_width)
S32 temp_data_size = old_width * old_height * getComponents();
try
{ {
std::vector<U8> temp_buffer(temp_data_size); setSize(new_width, new_height, getComponents());
memcpy(&temp_buffer[0], getData(), temp_data_size); new_buffer = reallocateData();
}
// allocate new image data, will delete old data else
U8* new_buffer = allocateDataSize(new_width, new_height, getComponents());
for( S32 row = 0; row < new_height; row++ )
{ {
if (row < old_height) old_buffer = LLImageBase::release();
new_buffer = allocateDataSize(new_width, new_height, getComponents());
for (S32 row = 0; row < min_height; ++row)
{ {
memcpy(new_buffer + (new_width * row * getComponents()), &temp_buffer[0] + (old_width * row * getComponents()), getComponents() * llmin(old_width, new_width)); memcpy(new_buffer + row * new_width_bytes, old_buffer + row * old_width_bytes, min_width_bytes);
if (old_width < new_width) if (new_width_bytes > old_width_bytes)
{ {
// pad out rest of row with black // Pad out rest of row with black.
memset(new_buffer + (getComponents() * ((new_width * row) + old_width)), 0, getComponents() * (new_width - old_width)); memset(new_buffer + new_width_bytes * row + old_width_bytes, 0, new_width_bytes - old_width_bytes);
} }
} }
else LLImageBase::deleteData(old_buffer);
{
// pad remaining rows with black
memset(new_buffer + (new_width * row * getComponents()), 0, new_width * getComponents());
}
} }
} if (new_height > old_height)
catch(std::bad_alloc)
{ {
llwarns << "Out of memory in LLImageRaw::scale: old (w, h, c) = (" << old_width << ", " << old_height << ", " << (S32)getComponents() << // Pad remaining rows with black.
") ; new (w, h, c) = (" << new_width << ", " << new_height << ", " << (S32)getComponents() << ")" << llendl; memset(new_buffer + new_width_bytes * min_height, 0, new_width_bytes * (new_height - old_height));
return FALSE ;
} }
} }
return TRUE ; return TRUE ;
} }

View File

@@ -114,6 +114,8 @@ public:
virtual void deleteData(); virtual void deleteData();
virtual U8* allocateData(S32 size = -1); virtual U8* allocateData(S32 size = -1);
virtual U8* reallocateData(S32 size = -1); virtual U8* reallocateData(S32 size = -1);
static void deleteData(U8* data) { FREE_MEM(sPrivatePoolp, data); }
U8* release() { U8* data = mData; mData = NULL; mDataSize = 0; return data; } // Same as deleteData(), but returns old data. Call deleteData(old_data) to free it.
virtual void dump(); virtual void dump();
virtual void sanityCheck(); virtual void sanityCheck();
@@ -175,12 +177,13 @@ public:
LLImageRaw(); LLImageRaw();
LLImageRaw(U16 width, U16 height, S8 components); LLImageRaw(U16 width, U16 height, S8 components);
LLImageRaw(U8 *data, U16 width, U16 height, S8 components); LLImageRaw(U8 *data, U16 width, U16 height, S8 components);
LLImageRaw(LLImageRaw const* src, U16 width, U16 height, U16 crop_offset, bool crop_vertically);
// Construct using createFromFile (used by tools) // Construct using createFromFile (used by tools)
//LLImageRaw(const std::string& filename, bool j2c_lowest_mip_only = false); //LLImageRaw(const std::string& filename, bool j2c_lowest_mip_only = false);
/*virtual*/ void deleteData(); /*virtual*/ void deleteData();
/*virtual*/ U8* allocateData(S32 size = -1); /*virtual*/ U8* allocateData(S32 size = -1);
/*virtual*/ U8* reallocateData(S32 size); /*virtual*/ U8* reallocateData(S32 size = -1);
BOOL resize(U16 width, U16 height, S8 components); BOOL resize(U16 width, U16 height, S8 components);
@@ -194,7 +197,8 @@ public:
void expandToPowerOfTwo(S32 max_dim = MAX_IMAGE_SIZE, BOOL scale_image = TRUE); void expandToPowerOfTwo(S32 max_dim = MAX_IMAGE_SIZE, BOOL scale_image = TRUE);
void contractToPowerOfTwo(S32 max_dim = MAX_IMAGE_SIZE, BOOL scale_image = TRUE); void contractToPowerOfTwo(S32 max_dim = MAX_IMAGE_SIZE, BOOL scale_image = TRUE);
void biasedScaleToPowerOfTwo(S32 max_dim = MAX_IMAGE_SIZE); void biasedScaleToPowerOfTwo(S32 target_width, S32 target_height, S32 max_dim = MAX_IMAGE_SIZE);
void biasedScaleToPowerOfTwo(S32 max_dim = MAX_IMAGE_SIZE) { biasedScaleToPowerOfTwo(getWidth(), getHeight(), max_dim); }
BOOL scale( S32 new_width, S32 new_height, BOOL scale_image = TRUE ); BOOL scale( S32 new_width, S32 new_height, BOOL scale_image = TRUE );
//BOOL scaleDownWithoutBlending( S32 new_width, S32 new_height) ; //BOOL scaleDownWithoutBlending( S32 new_width, S32 new_height) ;
@@ -287,7 +291,7 @@ public:
// LLImageBase // LLImageBase
/*virtual*/ void deleteData(); /*virtual*/ void deleteData();
/*virtual*/ U8* allocateData(S32 size = -1); /*virtual*/ U8* allocateData(S32 size = -1);
/*virtual*/ U8* reallocateData(S32 size); /*virtual*/ U8* reallocateData(S32 size = -1);
/*virtual*/ void dump(); /*virtual*/ void dump();
/*virtual*/ void sanityCheck(); /*virtual*/ void sanityCheck();

View File

@@ -545,6 +545,9 @@ void CurlEasyHandle::handle_easy_error(CURLcode code)
// Throws AICurlNoEasyHandle. // Throws AICurlNoEasyHandle.
CurlEasyHandle::CurlEasyHandle(void) : mActiveMultiHandle(NULL), mErrorBuffer(NULL), mQueuedForRemoval(false) CurlEasyHandle::CurlEasyHandle(void) : mActiveMultiHandle(NULL), mErrorBuffer(NULL), mQueuedForRemoval(false)
#ifdef DEBUG_CURLIO
, mDebug(false)
#endif
#ifdef SHOW_ASSERT #ifdef SHOW_ASSERT
, mRemovedPerCommand(true) , mRemovedPerCommand(true)
#endif #endif
@@ -588,6 +591,12 @@ CurlEasyHandle::~CurlEasyHandle()
llassert(!mActiveMultiHandle); llassert(!mActiveMultiHandle);
curl_easy_cleanup(mEasyHandle); curl_easy_cleanup(mEasyHandle);
Stats::easy_cleanup_calls++; Stats::easy_cleanup_calls++;
#ifdef DEBUG_CURLIO
if (mDebug)
{
debug_curl_remove_easy(mEasyHandle);
}
#endif
} }
//static //static
@@ -760,17 +769,17 @@ void CurlEasyRequest::setoptString(CURLoption option, std::string const& value)
setopt(option, value.c_str()); setopt(option, value.c_str());
} }
void CurlEasyRequest::setPost(AIPostFieldPtr const& postdata, U32 size) void CurlEasyRequest::setPost(AIPostFieldPtr const& postdata, U32 size, bool keepalive)
{ {
llassert_always(postdata->data()); llassert_always(postdata->data());
DoutCurl("POST size is " << size << " bytes: \"" << libcwd::buf2str(postdata->data(), size) << "\"."); DoutCurl("POST size is " << size << " bytes: \"" << libcwd::buf2str(postdata->data(), size) << "\".");
setPostField(postdata); // Make sure the data stays around until we don't need it anymore. setPostField(postdata); // Make sure the data stays around until we don't need it anymore.
setPost_raw(size, postdata->data()); setPost_raw(size, postdata->data(), keepalive);
} }
void CurlEasyRequest::setPost_raw(U32 size, char const* data) void CurlEasyRequest::setPost_raw(U32 size, char const* data, bool keepalive)
{ {
if (!data) if (!data)
{ {
@@ -780,7 +789,7 @@ void CurlEasyRequest::setPost_raw(U32 size, char const* data)
// The server never replies with 100-continue, so suppress the "Expect: 100-continue" header that libcurl adds by default. // The server never replies with 100-continue, so suppress the "Expect: 100-continue" header that libcurl adds by default.
addHeader("Expect:"); addHeader("Expect:");
if (size > 0) if (size > 0 && keepalive)
{ {
addHeader("Connection: keep-alive"); addHeader("Connection: keep-alive");
addHeader("Keep-alive: 300"); addHeader("Keep-alive: 300");
@@ -1005,6 +1014,8 @@ CURLcode CurlEasyRequest::curlCtxCallback(CURL* curl, void* sslctx, void* parm)
options |= SSL_OP_NO_TLSv1_1; options |= SSL_OP_NO_TLSv1_1;
} }
#else #else
// This is expected when you compile against the headers of a version < 1.0.1 and then link at runtime with version >= 1.0.1.
// Don't do that.
llassert_always(!need_renegotiation_hack); llassert_always(!need_renegotiation_hack);
#endif #endif
SSL_CTX_set_options(ctx, options); SSL_CTX_set_options(ctx, options);
@@ -1225,6 +1236,20 @@ void CurlEasyRequest::removed_from_multi_handle(AICurlEasyRequest_wat& curl_easy
mHandleEventsTarget->removed_from_multi_handle(curl_easy_request_w); mHandleEventsTarget->removed_from_multi_handle(curl_easy_request_w);
} }
void CurlEasyRequest::bad_file_descriptor(AICurlEasyRequest_wat& curl_easy_request_w)
{
if (mHandleEventsTarget)
mHandleEventsTarget->bad_file_descriptor(curl_easy_request_w);
}
#ifdef SHOW_ASSERT
void CurlEasyRequest::queued_for_removal(AICurlEasyRequest_wat& curl_easy_request_w)
{
if (mHandleEventsTarget)
mHandleEventsTarget->queued_for_removal(curl_easy_request_w);
}
#endif
PerHostRequestQueuePtr CurlEasyRequest::getPerHostPtr(void) PerHostRequestQueuePtr CurlEasyRequest::getPerHostPtr(void)
{ {
if (!mPerHostPtr) if (!mPerHostPtr)
@@ -1288,7 +1313,17 @@ void BufferedCurlEasyRequest::timed_out(void)
mResponder->finished(CURLE_OK, HTTP_INTERNAL_ERROR, "Request timeout, aborted.", sChannels, mOutput); mResponder->finished(CURLE_OK, HTTP_INTERNAL_ERROR, "Request timeout, aborted.", sChannels, mOutput);
if (mResponder->needsHeaders()) if (mResponder->needsHeaders())
{ {
send_buffer_events_to(NULL); // Revoke buffer events: we sent them to the responder. send_buffer_events_to(NULL); // Revoke buffer events: we send them to the responder.
}
mResponder = NULL;
}
void BufferedCurlEasyRequest::bad_socket(void)
{
mResponder->finished(CURLE_OK, HTTP_INTERNAL_ERROR, "File descriptor went bad! Aborted.", sChannels, mOutput);
if (mResponder->needsHeaders())
{
send_buffer_events_to(NULL); // Revoke buffer events: we send them to the responder.
} }
mResponder = NULL; mResponder = NULL;
} }
@@ -1408,3 +1443,18 @@ CurlMultiHandle::~CurlMultiHandle()
} }
} // namespace AICurlPrivate } // namespace AICurlPrivate
#if LL_LINUX
extern "C" {
// Keep linker happy.
const SSL_METHOD *SSLv2_client_method(void)
{
// Never used.
llassert_always(false);
return NULL;
}
}
#endif

View File

@@ -208,6 +208,10 @@ struct AICurlEasyHandleEvents {
virtual void added_to_multi_handle(AICurlEasyRequest_wat& curl_easy_request_w) = 0; virtual void added_to_multi_handle(AICurlEasyRequest_wat& curl_easy_request_w) = 0;
virtual void finished(AICurlEasyRequest_wat& curl_easy_request_w) = 0; virtual void finished(AICurlEasyRequest_wat& curl_easy_request_w) = 0;
virtual void removed_from_multi_handle(AICurlEasyRequest_wat& curl_easy_request_w) = 0; virtual void removed_from_multi_handle(AICurlEasyRequest_wat& curl_easy_request_w) = 0;
virtual void bad_file_descriptor(AICurlEasyRequest_wat& curl_easy_request_w) = 0;
#ifdef SHOW_ASSERT
virtual void queued_for_removal(AICurlEasyRequest_wat& curl_easy_request_w) = 0;
#endif
// Avoid compiler warning. // Avoid compiler warning.
virtual ~AICurlEasyHandleEvents() { } virtual ~AICurlEasyHandleEvents() { }
}; };
@@ -271,6 +275,11 @@ class AICurlEasyRequest {
// Queue a command to remove this request from the multi session (or cancel a queued command to add it). // Queue a command to remove this request from the multi session (or cancel a queued command to add it).
void removeRequest(void); void removeRequest(void);
#ifdef DEBUG_CURLIO
// Turn on/off debug output.
void debug(bool debug) { AICurlEasyRequest_wat(*mBufferedCurlEasyRequest)->debug(debug); }
#endif
private: private:
// The actual pointer to the ThreadSafeBufferedCurlEasyRequest instance. // The actual pointer to the ThreadSafeBufferedCurlEasyRequest instance.
AICurlPrivate::BufferedCurlEasyRequestPtr mBufferedCurlEasyRequest; AICurlPrivate::BufferedCurlEasyRequestPtr mBufferedCurlEasyRequest;

View File

@@ -40,7 +40,8 @@ enum curleasyrequeststatemachine_state_type {
AICurlEasyRequestStateMachine_timedOut, // This must be smaller than the rest, so they always overrule. AICurlEasyRequestStateMachine_timedOut, // This must be smaller than the rest, so they always overrule.
AICurlEasyRequestStateMachine_finished, AICurlEasyRequestStateMachine_finished,
AICurlEasyRequestStateMachine_removed, // The removed states must be largest two, so they are never ignored. AICurlEasyRequestStateMachine_removed, // The removed states must be largest two, so they are never ignored.
AICurlEasyRequestStateMachine_removed_after_finished AICurlEasyRequestStateMachine_removed_after_finished,
AICurlEasyRequestStateMachine_bad_file_descriptor
}; };
char const* AICurlEasyRequestStateMachine::state_str_impl(state_type run_state) const char const* AICurlEasyRequestStateMachine::state_str_impl(state_type run_state) const
@@ -54,6 +55,7 @@ char const* AICurlEasyRequestStateMachine::state_str_impl(state_type run_state)
AI_CASE_RETURN(AICurlEasyRequestStateMachine_finished); AI_CASE_RETURN(AICurlEasyRequestStateMachine_finished);
AI_CASE_RETURN(AICurlEasyRequestStateMachine_removed); AI_CASE_RETURN(AICurlEasyRequestStateMachine_removed);
AI_CASE_RETURN(AICurlEasyRequestStateMachine_removed_after_finished); AI_CASE_RETURN(AICurlEasyRequestStateMachine_removed_after_finished);
AI_CASE_RETURN(AICurlEasyRequestStateMachine_bad_file_descriptor);
} }
return "UNKNOWN STATE"; return "UNKNOWN STATE";
} }
@@ -94,6 +96,24 @@ void AICurlEasyRequestStateMachine::removed_from_multi_handle(AICurlEasyRequest_
set_state(mFinished ? AICurlEasyRequestStateMachine_removed_after_finished : AICurlEasyRequestStateMachine_removed); set_state(mFinished ? AICurlEasyRequestStateMachine_removed_after_finished : AICurlEasyRequestStateMachine_removed);
} }
// CURL-THREAD
void AICurlEasyRequestStateMachine::bad_file_descriptor(AICurlEasyRequest_wat&)
{
if (!mFinished)
{
mFinished = true;
set_state(AICurlEasyRequestStateMachine_bad_file_descriptor);
}
}
#ifdef SHOW_ASSERT
// CURL-THREAD
void AICurlEasyRequestStateMachine::queued_for_removal(AICurlEasyRequest_wat&)
{
llassert(mFinished || mTimedOut); // See AICurlEasyRequestStateMachine::removed_from_multi_handle
}
#endif
void AICurlEasyRequestStateMachine::multiplex_impl(void) void AICurlEasyRequestStateMachine::multiplex_impl(void)
{ {
mSetStateLock.lock(); mSetStateLock.lock();
@@ -207,6 +227,11 @@ void AICurlEasyRequestStateMachine::multiplex_impl(void)
break; break;
} }
case AICurlEasyRequestStateMachine_bad_file_descriptor:
{
AICurlEasyRequest_wat(*mCurlEasyRequest)->bad_socket();
abort();
}
} }
} }

View File

@@ -81,6 +81,14 @@ class AICurlEasyRequestStateMachine : public AIStateMachine, public AICurlEasyHa
// Called after this curl easy handle was removed from a multi handle. // Called after this curl easy handle was removed from a multi handle.
/*virtual*/ void removed_from_multi_handle(AICurlEasyRequest_wat&); /*virtual*/ void removed_from_multi_handle(AICurlEasyRequest_wat&);
// Called when the curl thread detected that the socket of this handle has become unusable.
/*virtual*/ void bad_file_descriptor(AICurlEasyRequest_wat&);
#ifdef SHOW_ASSERT
// Called when a command was added to remove this easy handle.
/*virtual*/ void queued_for_removal(AICurlEasyRequest_wat&);
#endif
protected: protected:
// AIStateMachine implementations. // AIStateMachine implementations.

View File

@@ -201,12 +201,19 @@ class CurlEasyHandle : public boost::noncopyable, protected AICurlEasyHandleEven
// In case it's added after being removed. // In case it's added after being removed.
void add_queued(void) { mQueuedForRemoval = false; } void add_queued(void) { mQueuedForRemoval = false; }
#ifdef DEBUG_CURLIO
void debug(bool debug) { if (mDebug) debug_curl_remove_easy(mEasyHandle); if (debug) debug_curl_add_easy(mEasyHandle); mDebug = debug; }
#endif
private: private:
CURL* mEasyHandle; CURL* mEasyHandle;
CURLM* mActiveMultiHandle; CURLM* mActiveMultiHandle;
mutable char* mErrorBuffer; mutable char* mErrorBuffer;
AIPostFieldPtr mPostField; // This keeps the POSTFIELD data alive for as long as the easy handle exists. AIPostFieldPtr mPostField; // This keeps the POSTFIELD data alive for as long as the easy handle exists.
bool mQueuedForRemoval; // Set if the easy handle is (probably) added to the multi handle, but is queued for removal. bool mQueuedForRemoval; // Set if the easy handle is (probably) added to the multi handle, but is queued for removal.
#ifdef DEBUG_CURLIO
bool mDebug;
#endif
#ifdef SHOW_ASSERT #ifdef SHOW_ASSERT
public: public:
bool mRemovedPerCommand; // Set if mActiveMultiHandle was reset as per command from the main thread. bool mRemovedPerCommand; // Set if mActiveMultiHandle was reset as per command from the main thread.
@@ -270,11 +277,11 @@ class CurlEasyHandle : public boost::noncopyable, protected AICurlEasyHandleEven
// and the CurlEasyRequest destructed. // and the CurlEasyRequest destructed.
class CurlEasyRequest : public CurlEasyHandle { class CurlEasyRequest : public CurlEasyHandle {
private: private:
void setPost_raw(U32 size, char const* data); void setPost_raw(U32 size, char const* data, bool keepalive);
public: public:
void setPost(U32 size) { setPost_raw(size, NULL); } void setPost(U32 size, bool keepalive = true) { setPost_raw(size, NULL, keepalive); }
void setPost(AIPostFieldPtr const& postdata, U32 size); void setPost(AIPostFieldPtr const& postdata, U32 size, bool keepalive = true);
void setPost(char const* data, U32 size) { setPost(new AIPostField(data), size); } void setPost(char const* data, U32 size, bool keepalive = true) { setPost(new AIPostField(data), size, keepalive); }
void setoptString(CURLoption option, std::string const& value); void setoptString(CURLoption option, std::string const& value);
void addHeader(char const* str); void addHeader(char const* str);
void addHeaders(AIHTTPHeaders const& headers); void addHeaders(AIHTTPHeaders const& headers);
@@ -413,6 +420,11 @@ class CurlEasyRequest : public CurlEasyHandle {
/*virtual*/ void added_to_multi_handle(AICurlEasyRequest_wat& curl_easy_request_w); /*virtual*/ void added_to_multi_handle(AICurlEasyRequest_wat& curl_easy_request_w);
/*virtual*/ void finished(AICurlEasyRequest_wat& curl_easy_request_w); /*virtual*/ void finished(AICurlEasyRequest_wat& curl_easy_request_w);
/*virtual*/ void removed_from_multi_handle(AICurlEasyRequest_wat& curl_easy_request_w); /*virtual*/ void removed_from_multi_handle(AICurlEasyRequest_wat& curl_easy_request_w);
public:
/*virtual*/ void bad_file_descriptor(AICurlEasyRequest_wat& curl_easy_request_w);
#ifdef SHOW_ASSERT
/*virtual*/ void queued_for_removal(AICurlEasyRequest_wat& curl_easy_request_w);
#endif
}; };
// This class adds input/output buffers to the request and hooks up the libcurl callbacks to use those buffers. // This class adds input/output buffers to the request and hooks up the libcurl callbacks to use those buffers.
@@ -431,6 +443,9 @@ class BufferedCurlEasyRequest : public CurlEasyRequest {
// Called if libcurl doesn't deliver within AIHTTPTimeoutPolicy::mMaximumTotalDelay seconds. // Called if libcurl doesn't deliver within AIHTTPTimeoutPolicy::mMaximumTotalDelay seconds.
void timed_out(void); void timed_out(void);
// Called if the underlaying socket went bad (ie, when accidently closed by a buggy library).
void bad_socket(void);
// Called after removed_from_multi_handle was called. // Called after removed_from_multi_handle was called.
void processOutput(void); void processOutput(void);

View File

@@ -286,14 +286,36 @@ enum refresh_t {
empty_and_complete = complete|empty empty_and_complete = complete|empty
}; };
// A class with info for each socket that is in use by curl.
class CurlSocketInfo
{
public:
CurlSocketInfo(MultiHandle& multi_handle, CURL* easy, curl_socket_t s, int action, ThreadSafeBufferedCurlEasyRequest* lockobj);
~CurlSocketInfo();
void set_action(int action);
void mark_dead(void) { set_action(CURL_POLL_NONE); mDead = true; }
curl_socket_t getSocketFd(void) const { return mSocketFd; }
AICurlEasyRequest& getEasyRequest(void) { return mEasyRequest; }
private:
MultiHandle& mMultiHandle;
CURL const* mEasy;
curl_socket_t mSocketFd;
int mAction;
bool mDead;
AICurlEasyRequest mEasyRequest;
LLPointer<HTTPTimeout> mTimeout;
};
class PollSet class PollSet
{ {
public: public:
PollSet(void); PollSet(void);
// Add/remove a filedescriptor to/from mFileDescriptors. // Add/remove a filedescriptor to/from mFileDescriptors.
void add(curl_socket_t s); void add(CurlSocketInfo* sp);
void remove(curl_socket_t s); void remove(CurlSocketInfo* sp);
// Copy mFileDescriptors to an internal fd_set that is returned by access(). // Copy mFileDescriptors to an internal fd_set that is returned by access().
// Returns if all fds could be copied (complete) and/or if the resulting fd_set is empty. // Returns if all fds could be copied (complete) and/or if the resulting fd_set is empty.
@@ -307,8 +329,8 @@ class PollSet
curl_socket_t get_max_fd(void) const { return mMaxFdSet; } curl_socket_t get_max_fd(void) const { return mMaxFdSet; }
#endif #endif
// Return true if a filedescriptor is set in mFileDescriptors (used for debugging). // Return a pointer to the corresponding CurlSocketInfo if a filedescriptor is set in mFileDescriptors, or NULL if s is not set.
bool contains(curl_socket_t s) const; CurlSocketInfo* contains(curl_socket_t s) const;
// Return true if a filedescriptor is set in mFdSet. // Return true if a filedescriptor is set in mFdSet.
bool is_set(curl_socket_t s) const; bool is_set(curl_socket_t s) const;
@@ -323,7 +345,7 @@ class PollSet
void next(void); // Advance to next filedescriptor. void next(void); // Advance to next filedescriptor.
private: private:
curl_socket_t* mFileDescriptors; CurlSocketInfo** mFileDescriptors;
int mNrFds; // The number of filedescriptors in the array. int mNrFds; // The number of filedescriptors in the array.
int mNext; // The index of the first file descriptor to start copying, the next call to refresh(). int mNext; // The index of the first file descriptor to start copying, the next call to refresh().
@@ -332,8 +354,8 @@ class PollSet
#if !WINDOWS_CODE #if !WINDOWS_CODE
curl_socket_t mMaxFd; // The largest filedescriptor in the array, or CURL_SOCKET_BAD when it is empty. curl_socket_t mMaxFd; // The largest filedescriptor in the array, or CURL_SOCKET_BAD when it is empty.
curl_socket_t mMaxFdSet; // The largest filedescriptor set in mFdSet by refresh(), or CURL_SOCKET_BAD when it was empty. curl_socket_t mMaxFdSet; // The largest filedescriptor set in mFdSet by refresh(), or CURL_SOCKET_BAD when it was empty.
std::vector<curl_socket_t> mCopiedFileDescriptors; // Filedescriptors copied by refresh to mFdSet. std::vector<CurlSocketInfo*> mCopiedFileDescriptors; // Filedescriptors copied by refresh to mFdSet.
std::vector<curl_socket_t>::iterator mIter; // Index into mCopiedFileDescriptors for next(); loop variable. std::vector<CurlSocketInfo*>::iterator mIter; // Index into mCopiedFileDescriptors for next(); loop variable.
#else #else
unsigned int mIter; // Index into fd_set::fd_array. unsigned int mIter; // Index into fd_set::fd_array.
#endif #endif
@@ -359,7 +381,7 @@ class PollSet
static size_t const MAXSIZE = llmax(1024, FD_SETSIZE); static size_t const MAXSIZE = llmax(1024, FD_SETSIZE);
// Create an empty PollSet. // Create an empty PollSet.
PollSet::PollSet(void) : mFileDescriptors(new curl_socket_t [MAXSIZE]), PollSet::PollSet(void) : mFileDescriptors(new CurlSocketInfo* [MAXSIZE]),
mNrFds(0), mNext(0) mNrFds(0), mNext(0)
#if !WINDOWS_CODE #if !WINDOWS_CODE
, mMaxFd(-1), mMaxFdSet(-1) , mMaxFd(-1), mMaxFdSet(-1)
@@ -369,17 +391,17 @@ PollSet::PollSet(void) : mFileDescriptors(new curl_socket_t [MAXSIZE]),
} }
// Add filedescriptor s to the PollSet. // Add filedescriptor s to the PollSet.
void PollSet::add(curl_socket_t s) void PollSet::add(CurlSocketInfo* sp)
{ {
llassert_always(mNrFds < (int)MAXSIZE); llassert_always(mNrFds < (int)MAXSIZE);
mFileDescriptors[mNrFds++] = s; mFileDescriptors[mNrFds++] = sp;
#if !WINDOWS_CODE #if !WINDOWS_CODE
mMaxFd = llmax(mMaxFd, s); mMaxFd = llmax(mMaxFd, sp->getSocketFd());
#endif #endif
} }
// Remove filedescriptor s from the PollSet. // Remove filedescriptor s from the PollSet.
void PollSet::remove(curl_socket_t s) void PollSet::remove(CurlSocketInfo* sp)
{ {
// The number of open filedescriptors is relatively small, // The number of open filedescriptors is relatively small,
// and on top of that we rather do something CPU intensive // and on top of that we rather do something CPU intensive
@@ -391,15 +413,15 @@ void PollSet::remove(curl_socket_t s)
// back, keeping it compact and keeping the filedescriptors // back, keeping it compact and keeping the filedescriptors
// in the same order (which is supposedly their priority). // in the same order (which is supposedly their priority).
// //
// The general case is where mFileDescriptors contains s at an index // The general case is where mFileDescriptors contains sp at an index
// between 0 and mNrFds: // between 0 and mNrFds:
// mNrFds = 6 // mNrFds = 6
// v // v
// index: 0 1 2 3 4 5 // index: 0 1 2 3 4 5
// a b c s d e // a b c s d e
// This function should never be called unless s is actually in mFileDescriptors, // This function should never be called unless sp is actually in mFileDescriptors,
// as a result of a previous call to PollSet::add(). // as a result of a previous call to PollSet::add(sp).
llassert(mNrFds > 0); llassert(mNrFds > 0);
// Correct mNrFds for when the descriptor is removed. // Correct mNrFds for when the descriptor is removed.
@@ -409,17 +431,18 @@ void PollSet::remove(curl_socket_t s)
// v // v
// index: 0 1 2 3 4 5 // index: 0 1 2 3 4 5
// a b c s d e // a b c s d e
curl_socket_t cur = mFileDescriptors[i]; // cur = 'e' curl_socket_t const s = sp->getSocketFd();
CurlSocketInfo* cur = mFileDescriptors[i]; // cur = 'e'
#if !WINDOWS_CODE #if !WINDOWS_CODE
curl_socket_t max = -1; curl_socket_t max = -1;
#endif #endif
while (cur != s) while (cur != sp)
{ {
llassert(i > 0); llassert(i > 0);
curl_socket_t next = mFileDescriptors[--i]; // next = 'd' CurlSocketInfo* next = mFileDescriptors[--i]; // next = 'd'
mFileDescriptors[i] = cur; // Overwrite 'd' with 'e'. mFileDescriptors[i] = cur; // Overwrite 'd' with 'e'.
#if !WINDOWS_CODE #if !WINDOWS_CODE
max = llmax(max, cur); // max is the maximum value in 'i' or higher. max = llmax(max, cur->getSocketFd()); // max is the maximum value in 'i' or higher.
#endif #endif
cur = next; // cur = 'd' cur = next; // cur = 'd'
// i NrFds = 5 // i NrFds = 5
@@ -427,21 +450,21 @@ void PollSet::remove(curl_socket_t s)
// index: 0 1 2 3 4 // index: 0 1 2 3 4
// a b c s e // cur = 'd' // a b c s e // cur = 'd'
// //
// Next loop iteration: next = 's', overwrite 's' with 'd', cur = 's'; loop terminates. // Next loop iteration: next = 'sp', overwrite 'sp' with 'd', cur = 'sp'; loop terminates.
// i NrFds = 5 // i NrFds = 5
// v v // v v
// index: 0 1 2 3 4 // index: 0 1 2 3 4
// a b c d e // cur = 's' // a b c d e // cur = 'sp'
} }
llassert(cur == s); llassert(cur == sp);
// At this point i was decremented once more and points to the element before the old s. // At this point i was decremented once more and points to the element before the old s.
// i NrFds = 5 // i NrFds = 5
// v v // v v
// index: 0 1 2 3 4 // index: 0 1 2 3 4
// a b c d e // max = llmax('d', 'e') // a b c d e // max = llmax('d', 'e')
// If mNext pointed to an element before s, it should be left alone. Otherwise, if mNext pointed // If mNext pointed to an element before sp, it should be left alone. Otherwise, if mNext pointed
// to s it must now point to 'd', or if it pointed beyond 's' it must be decremented by 1. // to sp it must now point to 'd', or if it pointed beyond 'sp' it must be decremented by 1.
if (mNext > i) // i is where s was. if (mNext > i) // i is where s was.
--mNext; --mNext;
@@ -451,8 +474,8 @@ void PollSet::remove(curl_socket_t s)
{ {
while (i > 0) while (i > 0)
{ {
curl_socket_t next = mFileDescriptors[--i]; CurlSocketInfo* next = mFileDescriptors[--i];
max = llmax(max, next); max = llmax(max, next->getSocketFd());
} }
mMaxFd = max; mMaxFd = max;
llassert(mMaxFd < s); llassert(mMaxFd < s);
@@ -487,12 +510,12 @@ void PollSet::remove(curl_socket_t s)
#endif #endif
} }
bool PollSet::contains(curl_socket_t fd) const CurlSocketInfo* PollSet::contains(curl_socket_t fd) const
{ {
for (int i = 0; i < mNrFds; ++i) for (int i = 0; i < mNrFds; ++i)
if (mFileDescriptors[i] == fd) if (mFileDescriptors[i]->getSocketFd() == fd)
return true; return mFileDescriptors[i];
return false; return NULL;
} }
inline bool PollSet::is_set(curl_socket_t fd) const inline bool PollSet::is_set(curl_socket_t fd) const
@@ -536,7 +559,7 @@ refresh_t PollSet::refresh(void)
// Calculate mMaxFdSet. // Calculate mMaxFdSet.
// Run over FD_SETSIZE - 1 elements, starting at mNext, wrapping to 0 when we reach the end. // Run over FD_SETSIZE - 1 elements, starting at mNext, wrapping to 0 when we reach the end.
int max = -1, i = mNext, count = 0; int max = -1, i = mNext, count = 0;
while (++count < FD_SETSIZE) { max = llmax(max, mFileDescriptors[i]); if (++i == mNrFds) i = 0; } while (++count < FD_SETSIZE) { max = llmax(max, mFileDescriptors[i]->getSocketFd()); if (++i == mNrFds) i = 0; }
mMaxFdSet = max; mMaxFdSet = max;
#endif #endif
} }
@@ -556,7 +579,7 @@ refresh_t PollSet::refresh(void)
mNext = i; mNext = i;
return not_complete_not_empty; return not_complete_not_empty;
} }
FD_SET(mFileDescriptors[i], &mFdSet); FD_SET(mFileDescriptors[i]->getSocketFd(), &mFdSet);
#if !WINDOWS_CODE #if !WINDOWS_CODE
mCopiedFileDescriptors.push_back(mFileDescriptors[i]); mCopiedFileDescriptors.push_back(mFileDescriptors[i]);
#endif #endif
@@ -603,7 +626,7 @@ void PollSet::reset(void)
else else
{ {
mIter = mCopiedFileDescriptors.begin(); mIter = mCopiedFileDescriptors.begin();
if (!FD_ISSET(*mIter, &mFdSet)) if (!FD_ISSET((*mIter)->getSocketFd(), &mFdSet))
next(); next();
} }
#endif #endif
@@ -614,7 +637,7 @@ inline curl_socket_t PollSet::get(void) const
#if WINDOWS_CODE #if WINDOWS_CODE
return (mIter >= mFdSet.fd_count) ? CURL_SOCKET_BAD : mFdSet.fd_array[mIter]; return (mIter >= mFdSet.fd_count) ? CURL_SOCKET_BAD : mFdSet.fd_array[mIter];
#else #else
return (mIter == mCopiedFileDescriptors.end()) ? CURL_SOCKET_BAD : *mIter; return (mIter == mCopiedFileDescriptors.end()) ? CURL_SOCKET_BAD : (*mIter)->getSocketFd();
#endif #endif
} }
@@ -625,7 +648,7 @@ void PollSet::next(void)
++mIter; ++mIter;
#else #else
llassert(mIter != mCopiedFileDescriptors.end()); // Only call next() if the last call to get() didn't return -1. llassert(mIter != mCopiedFileDescriptors.end()); // Only call next() if the last call to get() didn't return -1.
while (++mIter != mCopiedFileDescriptors.end() && !FD_ISSET(*mIter, &mFdSet)); while (++mIter != mCopiedFileDescriptors.end() && !FD_ISSET((*mIter)->getSocketFd(), &mFdSet));
#endif #endif
} }
@@ -743,26 +766,8 @@ std::ostream& operator<<(std::ostream& os, DebugFdSet const& s)
} }
#endif #endif
// A class with info for each socket that is in use by curl.
class CurlSocketInfo
{
public:
CurlSocketInfo(MultiHandle& multi_handle, CURL* easy, curl_socket_t s, int action, ThreadSafeBufferedCurlEasyRequest* lockobj);
~CurlSocketInfo();
void set_action(int action);
private:
MultiHandle& mMultiHandle;
CURL const* mEasy;
curl_socket_t mSocketFd;
int mAction;
AICurlEasyRequest mEasyRequest;
LLPointer<HTTPTimeout> mTimeout;
};
CurlSocketInfo::CurlSocketInfo(MultiHandle& multi_handle, CURL* easy, curl_socket_t s, int action, ThreadSafeBufferedCurlEasyRequest* lockobj) : CurlSocketInfo::CurlSocketInfo(MultiHandle& multi_handle, CURL* easy, curl_socket_t s, int action, ThreadSafeBufferedCurlEasyRequest* lockobj) :
mMultiHandle(multi_handle), mEasy(easy), mSocketFd(s), mAction(CURL_POLL_NONE), mEasyRequest(lockobj) mMultiHandle(multi_handle), mEasy(easy), mSocketFd(s), mAction(CURL_POLL_NONE), mDead(false), mEasyRequest(lockobj)
{ {
llassert(*AICurlEasyRequest_wat(*mEasyRequest) == easy); llassert(*AICurlEasyRequest_wat(*mEasyRequest) == easy);
mMultiHandle.assign(s, this); mMultiHandle.assign(s, this);
@@ -785,23 +790,28 @@ CurlSocketInfo::~CurlSocketInfo()
void CurlSocketInfo::set_action(int action) void CurlSocketInfo::set_action(int action)
{ {
if (mDead)
{
return;
}
Dout(dc::curl, "CurlSocketInfo::set_action(" << action_str(mAction) << " --> " << action_str(action) << ") [" << (void*)mEasyRequest.get_ptr().get() << "]"); Dout(dc::curl, "CurlSocketInfo::set_action(" << action_str(mAction) << " --> " << action_str(action) << ") [" << (void*)mEasyRequest.get_ptr().get() << "]");
int toggle_action = mAction ^ action; int toggle_action = mAction ^ action;
mAction = action; mAction = action;
if ((toggle_action & CURL_POLL_IN)) if ((toggle_action & CURL_POLL_IN))
{ {
if ((action & CURL_POLL_IN)) if ((action & CURL_POLL_IN))
mMultiHandle.mReadPollSet->add(mSocketFd); mMultiHandle.mReadPollSet->add(this);
else else
mMultiHandle.mReadPollSet->remove(mSocketFd); mMultiHandle.mReadPollSet->remove(this);
} }
if ((toggle_action & CURL_POLL_OUT)) if ((toggle_action & CURL_POLL_OUT))
{ {
if ((action & CURL_POLL_OUT)) if ((action & CURL_POLL_OUT))
mMultiHandle.mWritePollSet->add(mSocketFd); mMultiHandle.mWritePollSet->add(this);
else else
{ {
mMultiHandle.mWritePollSet->remove(mSocketFd); mMultiHandle.mWritePollSet->remove(this);
// The following is a bit of a hack, needed because of the lack of proper timeout callbacks in libcurl. // The following is a bit of a hack, needed because of the lack of proper timeout callbacks in libcurl.
// The removal of CURL_POLL_OUT could be part of the SSL handshake, therefore check if we're already connected: // The removal of CURL_POLL_OUT could be part of the SSL handshake, therefore check if we're already connected:
@@ -838,6 +848,9 @@ class AICurlThread : public LLThread
// MAIN-THREAD // MAIN-THREAD
void stop_thread(void) { mRunning = false; wakeup_thread(); } void stop_thread(void) { mRunning = false; wakeup_thread(); }
// MAIN-THREAD
apr_status_t join_thread(void);
protected: protected:
virtual void run(void); virtual void run(void);
void wakeup(AICurlMultiHandle_wat const& multi_handle_w); void wakeup(AICurlMultiHandle_wat const& multi_handle_w);
@@ -1110,6 +1123,17 @@ void AICurlThread::wakeup_thread(void)
#endif #endif
} }
apr_status_t AICurlThread::join_thread(void)
{
apr_status_t retval = APR_SUCCESS;
if (sInstance)
{
apr_thread_join(&retval, sInstance->mAPRThreadp);
delete sInstance;
}
return retval;
}
void AICurlThread::wakeup(AICurlMultiHandle_wat const& multi_handle_w) void AICurlThread::wakeup(AICurlMultiHandle_wat const& multi_handle_w)
{ {
DoutEntering(dc::curl, "AICurlThread::wakeup"); DoutEntering(dc::curl, "AICurlThread::wakeup");
@@ -1255,6 +1279,26 @@ void AICurlThread::process_commands(AICurlMultiHandle_wat const& multi_handle_w)
} }
} }
// Return true if fd is a 'bad' socket.
static bool is_bad(curl_socket_t fd, bool for_writing)
{
fd_set tmp;
FD_ZERO(&tmp);
FD_SET(fd, &tmp);
fd_set* readfds = for_writing ? NULL : &tmp;
fd_set* writefds = for_writing ? &tmp : NULL;
#if !WINDOWS_CODE
int nfds = fd + 1;
#else
int nfds = 64;
#endif
struct timeval timeout;
timeout.tv_sec = 0;
timeout.tv_usec = 10;
int ret = select(nfds, readfds, writefds, NULL, &timeout);
return ret == -1;
}
// The main loop of the curl thread. // The main loop of the curl thread.
void AICurlThread::run(void) void AICurlThread::run(void)
{ {
@@ -1266,7 +1310,7 @@ void AICurlThread::run(void)
{ {
// If mRunning is true then we can only get here if mWakeUpFd != CURL_SOCKET_BAD. // If mRunning is true then we can only get here if mWakeUpFd != CURL_SOCKET_BAD.
llassert(mWakeUpFd != CURL_SOCKET_BAD); llassert(mWakeUpFd != CURL_SOCKET_BAD);
// Copy the next batch of file descriptors from the PollSets mFiledescriptors into their mFdSet. // Copy the next batch of file descriptors from the PollSets mFileDescriptors into their mFdSet.
multi_handle_w->mReadPollSet->refresh(); multi_handle_w->mReadPollSet->refresh();
refresh_t wres = multi_handle_w->mWritePollSet->refresh(); refresh_t wres = multi_handle_w->mWritePollSet->refresh();
// Add wake up fd if any, and pass NULL to select() if a set is empty. // Add wake up fd if any, and pass NULL to select() if a set is empty.
@@ -1383,6 +1427,51 @@ void AICurlThread::run(void)
if (ready == -1) if (ready == -1)
{ {
llwarns << "select() failed: " << errno << ", " << strerror(errno) << llendl; llwarns << "select() failed: " << errno << ", " << strerror(errno) << llendl;
if (errno == EBADF)
{
// Somewhere (fmodex?) one of our file descriptors was closed. Try to recover by finding out which.
llassert_always(!is_bad(mWakeUpFd, false)); // We can't recover from this.
PollSet* found = NULL;
// Run over all read file descriptors.
multi_handle_w->mReadPollSet->refresh();
multi_handle_w->mReadPollSet->reset();
curl_socket_t fd;
while ((fd = multi_handle_w->mReadPollSet->get()) != CURL_SOCKET_BAD)
{
if (is_bad(fd, false))
{
found = multi_handle_w->mReadPollSet;
break;
}
multi_handle_w->mReadPollSet->next();
}
if (!found)
{
// Try all write file descriptors.
refresh_t wres = multi_handle_w->mWritePollSet->refresh();
if (!(wres & empty))
{
multi_handle_w->mWritePollSet->reset();
while ((fd = multi_handle_w->mWritePollSet->get()) != CURL_SOCKET_BAD)
{
if (is_bad(fd, true))
{
found = multi_handle_w->mWritePollSet;
break;
}
multi_handle_w->mWritePollSet->next();
}
}
}
llassert_always(found); // It makes no sense to continue if we can't recover.
// Find the corresponding CurlSocketInfo
CurlSocketInfo* sp = found->contains(fd);
llassert_always(sp); // fd was just *read* from this sp.
sp->mark_dead(); // Make sure it's never used again.
AICurlEasyRequest_wat curl_easy_request_w(*sp->getEasyRequest());
curl_easy_request_w->pause(CURLPAUSE_ALL); // Keep libcurl at bay.
curl_easy_request_w->bad_file_descriptor(curl_easy_request_w); // Make the main thread cleanly terminate this transaction.
}
continue; continue;
} }
// Clock count used for timeouts. // Clock count used for timeouts.
@@ -1822,7 +1911,7 @@ bool HTTPTimeout::data_received(size_t n)
// | | | | | | | | | | | | | | // | | | | | | | | | | | | | |
bool HTTPTimeout::lowspeed(size_t bytes) bool HTTPTimeout::lowspeed(size_t bytes)
{ {
DoutCurlEntering("HTTPTimeout::lowspeed(" << bytes << ")"); //DoutCurlEntering("HTTPTimeout::lowspeed(" << bytes << ")"); commented out... too spammy for normal use.
// The algorithm to determine if we timed out if different from how libcurls CURLOPT_LOW_SPEED_TIME works. // The algorithm to determine if we timed out if different from how libcurls CURLOPT_LOW_SPEED_TIME works.
// //
@@ -2000,12 +2089,11 @@ void HTTPTimeout::print_diagnostics(CurlEasyRequest const* curl_easy_request, ch
#if LOWRESTIMER #if LOWRESTIMER
llinfos << "Hostname seems to have been still in the DNS cache." << llendl; llinfos << "Hostname seems to have been still in the DNS cache." << llendl;
#else #else
llwarns << "Huh? Curl returned CURLE_OPERATION_TIMEDOUT, but DNS lookup did not occur according to timings. Expected CURLE_COULDNT_RESOLVE_PROXY or CURLE_COULDNT_RESOLVE_HOST!" << llendl; llwarns << "Curl returned CURLE_OPERATION_TIMEDOUT and DNS lookup did not occur according to timings. Apparently the resolve attempt timed out (bad network?)" << llendl;
llassert(connect_time == 0); llassert(connect_time == 0);
llassert(appconnect_time == 0); llassert(appconnect_time == 0);
llassert(pretransfer_time == 0); llassert(pretransfer_time == 0);
llassert(starttransfer_time == 0); llassert(starttransfer_time == 0);
// Fatal error for diagnostics.
return; return;
#endif #endif
} }
@@ -2028,11 +2116,10 @@ void HTTPTimeout::print_diagnostics(CurlEasyRequest const* curl_easy_request, ch
#endif #endif
) )
{ {
llwarns << "Huh? Curl returned CURLE_OPERATION_TIMEDOUT, but connection did not occur according to timings. Expected CURLE_COULDNT_CONNECT!" << llendl; llwarns << "Curl returned CURLE_OPERATION_TIMEDOUT and connection did not occur according to timings: apparently the connect attempt timed out (bad network?)" << llendl;
llassert(appconnect_time == 0); llassert(appconnect_time == 0);
llassert(pretransfer_time == 0); llassert(pretransfer_time == 0);
llassert(starttransfer_time == 0); llassert(starttransfer_time == 0);
// Fatal error for diagnostics.
return; return;
} }
// If connect_time is almost equal to namelookup_time, then it was just set because it was already connected. // If connect_time is almost equal to namelookup_time, then it was just set because it was already connected.
@@ -2148,12 +2235,22 @@ void stopCurlThread(void)
if (AICurlThread::sInstance) if (AICurlThread::sInstance)
{ {
AICurlThread::sInstance->stop_thread(); AICurlThread::sInstance->stop_thread();
int count = 101; int count = 401;
while(--count && !AICurlThread::sInstance->isStopped()) while(--count && !AICurlThread::sInstance->isStopped())
{ {
ms_sleep(10); ms_sleep(10);
} }
Dout(dc::curl, "Curl thread" << (curlThreadIsRunning() ? " not" : "") << " stopped after " << ((100 - count) * 10) << "ms."); if (AICurlThread::sInstance->isStopped())
{
// isStopped() returns true somewhere at the end of run(),
// but that doesn't mean the thread really stopped: it still
// needs to destroy it's static variables.
// If we don't join here, then there is a chance that the
// curl thread will crash when using globals that we (the
// main thread) will have destroyed before it REALLY finished.
AICurlThread::sInstance->join_thread(); // Wait till it is REALLY done.
}
llinfos << "Curl thread" << (curlThreadIsRunning() ? " not" : "") << " stopped after " << ((400 - count) * 10) << "ms." << llendl;
} }
} }
@@ -2174,7 +2271,7 @@ void BufferedCurlEasyRequest::setStatusAndReason(U32 status, std::string const&
AICurlInterface::Stats::status_count[AICurlInterface::Stats::status2index(mStatus)]++; AICurlInterface::Stats::status_count[AICurlInterface::Stats::status2index(mStatus)]++;
// Sanity check. If the server replies with a redirect status then we better have that option turned on! // Sanity check. If the server replies with a redirect status then we better have that option turned on!
if ((status >= 300 && status < 400) && mResponder && !mResponder->followRedir()) if ((status >= 300 && status < 400) && mResponder && !mResponder->redirect_status_ok())
{ {
llerrs << "Received " << status << " (" << reason << ") for responder \"" << mTimeoutPolicy->name() << "\" which has no followRedir()!" << llendl; llerrs << "Received " << status << " (" << reason << ") for responder \"" << mTimeoutPolicy->name() << "\" which has no followRedir()!" << llendl;
} }
@@ -2188,7 +2285,7 @@ void BufferedCurlEasyRequest::processOutput(void)
CURLcode code; CURLcode code;
AITransferInfo info; AITransferInfo info;
getResult(&code, &info); getResult(&code, &info);
if (code == CURLE_OK) if (code == CURLE_OK && mStatus != HTTP_INTERNAL_ERROR)
{ {
getinfo(CURLINFO_RESPONSE_CODE, &responseCode); getinfo(CURLINFO_RESPONSE_CODE, &responseCode);
// If getResult code is CURLE_OK then we should have decoded the first header line ourselves. // If getResult code is CURLE_OK then we should have decoded the first header line ourselves.
@@ -2201,7 +2298,7 @@ void BufferedCurlEasyRequest::processOutput(void)
else else
{ {
responseCode = HTTP_INTERNAL_ERROR; responseCode = HTTP_INTERNAL_ERROR;
responseReason = curl_easy_strerror(code); responseReason = (code == CURLE_OK) ? mReason : std::string(curl_easy_strerror(code));
setopt(CURLOPT_FRESH_CONNECT, TRUE); setopt(CURLOPT_FRESH_CONNECT, TRUE);
} }
@@ -2367,14 +2464,25 @@ size_t BufferedCurlEasyRequest::curlHeaderCallback(char* data, size_t size, size
} }
#if defined(CWDEBUG) || defined(DEBUG_CURLIO) #if defined(CWDEBUG) || defined(DEBUG_CURLIO)
int debug_callback(CURL*, curl_infotype infotype, char* buf, size_t size, void* user_ptr) int debug_callback(CURL* handle, curl_infotype infotype, char* buf, size_t size, void* user_ptr)
{ {
BufferedCurlEasyRequest* request = (BufferedCurlEasyRequest*)user_ptr; BufferedCurlEasyRequest* request = (BufferedCurlEasyRequest*)user_ptr;
if (infotype == CURLINFO_HEADER_OUT && size >= 5 && (strncmp(buf, "GET ", 4) == 0 || strncmp(buf, "HEAD ", 5) == 0))
{
request->mDebugIsHeadOrGetMethod = true;
}
#ifdef DEBUG_CURLIO
if (!debug_curl_print_debug(handle))
{
return 0;
}
#endif
#ifdef CWDEBUG #ifdef CWDEBUG
using namespace ::libcwd; using namespace ::libcwd;
std::ostringstream marker; std::ostringstream marker;
marker << (void*)request->get_lockobj(); marker << (void*)request->get_lockobj() << ' ';
libcw_do.push_marker(); libcw_do.push_marker();
libcw_do.marker().assign(marker.str().data(), marker.str().size()); libcw_do.marker().assign(marker.str().data(), marker.str().size());
if (!debug::channels::dc::curlio.is_on()) if (!debug::channels::dc::curlio.is_on())
@@ -2398,8 +2506,6 @@ int debug_callback(CURL*, curl_infotype infotype, char* buf, size_t size, void*
break; break;
case CURLINFO_HEADER_OUT: case CURLINFO_HEADER_OUT:
LibcwDoutStream << "H< "; LibcwDoutStream << "H< ";
if (size >= 5 && (strncmp(buf, "GET ", 4) == 0 || strncmp(buf, "HEAD ", 5) == 0))
request->mDebugIsHeadOrGetMethod = true;
break; break;
case CURLINFO_DATA_IN: case CURLINFO_DATA_IN:
LibcwDoutStream << "D> "; LibcwDoutStream << "D> ";
@@ -2573,6 +2679,14 @@ void AICurlEasyRequest::removeRequest(void)
} }
} }
} }
{
AICurlEasyRequest_wat curl_easy_request_w(*get());
// As soon as the lock on the command queue is released, it could be picked up by
// the curl thread and executed. At that point it (already) demands that the easy
// request either timed out or is finished. So, to avoid race conditions that already
// has to be true right now. The call to queued_for_removal() checks this.
curl_easy_request_w->queued_for_removal(curl_easy_request_w);
}
#endif #endif
// Add a command to remove this request from the multi session to the command queue. // Add a command to remove this request from the multi session to the command queue.
command_queue_w->push_back(Command(*this, cmd_remove)); command_queue_w->push_back(Command(*this, cmd_remove));

View File

@@ -107,6 +107,20 @@ void AIHTTPReceivedHeaders::addHeader(std::string const& key, std::string const&
{ {
mContainer = new Container; mContainer = new Container;
} }
else if (equal(key, "set-cookie"))
{
// If a cookie with this name already exists, replace it.
std::string const name = value.substr(0, value.find('='));
container_t::iterator const end = mContainer->mKeyValuePairs.end();
for (container_t::iterator header = mContainer->mKeyValuePairs.begin(); header != end; ++header)
{
if (equal(header->first, "set-cookie") && header->second.substr(0, header->second.find('=')) == name)
{
header->second = value;
return;
}
}
}
mContainer->mKeyValuePairs.insert(container_t::value_type(key, value)); mContainer->mKeyValuePairs.insert(container_t::value_type(key, value));
} }
@@ -151,3 +165,20 @@ std::ostream& operator<<(std::ostream& os, AIHTTPReceivedHeaders const& headers)
return os; return os;
} }
//static
bool AIHTTPReceivedHeaders::equal(std::string const& key1, std::string const& key2)
{
if (key1.length() != key2.length())
{
return false;
}
for (std::string::const_iterator i1 = key1.begin(), i2 = key2.begin(); i1 != key1.end(); ++i1, ++i2)
{
if ((*i1 ^ *i2) & 0xdf != 0)
{
return false;
}
}
return true;
}

View File

@@ -132,6 +132,9 @@ class AIHTTPReceivedHeaders {
// Add a header. // Add a header.
void addHeader(std::string const& key, std::string const& value); void addHeader(std::string const& key, std::string const& value);
// Swap headers with another container.
void swap(AIHTTPReceivedHeaders& headers) { LLPointer<Container>::swap(mContainer, headers.mContainer); }
// Return true if there are no headers associated with this object. // Return true if there are no headers associated with this object.
bool empty(void) const { return !mContainer || mContainer->mKeyValuePairs.empty(); } bool empty(void) const { return !mContainer || mContainer->mKeyValuePairs.empty(); }
@@ -147,6 +150,9 @@ class AIHTTPReceivedHeaders {
// For debug purposes. // For debug purposes.
friend std::ostream& operator<<(std::ostream& os, AIHTTPReceivedHeaders const& headers); friend std::ostream& operator<<(std::ostream& os, AIHTTPReceivedHeaders const& headers);
// Returns true if the two keys compare equal (ie, "Set-Cookie" == "set-cookie").
static bool equal(std::string const& key1, std::string const& key2);
private: private:
struct Container : public LLThreadSafeRefCount { struct Container : public LLThreadSafeRefCount {
container_t mKeyValuePairs; container_t mKeyValuePairs;

View File

@@ -646,6 +646,12 @@ AIHTTPTimeoutPolicyBase transfer_18s(AIHTTPTimeoutPolicyBase::getDebugSettingsCu
transactionOp18s transactionOp18s
); );
// This used to be '30 seconds'.
Transaction transactionOp30s(30);
AIHTTPTimeoutPolicyBase transfer_30s(AIHTTPTimeoutPolicyBase::getDebugSettingsCurlTimeout(),
transactionOp30s
);
// This used to be '300 seconds'. We derive this from the hardcoded result so users can't mess with it. // This used to be '300 seconds'. We derive this from the hardcoded result so users can't mess with it.
Transaction transactionOp300s(300); Transaction transactionOp300s(300);
AIHTTPTimeoutPolicyBase transfer_300s(HTTPTimeoutPolicy_default, AIHTTPTimeoutPolicyBase transfer_300s(HTTPTimeoutPolicy_default,
@@ -852,6 +858,7 @@ P(lcl_responder);
P(MPImportGetResponder); P(MPImportGetResponder);
P(MPImportPostResponder); P(MPImportPostResponder);
P(mapLayerResponder); P(mapLayerResponder);
P2(maturityPreferences, transfer_30s);
P(mediaTypeResponder); P(mediaTypeResponder);
P(meshDecompositionResponder); P(meshDecompositionResponder);
P(meshHeaderResponder); P(meshHeaderResponder);

View File

@@ -6,6 +6,7 @@
#include <cstdlib> #include <cstdlib>
#include <stdarg.h> #include <stdarg.h>
#include <cstring> #include <cstring>
#include <algorithm>
#include "llpreprocessor.h" #include "llpreprocessor.h"
#include <curl/curl.h> #include <curl/curl.h>
#define COMPILING_DEBUG_LIBCURL_CC #define COMPILING_DEBUG_LIBCURL_CC
@@ -528,19 +529,66 @@ std::ostream& operator<<(std::ostream& os, EvBitmask const& bitmask)
return os; return os;
} }
// Set this to limit the curl debug output to specific easy handles.
bool gDebugCurlTerse = false;
namespace {
std::vector<CURL*> handles;
inline bool print_debug(CURL* handle)
{
if (!gDebugCurlTerse)
return true;
return std::find(handles.begin(), handles.end(), handle) != handles.end();
}
} // namespace
void debug_curl_add_easy(CURL* handle)
{
std::vector<CURL*>::iterator iter = std::find(handles.begin(), handles.end(), handle);
if (iter == handles.end())
{
handles.push_back(handle);
Dout(dc::warning, "debug_curl_add_easy(" << (void*)handle << "): added");
}
llassert(print_debug(handle));
}
void debug_curl_remove_easy(CURL* handle)
{
std::vector<CURL*>::iterator iter = std::find(handles.begin(), handles.end(), handle);
if (iter != handles.end())
{
handles.erase(iter);
Dout(dc::warning, "debug_curl_remove_easy(" << (void*)handle << "): removed");
}
llassert(!print_debug(handle));
}
bool debug_curl_print_debug(CURL* handle)
{
return print_debug(handle);
}
extern "C" { extern "C" {
void debug_curl_easy_cleanup(CURL* handle) void debug_curl_easy_cleanup(CURL* handle)
{ {
curl_easy_cleanup(handle); curl_easy_cleanup(handle);
Dout(dc::curl, "curl_easy_cleanup(" << (AICURL*)handle << ")"); if (print_debug(handle))
{
Dout(dc::curltr, "curl_easy_cleanup(" << (AICURL*)handle << ")");
}
} }
CURL* debug_curl_easy_duphandle(CURL* handle) CURL* debug_curl_easy_duphandle(CURL* handle)
{ {
CURL* ret; CURL* ret;
ret = curl_easy_duphandle(handle); ret = curl_easy_duphandle(handle);
Dout(dc::curl, "curl_easy_duphandle(" << (AICURL*)handle << ") = " << (AICURL*)ret); if (!print_debug(handle)) return ret;
Dout(dc::curltr, "curl_easy_duphandle(" << (AICURL*)handle << ") = " << (AICURL*)ret);
return ret; return ret;
} }
@@ -548,11 +596,12 @@ char* debug_curl_easy_escape(CURL* curl, char* url, int length)
{ {
char* ret; char* ret;
ret = curl_easy_escape(curl, url, length); ret = curl_easy_escape(curl, url, length);
Dout(dc::curl, "curl_easy_escape(" << (AICURL*)curl << ", \"" << url << "\", " << length << ") = \"" << ret << '"'); if (!print_debug(curl)) return ret;
Dout(dc::curltr, "curl_easy_escape(" << (AICURL*)curl << ", \"" << url << "\", " << length << ") = \"" << ret << '"');
return ret; return ret;
} }
CURLcode debug_curl_easy_getinfo(CURL* curl, CURLINFO info, ...) CURLcode debug_curl_easy_getinfo(CURL* handle, CURLINFO info, ...)
{ {
CURLcode ret; CURLcode ret;
va_list ap; va_list ap;
@@ -566,26 +615,27 @@ CURLcode debug_curl_easy_getinfo(CURL* curl, CURLINFO info, ...)
va_start(ap, info); va_start(ap, info);
param.some_ptr = va_arg(ap, void*); param.some_ptr = va_arg(ap, void*);
va_end(ap); va_end(ap);
ret = curl_easy_getinfo(curl, info, param.some_ptr); ret = curl_easy_getinfo(handle, info, param.some_ptr);
if (!print_debug(handle)) return ret;
if (info == CURLINFO_PRIVATE) if (info == CURLINFO_PRIVATE)
{ {
Dout(dc::curl, "curl_easy_getinfo(" << (AICURL*)curl << ", " << info << ", 0x" << std::hex << (size_t)param.some_ptr << std::dec << ") = " << ret); Dout(dc::curltr, "curl_easy_getinfo(" << (AICURL*)handle << ", " << info << ", 0x" << std::hex << (size_t)param.some_ptr << std::dec << ") = " << ret);
} }
else else
{ {
switch((info & CURLINFO_TYPEMASK)) switch((info & CURLINFO_TYPEMASK))
{ {
case CURLINFO_STRING: case CURLINFO_STRING:
Dout(dc::curl, "curl_easy_getinfo(" << (AICURL*)curl << ", " << info << ", (char**){ \"" << (ret == CURLE_OK ? *param.char_ptr : " <unchanged> ") << "\" }) = " << ret); Dout(dc::curltr, "curl_easy_getinfo(" << (AICURL*)handle << ", " << info << ", (char**){ \"" << (ret == CURLE_OK ? *param.char_ptr : " <unchanged> ") << "\" }) = " << ret);
break; break;
case CURLINFO_LONG: case CURLINFO_LONG:
Dout(dc::curl, "curl_easy_getinfo(" << (AICURL*)curl << ", " << info << ", (long*){ " << (ret == CURLE_OK ? *param.long_ptr : 0L) << "L }) = " << ret); Dout(dc::curltr, "curl_easy_getinfo(" << (AICURL*)handle << ", " << info << ", (long*){ " << (ret == CURLE_OK ? *param.long_ptr : 0L) << "L }) = " << ret);
break; break;
case CURLINFO_DOUBLE: case CURLINFO_DOUBLE:
Dout(dc::curl, "curl_easy_getinfo(" << (AICURL*)curl << ", " << info << ", (double*){" << (ret == CURLE_OK ? *param.double_ptr : 0.) << "}) = " << ret); Dout(dc::curltr, "curl_easy_getinfo(" << (AICURL*)handle << ", " << info << ", (double*){" << (ret == CURLE_OK ? *param.double_ptr : 0.) << "}) = " << ret);
break; break;
case CURLINFO_SLIST: case CURLINFO_SLIST:
Dout(dc::curl, "curl_easy_getinfo(" << (AICURL*)curl << ", " << info << ", (curl_slist**){ " << (ret == CURLE_OK ? **param.curl_slist_ptr : unchanged_slist) << " }) = " << ret); Dout(dc::curltr, "curl_easy_getinfo(" << (AICURL*)handle << ", " << info << ", (curl_slist**){ " << (ret == CURLE_OK ? **param.curl_slist_ptr : unchanged_slist) << " }) = " << ret);
break; break;
} }
} }
@@ -596,7 +646,8 @@ CURL* debug_curl_easy_init(void)
{ {
CURL* ret; CURL* ret;
ret = curl_easy_init(); ret = curl_easy_init();
Dout(dc::curl, "curl_easy_init() = " << (AICURL*)ret); if (gDebugCurlTerse) return ret;
Dout(dc::curltr, "curl_easy_init() = " << (AICURL*)ret);
return ret; return ret;
} }
@@ -604,7 +655,8 @@ CURLcode debug_curl_easy_pause(CURL* handle, int bitmask)
{ {
CURLcode ret; CURLcode ret;
ret = curl_easy_pause(handle, bitmask); ret = curl_easy_pause(handle, bitmask);
Dout(dc::curl, "curl_easy_pause(" << (AICURL*)handle << ", 0x" << std::hex << bitmask << std::dec << ") = " << ret); if (!print_debug(handle)) return ret;
Dout(dc::curltr, "curl_easy_pause(" << (AICURL*)handle << ", 0x" << std::hex << bitmask << std::dec << ") = " << ret);
return ret; return ret;
} }
@@ -612,19 +664,21 @@ CURLcode debug_curl_easy_perform(CURL* handle)
{ {
CURLcode ret; CURLcode ret;
ret = curl_easy_perform(handle); ret = curl_easy_perform(handle);
Dout(dc::curl, "curl_easy_perform(" << (AICURL*)handle << ") = " << ret); if (!print_debug(handle)) return ret;
Dout(dc::curltr, "curl_easy_perform(" << (AICURL*)handle << ") = " << ret);
return ret; return ret;
} }
void debug_curl_easy_reset(CURL* handle) void debug_curl_easy_reset(CURL* handle)
{ {
curl_easy_reset(handle); curl_easy_reset(handle);
Dout(dc::curl, "curl_easy_reset(" << (AICURL*)handle << ")"); if (!print_debug(handle)) return;
Dout(dc::curltr, "curl_easy_reset(" << (AICURL*)handle << ")");
} }
CURLcode debug_curl_easy_setopt(CURL* handle, CURLoption option, ...) CURLcode debug_curl_easy_setopt(CURL* handle, CURLoption option, ...)
{ {
CURLcode ret = CURLE_UNKNOWN_OPTION; // Suppress compiler warning. CURLcode ret = CURLE_OBSOLETE50; // Suppress compiler warning.
va_list ap; va_list ap;
union param_type { union param_type {
long along; long along;
@@ -656,7 +710,10 @@ CURLcode debug_curl_easy_setopt(CURL* handle, CURLoption option, ...)
case CURLOPTTYPE_LONG: case CURLOPTTYPE_LONG:
{ {
ret = curl_easy_setopt(handle, option, param.along); ret = curl_easy_setopt(handle, option, param.along);
Dout(dc::curl, "curl_easy_setopt(" << (AICURL*)handle << ", " << option << ", " << param.along << "L) = " << ret); if (print_debug(handle))
{
Dout(dc::curltr, "curl_easy_setopt(" << (AICURL*)handle << ", " << option << ", " << param.along << "L) = " << ret);
}
if (option == CURLOPT_POSTFIELDSIZE) if (option == CURLOPT_POSTFIELDSIZE)
{ {
postfieldsize = param.along; postfieldsize = param.along;
@@ -666,7 +723,8 @@ CURLcode debug_curl_easy_setopt(CURL* handle, CURLoption option, ...)
case CURLOPTTYPE_OBJECTPOINT: case CURLOPTTYPE_OBJECTPOINT:
{ {
ret = curl_easy_setopt(handle, option, param.ptr); ret = curl_easy_setopt(handle, option, param.ptr);
LibcwDoutScopeBegin(LIBCWD_DEBUGCHANNELS, libcwd::libcw_do, dc::curl) if (!print_debug(handle)) break;
LibcwDoutScopeBegin(LIBCWD_DEBUGCHANNELS, libcwd::libcw_do, dc::curltr)
LibcwDoutStream << "curl_easy_setopt(" << (AICURL*)handle << ", " << option << ", "; LibcwDoutStream << "curl_easy_setopt(" << (AICURL*)handle << ", " << option << ", ";
// For a subset of all options that take a char*, print the string passed. // For a subset of all options that take a char*, print the string passed.
if (option == CURLOPT_PROXY || // Set HTTP proxy to use. The parameter should be a char* to a zero terminated string holding the host name or dotted IP address. if (option == CURLOPT_PROXY || // Set HTTP proxy to use. The parameter should be a char* to a zero terminated string holding the host name or dotted IP address.
@@ -717,11 +775,11 @@ CURLcode debug_curl_easy_setopt(CURL* handle, CURLoption option, ...)
if (option == CURLOPT_HTTPHEADER && param.ptr) if (option == CURLOPT_HTTPHEADER && param.ptr)
{ {
debug::Indent indent(2); debug::Indent indent(2);
Dout(dc::curl, "HTTP Headers:"); Dout(dc::curltr, "HTTP Headers:");
struct curl_slist* list = (struct curl_slist*)param.ptr; struct curl_slist* list = (struct curl_slist*)param.ptr;
while (list) while (list)
{ {
Dout(dc::curl, '"' << list->data << '"'); Dout(dc::curltr, '"' << list->data << '"');
list = list->next; list = list->next;
} }
} }
@@ -729,12 +787,18 @@ CURLcode debug_curl_easy_setopt(CURL* handle, CURLoption option, ...)
} }
case CURLOPTTYPE_FUNCTIONPOINT: case CURLOPTTYPE_FUNCTIONPOINT:
ret = curl_easy_setopt(handle, option, param.ptr); ret = curl_easy_setopt(handle, option, param.ptr);
Dout(dc::curl, "curl_easy_setopt(" << (AICURL*)handle << ", " << option << ", (function*)0x" << std::hex << (size_t)param.ptr << std::dec << ") = " << ret); if (print_debug(handle))
{
Dout(dc::curltr, "curl_easy_setopt(" << (AICURL*)handle << ", " << option << ", (function*)0x" << std::hex << (size_t)param.ptr << std::dec << ") = " << ret);
}
break; break;
case CURLOPTTYPE_OFF_T: case CURLOPTTYPE_OFF_T:
{ {
ret = curl_easy_setopt(handle, option, param.offset); ret = curl_easy_setopt(handle, option, param.offset);
Dout(dc::curl, "curl_easy_setopt(" << (AICURL*)handle << ", " << option << ", (curl_off_t)" << param.offset << ") = " << ret); if (print_debug(handle))
{
Dout(dc::curltr, "curl_easy_setopt(" << (AICURL*)handle << ", " << option << ", (curl_off_t)" << param.offset << ") = " << ret);
}
if (option == CURLOPT_POSTFIELDSIZE_LARGE) if (option == CURLOPT_POSTFIELDSIZE_LARGE)
{ {
postfieldsize = (long)param.offset; postfieldsize = (long)param.offset;
@@ -751,7 +815,8 @@ char const* debug_curl_easy_strerror(CURLcode errornum)
{ {
char const* ret; char const* ret;
ret = curl_easy_strerror(errornum); ret = curl_easy_strerror(errornum);
Dout(dc::curl, "curl_easy_strerror(" << errornum << ") = \"" << ret << '"'); if (gDebugCurlTerse) return ret;
Dout(dc::curltr, "curl_easy_strerror(" << errornum << ") = \"" << ret << '"');
return ret; return ret;
} }
@@ -759,35 +824,38 @@ char* debug_curl_easy_unescape(CURL* curl, char* url, int inlength, int* outleng
{ {
char* ret; char* ret;
ret = curl_easy_unescape(curl, url, inlength, outlength); ret = curl_easy_unescape(curl, url, inlength, outlength);
Dout(dc::curl, "curl_easy_unescape(" << (AICURL*)curl << ", \"" << url << "\", " << inlength << ", " << ((ret && outlength) ? *outlength : 1) << ") = \"" << ret << '"'); if (!print_debug(curl)) return ret;
Dout(dc::curltr, "curl_easy_unescape(" << (AICURL*)curl << ", \"" << url << "\", " << inlength << ", " << ((ret && outlength) ? *outlength : 1) << ") = \"" << ret << '"');
return ret; return ret;
} }
void debug_curl_free(char* ptr) void debug_curl_free(char* ptr)
{ {
curl_free(ptr); curl_free(ptr);
Dout(dc::curl, "curl_free(0x" << std::hex << (size_t)ptr << std::dec << ")"); if (gDebugCurlTerse) return;
Dout(dc::curltr, "curl_free(0x" << std::hex << (size_t)ptr << std::dec << ")");
} }
time_t debug_curl_getdate(char const* datestring, time_t* now) time_t debug_curl_getdate(char const* datestring, time_t* now)
{ {
time_t ret; time_t ret;
ret = curl_getdate(datestring, now); ret = curl_getdate(datestring, now);
Dout(dc::curl, "curl_getdate(\"" << datestring << "\", " << (now == NULL ? "NULL" : "<erroneous non-NULL value for 'now'>") << ") = " << ret); if (gDebugCurlTerse) return ret;
Dout(dc::curltr, "curl_getdate(\"" << datestring << "\", " << (now == NULL ? "NULL" : "<erroneous non-NULL value for 'now'>") << ") = " << ret);
return ret; return ret;
} }
void debug_curl_global_cleanup(void) void debug_curl_global_cleanup(void)
{ {
curl_global_cleanup(); curl_global_cleanup();
Dout(dc::curl, "curl_global_cleanup()"); Dout(dc::curltr, "curl_global_cleanup()");
} }
CURLcode debug_curl_global_init(long flags) CURLcode debug_curl_global_init(long flags)
{ {
CURLcode ret; CURLcode ret;
ret = curl_global_init(flags); ret = curl_global_init(flags);
Dout(dc::curl, "curl_global_init(0x" << std::hex << flags << std::dec << ") = " << ret); Dout(dc::curltr, "curl_global_init(0x" << std::hex << flags << std::dec << ") = " << ret);
return ret; return ret;
} }
@@ -795,7 +863,8 @@ CURLMcode debug_curl_multi_add_handle(CURLM* multi_handle, CURL* easy_handle)
{ {
CURLMcode ret; CURLMcode ret;
ret = curl_multi_add_handle(multi_handle, easy_handle); ret = curl_multi_add_handle(multi_handle, easy_handle);
Dout(dc::curl, "curl_multi_add_handle(" << (AICURLM*)multi_handle << ", " << (AICURL*)easy_handle << ") = " << ret); if (gDebugCurlTerse) return ret;
Dout(dc::curltr, "curl_multi_add_handle(" << (AICURLM*)multi_handle << ", " << (AICURL*)easy_handle << ") = " << ret);
return ret; return ret;
} }
@@ -803,7 +872,8 @@ CURLMcode debug_curl_multi_assign(CURLM* multi_handle, curl_socket_t sockfd, voi
{ {
CURLMcode ret; CURLMcode ret;
ret = curl_multi_assign(multi_handle, sockfd, sockptr); ret = curl_multi_assign(multi_handle, sockfd, sockptr);
Dout(dc::curl, "curl_multi_assign(" << (AICURLM*)multi_handle << ", " << Socket(sockfd) << ", " << sockptr << ") = " << ret); if (gDebugCurlTerse) return ret;
Dout(dc::curltr, "curl_multi_assign(" << (AICURLM*)multi_handle << ", " << Socket(sockfd) << ", " << sockptr << ") = " << ret);
return ret; return ret;
} }
@@ -811,7 +881,8 @@ CURLMcode debug_curl_multi_cleanup(CURLM* multi_handle)
{ {
CURLMcode ret; CURLMcode ret;
ret = curl_multi_cleanup(multi_handle); ret = curl_multi_cleanup(multi_handle);
Dout(dc::curl, "curl_multi_cleanup(" << (AICURLM*)multi_handle << ") = " << ret); if (gDebugCurlTerse) return ret;
Dout(dc::curltr, "curl_multi_cleanup(" << (AICURLM*)multi_handle << ") = " << ret);
return ret; return ret;
} }
@@ -819,7 +890,8 @@ CURLMsg* debug_curl_multi_info_read(CURLM* multi_handle, int* msgs_in_queue)
{ {
CURLMsg* ret; CURLMsg* ret;
ret = curl_multi_info_read(multi_handle, msgs_in_queue); ret = curl_multi_info_read(multi_handle, msgs_in_queue);
Dout(dc::curl, "curl_multi_info_read(" << (AICURLM*)multi_handle << ", {" << *msgs_in_queue << "}) = " << ret); if (gDebugCurlTerse) return ret;
Dout(dc::curltr, "curl_multi_info_read(" << (AICURLM*)multi_handle << ", {" << *msgs_in_queue << "}) = " << ret);
return ret; return ret;
} }
@@ -827,7 +899,8 @@ CURLM* debug_curl_multi_init(void)
{ {
CURLM* ret; CURLM* ret;
ret = curl_multi_init(); ret = curl_multi_init();
Dout(dc::curl, "curl_multi_init() = " << (AICURLM*)ret); if (gDebugCurlTerse) return ret;
Dout(dc::curltr, "curl_multi_init() = " << (AICURLM*)ret);
return ret; return ret;
} }
@@ -835,7 +908,8 @@ CURLMcode debug_curl_multi_remove_handle(CURLM* multi_handle, CURL* easy_handle)
{ {
CURLMcode ret; CURLMcode ret;
ret = curl_multi_remove_handle(multi_handle, easy_handle); ret = curl_multi_remove_handle(multi_handle, easy_handle);
Dout(dc::curl, "curl_multi_remove_handle(" << (AICURLM*)multi_handle << ", " << (AICURL*)easy_handle << ") = " << ret); if (!print_debug(easy_handle)) return ret;
Dout(dc::curltr, "curl_multi_remove_handle(" << (AICURLM*)multi_handle << ", " << (AICURL*)easy_handle << ") = " << ret);
return ret; return ret;
} }
@@ -871,19 +945,23 @@ CURLMcode debug_curl_multi_setopt(CURLM* multi_handle, CURLMoption option, ...)
{ {
case CURLOPTTYPE_LONG: case CURLOPTTYPE_LONG:
ret = curl_multi_setopt(multi_handle, option, param.along); ret = curl_multi_setopt(multi_handle, option, param.along);
Dout(dc::curl, "curl_easy_setopt(" << (AICURLM*)multi_handle << ", " << option << ", " << param.along << "L) = " << ret); if (gDebugCurlTerse) break;
Dout(dc::curltr, "curl_easy_setopt(" << (AICURLM*)multi_handle << ", " << option << ", " << param.along << "L) = " << ret);
break; break;
case CURLOPTTYPE_OBJECTPOINT: case CURLOPTTYPE_OBJECTPOINT:
ret = curl_multi_setopt(multi_handle, option, param.ptr); ret = curl_multi_setopt(multi_handle, option, param.ptr);
Dout(dc::curl, "curl_easy_setopt(" << (AICURLM*)multi_handle << ", " << option << ", (object*)0x" << std::hex << (size_t)param.ptr << std::dec << ") = " << ret); if (gDebugCurlTerse) break;
Dout(dc::curltr, "curl_easy_setopt(" << (AICURLM*)multi_handle << ", " << option << ", (object*)0x" << std::hex << (size_t)param.ptr << std::dec << ") = " << ret);
break; break;
case CURLOPTTYPE_FUNCTIONPOINT: case CURLOPTTYPE_FUNCTIONPOINT:
ret = curl_multi_setopt(multi_handle, option, param.ptr); ret = curl_multi_setopt(multi_handle, option, param.ptr);
Dout(dc::curl, "curl_easy_setopt(" << (AICURLM*)multi_handle << ", " << option << ", (function*)0x" << std::hex << (size_t)param.ptr << std::dec << ") = " << ret); if (gDebugCurlTerse) break;
Dout(dc::curltr, "curl_easy_setopt(" << (AICURLM*)multi_handle << ", " << option << ", (function*)0x" << std::hex << (size_t)param.ptr << std::dec << ") = " << ret);
break; break;
case CURLOPTTYPE_OFF_T: case CURLOPTTYPE_OFF_T:
ret = curl_multi_setopt(multi_handle, option, param.offset); ret = curl_multi_setopt(multi_handle, option, param.offset);
Dout(dc::curl, "curl_easy_setopt(" << (AICURLM*)multi_handle << ", " << option << ", (curl_off_t)" << param.offset << ") = " << ret); if (gDebugCurlTerse) break;
Dout(dc::curltr, "curl_easy_setopt(" << (AICURLM*)multi_handle << ", " << option << ", (curl_off_t)" << param.offset << ") = " << ret);
break; break;
default: // Stop compiler complaining about no default. default: // Stop compiler complaining about no default.
break; break;
@@ -895,7 +973,8 @@ CURLMcode debug_curl_multi_socket_action(CURLM* multi_handle, curl_socket_t sock
{ {
CURLMcode ret; CURLMcode ret;
ret = curl_multi_socket_action(multi_handle, sockfd, ev_bitmask, running_handles); ret = curl_multi_socket_action(multi_handle, sockfd, ev_bitmask, running_handles);
Dout(dc::curl, "curl_multi_socket_action(" << (AICURLM*)multi_handle << ", " << Socket(sockfd) << if (gDebugCurlTerse) return ret;
Dout(dc::curltr, "curl_multi_socket_action(" << (AICURLM*)multi_handle << ", " << Socket(sockfd) <<
", " << EvBitmask(ev_bitmask) << ", {" << (ret == CURLM_OK ? *running_handles : 0) << "}) = " << ret); ", " << EvBitmask(ev_bitmask) << ", {" << (ret == CURLM_OK ? *running_handles : 0) << "}) = " << ret);
return ret; return ret;
} }
@@ -904,7 +983,8 @@ char const* debug_curl_multi_strerror(CURLMcode errornum)
{ {
char const* ret; char const* ret;
ret = curl_multi_strerror(errornum); ret = curl_multi_strerror(errornum);
Dout(dc::curl, "curl_multi_strerror(" << errornum << ") = \"" << ret << '"'); if (gDebugCurlTerse) return ret;
Dout(dc::curltr, "curl_multi_strerror(" << errornum << ") = \"" << ret << '"');
return ret; return ret;
} }
@@ -912,21 +992,24 @@ struct curl_slist* debug_curl_slist_append(struct curl_slist* list, char const*
{ {
struct curl_slist* ret; struct curl_slist* ret;
ret = curl_slist_append(list, string); ret = curl_slist_append(list, string);
Dout(dc::curl, "curl_slist_append((curl_slist)@0x" << std::hex << (size_t)list << std::dec << ", \"" << string << "\") = " << *ret); if (gDebugCurlTerse) return ret;
Dout(dc::curltr, "curl_slist_append((curl_slist)@0x" << std::hex << (size_t)list << std::dec << ", \"" << string << "\") = " << *ret);
return ret; return ret;
} }
void debug_curl_slist_free_all(struct curl_slist* list) void debug_curl_slist_free_all(struct curl_slist* list)
{ {
curl_slist_free_all(list); curl_slist_free_all(list);
Dout(dc::curl, "curl_slist_free_all((curl_slist)@0x" << std::hex << (size_t)list << std::dec << ")"); if (gDebugCurlTerse) return;
Dout(dc::curltr, "curl_slist_free_all((curl_slist)@0x" << std::hex << (size_t)list << std::dec << ")");
} }
char* debug_curl_unescape(char const* url, int length) char* debug_curl_unescape(char const* url, int length)
{ {
char* ret; char* ret;
ret = curl_unescape(url, length); ret = curl_unescape(url, length);
Dout(dc::curl, "curl_unescape(\"" << url << "\", " << length << ") = \"" << ret << '"'); if (gDebugCurlTerse) return ret;
Dout(dc::curltr, "curl_unescape(\"" << url << "\", " << length << ") = \"" << ret << '"');
return ret; return ret;
} }
@@ -934,7 +1017,8 @@ char* debug_curl_version(void)
{ {
char* ret; char* ret;
ret = curl_version(); ret = curl_version();
Dout(dc::curl, "curl_version() = \"" << ret << '"'); if (gDebugCurlTerse) return ret;
Dout(dc::curltr, "curl_version() = \"" << ret << '"');
return ret; return ret;
} }

View File

@@ -86,4 +86,9 @@ extern char* debug_curl_version(void);
#endif // !COMPILING_DEBUG_LIBCURL_CC #endif // !COMPILING_DEBUG_LIBCURL_CC
extern bool gDebugCurlTerse; // With this set,
void debug_curl_add_easy(CURL* handle); // only output debug output for easy handles added with this function.
void debug_curl_remove_easy(CURL* handle);
bool debug_curl_print_debug(CURL* handle);
#endif // DEBUG_LIBCURL #endif // DEBUG_LIBCURL

View File

@@ -200,7 +200,9 @@ static void request(
LLURLRequest::ERequestAction method, LLURLRequest::ERequestAction method,
Injector* body_injector, Injector* body_injector,
LLHTTPClient::ResponderPtr responder, LLHTTPClient::ResponderPtr responder,
AIHTTPHeaders& headers, AIHTTPHeaders& headers/*,*/
DEBUG_CURLIO_PARAM(EDebugCurl debug),
EKeepAlive keepalive = keep_alive,
bool is_auth = false, bool is_auth = false,
bool no_compression = false) bool no_compression = false)
{ {
@@ -213,7 +215,10 @@ static void request(
LLURLRequest* req; LLURLRequest* req;
try try
{ {
req = new LLURLRequest(method, url, body_injector, responder, headers, is_auth, no_compression); req = new LLURLRequest(method, url, body_injector, responder, headers, keepalive, is_auth, no_compression);
#ifdef DEBUG_CURLIO
req->mCurlEasyRequest.debug(debug);
#endif
} }
catch(AICurlNoEasyHandle& error) catch(AICurlNoEasyHandle& error)
{ {
@@ -225,36 +230,36 @@ static void request(
req->run(); req->run();
} }
void LLHTTPClient::getByteRange(std::string const& url, S32 offset, S32 bytes, ResponderPtr responder, AIHTTPHeaders& headers) void LLHTTPClient::getByteRange(std::string const& url, S32 offset, S32 bytes, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug))
{ {
if(offset > 0 || bytes > 0) if(offset > 0 || bytes > 0)
{ {
headers.addHeader("Range", llformat("bytes=%d-%d", offset, offset + bytes - 1)); headers.addHeader("Range", llformat("bytes=%d-%d", offset, offset + bytes - 1));
} }
request(url, LLURLRequest::HTTP_GET, NULL, responder, headers); request(url, LLURLRequest::HTTP_GET, NULL, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug));
} }
void LLHTTPClient::head(std::string const& url, ResponderHeadersOnly* responder, AIHTTPHeaders& headers) void LLHTTPClient::head(std::string const& url, ResponderHeadersOnly* responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug))
{ {
request(url, LLURLRequest::HTTP_HEAD, NULL, responder, headers); request(url, LLURLRequest::HTTP_HEAD, NULL, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug));
} }
void LLHTTPClient::get(std::string const& url, ResponderPtr responder, AIHTTPHeaders& headers) void LLHTTPClient::get(std::string const& url, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug))
{ {
request(url, LLURLRequest::HTTP_GET, NULL, responder, headers); request(url, LLURLRequest::HTTP_GET, NULL, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug));
} }
void LLHTTPClient::getHeaderOnly(std::string const& url, ResponderHeadersOnly* responder, AIHTTPHeaders& headers) void LLHTTPClient::getHeaderOnly(std::string const& url, ResponderHeadersOnly* responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug))
{ {
request(url, LLURLRequest::HTTP_HEAD, NULL, responder, headers); request(url, LLURLRequest::HTTP_HEAD, NULL, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug));
} }
void LLHTTPClient::get(std::string const& url, LLSD const& query, ResponderPtr responder, AIHTTPHeaders& headers) void LLHTTPClient::get(std::string const& url, LLSD const& query, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug))
{ {
LLURI uri; LLURI uri;
uri = LLURI::buildHTTP(url, LLSD::emptyArray(), query); uri = LLURI::buildHTTP(url, LLSD::emptyArray(), query);
get(uri.asString(), responder, headers); get(uri.asString(), responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug));
} }
//============================================================================= //=============================================================================
@@ -362,6 +367,22 @@ void LLHTTPClient::ResponderBase::decode_raw_body(U32 status, std::string const&
} }
} }
std::string const& LLHTTPClient::ResponderBase::get_cookie(std::string const& key)
{
AIHTTPReceivedHeaders::range_type cookies;
mReceivedHeaders.getValues("set-cookie", cookies);
for (AIHTTPReceivedHeaders::iterator_type cookie = cookies.first; cookie != cookies.second; ++cookie)
{
if (key == cookie->second.substr(0, cookie->second.find('=')))
{
return cookie->second;
}
}
// Not found.
static std::string empty_dummy;
return empty_dummy;
}
// Called with HTML body. // Called with HTML body.
// virtual // virtual
void LLHTTPClient::ResponderWithCompleted::completedRaw(U32 status, std::string const& reason, LLChannelDescriptors const& channels, buffer_ptr_t const& buffer) void LLHTTPClient::ResponderWithCompleted::completedRaw(U32 status, std::string const& reason, LLChannelDescriptors const& channels, buffer_ptr_t const& buffer)
@@ -554,7 +575,8 @@ enum EBlockingRequestAction {
static LLSD blocking_request( static LLSD blocking_request(
std::string const& url, std::string const& url,
EBlockingRequestAction method, EBlockingRequestAction method,
LLSD const& body) // Only used for HTTP_LLSD_POST LLSD const& body/*,*/ // Only used for HTTP_LLSD_POST
DEBUG_CURLIO_PARAM(EDebugCurl debug))
{ {
lldebugs << "blockingRequest of " << url << llendl; lldebugs << "blockingRequest of " << url << llendl;
@@ -563,17 +585,17 @@ static LLSD blocking_request(
if (method == HTTP_LLSD_POST) if (method == HTTP_LLSD_POST)
{ {
responder = new BlockingLLSDPostResponder; responder = new BlockingLLSDPostResponder;
LLHTTPClient::post(url, body, responder, headers); LLHTTPClient::post(url, body, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug));
} }
else if (method == HTTP_LLSD_GET) else if (method == HTTP_LLSD_GET)
{ {
responder = new BlockingLLSDGetResponder; responder = new BlockingLLSDGetResponder;
LLHTTPClient::get(url, responder, headers); LLHTTPClient::get(url, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug));
} }
else // method == HTTP_RAW_GET else // method == HTTP_RAW_GET
{ {
responder = new BlockingRawGetResponder; responder = new BlockingRawGetResponder;
LLHTTPClient::get(url, responder, headers); LLHTTPClient::get(url, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug));
} }
responder->wait(); responder->wait();
@@ -635,39 +657,39 @@ static LLSD blocking_request(
return response; return response;
} }
LLSD LLHTTPClient::blockingPost(const std::string& url, const LLSD& body) LLSD LLHTTPClient::blockingPost(const std::string& url, const LLSD& body/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug))
{ {
return blocking_request(url, HTTP_LLSD_POST, body); return blocking_request(url, HTTP_LLSD_POST, body/*,*/ DEBUG_CURLIO_PARAM(debug));
} }
LLSD LLHTTPClient::blockingGet(const std::string& url) LLSD LLHTTPClient::blockingGet(const std::string& url/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug))
{ {
return blocking_request(url, HTTP_LLSD_GET, LLSD()); return blocking_request(url, HTTP_LLSD_GET, LLSD()/*,*/ DEBUG_CURLIO_PARAM(debug));
} }
U32 LLHTTPClient::blockingGetRaw(const std::string& url, std::string& body) U32 LLHTTPClient::blockingGetRaw(const std::string& url, std::string& body/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug))
{ {
LLSD result = blocking_request(url, HTTP_RAW_GET, LLSD()); LLSD result = blocking_request(url, HTTP_RAW_GET, LLSD()/*,*/ DEBUG_CURLIO_PARAM(debug));
body = result["body"].asString(); body = result["body"].asString();
return result["status"].asInteger(); return result["status"].asInteger();
} }
void LLHTTPClient::put(std::string const& url, LLSD const& body, ResponderPtr responder, AIHTTPHeaders& headers) void LLHTTPClient::put(std::string const& url, LLSD const& body, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug))
{ {
request(url, LLURLRequest::HTTP_PUT, new LLSDInjector(body), responder, headers); request(url, LLURLRequest::HTTP_PUT, new LLSDInjector(body), responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug));
} }
void LLHTTPClient::post(std::string const& url, LLSD const& body, ResponderPtr responder, AIHTTPHeaders& headers) void LLHTTPClient::post(std::string const& url, LLSD const& body, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug), EKeepAlive keepalive)
{ {
request(url, LLURLRequest::HTTP_POST, new LLSDInjector(body), responder, headers); request(url, LLURLRequest::HTTP_POST, new LLSDInjector(body), responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug), keepalive);
} }
void LLHTTPClient::postXMLRPC(std::string const& url, XMLRPC_REQUEST xmlrpc_request, ResponderPtr responder, AIHTTPHeaders& headers) void LLHTTPClient::postXMLRPC(std::string const& url, XMLRPC_REQUEST xmlrpc_request, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug), EKeepAlive keepalive)
{ {
request(url, LLURLRequest::HTTP_POST, new XMLRPCInjector(xmlrpc_request), responder, headers, true, false); // Does use compression. request(url, LLURLRequest::HTTP_POST, new XMLRPCInjector(xmlrpc_request), responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug), keepalive, true, false); // Does use compression.
} }
void LLHTTPClient::postXMLRPC(std::string const& url, char const* method, XMLRPC_VALUE value, ResponderPtr responder, AIHTTPHeaders& headers) void LLHTTPClient::postXMLRPC(std::string const& url, char const* method, XMLRPC_VALUE value, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug), EKeepAlive keepalive)
{ {
XMLRPC_REQUEST xmlrpc_request = XMLRPC_RequestNew(); XMLRPC_REQUEST xmlrpc_request = XMLRPC_RequestNew();
XMLRPC_RequestSetMethodName(xmlrpc_request, method); XMLRPC_RequestSetMethodName(xmlrpc_request, method);
@@ -675,33 +697,33 @@ void LLHTTPClient::postXMLRPC(std::string const& url, char const* method, XMLRPC
XMLRPC_RequestSetData(xmlrpc_request, value); XMLRPC_RequestSetData(xmlrpc_request, value);
// XMLRPCInjector takes ownership of xmlrpc_request and will free it when done. // XMLRPCInjector takes ownership of xmlrpc_request and will free it when done.
// LLURLRequest takes ownership of the XMLRPCInjector object and will free it when done. // LLURLRequest takes ownership of the XMLRPCInjector object and will free it when done.
request(url, LLURLRequest::HTTP_POST, new XMLRPCInjector(xmlrpc_request), responder, headers, true, true); // Does not use compression. request(url, LLURLRequest::HTTP_POST, new XMLRPCInjector(xmlrpc_request), responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug), keepalive, true, true); // Does not use compression.
} }
void LLHTTPClient::postRaw(std::string const& url, char const* data, S32 size, ResponderPtr responder, AIHTTPHeaders& headers) void LLHTTPClient::postRaw(std::string const& url, char const* data, S32 size, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug), EKeepAlive keepalive)
{ {
request(url, LLURLRequest::HTTP_POST, new RawInjector(data, size), responder, headers); request(url, LLURLRequest::HTTP_POST, new RawInjector(data, size), responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug), keepalive);
} }
void LLHTTPClient::postFile(std::string const& url, std::string const& filename, ResponderPtr responder, AIHTTPHeaders& headers) void LLHTTPClient::postFile(std::string const& url, std::string const& filename, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug), EKeepAlive keepalive)
{ {
request(url, LLURLRequest::HTTP_POST, new FileInjector(filename), responder, headers); request(url, LLURLRequest::HTTP_POST, new FileInjector(filename), responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug), keepalive);
} }
void LLHTTPClient::postFile(std::string const& url, LLUUID const& uuid, LLAssetType::EType asset_type, ResponderPtr responder, AIHTTPHeaders& headers) void LLHTTPClient::postFile(std::string const& url, LLUUID const& uuid, LLAssetType::EType asset_type, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug), EKeepAlive keepalive)
{ {
request(url, LLURLRequest::HTTP_POST, new VFileInjector(uuid, asset_type), responder, headers); request(url, LLURLRequest::HTTP_POST, new VFileInjector(uuid, asset_type), responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug), keepalive);
} }
// static // static
void LLHTTPClient::del(std::string const& url, ResponderPtr responder, AIHTTPHeaders& headers) void LLHTTPClient::del(std::string const& url, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug))
{ {
request(url, LLURLRequest::HTTP_DELETE, NULL, responder, headers); request(url, LLURLRequest::HTTP_DELETE, NULL, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug));
} }
// static // static
void LLHTTPClient::move(std::string const& url, std::string const& destination, ResponderPtr responder, AIHTTPHeaders& headers) void LLHTTPClient::move(std::string const& url, std::string const& destination, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug))
{ {
headers.addHeader("Destination", destination); headers.addHeader("Destination", destination);
request(url, LLURLRequest::HTTP_MOVE, NULL, responder, headers); request(url, LLURLRequest::HTTP_MOVE, NULL, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug));
} }

View File

@@ -66,6 +66,21 @@ struct AIBufferedCurlEasyRequestEvents {
virtual void completed_headers(U32 status, std::string const& reason, AITransferInfo* info) = 0; // Transaction completed. virtual void completed_headers(U32 status, std::string const& reason, AITransferInfo* info) = 0; // Transaction completed.
}; };
enum EKeepAlive {
no_keep_alive = 0,
keep_alive
};
#ifdef DEBUG_CURLIO
enum EDebugCurl {
debug_off = 0,
debug_on
};
#define DEBUG_CURLIO_PARAM(p) ,p
#else
#define DEBUG_CURLIO_PARAM(p)
#endif
class LLHTTPClient { class LLHTTPClient {
public: public:
@@ -140,7 +155,16 @@ public:
{ {
// It's possible that this page was moved (302), so we already saw headers // It's possible that this page was moved (302), so we already saw headers
// from the 302 page and are starting over on the new page now. // from the 302 page and are starting over on the new page now.
mReceivedHeaders.clear(); // Erase all headers EXCEPT the cookies.
AIHTTPReceivedHeaders set_cookie_headers;
AIHTTPReceivedHeaders::range_type cookies;
mReceivedHeaders.getValues("set-cookie", cookies);
for (AIHTTPReceivedHeaders::iterator_type cookie = cookies.first; cookie != cookies.second; ++cookie)
{
set_cookie_headers.addHeader(cookie->first, cookie->second);
}
// Replace headers with just the cookie headers.
mReceivedHeaders.swap(set_cookie_headers);
} }
// Called for all remaining headers. // Called for all remaining headers.
@@ -155,6 +179,9 @@ public:
completedHeaders(status, reason, mReceivedHeaders); completedHeaders(status, reason, mReceivedHeaders);
} }
// Extract cookie 'key' from mReceivedHeaders and return the string 'key=value', or an empty string if key does not exists.
std::string const& get_cookie(std::string const& key);
public: public:
// Derived classes that implement completed_headers()/completedHeaders() should return true here. // Derived classes that implement completed_headers()/completedHeaders() should return true here.
virtual bool needsHeaders(void) const { return false; } virtual bool needsHeaders(void) const { return false; }
@@ -163,6 +190,9 @@ public:
// The default is not to follow redirections. // The default is not to follow redirections.
virtual bool followRedir(void) const { return false; } virtual bool followRedir(void) const { return false; }
// If this function returns false then we generate an error when a redirect status (300..399) is received.
virtual bool redirect_status_ok(void) const { return followRedir(); }
// Timeout policy to use. // Timeout policy to use.
virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const = 0; virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const = 0;
@@ -358,59 +388,59 @@ public:
/** @name non-blocking API */ /** @name non-blocking API */
//@{ //@{
static void head(std::string const& url, ResponderHeadersOnly* responder, AIHTTPHeaders& headers); static void head(std::string const& url, ResponderHeadersOnly* responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off));
static void head(std::string const& url, ResponderHeadersOnly* responder) static void head(std::string const& url, ResponderHeadersOnly* responder/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off))
{ AIHTTPHeaders headers; head(url, responder, headers); } { AIHTTPHeaders headers; head(url, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug)); }
static void getByteRange(std::string const& url, S32 offset, S32 bytes, ResponderPtr responder, AIHTTPHeaders& headers); static void getByteRange(std::string const& url, S32 offset, S32 bytes, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off));
static void getByteRange(std::string const& url, S32 offset, S32 bytes, ResponderPtr responder) static void getByteRange(std::string const& url, S32 offset, S32 bytes, ResponderPtr responder/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off))
{ AIHTTPHeaders headers; getByteRange(url, offset, bytes, responder, headers); } { AIHTTPHeaders headers; getByteRange(url, offset, bytes, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug)); }
static void get(std::string const& url, ResponderPtr responder, AIHTTPHeaders& headers); static void get(std::string const& url, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off));
static void get(std::string const& url, ResponderPtr responder) static void get(std::string const& url, ResponderPtr responder/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off))
{ AIHTTPHeaders headers; get(url, responder, headers); } { AIHTTPHeaders headers; get(url, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug)); }
static void get(std::string const& url, LLSD const& query, ResponderPtr responder, AIHTTPHeaders& headers); static void get(std::string const& url, LLSD const& query, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off));
static void get(std::string const& url, LLSD const& query, ResponderPtr responder) static void get(std::string const& url, LLSD const& query, ResponderPtr responder/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off))
{ AIHTTPHeaders headers; get(url, query, responder, headers); } { AIHTTPHeaders headers; get(url, query, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug)); }
static void put(std::string const& url, LLSD const& body, ResponderPtr responder, AIHTTPHeaders& headers); static void put(std::string const& url, LLSD const& body, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off));
static void put(std::string const& url, LLSD const& body, ResponderPtr responder) static void put(std::string const& url, LLSD const& body, ResponderPtr responder/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off))
{ AIHTTPHeaders headers; put(url, body, responder, headers); } { AIHTTPHeaders headers; put(url, body, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug)); }
static void getHeaderOnly(std::string const& url, ResponderHeadersOnly* responder, AIHTTPHeaders& headers); static void getHeaderOnly(std::string const& url, ResponderHeadersOnly* responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off));
static void getHeaderOnly(std::string const& url, ResponderHeadersOnly* responder) static void getHeaderOnly(std::string const& url, ResponderHeadersOnly* responder/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off))
{ AIHTTPHeaders headers; getHeaderOnly(url, responder, headers); } { AIHTTPHeaders headers; getHeaderOnly(url, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug)); }
static void post(std::string const& url, LLSD const& body, ResponderPtr responder, AIHTTPHeaders& headers); static void post(std::string const& url, LLSD const& body, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off), EKeepAlive keepalive = keep_alive);
static void post(std::string const& url, LLSD const& body, ResponderPtr responder) static void post(std::string const& url, LLSD const& body, ResponderPtr responder/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off), EKeepAlive keepalive = keep_alive)
{ AIHTTPHeaders headers; post(url, body, responder, headers); } { AIHTTPHeaders headers; post(url, body, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug), keepalive); }
/** Takes ownership of request and deletes it when sent */ /** Takes ownership of request and deletes it when sent */
static void postXMLRPC(std::string const& url, XMLRPC_REQUEST request, ResponderPtr responder, AIHTTPHeaders& headers); static void postXMLRPC(std::string const& url, XMLRPC_REQUEST request, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off), EKeepAlive keepalive = keep_alive);
static void postXMLRPC(std::string const& url, XMLRPC_REQUEST request, ResponderPtr responder) static void postXMLRPC(std::string const& url, XMLRPC_REQUEST request, ResponderPtr responder/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off), EKeepAlive keepalive = keep_alive)
{ AIHTTPHeaders headers; postXMLRPC(url, request, responder, headers); } { AIHTTPHeaders headers; postXMLRPC(url, request, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug), keepalive); }
static void postXMLRPC(std::string const& url, char const* method, XMLRPC_VALUE value, ResponderPtr responder, AIHTTPHeaders& headers); static void postXMLRPC(std::string const& url, char const* method, XMLRPC_VALUE value, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off), EKeepAlive keepalive = keep_alive);
static void postXMLRPC(std::string const& url, char const* method, XMLRPC_VALUE value, ResponderPtr responder) static void postXMLRPC(std::string const& url, char const* method, XMLRPC_VALUE value, ResponderPtr responder/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off), EKeepAlive keepalive = keep_alive)
{ AIHTTPHeaders headers; postXMLRPC(url, method, value, responder, headers); } { AIHTTPHeaders headers; postXMLRPC(url, method, value, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug), keepalive); }
/** Takes ownership of data and deletes it when sent */ /** Takes ownership of data and deletes it when sent */
static void postRaw(std::string const& url, const char* data, S32 size, ResponderPtr responder, AIHTTPHeaders& headers); static void postRaw(std::string const& url, const char* data, S32 size, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off), EKeepAlive keepalive = keep_alive);
static void postRaw(std::string const& url, const char* data, S32 size, ResponderPtr responder) static void postRaw(std::string const& url, const char* data, S32 size, ResponderPtr responder/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off), EKeepAlive keepalive = keep_alive)
{ AIHTTPHeaders headers; postRaw(url, data, size, responder, headers); } { AIHTTPHeaders headers; postRaw(url, data, size, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug), keepalive); }
static void postFile(std::string const& url, std::string const& filename, ResponderPtr responder, AIHTTPHeaders& headers); static void postFile(std::string const& url, std::string const& filename, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off), EKeepAlive keepalive = keep_alive);
static void postFile(std::string const& url, std::string const& filename, ResponderPtr responder) static void postFile(std::string const& url, std::string const& filename, ResponderPtr responder/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off), EKeepAlive keepalive = keep_alive)
{ AIHTTPHeaders headers; postFile(url, filename, responder, headers); } { AIHTTPHeaders headers; postFile(url, filename, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug), keepalive); }
static void postFile(std::string const& url, const LLUUID& uuid, LLAssetType::EType asset_type, ResponderPtr responder, AIHTTPHeaders& headers); static void postFile(std::string const& url, const LLUUID& uuid, LLAssetType::EType asset_type, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off), EKeepAlive keepalive = keep_alive);
static void postFile(std::string const& url, const LLUUID& uuid, LLAssetType::EType asset_type, ResponderPtr responder) static void postFile(std::string const& url, const LLUUID& uuid, LLAssetType::EType asset_type, ResponderPtr responder/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off), EKeepAlive keepalive = keep_alive)
{ AIHTTPHeaders headers; postFile(url, uuid, asset_type, responder, headers); } { AIHTTPHeaders headers; postFile(url, uuid, asset_type, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug), keepalive); }
static void del(std::string const& url, ResponderPtr responder, AIHTTPHeaders& headers); static void del(std::string const& url, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off));
static void del(std::string const& url, ResponderPtr responder) static void del(std::string const& url, ResponderPtr responder/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off))
{ AIHTTPHeaders headers; del(url, responder, headers); } { AIHTTPHeaders headers; del(url, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug)); }
///< sends a DELETE method, but we can't call it delete in c++ ///< sends a DELETE method, but we can't call it delete in c++
@@ -423,9 +453,9 @@ public:
* @param headers A map of key:value headers to pass to the request * @param headers A map of key:value headers to pass to the request
* @param timeout The number of seconds to give the server to respond. * @param timeout The number of seconds to give the server to respond.
*/ */
static void move(std::string const& url, std::string const& destination, ResponderPtr responder, AIHTTPHeaders& headers); static void move(std::string const& url, std::string const& destination, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off));
static void move(std::string const& url, std::string const& destination, ResponderPtr responder) static void move(std::string const& url, std::string const& destination, ResponderPtr responder/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off))
{ AIHTTPHeaders headers; move(url, destination, responder, headers); } { AIHTTPHeaders headers; move(url, destination, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug)); }
//@} //@}
@@ -435,7 +465,7 @@ public:
* @param url the complete serialized (and escaped) url to get * @param url the complete serialized (and escaped) url to get
* @return An LLSD of { 'status':status, 'body':payload } * @return An LLSD of { 'status':status, 'body':payload }
*/ */
static LLSD blockingGet(std::string const& url); static LLSD blockingGet(std::string const& url/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off));
/** /**
* @brief Blocking HTTP GET that returns the raw body. * @brief Blocking HTTP GET that returns the raw body.
@@ -444,7 +474,7 @@ public:
* @param result the target string to write the body to * @param result the target string to write the body to
* @return HTTP status * @return HTTP status
*/ */
static U32 blockingGetRaw(const std::string& url, std::string& result); static U32 blockingGetRaw(const std::string& url, std::string& result/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off));
/** /**
* @brief Blocking HTTP POST that returns an LLSD map of status and body. * @brief Blocking HTTP POST that returns an LLSD map of status and body.
@@ -453,7 +483,7 @@ public:
* @param body the LLSD post body * @param body the LLSD post body
* @return An LLSD of { 'status':status (an int), 'body':payload (an LLSD) } * @return An LLSD of { 'status':status (an int), 'body':payload (an LLSD) }
*/ */
static LLSD blockingPost(std::string const& url, LLSD const& body); static LLSD blockingPost(std::string const& url, LLSD const& body/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off));
}; };
#endif // LL_LLHTTPCLIENT_H #endif // LL_LLHTTPCLIENT_H

View File

@@ -77,8 +77,8 @@ std::string LLURLRequest::actionAsVerb(LLURLRequest::ERequestAction action)
// This might throw AICurlNoEasyHandle. // This might throw AICurlNoEasyHandle.
LLURLRequest::LLURLRequest(LLURLRequest::ERequestAction action, std::string const& url, Injector* body, LLURLRequest::LLURLRequest(LLURLRequest::ERequestAction action, std::string const& url, Injector* body,
LLHTTPClient::ResponderPtr responder, AIHTTPHeaders& headers, bool is_auth, bool no_compression) : LLHTTPClient::ResponderPtr responder, AIHTTPHeaders& headers, bool keepalive, bool is_auth, bool no_compression) :
mAction(action), mURL(url), mIsAuth(is_auth), mNoCompression(no_compression), mAction(action), mURL(url), mKeepAlive(keepalive), mIsAuth(is_auth), mNoCompression(no_compression),
mBody(body), mResponder(responder), mHeaders(headers) mBody(body), mResponder(responder), mHeaders(headers)
{ {
} }
@@ -226,7 +226,7 @@ bool LLURLRequest::configure(AICurlEasyRequest_wat const& curlEasyRequest_w)
case HTTP_POST: case HTTP_POST:
{ {
// Set the handle for an http post // Set the handle for an http post
curlEasyRequest_w->setPost(mBodySize); curlEasyRequest_w->setPost(mBodySize, mKeepAlive);
// Set Accept-Encoding to allow response compression // Set Accept-Encoding to allow response compression
curlEasyRequest_w->setoptString(CURLOPT_ENCODING, mNoCompression ? "identity" : ""); curlEasyRequest_w->setoptString(CURLOPT_ENCODING, mNoCompression ? "identity" : "");

View File

@@ -77,7 +77,7 @@ class LLURLRequest : public AICurlEasyRequestStateMachine {
* @param action One of the ERequestAction enumerations. * @param action One of the ERequestAction enumerations.
* @param url The url of the request. It should already be encoded. * @param url The url of the request. It should already be encoded.
*/ */
LLURLRequest(ERequestAction action, std::string const& url, Injector* body, LLHTTPClient::ResponderPtr responder, AIHTTPHeaders& headers, bool is_auth, bool no_compression); LLURLRequest(ERequestAction action, std::string const& url, Injector* body, LLHTTPClient::ResponderPtr responder, AIHTTPHeaders& headers, bool keepalive, bool is_auth, bool no_compression);
protected: protected:
// Call abort(), not delete. // Call abort(), not delete.
@@ -111,6 +111,7 @@ class LLURLRequest : public AICurlEasyRequestStateMachine {
private: private:
ERequestAction mAction; ERequestAction mAction;
std::string mURL; std::string mURL;
bool mKeepAlive; // Set to false only when explicitely requested.
bool mIsAuth; // Set for authentication messages (login, buy land, buy currency). bool mIsAuth; // Set for authentication messages (login, buy land, buy currency).
bool mNoCompression; // Set to disable using gzip. bool mNoCompression; // Set to disable using gzip.
Injector* mBody; // Non-zero iff the action is HTTP_POST and HTTP_PUT. Injector* mBody; // Non-zero iff the action is HTTP_POST and HTTP_PUT.

View File

@@ -155,12 +155,6 @@ public:
/*virtual*/ QuadType preDraw() /*virtual*/ QuadType preDraw()
{ {
/// CALCULATING LUMINANCE (Using NTSC lum weights)
/// http://en.wikipedia.org/wiki/Luma_%28video%29
static const float LUMINANCE_R = 0.299f;
static const float LUMINANCE_G = 0.587f;
static const float LUMINANCE_B = 0.114f;
getShader().uniform1f("gamma", mGamma); getShader().uniform1f("gamma", mGamma);
getShader().uniform1f("brightness", mBrightness); getShader().uniform1f("brightness", mBrightness);
getShader().uniform1f("contrast", mContrast); getShader().uniform1f("contrast", mContrast);

View File

@@ -197,8 +197,9 @@ set(viewer_SOURCE_FILES
llfloaterevent.cpp llfloaterevent.cpp
llfloaterexploreanimations.cpp llfloaterexploreanimations.cpp
llfloaterexploresounds.cpp llfloaterexploresounds.cpp
llfloaterfriends.cpp llfloaterfeed.cpp
llfloaterfonttest.cpp llfloaterfonttest.cpp
llfloaterfriends.cpp
llfloatergesture.cpp llfloatergesture.cpp
llfloatergodtools.cpp llfloatergodtools.cpp
llfloatergroupinfo.cpp llfloatergroupinfo.cpp
@@ -301,6 +302,7 @@ set(viewer_SOURCE_FILES
lllogchat.cpp lllogchat.cpp
llloginhandler.cpp llloginhandler.cpp
llmainlooprepeater.cpp llmainlooprepeater.cpp
llmakeoutfitdialog.cpp
llmanip.cpp llmanip.cpp
llmaniprotate.cpp llmaniprotate.cpp
llmanipscale.cpp llmanipscale.cpp
@@ -312,6 +314,7 @@ set(viewer_SOURCE_FILES
llmediaremotectrl.cpp llmediaremotectrl.cpp
llmemoryview.cpp llmemoryview.cpp
llmenucommands.cpp llmenucommands.cpp
llmenuoptionpathfindingrebakenavmesh.cpp
llmeshrepository.cpp llmeshrepository.cpp
llmimetypes.cpp llmimetypes.cpp
llmorphview.cpp llmorphview.cpp
@@ -366,7 +369,6 @@ set(viewer_SOURCE_FILES
llpanelnetwork.cpp llpanelnetwork.cpp
llpanelobject.cpp llpanelobject.cpp
llpanelobjectinventory.cpp llpanelobjectinventory.cpp
llpanelpathfindingrebakenavmesh.cpp
llpanelpermissions.cpp llpanelpermissions.cpp
llpanelpick.cpp llpanelpick.cpp
llpanelplace.cpp llpanelplace.cpp
@@ -695,6 +697,7 @@ set(viewer_HEADER_FILES
llfloaterexploreanimations.h llfloaterexploreanimations.h
llfloaterexploresounds.h llfloaterexploresounds.h
llfloaterevent.h llfloaterevent.h
llfloaterfeed.h
llfloaterfonttest.h llfloaterfonttest.h
llfloaterfriends.h llfloaterfriends.h
llfloatergesture.h llfloatergesture.h
@@ -799,6 +802,7 @@ set(viewer_HEADER_FILES
lllogchat.h lllogchat.h
llloginhandler.h llloginhandler.h
llmainlooprepeater.h llmainlooprepeater.h
llmakeoutfitdialog.h
llmanip.h llmanip.h
llmaniprotate.h llmaniprotate.h
llmanipscale.h llmanipscale.h
@@ -809,6 +813,7 @@ set(viewer_HEADER_FILES
llmediactrl.h llmediactrl.h
llmediaremotectrl.h llmediaremotectrl.h
llmemoryview.h llmemoryview.h
llmenuoptionpathfindingrebakenavmesh.h
llmenucommands.h llmenucommands.h
llmeshrepository.h llmeshrepository.h
llmimetypes.h llmimetypes.h
@@ -864,7 +869,6 @@ set(viewer_HEADER_FILES
llpanelnetwork.h llpanelnetwork.h
llpanelobject.h llpanelobject.h
llpanelobjectinventory.h llpanelobjectinventory.h
llpanelpathfindingrebakenavmesh.h
llpanelpermissions.h llpanelpermissions.h
llpanelpick.h llpanelpick.h
llpanelplace.h llpanelplace.h

View File

@@ -701,7 +701,23 @@ CHARACTER_MAX_TURN_RADIUS TODO: add documentation
# --- OpenSim and Aurora-Sim constants Below --- # --- OpenSim and Aurora-Sim constants Below ---
# OpenSim Constants (\OpenSim\Region\ScriptEngine\Shared\Api\Runtime\LSL_Constants.cs) # OpenSim Constants (\OpenSim\Region\ScriptEngine\Shared\Api\Runtime\LSL_Constants.cs)
# Constants for cmWindlight (\OpenSim\Region\ScriptEngine\Shared\Api\Runtime\CM_Constants.cs) # Constants for cmWindlight (\OpenSim\Region\ScriptEngine\Shared\Api\Runtime\CM_Constants.cs)
CHANGED_ANIMATION OpenSim change event animation change detection. CHANGED_ANIMATION OpenSim change event animation change detection.
CAMERA_FOCUS_OFFSET_X OpenSim enhancement for llSetCameraParams(), adjusts the camera focus x position relative to the target. (float)
CAMERA_FOCUS_OFFSET_Y OpenSim enhancement for llSetCameraParams(), adjusts the camera focus y position relative to the target. (float)
CAMERA_FOCUS_OFFSET_Z OpenSim enhancement for llSetCameraParams(), adjusts the camera focus z position relative to the target. (float)
CAMERA_POSITION_X OpenSim enhancement for llSetCameraParams(), sets camera x position in region coordinates. (float)
CAMERA_POSITION_Y OpenSim enhancement for llSetCameraParams(), sets camera y position in region coordinates. (float)
CAMERA_POSITION_Z OpenSim enhancement for llSetCameraParams(), sets camera z position in region coordinates. (float)
CAMERA_FOCUS_X OpenSim enhancement for llSetCameraParams(), sets camera x focus (target position) in region coordinates. (float)
CAMERA_FOCUS_Y OpenSim enhancement for llSetCameraParams(), sets camera y focus (target position) in region coordinates. (float)
CAMERA_FOCUS_Z OpenSim enhancement for llSetCameraParams(), sets camera z focus (target position) in region coordinates. (float)
OS_LISTEN_REGEX_NAME Value 0x1, process name parameter as regex
OS_LISTEN_REGEX_MESSAGE Value 0x2, process name parameter as regex
OS_ATTACH_MSG_ALL Used with osMessageAttachements
OS_ATTACH_MSG_INVERT_POINTS Used with osMessageAttachements
OS_ATTACH_MSG_OBJECT_CREATOR Used with osMessageAttachements
OS_ATTACH_MSG_SCRIPT_CREATOR Used with osMessageAttachements
PARCEL_DETAILS_CLAIMDATE Used with osSetParcelDetails
# osGetRegionStats # osGetRegionStats
STATS_TIME_DILATION returned value from osGetRegionStats(), 1st of 21 items in returned list. STATS_TIME_DILATION returned value from osGetRegionStats(), 1st of 21 items in returned list.
STATS_SIM_FPS returned value from osGetRegionStats(), 2nd of 21 items in returned list. STATS_SIM_FPS returned value from osGetRegionStats(), 2nd of 21 items in returned list.
@@ -725,14 +741,15 @@ STATS_PENDING_UPLOADS returned value from osGetRegionStats(), 19th of 21 items
STATS_ACTIVE_SCRIPTS returned value from osGetRegionStats(), 20th of 21 items in returned list. STATS_ACTIVE_SCRIPTS returned value from osGetRegionStats(), 20th of 21 items in returned list.
STATS_SCRIPT_LPS returned value from osGetRegionStats(), 21st of 21 items in returned list. STATS_SCRIPT_LPS returned value from osGetRegionStats(), 21st of 21 items in returned list.
# OpenSim NPC # OpenSim NPC
OS_NPC_FLY used by osNPC. OS_NPC used by osNPC. Value 0x01000000
OS_NPC_NO_FLY used by osNPC. OS_NPC_FLY used by osNPC. Value 0
OS_NPC_LAND_AT_TARGET used by osNPC. OS_NPC_NO_FLY used by osNPC. Value 1
OS_NPC_SIT_NOW used by osNPC. OS_NPC_LAND_AT_TARGET used by osNPC. Value 2
OS_NPC_CREATOR_OWNED used by osNPC. OS_NPC_SIT_NOW used by osNPC. Value 0
OS_NPC_NOT_OWNED used by osNPC. OS_NPC_CREATOR_OWNED used by osNPC. Value 0x1
OS_NPC_SENSE_AS_AGENT used by osNPC. OS_NPC_NOT_OWNED used by osNPC. Value 0x2
OS_NPC_RUNNING used by osNPC. OS_NPC_SENSE_AS_AGENT used by osNPC. Value 0x4
OS_NPC_RUNNING used by osNPC. Value 4
# Windlight/Lightshare # Windlight/Lightshare
WL_WATER_COLOR Windlight Water Colour WL_WATER_COLOR Windlight Water Colour
WL_WATER_FOG_DENSITY_EXPONENT Windlight Water Fog Density Exponent WL_WATER_FOG_DENSITY_EXPONENT Windlight Water Fog Density Exponent
@@ -771,7 +788,15 @@ WL_CLOUD_SCROLL_Y Windlight Cloud Scroll Y
WL_CLOUD_SCROLL_Y_LOCK Windlight Cloud Scroll Y Lock WL_CLOUD_SCROLL_Y_LOCK Windlight Cloud Scroll Y Lock
WL_CLOUD_SCROLL_X_LOCK Windlight Cloud Scroll X Lock WL_CLOUD_SCROLL_X_LOCK Windlight Cloud Scroll X Lock
WL_DRAW_CLASSIC_CLOUDS Windlight Draw Classic Clouds WL_DRAW_CLASSIC_CLOUDS Windlight Draw Classic Clouds
# Aurora-Sim Constants (\Aurora\AuroraDotNetEngine\APIs\AA_Constants.cs) --> # WL Constants added unique to Aurora-Sim
WL_OK Value -1
WL_ERROR Value -2
WL_ERROR_NO_SCENE_SET Value -3
WL_ERROR_SCENE_MUST_BE_STATIC Value -4
WL_ERROR_SCENE_MUST_NOT_BE_STATIC Value -5
WL_ERROR_BAD_SETTING Value -6
WL_ERROR_NO_PRESET_FOUND Value -7
# Aurora-Sim Constants (\Aurora\AuroraDotNetEngine\APIs\AA_Constants.cs)
ENABLE_GRAVITY enable_gravity. ENABLE_GRAVITY enable_gravity.
GRAVITY_FORCE_X gravity_force_x. GRAVITY_FORCE_X gravity_force_x.
GRAVITY_FORCE_Y gravity_force_y. GRAVITY_FORCE_Y gravity_force_y.

View File

@@ -247,6 +247,46 @@
<map/> <map/>
<key>osNpcWhisper</key> <key>osNpcWhisper</key>
<map/> <map/>
<key>osForceAttachToAvatar</key>
<map/>
<key>osForceAttachToAvatarFromInventory</key>
<map/>
<key>osForceAttachToOtherAvatarFromInventory</key>
<map/>
<key>osNpcTouch</key>
<map/>
<key>osNpcTouch</key>
<map/>
<key>osIsUUID</key>
<map/>
<key>osMin</key>
<map/>
<key>osMax</key>
<map/>
<key>osMax</key>
<map/>
<key>osGetRezzingObject</key>
<map/>
<key>osGetHealth</key>
<map/>
<key>osSetContentType</key>
<map/>
<key>osGetNumberOfAttachments</key>
<map/>
<key>osMessageAttachments</key>
<map/>
<key>osDropAttachment</key>
<map/>
<key>osDropAttachmentAt</key>
<map/>
<key>osForceDropAttachment</key>
<map/>
<key>osForceDropAttachmentAt</key>
<map/>
<key>osListenRegex</key>
<map/>
<key>osRegexIsMatch</key>
<map/>
<!-- OSSL Functions Aurora-Sim Unique --> <!-- OSSL Functions Aurora-Sim Unique -->
<key>osReturnObject</key> <key>osReturnObject</key>
@@ -334,6 +374,24 @@
<map/> <map/>
<key>aaGetIsInfiniteRegion</key> <key>aaGetIsInfiniteRegion</key>
<map/> <map/>
<key>aaSetCharacterStat</key>
<map/>
<key>aaAllRegionInstanceSay</key>
<map/>
<key>aaWindlightGetDayCycle</key>
<map/>
<key>aaWindlightAddDayCycleFrame</key>
<map/>
<key>aaWindlightRemoveDayCycleFrame</key>
<map/>
<key>aaWindlightSetScene</key>
<map/>
<key>aaWindlightGetScene</key>
<map/>
<key>aaWindlightGetSceneIsStatic</key>
<map/>
<key>aaWindlightGetSceneDayCycleKeyFrameCount</key>
<map/>
<!-- botFunctions Aurora-Sim ONLY --> <!-- botFunctions Aurora-Sim ONLY -->
<key>botGetWaitingTime</key> <key>botGetWaitingTime</key>
<map/> <map/>
@@ -370,4 +428,4 @@
<key>botRemoveBotsWithTag</key> <key>botRemoveBotsWithTag</key>
<map/> <map/>
</map> </map>
</llsd> </llsd>

View File

@@ -9,6 +9,17 @@
<string>settings_rlv.xml</string> <string>settings_rlv.xml</string>
</array> </array>
<key>UseNewTargetOmegaCode</key>
<map>
<key>Comment</key>
<string>Enable target omega code from Viewer 3.4</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>SGIgnoreSimulatorCameraConstraints</key> <key>SGIgnoreSimulatorCameraConstraints</key>
<map> <map>
<key>Comment</key> <key>Comment</key>
@@ -692,22 +703,55 @@
<string>Boolean</string> <string>Boolean</string>
<key>Value</key> <key>Value</key>
<integer>0</integer> <integer>0</integer>
</map> </map>
<key>LiruNoTransactionClutter</key> <key>LiruAddNotReplace</key>
<map> <map>
<key>Comment</key> <key>Comment</key>
<string>Use notifytips for transactions instead of notifys, this way they do not collect in the top right of the screen.</string> <string>Add clothing and attachments instead of having them replace the currently worn or attached item at their destination.</string>
<key>Persist</key> <key>Persist</key>
<integer>1</integer> <integer>1</integer>
<key>Type</key> <key>Type</key>
<string>Boolean</string> <string>Boolean</string>
<key>Value</key> <key>Value</key>
<integer>0</integer> <integer>0</integer>
</map> </map>
<key>LiruContinueFlyingOnUnsit</key>
<map>
<key>Comment</key>
<string>Fly after standing up, if you were flying when you sat down</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>LiruFlyAfterTeleport</key>
<map>
<key>Comment</key>
<string>Fly after teleports</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>LiruNoTransactionClutter</key>
<map>
<key>Comment</key>
<string>Use notifytips for transactions instead of notifys, this way they do not collect in the top right of the screen.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>LiruSensibleARC</key> <key>LiruSensibleARC</key>
<map> <map>
<key>Comment</key> <key>Comment</key>
<string>Use the old-style way to calculate Avatar Render Cost. <string>Use the old-style way to calculate Avatar Render Cost.
Found in Advanced->Rendering->Info Displays</string> Found in Advanced->Rendering->Info Displays</string>
<key>Persist</key> <key>Persist</key>
<integer>1</integer> <integer>1</integer>
@@ -715,7 +759,29 @@ Found in Advanced->Rendering->Info Displays</string>
<string>Boolean</string> <string>Boolean</string>
<key>Value</key> <key>Value</key>
<integer>1</integer> <integer>1</integer>
</map> </map>
<key>OtherChatsTornOff</key>
<map>
<key>Comment</key>
<string>When true, chats other than local chat open torn off of the Communicate window.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>OtherChatsTornOffAndMinimized</key>
<map>
<key>Comment</key>
<string>When this and OtherChatsTornOff are true, new chats open torn off and minimized.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>MarketImporterUpdateFreq</key> <key>MarketImporterUpdateFreq</key>
<map> <map>
<key>Comment</key> <key>Comment</key>
@@ -810,6 +876,28 @@ This should be as low as possible, but too low may break functionality</string>
<key>Value</key> <key>Value</key>
<integer>1</integer> <integer>1</integer>
</map> </map>
<key>AnnounceSnapshots</key>
<map>
<key>Comment</key>
<string>Announce if someone nearby has taken a snapshot in chat (Won't work on people who hide/quiet snapshots)</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>AnnounceStreamMetadata</key>
<map>
<key>Comment</key>
<string>Announce the metadata of the track playing, in chat, during streams.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>InventorySortOrder</key> <key>InventorySortOrder</key>
<map> <map>
<key>Comment</key> <key>Comment</key>
@@ -876,6 +964,17 @@ This should be as low as possible, but too low may break functionality</string>
<key>Value</key> <key>Value</key>
<integer>0</integer> <integer>0</integer>
</map> </map>
<key>TurnAroundWhenWalkingBackwards</key>
<map>
<key>Comment</key>
<string>Turn your avatar around to face the camera while walking backwards.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>1</integer>
</map>
<key>EmeraldBoobMass</key> <key>EmeraldBoobMass</key>
<map> <map>
<key>Comment</key> <key>Comment</key>
@@ -5769,6 +5868,17 @@ This should be as low as possible, but too low may break functionality</string>
<key>Value</key> <key>Value</key>
<integer>0</integer> <integer>0</integer>
</map> </map>
<key>SecondsInLog</key>
<map>
<key>Comment</key>
<string>TRUE to add seconds to timestamps for Log</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>FloaterAboutRect</key> <key>FloaterAboutRect</key>
<map> <map>
<key>Comment</key> <key>Comment</key>
@@ -6285,6 +6395,149 @@ This should be as low as possible, but too low may break functionality</string>
<integer>0</integer> <integer>0</integer>
</array> </array>
</map> </map>
<key>RadarColumnMarkWidth</key>
<map>
<key>Comment</key>
<string>Width for radar's mark column</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>S32</string>
<key>Value</key>
<integer>12</integer>
</map>
<key>RadarColumnPositionWidth</key>
<map>
<key>Comment</key>
<string>Width for radar's position column</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>S32</string>
<key>Value</key>
<integer>60</integer>
</map>
<key>RadarColumnAltitudeWidth</key>
<map>
<key>Comment</key>
<string>Width for radar's altitude column</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>S32</string>
<key>Value</key>
<integer>48</integer>
</map>
<key>RadarColumnActivityWidth</key>
<map>
<key>Comment</key>
<string>Width for radar's activity column</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>S32</string>
<key>Value</key>
<integer>24</integer>
</map>
<key>RadarColumnAgeWidth</key>
<map>
<key>Comment</key>
<string>Width for radar's age column</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>S32</string>
<key>Value</key>
<integer>45</integer>
</map>
<key>RadarColumnTimeWidth</key>
<map>
<key>Comment</key>
<string>Width for radar's time column</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>S32</string>
<key>Value</key>
<integer>52</integer>
</map>
<key>RadarColumnMarkHidden</key>
<map>
<key>Comment</key>
<string>Hide radar's mark column</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>RadarColumnPositionHidden</key>
<map>
<key>Comment</key>
<string>Hide radar's position column</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>RadarColumnAltitudeHidden</key>
<map>
<key>Comment</key>
<string>Hide radar's altitude column</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>RadarColumnActivityHidden</key>
<map>
<key>Comment</key>
<string>Hide radar's activity column</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>RadarColumnAgeHidden</key>
<map>
<key>Comment</key>
<string>Hide radar's age column</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>RadarColumnTimeHidden</key>
<map>
<key>Comment</key>
<string>Hide radar's time column</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>1</integer>
</map>
<key>RadarColumnClientHidden</key>
<map>
<key>Comment</key>
<string>Hide radar's client column</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>RadarKeepOpen</key> <key>RadarKeepOpen</key>
<map> <map>
<key>Comment</key> <key>Comment</key>
@@ -6351,6 +6604,28 @@ This should be as low as possible, but too low may break functionality</string>
<key>Value</key> <key>Value</key>
<integer>1</integer> <integer>1</integer>
</map> </map>
<key>RadarAlertAge</key>
<map>
<key>Comment</key>
<string>Whether the radar emits chat alerts for avatars younger than AvatarAgeAlertDays appearing.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>AvatarAgeAlertDays</key>
<map>
<key>Comment</key>
<string>Age below which avatars will be made known to you</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>U32</string>
<key>Value</key>
<integer>3</integer>
</map>
<key>RadarChatAlerts</key> <key>RadarChatAlerts</key>
<map> <map>
<key>Comment</key> <key>Comment</key>
@@ -6501,6 +6776,22 @@ This should be as low as possible, but too low may break functionality</string>
<integer>0</integer> <integer>0</integer>
</array> </array>
</map> </map>
<key>FloaterOutboxRect</key>
<map>
<key>Comment</key>
<string>Rectangle for merchant outbox window</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Rect</string>
<key>Value</key>
<array>
<integer>0</integer>
<integer>342</integer>
<integer>310</integer>
<integer>52</integer>
</array>
</map>
<key>FloaterPayRectB</key> <key>FloaterPayRectB</key>
<map> <map>
<key>Comment</key> <key>Comment</key>
@@ -6581,6 +6872,38 @@ This should be as low as possible, but too low may break functionality</string>
<integer>400</integer> <integer>400</integer>
</array> </array>
</map> </map>
<key>FloaterSnapshotFeedRect</key>
<map>
<key>Comment</key>
<string>Rectangle for snapshot feed window</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Rect</string>
<key>Value</key>
<array>
<integer>0</integer>
<integer>200</integer>
<integer>200</integer>
<integer>400</integer>
</array>
</map>
<key>FloaterSnapshotPostcardRect</key>
<map>
<key>Comment</key>
<string>Rectangle for snapshot postcard window</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Rect</string>
<key>Value</key>
<array>
<integer>0</integer>
<integer>346</integer>
<integer>450</integer>
<integer>400</integer>
</array>
</map>
<key>FloaterSoundsRect</key> <key>FloaterSoundsRect</key>
<map> <map>
<key>Comment</key> <key>Comment</key>
@@ -7888,17 +8211,6 @@ This should be as low as possible, but too low may break functionality</string>
<key>Value</key> <key>Value</key>
<integer>64</integer> <integer>64</integer>
</map> </map>
<key>KeepAspectForSnapshot</key>
<map>
<key>Comment</key>
<string>Use full window when taking snapshot, regardless of requested image size</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>1</integer>
</map>
<key>LandBrushSize</key> <key>LandBrushSize</key>
<map> <map>
<key>Comment</key> <key>Comment</key>
@@ -8069,6 +8381,50 @@ This should be as low as possible, but too low may break functionality</string>
<key>Value</key> <key>Value</key>
<string>0.0.0</string> <string>0.0.0</string>
</map> </map>
<key>LastSnapshotToFeedAspect</key>
<map>
<key>Comment</key>
<string>The aspect ratio spinner value for snapshots uploaded to my.secondlife.com</string>
<key>Persist</key>
<integer>0</integer>
<key>Type</key>
<string>F32</string>
<key>Value</key>
<integer>1.33333</integer>
</map>
<key>LastSnapshotToFeedHeight</key>
<map>
<key>Comment</key>
<string>The height of the last my.secondlife.com feed snapshot, in px</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>S32</string>
<key>Value</key>
<integer>525</integer>
</map>
<key>LastSnapshotToFeedWidth</key>
<map>
<key>Comment</key>
<string>The width of the last my.secondlife.com feed snapshot, in px</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>S32</string>
<key>Value</key>
<integer>700</integer>
</map>
<key>LastSnapshotToEmailAspect</key>
<map>
<key>Comment</key>
<string>The aspect ratio spinner value for snapshots sent by email</string>
<key>Persist</key>
<integer>0</integer>
<key>Type</key>
<string>F32</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>LastSnapshotToEmailHeight</key> <key>LastSnapshotToEmailHeight</key>
<map> <map>
<key>Comment</key> <key>Comment</key>
@@ -8091,6 +8447,17 @@ This should be as low as possible, but too low may break functionality</string>
<key>Value</key> <key>Value</key>
<integer>1024</integer> <integer>1024</integer>
</map> </map>
<key>LastSnapshotToDiskAspect</key>
<map>
<key>Comment</key>
<string>The aspect ratio spinner value for snapshots written to disk</string>
<key>Persist</key>
<integer>0</integer>
<key>Type</key>
<string>F32</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>LastSnapshotToDiskHeight</key> <key>LastSnapshotToDiskHeight</key>
<map> <map>
<key>Comment</key> <key>Comment</key>
@@ -8113,6 +8480,17 @@ This should be as low as possible, but too low may break functionality</string>
<key>Value</key> <key>Value</key>
<integer>1024</integer> <integer>1024</integer>
</map> </map>
<key>LastSnapshotToInventoryAspect</key>
<map>
<key>Comment</key>
<string>The aspect ratio spinner value for snapshots uploaded to inventory</string>
<key>Persist</key>
<integer>0</integer>
<key>Type</key>
<string>F32</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>LastSnapshotToInventoryHeight</key> <key>LastSnapshotToInventoryHeight</key>
<map> <map>
<key>Comment</key> <key>Comment</key>
@@ -8146,6 +8524,17 @@ This should be as low as possible, but too low may break functionality</string>
<key>Value</key> <key>Value</key>
<integer>0</integer> <integer>0</integer>
</map> </map>
<key>SnapshotFeedAddLocation</key>
<map>
<key>Comment</key>
<string>Include your location in your uploads to profile feed.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>LeftClickShowMenu</key> <key>LeftClickShowMenu</key>
<map> <map>
<key>Comment</key> <key>Comment</key>
@@ -13411,6 +13800,28 @@ This should be as low as possible, but too low may break functionality</string>
<key>Value</key> <key>Value</key>
<integer>0</integer> <integer>0</integer>
</map> </map>
<key>SnapshotFeedLastAspect</key>
<map>
<key>Comment</key>
<string>Take next feed snapshot at this aspect</string>
<key>Persist</key>
<integer>0</integer>
<key>Type</key>
<string>S32</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>SnapshotFeedLastResolution</key>
<map>
<key>Comment</key>
<string>Take next feed snapshot at this resolution</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>S32</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>SnapshotFormat</key> <key>SnapshotFormat</key>
<map> <map>
<key>Comment</key> <key>Comment</key>
@@ -13422,6 +13833,28 @@ This should be as low as possible, but too low may break functionality</string>
<key>Value</key> <key>Value</key>
<integer>0</integer> <integer>0</integer>
</map> </map>
<key>SnapshotLayerType</key>
<map>
<key>Comment</key>
<string>Save snapshots in this format (0 = Colors, 1 = Depth)</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>S32</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>SnapshotLocalLastAspect</key>
<map>
<key>Comment</key>
<string>Take next local snapshot at this aspect</string>
<key>Persist</key>
<integer>0</integer>
<key>Type</key>
<string>S32</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>SnapshotLocalLastResolution</key> <key>SnapshotLocalLastResolution</key>
<map> <map>
<key>Comment</key> <key>Comment</key>
@@ -13433,6 +13866,17 @@ This should be as low as possible, but too low may break functionality</string>
<key>Value</key> <key>Value</key>
<integer>0</integer> <integer>0</integer>
</map> </map>
<key>SnapshotPostcardLastAspect</key>
<map>
<key>Comment</key>
<string>Take next postcard snapshot at this aspect</string>
<key>Persist</key>
<integer>0</integer>
<key>Type</key>
<string>S32</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>SnapshotPostcardLastResolution</key> <key>SnapshotPostcardLastResolution</key>
<map> <map>
<key>Comment</key> <key>Comment</key>
@@ -13455,6 +13899,17 @@ This should be as low as possible, but too low may break functionality</string>
<key>Value</key> <key>Value</key>
<integer>75</integer> <integer>75</integer>
</map> </map>
<key>SnapshotTextureLastAspect</key>
<map>
<key>Comment</key>
<string>Take next texture snapshot at this aspect</string>
<key>Persist</key>
<integer>0</integer>
<key>Type</key>
<string>S32</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>SnapshotTextureLastResolution</key> <key>SnapshotTextureLastResolution</key>
<map> <map>
<key>Comment</key> <key>Comment</key>
@@ -13466,6 +13921,17 @@ This should be as low as possible, but too low may break functionality</string>
<key>Value</key> <key>Value</key>
<integer>0</integer> <integer>0</integer>
</map> </map>
<key>SnapshotOpenFreezeTime</key>
<map>
<key>Comment</key>
<string>When opening the snapshot floater, immediately freeze time.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>SpeakingColor</key> <key>SpeakingColor</key>
<map> <map>
<key>Comment</key> <key>Comment</key>
@@ -14178,12 +14644,12 @@ This should be as low as possible, but too low may break functionality</string>
<key>Value</key> <key>Value</key>
<integer>0</integer> <integer>0</integer>
</map> </map>
<key>UseFreezeFrame</key> <key>UseFreezeTime</key>
<map> <map>
<key>Comment</key> <key>Comment</key>
<string>Freeze time when taking snapshots.</string> <string>Freeze time when taking snapshots.</string>
<key>Persist</key> <key>Persist</key>
<integer>1</integer> <integer>0</integer>
<key>Type</key> <key>Type</key>
<string>Boolean</string> <string>Boolean</string>
<key>Value</key> <key>Value</key>

View File

@@ -135,7 +135,7 @@
<key>AscentFriendColor</key> <key>AscentFriendColor</key>
<map> <map>
<key>Comment</key> <key>Comment</key>
<string>Color of chat messages from other residents</string> <string>Special color to distinguish friends from other residents</string>
<key>Persist</key> <key>Persist</key>
<integer>1</integer> <integer>1</integer>
<key>Type</key> <key>Type</key>
@@ -153,7 +153,7 @@
<key>AscentLindenColor</key> <key>AscentLindenColor</key>
<map> <map>
<key>Comment</key> <key>Comment</key>
<string>Color of chat messages from other residents</string> <string>Special color to distinguish Lindens(/grid operators) from other residents</string>
<key>Persist</key> <key>Persist</key>
<integer>1</integer> <integer>1</integer>
<key>Type</key> <key>Type</key>
@@ -171,7 +171,7 @@
<key>AscentMutedColor</key> <key>AscentMutedColor</key>
<map> <map>
<key>Comment</key> <key>Comment</key>
<string>Color of chat messages from other residents</string> <string>Special color to distinguish those who have been muted from other residents</string>
<key>Persist</key> <key>Persist</key>
<integer>1</integer> <integer>1</integer>
<key>Type</key> <key>Type</key>
@@ -189,7 +189,7 @@
<key>AscentEstateOwnerColor</key> <key>AscentEstateOwnerColor</key>
<map> <map>
<key>Comment</key> <key>Comment</key>
<string>Color of chat messages from other residents</string> <string>Special color to distinguish estate owners from other residents</string>
<key>Persist</key> <key>Persist</key>
<integer>1</integer> <integer>1</integer>
<key>Type</key> <key>Type</key>
@@ -204,7 +204,59 @@
<key>IsCOA</key> <key>IsCOA</key>
<integer>1</integer> <integer>1</integer>
</map> </map>
<key>AscentReportClientUUID</key> <key>ColorFriendChat</key>
<map>
<key>Comment</key>
<string>Color chat from friends using AscentFriendColor</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
<key>IsCOA</key>
<integer>1</integer>
</map>
<key>ColorLindenChat</key>
<map>
<key>Comment</key>
<string>Color chat from Lindens(/grid operators) using AscentLindenColor</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
<key>IsCOA</key>
<integer>1</integer>
</map>
<key>ColorMutedChat</key>
<map>
<key>Comment</key>
<string>Color chat from muted residents using AscentMutedColor</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
<key>IsCOA</key>
<integer>1</integer>
</map>
<key>ColorEstateOwnerChat</key>
<map>
<key>Comment</key>
<string>Color chat from estate owners using AscentEstateOwnerColor</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
<key>IsCOA</key>
<integer>1</integer>
</map>
<key>AscentReportClientUUID</key>
<map> <map>
<key>Comment</key> <key>Comment</key>
<string>Broadcasted Client Key</string> <string>Broadcasted Client Key</string>

View File

@@ -335,6 +335,8 @@ void LLPrefsAscentChat::refreshValues()
mEnableOOCAutoClose = gSavedSettings.getBOOL("AscentAutoCloseOOC"); mEnableOOCAutoClose = gSavedSettings.getBOOL("AscentAutoCloseOOC");
mLinksForChattingObjects = gSavedSettings.getU32("LinksForChattingObjects"); mLinksForChattingObjects = gSavedSettings.getU32("LinksForChattingObjects");
mSecondsInChatAndIMs = gSavedSettings.getBOOL("SecondsInChatAndIMs"); mSecondsInChatAndIMs = gSavedSettings.getBOOL("SecondsInChatAndIMs");
mSecondsInLog = gSavedSettings.getBOOL("SecondsInLog");
mOtherChatsTornOff = gSavedSettings.getBOOL("OtherChatsTornOff");
std::string format = gSavedSettings.getString("ShortTimeFormat"); std::string format = gSavedSettings.getString("ShortTimeFormat");
if (format.find("%p") == -1) if (format.find("%p") == -1)
@@ -390,6 +392,7 @@ void LLPrefsAscentChat::refreshValues()
mSoundMulti = gSavedSettings.getU32("_NACL_AntiSpamSoundMulti"); mSoundMulti = gSavedSettings.getU32("_NACL_AntiSpamSoundMulti");
mNewLines = gSavedSettings.getU32("_NACL_AntiSpamNewlines"); mNewLines = gSavedSettings.getU32("_NACL_AntiSpamNewlines");
mPreloadMulti = gSavedSettings.getU32("_NACL_AntiSpamSoundPreloadMulti"); mPreloadMulti = gSavedSettings.getU32("_NACL_AntiSpamSoundPreloadMulti");
mEnableGestureSounds = gSavedSettings.getBOOL("EnableGestureSounds");
//Text Options ------------------------------------------------------------------------ //Text Options ------------------------------------------------------------------------
mSpellDisplay = gSavedSettings.getBOOL("SpellDisplay"); mSpellDisplay = gSavedSettings.getBOOL("SpellDisplay");
@@ -539,6 +542,8 @@ void LLPrefsAscentChat::cancel()
gSavedSettings.setBOOL("AscentAutoCloseOOC", mEnableOOCAutoClose); gSavedSettings.setBOOL("AscentAutoCloseOOC", mEnableOOCAutoClose);
gSavedSettings.setU32("LinksForChattingObjects", mLinksForChattingObjects); gSavedSettings.setU32("LinksForChattingObjects", mLinksForChattingObjects);
gSavedSettings.setBOOL("SecondsInChatAndIMs", mSecondsInChatAndIMs); gSavedSettings.setBOOL("SecondsInChatAndIMs", mSecondsInChatAndIMs);
gSavedSettings.setBOOL("SecondsInLog", mSecondsInLog);
gSavedSettings.setBOOL("OtherChatsTornOff", mOtherChatsTornOff);
std::string short_date, long_date, short_time, long_time, timestamp; std::string short_date, long_date, short_time, long_time, timestamp;
@@ -607,6 +612,7 @@ void LLPrefsAscentChat::cancel()
gSavedSettings.setU32("_NACL_AntiSpamSoundMulti", mSoundMulti); gSavedSettings.setU32("_NACL_AntiSpamSoundMulti", mSoundMulti);
gSavedSettings.setU32("_NACL_AntiSpamNewlines", mNewLines); gSavedSettings.setU32("_NACL_AntiSpamNewlines", mNewLines);
gSavedSettings.setU32("_NACL_AntiSpamSoundPreloadMulti", mPreloadMulti); gSavedSettings.setU32("_NACL_AntiSpamSoundPreloadMulti", mPreloadMulti);
gSavedSettings.setBOOL("EnableGestureSounds", mEnableGestureSounds);
//Text Options ------------------------------------------------------------------------ //Text Options ------------------------------------------------------------------------
gSavedSettings.setBOOL("SpellDisplay", mSpellDisplay); gSavedSettings.setBOOL("SpellDisplay", mSpellDisplay);

View File

@@ -76,6 +76,8 @@ protected:
U32 tempTimeFormat; U32 tempTimeFormat;
U32 tempDateFormat; U32 tempDateFormat;
BOOL mSecondsInChatAndIMs; BOOL mSecondsInChatAndIMs;
BOOL mSecondsInLog;
BOOL mOtherChatsTornOff;
BOOL mIMResponseAnyone; BOOL mIMResponseAnyone;
BOOL mIMResponseFriends; BOOL mIMResponseFriends;
@@ -104,6 +106,7 @@ protected:
BOOL mSoundMulti; BOOL mSoundMulti;
U32 mNewLines; U32 mNewLines;
U32 mPreloadMulti; U32 mPreloadMulti;
bool mEnableGestureSounds;
//Text Options ------------------------------------------------------------------------ //Text Options ------------------------------------------------------------------------
BOOL mSpellDisplay; BOOL mSpellDisplay;

View File

@@ -267,6 +267,8 @@ void LLPrefsAscentSys::refreshValues()
mDoubleClickTeleport = gSavedSettings.getBOOL("DoubleClickTeleport"); mDoubleClickTeleport = gSavedSettings.getBOOL("DoubleClickTeleport");
mResetCameraAfterTP = gSavedSettings.getBOOL("OptionRotateCamAfterLocalTP"); mResetCameraAfterTP = gSavedSettings.getBOOL("OptionRotateCamAfterLocalTP");
mOffsetTPByUserHeight = gSavedSettings.getBOOL("OptionOffsetTPByAgentHeight"); mOffsetTPByUserHeight = gSavedSettings.getBOOL("OptionOffsetTPByAgentHeight");
mLiruFlyAfterTeleport = gSavedSettings.getBOOL("LiruFlyAfterTeleport");
mLiruContinueFlying = gSavedSettings.getBOOL("LiruContinueFlyingOnUnsit");
mPreviewAnimInWorld = gSavedSettings.getBOOL("PreviewAnimInWorld"); mPreviewAnimInWorld = gSavedSettings.getBOOL("PreviewAnimInWorld");
mSaveScriptsAsMono = gSavedSettings.getBOOL("SaveInventoryScriptsAsMono"); mSaveScriptsAsMono = gSavedSettings.getBOOL("SaveInventoryScriptsAsMono");
mAlwaysRezInGroup = gSavedSettings.getBOOL("AscentAlwaysRezInGroup"); mAlwaysRezInGroup = gSavedSettings.getBOOL("AscentAlwaysRezInGroup");
@@ -416,6 +418,8 @@ void LLPrefsAscentSys::cancel()
gSavedSettings.setBOOL("DoubleClickTeleport", mDoubleClickTeleport); gSavedSettings.setBOOL("DoubleClickTeleport", mDoubleClickTeleport);
gSavedSettings.setBOOL("OptionRotateCamAfterLocalTP", mResetCameraAfterTP); gSavedSettings.setBOOL("OptionRotateCamAfterLocalTP", mResetCameraAfterTP);
gSavedSettings.setBOOL("OptionOffsetTPByAgentHeight", mOffsetTPByUserHeight); gSavedSettings.setBOOL("OptionOffsetTPByAgentHeight", mOffsetTPByUserHeight);
gSavedSettings.setBOOL("LiruFlyAfterTeleport", mLiruFlyAfterTeleport);
gSavedSettings.setBOOL("LiruContinueFlyingOnUnsit", mLiruContinueFlying);
gSavedSettings.setBOOL("PreviewAnimInWorld", mPreviewAnimInWorld); gSavedSettings.setBOOL("PreviewAnimInWorld", mPreviewAnimInWorld);
gSavedSettings.setBOOL("SaveInventoryScriptsAsMono", mSaveScriptsAsMono); gSavedSettings.setBOOL("SaveInventoryScriptsAsMono", mSaveScriptsAsMono);
gSavedSettings.setBOOL("AscentAlwaysRezInGroup", mAlwaysRezInGroup); gSavedSettings.setBOOL("AscentAlwaysRezInGroup", mAlwaysRezInGroup);

View File

@@ -58,6 +58,8 @@ protected:
BOOL mDoubleClickTeleport; BOOL mDoubleClickTeleport;
BOOL mResetCameraAfterTP; BOOL mResetCameraAfterTP;
BOOL mOffsetTPByUserHeight; BOOL mOffsetTPByUserHeight;
bool mLiruFlyAfterTeleport;
bool mLiruContinueFlying;
BOOL mPreviewAnimInWorld; BOOL mPreviewAnimInWorld;
BOOL mSaveScriptsAsMono; BOOL mSaveScriptsAsMono;
BOOL mAlwaysRezInGroup; BOOL mAlwaysRezInGroup;

View File

@@ -36,6 +36,8 @@
#include "ascentprefsvan.h" #include "ascentprefsvan.h"
//project includes //project includes
#include "llaudioengine.h" //For gAudiop
#include "llstreamingaudio.h" //For LLStreamingAudioInterface
#include "llcolorswatch.h" #include "llcolorswatch.h"
#include "llvoavatar.h" #include "llvoavatar.h"
#include "llvoavatarself.h" #include "llvoavatarself.h"
@@ -55,6 +57,8 @@ LLPrefsAscentVan::LLPrefsAscentVan()
{ {
LLUICtrlFactory::getInstance()->buildPanel(this, "panel_preferences_ascent_vanity.xml"); LLUICtrlFactory::getInstance()->buildPanel(this, "panel_preferences_ascent_vanity.xml");
childSetVisible("announce_streaming_metadata", gAudiop && gAudiop->getStreamingAudioImpl() && gAudiop->getStreamingAudioImpl()->supportsMetaData());
childSetCommitCallback("tag_spoofing_combobox", onCommitClientTag, this); childSetCommitCallback("tag_spoofing_combobox", onCommitClientTag, this);
childSetCommitCallback("show_my_tag_check", onCommitCheckBox, this); childSetCommitCallback("show_my_tag_check", onCommitCheckBox, this);
@@ -153,12 +157,16 @@ void LLPrefsAscentVan::onCommitCheckBox(LLUICtrl* ctrl, void* user_data)
if (ctrl->getName() == "use_status_check") if (ctrl->getName() == "use_status_check")
{ {
BOOL showCustomColors = gSavedSettings.getBOOL("AscentUseStatusColors"); bool showCustomColors = gSavedSettings.getBOOL("AscentUseStatusColors");
self->childSetEnabled("friends_color_textbox", showCustomColors); self->childSetEnabled("friends_color_textbox", showCustomColors);
self->childSetEnabled("friend_color_swatch", showCustomColors); bool frColors = gSavedSettings.getBOOL("ColorFriendChat");
self->childSetEnabled("estate_owner_color_swatch", showCustomColors); self->childSetEnabled("friend_color_swatch", showCustomColors || frColors);
self->childSetEnabled("linden_color_swatch", showCustomColors); bool eoColors = gSavedSettings.getBOOL("ColorEstateOwnerChat");
self->childSetEnabled("muted_color_swatch", showCustomColors); self->childSetEnabled("estate_owner_color_swatch", showCustomColors || eoColors);
bool lindColors = gSavedSettings.getBOOL("ColorLindenChat");
self->childSetEnabled("linden_color_swatch", showCustomColors || lindColors);
bool muteColors = gSavedSettings.getBOOL("ColorMutedChat");
self->childSetEnabled("muted_color_swatch", showCustomColors || muteColors);
} }
else if (ctrl->getName() == "customize_own_tag_check") else if (ctrl->getName() == "customize_own_tag_check")
{ {
@@ -173,12 +181,16 @@ void LLPrefsAscentVan::onCommitCheckBox(LLUICtrl* ctrl, void* user_data)
// Store current settings for cancel // Store current settings for cancel
void LLPrefsAscentVan::refreshValues() void LLPrefsAscentVan::refreshValues()
{ {
//General -------------------------------------------------------------------------------- //Main -----------------------------------------------------------------------------------
mUseAccountSettings = gSavedSettings.getBOOL("AscentStoreSettingsPerAccount"); mUseAccountSettings = gSavedSettings.getBOOL("AscentStoreSettingsPerAccount");
mShowTPScreen = !gSavedSettings.getBOOL("AscentDisableTeleportScreens"); mShowTPScreen = !gSavedSettings.getBOOL("AscentDisableTeleportScreens");
mPlayTPSound = gSavedSettings.getBOOL("OptionPlayTpSound"); mPlayTPSound = gSavedSettings.getBOOL("OptionPlayTpSound");
mShowLogScreens = !gSavedSettings.getBOOL("AscentDisableLogoutScreens"); mShowLogScreens = !gSavedSettings.getBOOL("AscentDisableLogoutScreens");
mDisableChatAnimation = gSavedSettings.getBOOL("SGDisableChatAnimation"); mDisableChatAnimation = gSavedSettings.getBOOL("SGDisableChatAnimation");
mAddNotReplace = gSavedSettings.getBOOL("LiruAddNotReplace");
mTurnAround = gSavedSettings.getBOOL("TurnAroundWhenWalkingBackwards");
mAnnounceSnapshots = gSavedSettings.getBOOL("AnnounceSnapshots");
mAnnounceStreamMetadata = gSavedSettings.getBOOL("AnnounceStreamMetadata");
//Tags\Colors ---------------------------------------------------------------------------- //Tags\Colors ----------------------------------------------------------------------------
mAscentUseTag = gSavedSettings.getBOOL("AscentUseTag"); mAscentUseTag = gSavedSettings.getBOOL("AscentUseTag");
@@ -201,6 +213,10 @@ void LLPrefsAscentVan::refreshValues()
mLindenColor = gSavedSettings.getColor4("AscentLindenColor"); mLindenColor = gSavedSettings.getColor4("AscentLindenColor");
mMutedColor = gSavedSettings.getColor4("AscentMutedColor"); mMutedColor = gSavedSettings.getColor4("AscentMutedColor");
//mCustomColor = gSavedSettings.getColor4("MoyMiniMapCustomColor"); //mCustomColor = gSavedSettings.getColor4("MoyMiniMapCustomColor");
mColorFriendChat = gSavedSettings.getBOOL("ColorFriendChat");
mColorEOChat = gSavedSettings.getBOOL("ColorEstateOwnerChat");
mColorLindenChat = gSavedSettings.getBOOL("ColorLindenChat");
mColorMutedChat = gSavedSettings.getBOOL("ColorMutedChat");
//Body Dynamics -------------------------------------------------------------------------- //Body Dynamics --------------------------------------------------------------------------
mBreastPhysicsToggle = gSavedSettings.getBOOL("EmeraldBreastPhysicsToggle"); mBreastPhysicsToggle = gSavedSettings.getBOOL("EmeraldBreastPhysicsToggle");
@@ -218,17 +234,17 @@ void LLPrefsAscentVan::refreshValues()
// Update controls based on current settings // Update controls based on current settings
void LLPrefsAscentVan::refresh() void LLPrefsAscentVan::refresh()
{ {
//General -------------------------------------------------------------------------------- //Main -----------------------------------------------------------------------------------
//Tags\Colors ---------------------------------------------------------------------------- //Tags\Colors ----------------------------------------------------------------------------
LLComboBox* combo = getChild<LLComboBox>("tag_spoofing_combobox"); LLComboBox* combo = getChild<LLComboBox>("tag_spoofing_combobox");
combo->setCurrentByIndex(mSelectedClient); combo->setCurrentByIndex(mSelectedClient);
childSetEnabled("friends_color_textbox", mUseStatusColors); childSetEnabled("friends_color_textbox", mUseStatusColors);
childSetEnabled("friend_color_swatch", mUseStatusColors); childSetEnabled("friend_color_swatch", mUseStatusColors || mColorFriendChat);
childSetEnabled("estate_owner_color_swatch", mUseStatusColors); childSetEnabled("estate_owner_color_swatch", mUseStatusColors || mColorEOChat);
childSetEnabled("linden_color_swatch", mUseStatusColors); childSetEnabled("linden_color_swatch", mUseStatusColors || mColorLindenChat);
childSetEnabled("muted_color_swatch", mUseStatusColors); childSetEnabled("muted_color_swatch", mUseStatusColors || mColorMutedChat);
childSetEnabled("custom_tag_label_text", mCustomTagOn); childSetEnabled("custom_tag_label_text", mCustomTagOn);
childSetEnabled("custom_tag_label_box", mCustomTagOn); childSetEnabled("custom_tag_label_box", mCustomTagOn);
@@ -247,12 +263,16 @@ void LLPrefsAscentVan::refresh()
// Reset settings to local copy // Reset settings to local copy
void LLPrefsAscentVan::cancel() void LLPrefsAscentVan::cancel()
{ {
//General -------------------------------------------------------------------------------- //Main -----------------------------------------------------------------------------------
gSavedSettings.setBOOL("AscentStoreSettingsPerAccount", mUseAccountSettings); gSavedSettings.setBOOL("AscentStoreSettingsPerAccount", mUseAccountSettings);
gSavedSettings.setBOOL("AscentDisableTeleportScreens", !mShowTPScreen); gSavedSettings.setBOOL("AscentDisableTeleportScreens", !mShowTPScreen);
gSavedSettings.setBOOL("OptionPlayTpSound", mPlayTPSound); gSavedSettings.setBOOL("OptionPlayTpSound", mPlayTPSound);
gSavedSettings.setBOOL("AscentDisableLogoutScreens", !mShowLogScreens); gSavedSettings.setBOOL("AscentDisableLogoutScreens", !mShowLogScreens);
gSavedSettings.setBOOL("SGDisableChatAnimation", mDisableChatAnimation); gSavedSettings.setBOOL("SGDisableChatAnimation", mDisableChatAnimation);
gSavedSettings.setBOOL("LiruAddNotReplace", mAddNotReplace);
gSavedSettings.setBOOL("TurnAroundWhenWalkingBackwards", mTurnAround);
gSavedSettings.setBOOL("AnnounceSnapshots", mAnnounceSnapshots);
gSavedSettings.setBOOL("AnnounceStreamMetadata", mAnnounceStreamMetadata);
//Tags\Colors ---------------------------------------------------------------------------- //Tags\Colors ----------------------------------------------------------------------------
gSavedSettings.setBOOL("AscentUseTag", mAscentUseTag); gSavedSettings.setBOOL("AscentUseTag", mAscentUseTag);
@@ -275,6 +295,10 @@ void LLPrefsAscentVan::cancel()
gSavedSettings.setColor4("AscentLindenColor", mLindenColor); gSavedSettings.setColor4("AscentLindenColor", mLindenColor);
gSavedSettings.setColor4("AscentMutedColor", mMutedColor); gSavedSettings.setColor4("AscentMutedColor", mMutedColor);
// gSavedSettings.setColor4("MoyMiniMapCustomColor", mCustomColor); // gSavedSettings.setColor4("MoyMiniMapCustomColor", mCustomColor);
gSavedSettings.setBOOL("ColorFriendChat", mColorFriendChat);
gSavedSettings.setBOOL("ColorEstateOwnerChat", mColorEOChat);
gSavedSettings.setBOOL("ColorLindenChat", mColorLindenChat);
gSavedSettings.setBOOL("ColorMutedChat", mColorMutedChat);
//Body Dynamics -------------------------------------------------------------------------- //Body Dynamics --------------------------------------------------------------------------
gSavedSettings.setBOOL("EmeraldBreastPhysicsToggle", mBreastPhysicsToggle); gSavedSettings.setBOOL("EmeraldBreastPhysicsToggle", mBreastPhysicsToggle);

View File

@@ -52,12 +52,16 @@ protected:
static void onCommitCheckBox(LLUICtrl* ctrl, void* user_data); static void onCommitCheckBox(LLUICtrl* ctrl, void* user_data);
static void onCommitTextModified(LLUICtrl* ctrl, void* userdata); static void onCommitTextModified(LLUICtrl* ctrl, void* userdata);
static void onManualClientUpdate(void* data); static void onManualClientUpdate(void* data);
//General //Main
BOOL mUseAccountSettings; BOOL mUseAccountSettings;
BOOL mShowTPScreen; BOOL mShowTPScreen;
BOOL mPlayTPSound; BOOL mPlayTPSound;
BOOL mShowLogScreens; BOOL mShowLogScreens;
bool mDisableChatAnimation; bool mDisableChatAnimation;
bool mAddNotReplace;
bool mTurnAround;
bool mAnnounceSnapshots;
bool mAnnounceStreamMetadata;
//Tags\Colors //Tags\Colors
BOOL mAscentUseTag; BOOL mAscentUseTag;
std::string mReportClientUUID; std::string mReportClientUUID;
@@ -78,6 +82,10 @@ protected:
LLColor4 mEstateOwnerColor; LLColor4 mEstateOwnerColor;
LLColor4 mLindenColor; LLColor4 mLindenColor;
LLColor4 mMutedColor; LLColor4 mMutedColor;
bool mColorFriendChat;
bool mColorEOChat;
bool mColorLindenChat;
bool mColorMutedChat;
//Body Dynamics //Body Dynamics
BOOL mBreastPhysicsToggle; BOOL mBreastPhysicsToggle;
F32 mBoobMass; F32 mBoobMass;

View File

@@ -76,6 +76,11 @@ bool HippoGridInfo::isOpenSimulator() const
return (mPlatform == HippoGridInfo::PLATFORM_OPENSIM); return (mPlatform == HippoGridInfo::PLATFORM_OPENSIM);
} }
bool HippoGridInfo::isAurora() const
{
return (mPlatform == HippoGridInfo::PLATFORM_AURORA);
}
bool HippoGridInfo::isSecondLife() const bool HippoGridInfo::isSecondLife() const
{ {
return (mPlatform == HippoGridInfo::PLATFORM_SECONDLIFE); return (mPlatform == HippoGridInfo::PLATFORM_SECONDLIFE);
@@ -92,11 +97,15 @@ const std::string& HippoGridInfo::getGridName() const
return mGridName; return mGridName;
} }
const std::string& HippoGridInfo::getGridOwner() const { const std::string& HippoGridInfo::getGridOwner() const
if(isSecondLife()) { {
if(isSecondLife())
{
static const std::string ll = "Linden Lab"; static const std::string ll = "Linden Lab";
return ll; return ll;
} else { }
else
{
return this->getGridName(); return this->getGridName();
} }
} }

View File

@@ -38,6 +38,7 @@ public:
Platform getPlatform(); Platform getPlatform();
bool isOpenSimulator() const; bool isOpenSimulator() const;
bool isAurora() const;
bool isSecondLife() const; bool isSecondLife() const;
bool isInProductionGrid() const; // Should only be called if isSecondLife() returns true. bool isInProductionGrid() const; // Should only be called if isSecondLife() returns true.
const std::string& getGridName() const; const std::string& getGridName() const;

View File

@@ -21,6 +21,8 @@ void HippoLimits::setLimits()
{ {
if (gHippoGridManager->getConnectedGrid()->getPlatform() == HippoGridInfo::PLATFORM_SECONDLIFE) { if (gHippoGridManager->getConnectedGrid()->getPlatform() == HippoGridInfo::PLATFORM_SECONDLIFE) {
setSecondLifeLimits(); setSecondLifeLimits();
} else if (gHippoGridManager->getConnectedGrid()->getPlatform() == HippoGridInfo::PLATFORM_AURORA) {
setAuroraLimits();
} else { } else {
setOpenSimLimits(); setOpenSimLimits();
} }
@@ -46,6 +48,17 @@ void HippoLimits::setOpenSimLimits()
} }
} }
void HippoLimits::setAuroraLimits()
{
mMaxAgentGroups = gHippoGridManager->getConnectedGrid()->getMaxAgentGroups();
if (mMaxAgentGroups < 0) mMaxAgentGroups = 50;
mMaxPrimScale = 256.0f;
mMinPrimScale = 0.001f;
mMaxHeight = 8192.0f;
mMinHoleSize = 0.001f;
mMaxHollow = 99.0f;
}
void HippoLimits::setSecondLifeLimits() void HippoLimits::setSecondLifeLimits()
{ {
llinfos << "Using Second Life limits." << llendl; llinfos << "Using Second Life limits." << llendl;

View File

@@ -26,6 +26,7 @@ private:
float mMinPrimScale; float mMinPrimScale;
void setOpenSimLimits(); void setOpenSimLimits();
void setAuroraLimits();
void setSecondLifeLimits(); void setSecondLifeLimits();
}; };

View File

@@ -50,7 +50,6 @@
#include "llmoveview.h" #include "llmoveview.h"
#include "llchatbar.h" #include "llchatbar.h"
#include "llnotificationsutil.h" #include "llnotificationsutil.h"
#include "llpanelpathfindingrebakenavmesh.h"
#include "llparcel.h" #include "llparcel.h"
#include "llrendersphere.h" #include "llrendersphere.h"
#include "llsdmessage.h" #include "llsdmessage.h"
@@ -131,6 +130,104 @@ std::string gAuthString;
LLUUID gReSitTargetID; LLUUID gReSitTargetID;
LLVector3 gReSitOffset; LLVector3 gReSitOffset;
// </edit> // </edit>
class LLTeleportRequest
{
public:
enum EStatus
{
kPending,
kStarted,
kFailed,
kRestartPending
};
LLTeleportRequest();
virtual ~LLTeleportRequest();
EStatus getStatus() const {return mStatus;};
void setStatus(EStatus pStatus) {mStatus = pStatus;};
virtual bool canRestartTeleport();
virtual void startTeleport() = 0;
virtual void restartTeleport();
protected:
private:
EStatus mStatus;
};
class LLTeleportRequestViaLandmark : public LLTeleportRequest
{
public:
LLTeleportRequestViaLandmark(const LLUUID &pLandmarkId);
virtual ~LLTeleportRequestViaLandmark();
virtual bool canRestartTeleport();
virtual void startTeleport();
virtual void restartTeleport();
protected:
inline const LLUUID &getLandmarkId() const {return mLandmarkId;};
private:
LLUUID mLandmarkId;
};
class LLTeleportRequestViaLure : public LLTeleportRequestViaLandmark
{
public:
LLTeleportRequestViaLure(const LLUUID &pLureId, BOOL pIsLureGodLike);
virtual ~LLTeleportRequestViaLure();
virtual bool canRestartTeleport();
virtual void startTeleport();
protected:
inline BOOL isLureGodLike() const {return mIsLureGodLike;};
private:
BOOL mIsLureGodLike;
};
class LLTeleportRequestViaLocation : public LLTeleportRequest
{
public:
LLTeleportRequestViaLocation(const LLVector3d &pPosGlobal);
virtual ~LLTeleportRequestViaLocation();
virtual bool canRestartTeleport();
virtual void startTeleport();
virtual void restartTeleport();
protected:
inline const LLVector3d &getPosGlobal() const {return mPosGlobal;};
private:
LLVector3d mPosGlobal;
};
class LLTeleportRequestViaLocationLookAt : public LLTeleportRequestViaLocation
{
public:
LLTeleportRequestViaLocationLookAt(const LLVector3d &pPosGlobal);
virtual ~LLTeleportRequestViaLocationLookAt();
virtual bool canRestartTeleport();
virtual void startTeleport();
virtual void restartTeleport();
protected:
private:
};
//-------------------------------------------------------------------- //--------------------------------------------------------------------
// Statics // Statics
// //
@@ -201,6 +298,19 @@ LLAgent::LLAgent() :
mbTeleportKeepsLookAt(false), mbTeleportKeepsLookAt(false),
mAgentAccess(new LLAgentAccess(gSavedSettings)), mAgentAccess(new LLAgentAccess(gSavedSettings)),
mGodLevelChangeSignal(),
mCanEditParcel(false),
mTeleportRequest(),
mTeleportFinishedSlot(),
mTeleportFailedSlot(),
mIsMaturityRatingChangingDuringTeleport(false),
mMaturityRatingChange(0U),
mIsDoSendMaturityPreferenceToServer(false),
mMaturityPreferenceRequestId(0U),
mMaturityPreferenceResponseId(0U),
mMaturityPreferenceNumRetries(0U),
mLastKnownRequestMaturity(SIM_ACCESS_MIN),
mLastKnownResponseMaturity(SIM_ACCESS_MIN),
mTeleportState( TELEPORT_NONE ), mTeleportState( TELEPORT_NONE ),
mRegionp(NULL), mRegionp(NULL),
@@ -277,9 +387,21 @@ void LLAgent::init()
gSavedSettings.getControl("PreferredMaturity")->getValidateSignal()->connect(boost::bind(&LLAgent::validateMaturity, this, _2)); gSavedSettings.getControl("PreferredMaturity")->getValidateSignal()->connect(boost::bind(&LLAgent::validateMaturity, this, _2));
gSavedSettings.getControl("PreferredMaturity")->getSignal()->connect(boost::bind(&LLAgent::handleMaturity, this, _2)); gSavedSettings.getControl("PreferredMaturity")->getSignal()->connect(boost::bind(&LLAgent::handleMaturity, this, _2));
mLastKnownResponseMaturity = static_cast<U8>(gSavedSettings.getU32("PreferredMaturity"));
mLastKnownRequestMaturity = mLastKnownResponseMaturity;
mIsDoSendMaturityPreferenceToServer = true;
LLViewerParcelMgr::getInstance()->addAgentParcelChangedCallback(boost::bind(&LLAgent::parcelChangedCallback)); LLViewerParcelMgr::getInstance()->addAgentParcelChangedCallback(boost::bind(&LLAgent::parcelChangedCallback));
if (!mTeleportFinishedSlot.connected())
{
mTeleportFinishedSlot = LLViewerParcelMgr::getInstance()->setTeleportFinishedCallback(boost::bind(&LLAgent::handleTeleportFinished, this));
}
if (!mTeleportFailedSlot.connected())
{
mTeleportFailedSlot = LLViewerParcelMgr::getInstance()->setTeleportFailedCallback(boost::bind(&LLAgent::handleTeleportFailed, this));
}
mInitialized = TRUE; mInitialized = TRUE;
} }
@@ -292,6 +414,14 @@ void LLAgent::cleanup()
if(mPendingLure) if(mPendingLure)
delete mPendingLure; delete mPendingLure;
mPendingLure = NULL; mPendingLure = NULL;
if (mTeleportFinishedSlot.connected())
{
mTeleportFinishedSlot.disconnect();
}
if (mTeleportFailedSlot.connected())
{
mTeleportFailedSlot.disconnect();
}
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@@ -1866,7 +1996,6 @@ void LLAgent::endAnimationUpdateUI()
gMenuBarView->setVisible(TRUE); gMenuBarView->setVisible(TRUE);
gStatusBar->setVisibleForMouselook(true); gStatusBar->setVisibleForMouselook(true);
LLPanelPathfindingRebakeNavmesh::getInstance()->setVisible(TRUE);
LLToolMgr::getInstance()->setCurrentToolset(gBasicToolset); LLToolMgr::getInstance()->setCurrentToolset(gBasicToolset);
@@ -1960,7 +2089,6 @@ void LLAgent::endAnimationUpdateUI()
gMenuBarView->setVisible(FALSE); gMenuBarView->setVisible(FALSE);
gStatusBar->setVisibleForMouselook(false); gStatusBar->setVisibleForMouselook(false);
LLPanelPathfindingRebakeNavmesh::getInstance()->setVisible(FALSE);
// clear out camera lag effect // clear out camera lag effect
gAgentCamera.clearCameraLag(); gAgentCamera.clearCameraLag();
@@ -2377,38 +2505,271 @@ int LLAgent::convertTextToMaturity(char text)
return LLAgentAccess::convertTextToMaturity(text); return LLAgentAccess::convertTextToMaturity(text);
} }
bool LLAgent::sendMaturityPreferenceToServer(int preferredMaturity) extern AIHTTPTimeoutPolicy maturityPreferences_timeout;
class LLMaturityPreferencesResponder : public LLHTTPClient::ResponderWithResult
{ {
if (!getRegion()) public:
return false; LLMaturityPreferencesResponder(LLAgent *pAgent, U8 pPreferredMaturity, U8 pPreviousMaturity);
virtual ~LLMaturityPreferencesResponder();
// Update agent access preference on the server
std::string url = getRegion()->getCapability("UpdateAgentInformation");
if (!url.empty())
{
// Set new access preference
LLSD access_prefs = LLSD::emptyMap();
if (preferredMaturity == SIM_ACCESS_PG)
{
access_prefs["max"] = "PG";
}
else if (preferredMaturity == SIM_ACCESS_MATURE)
{
access_prefs["max"] = "M";
}
if (preferredMaturity == SIM_ACCESS_ADULT)
{
access_prefs["max"] = "A";
}
LLSD body = LLSD::emptyMap(); virtual void result(const LLSD &pContent);
body["access_prefs"] = access_prefs; virtual void error(U32 pStatus, const std::string& pReason);
llinfos << "Sending access prefs update to " << (access_prefs["max"].asString()) << " via capability to: "
<< url << llendl; virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return maturityPreferences_timeout; }
LLHTTPClient::post(url, body, new LLHTTPClient::ResponderIgnore); // Ignore response
return true; private:
U8 parseMaturityFromServerResponse(const LLSD &pContent);
LLAgent *mAgent;
U8 mPreferredMaturity;
U8 mPreviousMaturity;
};
LLMaturityPreferencesResponder::LLMaturityPreferencesResponder(LLAgent *pAgent, U8 pPreferredMaturity, U8 pPreviousMaturity) :
mAgent(pAgent),
mPreferredMaturity(pPreferredMaturity),
mPreviousMaturity(pPreviousMaturity)
{
}
LLMaturityPreferencesResponder::~LLMaturityPreferencesResponder()
{
}
void LLMaturityPreferencesResponder::result(const LLSD &pContent)
{
U8 actualMaturity = parseMaturityFromServerResponse(pContent);
if (actualMaturity != mPreferredMaturity)
{
llwarns << "while attempting to change maturity preference from '" << LLViewerRegion::accessToString(mPreviousMaturity)
<< "' to '" << LLViewerRegion::accessToString(mPreferredMaturity) << "', the server responded with '"
<< LLViewerRegion::accessToString(actualMaturity) << "' [value:" << static_cast<U32>(actualMaturity) << ", llsd:"
<< pContent << "]" << llendl;
}
mAgent->handlePreferredMaturityResult(actualMaturity);
}
void LLMaturityPreferencesResponder::error(U32 pStatus, const std::string& pReason)
{
llwarns << "while attempting to change maturity preference from '" << LLViewerRegion::accessToString(mPreviousMaturity)
<< "' to '" << LLViewerRegion::accessToString(mPreferredMaturity) << "', we got an error because '"
<< pReason << "' [status:" << pStatus << "]" << llendl;
mAgent->handlePreferredMaturityError();
}
U8 LLMaturityPreferencesResponder::parseMaturityFromServerResponse(const LLSD &pContent)
{
// stinson 05/24/2012 Pathfinding regions have re-defined the response behavior. In the old server code,
// if you attempted to change the preferred maturity to the same value, the response content would be an
// undefined LLSD block. In the new server code with pathfinding, the response content should always be
// defined. Thus, the check for isUndefined() can be replaced with an assert after pathfinding is merged
// into server trunk and fully deployed.
U8 maturity = SIM_ACCESS_MIN;
if (pContent.isUndefined())
{
maturity = mPreferredMaturity;
}
else
{
llassert(!pContent.isUndefined());
llassert(pContent.isMap());
if (!pContent.isUndefined() && pContent.isMap())
{
// stinson 05/24/2012 Pathfinding regions have re-defined the response syntax. The if statement catches
// the new syntax, and the else statement catches the old syntax. After pathfinding is merged into
// server trunk and fully deployed, we can remove the else statement.
if (pContent.has("access_prefs"))
{
llassert(pContent.has("access_prefs"));
llassert(pContent.get("access_prefs").isMap());
llassert(pContent.get("access_prefs").has("max"));
llassert(pContent.get("access_prefs").get("max").isString());
if (pContent.get("access_prefs").isMap() && pContent.get("access_prefs").has("max") &&
pContent.get("access_prefs").get("max").isString())
{
LLSD::String actualPreference = pContent.get("access_prefs").get("max").asString();
LLStringUtil::trim(actualPreference);
maturity = LLViewerRegion::shortStringToAccess(actualPreference);
}
}
else if (pContent.has("max"))
{
llassert(pContent.get("max").isString());
if (pContent.get("max").isString())
{
LLSD::String actualPreference = pContent.get("max").asString();
LLStringUtil::trim(actualPreference);
maturity = LLViewerRegion::shortStringToAccess(actualPreference);
}
}
}
}
return maturity;
}
void LLAgent::handlePreferredMaturityResult(U8 pServerMaturity)
{
// Update the number of responses received
++mMaturityPreferenceResponseId;
llassert(mMaturityPreferenceResponseId <= mMaturityPreferenceRequestId);
// Update the last known server maturity response
mLastKnownResponseMaturity = pServerMaturity;
// Ignore all responses if we know there are more unanswered requests that are expected
if (mMaturityPreferenceResponseId == mMaturityPreferenceRequestId)
{
// If we received a response that matches the last known request, then we are good
if (mLastKnownRequestMaturity == mLastKnownResponseMaturity)
{
mMaturityPreferenceNumRetries = 0;
reportPreferredMaturitySuccess();
llassert(static_cast<U8>(gSavedSettings.getU32("PreferredMaturity")) == mLastKnownResponseMaturity);
}
// Else, the viewer is out of sync with the server, so let's try to re-sync with the
// server by re-sending our last known request. Cap the re-tries at 3 just to be safe.
else if (++mMaturityPreferenceNumRetries <= 3)
{
llinfos << "Retrying attempt #" << mMaturityPreferenceNumRetries << " to set viewer preferred maturity to '"
<< LLViewerRegion::accessToString(mLastKnownRequestMaturity) << "'" << llendl;
sendMaturityPreferenceToServer(mLastKnownRequestMaturity);
}
// Else, the viewer is style out of sync with the server after 3 retries, so inform the user
else
{
mMaturityPreferenceNumRetries = 0;
reportPreferredMaturityError();
}
}
}
void LLAgent::handlePreferredMaturityError()
{
// Update the number of responses received
++mMaturityPreferenceResponseId;
llassert(mMaturityPreferenceResponseId <= mMaturityPreferenceRequestId);
// Ignore all responses if we know there are more unanswered requests that are expected
if (mMaturityPreferenceResponseId == mMaturityPreferenceRequestId)
{
mMaturityPreferenceNumRetries = 0;
// If we received a response that matches the last known request, then we are synced with
// the server, but not quite sure why we are
if (mLastKnownRequestMaturity == mLastKnownResponseMaturity)
{
llwarns << "Got an error but maturity preference '" << LLViewerRegion::accessToString(mLastKnownRequestMaturity)
<< "' seems to be in sync with the server" << llendl;
reportPreferredMaturitySuccess();
}
// Else, the more likely case is that the last request does not match the last response,
// so inform the user
else
{
reportPreferredMaturityError();
}
}
}
void LLAgent::reportPreferredMaturitySuccess()
{
// If there is a pending teleport request waiting for the maturity preference to be synced with
// the server, let's start the pending request
if (hasPendingTeleportRequest())
{
startTeleportRequest();
}
}
void LLAgent::reportPreferredMaturityError()
{
// If there is a pending teleport request waiting for the maturity preference to be synced with
// the server, we were unable to successfully sync with the server on maturity preference, so let's
// just raise the screen.
mIsMaturityRatingChangingDuringTeleport = false;
if (hasPendingTeleportRequest())
{
setTeleportState(LLAgent::TELEPORT_NONE);
}
// Get the last known maturity request from the user activity
std::string preferredMaturity = LLViewerRegion::accessToString(mLastKnownRequestMaturity);
LLStringUtil::toLower(preferredMaturity);
// Get the last known maturity response from the server
std::string actualMaturity = LLViewerRegion::accessToString(mLastKnownResponseMaturity);
LLStringUtil::toLower(actualMaturity);
// Notify the user
LLSD args = LLSD::emptyMap();
args["PREFERRED_MATURITY"] = preferredMaturity;
args["ACTUAL_MATURITY"] = actualMaturity;
LLNotificationsUtil::add("MaturityChangeError", args);
// Check the saved settings to ensure that we are consistent. If we are not consistent, update
// the viewer, but do not send anything to server
U8 localMaturity = static_cast<U8>(gSavedSettings.getU32("PreferredMaturity"));
if (localMaturity != mLastKnownResponseMaturity)
{
bool tmpIsDoSendMaturityPreferenceToServer = mIsDoSendMaturityPreferenceToServer;
mIsDoSendMaturityPreferenceToServer = false;
llinfos << "Setting viewer preferred maturity to '" << LLViewerRegion::accessToString(mLastKnownResponseMaturity) << "'" << llendl;
gSavedSettings.setU32("PreferredMaturity", static_cast<U32>(mLastKnownResponseMaturity));
mIsDoSendMaturityPreferenceToServer = tmpIsDoSendMaturityPreferenceToServer;
}
}
bool LLAgent::isMaturityPreferenceSyncedWithServer() const
{
return (mMaturityPreferenceRequestId == mMaturityPreferenceResponseId);
}
void LLAgent::sendMaturityPreferenceToServer(U8 pPreferredMaturity)
{
// Only send maturity preference to the server if enabled
if (mIsDoSendMaturityPreferenceToServer)
{
// Increment the number of requests. The handlers manage a separate count of responses.
++mMaturityPreferenceRequestId;
// Update the last know maturity request
mLastKnownRequestMaturity = pPreferredMaturity;
// Create a response handler
boost::intrusive_ptr<LLMaturityPreferencesResponder> responderPtr = new LLMaturityPreferencesResponder(this, pPreferredMaturity, mLastKnownResponseMaturity);
// If we don't have a region, report it as an error
if (getRegion() == NULL)
{
responderPtr->error(0U, "region is not defined");
}
else
{
// Find the capability to send maturity preference
std::string url = getRegion()->getCapability("UpdateAgentInformation");
// If the capability is not defined, report it as an error
if (url.empty())
{
responderPtr->error(0U, "capability 'UpdateAgentInformation' is not defined for region");
}
else
{
// Set new access preference
LLSD access_prefs = LLSD::emptyMap();
access_prefs["max"] = LLViewerRegion::accessToShortString(pPreferredMaturity);
LLSD body = LLSD::emptyMap();
body["access_prefs"] = access_prefs;
llinfos << "Sending viewer preferred maturity to '" << LLViewerRegion::accessToString(pPreferredMaturity)
<< "' via capability to: " << url << llendl;
LLHTTPClient::post(url, body, responderPtr);
}
}
} }
return false;
} }
BOOL LLAgent::getAdminOverride() const BOOL LLAgent::getAdminOverride() const
@@ -2429,6 +2790,12 @@ void LLAgent::setAdminOverride(BOOL b)
void LLAgent::setGodLevel(U8 god_level) void LLAgent::setGodLevel(U8 god_level)
{ {
mAgentAccess->setGodLevel(god_level); mAgentAccess->setGodLevel(god_level);
mGodLevelChangeSignal(god_level);
}
LLAgent::god_level_change_slot_t LLAgent::registerGodLevelChanageListener(god_level_change_callback_t pGodLevelChangeCallback)
{
return mGodLevelChangeSignal.connect(pGodLevelChangeCallback);
} }
void LLAgent::setAOTransition() void LLAgent::setAOTransition()
@@ -2446,9 +2813,9 @@ bool LLAgent::validateMaturity(const LLSD& newvalue)
return mAgentAccess->canSetMaturity(newvalue.asInteger()); return mAgentAccess->canSetMaturity(newvalue.asInteger());
} }
void LLAgent::handleMaturity(const LLSD& newvalue) void LLAgent::handleMaturity(const LLSD &pNewValue)
{ {
sendMaturityPreferenceToServer(newvalue.asInteger()); sendMaturityPreferenceToServer(static_cast<U8>(pNewValue.asInteger()));
} }
void LLAgent::buildFullname(std::string& name) const void LLAgent::buildFullname(std::string& name) const
@@ -3460,7 +3827,7 @@ void LLAgent::clearVisualParams(void *data)
// protected // protected
bool LLAgent::teleportCore(bool is_local) bool LLAgent::teleportCore(bool is_local)
{ {
if(TELEPORT_NONE != mTeleportState) if ((TELEPORT_NONE != mTeleportState) && (mTeleportState != TELEPORT_PENDING))
{ {
llwarns << "Attempt to teleport when already teleporting." << llendl; llwarns << "Attempt to teleport when already teleporting." << llendl;
// <edit> // <edit>
@@ -3547,6 +3914,102 @@ bool LLAgent::teleportCore(bool is_local)
return true; return true;
} }
bool LLAgent::hasRestartableFailedTeleportRequest()
{
return ((mTeleportRequest != NULL) && (mTeleportRequest->getStatus() == LLTeleportRequest::kFailed) &&
mTeleportRequest->canRestartTeleport());
}
void LLAgent::restartFailedTeleportRequest()
{
if (hasRestartableFailedTeleportRequest())
{
mTeleportRequest->setStatus(LLTeleportRequest::kRestartPending);
startTeleportRequest();
}
}
void LLAgent::clearTeleportRequest()
{
mTeleportRequest.reset();
}
void LLAgent::setMaturityRatingChangeDuringTeleport(U8 pMaturityRatingChange)
{
mIsMaturityRatingChangingDuringTeleport = true;
mMaturityRatingChange = pMaturityRatingChange;
}
bool LLAgent::hasPendingTeleportRequest()
{
return ((mTeleportRequest != NULL) &&
((mTeleportRequest->getStatus() == LLTeleportRequest::kPending) ||
(mTeleportRequest->getStatus() == LLTeleportRequest::kRestartPending)));
}
void LLAgent::startTeleportRequest()
{
if (hasPendingTeleportRequest())
{
if (!isMaturityPreferenceSyncedWithServer())
{
gTeleportDisplay = TRUE;
setTeleportState(TELEPORT_PENDING);
}
else
{
switch (mTeleportRequest->getStatus())
{
case LLTeleportRequest::kPending :
mTeleportRequest->setStatus(LLTeleportRequest::kStarted);
mTeleportRequest->startTeleport();
break;
case LLTeleportRequest::kRestartPending :
llassert(mTeleportRequest->canRestartTeleport());
mTeleportRequest->setStatus(LLTeleportRequest::kStarted);
mTeleportRequest->restartTeleport();
break;
default :
llassert(0);
break;
}
}
}
}
void LLAgent::handleTeleportFinished()
{
clearTeleportRequest();
if (mIsMaturityRatingChangingDuringTeleport)
{
// notify user that the maturity preference has been changed
std::string maturityRating = LLViewerRegion::accessToString(mMaturityRatingChange);
LLStringUtil::toLower(maturityRating);
LLSD args;
args["RATING"] = maturityRating;
LLNotificationsUtil::add("PreferredMaturityChanged", args);
mIsMaturityRatingChangingDuringTeleport = false;
}
}
void LLAgent::handleTeleportFailed()
{
if (mTeleportRequest != NULL)
{
mTeleportRequest->setStatus(LLTeleportRequest::kFailed);
}
if (mIsMaturityRatingChangingDuringTeleport)
{
// notify user that the maturity preference has been changed
std::string maturityRating = LLViewerRegion::accessToString(mMaturityRatingChange);
LLStringUtil::toLower(maturityRating);
LLSD args;
args["RATING"] = maturityRating;
LLNotificationsUtil::add("PreferredMaturityChanged", args);
mIsMaturityRatingChangingDuringTeleport = false;
}
}
void LLAgent::teleportRequest( void LLAgent::teleportRequest(
const U64& region_handle, const U64& region_handle,
const LLVector3& pos_local, const LLVector3& pos_local,
@@ -3593,7 +4056,12 @@ void LLAgent::teleportViaLandmark(const LLUUID& landmark_asset_id)
return; return;
} }
// [/RLVa:KB] // [/RLVa:KB]
mTeleportRequest = LLTeleportRequestPtr(new LLTeleportRequestViaLandmark(landmark_asset_id));
startTeleportRequest();
}
void LLAgent::doTeleportViaLandmark(const LLUUID& landmark_asset_id)
{
LLViewerRegion *regionp = getRegion(); LLViewerRegion *regionp = getRegion();
if(regionp && teleportCore()) if(regionp && teleportCore())
{ {
@@ -3608,6 +4076,12 @@ void LLAgent::teleportViaLandmark(const LLUUID& landmark_asset_id)
} }
void LLAgent::teleportViaLure(const LLUUID& lure_id, BOOL godlike) void LLAgent::teleportViaLure(const LLUUID& lure_id, BOOL godlike)
{
mTeleportRequest = LLTeleportRequestPtr(new LLTeleportRequestViaLure(lure_id, godlike));
startTeleportRequest();
}
void LLAgent::doTeleportViaLure(const LLUUID& lure_id, BOOL godlike)
{ {
LLViewerRegion* regionp = getRegion(); LLViewerRegion* regionp = getRegion();
if(regionp && teleportCore()) if(regionp && teleportCore())
@@ -3640,18 +4114,21 @@ void LLAgent::teleportViaLure(const LLUUID& lure_id, BOOL godlike)
// James Cook, July 28, 2005 // James Cook, July 28, 2005
void LLAgent::teleportCancel() void LLAgent::teleportCancel()
{ {
LLViewerRegion* regionp = getRegion(); if (!hasPendingTeleportRequest())
if(regionp)
{ {
// send the message LLViewerRegion* regionp = getRegion();
LLMessageSystem* msg = gMessageSystem; if(regionp)
msg->newMessage("TeleportCancel"); {
msg->nextBlockFast(_PREHASH_Info); // send the message
msg->addUUIDFast(_PREHASH_AgentID, getID()); LLMessageSystem* msg = gMessageSystem;
msg->addUUIDFast(_PREHASH_SessionID, getSessionID()); msg->newMessage("TeleportCancel");
sendReliableMessage(); msg->nextBlockFast(_PREHASH_Info);
} msg->addUUIDFast(_PREHASH_AgentID, getID());
gTeleportDisplay = FALSE; msg->addUUIDFast(_PREHASH_SessionID, getSessionID());
sendReliableMessage();
}
}
clearTeleportRequest();
gAgent.setTeleportState( LLAgent::TELEPORT_NONE ); gAgent.setTeleportState( LLAgent::TELEPORT_NONE );
} }
@@ -3676,8 +4153,19 @@ void LLAgent::teleportViaLocation(const LLVector3d& pos_global)
} }
} }
// [/RLVa:KB] // [/RLVa:KB]
mTeleportRequest = LLTeleportRequestPtr(new LLTeleportRequestViaLocation(pos_global));
startTeleportRequest();
}
void LLAgent::doTeleportViaLocation(const LLVector3d& pos_global)
{
LLViewerRegion* regionp = getRegion(); LLViewerRegion* regionp = getRegion();
if (!regionp)
{
return;
}
U64 handle = to_region_handle(pos_global); U64 handle = to_region_handle(pos_global);
LLSimInfo* info = LLWorldMap::getInstance()->simInfoFromHandle(handle); LLSimInfo* info = LLWorldMap::getInstance()->simInfoFromHandle(handle);
bool calc = gSavedSettings.getBOOL("OptionOffsetTPByAgentHeight"); bool calc = gSavedSettings.getBOOL("OptionOffsetTPByAgentHeight");
@@ -3737,7 +4225,12 @@ void LLAgent::teleportViaLocationLookAt(const LLVector3d& pos_global)
return; return;
} }
// [/RLVa:KB] // [/RLVa:KB]
mTeleportRequest = LLTeleportRequestPtr(new LLTeleportRequestViaLocationLookAt(pos_global));
startTeleportRequest();
}
void LLAgent::doTeleportViaLocationLookAt(const LLVector3d& pos_global)
{
mbTeleportKeepsLookAt = true; mbTeleportKeepsLookAt = true;
gAgentCamera.setFocusOnAvatar(FALSE, ANIMATE); // detach camera form avatar, so it keeps direction gAgentCamera.setFocusOnAvatar(FALSE, ANIMATE); // detach camera form avatar, so it keeps direction
U64 region_handle = to_region_handle(pos_global); U64 region_handle = to_region_handle(pos_global);
@@ -4233,4 +4726,148 @@ LLAgentQueryManager::~LLAgentQueryManager()
{ {
} }
//-----------------------------------------------------------------------------
// LLTeleportRequest
//-----------------------------------------------------------------------------
LLTeleportRequest::LLTeleportRequest()
: mStatus(kPending)
{
}
LLTeleportRequest::~LLTeleportRequest()
{
}
bool LLTeleportRequest::canRestartTeleport()
{
return false;
}
void LLTeleportRequest::restartTeleport()
{
llassert(0);
}
//-----------------------------------------------------------------------------
// LLTeleportRequestViaLandmark
//-----------------------------------------------------------------------------
LLTeleportRequestViaLandmark::LLTeleportRequestViaLandmark(const LLUUID &pLandmarkId)
: LLTeleportRequest(),
mLandmarkId(pLandmarkId)
{
}
LLTeleportRequestViaLandmark::~LLTeleportRequestViaLandmark()
{
}
bool LLTeleportRequestViaLandmark::canRestartTeleport()
{
return true;
}
void LLTeleportRequestViaLandmark::startTeleport()
{
gAgent.doTeleportViaLandmark(getLandmarkId());
}
void LLTeleportRequestViaLandmark::restartTeleport()
{
gAgent.doTeleportViaLandmark(getLandmarkId());
}
//-----------------------------------------------------------------------------
// LLTeleportRequestViaLure
//-----------------------------------------------------------------------------
LLTeleportRequestViaLure::LLTeleportRequestViaLure(const LLUUID &pLureId, BOOL pIsLureGodLike)
: LLTeleportRequestViaLandmark(pLureId),
mIsLureGodLike(pIsLureGodLike)
{
}
LLTeleportRequestViaLure::~LLTeleportRequestViaLure()
{
}
bool LLTeleportRequestViaLure::canRestartTeleport()
{
// stinson 05/17/2012 : cannot restart a teleport via lure because of server-side restrictions
// The current scenario is as follows:
// 1. User A initializes a request for User B to teleport via lure
// 2. User B accepts the teleport via lure request
// 3. The server sees the init request from User A and the accept request from User B and matches them up
// 4. The server then removes the paired requests up from the "queue"
// 5. The server then fails User B's teleport for reason of maturity level (for example)
// 6. User B's viewer prompts user to increase their maturity level profile value.
// 7. User B confirms and accepts increase in maturity level
// 8. User B's viewer then attempts to teleport via lure again
// 9. This request will time-out on the viewer-side because User A's initial request has been removed from the "queue" in step 4
return false;
}
void LLTeleportRequestViaLure::startTeleport()
{
gAgent.doTeleportViaLure(getLandmarkId(), isLureGodLike());
}
//-----------------------------------------------------------------------------
// LLTeleportRequestViaLocation
//-----------------------------------------------------------------------------
LLTeleportRequestViaLocation::LLTeleportRequestViaLocation(const LLVector3d &pPosGlobal)
: LLTeleportRequest(),
mPosGlobal(pPosGlobal)
{
}
LLTeleportRequestViaLocation::~LLTeleportRequestViaLocation()
{
}
bool LLTeleportRequestViaLocation::canRestartTeleport()
{
return true;
}
void LLTeleportRequestViaLocation::startTeleport()
{
gAgent.doTeleportViaLocation(getPosGlobal());
}
void LLTeleportRequestViaLocation::restartTeleport()
{
gAgent.doTeleportViaLocation(getPosGlobal());
}
//-----------------------------------------------------------------------------
// LLTeleportRequestViaLocationLookAt
//-----------------------------------------------------------------------------
LLTeleportRequestViaLocationLookAt::LLTeleportRequestViaLocationLookAt(const LLVector3d &pPosGlobal)
: LLTeleportRequestViaLocation(pPosGlobal)
{
}
LLTeleportRequestViaLocationLookAt::~LLTeleportRequestViaLocationLookAt()
{
}
bool LLTeleportRequestViaLocationLookAt::canRestartTeleport()
{
return true;
}
void LLTeleportRequestViaLocationLookAt::startTeleport()
{
gAgent.doTeleportViaLocationLookAt(getPosGlobal());
}
void LLTeleportRequestViaLocationLookAt::restartTeleport()
{
gAgent.doTeleportViaLocationLookAt(getPosGlobal());
}
// EOF // EOF

View File

@@ -47,6 +47,8 @@
#include "llinventorymodel.h" #include "llinventorymodel.h"
#include "v3dmath.h" #include "v3dmath.h"
#include <boost/function.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/signals2.hpp> #include <boost/signals2.hpp>
extern const BOOL ANIMATE; extern const BOOL ANIMATE;
@@ -67,8 +69,10 @@ class LLViewerObject;
class LLAgentDropGroupViewerNode; class LLAgentDropGroupViewerNode;
class LLAgentAccess; class LLAgentAccess;
class LLSimInfo; class LLSimInfo;
class LLTeleportRequest;
typedef std::vector<LLViewerObject*> llvo_vec_t; typedef std::vector<LLViewerObject*> llvo_vec_t;
typedef boost::shared_ptr<LLTeleportRequest> LLTeleportRequestPtr;
enum EAnimRequest enum EAnimRequest
{ {
@@ -557,7 +561,8 @@ public:
TELEPORT_MOVING = 3, // Viewer has received destination location from source simulator TELEPORT_MOVING = 3, // Viewer has received destination location from source simulator
TELEPORT_START_ARRIVAL = 4, // Transition to ARRIVING. Viewer has received avatar update, etc., from destination simulator TELEPORT_START_ARRIVAL = 4, // Transition to ARRIVING. Viewer has received avatar update, etc., from destination simulator
TELEPORT_ARRIVING = 5, // Make the user wait while content "pre-caches" TELEPORT_ARRIVING = 5, // Make the user wait while content "pre-caches"
TELEPORT_LOCAL = 6 // Teleporting in-sim without showing the progress screen TELEPORT_LOCAL = 6, // Teleporting in-sim without showing the progress screen
TELEPORT_PENDING = 7
}; };
public: public:
@@ -573,9 +578,6 @@ public:
// Teleport Actions // Teleport Actions
//-------------------------------------------------------------------- //--------------------------------------------------------------------
public: public:
void teleportRequest(const U64& region_handle,
const LLVector3& pos_local, // Go to a named location home
bool look_at_from_camera = false);
void teleportViaLandmark(const LLUUID& landmark_id); // Teleport to a landmark void teleportViaLandmark(const LLUUID& landmark_id); // Teleport to a landmark
void teleportHome() { teleportViaLandmark(LLUUID::null); } // Go home void teleportHome() { teleportViaLandmark(LLUUID::null); } // Go home
void teleportViaLure(const LLUUID& lure_id, BOOL godlike); // To an invited location void teleportViaLure(const LLUUID& lure_id, BOOL godlike); // To an invited location
@@ -586,6 +588,44 @@ public:
protected: protected:
bool teleportCore(bool is_local = false); // Stuff for all teleports; returns true if the teleport can proceed bool teleportCore(bool is_local = false); // Stuff for all teleports; returns true if the teleport can proceed
//--------------------------------------------------------------------
// Teleport State
//--------------------------------------------------------------------
public:
bool hasRestartableFailedTeleportRequest();
void restartFailedTeleportRequest();
void clearTeleportRequest();
void setMaturityRatingChangeDuringTeleport(U8 pMaturityRatingChange);
private:
friend class LLTeleportRequest;
friend class LLTeleportRequestViaLandmark;
friend class LLTeleportRequestViaLure;
friend class LLTeleportRequestViaLocation;
friend class LLTeleportRequestViaLocationLookAt;
LLTeleportRequestPtr mTeleportRequest;
boost::signals2::connection mTeleportFinishedSlot;
boost::signals2::connection mTeleportFailedSlot;
bool mIsMaturityRatingChangingDuringTeleport;
U8 mMaturityRatingChange;
bool hasPendingTeleportRequest();
void startTeleportRequest();
void teleportRequest(const U64& region_handle,
const LLVector3& pos_local, // Go to a named location home
bool look_at_from_camera = false);
void doTeleportViaLandmark(const LLUUID& landmark_id); // Teleport to a landmark
void doTeleportViaLure(const LLUUID& lure_id, BOOL godlike); // To an invited location
void doTeleportViaLocation(const LLVector3d& pos_global); // To a global location - this will probably need to be deprecated
void doTeleportViaLocationLookAt(const LLVector3d& pos_global);// To a global location, preserving camera rotation
void handleTeleportFinished();
void handleTeleportFailed();
//-------------------------------------------------------------------- //--------------------------------------------------------------------
// Teleport State // Teleport State
//-------------------------------------------------------------------- //--------------------------------------------------------------------
@@ -648,6 +688,16 @@ public:
void requestEnterGodMode(); void requestEnterGodMode();
void requestLeaveGodMode(); void requestLeaveGodMode();
typedef boost::function<void (U8)> god_level_change_callback_t;
typedef boost::signals2::signal<void (U8)> god_level_change_signal_t;
typedef boost::signals2::connection god_level_change_slot_t;
god_level_change_slot_t registerGodLevelChanageListener(god_level_change_callback_t pGodLevelChangeCallback);
private:
god_level_change_signal_t mGodLevelChangeSignal;
//-------------------------------------------------------------------- //--------------------------------------------------------------------
// Maturity // Maturity
//-------------------------------------------------------------------- //--------------------------------------------------------------------
@@ -670,10 +720,25 @@ public:
void setTeen(bool teen); void setTeen(bool teen);
void setMaturity(char text); void setMaturity(char text);
static int convertTextToMaturity(char text); static int convertTextToMaturity(char text);
bool sendMaturityPreferenceToServer(int preferredMaturity); // ! "U8" instead of "int"? private:
bool mIsDoSendMaturityPreferenceToServer;
unsigned int mMaturityPreferenceRequestId;
unsigned int mMaturityPreferenceResponseId;
unsigned int mMaturityPreferenceNumRetries;
U8 mLastKnownRequestMaturity;
U8 mLastKnownResponseMaturity;
bool isMaturityPreferenceSyncedWithServer() const;
void sendMaturityPreferenceToServer(U8 pPreferredMaturity);
friend class LLMaturityPreferencesResponder;
void handlePreferredMaturityResult(U8 pServerMaturity);
void handlePreferredMaturityError();
void reportPreferredMaturitySuccess();
void reportPreferredMaturityError();
// Maturity callbacks for PreferredMaturity control variable // Maturity callbacks for PreferredMaturity control variable
void handleMaturity(const LLSD& newvalue); void handleMaturity(const LLSD &pNewValue);
bool validateMaturity(const LLSD& newvalue); bool validateMaturity(const LLSD& newvalue);

View File

@@ -410,11 +410,7 @@ LLVector3 LLAgentCamera::calcFocusOffset(LLViewerObject *object, LLVector3 origi
} }
LLQuaternion inv_obj_rot = ~obj_rot; // get inverse of rotation LLQuaternion inv_obj_rot = ~obj_rot; // get inverse of rotation
LLVector3 object_extents = object->getScale(); LLVector3 object_extents = object->getScale();
//this stuff just seems to make camera snapping worse...
//const LLVector4a* oe4 = object->mDrawable->getSpatialExtents();
//object_extents.set( oe4[1][0], oe4[1][1], oe4[1][2] );
// make sure they object extents are non-zero // make sure they object extents are non-zero
object_extents.clamp(0.001f, F32_MAX); object_extents.clamp(0.001f, F32_MAX);
@@ -1637,7 +1633,7 @@ LLVector3d LLAgentCamera::calcFocusPositionTargetGlobal()
{ {
gPipeline.updateMoveNormalAsync(drawablep); gPipeline.updateMoveNormalAsync(drawablep);
} }
else else if(!drawablep->isState(LLDrawable::ON_MOVE_LIST))
{ {
if (drawablep->isState(LLDrawable::MOVE_UNDAMPED)) if (drawablep->isState(LLDrawable::MOVE_UNDAMPED))
{ {
@@ -2312,12 +2308,7 @@ void LLAgentCamera::changeCameraToThirdPerson(BOOL animate)
} }
updateLastCamera(); updateLastCamera();
mCameraMode = CAMERA_MODE_THIRD_PERSON; mCameraMode = CAMERA_MODE_THIRD_PERSON;
U32 old_flags = gAgent.getControlFlags();
gAgent.clearControlFlags(AGENT_CONTROL_MOUSELOOK); gAgent.clearControlFlags(AGENT_CONTROL_MOUSELOOK);
if (old_flags != gAgent.getControlFlags())
{
gAgent.setFlagsDirty();
}
} }
// Remove any pitch from the avatar // Remove any pitch from the avatar
@@ -2523,9 +2514,10 @@ void LLAgentCamera::setFocusObject(LLViewerObject* object)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void LLAgentCamera::setFocusGlobal(const LLPickInfo& pick) void LLAgentCamera::setFocusGlobal(const LLPickInfo& pick)
{ {
static const LLCachedControl<bool> freeze_time("FreezeTime",false);
LLViewerObject* objectp = gObjectList.findObject(pick.mObjectID); LLViewerObject* objectp = gObjectList.findObject(pick.mObjectID);
if (objectp) if (objectp && !freeze_time)
{ {
// focus on object plus designated offset // focus on object plus designated offset
// which may or may not be same as pick.mPosGlobal // which may or may not be same as pick.mPosGlobal

View File

@@ -3974,7 +3974,8 @@ void LLAppViewer::idle()
} }
static const LLCachedControl<bool> hide_tp_screen("AscentDisableTeleportScreens",false); static const LLCachedControl<bool> hide_tp_screen("AscentDisableTeleportScreens",false);
if (!hide_tp_screen && gAgent.getTeleportState() != LLAgent::TELEPORT_NONE && gAgent.getTeleportState() != LLAgent::TELEPORT_LOCAL) LLAgent::ETeleportState tp_state = gAgent.getTeleportState();
if (!hide_tp_screen && tp_state != LLAgent::TELEPORT_NONE && tp_state != LLAgent::TELEPORT_LOCAL && tp_state != LLAgent::TELEPORT_PENDING)
{ {
return; return;
} }

View File

@@ -237,7 +237,10 @@ void LLDrawPoolWater::render(S32 pass)
glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
// Slowly move over time. // Slowly move over time.
F32 offset = fmod(gFrameTimeSeconds*2.f, 100.f); static const LLCachedControl<bool> freeze_time("FreezeTime",false);
static F32 frame_time;
if (!freeze_time) frame_time = gFrameTimeSeconds;
F32 offset = fmod(frame_time*2.f, 100.f);
F32 tp0[4] = {16.f/256.f, 0.0f, 0.0f, offset*0.01f}; F32 tp0[4] = {16.f/256.f, 0.0f, 0.0f, offset*0.01f};
F32 tp1[4] = {0.0f, 16.f/256.f, 0.0f, offset*0.01f}; F32 tp1[4] = {0.0f, 16.f/256.f, 0.0f, offset*0.01f};
glTexGenfv(GL_S, GL_OBJECT_PLANE, tp0); glTexGenfv(GL_S, GL_OBJECT_PLANE, tp0);
@@ -418,11 +421,14 @@ void LLDrawPoolWater::renderOpaqueLegacyWater()
// Use the fact that we know all water faces are the same size // Use the fact that we know all water faces are the same size
// to save some computation // to save some computation
// Slowly move texture coordinates over time so the watter appears // Slowly move texture coordinates over time so the water appears
// to be moving. // to be moving.
F32 movement_period_secs = 50.f; F32 movement_period_secs = 50.f;
F32 offset = fmod(gFrameTimeSeconds, movement_period_secs); static const LLCachedControl<bool> freeze_time("FreezeTime",false);
static F32 frame_time;
if (!freeze_time) frame_time = gFrameTimeSeconds;
F32 offset = fmod(frame_time, movement_period_secs);
if (movement_period_secs != 0) if (movement_period_secs != 0)
{ {
@@ -580,7 +586,11 @@ void LLDrawPoolWater::shade()
shader->bind(); shader->bind();
} }
sTime = (F32)LLFrameTimer::getElapsedSeconds()*0.5f; static const LLCachedControl<bool> freeze_time("FreezeTime",false);
if (!freeze_time)
{
sTime = (F32)LLFrameTimer::getElapsedSeconds()*0.5f;
}
S32 reftex = shader->enableTexture(LLViewerShaderMgr::WATER_REFTEX); S32 reftex = shader->enableTexture(LLViewerShaderMgr::WATER_REFTEX);

View File

@@ -47,6 +47,8 @@
#include "rlvhandler.h" #include "rlvhandler.h"
// [/RLVa:KB] // [/RLVa:KB]
#include "hippogridmanager.h"
std::string LLEnvPrefs::getWaterPresetName() const std::string LLEnvPrefs::getWaterPresetName() const
{ {
if (mWaterPresetName.empty()) if (mWaterPresetName.empty())
@@ -509,7 +511,8 @@ void LLEnvManagerNew::onRegionSettingsResponse(const LLSD& content)
mRegionSettingsChangeSignal(); mRegionSettingsChangeSignal();
// reset // reset
mInterpNextChangeMessage = false; if (!gHippoGridManager->getConnectedGrid()->isAurora()) // On Aurora, the region says when to refresh
mInterpNextChangeMessage = false;
} }
void LLEnvManagerNew::onRegionSettingsApplyResponse(bool ok) void LLEnvManagerNew::onRegionSettingsApplyResponse(bool ok)
@@ -698,3 +701,36 @@ void LLEnvManagerNew::onRegionChange(bool interpolate)
// Let interested parties know agent region has been changed. // Let interested parties know agent region has been changed.
mRegionChangeSignal(); mRegionChangeSignal();
} }
// Aurora-sim windlight refresh
class WindLightRefresh : public LLHTTPNode
{
/*virtual*/ void post(LLHTTPNode::ResponsePtr response, const LLSD& context, const LLSD& input) const
{
if (!input || !context || !input.isMap() || !input.has("body"))
{
llinfos << "malformed WindLightRefresh!" << llendl;
return;
}
//std::string dump = input["body"].asString();
//llwarns << dump << llendl;
LLSD body = input["body"];
LLEnvManagerNew *env = &LLEnvManagerNew::instance();
LLViewerRegion* regionp = gAgent.getRegion();
LLUUID region_uuid = regionp ? regionp->getRegionID() : LLUUID::null;
env->mNewRegionPrefs.clear();
env->mCurRegionUUID = region_uuid;
env->mInterpNextChangeMessage = !body.has("Interpolate") || body["Interpolate"].asInteger() == 1;
llinfos << "Windlight Refresh, interpolate:" << env->mInterpNextChangeMessage << llendl;
env->requestRegionSettings();
env->mRegionChangeSignal();
}
};
LLHTTPRegistration<WindLightRefresh> gHTTPRegistrationWindLightRefresh("/message/WindLightRefresh");

View File

@@ -35,11 +35,11 @@
#include "llmemory.h" #include "llmemory.h"
#include "llsd.h" #include "llsd.h"
#include <boost/signals2.hpp>
class LLWLParamManager; class LLWLParamManager;
class LLWaterParamManager; class LLWaterParamManager;
class LLWLAnimator; class LLWLAnimator;
class WindLightRefresh;
// generic key // generic key
struct LLEnvKey struct LLEnvKey
@@ -257,6 +257,7 @@ public:
bool useRegionWater(); bool useRegionWater();
private: private:
friend class WindLightRefresh;
bool useDefaultSky(); bool useDefaultSky();
bool useDefaultWater(); bool useDefaultWater();

View File

@@ -180,7 +180,7 @@ void LLFloaterAuction::onClickSnapshot(void* data)
BOOL success = gViewerWindow->rawSnapshot(raw, BOOL success = gViewerWindow->rawSnapshot(raw,
gViewerWindow->getWindowWidth(), gViewerWindow->getWindowWidth(),
gViewerWindow->getWindowHeight(), gViewerWindow->getWindowHeight(),
TRUE, FALSE, (F32)gViewerWindow->getWindowWidth() / gViewerWindow->getWindowHeight(),
FALSE, FALSE); FALSE, FALSE);
gForceRenderLandFence = FALSE; gForceRenderLandFence = FALSE;

View File

@@ -52,7 +52,9 @@
#include <string.h> #include <string.h>
#include <map> #include <map>
#include <boost/date_time.hpp>
#include <boost/foreach.hpp> #include <boost/foreach.hpp>
#include <boost/lexical_cast.hpp>
#include "llworld.h" #include "llworld.h"
#include "llsdutil.h" #include "llsdutil.h"
@@ -79,6 +81,7 @@ typedef enum e_radar_alert_type
ALERT_TYPE_DRAW = 2, ALERT_TYPE_DRAW = 2,
ALERT_TYPE_SHOUTRANGE = 4, ALERT_TYPE_SHOUTRANGE = 4,
ALERT_TYPE_CHATRANGE = 8, ALERT_TYPE_CHATRANGE = 8,
ALERT_TYPE_AGE = 16,
} ERadarAlertType; } ERadarAlertType;
void chat_avatar_status(std::string name, LLUUID key, ERadarAlertType type, bool entering) void chat_avatar_status(std::string name, LLUUID key, ERadarAlertType type, bool entering)
@@ -90,10 +93,12 @@ void chat_avatar_status(std::string name, LLUUID key, ERadarAlertType type, bool
static LLCachedControl<bool> radar_alert_draw(gSavedSettings, "RadarAlertDraw"); static LLCachedControl<bool> radar_alert_draw(gSavedSettings, "RadarAlertDraw");
static LLCachedControl<bool> radar_alert_shout_range(gSavedSettings, "RadarAlertShoutRange"); static LLCachedControl<bool> radar_alert_shout_range(gSavedSettings, "RadarAlertShoutRange");
static LLCachedControl<bool> radar_alert_chat_range(gSavedSettings, "RadarAlertChatRange"); static LLCachedControl<bool> radar_alert_chat_range(gSavedSettings, "RadarAlertChatRange");
static LLCachedControl<bool> radar_alert_age(gSavedSettings, "RadarAlertAge");
static LLCachedControl<bool> radar_chat_keys(gSavedSettings, "RadarChatKeys"); static LLCachedControl<bool> radar_chat_keys(gSavedSettings, "RadarChatKeys");
LLFloaterAvatarList* self = LLFloaterAvatarList::getInstance(); LLFloaterAvatarList* self = LLFloaterAvatarList::getInstance();
LLStringUtil::format_map_t args; LLStringUtil::format_map_t args;
args["[NAME]"] = name;
switch(type) switch(type)
{ {
case ALERT_TYPE_SIM: case ALERT_TYPE_SIM:
@@ -123,10 +128,21 @@ void chat_avatar_status(std::string name, LLUUID key, ERadarAlertType type, bool
args["[RANGE]"] = self->getString("chat_range"); args["[RANGE]"] = self->getString("chat_range");
} }
break; break;
case ALERT_TYPE_AGE:
if (radar_alert_age)
{
LLChat chat;
chat.mFromName = name;
chat.mText = name + " " + self->getString("has_triggered_your_avatar_age_alert") + ".";
chat.mURL = llformat("secondlife:///app/agent/%s/about",key.asString().c_str());
chat.mSourceType = CHAT_SOURCE_SYSTEM;
LLFloaterChat::addChat(chat);
}
break;
} }
if (args.find("[RANGE]") != args.end()) if (args.find("[RANGE]") != args.end())
{ {
args["[NAME]"] = name;
args["[ACTION]"] = self->getString(entering ? "has_entered" : "has_left"); args["[ACTION]"] = self->getString(entering ? "has_entered" : "has_left");
LLChat chat; LLChat chat;
chat.mText = self->getString("template", args); chat.mText = self->getString("template", args);
@@ -142,8 +158,37 @@ LLAvatarListEntry::LLAvatarListEntry(const LLUUID& id, const std::string &name,
mUpdateTimer(), mFrame(gFrameCount), mInSimFrame(U32_MAX), mInDrawFrame(U32_MAX), mUpdateTimer(), mFrame(gFrameCount), mInSimFrame(U32_MAX), mInDrawFrame(U32_MAX),
mInChatFrame(U32_MAX), mInShoutFrame(U32_MAX), mInChatFrame(U32_MAX), mInShoutFrame(U32_MAX),
mActivityType(ACTIVITY_NEW), mActivityTimer(), mActivityType(ACTIVITY_NEW), mActivityTimer(),
mIsInList(false) mIsInList(false), mAge(-1), mAgeAlert(false), mTime(time(NULL))
{ {
if (mID.notNull())
{
LLAvatarPropertiesProcessor::getInstance()->addObserver(mID, this);
LLAvatarPropertiesProcessor::getInstance()->sendAvatarPropertiesRequest(mID);
}
}
LLAvatarListEntry::~LLAvatarListEntry()
{
if (mID.notNull())
LLAvatarPropertiesProcessor::getInstance()->removeObserver(mID, this);
}
// virtual
void LLAvatarListEntry::processProperties(void* data, EAvatarProcessorType type)
{
if(type == APT_PROPERTIES)
{
LLAvatarPropertiesProcessor::getInstance()->removeObserver(mID, this);
const LLAvatarData* pAvatarData = static_cast<const LLAvatarData*>(data);
if (pAvatarData && (pAvatarData->avatar_id != LLUUID::null))
{
using namespace boost::gregorian;
int year, month, day;
sscanf(pAvatarData->born_on.c_str(),"%d/%d/%d",&month,&day,&year);
mAge = (day_clock::local_day() - date(year, month, day)).days();
// If one wanted more information that gets displayed on profiles to be displayed, here would be the place to do it.
}
}
} }
void LLAvatarListEntry::setPosition(LLVector3d position, bool this_sim, bool drawn, bool chatrange, bool shoutrange) void LLAvatarListEntry::setPosition(LLVector3d position, bool this_sim, bool drawn, bool chatrange, bool shoutrange)
@@ -354,6 +399,13 @@ BOOL LLFloaterAvatarList::postBuild()
getChild<LLRadioGroup>("update_rate")->setSelectedIndex(gSavedSettings.getU32("RadarUpdateRate")); getChild<LLRadioGroup>("update_rate")->setSelectedIndex(gSavedSettings.getU32("RadarUpdateRate"));
getChild<LLRadioGroup>("update_rate")->setCommitCallback(boost::bind(&LLFloaterAvatarList::onCommitUpdateRate, this)); getChild<LLRadioGroup>("update_rate")->setCommitCallback(boost::bind(&LLFloaterAvatarList::onCommitUpdateRate, this));
getChild<LLCheckboxCtrl>("hide_mark")->setCommitCallback(boost::bind(&LLFloaterAvatarList::assessColumns, this));
getChild<LLCheckboxCtrl>("hide_pos")->setCommitCallback(boost::bind(&LLFloaterAvatarList::assessColumns, this));
getChild<LLCheckboxCtrl>("hide_alt")->setCommitCallback(boost::bind(&LLFloaterAvatarList::assessColumns, this));
getChild<LLCheckboxCtrl>("hide_act")->setCommitCallback(boost::bind(&LLFloaterAvatarList::assessColumns, this));
getChild<LLCheckboxCtrl>("hide_age")->setCommitCallback(boost::bind(&LLFloaterAvatarList::assessColumns, this));
getChild<LLCheckboxCtrl>("hide_time")->setCommitCallback(boost::bind(&LLFloaterAvatarList::assessColumns, this));
// Get a pointer to the scroll list from the interface // Get a pointer to the scroll list from the interface
mAvatarList = getChild<LLScrollListCtrl>("avatar_list"); mAvatarList = getChild<LLScrollListCtrl>("avatar_list");
mAvatarList->sortByColumn("distance", TRUE); mAvatarList->sortByColumn("distance", TRUE);
@@ -365,20 +417,69 @@ BOOL LLFloaterAvatarList::postBuild()
gIdleCallbacks.addFunction(LLFloaterAvatarList::callbackIdle); gIdleCallbacks.addFunction(LLFloaterAvatarList::callbackIdle);
if(gHippoGridManager->getConnectedGrid()->isSecondLife()){ assessColumns();
LLScrollListCtrl* list = getChild<LLScrollListCtrl>("avatar_list");
list->getColumn(LIST_AVATAR_NAME)->setWidth(0); if(gHippoGridManager->getConnectedGrid()->isSecondLife())
list->getColumn(LIST_CLIENT)->setWidth(0); childSetVisible("hide_client", false);
list->getColumn(LIST_CLIENT)->mDynamicWidth = FALSE; else
list->getColumn(LIST_CLIENT)->mRelWidth = 0; getChild<LLCheckboxCtrl>("hide_client")->setCommitCallback(boost::bind(&LLFloaterAvatarList::assessColumns, this));
list->getColumn(LIST_AVATAR_NAME)->mDynamicWidth = TRUE;
list->getColumn(LIST_AVATAR_NAME)->mRelWidth = -1;
list->updateLayout();
}
return TRUE; return TRUE;
} }
void col_helper(const bool hide, const std::string width_ctrl_name, LLScrollListColumn* col)
{
// Brief Explanation:
// Check if we want the column hidden, and if it's still showing. If so, hide it, but save its width.
// Otherwise, if we don't want it hidden, but it is, unhide it to the saved width.
// We only store width of columns when hiding here for the purpose of hiding and unhiding.
const int width = col->getWidth();
if (hide && width)
{
gSavedSettings.setS32(width_ctrl_name, width);
col->setWidth(0);
}
else if(!hide && !width)
{
llinfos << "We got into the setter!!" << llendl;
col->setWidth(gSavedSettings.getS32(width_ctrl_name));
}
}
void LLFloaterAvatarList::assessColumns()
{
static LLCachedControl<bool> hide_mark(gSavedSettings, "RadarColumnMarkHidden");
col_helper(hide_mark, "RadarColumnMarkWidth", mAvatarList->getColumn(LIST_MARK));
static LLCachedControl<bool> hide_pos(gSavedSettings, "RadarColumnPositionHidden");
col_helper(hide_pos, "RadarColumnPositionWidth", mAvatarList->getColumn(LIST_POSITION));
static LLCachedControl<bool> hide_alt(gSavedSettings, "RadarColumnAltitudeHidden");
col_helper(hide_alt, "RadarColumnAltitudeWidth", mAvatarList->getColumn(LIST_ALTITUDE));
static LLCachedControl<bool> hide_act(gSavedSettings, "RadarColumnActivityHidden");
col_helper(hide_act, "RadarColumnActivityWidth", mAvatarList->getColumn(LIST_ACTIVITY));
static LLCachedControl<bool> hide_age(gSavedSettings, "RadarColumnAgeHidden");
col_helper(hide_age, "RadarColumnAgeWidth", mAvatarList->getColumn(LIST_AGE));
static LLCachedControl<bool> hide_time(gSavedSettings, "RadarColumnTimeHidden");
col_helper(hide_time, "RadarColumnTimeWidth", mAvatarList->getColumn(LIST_TIME));
static LLCachedControl<bool> hide_client(gSavedSettings, "RadarColumnClientHidden");
if (gHippoGridManager->getConnectedGrid()->isSecondLife() || hide_client){
mAvatarList->getColumn(LIST_AVATAR_NAME)->setWidth(0);
mAvatarList->getColumn(LIST_CLIENT)->setWidth(0);
mAvatarList->getColumn(LIST_CLIENT)->mDynamicWidth = FALSE;
mAvatarList->getColumn(LIST_CLIENT)->mRelWidth = 0;
mAvatarList->getColumn(LIST_AVATAR_NAME)->mDynamicWidth = TRUE;
mAvatarList->getColumn(LIST_AVATAR_NAME)->mRelWidth = -1;
}
mAvatarList->updateLayout();
}
void updateParticleActivity(LLDrawable *drawablep) void updateParticleActivity(LLDrawable *drawablep)
{ {
if (LLFloaterAvatarList::instanceExists()) if (LLFloaterAvatarList::instanceExists())
@@ -511,10 +612,9 @@ void LLFloaterAvatarList::updateAvatarList()
else else
{ {
// Avatar not there yet, add it // Avatar not there yet, add it
LLAvatarListEntry entry(avid, name, position);
if(announce && avatarp->getRegion() == gAgent.getRegion()) if(announce && avatarp->getRegion() == gAgent.getRegion())
announce_keys.push(avid); announce_keys.push(avid);
mAvatars.push_back(entry); mAvatars.push_back(LLAvatarListEntryPtr(new LLAvatarListEntry(avid, name, position)));
} }
} }
else else
@@ -543,10 +643,9 @@ void LLFloaterAvatarList::updateAvatarList()
} }
else else
{ {
LLAvatarListEntry entry(avid, name, position);
if(announce && gAgent.getRegion()->pointInRegionGlobal(position)) if(announce && gAgent.getRegion()->pointInRegionGlobal(position))
announce_keys.push(avid); announce_keys.push(avid);
mAvatars.push_back(entry); mAvatars.push_back(LLAvatarListEntryPtr(new LLAvatarListEntry(avid, name, position)));
} }
} }
} }
@@ -610,10 +709,19 @@ void LLFloaterAvatarList::expireAvatarList()
// llinfos << "radar: expiring" << llendl; // llinfos << "radar: expiring" << llendl;
for(av_list_t::iterator it = mAvatars.begin(); it != mAvatars.end();) for(av_list_t::iterator it = mAvatars.begin(); it != mAvatars.end();)
{ {
if(!it->isDead()) LLAvatarListEntry* entry = it->get();
(it++)->getAlive(); if(!entry->isDead())
{
entry->getAlive();
++it;
}
else else
{ {
if(mAvatars.back() == *it)
{
mAvatars.pop_back();
return;
}
*it = mAvatars.back(); *it = mAvatars.back();
mAvatars.pop_back(); mAvatars.pop_back();
if(mAvatars.empty()) if(mAvatars.empty())
@@ -674,17 +782,17 @@ void LLFloaterAvatarList::refreshAvatarList()
std::string av_name; std::string av_name;
// Skip if avatar hasn't been around // Skip if avatar hasn't been around
if (entry.isDead()) if (entry->isDead())
{ {
continue; continue;
} }
entry.setInList(); entry->setInList();
av_id = entry.getID(); av_id = entry->getID();
av_name = entry.getName().c_str(); av_name = entry->getName().c_str();
LLVector3d position = entry.getPosition(); LLVector3d position = entry->getPosition();
BOOL UnknownAltitude = false; BOOL UnknownAltitude = false;
LLVector3d delta = position - mypos; LLVector3d delta = position - mypos;
@@ -716,11 +824,12 @@ void LLFloaterAvatarList::refreshAvatarList()
continue; continue;
} }
element["id"] = av_id; element["id"] = av_id;
element["columns"][LIST_MARK]["column"] = "marked"; element["columns"][LIST_MARK]["column"] = "marked";
element["columns"][LIST_MARK]["type"] = "text"; element["columns"][LIST_MARK]["type"] = "text";
if (entry.isMarked()) if (entry->isMarked())
{ {
element["columns"][LIST_MARK]["value"] = "X"; element["columns"][LIST_MARK]["value"] = "X";
element["columns"][LIST_MARK]["color"] = LLColor4::blue.getValue(); element["columns"][LIST_MARK]["color"] = LLColor4::blue.getValue();
@@ -734,7 +843,7 @@ void LLFloaterAvatarList::refreshAvatarList()
element["columns"][LIST_AVATAR_NAME]["column"] = "avatar_name"; element["columns"][LIST_AVATAR_NAME]["column"] = "avatar_name";
element["columns"][LIST_AVATAR_NAME]["type"] = "text"; element["columns"][LIST_AVATAR_NAME]["type"] = "text";
element["columns"][LIST_AVATAR_NAME]["value"] = av_name; element["columns"][LIST_AVATAR_NAME]["value"] = av_name;
if (entry.isFocused()) if (entry->isFocused())
{ {
element["columns"][LIST_AVATAR_NAME]["font-style"] = "BOLD"; element["columns"][LIST_AVATAR_NAME]["font-style"] = "BOLD";
} }
@@ -742,7 +851,7 @@ void LLFloaterAvatarList::refreshAvatarList()
//<edit> custom colors for certain types of avatars! //<edit> custom colors for certain types of avatars!
//Changed a bit so people can modify them in settings. And since they're colors, again it's possibly account-based. Starting to think I need a function just to determine that. - HgB //Changed a bit so people can modify them in settings. And since they're colors, again it's possibly account-based. Starting to think I need a function just to determine that. - HgB
//element["columns"][LIST_AVATAR_NAME]["color"] = gColors.getColor( "MapAvatar" ).getValue(); //element["columns"][LIST_AVATAR_NAME]["color"] = gColors.getColor( "MapAvatar" ).getValue();
LLViewerRegion* parent_estate = LLWorld::getInstance()->getRegionFromPosGlobal(entry.getPosition()); LLViewerRegion* parent_estate = LLWorld::getInstance()->getRegionFromPosGlobal(entry->getPosition());
LLUUID estate_owner = LLUUID::null; LLUUID estate_owner = LLUUID::null;
if(parent_estate && parent_estate->isAlive()) if(parent_estate && parent_estate->isAlive())
{ {
@@ -755,6 +864,7 @@ void LLFloaterAvatarList::refreshAvatarList()
static LLCachedControl<LLColor4> sRadarTextChatRange(gColors, "RadarTextChatRange"); static LLCachedControl<LLColor4> sRadarTextChatRange(gColors, "RadarTextChatRange");
static LLCachedControl<LLColor4> sRadarTextShoutRange(gColors, "RadarTextShoutRange"); static LLCachedControl<LLColor4> sRadarTextShoutRange(gColors, "RadarTextShoutRange");
static LLCachedControl<LLColor4> sRadarTextDrawDist(gColors, "RadarTextDrawDist"); static LLCachedControl<LLColor4> sRadarTextDrawDist(gColors, "RadarTextDrawDist");
static LLCachedControl<LLColor4> sRadarTextYoung(gColors, "RadarTextYoung");
LLColor4 name_color = sDefaultListText; LLColor4 name_color = sDefaultListText;
//Lindens are always more Linden than your friend, make that take precedence //Lindens are always more Linden than your friend, make that take precedence
@@ -793,7 +903,7 @@ void LLFloaterAvatarList::refreshAvatarList()
if (UnknownAltitude) if (UnknownAltitude)
{ {
strcpy(temp, "?"); strcpy(temp, "?");
if (entry.isDrawn()) if (entry->isDrawn())
{ {
color = sRadarTextDrawDist; color = sRadarTextDrawDist;
} }
@@ -814,7 +924,7 @@ void LLFloaterAvatarList::refreshAvatarList()
} }
else else
{ {
if (entry.isDrawn()) if (entry->isDrawn())
{ {
color = sRadarTextDrawDist; color = sRadarTextDrawDist;
} }
@@ -872,28 +982,50 @@ void LLFloaterAvatarList::refreshAvatarList()
element["columns"][LIST_ACTIVITY]["type"] = "icon"; element["columns"][LIST_ACTIVITY]["type"] = "icon";
std::string activity_icon = ""; std::string activity_icon = "";
switch(entry.getActivity()) std::string activity_tip = "";
switch(entry->getActivity())
{ {
case LLAvatarListEntry::ACTIVITY_MOVING: case LLAvatarListEntry::ACTIVITY_MOVING:
activity_icon = "inv_item_animation.tga"; {
activity_icon = "inv_item_animation.tga";
activity_tip = getString("Moving");
}
break; break;
case LLAvatarListEntry::ACTIVITY_GESTURING: case LLAvatarListEntry::ACTIVITY_GESTURING:
activity_icon = "inv_item_gesture.tga"; {
activity_icon = "inv_item_gesture.tga";
activity_tip = getString("Playing a gesture");
}
break; break;
case LLAvatarListEntry::ACTIVITY_SOUND: case LLAvatarListEntry::ACTIVITY_SOUND:
activity_icon = "inv_item_sound.tga"; {
activity_icon = "inv_item_sound.tga";
activity_tip = getString("Playing a sound");
}
break; break;
case LLAvatarListEntry::ACTIVITY_REZZING: case LLAvatarListEntry::ACTIVITY_REZZING:
activity_icon = "ff_edit_theirs.tga"; {
activity_icon = "ff_edit_theirs.tga";
activity_tip = getString("Rezzing objects");
}
break; break;
case LLAvatarListEntry::ACTIVITY_PARTICLES: case LLAvatarListEntry::ACTIVITY_PARTICLES:
activity_icon = "particles_scan.tga"; {
activity_icon = "particles_scan.tga";
activity_tip = getString("Creating particles");
}
break; break;
case LLAvatarListEntry::ACTIVITY_NEW: case LLAvatarListEntry::ACTIVITY_NEW:
activity_icon = "avatar_new.tga"; {
activity_icon = "avatar_new.tga";
activity_tip = getString("Just arrived");
}
break; break;
case LLAvatarListEntry::ACTIVITY_TYPING: case LLAvatarListEntry::ACTIVITY_TYPING:
activity_icon = "avatar_typing.tga"; {
activity_icon = "avatar_typing.tga";
activity_tip = getString("Typing");
}
break; break;
default: default:
break; break;
@@ -901,6 +1033,40 @@ void LLFloaterAvatarList::refreshAvatarList()
element["columns"][LIST_ACTIVITY]["value"] = activity_icon;//icon_image_id; //"icn_active-speakers-dot-lvl0.tga"; element["columns"][LIST_ACTIVITY]["value"] = activity_icon;//icon_image_id; //"icn_active-speakers-dot-lvl0.tga";
//element["columns"][LIST_AVATAR_ACTIVITY]["color"] = icon_color.getValue(); //element["columns"][LIST_AVATAR_ACTIVITY]["color"] = icon_color.getValue();
element["columns"][LIST_ACTIVITY]["tool_tip"] = activity_tip;
element["columns"][LIST_AGE]["column"] = "age";
element["columns"][LIST_AGE]["type"] = "text";
color = sDefaultListText;
std::string age = boost::lexical_cast<std::string>(entry->mAge);
if (entry->mAge > -1)
{
static LLCachedControl<U32> sAvatarAgeAlertDays(gSavedSettings, "AvatarAgeAlertDays");
if ((U32)entry->mAge < sAvatarAgeAlertDays)
{
color = sRadarTextYoung;
if (!entry->mAgeAlert) //Only announce age once per entry.
{
entry->mAgeAlert = true;
chat_avatar_status(entry->getName().c_str(), av_id, ALERT_TYPE_AGE, true);
}
}
}
else
{
age = "?";
}
element["columns"][LIST_AGE]["value"] = age;
element["columns"][LIST_AGE]["color"] = color.getValue();
int dur = difftime(time(NULL), entry->getTime());
int hours = dur / 3600;
int mins = (dur % 3600) / 60;
int secs = (dur % 3600) % 60;
element["columns"][LIST_TIME]["column"] = "time";
element["columns"][LIST_TIME]["type"] = "text";
element["columns"][LIST_TIME]["value"] = llformat("%d:%02d:%02d", hours, mins, secs);
element["columns"][LIST_CLIENT]["column"] = "client"; element["columns"][LIST_CLIENT]["column"] = "client";
element["columns"][LIST_CLIENT]["type"] = "text"; element["columns"][LIST_CLIENT]["type"] = "text";
@@ -950,6 +1116,17 @@ void LLFloaterAvatarList::refreshAvatarList()
mDirtyAvatarSorting = true; mDirtyAvatarSorting = true;
if (mAvatars.empty())
setTitle(getString("Title"));
else if (mAvatars.size() == 1)
setTitle(getString("TitleOneAvatar"));
else
{
LLStringUtil::format_map_t args;
args["[COUNT]"] = boost::lexical_cast<std::string>(mAvatars.size());
setTitle(getString("TitleWithCount", args));
}
// llinfos << "radar refresh: done" << llendl; // llinfos << "radar refresh: done" << llendl;
} }
@@ -1056,7 +1233,7 @@ LLAvatarListEntry * LLFloaterAvatarList::getAvatarEntry(LLUUID avatar)
av_list_t::iterator iter = std::find_if(mAvatars.begin(),mAvatars.end(),LLAvatarListEntry::uuidMatch(avatar)); av_list_t::iterator iter = std::find_if(mAvatars.begin(),mAvatars.end(),LLAvatarListEntry::uuidMatch(avatar));
if(iter != mAvatars.end()) if(iter != mAvatars.end())
return &(*iter); return iter->get();
else else
return NULL; return NULL;
} }
@@ -1128,7 +1305,7 @@ void LLFloaterAvatarList::removeFocusFromAll()
{ {
BOOST_FOREACH(av_list_t::value_type& entry, mAvatars) BOOST_FOREACH(av_list_t::value_type& entry, mAvatars)
{ {
entry.setFocus(FALSE); entry->setFocus(FALSE);
} }
} }
@@ -1140,7 +1317,7 @@ void LLFloaterAvatarList::setFocusAvatar(const LLUUID& id)
if(!gAgentCamera.lookAtObject(id, false)) if(!gAgentCamera.lookAtObject(id, false))
return; return;
removeFocusFromAll(); removeFocusFromAll();
iter->setFocus(TRUE); (*iter)->setFocus(TRUE);
} }
} }
@@ -1148,22 +1325,22 @@ template<typename T>
void decrement_focus_target(T begin, T end, BOOL marked_only) void decrement_focus_target(T begin, T end, BOOL marked_only)
{ {
T iter = begin; T iter = begin;
while(iter != end && !iter->isFocused()) ++iter; while(iter != end && !(*iter)->isFocused()) ++iter;
if(iter == end) if(iter == end)
return; return;
T prev_iter = iter; T prev_iter = iter;
while(prev_iter != begin) while(prev_iter != begin)
{ {
LLAvatarListEntry& entry = *(--prev_iter); const LLAvatarListEntry& entry = *((--prev_iter)->get());
if(entry.isInList() && (entry.isMarked() || !marked_only) && gAgentCamera.lookAtObject(entry.getID(), false)) if(entry.isInList() && (entry.isMarked() || !marked_only) && gAgentCamera.lookAtObject(entry.getID(), false))
{ {
iter->setFocus(FALSE); (*iter)->setFocus(FALSE);
prev_iter->setFocus(TRUE); (*prev_iter)->setFocus(TRUE);
gAgentCamera.lookAtObject(prev_iter->getID(), false); gAgentCamera.lookAtObject((*prev_iter)->getID(), false);
return; return;
} }
} }
gAgentCamera.lookAtObject(iter->getID(), false); gAgentCamera.lookAtObject((*iter)->getID(), false);
} }
void LLFloaterAvatarList::focusOnPrev(BOOL marked_only) void LLFloaterAvatarList::focusOnPrev(BOOL marked_only)

View File

@@ -11,6 +11,7 @@
// //
// //
#include "llavatarname.h" #include "llavatarname.h"
#include "llavatarpropertiesprocessor.h"
#include "llfloater.h" #include "llfloater.h"
#include "llfloaterreporter.h" #include "llfloaterreporter.h"
#include "lluuid.h" #include "lluuid.h"
@@ -21,6 +22,8 @@
#include <map> #include <map>
#include <set> #include <set>
#include <boost/shared_ptr.hpp>
class LLFloaterAvatarList; class LLFloaterAvatarList;
/** /**
@@ -29,7 +32,8 @@ class LLFloaterAvatarList;
* Instances are kept in a map<LLAvatarListEntry>. We keep track of the * Instances are kept in a map<LLAvatarListEntry>. We keep track of the
* frame where the avatar was last seen. * frame where the avatar was last seen.
*/ */
class LLAvatarListEntry { class LLAvatarListEntry : public LLAvatarPropertiesObserver
{
public: public:
@@ -52,6 +56,10 @@ enum ACTIVITY_TYPE
* @param position Avatar's current position * @param position Avatar's current position
*/ */
LLAvatarListEntry(const LLUUID& id = LLUUID::null, const std::string &name = "", const LLVector3d &position = LLVector3d::zero); LLAvatarListEntry(const LLUUID& id = LLUUID::null, const std::string &name = "", const LLVector3d &position = LLVector3d::zero);
~LLAvatarListEntry();
// Get properties, such as age and other niceties displayed on profiles.
/*virtual*/ void processProperties(void* data, EAvatarProcessorType type);
/** /**
* Update world position. * Update world position.
@@ -78,6 +86,7 @@ enum ACTIVITY_TYPE
* @brief Returns the name of the avatar * @brief Returns the name of the avatar
*/ */
const std::string& getName() const { return mName; } const std::string& getName() const { return mName; }
const time_t& getTime() const { return mTime; }
/** /**
* @brief Returns the ID of the avatar * @brief Returns the ID of the avatar
@@ -123,7 +132,7 @@ enum ACTIVITY_TYPE
struct uuidMatch struct uuidMatch
{ {
uuidMatch(const LLUUID& id) : mID(id) {} uuidMatch(const LLUUID& id) : mID(id) {}
bool operator()(const LLAvatarListEntry& l) { return l.getID() == mID; } bool operator()(const boost::shared_ptr<LLAvatarListEntry>& l) { return l->getID() == mID; }
LLUUID mID; LLUUID mID;
}; };
@@ -132,11 +141,14 @@ private:
LLUUID mID; LLUUID mID;
std::string mName; std::string mName;
time_t mTime;
LLVector3d mPosition; LLVector3d mPosition;
LLVector3d mDrawPosition; LLVector3d mDrawPosition;
bool mMarked; bool mMarked;
bool mFocused; bool mFocused;
bool mIsInList; bool mIsInList;
bool mAgeAlert;
int mAge;
/** /**
* @brief Timer to keep track of whether avatars are still there * @brief Timer to keep track of whether avatars are still there
@@ -202,6 +214,9 @@ public:
static void showInstance(); static void showInstance();
// Decides which user-chosen columns to show and hide.
void assessColumns();
/** /**
* @brief Updates the internal avatar list with the currently present avatars. * @brief Updates the internal avatar list with the currently present avatars.
*/ */
@@ -230,7 +245,8 @@ public:
static void sound_trigger_hook(LLMessageSystem* msg,void **); static void sound_trigger_hook(LLMessageSystem* msg,void **);
void sendKeys(); void sendKeys();
typedef std::vector<LLAvatarListEntry> av_list_t; typedef boost::shared_ptr<LLAvatarListEntry> LLAvatarListEntryPtr;
typedef std::vector< LLAvatarListEntryPtr > av_list_t;
private: private:
// when a line editor loses keyboard focus, it is committed. // when a line editor loses keyboard focus, it is committed.
@@ -245,6 +261,8 @@ private:
LIST_POSITION, LIST_POSITION,
LIST_ALTITUDE, LIST_ALTITUDE,
LIST_ACTIVITY, LIST_ACTIVITY,
LIST_AGE,
LIST_TIME,
LIST_CLIENT, LIST_CLIENT,
}; };

View File

@@ -317,8 +317,9 @@ void LLFloaterChat::addChatHistory(const LLChat& chat, bool log_to_file)
} }
else else
{ {
static LLCachedControl<bool> color_muted_chat("ColorMutedChat");
// desaturate muted chat // desaturate muted chat
LLColor4 muted_color = lerp(color, LLColor4::grey, 0.5f); LLColor4 muted_color = lerp(color, color_muted_chat ? gSavedSettings.getColor4("AscentMutedColor") : LLColor4::grey, 0.5f);
add_timestamped_line(history_editor_with_mute, chat, muted_color); add_timestamped_line(history_editor_with_mute, chat, muted_color);
} }
@@ -493,7 +494,7 @@ void LLFloaterChat::triggerAlerts(const std::string& text)
{ {
// Cannot instantiate LLTextParser before logging in. // Cannot instantiate LLTextParser before logging in.
if (gDirUtilp->getLindenUserDir(true).empty()) if (gDirUtilp->getLindenUserDir(true).empty())
return; return;
LLTextParser* parser = LLTextParser::getInstance(); LLTextParser* parser = LLTextParser::getInstance();
// bool spoken=FALSE; // bool spoken=FALSE;
@@ -539,7 +540,11 @@ LLColor4 get_text_color(const LLChat& chat)
if(chat.mMuted) if(chat.mMuted)
{ {
text_color.setVec(0.8f, 0.8f, 0.8f, 1.f); static LLCachedControl<bool> color_muted_chat("ColorMutedChat");
if (color_muted_chat)
text_color = gSavedSettings.getColor4("AscentMutedColor");
else
text_color.setVec(0.8f, 0.8f, 0.8f, 1.f);
} }
else else
{ {
@@ -549,7 +554,7 @@ LLColor4 get_text_color(const LLChat& chat)
text_color = gSavedSettings.getColor4("SystemChatColor"); text_color = gSavedSettings.getColor4("SystemChatColor");
break; break;
case CHAT_SOURCE_AGENT: case CHAT_SOURCE_AGENT:
if (chat.mFromID.isNull()) if (chat.mFromID.isNull())
{ {
text_color = gSavedSettings.getColor4("SystemChatColor"); text_color = gSavedSettings.getColor4("SystemChatColor");
} }
@@ -561,7 +566,34 @@ LLColor4 get_text_color(const LLChat& chat)
} }
else else
{ {
text_color = gSavedSettings.getColor4("AgentChatColor"); static LLCachedControl<bool> color_linden_chat("ColorLindenChat");
if (color_linden_chat && LLMuteList::getInstance()->isLinden(chat.mFromName))
{
text_color = gSavedSettings.getColor4("AscentLindenColor");
}
else if (!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES))
{
static LLCachedControl<bool> color_friend_chat("ColorFriendChat");
static LLCachedControl<bool> color_eo_chat("ColorEstateOwnerChat");
if (color_friend_chat && LLAvatarTracker::instance().isBuddy(chat.mFromID))
{
text_color = gSavedSettings.getColor4("AscentFriendColor");
}
else if (color_eo_chat)
{
LLViewerRegion* parent_estate = gAgent.getRegion();
if (parent_estate && parent_estate->isAlive() && chat.mFromID == parent_estate->getOwner())
text_color = gSavedSettings.getColor4("AscentEstateOwnerColor");
else
text_color = gSavedSettings.getColor4("AgentChatColor");
}
else
text_color = gSavedSettings.getColor4("AgentChatColor");
}
else
{
text_color = gSavedSettings.getColor4("AgentChatColor");
}
} }
} }
break; break;

View File

@@ -32,7 +32,6 @@
#include "llviewerprecompiledheaders.h" #include "llviewerprecompiledheaders.h"
#include "llappearancemgr.h"
#include "llimagejpeg.h" #include "llimagejpeg.h"
#include "llfloatercustomize.h" #include "llfloatercustomize.h"
#include "llfontgl.h" #include "llfontgl.h"
@@ -64,7 +63,6 @@
#include "llviewercamera.h" #include "llviewercamera.h"
#include "llappearance.h" #include "llappearance.h"
#include "imageids.h" #include "imageids.h"
#include "llmodaldialog.h"
#include "llassetstorage.h" #include "llassetstorage.h"
#include "lltexturectrl.h" #include "lltexturectrl.h"
#include "lltextureentry.h" #include "lltextureentry.h"
@@ -79,9 +77,9 @@
#include "lluictrlfactory.h" #include "lluictrlfactory.h"
#include "llnotificationsutil.h" #include "llnotificationsutil.h"
#include "llpaneleditwearable.h" #include "llpaneleditwearable.h"
#include "llmakeoutfitdialog.h"
#include "statemachine/aifilepicker.h" #include "statemachine/aifilepicker.h"
#include "hippogridmanager.h"
using namespace LLAvatarAppearanceDefines; using namespace LLAvatarAppearanceDefines;
@@ -119,220 +117,6 @@ BOOL edit_wearable_for_teens(LLWearableType::EType type)
} }
} }
class LLMakeOutfitDialog : public LLModalDialog
{
private:
std::string mFolderName;
void (*mCommitCallback)(LLMakeOutfitDialog*,void*);
void* mCallbackUserData;
std::vector<std::pair<std::string,S32> > mCheckBoxList;
public:
LLMakeOutfitDialog( void(*commit_cb)(LLMakeOutfitDialog*,void*), void* userdata )
: LLModalDialog(LLStringUtil::null,515, 510, TRUE ),
mCommitCallback( commit_cb ),
mCallbackUserData( userdata )
{
LLUICtrlFactory::getInstance()->buildFloater(this, "floater_new_outfit_dialog.xml");
// Build list of check boxes
for( S32 i = 0; i < LLWearableType::WT_COUNT; i++ )
{
std::string name = std::string("checkbox_") + LLWearableType::getTypeLabel( (LLWearableType::EType)i );
mCheckBoxList.push_back(std::make_pair(name,i));
// Hide teen items
if (gAgent.isTeen() &&
!edit_wearable_for_teens((LLWearableType::EType)i))
{
// hide wearable checkboxes that don't apply to this account
std::string name = std::string("checkbox_") + LLWearableType::getTypeLabel( (LLWearableType::EType)i );
childSetVisible(name, FALSE);
}
}
// NOTE: .xml needs to be updated if attachments are added or their names are changed!
LLVOAvatar* avatar = gAgentAvatarp;
if( avatar )
{
for (LLVOAvatar::attachment_map_t::iterator iter = avatar->mAttachmentPoints.begin();
iter != avatar->mAttachmentPoints.end(); )
{
LLVOAvatar::attachment_map_t::iterator curiter = iter++;
LLViewerJointAttachment* attachment = curiter->second;
S32 attachment_pt = curiter->first;
BOOL object_attached = ( attachment->getNumObjects() > 0 );
std::string name = std::string("checkbox_") + attachment->getName();
mCheckBoxList.push_back(std::make_pair(name,attachment_pt));
childSetEnabled(name, object_attached);
}
}
if(!gHippoGridManager->getConnectedGrid()->supportsInvLinks()) {
childSetEnabled("checkbox_use_links", FALSE);
childSetValue("checkbox_use_links", FALSE);
childSetEnabled("checkbox_use_outfits", FALSE);
childSetValue("checkbox_use_outfits", FALSE);
}
childSetAction("Save", onSave, this );
childSetAction("Cancel", onCancel, this );
childSetAction("Check All", onCheckAll, this );
childSetAction("Uncheck All", onUncheckAll, this );
LLCheckBoxCtrl* pOutfitFoldersCtrl = getChild<LLCheckBoxCtrl>("checkbox_use_outfits");
pOutfitFoldersCtrl->setCommitCallback(&LLMakeOutfitDialog::onOutfitFoldersToggle);
pOutfitFoldersCtrl->setCallbackUserData(this);
}
bool getUseOutfits()
{
return childGetValue("checkbox_use_outfits").asBoolean();
}
bool getUseLinks()
{
return childGetValue("checkbox_use_links").asBoolean();
}
/*bool getRenameClothing()
{
return childGetValue("rename").asBoolean();
}*/
virtual void draw()
{
BOOL one_or_more_items_selected = FALSE;
for( S32 i = 0; i < (S32)mCheckBoxList.size(); i++ )
{
if( childGetValue(mCheckBoxList[i].first).asBoolean() )
{
one_or_more_items_selected = TRUE;
break;
}
}
childSetEnabled("Save", one_or_more_items_selected );
LLModalDialog::draw();
}
const std::string& getFolderName() { return mFolderName; }
void setWearableToInclude( S32 wearable, S32 enabled, S32 selected )
{
LLWearableType::EType wtType = (LLWearableType::EType)wearable;
if ( ( (0 <= wtType) && (wtType < LLWearableType::WT_COUNT) ) &&
( (LLAssetType::AT_BODYPART != LLWearableType::getAssetType(wtType)) || (!getUseOutfits()) ) )
{
std::string name = std::string("checkbox_") + LLWearableType::getTypeLabel(wtType);
childSetEnabled(name, enabled);
childSetValue(name, selected);
}
}
void getIncludedItems( LLInventoryModel::item_array_t& item_list )
{
LLInventoryModel::cat_array_t *cats;
LLInventoryModel::item_array_t *items;
gInventory.getDirectDescendentsOf(LLAppearanceMgr::instance().getCOF(), cats, items);
for (LLInventoryModel::item_array_t::const_iterator iter = items->begin();
iter != items->end();
++iter)
{
LLViewerInventoryItem* item = (*iter);
if(!item)
continue;
if(item->isWearableType())
{
LLWearableType::EType type = item->getWearableType();
if (type < LLWearableType::WT_COUNT && childGetValue(mCheckBoxList[type].first).asBoolean())
{
item_list.push_back(item);
}
}
else
{
LLViewerJointAttachment* attachment = gAgentAvatarp->getWornAttachmentPoint(item->getLinkedUUID());
if(attachment && childGetValue(std::string("checkbox_")+attachment->getName()).asBoolean())
{
item_list.push_back(item);
}
}
}
}
static void onSave( void* userdata )
{
LLMakeOutfitDialog* self = (LLMakeOutfitDialog*) userdata;
self->mFolderName = self->childGetValue("name ed").asString();
LLStringUtil::trim(self->mFolderName);
if( !self->mFolderName.empty() )
{
if( self->mCommitCallback )
{
self->mCommitCallback( self, self->mCallbackUserData );
}
self->close(); // destroys this object
}
}
static void onCheckAll( void* userdata )
{
LLMakeOutfitDialog* self = (LLMakeOutfitDialog*) userdata;
for( S32 i = 0; i < (S32)(self->mCheckBoxList.size()); i++)
{
std::string name = self->mCheckBoxList[i].first;
if(self->childIsEnabled(name))self->childSetValue(name,TRUE);
}
}
static void onUncheckAll( void* userdata )
{
LLMakeOutfitDialog* self = (LLMakeOutfitDialog*) userdata;
for( S32 i = 0; i < (S32)(self->mCheckBoxList.size()); i++)
{
std::string name = self->mCheckBoxList[i].first;
if(self->childIsEnabled(name))self->childSetValue(name,FALSE);
}
}
static void onCancel( void* userdata )
{
LLMakeOutfitDialog* self = (LLMakeOutfitDialog*) userdata;
self->close(); // destroys this object
}
BOOL postBuild()
{
refresh();
return TRUE;
}
void refresh()
{
BOOL fUseOutfits = getUseOutfits();
for (S32 idxType = 0; idxType < LLWearableType::WT_COUNT; idxType++ )
{
LLWearableType::EType wtType = (LLWearableType::EType)idxType;
if (LLAssetType::AT_BODYPART != LLWearableType::getAssetType(wtType))
continue;
LLCheckBoxCtrl* pCheckCtrl = getChild<LLCheckBoxCtrl>(std::string("checkbox_") + LLWearableType::getTypeLabel(wtType));
if (!pCheckCtrl)
continue;
pCheckCtrl->setEnabled(!fUseOutfits);
if (fUseOutfits)
pCheckCtrl->setValue(TRUE);
}
childSetEnabled("checkbox_use_links", !fUseOutfits);
}
static void onOutfitFoldersToggle(LLUICtrl*, void* pParam)
{
LLMakeOutfitDialog* pSelf = (LLMakeOutfitDialog*)pParam;
if (pSelf)
pSelf->refresh();
}
};
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
void updateAvatarHeightDisplay() void updateAvatarHeightDisplay()
@@ -393,13 +177,13 @@ LLFloaterCustomize::LLFloaterCustomize()
BOOL LLFloaterCustomize::postBuild() BOOL LLFloaterCustomize::postBuild()
{ {
childSetAction("Make Outfit", LLFloaterCustomize::onBtnMakeOutfit, (void*)this); getChild<LLUICtrl>("Make Outfit")->setCommitCallback(boost::bind(&LLFloaterCustomize::onBtnMakeOutfit, this));
childSetAction("Ok", LLFloaterCustomize::onBtnOk, (void*)this); getChild<LLUICtrl>("Ok")->setCommitCallback(boost::bind(&LLFloaterCustomize::onBtnOk, this));
childSetAction("Cancel", LLFloater::onClickClose, (void*)this); getChild<LLUICtrl>("Cancel")->setCommitCallback(boost::bind(&LLFloater::onClickClose, this));
// reX // reX
childSetAction("Import", LLFloaterCustomize::onBtnImport, (void*)this); getChild<LLUICtrl>("Import")->setCommitCallback(boost::bind(&LLFloaterCustomize::onBtnImport, this));
childSetAction("Export", LLFloaterCustomize::onBtnExport, (void*)this); getChild<LLUICtrl>("Export")->setCommitCallback(boost::bind(&LLFloaterCustomize::onBtnExport, this));
// Wearable panels // Wearable panels
initWearablePanels(); initWearablePanels();
@@ -459,7 +243,7 @@ void LLFloaterCustomize::setCurrentWearableType( LLWearableType::EType type )
} }
// reX: new function // reX: new function
void LLFloaterCustomize::onBtnImport( void* userdata ) void LLFloaterCustomize::onBtnImport()
{ {
AIFilePicker* filepicker = AIFilePicker::create(); AIFilePicker* filepicker = AIFilePicker::create();
filepicker->open(FFLOAD_XML); filepicker->open(FFLOAD_XML);
@@ -519,7 +303,7 @@ void LLFloaterCustomize::onBtnImport_continued(AIFilePicker* filepicker)
} }
// reX: new function // reX: new function
void LLFloaterCustomize::onBtnExport( void* userdata ) void LLFloaterCustomize::onBtnExport()
{ {
AIFilePicker* filepicker = AIFilePicker::create(); AIFilePicker* filepicker = AIFilePicker::create();
filepicker->open("", FFSAVE_XML); filepicker->open("", FFSAVE_XML);
@@ -592,10 +376,8 @@ void LLFloaterCustomize::onBtnExport_continued(AIFilePicker* filepicker)
fclose(fp); fclose(fp);
} }
// static void LLFloaterCustomize::onBtnOk()
void LLFloaterCustomize::onBtnOk( void* userdata )
{ {
LLFloaterCustomize* floater = (LLFloaterCustomize*) userdata;
gAgentWearables.saveAllWearables(); gAgentWearables.saveAllWearables();
if ( gAgentAvatarp ) if ( gAgentAvatarp )
@@ -607,55 +389,13 @@ void LLFloaterCustomize::onBtnOk( void* userdata )
gAgent.sendAgentSetAppearance(); gAgent.sendAgentSetAppearance();
} }
gFloaterView->sendChildToBack(floater); gFloaterView->sendChildToBack(this);
handle_reset_view(); // Calls askToSaveIfDirty handle_reset_view(); // Calls askToSaveIfDirty
} }
// static void LLFloaterCustomize::onBtnMakeOutfit()
void LLFloaterCustomize::onBtnMakeOutfit( void* userdata )
{ {
LLVOAvatar* avatar = gAgentAvatarp; new LLMakeOutfitDialog(true); // LLMakeOutfitDialog deletes itself.
if(avatar)
{
LLMakeOutfitDialog* dialog = new LLMakeOutfitDialog( onMakeOutfitCommit, NULL );
// LLMakeOutfitDialog deletes itself.
for( S32 i = 0; i < LLWearableType::WT_COUNT; i++ )
{
BOOL enabled = (gAgentWearables.getWearableCount( (LLWearableType::EType) i )); // TODO: MULTI-WEARABLE
BOOL selected = (enabled && (LLWearableType::WT_SHIRT <= i) && (i < LLWearableType::WT_COUNT)); // only select clothing by default
if (gAgent.isTeen()
&& !edit_wearable_for_teens((LLWearableType::EType)i))
{
dialog->setWearableToInclude( i, FALSE, FALSE );
}
else
{
dialog->setWearableToInclude( i, enabled, selected );
}
}
dialog->startModal();
}
}
// static
void LLFloaterCustomize::onMakeOutfitCommit( LLMakeOutfitDialog* dialog, void* userdata )
{
LLVOAvatar* avatar = gAgentAvatarp;
if(avatar)
{
LLDynamicArray<S32> wearables_to_include;
LLDynamicArray<S32> attachments_to_include; // attachment points
LLInventoryModel::item_array_t item_list;
dialog->getIncludedItems(item_list);
// MULTI-WEARABLES TODO
if(dialog->getUseOutfits())
LLAppearanceMgr::instance().makeNewOutfitLinks( dialog->getFolderName(), item_list);
else
LLAppearanceMgr::instance().makeNewOutfitLegacy( dialog->getFolderName(), item_list, dialog->getUseLinks());
}
} }
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////

View File

@@ -98,12 +98,12 @@ public:
static LLWearableType::EType getCurrentWearableType() { return sCurrentWearableType; } static LLWearableType::EType getCurrentWearableType() { return sCurrentWearableType; }
// Callbacks // Callbacks
static void onBtnOk( void* userdata ); void onBtnOk();
static void onBtnMakeOutfit( void* userdata ); void onBtnMakeOutfit();
static void onMakeOutfitCommit( LLMakeOutfitDialog* dialog, void* userdata ); void onMakeOutfitCommit();
static void onBtnImport( void* userdata ); void onBtnImport();
static void onBtnImport_continued(AIFilePicker* filepicker); static void onBtnImport_continued(AIFilePicker* filepicker);
static void onBtnExport( void* userdata ); void onBtnExport();
static void onBtnExport_continued(AIFilePicker* filepicker); static void onBtnExport_continued(AIFilePicker* filepicker);
static void onTabChanged( const LLSD& param ); static void onTabChanged( const LLSD& param );

View File

@@ -0,0 +1,177 @@
/**
* @file llfloaterfeed.cpp
* @brief Feed send floater, allows setting caption and whether or to add location, etc.
*
* $LicenseInfo:firstyear=2012&license=viewergpl$
*
* Copyright (c) 2004-2009, Linden Research, Inc.
* Copyright (c) 2012, Aleric Ingelwood.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#include "llviewerprecompiledheaders.h"
#include "llfloaterfeed.h"
#include "llfloatersnapshot.h"
#include "llimagepng.h"
#include "llnotificationsutil.h"
#include "lluictrlfactory.h"
#include "llviewertexture.h"
#include "llviewerwindow.h"
#include "llwebprofile.h"
#include <boost/bind.hpp>
///----------------------------------------------------------------------------
/// Class LLFloaterFeed
///----------------------------------------------------------------------------
LLFloaterFeed::LLFloaterFeed(LLImagePNG* png, LLViewerTexture* img, LLVector2 const& img_scale, int index) :
LLFloater(std::string("Feed Floater")),
mPNGImage(png), mViewerImage(img), mImageScale(img_scale), mSnapshotIndex(index)
{
}
// Destroys the object
LLFloaterFeed::~LLFloaterFeed()
{
mPNGImage = NULL;
}
BOOL LLFloaterFeed::postBuild()
{
getChild<LLUICtrl>("cancel_btn")->setCommitCallback(boost::bind(&LLFloaterFeed::onClickCancel, this));
getChild<LLUICtrl>("post_btn")->setCommitCallback(boost::bind(&LLFloaterFeed::onClickPost, this));
return true;
}
// static
LLFloaterFeed* LLFloaterFeed::showFromSnapshot(LLImagePNG* png, LLViewerTexture* img, LLVector2 const& image_scale, int index)
{
// Take the images from the caller
// It's now our job to clean them up
LLFloaterFeed* instance = new LLFloaterFeed(png, img, image_scale, index);
LLUICtrlFactory::getInstance()->buildFloater(instance, "floater_snapshot_feed.xml");
S32 left, top;
gFloaterView->getNewFloaterPosition(&left, &top);
instance->setOrigin(left, top - instance->getRect().getHeight());
instance->open();
return instance;
}
void LLFloaterFeed::draw(void)
{
LLGLSUIDefault gls_ui;
LLFloater::draw();
if (!isMinimized() && mViewerImage.notNull() && mPNGImage.notNull())
{
LLRect rect(getRect());
// First set the max extents of our preview.
rect.translate(-rect.mLeft, -rect.mBottom);
rect.mLeft += 10;
rect.mRight -= 10;
rect.mTop -= 25;
rect.mBottom = rect.mTop - 150;
// Then fix the aspect ratio.
F32 ratio = (F32)mPNGImage->getWidth() / (F32)mPNGImage->getHeight();
if ((F32)rect.getWidth() / (F32)rect.getHeight() >= ratio)
{
rect.mRight = (S32)((F32)rect.mLeft + ((F32)rect.getHeight() * ratio));
}
else
{
rect.mBottom = (S32)((F32)rect.mTop - ((F32)rect.getWidth() / ratio));
}
{
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
gl_rect_2d(rect, LLColor4(0.f, 0.f, 0.f, 1.f));
rect.stretch(-1);
}
{
gGL.matrixMode(LLRender::MM_TEXTURE);
gGL.pushMatrix();
{
gGL.scalef(mImageScale.mV[VX], mImageScale.mV[VY], 1.f);
gGL.matrixMode(LLRender::MM_MODELVIEW);
gl_draw_scaled_image(rect.mLeft, rect.mBottom, rect.getWidth(), rect.getHeight(), mViewerImage, LLColor4::white);
}
gGL.matrixMode(LLRender::MM_TEXTURE);
gGL.popMatrix();
gGL.matrixMode(LLRender::MM_MODELVIEW);
}
}
}
void LLFloaterFeed::onClickCancel()
{
// Return false on cancel, to enable the upload button again.
LLFloaterSnapshot::saveFeedDone(false, mSnapshotIndex);
close(false);
}
void LLFloaterFeed::onClose(bool app_quitting)
{
LLFloaterSnapshot::saveFeedDone(false, mSnapshotIndex);
destroy();
}
void LLFloaterFeed::onClickPost()
{
if (mPNGImage.notNull())
{
static LLCachedControl<bool> add_location("SnapshotFeedAddLocation");
const std::string caption = childGetValue("caption").asString();
LLWebProfile::setImageUploadResultCallback(boost::bind(&LLFloaterSnapshot::saveFeedDone, _1, mPNGImage));
LLWebProfile::uploadImage(mPNGImage, caption, add_location);
// give user feedback of the event
gViewerWindow->playSnapshotAnimAndSound();
// don't destroy the window until the upload is done
// this way we keep the information in the form
setVisible(FALSE);
// remove any dependency on snapshot floater
// so we outlive it during the upload.
LLFloater* dependee = getDependee();
if (dependee)
{
dependee->removeDependentFloater(this);
}
}
else
{
LLNotificationsUtil::add("ErrorProcessingSnapshot");
}
}

View File

@@ -0,0 +1,64 @@
/**
* @file llfloaterfeed.h
* @brief Feed send floater, allows setting caption and whether or not to include location.
*
* Copyright (c) 2004-2009, Linden Research, Inc.
* Copyright (c) 2012, Aleric Inglewood.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#ifndef LL_LLFLOATERFEED_H
#define LL_LLFLOATERFEED_H
#include "llfloater.h" // LLFloater
#include "v2math.h" // LLVector2
#include "llpointer.h" // LLPointer
class LLImagePNG;
class LLViewerTexture;
class LLFloaterFeed : public LLFloater
{
public:
LLFloaterFeed(LLImagePNG* png, LLViewerTexture* img, LLVector2 const& img_scale, int index);
virtual ~LLFloaterFeed();
/*virtual*/ void onClose(bool app_quitting);
/*virtual*/ BOOL postBuild();
/*virtual*/ void draw();
static LLFloaterFeed* showFromSnapshot(LLImagePNG* png, LLViewerTexture* img, LLVector2 const& img_scale, int index);
void onClickCancel();
void onClickPost();
protected:
LLPointer<LLImagePNG> mPNGImage;
LLPointer<LLViewerTexture> mViewerImage;
LLVector2 const mImageScale;
int mSnapshotIndex;
};
#endif // LL_LLFLOATERFEED_H

View File

@@ -855,6 +855,8 @@ void LLPanelFriends::onClickIM(void* user_data)
const uuid_vec_t ids = panelp->mFriendsList->getSelectedIDs(); const uuid_vec_t ids = panelp->mFriendsList->getSelectedIDs();
if(!ids.empty()) if(!ids.empty())
{ {
static LLCachedControl<bool> tear_off("OtherChatsTornOff");
if(!tear_off) gIMMgr->setFloaterOpen(TRUE);
if(ids.size() == 1) if(ids.size() == 1)
{ {
LLUUID agent_id = ids[0]; LLUUID agent_id = ids[0];
@@ -862,13 +864,11 @@ void LLPanelFriends::onClickIM(void* user_data)
std::string fullname; std::string fullname;
if(info && gCacheName->getFullName(agent_id, fullname)) if(info && gCacheName->getFullName(agent_id, fullname))
{ {
gIMMgr->setFloaterOpen(TRUE);
gIMMgr->addSession(fullname, IM_NOTHING_SPECIAL, agent_id); gIMMgr->addSession(fullname, IM_NOTHING_SPECIAL, agent_id);
} }
} }
else else
{ {
gIMMgr->setFloaterOpen(TRUE);
gIMMgr->addSession("Friends Conference", IM_SESSION_CONFERENCE_START, ids[0], ids); gIMMgr->addSession("Friends Conference", IM_SESSION_CONFERENCE_START, ids[0], ids);
} }
make_ui_sound("UISndStartIM"); make_ui_sound("UISndStartIM");

View File

@@ -386,7 +386,9 @@ void LLPanelGroups::startIM()
LLGroupData group_data; LLGroupData group_data;
if (gAgent.getGroupData(group_id, group_data)) if (gAgent.getGroupData(group_id, group_data))
{ {
gIMMgr->setFloaterOpen(TRUE); static LLCachedControl<bool> tear_off("OtherChatsTornOff");
if (!tear_off)
gIMMgr->setFloaterOpen(TRUE);
gIMMgr->addSession( gIMMgr->addSession(
group_data.mName, group_data.mName,
IM_SESSION_GROUP_START, IM_SESSION_GROUP_START,

View File

@@ -67,6 +67,7 @@
#include "llassetuploadresponders.h" #include "llassetuploadresponders.h"
#include "hippogridmanager.h" #include "hippogridmanager.h"
#include "llfloatersnapshot.h"
#if LL_MSVC #if LL_MSVC
#pragma warning( disable : 4265 ) // "class has virtual functions, but destructor is not virtual" #pragma warning( disable : 4265 ) // "class has virtual functions, but destructor is not virtual"
@@ -84,13 +85,14 @@ LLFloaterPostcard::instance_list_t LLFloaterPostcard::sInstances;
/// Class LLFloaterPostcard /// Class LLFloaterPostcard
///---------------------------------------------------------------------------- ///----------------------------------------------------------------------------
LLFloaterPostcard::LLFloaterPostcard(LLImageJPEG* jpeg, LLViewerTexture *img, const LLVector2& img_scale, const LLVector3d& pos_taken_global) LLFloaterPostcard::LLFloaterPostcard(LLImageJPEG* jpeg, LLViewerTexture *img, const LLVector2& img_scale, const LLVector3d& pos_taken_global, int index)
: LLFloater(std::string("Postcard Floater")), : LLFloater(std::string("Postcard Floater")),
mJPEGImage(jpeg), mJPEGImage(jpeg),
mViewerImage(img), mViewerImage(img),
mImageScale(img_scale), mImageScale(img_scale),
mPosTakenGlobal(pos_taken_global), mPosTakenGlobal(pos_taken_global),
mHasFirstMsgFocus(false) mHasFirstMsgFocus(false),
mSnapshotIndex(index)
{ {
init(); init();
} }
@@ -146,11 +148,11 @@ BOOL LLFloaterPostcard::postBuild()
// static // static
LLFloaterPostcard* LLFloaterPostcard::showFromSnapshot(LLImageJPEG *jpeg, LLViewerTexture *img, const LLVector2 &image_scale, const LLVector3d& pos_taken_global) LLFloaterPostcard* LLFloaterPostcard::showFromSnapshot(LLImageJPEG *jpeg, LLViewerTexture *img, const LLVector2 &image_scale, const LLVector3d& pos_taken_global, int index)
{ {
// Take the images from the caller // Take the images from the caller
// It's now our job to clean them up // It's now our job to clean them up
LLFloaterPostcard *instance = new LLFloaterPostcard(jpeg, img, image_scale, pos_taken_global); LLFloaterPostcard *instance = new LLFloaterPostcard(jpeg, img, image_scale, pos_taken_global, index);
LLUICtrlFactory::getInstance()->buildFloater(instance, "floater_postcard.xml"); LLUICtrlFactory::getInstance()->buildFloater(instance, "floater_postcard.xml");
@@ -221,25 +223,47 @@ void LLFloaterPostcard::onClickCancel(void* data)
if (data) if (data)
{ {
LLFloaterPostcard *self = (LLFloaterPostcard *)data; LLFloaterPostcard *self = (LLFloaterPostcard *)data;
LLFloaterSnapshot::savePostcardDone(false, self->mSnapshotIndex);
self->close(false); self->close(false);
} }
} }
void LLFloaterPostcard::onClose(bool app_quitting)
{
LLFloaterSnapshot::savePostcardDone(false, mSnapshotIndex);
destroy();
}
class LLSendPostcardResponder : public LLAssetUploadResponder class LLSendPostcardResponder : public LLAssetUploadResponder
{ {
private:
int mSnapshotIndex;
public: public:
LLSendPostcardResponder(const LLSD &post_data, LLSendPostcardResponder(const LLSD &post_data,
const LLUUID& vfile_id, const LLUUID& vfile_id,
LLAssetType::EType asset_type): LLAssetType::EType asset_type,
LLAssetUploadResponder(post_data, vfile_id, asset_type) int index) :
LLAssetUploadResponder(post_data, vfile_id, asset_type),
mSnapshotIndex(index)
{ {
} }
// *TODO define custom uploadFailed here so it's not such a generic message // *TODO define custom uploadFailed here so it's not such a generic message
void uploadComplete(const LLSD& content) /*virtual*/ void uploadComplete(const LLSD& content)
{ {
// we don't care about what the server returns from this post, just clean up the UI // we don't care about what the server returns from this post, just clean up the UI
LLUploadDialog::modalUploadFinished(); LLUploadDialog::modalUploadFinished();
LLFloaterSnapshot::savePostcardDone(true, mSnapshotIndex);
}
/*virtual*/ void uploadFailure(const LLSD& content)
{
LLAssetUploadResponder::uploadFailure(content);
LLFloaterSnapshot::savePostcardDone(false, mSnapshotIndex);
}
/*virtual*/ void error(U32 statusNum, const std::string& reason)
{
LLAssetUploadResponder::error(statusNum, reason);
LLFloaterSnapshot::savePostcardDone(false, mSnapshotIndex);
} }
}; };
@@ -292,6 +316,8 @@ void LLFloaterPostcard::uploadCallback(const LLUUID& asset_id, void *user_data,
LLUploadDialog::modalUploadFinished(); LLUploadDialog::modalUploadFinished();
LLFloaterSnapshot::savePostcardDone(!result, self->mSnapshotIndex);
if (result) if (result)
{ {
LLSD args; LLSD args;
@@ -396,7 +422,7 @@ void LLFloaterPostcard::sendPostcard()
body["name"] = childGetValue("name_form").asString(); body["name"] = childGetValue("name_form").asString();
body["subject"] = childGetValue("subject_form").asString(); body["subject"] = childGetValue("subject_form").asString();
body["msg"] = childGetValue("msg_form").asString(); body["msg"] = childGetValue("msg_form").asString();
LLHTTPClient::post(url, body, new LLSendPostcardResponder(body, mAssetID, LLAssetType::AT_IMAGE_JPEG)); LLHTTPClient::post(url, body, new LLSendPostcardResponder(body, mAssetID, LLAssetType::AT_IMAGE_JPEG, mSnapshotIndex));
} }
else else
{ {

View File

@@ -50,14 +50,15 @@ class LLFloaterPostcard
: public LLFloater : public LLFloater
{ {
public: public:
LLFloaterPostcard(LLImageJPEG* jpeg, LLViewerTexture *img, const LLVector2& img_scale, const LLVector3d& pos_taken_global); LLFloaterPostcard(LLImageJPEG* jpeg, LLViewerTexture *img, const LLVector2& img_scale, const LLVector3d& pos_taken_global, int index);
virtual ~LLFloaterPostcard(); /*virtual*/ ~LLFloaterPostcard();
virtual void init(); /*virtual*/ void init();
virtual BOOL postBuild(); /*virtual*/ BOOL postBuild();
virtual void draw(); /*virtual*/ void draw();
/*virtual*/ void onClose(bool app_quitting);
static LLFloaterPostcard* showFromSnapshot(LLImageJPEG *jpeg, LLViewerTexture *img, const LLVector2& img_scale, const LLVector3d& pos_taken_global); static LLFloaterPostcard* showFromSnapshot(LLImageJPEG *jpeg, LLViewerTexture *img, const LLVector2& img_scale, const LLVector3d& pos_taken_global, int index);
static void onClickCancel(void* data); static void onClickCancel(void* data);
static void onClickSend(void* data); static void onClickSend(void* data);
@@ -82,6 +83,7 @@ protected:
LLVector2 mImageScale; LLVector2 mImageScale;
LLVector3d mPosTakenGlobal; LLVector3d mPosTakenGlobal;
bool mHasFirstMsgFocus; bool mHasFirstMsgFocus;
int mSnapshotIndex;
typedef std::set<LLFloaterPostcard*> instance_list_t; typedef std::set<LLFloaterPostcard*> instance_list_t;
static instance_list_t sInstances; static instance_list_t sInstances;

View File

@@ -537,11 +537,11 @@ void LLFloaterProperties::refreshFromItem(LLInventoryItem* item)
if (!is_link && is_obj_modify && can_agent_manipulate) if (!is_link && is_obj_modify && can_agent_manipulate)
{ {
childSetEnabled("GroupLabel", true); childSetEnabled("GroupLabel", true);
childSetEnabled("CheckGroupCopy",owner_mask & PERM_TRANSFER); childSetEnabled("CheckGroupCopy", (owner_mask & (PERM_TRANSFER|PERM_COPY)) == (PERM_TRANSFER|PERM_COPY));
childSetEnabled("CheckGroupMod", owner_mask & PERM_MODIFY); childSetEnabled("CheckGroupMod", owner_mask & PERM_MODIFY);
childSetEnabled("CheckGroupMove", true); childSetEnabled("CheckGroupMove", true);
childSetEnabled("EveryoneLabel", true); childSetEnabled("EveryoneLabel", true);
childSetEnabled("CheckEveryoneCopy",(owner_mask & PERM_COPY) && (owner_mask & PERM_TRANSFER)); childSetEnabled("CheckEveryoneCopy", (owner_mask & (PERM_TRANSFER|PERM_COPY)) == (PERM_TRANSFER|PERM_COPY));
childSetEnabled("CheckEveryoneMove",true); childSetEnabled("CheckEveryoneMove",true);
} }
else else
@@ -551,7 +551,7 @@ void LLFloaterProperties::refreshFromItem(LLInventoryItem* item)
childSetEnabled("CheckGroupMod", false); childSetEnabled("CheckGroupMod", false);
childSetEnabled("CheckGroupMove", false); childSetEnabled("CheckGroupMove", false);
childSetEnabled("EveryoneLabel", false); childSetEnabled("EveryoneLabel", false);
childSetEnabled("CheckEveryoneCopy",FALSE); childSetEnabled("CheckEveryoneCopy",false);
childSetEnabled("CheckEveryoneMove",false); childSetEnabled("CheckEveryoneMove",false);
} }

View File

@@ -898,7 +898,8 @@ void LLFloaterReporter::takeScreenshot()
const S32 IMAGE_HEIGHT = 768; const S32 IMAGE_HEIGHT = 768;
LLPointer<LLImageRaw> raw = new LLImageRaw; LLPointer<LLImageRaw> raw = new LLImageRaw;
if( !gViewerWindow->rawSnapshot(raw, IMAGE_WIDTH, IMAGE_HEIGHT, TRUE, FALSE, TRUE, FALSE)) // Warning: This crops left and right in case of wide-screen monitor:
if( !gViewerWindow->rawSnapshot(raw, IMAGE_WIDTH, IMAGE_HEIGHT, (F32)IMAGE_WIDTH / IMAGE_HEIGHT, TRUE, FALSE))
{ {
llwarns << "Unable to take screenshot" << llendl; llwarns << "Unable to take screenshot" << llendl;
return; return;

File diff suppressed because it is too large Load Diff

View File

@@ -47,16 +47,22 @@ public:
{ {
SNAPSHOT_FORMAT_PNG, SNAPSHOT_FORMAT_PNG,
SNAPSHOT_FORMAT_JPEG, SNAPSHOT_FORMAT_JPEG,
SNAPSHOT_FORMAT_BMP SNAPSHOT_FORMAT_BMP,
SNAPSHOT_FORMAT_J2C
} ESnapshotFormat; } ESnapshotFormat;
LLFloaterSnapshot(); LLFloaterSnapshot();
virtual ~LLFloaterSnapshot(); virtual ~LLFloaterSnapshot();
LLRect getThumbnailAreaRect();
/*virtual*/ BOOL postBuild(); /*virtual*/ BOOL postBuild();
/*virtual*/ void draw(); /*virtual*/ void draw();
/*virtual*/ void onClose(bool app_quitting); /*virtual*/ void onClose(bool app_quitting);
/*virtual*/ void onOpen(); /*virtual*/ void onOpen();
/*virtual*/ BOOL handleKeyHere(KEY key, MASK mask);
/*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask);
/*virtual*/ BOOL handleMouseUp(S32 x, S32 y, MASK mask);
static void show(void*); static void show(void*);
static void hide(void*); static void hide(void*);
@@ -66,6 +72,13 @@ public:
static S32 getUIWinHeightShort() {return sUIWinHeightShort ;} static S32 getUIWinHeightShort() {return sUIWinHeightShort ;}
static S32 getUIWinWidth() {return sUIWinWidth ;} static S32 getUIWinWidth() {return sUIWinWidth ;}
static void saveLocalDone(bool success, int index);
static void saveFeedDone(bool success, int index);
static void savePostcardDone(bool success, int index);
static void updateControls();
static void resetFeedAndPostcardAspect();
private: private:
class Impl; class Impl;
Impl& impl; Impl& impl;

View File

@@ -483,8 +483,8 @@ void LLIMMgr::addMessage(
} }
//not sure why...but if it is from ourselves we set the target_id //not sure why...but if it is from ourselves we set the target_id
//to be NULL //to be NULL, which seems to be breaking links on group chats, so let's not there.
if( other_participant_id == gAgent.getID() ) if (other_participant_id == gAgent.getID() && !gAgent.isInGroup(session_id))
{ {
other_participant_id = LLUUID::null; other_participant_id = LLUUID::null;
} }
@@ -553,7 +553,6 @@ void LLIMMgr::addMessage(
// when answering questions. // when answering questions.
if(gAgent.isGodlike()) if(gAgent.isGodlike())
{ {
// *TODO:translate (low priority, god ability)
std::ostringstream bonus_info; std::ostringstream bonus_info;
bonus_info << LLTrans::getString("***")+ " "+ LLTrans::getString("IMParentEstate") + LLTrans::getString(":") + " " bonus_info << LLTrans::getString("***")+ " "+ LLTrans::getString("IMParentEstate") + LLTrans::getString(":") + " "
<< parent_estate_id << parent_estate_id
@@ -574,9 +573,26 @@ void LLIMMgr::addMessage(
// now add message to floater // now add message to floater
bool is_from_system = target_id.isNull() || (from == SYSTEM_FROM); bool is_from_system = target_id.isNull() || (from == SYSTEM_FROM);
const LLColor4& color = ( is_from_system ?
gSavedSettings.getColor4("SystemChatColor") : static LLCachedControl<bool> color_linden_chat("ColorLindenChat");
gSavedSettings.getColor("IMChatColor")); bool linden = color_linden_chat && LLMuteList::getInstance()->isLinden(from);
static LLCachedControl<bool> color_friend_chat("ColorFriendChat");
bool contact = color_friend_chat && LLAvatarTracker::instance().isBuddy(other_participant_id);
static LLCachedControl<bool> color_eo_chat("ColorEstateOwnerChat");
bool estate_owner = false;
if (color_eo_chat)
{
LLViewerRegion* parent_estate = gAgent.getRegion();
estate_owner = (parent_estate && parent_estate->isAlive() && other_participant_id == parent_estate->getOwner());
}
const LLColor4& color = ( is_from_system ? gSavedSettings.getColor4("SystemChatColor")
: linden ? gSavedSettings.getColor4("AscentLindenColor")
: contact ? gSavedSettings.getColor4("AscentFriendColor")
: estate_owner ? gSavedSettings.getColor4("AscentEstateOwnerColor")
: gSavedSettings.getColor("IMChatColor"));
if ( !link_name ) if ( !link_name )
{ {
floater->addHistoryLine(msg,color); // No name to prepend, so just add the message normally floater->addHistoryLine(msg,color); // No name to prepend, so just add the message normally
@@ -731,7 +747,18 @@ LLUUID LLIMMgr::addSession(
{ {
noteMutedUsers(floater, ids); noteMutedUsers(floater, ids);
} }
LLFloaterChatterBox::getInstance(LLSD())->showFloater(floater);
static LLCachedControl<bool> tear_off("OtherChatsTornOff");
if(tear_off)
{
// removal sets up relationship for re-attach
LLFloaterChatterBox::getInstance(LLSD())->removeFloater(floater);
// reparent to floater view
gFloaterView->addChild(floater);
gFloaterView->bringToFront(floater);
}
else
LLFloaterChatterBox::getInstance(LLSD())->showFloater(floater);
} }
else else
{ {
@@ -1103,6 +1130,19 @@ LLFloaterIMPanel* LLIMMgr::createFloater(
dialog); dialog);
LLTabContainer::eInsertionPoint i_pt = user_initiated ? LLTabContainer::RIGHT_OF_CURRENT : LLTabContainer::END; LLTabContainer::eInsertionPoint i_pt = user_initiated ? LLTabContainer::RIGHT_OF_CURRENT : LLTabContainer::END;
LLFloaterChatterBox::getInstance(LLSD())->addFloater(floater, FALSE, i_pt); LLFloaterChatterBox::getInstance(LLSD())->addFloater(floater, FALSE, i_pt);
static LLCachedControl<bool> tear_off("OtherChatsTornOff");
if (tear_off)
{
LLFloaterChatterBox::getInstance(LLSD())->removeFloater(floater); // removal sets up relationship for re-attach
gFloaterView->addChild(floater); // reparent to floater view
LLFloater* focused_floater = gFloaterView->getFocusedFloater(); // obtain the focused floater
floater->open(); // make the new chat floater appear
if (focused_floater != NULL) // there was a focused floater
{
floater->setMinimized(true); // so minimize this one, for now
focused_floater->setFocus(true); // and work around focus being removed by focusing on the last
}
}
mFloaters.insert(floater->getHandle()); mFloaters.insert(floater->getHandle());
return floater; return floater;
} }
@@ -1129,6 +1169,24 @@ LLFloaterIMPanel* LLIMMgr::createFloater(
dialog); dialog);
LLTabContainer::eInsertionPoint i_pt = user_initiated ? LLTabContainer::RIGHT_OF_CURRENT : LLTabContainer::END; LLTabContainer::eInsertionPoint i_pt = user_initiated ? LLTabContainer::RIGHT_OF_CURRENT : LLTabContainer::END;
LLFloaterChatterBox::getInstance(LLSD())->addFloater(floater, FALSE, i_pt); LLFloaterChatterBox::getInstance(LLSD())->addFloater(floater, FALSE, i_pt);
static LLCachedControl<bool> tear_off("OtherChatsTornOff");
if (tear_off)
{
LLFloaterChatterBox::getInstance(LLSD())->removeFloater(floater); // removal sets up relationship for re-attach
gFloaterView->addChild(floater); // reparent to floater view
LLFloater* focused_floater = gFloaterView->getFocusedFloater(); // obtain the focused floater
floater->open(); // make the new chat floater appear
static LLCachedControl<bool> minimize("OtherChatsTornOffAndMinimized");
if (focused_floater != NULL) // there was a focused floater
{
floater->setMinimized(true); // so minimize this one, for now
focused_floater->setFocus(true); // and work around focus being removed by focusing on the last
}
else if (minimize)
{
floater->setMinimized(true);
}
}
mFloaters.insert(floater->getHandle()); mFloaters.insert(floater->getHandle());
return floater; return floater;
} }
@@ -1153,7 +1211,7 @@ void LLIMMgr::noteOfflineUsers(
std::string full_name; std::string full_name;
if (info if (info
&& !info->isOnline() && !info->isOnline()
&& gCacheName->getFullName(ids.get(i), full_name)) && LLAvatarNameCache::getPNSName(ids.get(i), full_name))
{ {
LLUIString offline = LLTrans::getString("offline_message"); LLUIString offline = LLTrans::getString("offline_message");
offline.setArg("[NAME]", full_name); offline.setArg("[NAME]", full_name);

View File

@@ -67,6 +67,7 @@
#include "llinventoryclipboard.h" #include "llinventoryclipboard.h"
#include "llinventorymodelbackgroundfetch.h" #include "llinventorymodelbackgroundfetch.h"
#include "lllineeditor.h" #include "lllineeditor.h"
#include "llmakeoutfitdialog.h"
#include "llmenugl.h" #include "llmenugl.h"
#include "llpreviewanim.h" #include "llpreviewanim.h"
#include "llpreviewgesture.h" #include "llpreviewgesture.h"
@@ -382,6 +383,10 @@ void do_create(LLInventoryModel *model, LLInventoryPanel *ptr, std::string type,
LLInventoryType::IT_GESTURE, LLInventoryType::IT_GESTURE,
PERM_ALL); PERM_ALL);
} }
else if ("outfit" == type)
{
new LLMakeOutfitDialog(false);
}
else else
{ {
LLWearableType::EType wear_type = LLWearableType::typeNameToType(type); LLWearableType::EType wear_type = LLWearableType::typeNameToType(type);

View File

@@ -854,21 +854,26 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id,
} }
} }
bool paste_as_copy = false; // If Paste As Copy is on the menu, Paste As Link will always show up disabled, so don't bother.
// Don't allow items to be pasted directly into the COF or the inbox/outbox // Don't allow items to be pasted directly into the COF or the inbox/outbox
if (!isCOFFolder() && !isInboxFolder() && !isOutboxFolder()) if (!isCOFFolder() && !isInboxFolder() && !isOutboxFolder())
{ {
items.push_back(std::string("Paste")); items.push_back(std::string("Paste"));
// Paste as copy if we have links. // Paste as copy if we have links.
if (InventoryLinksEnabled() && isClipboardPasteableAsCopy()) if (InventoryLinksEnabled() && isClipboardPasteableAsCopy())
{
items.push_back(std::string("Paste As Copy")); items.push_back(std::string("Paste As Copy"));
paste_as_copy = true;
}
} }
if (!isClipboardPasteable() || ((flags & FIRST_SELECTED_ITEM) == 0)) if (!isClipboardPasteable() || ((flags & FIRST_SELECTED_ITEM) == 0))
{ {
disabled_items.push_back(std::string("Paste")); disabled_items.push_back(std::string("Paste"));
disabled_items.push_back(std::string("Paste As Copy")); disabled_items.push_back(std::string("Paste As Copy"));
paste_as_copy = false;
} }
if(InventoryLinksEnabled()) if (!paste_as_copy && InventoryLinksEnabled())
{ {
items.push_back(std::string("Paste As Link")); items.push_back(std::string("Paste As Link"));
if (!isClipboardPasteableAsLink() || (flags & FIRST_SELECTED_ITEM) == 0) if (!isClipboardPasteableAsLink() || (flags & FIRST_SELECTED_ITEM) == 0)
@@ -5342,9 +5347,10 @@ void LLObjectBridge::performAction(LLInventoryModel* model, std::string action)
void LLObjectBridge::openItem() void LLObjectBridge::openItem()
{ {
static LLCachedControl<bool> add(gSavedSettings, "LiruAddNotReplace");
// object double-click action is to wear/unwear object // object double-click action is to wear/unwear object
performAction(getInventoryModel(), performAction(getInventoryModel(),
get_is_item_worn(mUUID) ? "detach" : "attach"); get_is_item_worn(mUUID) ? "detach" : (add ? "wear_add" : "attach"));
} }
std::string LLObjectBridge::getLabelSuffix() const std::string LLObjectBridge::getLabelSuffix() const
@@ -6798,10 +6804,14 @@ void LLWearableBridgeAction::wearOnAvatar()
{ {
// TODO: investigate wearables may not be loaded at this point EXT-8231 // TODO: investigate wearables may not be loaded at this point EXT-8231
static LLCachedControl<bool> add(gSavedSettings, "LiruAddNotReplace");
LLViewerInventoryItem* item = getItem(); LLViewerInventoryItem* item = getItem();
if(item) if(item)
{ {
LLAppearanceMgr::instance().wearItemOnAvatar(item->getUUID(), true, true); if (get_is_item_worn(item))
LLAppearanceMgr::instance().removeItemFromAvatar(item->getUUID());
else
LLAppearanceMgr::instance().wearItemOnAvatar(item->getUUID(), true, !add);
} }
} }

View File

@@ -88,11 +88,18 @@ std::string LLLogChat::timestamp(bool withdate)
// it's daylight savings time there. // it's daylight savings time there.
timep = utc_to_pacific_time(utc_time, gPacificDaylightTime); timep = utc_to_pacific_time(utc_time, gPacificDaylightTime);
static LLCachedControl<bool> withseconds("SecondsInLog");
std::string text; std::string text;
if (withdate) if (withdate)
text = llformat("[%d/%02d/%02d %02d:%02d] ", (timep->tm_year-100)+2000, timep->tm_mon+1, timep->tm_mday, timep->tm_hour, timep->tm_min); if (withseconds)
text = llformat("[%d-%02d-%02d %02d:%02d:%02d] ", (timep->tm_year-100)+2000, timep->tm_mon+1, timep->tm_mday, timep->tm_hour, timep->tm_min, timep->tm_sec);
else
text = llformat("[%d/%02d/%02d %02d:%02d] ", (timep->tm_year-100)+2000, timep->tm_mon+1, timep->tm_mday, timep->tm_hour, timep->tm_min);
else else
text = llformat("[%02d:%02d] ", timep->tm_hour, timep->tm_min); if (withseconds)
text = llformat("[%02d:%02d:%02d] ", timep->tm_hour, timep->tm_min, timep->tm_sec);
else
text = llformat("[%02d:%02d] ", timep->tm_hour, timep->tm_min);
return text; return text;
} }

View File

@@ -0,0 +1,218 @@
/**
* @file llmakeoutfitdialog.cpp
* @brief The Make Outfit Dialog, triggered by "Make Outfit" and similar UICtrls.
*
* $LicenseInfo:firstyear=2002&license=viewergpl$
*
* Copyright (c) 2002-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#include "llviewerprecompiledheaders.h"
#include "llmakeoutfitdialog.h"
#include "llagent.h"
#include "llappearancemgr.h"
#include "lluictrlfactory.h"
#include "llvoavatarself.h"
#include "hippogridmanager.h"
LLMakeOutfitDialog::LLMakeOutfitDialog(bool modal) : LLModalDialog(LLStringUtil::null, 515, 510, modal)
{
LLUICtrlFactory::getInstance()->buildFloater(this, "floater_new_outfit_dialog.xml");
setCanClose(!modal);
setCanMinimize(!modal);
// Build list of check boxes
for (S32 i = 0; i < LLWearableType::WT_COUNT; i++)
{
std::string name = std::string("checkbox_") + LLWearableType::getTypeLabel((LLWearableType::EType)i);
mCheckBoxList.push_back(std::make_pair(name, i));
// Hide undergarments from teens
if (gAgent.isTeen() && ((LLWearableType::WT_UNDERSHIRT == (LLWearableType::EType)i) || (LLWearableType::WT_UNDERPANTS == (LLWearableType::EType)i)))
{
childSetVisible(name, false); // Lest they know what's beyond their reach.
}
else
{
bool enabled = gAgentWearables.getWearableCount((LLWearableType::EType)i); // TODO: MULTI-WEARABLE
bool selected = enabled && (LLWearableType::WT_SHIRT <= i); // only select clothing by default
childSetEnabled(name, enabled);
childSetValue(name, selected);
}
}
// NOTE: .xml needs to be updated if attachments are added or their names are changed!
LLVOAvatar* avatar = gAgentAvatarp;
if (avatar)
{
for (LLVOAvatar::attachment_map_t::iterator iter = avatar->mAttachmentPoints.begin(); iter != avatar->mAttachmentPoints.end();)
{
LLVOAvatar::attachment_map_t::iterator curiter = iter++;
LLViewerJointAttachment* attachment = curiter->second;
S32 attachment_pt = curiter->first;
bool object_attached = (attachment->getNumObjects() > 0);
std::string name = std::string("checkbox_") + attachment->getName();
mCheckBoxList.push_back(std::make_pair(name, attachment_pt));
childSetEnabled(name, object_attached);
}
}
if (!gHippoGridManager->getConnectedGrid()->supportsInvLinks())
{
childSetEnabled("checkbox_use_links", false);
childSetValue("checkbox_use_links", false);
childSetEnabled("checkbox_use_outfits", false);
childSetValue("checkbox_use_outfits", false);
}
getChild<LLUICtrl>("Save")->setCommitCallback(boost::bind(&LLMakeOutfitDialog::onSave, this));
getChild<LLUICtrl>("Cancel")->setCommitCallback(boost::bind(&LLMakeOutfitDialog::close, this, _1));
getChild<LLUICtrl>("Check All")->setCommitCallback(boost::bind(&LLMakeOutfitDialog::onCheckAll, this, true));
getChild<LLUICtrl>("Uncheck All")->setCommitCallback(boost::bind(&LLMakeOutfitDialog::onCheckAll, this, false));
getChild<LLUICtrl>("checkbox_use_outfits")->setCommitCallback(boost::bind(&LLMakeOutfitDialog::refresh, this));
startModal();
}
//virtual
void LLMakeOutfitDialog::draw()
{
bool one_or_more_items_selected = false;
for (S32 i = 0; i < (S32)mCheckBoxList.size(); i++)
{
if (childGetValue(mCheckBoxList[i].first).asBoolean())
{
one_or_more_items_selected = true;
break;
}
}
childSetEnabled("Save", one_or_more_items_selected);
LLModalDialog::draw();
}
BOOL LLMakeOutfitDialog::postBuild()
{
refresh();
return true;
}
void LLMakeOutfitDialog::refresh()
{
bool fUseOutfits = getUseOutfits();
for (S32 idxType = 0; idxType < LLWearableType::WT_COUNT; idxType++)
{
LLWearableType::EType wtType = (LLWearableType::EType)idxType;
if (LLAssetType::AT_BODYPART != LLWearableType::getAssetType(wtType))
continue;
LLUICtrl* pCheckCtrl = getChild<LLUICtrl>(std::string("checkbox_") + LLWearableType::getTypeLabel(wtType));
if (!pCheckCtrl)
continue;
pCheckCtrl->setEnabled(!fUseOutfits);
if (fUseOutfits)
pCheckCtrl->setValue(true);
}
childSetEnabled("checkbox_use_links", !fUseOutfits);
}
void LLMakeOutfitDialog::setWearableToInclude(S32 wearable, bool enabled, bool selected)
{
LLWearableType::EType wtType = (LLWearableType::EType)wearable;
if (((0 <= wtType) && (wtType < LLWearableType::WT_COUNT)) &&
((LLAssetType::AT_BODYPART != LLWearableType::getAssetType(wtType)) || !getUseOutfits()))
{
std::string name = std::string("checkbox_") + LLWearableType::getTypeLabel(wtType);
childSetEnabled(name, enabled);
childSetValue(name, selected);
}
}
void LLMakeOutfitDialog::getIncludedItems(LLInventoryModel::item_array_t& item_list)
{
LLInventoryModel::cat_array_t *cats;
LLInventoryModel::item_array_t *items;
gInventory.getDirectDescendentsOf(LLAppearanceMgr::instance().getCOF(), cats, items);
for (LLInventoryModel::item_array_t::const_iterator iter = items->begin(); iter != items->end(); ++iter)
{
LLViewerInventoryItem* item = (*iter);
if (!item)
continue;
if (item->isWearableType())
{
LLWearableType::EType type = item->getWearableType();
if (type < LLWearableType::WT_COUNT && childGetValue(mCheckBoxList[type].first).asBoolean())
{
item_list.push_back(item);
}
}
else
{
LLViewerJointAttachment* attachment = gAgentAvatarp->getWornAttachmentPoint(item->getLinkedUUID());
if (attachment && childGetValue(std::string("checkbox_")+attachment->getName()).asBoolean())
{
item_list.push_back(item);
}
}
}
}
void LLMakeOutfitDialog::onSave()
{
std::string folder_name = childGetValue("name ed").asString();
LLStringUtil::trim(folder_name);
if (!folder_name.empty())
{
makeOutfit(folder_name);
close(); // destroys this object
}
}
void LLMakeOutfitDialog::onCheckAll(bool check)
{
for (S32 i = 0; i < (S32)(mCheckBoxList.size()); i++)
{
std::string name = mCheckBoxList[i].first;
if (childIsEnabled(name)) childSetValue(name, check);
}
}
void LLMakeOutfitDialog::makeOutfit(const std::string folder_name)
{
LLInventoryModel::item_array_t item_list;
getIncludedItems(item_list);
// MULTI-WEARABLES TODO
if (getUseOutfits())
LLAppearanceMgr::instance().makeNewOutfitLinks(folder_name, item_list);
else
LLAppearanceMgr::instance().makeNewOutfitLegacy(folder_name, item_list, getUseLinks());
}

View File

@@ -0,0 +1,66 @@
/**
* @file llmakeoutfitdialog.h
* @brief The Make Outfit Dialog, triggered by "Make Outfit" and similar UICtrls.
*
* $LicenseInfo:firstyear=2002&license=viewergpl$
*
* Copyright (c) 2002-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#ifndef LLMAKEOUTFITDIALOG_H
#define LLMAKEOUTFITDIALOG_H
#include "llinventorymodel.h"
#include "llmodaldialog.h"
class LLMakeOutfitDialog : public LLModalDialog
{
private:
std::vector<std::pair<std::string,S32> > mCheckBoxList;
public:
LLMakeOutfitDialog(bool modal = true);
/*virtual*/ void draw();
BOOL postBuild();
void refresh();
void setWearableToInclude(S32 wearable, bool enabled, bool selected); //TODO: Call this when Wearables are added or removed to update the Dialog in !modal mode.
void onSave();
void onCheckAll(bool check);
//Accessors
void getIncludedItems(LLInventoryModel::item_array_t& item_list);
bool getUseOutfits() { return childGetValue("checkbox_use_outfits").asBoolean(); }
bool getUseLinks() { return childGetValue("checkbox_use_links").asBoolean(); }
//bool getRenameClothing() { return childGetValue("rename").asBoolean(); }
protected:
void makeOutfit(const std::string folder_name);
};
#endif //LLMAKEOUTFITDIALOG_H

View File

@@ -199,12 +199,19 @@ namespace LLMarketplaceImport
/*virtual*/ bool followRedir(void) const { return true; } /*virtual*/ bool followRedir(void) const { return true; }
/*virtual*/ bool needsHeaders(void) const { return true; } /*virtual*/ bool needsHeaders(void) const { return true; }
void completedHeaders(U32 status, std::string const& reason, AIHTTPReceivedHeaders const& headers) /*virtual*/ void completedHeaders(U32 status, std::string const& reason, AIHTTPReceivedHeaders const& headers)
{ {
std::string set_cookie_string; if (status == HTTP_OK)
if (headers.getFirstValue("set-cookie", set_cookie_string) && !set_cookie_string.empty())
{ {
sMarketplaceCookie = set_cookie_string; std::string value = get_cookie("_slm_session");
if (!value.empty())
{
sMarketplaceCookie = value;
}
else if (sMarketplaceCookie.empty())
{
llwarns << "No such cookie \"_slm_session\" received!" << llendl;
}
} }
} }
@@ -226,7 +233,7 @@ namespace LLMarketplaceImport
{ {
if (gSavedSettings.getBOOL("InventoryOutboxLogging")) if (gSavedSettings.getBOOL("InventoryOutboxLogging"))
{ {
llinfos << " SLM GET clearing marketplace cookie due to authentication failure or timeout" << llendl; llinfos << " SLM GET clearing marketplace cookie due to authentication failure or timeout (" << status << " / " << reason << ")." << llendl;
} }
sMarketplaceCookie.clear(); sMarketplaceCookie.clear();
@@ -372,7 +379,7 @@ namespace LLMarketplaceImport
// Interface class // Interface class
// //
//static const F32 MARKET_IMPORTER_UPDATE_FREQUENCY = 300.0f; //1.0f; static const F32 MARKET_IMPORTER_UPDATE_FREQUENCY = 1.0f;
//static //static
void LLMarketplaceInventoryImporter::update() void LLMarketplaceInventoryImporter::update()
@@ -383,7 +390,7 @@ void LLMarketplaceInventoryImporter::update()
if (update_timer.hasExpired()) if (update_timer.hasExpired())
{ {
LLMarketplaceInventoryImporter::instance().updateImport(); LLMarketplaceInventoryImporter::instance().updateImport();
static LLCachedControl<F32> MARKET_IMPORTER_UPDATE_FREQUENCY("MarketImporterUpdateFreq", 10.0f); //static LLCachedControl<F32> MARKET_IMPORTER_UPDATE_FREQUENCY("MarketImporterUpdateFreq", 1.0f);
update_timer.setTimerExpirySec(MARKET_IMPORTER_UPDATE_FREQUENCY); update_timer.setTimerExpirySec(MARKET_IMPORTER_UPDATE_FREQUENCY);
} }
} }

View File

@@ -35,6 +35,8 @@
#include "llmediaremotectrl.h" #include "llmediaremotectrl.h"
#include "llaudioengine.h" #include "llaudioengine.h"
#include "llchat.h"
#include "llfloaterchat.h"
#include "lliconctrl.h" #include "lliconctrl.h"
#include "llmimetypes.h" #include "llmimetypes.h"
#include "lloverlaybar.h" #include "lloverlaybar.h"
@@ -53,6 +55,7 @@
// //
static LLRegisterWidget<LLMediaRemoteCtrl> r("media_remote"); static LLRegisterWidget<LLMediaRemoteCtrl> r("media_remote");
static std::string sLastTooltip;
LLMediaRemoteCtrl::LLMediaRemoteCtrl() LLMediaRemoteCtrl::LLMediaRemoteCtrl()
{ {
@@ -263,10 +266,22 @@ void LLMediaRemoteCtrl::enableMediaButtons()
if(artist.isDefined() && title.isDefined()) if(artist.isDefined() && title.isDefined())
info_text = artist.asString() + " -- " + title.asString(); info_text = artist.asString() + " -- " + title.asString();
else if(title.isDefined()) else if(title.isDefined())
info_text = std::string("Title: ") + title.asString(); info_text = getString("Title") + ": " + title.asString();
else if(artist.isDefined()) else if(artist.isDefined())
info_text = std::string("Artist: ") + artist.asString(); info_text = getString("Artist") + ": " + artist.asString();
music_pause_btn->setToolTip(info_text); if(music_pause_btn->getToolTip() != info_text) //Has info_text changed since last call?
{
music_pause_btn->setToolTip(info_text);
static LLCachedControl<bool> announce_stream_metadata("AnnounceStreamMetadata");
if(announce_stream_metadata && info_text != sLastTooltip && info_text != "Loading...") //Are we announcing? Don't annoounce what we've last announced. Don't announce Loading.
{
sLastTooltip = info_text;
LLChat chat;
chat.mText = getString("Now_playing") + " " + info_text;
chat.mSourceType = CHAT_SOURCE_SYSTEM;
LLFloaterChat::addChat(chat);
}
}
} }
else else
music_pause_btn->setToolTip(mCachedPauseTip); music_pause_btn->setToolTip(mCachedPauseTip);

View File

@@ -0,0 +1,237 @@
/**
* @file llmenuoptionpathfindingrebakenavmesh.cpp
* @brief Implementation of llmenuoptionpathfindingrebakenavmesh
* @author Prep@lindenlab.com
*
* $LicenseInfo:firstyear=2012&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2012, 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 "llmenuoptionpathfindingrebakenavmesh.h"
#include <boost/bind.hpp>
#include <boost/signals2.hpp>
#include "llagent.h"
#include "llenvmanager.h"
#include "llnotificationsutil.h"
#include "llpathfindingmanager.h"
#include "llpathfindingnavmesh.h"
#include "llpathfindingnavmeshstatus.h"
#include "llviewerregion.h"
LLMenuOptionPathfindingRebakeNavmesh::LLMenuOptionPathfindingRebakeNavmesh()
: LLSingleton<LLMenuOptionPathfindingRebakeNavmesh>(),
mIsInitialized(false),
mCanRebakeRegion(false),
mRebakeNavMeshMode(kRebakeNavMesh_Default),
mNavMeshSlot(),
mRegionCrossingSlot(),
mAgentStateSlot()
{
}
LLMenuOptionPathfindingRebakeNavmesh::~LLMenuOptionPathfindingRebakeNavmesh()
{
if (mRebakeNavMeshMode == kRebakeNavMesh_RequestSent)
{
LL_WARNS("navmeshRebaking") << "During destruction of the LLMenuOptionPathfindingRebakeNavmesh "
<< "singleton, the mode indicates that a request has been sent for which a response has yet "
<< "to be received. This could contribute to a crash on exit." << LL_ENDL;
}
llassert(!mIsInitialized);
if (mIsInitialized)
{
quit();
}
}
void LLMenuOptionPathfindingRebakeNavmesh::initialize()
{
if (!mIsInitialized)
{
mIsInitialized = true;
setMode(kRebakeNavMesh_Default);
createNavMeshStatusListenerForCurrentRegion();
if ( !mRegionCrossingSlot.connected() )
{
mRegionCrossingSlot = LLEnvManagerNew::getInstance()->setRegionChangeCallback(boost::bind(&LLMenuOptionPathfindingRebakeNavmesh::handleRegionBoundaryCrossed, this));
}
if (!mAgentStateSlot.connected())
{
mAgentStateSlot = LLPathfindingManager::getInstance()->registerAgentStateListener(boost::bind(&LLMenuOptionPathfindingRebakeNavmesh::handleAgentState, this, _1));
}
LLPathfindingManager::getInstance()->requestGetAgentState();
}
}
void LLMenuOptionPathfindingRebakeNavmesh::quit()
{
llassert(mIsInitialized);
if (mIsInitialized)
{
if (mNavMeshSlot.connected())
{
mNavMeshSlot.disconnect();
}
if (mRegionCrossingSlot.connected())
{
mRegionCrossingSlot.disconnect();
}
if (mAgentStateSlot.connected())
{
mAgentStateSlot.disconnect();
}
mIsInitialized = false;
}
}
bool LLMenuOptionPathfindingRebakeNavmesh::canRebakeRegion() const
{
if (!mIsInitialized)
{
LL_ERRS("navmeshRebaking") << "LLMenuOptionPathfindingRebakeNavmesh class has not been initialized "
<< "when the ability to rebake navmesh is being requested." << LL_ENDL;
}
return mCanRebakeRegion;
}
LLMenuOptionPathfindingRebakeNavmesh::ERebakeNavMeshMode LLMenuOptionPathfindingRebakeNavmesh::getMode() const
{
if (!mIsInitialized)
{
LL_ERRS("navmeshRebaking") << "LLMenuOptionPathfindingRebakeNavmesh class has not been initialized "
<< "when the mode is being requested." << LL_ENDL;
}
return mRebakeNavMeshMode;
}
void LLMenuOptionPathfindingRebakeNavmesh::sendRequestRebakeNavmesh()
{
if (!mIsInitialized)
{
LL_ERRS("navmeshRebaking") << "LLMenuOptionPathfindingRebakeNavmesh class has not been initialized "
<< "when the request is being made to rebake the navmesh." << LL_ENDL;
}
else
{
if (!canRebakeRegion())
{
LL_WARNS("navmeshRebaking") << "attempting to rebake navmesh when user does not have permissions "
<< "on this region" << LL_ENDL;
}
if (getMode() != kRebakeNavMesh_Available)
{
LL_WARNS("navmeshRebaking") << "attempting to rebake navmesh when mode is not available"
<< LL_ENDL;
}
setMode(kRebakeNavMesh_RequestSent);
LLPathfindingManager::getInstance()->requestRebakeNavMesh(boost::bind(&LLMenuOptionPathfindingRebakeNavmesh::handleRebakeNavMeshResponse, this, _1));
}
}
void LLMenuOptionPathfindingRebakeNavmesh::setMode(ERebakeNavMeshMode pRebakeNavMeshMode)
{
mRebakeNavMeshMode = pRebakeNavMeshMode;
}
void LLMenuOptionPathfindingRebakeNavmesh::handleAgentState(BOOL pCanRebakeRegion)
{
llassert(mIsInitialized);
mCanRebakeRegion = pCanRebakeRegion;
}
void LLMenuOptionPathfindingRebakeNavmesh::handleRebakeNavMeshResponse(bool pResponseStatus)
{
llassert(mIsInitialized);
if (getMode() == kRebakeNavMesh_RequestSent)
{
setMode(pResponseStatus ? kRebakeNavMesh_InProgress : kRebakeNavMesh_Default);
}
if (!pResponseStatus)
{
LLNotificationsUtil::add("PathfindingCannotRebakeNavmesh");
}
}
void LLMenuOptionPathfindingRebakeNavmesh::handleNavMeshStatus(const LLPathfindingNavMeshStatus &pNavMeshStatus)
{
llassert(mIsInitialized);
ERebakeNavMeshMode rebakeNavMeshMode = kRebakeNavMesh_Default;
if (pNavMeshStatus.isValid())
{
switch (pNavMeshStatus.getStatus())
{
case LLPathfindingNavMeshStatus::kPending :
case LLPathfindingNavMeshStatus::kRepending :
rebakeNavMeshMode = kRebakeNavMesh_Available;
break;
case LLPathfindingNavMeshStatus::kBuilding :
rebakeNavMeshMode = kRebakeNavMesh_InProgress;
break;
case LLPathfindingNavMeshStatus::kComplete :
rebakeNavMeshMode = kRebakeNavMesh_NotAvailable;
break;
default :
rebakeNavMeshMode = kRebakeNavMesh_Default;
llassert(0);
break;
}
}
setMode(rebakeNavMeshMode);
}
void LLMenuOptionPathfindingRebakeNavmesh::handleRegionBoundaryCrossed()
{
llassert(mIsInitialized);
createNavMeshStatusListenerForCurrentRegion();
mCanRebakeRegion = FALSE;
LLPathfindingManager::getInstance()->requestGetAgentState();
}
void LLMenuOptionPathfindingRebakeNavmesh::createNavMeshStatusListenerForCurrentRegion()
{
if (mNavMeshSlot.connected())
{
mNavMeshSlot.disconnect();
}
LLViewerRegion *currentRegion = gAgent.getRegion();
if (currentRegion != NULL)
{
mNavMeshSlot = LLPathfindingManager::getInstance()->registerNavMeshListenerForRegion(currentRegion, boost::bind(&LLMenuOptionPathfindingRebakeNavmesh::handleNavMeshStatus, this, _2));
LLPathfindingManager::getInstance()->requestGetNavMeshForRegion(currentRegion, true);
}
}

View File

@@ -1,6 +1,6 @@
/** /**
* @file llpanelpathfindingrebakenavmesh.h * @file llmenuoptionpathfindingrebakenavmesh.h
* @brief Header file for llpanelpathfindingrebakenavmesh * @brief Header file for llmenuoptionpathfindingrebakenavmesh
* @author Prep@lindenlab.com * @author Prep@lindenlab.com
* *
* $LicenseInfo:firstyear=2012&license=viewerlgpl$ * $LicenseInfo:firstyear=2012&license=viewerlgpl$
@@ -24,34 +24,22 @@
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$ * $/LicenseInfo$
*/ */
#ifndef LL_LLPANELPATHFINDINGREBAKENAVMESH_H #ifndef LL_LLMENUOPTIONPATHFINDINGREBAKENAVMESH_H
#define LL_LLPANELPATHFINDINGREBAKENAVMESH_H #define LL_LLMENUOPTIONPATHFINDINGREBAKENAVMESH_H
#include <boost/signals2.hpp> #include <boost/signals2.hpp>
#include "llpanel.h"
#include "llpathfindingmanager.h" #include "llpathfindingmanager.h"
#include "llpathfindingnavmesh.h" #include "llpathfindingnavmesh.h"
#include "llsingleton.h"
class LLButton;
class LLPathfindingNavMeshStatus; class LLPathfindingNavMeshStatus;
class LLPanelPathfindingRebakeNavmesh : public LLPanel class LLMenuOptionPathfindingRebakeNavmesh : public LLSingleton<LLMenuOptionPathfindingRebakeNavmesh>
{ {
LOG_CLASS(LLMenuOptionPathfindingRebakeNavmesh);
LOG_CLASS(LLPanelPathfindingRebakeNavmesh);
public: public:
static LLPanelPathfindingRebakeNavmesh* getInstance();
virtual BOOL postBuild();
virtual void draw();
virtual BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect_screen);
protected:
private:
typedef enum typedef enum
{ {
kRebakeNavMesh_Available, kRebakeNavMesh_Available,
@@ -61,15 +49,21 @@ private:
kRebakeNavMesh_Default = kRebakeNavMesh_NotAvailable kRebakeNavMesh_Default = kRebakeNavMesh_NotAvailable
} ERebakeNavMeshMode; } ERebakeNavMeshMode;
LLPanelPathfindingRebakeNavmesh(); LLMenuOptionPathfindingRebakeNavmesh();
virtual ~LLPanelPathfindingRebakeNavmesh(); virtual ~LLMenuOptionPathfindingRebakeNavmesh();
static LLPanelPathfindingRebakeNavmesh* getPanel(); void initialize();
void quit();
void setMode(ERebakeNavMeshMode pRebakeNavMeshMode); bool canRebakeRegion() const;
ERebakeNavMeshMode getMode() const; ERebakeNavMeshMode getMode() const;
void onNavMeshRebakeClick(); void sendRequestRebakeNavmesh();
protected:
private:
void setMode(ERebakeNavMeshMode pRebakeNavMeshMode);
void handleAgentState(BOOL pCanRebakeRegion); void handleAgentState(BOOL pCanRebakeRegion);
void handleRebakeNavMeshResponse(bool pResponseStatus); void handleRebakeNavMeshResponse(bool pResponseStatus);
@@ -78,19 +72,14 @@ private:
void createNavMeshStatusListenerForCurrentRegion(); void createNavMeshStatusListenerForCurrentRegion();
bool doDraw() const; bool mIsInitialized;
void updatePosition();
BOOL mCanRebakeRegion; bool mCanRebakeRegion;
ERebakeNavMeshMode mRebakeNavMeshMode; ERebakeNavMeshMode mRebakeNavMeshMode;
LLButton* mNavMeshRebakeButton;
LLButton* mNavMeshSendingButton;
LLButton* mNavMeshBakingButton;
LLPathfindingNavMesh::navmesh_slot_t mNavMeshSlot; LLPathfindingNavMesh::navmesh_slot_t mNavMeshSlot;
boost::signals2::connection mRegionCrossingSlot; boost::signals2::connection mRegionCrossingSlot;
LLPathfindingManager::agent_state_slot_t mAgentStateSlot; LLPathfindingManager::agent_state_slot_t mAgentStateSlot;
}; };
#endif // LL_LLPANELPATHFINDINGREBAKENAVMESH_H #endif // LL_LLMENUOPTIONPATHFINDINGREBAKENAVMESH_H

View File

@@ -246,19 +246,23 @@ void LLOverlayBar::layoutButtons()
if (state_buttons_panel->getVisible()) if (state_buttons_panel->getVisible())
{ {
U32 required_width=0; U32 button_count = 0;
const child_list_t& view_list = *(state_buttons_panel->getChildList()); const child_list_t& view_list = *(state_buttons_panel->getChildList());
BOOST_FOREACH(LLView* viewp, view_list) BOOST_FOREACH(LLView* viewp, view_list)
{ {
required_width+=viewp->getRect().getWidth(); if(!viewp->getEnabled())
continue;
++button_count;
} }
const S32 MAX_BAR_WIDTH = 600;
S32 bar_width = llclamp(state_buttons_panel->getRect().getWidth(), 0, MAX_BAR_WIDTH);
const S32 MAX_BAR_WIDTH = 800; // calculate button widths
//const S32 MAX_BUTTON_WIDTH = 150; const S32 MAX_BUTTON_WIDTH = 150;
static LLCachedControl<S32> status_bar_pad("StatusBarPad",10); static LLCachedControl<S32> status_bar_pad("StatusBarPad",10);
S32 usable_bar_width = llclamp(state_buttons_panel->getRect().getWidth(), 0, MAX_BAR_WIDTH) - (view_list.size()-1) * status_bar_pad; S32 segment_width = llclamp(lltrunc((F32)(bar_width) / (F32)button_count), 0, MAX_BUTTON_WIDTH);
F32 element_scale = (F32)usable_bar_width / (F32)required_width; S32 btn_width = segment_width - status_bar_pad;
// Evenly space all buttons, starting from left // Evenly space all buttons, starting from left
S32 left = 0; S32 left = 0;
@@ -266,13 +270,14 @@ void LLOverlayBar::layoutButtons()
BOOST_REVERSE_FOREACH(LLView* viewp, view_list) BOOST_REVERSE_FOREACH(LLView* viewp, view_list)
{ {
if(!viewp->getEnabled())
continue;
LLRect r = viewp->getRect(); LLRect r = viewp->getRect();
S32 new_width = r.getWidth() * element_scale;
//if(dynamic_cast<LLButton*>(viewp)) //if(dynamic_cast<LLButton*>(viewp))
// new_width = llclamp(new_width,0,MAX_BUTTON_WIDTH); // new_width = llclamp(new_width,0,MAX_BUTTON_WIDTH);
r.setOriginAndSize(left, bottom, new_width, r.getHeight()); r.setOriginAndSize(left, bottom, btn_width, r.getHeight());
viewp->setShape(r,false); viewp->setRect(r);
left += viewp->getRect().getWidth() + status_bar_pad; left += segment_width;
} }
} }
} }

View File

@@ -89,6 +89,7 @@
#include <iosfwd> #include <iosfwd>
#include <boost/date_time.hpp>
@@ -269,23 +270,15 @@ void LLPanelAvatarSecondLife::processProperties(void* data, EAvatarProcessorType
getChild<LLTextureCtrl>("img")->setImageAssetID(pAvatarData->image_id); getChild<LLTextureCtrl>("img")->setImageAssetID(pAvatarData->image_id);
//Chalice - Show avatar age in days. // Show avatar age in days.
int year, month, day; {
sscanf(pAvatarData->born_on.c_str(),"%d/%d/%d",&month,&day,&year); using namespace boost::gregorian;
time_t now = time(NULL); int year, month, day;
struct tm * timeinfo; sscanf(pAvatarData->born_on.c_str(),"%d/%d/%d",&month,&day,&year);
timeinfo=localtime(&now); std::ostringstream born_on;
timeinfo->tm_mon = --month; born_on << pAvatarData->born_on << " (" << day_clock::local_day() - date(year, month, day) << ")";
timeinfo->tm_year = year - 1900; childSetValue("born", born_on.str());
timeinfo->tm_mday = day; }
time_t birth = mktime(timeinfo);
std::stringstream NumberString;
NumberString << (difftime(now,birth) / (60*60*24));
std::string born_on = pAvatarData->born_on;
born_on += " (";
born_on += NumberString.str();
born_on += ")";
childSetValue("born", born_on);
bool allow_publish = (pAvatarData->flags & AVATAR_ALLOW_PUBLISH); bool allow_publish = (pAvatarData->flags & AVATAR_ALLOW_PUBLISH);
childSetValue("allow_publish", allow_publish); childSetValue("allow_publish", allow_publish);

View File

@@ -162,10 +162,6 @@ public:
LLLoginRefreshHandler gLoginRefreshHandler; LLLoginRefreshHandler gLoginRefreshHandler;
// <edit>
std::string gFullName;
// </edit>
// helper class that trys to download a URL from a web site and calls a method // helper class that trys to download a URL from a web site and calls a method
// on parent class indicating if the web server is working or not // on parent class indicating if the web server is working or not
class LLIamHereLogin : public LLHTTPClient::ResponderHeadersOnly class LLIamHereLogin : public LLHTTPClient::ResponderHeadersOnly

View File

@@ -41,10 +41,6 @@
class LLUIImage; class LLUIImage;
class LLComboBox; class LLComboBox;
// <edit>
extern std::string gFullName;
// </edit>
class LLPanelLogin: class LLPanelLogin:
public LLPanel, public LLPanel,
public LLViewerMediaObserver public LLViewerMediaObserver
@@ -165,8 +161,4 @@ private:
std::string load_password_from_disk(void); std::string load_password_from_disk(void);
void save_password_to_disk(const char* hashed_password); void save_password_to_disk(const char* hashed_password);
// <edit>
extern std::string gFullName;
// </edit>
#endif #endif

View File

@@ -1,281 +0,0 @@
/**
* @file llpanelpathfindingrebakenavmesh.cpp
* @brief Implementation of llpanelpathfindingrebakenavmesh
* @author Prep@lindenlab.com
*
* $LicenseInfo:firstyear=2012&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2012, 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 "llpanelpathfindingrebakenavmesh.h"
#include <boost/bind.hpp>
#include <boost/signals2.hpp>
#include "llagent.h"
#include "llbutton.h"
#include "llenvmanager.h"
#include "llnotificationsutil.h"
#include "llpanel.h"
#include "llpathfindingmanager.h"
#include "llpathfindingnavmesh.h"
#include "llpathfindingnavmeshstatus.h"
#include "lltoolbar.h"
#include "llviewerregion.h"
#include "llviewerwindow.h"
#include "lluictrlfactory.h"
LLPanelPathfindingRebakeNavmesh* LLPanelPathfindingRebakeNavmesh::getInstance()
{
static LLPanelPathfindingRebakeNavmesh* panel = getPanel();
return panel;
}
BOOL LLPanelPathfindingRebakeNavmesh::postBuild()
{
//Rebake button
mNavMeshRebakeButton = getChild<LLButton>("navmesh_btn");
llassert(mNavMeshRebakeButton != NULL);
mNavMeshRebakeButton->setCommitCallback(boost::bind(&LLPanelPathfindingRebakeNavmesh::onNavMeshRebakeClick, this));
//LLHints::registerHintTarget("navmesh_btn", mNavMeshRebakeButton->getHandle());
//Sending rebake request
mNavMeshSendingButton = findChild<LLButton>("navmesh_btn_sending");
llassert(mNavMeshSendingButton != NULL);
//LLHints::registerHintTarget("navmesh_btn_sending", mNavMeshSendingButton->getHandle());
//rebaking...
mNavMeshBakingButton = findChild<LLButton>("navmesh_btn_baking");
llassert(mNavMeshBakingButton != NULL);
//LLHints::registerHintTarget("navmesh_btn_baking", mNavMeshBakingButton->getHandle());
setMode(kRebakeNavMesh_Default);
createNavMeshStatusListenerForCurrentRegion();
if ( !mRegionCrossingSlot.connected() )
{
mRegionCrossingSlot = LLEnvManagerNew::getInstance()->setRegionChangeCallback(boost::bind(&LLPanelPathfindingRebakeNavmesh::handleRegionBoundaryCrossed, this));
}
if (!mAgentStateSlot.connected())
{
mAgentStateSlot = LLPathfindingManager::getInstance()->registerAgentStateListener(boost::bind(&LLPanelPathfindingRebakeNavmesh::handleAgentState, this, _1));
}
LLPathfindingManager::getInstance()->requestGetAgentState();
return LLPanel::postBuild();
}
void LLPanelPathfindingRebakeNavmesh::draw()
{
if (doDraw())
{
updatePosition();
LLPanel::draw();
}
}
BOOL LLPanelPathfindingRebakeNavmesh::handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect_screen)
{
gViewerWindow->unblockToolTips();
if (mNavMeshRebakeButton->getVisible())
{
msg=mNavMeshRebakeButton->getToolTip();
//LLToolTipMgr::instance().show(mNavMeshRebakeButton->getToolTip());
}
else if (mNavMeshSendingButton->getVisible())
{
msg=mNavMeshSendingButton->getToolTip();
//LLToolTipMgr::instance().show(mNavMeshSendingButton->getToolTip());
}
else if (mNavMeshBakingButton->getVisible())
{
msg=mNavMeshBakingButton->getToolTip();
//LLToolTipMgr::instance().show(mNavMeshBakingButton->getToolTip());
}
// Convert rect local to screen coordinates
localPointToScreen(
0, 0,
&(sticky_rect_screen->mLeft), &(sticky_rect_screen->mBottom) );
localPointToScreen(
getRect().getWidth(), getRect().getHeight(),
&(sticky_rect_screen->mRight), &(sticky_rect_screen->mTop) );
return true;//LLPanel::handleToolTip(x, y, mask);
}
LLPanelPathfindingRebakeNavmesh::LLPanelPathfindingRebakeNavmesh()
: LLPanel(),
mCanRebakeRegion(FALSE),
mRebakeNavMeshMode(kRebakeNavMesh_Default),
mNavMeshRebakeButton(NULL),
mNavMeshSendingButton(NULL),
mNavMeshBakingButton(NULL),
mNavMeshSlot(),
mRegionCrossingSlot(),
mAgentStateSlot()
{
// make sure we have the only instance of this class
static bool b = true;
llassert_always(b);
b=false;
}
LLPanelPathfindingRebakeNavmesh::~LLPanelPathfindingRebakeNavmesh()
{
}
LLPanelPathfindingRebakeNavmesh* LLPanelPathfindingRebakeNavmesh::getPanel()
{
LLPanelPathfindingRebakeNavmesh* panel = new LLPanelPathfindingRebakeNavmesh();
LLUICtrlFactory::getInstance()->buildPanel(panel,"panel_navmesh_rebake.xml");
return panel;
}
void LLPanelPathfindingRebakeNavmesh::setMode(ERebakeNavMeshMode pRebakeNavMeshMode)
{
if (pRebakeNavMeshMode == kRebakeNavMesh_Available)
{
LLNotificationsUtil::add("PathfindingRebakeNavmesh");
}
mNavMeshRebakeButton->setVisible(pRebakeNavMeshMode == kRebakeNavMesh_Available);
mNavMeshSendingButton->setVisible(pRebakeNavMeshMode == kRebakeNavMesh_RequestSent);
mNavMeshBakingButton->setVisible(pRebakeNavMeshMode == kRebakeNavMesh_InProgress);
mRebakeNavMeshMode = pRebakeNavMeshMode;
}
LLPanelPathfindingRebakeNavmesh::ERebakeNavMeshMode LLPanelPathfindingRebakeNavmesh::getMode() const
{
return mRebakeNavMeshMode;
}
void LLPanelPathfindingRebakeNavmesh::onNavMeshRebakeClick()
{
setMode(kRebakeNavMesh_RequestSent);
LLPathfindingManager::getInstance()->requestRebakeNavMesh(boost::bind(&LLPanelPathfindingRebakeNavmesh::handleRebakeNavMeshResponse, this, _1));
}
void LLPanelPathfindingRebakeNavmesh::handleAgentState(BOOL pCanRebakeRegion)
{
mCanRebakeRegion = pCanRebakeRegion;
}
void LLPanelPathfindingRebakeNavmesh::handleRebakeNavMeshResponse(bool pResponseStatus)
{
if (getMode() == kRebakeNavMesh_RequestSent)
{
setMode(pResponseStatus ? kRebakeNavMesh_InProgress : kRebakeNavMesh_Default);
}
if (!pResponseStatus)
{
LLNotificationsUtil::add("PathfindingCannotRebakeNavmesh");
}
}
void LLPanelPathfindingRebakeNavmesh::handleNavMeshStatus(const LLPathfindingNavMeshStatus &pNavMeshStatus)
{
ERebakeNavMeshMode rebakeNavMeshMode = kRebakeNavMesh_Default;
if (pNavMeshStatus.isValid())
{
switch (pNavMeshStatus.getStatus())
{
case LLPathfindingNavMeshStatus::kPending :
case LLPathfindingNavMeshStatus::kRepending :
rebakeNavMeshMode = kRebakeNavMesh_Available;
break;
case LLPathfindingNavMeshStatus::kBuilding :
rebakeNavMeshMode = kRebakeNavMesh_InProgress;
break;
case LLPathfindingNavMeshStatus::kComplete :
rebakeNavMeshMode = kRebakeNavMesh_NotAvailable;
break;
default :
rebakeNavMeshMode = kRebakeNavMesh_Default;
llassert(0);
break;
}
}
setMode(rebakeNavMeshMode);
}
void LLPanelPathfindingRebakeNavmesh::handleRegionBoundaryCrossed()
{
createNavMeshStatusListenerForCurrentRegion();
mCanRebakeRegion = FALSE;
LLPathfindingManager::getInstance()->requestGetAgentState();
}
void LLPanelPathfindingRebakeNavmesh::createNavMeshStatusListenerForCurrentRegion()
{
if (mNavMeshSlot.connected())
{
mNavMeshSlot.disconnect();
}
LLViewerRegion *currentRegion = gAgent.getRegion();
if (currentRegion != NULL)
{
mNavMeshSlot = LLPathfindingManager::getInstance()->registerNavMeshListenerForRegion(currentRegion, boost::bind(&LLPanelPathfindingRebakeNavmesh::handleNavMeshStatus, this, _2));
LLPathfindingManager::getInstance()->requestGetNavMeshForRegion(currentRegion, true);
}
}
bool LLPanelPathfindingRebakeNavmesh::doDraw() const
{
return (mCanRebakeRegion && (mRebakeNavMeshMode != kRebakeNavMesh_NotAvailable));
}
void LLPanelPathfindingRebakeNavmesh::updatePosition()
{
#if 0
S32 y_pos = 0;
S32 bottom_tb_center = 0;
if (LLToolBar* toolbar_bottom = gToolBarView->getChild<LLToolBar>("toolbar_bottom"))
{
y_pos = toolbar_bottom->getRect().getHeight();
bottom_tb_center = toolbar_bottom->getRect().getCenterX();
}
S32 left_tb_width = 0;
if (LLToolBar* toolbar_left = gToolBarView->getChild<LLToolBar>("toolbar_left"))
{
left_tb_width = toolbar_left->getRect().getWidth();
}
if(LLPanel* panel_ssf_container = getRootView()->getChild<LLPanel>("state_management_buttons_container"))
{
panel_ssf_container->setOrigin(0, y_pos);
}
S32 x_pos = bottom_tb_center-getRect().getWidth()/2 - left_tb_width + 113 /* width of stand/fly button *//* + 10 *//* margin */;
/*setOrigin( x_pos, 0);*/
#endif
}

View File

@@ -39,6 +39,7 @@
#define LINKSET_MODIFIABLE_FIELD "modifiable" #define LINKSET_MODIFIABLE_FIELD "modifiable"
#define LINKSET_CATEGORY_FIELD "navmesh_category" #define LINKSET_CATEGORY_FIELD "navmesh_category"
#define LINKSET_CAN_BE_VOLUME "can_be_volume" #define LINKSET_CAN_BE_VOLUME "can_be_volume"
#define LINKSET_IS_SCRIPTED_FIELD "is_scripted"
#define LINKSET_PHANTOM_FIELD "phantom" #define LINKSET_PHANTOM_FIELD "phantom"
#define LINKSET_WALKABILITY_A_FIELD "A" #define LINKSET_WALKABILITY_A_FIELD "A"
#define LINKSET_WALKABILITY_B_FIELD "B" #define LINKSET_WALKABILITY_B_FIELD "B"
@@ -62,6 +63,8 @@ LLPathfindingLinkset::LLPathfindingLinkset(const LLSD& pTerrainData)
mLandImpact(0U), mLandImpact(0U),
mIsModifiable(FALSE), mIsModifiable(FALSE),
mCanBeVolume(FALSE), mCanBeVolume(FALSE),
mIsScripted(FALSE),
mHasIsScripted(TRUE),
mLinksetUse(kUnknown), mLinksetUse(kUnknown),
mWalkabilityCoefficientA(MIN_WALKABILITY_VALUE), mWalkabilityCoefficientA(MIN_WALKABILITY_VALUE),
mWalkabilityCoefficientB(MIN_WALKABILITY_VALUE), mWalkabilityCoefficientB(MIN_WALKABILITY_VALUE),
@@ -77,6 +80,8 @@ LLPathfindingLinkset::LLPathfindingLinkset(const std::string &pUUID, const LLSD&
mLandImpact(0U), mLandImpact(0U),
mIsModifiable(TRUE), mIsModifiable(TRUE),
mCanBeVolume(TRUE), mCanBeVolume(TRUE),
mIsScripted(FALSE),
mHasIsScripted(FALSE),
mLinksetUse(kUnknown), mLinksetUse(kUnknown),
mWalkabilityCoefficientA(MIN_WALKABILITY_VALUE), mWalkabilityCoefficientA(MIN_WALKABILITY_VALUE),
mWalkabilityCoefficientB(MIN_WALKABILITY_VALUE), mWalkabilityCoefficientB(MIN_WALKABILITY_VALUE),
@@ -93,6 +98,8 @@ LLPathfindingLinkset::LLPathfindingLinkset(const LLPathfindingLinkset& pOther)
mLandImpact(pOther.mLandImpact), mLandImpact(pOther.mLandImpact),
mIsModifiable(pOther.mIsModifiable), mIsModifiable(pOther.mIsModifiable),
mCanBeVolume(pOther.mCanBeVolume), mCanBeVolume(pOther.mCanBeVolume),
mIsScripted(pOther.mIsScripted),
mHasIsScripted(pOther.mHasIsScripted),
mLinksetUse(pOther.mLinksetUse), mLinksetUse(pOther.mLinksetUse),
mWalkabilityCoefficientA(pOther.mWalkabilityCoefficientA), mWalkabilityCoefficientA(pOther.mWalkabilityCoefficientA),
mWalkabilityCoefficientB(pOther.mWalkabilityCoefficientB), mWalkabilityCoefficientB(pOther.mWalkabilityCoefficientB),
@@ -113,6 +120,8 @@ LLPathfindingLinkset& LLPathfindingLinkset::operator =(const LLPathfindingLinkse
mLandImpact = pOther.mLandImpact; mLandImpact = pOther.mLandImpact;
mIsModifiable = pOther.mIsModifiable; mIsModifiable = pOther.mIsModifiable;
mCanBeVolume = pOther.mCanBeVolume; mCanBeVolume = pOther.mCanBeVolume;
mIsScripted = pOther.mIsScripted;
mHasIsScripted = pOther.mHasIsScripted;
mLinksetUse = pOther.mLinksetUse; mLinksetUse = pOther.mLinksetUse;
mWalkabilityCoefficientA = pOther.mWalkabilityCoefficientA; mWalkabilityCoefficientA = pOther.mWalkabilityCoefficientA;
mWalkabilityCoefficientB = pOther.mWalkabilityCoefficientB; mWalkabilityCoefficientB = pOther.mWalkabilityCoefficientB;
@@ -140,6 +149,11 @@ bool LLPathfindingLinkset::isShowUnmodifiablePhantomWarning(ELinksetUse pLinkset
return (!isModifiable() && (isPhantom() != isPhantom(pLinksetUse))); return (!isModifiable() && (isPhantom() != isPhantom(pLinksetUse)));
} }
bool LLPathfindingLinkset::isShowPhantomToggleWarning(ELinksetUse pLinksetUse) const
{
return (isModifiable() && (isPhantom() != isPhantom(pLinksetUse)));
}
bool LLPathfindingLinkset::isShowCannotBeVolumeWarning(ELinksetUse pLinksetUse) const bool LLPathfindingLinkset::isShowCannotBeVolumeWarning(ELinksetUse pLinksetUse) const
{ {
return (!canBeVolume() && ((pLinksetUse == kMaterialVolume) || (pLinksetUse == kExclusionVolume))); return (!canBeVolume() && ((pLinksetUse == kMaterialVolume) || (pLinksetUse == kExclusionVolume)));
@@ -193,6 +207,13 @@ void LLPathfindingLinkset::parseLinksetData(const LLSD &pLinksetData)
llassert(pLinksetData.has(LINKSET_MODIFIABLE_FIELD)); llassert(pLinksetData.has(LINKSET_MODIFIABLE_FIELD));
llassert(pLinksetData.get(LINKSET_MODIFIABLE_FIELD).isBoolean()); llassert(pLinksetData.get(LINKSET_MODIFIABLE_FIELD).isBoolean());
mIsModifiable = pLinksetData.get(LINKSET_MODIFIABLE_FIELD).asBoolean(); mIsModifiable = pLinksetData.get(LINKSET_MODIFIABLE_FIELD).asBoolean();
mHasIsScripted = pLinksetData.has(LINKSET_IS_SCRIPTED_FIELD);
if (mHasIsScripted)
{
llassert(pLinksetData.get(LINKSET_IS_SCRIPTED_FIELD).isBoolean());
mIsScripted = pLinksetData.get(LINKSET_IS_SCRIPTED_FIELD).asBoolean();
}
} }
void LLPathfindingLinkset::parsePathfindingData(const LLSD &pLinksetData) void LLPathfindingLinkset::parsePathfindingData(const LLSD &pLinksetData)

View File

@@ -63,12 +63,16 @@ public:
inline ELinksetUse getLinksetUse() const {return mLinksetUse;}; inline ELinksetUse getLinksetUse() const {return mLinksetUse;};
inline BOOL isScripted() const {return mIsScripted;};
inline BOOL hasIsScripted() const {return mHasIsScripted;};
inline S32 getWalkabilityCoefficientA() const {return mWalkabilityCoefficientA;}; inline S32 getWalkabilityCoefficientA() const {return mWalkabilityCoefficientA;};
inline S32 getWalkabilityCoefficientB() const {return mWalkabilityCoefficientB;}; inline S32 getWalkabilityCoefficientB() const {return mWalkabilityCoefficientB;};
inline S32 getWalkabilityCoefficientC() const {return mWalkabilityCoefficientC;}; inline S32 getWalkabilityCoefficientC() const {return mWalkabilityCoefficientC;};
inline S32 getWalkabilityCoefficientD() const {return mWalkabilityCoefficientD;}; inline S32 getWalkabilityCoefficientD() const {return mWalkabilityCoefficientD;};
bool isShowUnmodifiablePhantomWarning(ELinksetUse pLinksetUse) const; bool isShowUnmodifiablePhantomWarning(ELinksetUse pLinksetUse) const;
bool isShowPhantomToggleWarning(ELinksetUse pLinksetUse) const;
bool isShowCannotBeVolumeWarning(ELinksetUse pLinksetUse) const; bool isShowCannotBeVolumeWarning(ELinksetUse pLinksetUse) const;
LLSD encodeAlteredFields(ELinksetUse pLinksetUse, S32 pA, S32 pB, S32 pC, S32 pD) const; LLSD encodeAlteredFields(ELinksetUse pLinksetUse, S32 pA, S32 pB, S32 pC, S32 pD) const;
@@ -98,6 +102,8 @@ private:
U32 mLandImpact; U32 mLandImpact;
BOOL mIsModifiable; BOOL mIsModifiable;
BOOL mCanBeVolume; BOOL mCanBeVolume;
BOOL mIsScripted;
BOOL mHasIsScripted;
ELinksetUse mLinksetUse; ELinksetUse mLinksetUse;
S32 mWalkabilityCoefficientA; S32 mWalkabilityCoefficientA;
S32 mWalkabilityCoefficientB; S32 mWalkabilityCoefficientB;

View File

@@ -113,6 +113,20 @@ bool LLPathfindingLinksetList::isShowUnmodifiablePhantomWarning(LLPathfindingLin
return isShowWarning; return isShowWarning;
} }
bool LLPathfindingLinksetList::isShowPhantomToggleWarning(LLPathfindingLinkset::ELinksetUse pLinksetUse) const
{
bool isShowWarning = false;
for (const_iterator objectIter = begin(); !isShowWarning && (objectIter != end()); ++objectIter)
{
const LLPathfindingObjectPtr objectPtr = objectIter->second;
const LLPathfindingLinkset *linkset = dynamic_cast<const LLPathfindingLinkset *>(objectPtr.get());
isShowWarning = linkset->isShowPhantomToggleWarning(pLinksetUse);
}
return isShowWarning;
}
bool LLPathfindingLinksetList::isShowCannotBeVolumeWarning(LLPathfindingLinkset::ELinksetUse pLinksetUse) const bool LLPathfindingLinksetList::isShowCannotBeVolumeWarning(LLPathfindingLinkset::ELinksetUse pLinksetUse) const
{ {
bool isShowWarning = false; bool isShowWarning = false;

View File

@@ -43,6 +43,7 @@ public:
LLSD encodeTerrainFields(LLPathfindingLinkset::ELinksetUse pLinksetUse, S32 pA, S32 pB, S32 pC, S32 pD) const; LLSD encodeTerrainFields(LLPathfindingLinkset::ELinksetUse pLinksetUse, S32 pA, S32 pB, S32 pC, S32 pD) const;
bool isShowUnmodifiablePhantomWarning(LLPathfindingLinkset::ELinksetUse pLinksetUse) const; bool isShowUnmodifiablePhantomWarning(LLPathfindingLinkset::ELinksetUse pLinksetUse) const;
bool isShowPhantomToggleWarning(LLPathfindingLinkset::ELinksetUse pLinksetUse) const;
bool isShowCannotBeVolumeWarning(LLPathfindingLinkset::ELinksetUse pLinksetUse) const; bool isShowCannotBeVolumeWarning(LLPathfindingLinkset::ELinksetUse pLinksetUse) const;
void determinePossibleStates(BOOL &pCanBeWalkable, BOOL &pCanBeStaticObstacle, BOOL &pCanBeDynamicObstacle, void determinePossibleStates(BOOL &pCanBeWalkable, BOOL &pCanBeStaticObstacle, BOOL &pCanBeDynamicObstacle,

View File

@@ -55,8 +55,10 @@ LLPathfindingObject::LLPathfindingObject()
mOwnerUUID(), mOwnerUUID(),
mHasOwnerName(false), mHasOwnerName(false),
mOwnerName(), mOwnerName(),
mAvatarNameCacheConnection(),
mIsGroupOwned(false), mIsGroupOwned(false),
mLocation() mLocation(),
mOwnerNameSignal()
{ {
} }
@@ -67,8 +69,10 @@ LLPathfindingObject::LLPathfindingObject(const std::string &pUUID, const LLSD &p
mOwnerUUID(), mOwnerUUID(),
mHasOwnerName(false), mHasOwnerName(false),
mOwnerName(), mOwnerName(),
mAvatarNameCacheConnection(),
mIsGroupOwned(false), mIsGroupOwned(false),
mLocation() mLocation(),
mOwnerNameSignal()
{ {
parseObjectData(pObjectData); parseObjectData(pObjectData);
} }
@@ -80,14 +84,17 @@ LLPathfindingObject::LLPathfindingObject(const LLPathfindingObject& pOther)
mOwnerUUID(pOther.mOwnerUUID), mOwnerUUID(pOther.mOwnerUUID),
mHasOwnerName(false), mHasOwnerName(false),
mOwnerName(), mOwnerName(),
mAvatarNameCacheConnection(),
mIsGroupOwned(pOther.mIsGroupOwned), mIsGroupOwned(pOther.mIsGroupOwned),
mLocation(pOther.mLocation) mLocation(pOther.mLocation),
mOwnerNameSignal()
{ {
fetchOwnerName(); fetchOwnerName();
} }
LLPathfindingObject::~LLPathfindingObject() LLPathfindingObject::~LLPathfindingObject()
{ {
disconnectAvatarNameCacheConnection();
} }
LLPathfindingObject &LLPathfindingObject::operator =(const LLPathfindingObject& pOther) LLPathfindingObject &LLPathfindingObject::operator =(const LLPathfindingObject& pOther)
@@ -115,6 +122,23 @@ std::string LLPathfindingObject::getOwnerName() const
return ownerName; return ownerName;
} }
LLPathfindingObject::name_connection_t LLPathfindingObject::registerOwnerNameListener(name_callback_t pOwnerNameCallback)
{
llassert(hasOwner());
name_connection_t connection;
if (hasOwnerName())
{
pOwnerNameCallback(this);
}
else
{
connection = mOwnerNameSignal.connect(pOwnerNameCallback);
}
return connection;
}
void LLPathfindingObject::parseObjectData(const LLSD &pObjectData) void LLPathfindingObject::parseObjectData(const LLSD &pObjectData)
{ {
llassert(pObjectData.has(PATHFINDING_OBJECT_NAME_FIELD)); llassert(pObjectData.has(PATHFINDING_OBJECT_NAME_FIELD));
@@ -149,7 +173,7 @@ void LLPathfindingObject::fetchOwnerName()
mHasOwnerName = LLAvatarNameCache::get(mOwnerUUID, &mOwnerName); mHasOwnerName = LLAvatarNameCache::get(mOwnerUUID, &mOwnerName);
if (!mHasOwnerName) if (!mHasOwnerName)
{ {
LLAvatarNameCache::get(mOwnerUUID, boost::bind(&LLPathfindingObject::handleAvatarNameFetch, this, _1, _2)); mAvatarNameCacheConnection = LLAvatarNameCache::get(mOwnerUUID, boost::bind(&LLPathfindingObject::handleAvatarNameFetch, this, _1, _2));
} }
} }
} }
@@ -157,6 +181,19 @@ void LLPathfindingObject::fetchOwnerName()
void LLPathfindingObject::handleAvatarNameFetch(const LLUUID &pOwnerUUID, const LLAvatarName &pAvatarName) void LLPathfindingObject::handleAvatarNameFetch(const LLUUID &pOwnerUUID, const LLAvatarName &pAvatarName)
{ {
llassert(mOwnerUUID == pOwnerUUID); llassert(mOwnerUUID == pOwnerUUID);
mOwnerName = pAvatarName; mOwnerName = pAvatarName;
mHasOwnerName = true; mHasOwnerName = true;
disconnectAvatarNameCacheConnection();
mOwnerNameSignal(this);
}
void LLPathfindingObject::disconnectAvatarNameCacheConnection()
{
if (mAvatarNameCacheConnection.connected())
{
mAvatarNameCacheConnection.disconnect();
}
} }

View File

@@ -30,8 +30,11 @@
#include <string> #include <string>
#include <boost/shared_ptr.hpp> #include <boost/shared_ptr.hpp>
#include <boost/function.hpp>
#include <boost/signals2.hpp>
#include "llavatarname.h" #include "llavatarname.h"
#include "llavatarnamecache.h"
#include "lluuid.h" #include "lluuid.h"
#include "v3math.h" #include "v3math.h"
@@ -59,6 +62,12 @@ public:
inline BOOL isGroupOwned() const {return mIsGroupOwned;}; inline BOOL isGroupOwned() const {return mIsGroupOwned;};
inline const LLVector3& getLocation() const {return mLocation;}; inline const LLVector3& getLocation() const {return mLocation;};
typedef boost::function<void (const LLPathfindingObject *)> name_callback_t;
typedef boost::signals2::signal<void (const LLPathfindingObject *)> name_signal_t;
typedef boost::signals2::connection name_connection_t;
name_connection_t registerOwnerNameListener(name_callback_t pOwnerNameCallback);
protected: protected:
private: private:
@@ -66,15 +75,18 @@ private:
void fetchOwnerName(); void fetchOwnerName();
void handleAvatarNameFetch(const LLUUID &pOwnerUUID, const LLAvatarName &pAvatarName); void handleAvatarNameFetch(const LLUUID &pOwnerUUID, const LLAvatarName &pAvatarName);
void disconnectAvatarNameCacheConnection();
LLUUID mUUID; LLUUID mUUID;
std::string mName; std::string mName;
std::string mDescription; std::string mDescription;
LLUUID mOwnerUUID; LLUUID mOwnerUUID;
bool mHasOwnerName; bool mHasOwnerName;
LLAvatarName mOwnerName; LLAvatarName mOwnerName;
BOOL mIsGroupOwned; LLAvatarNameCache::callback_connection_t mAvatarNameCacheConnection;
LLVector3 mLocation; BOOL mIsGroupOwned;
LLVector3 mLocation;
name_signal_t mOwnerNameSignal;
}; };
#endif // LL_LLPATHFINDINGOBJECT_H #endif // LL_LLPATHFINDINGOBJECT_H

View File

@@ -45,6 +45,7 @@ LLPathfindingObjectList::LLPathfindingObjectList()
LLPathfindingObjectList::~LLPathfindingObjectList() LLPathfindingObjectList::~LLPathfindingObjectList()
{ {
clear();
} }
bool LLPathfindingObjectList::isEmpty() const bool LLPathfindingObjectList::isEmpty() const
@@ -52,6 +53,15 @@ bool LLPathfindingObjectList::isEmpty() const
return mObjectMap.empty(); return mObjectMap.empty();
} }
void LLPathfindingObjectList::clear()
{
for (LLPathfindingObjectMap::iterator objectIter = mObjectMap.begin(); objectIter != mObjectMap.end(); ++objectIter)
{
objectIter->second.reset();
}
mObjectMap.clear();
}
void LLPathfindingObjectList::update(LLPathfindingObjectPtr pUpdateObjectPtr) void LLPathfindingObjectList::update(LLPathfindingObjectPtr pUpdateObjectPtr)
{ {
if (pUpdateObjectPtr != NULL) if (pUpdateObjectPtr != NULL)

View File

@@ -47,6 +47,8 @@ public:
bool isEmpty() const; bool isEmpty() const;
void clear();
void update(LLPathfindingObjectPtr pUpdateObjectPtr); void update(LLPathfindingObjectPtr pUpdateObjectPtr);
void update(LLPathfindingObjectListPtr pUpdateObjectListPtr); void update(LLPathfindingObjectListPtr pUpdateObjectListPtr);
@@ -56,7 +58,6 @@ public:
const_iterator begin() const; const_iterator begin() const;
const_iterator end() const; const_iterator end() const;
protected: protected:
LLPathfindingObjectMap &getObjectMap(); LLPathfindingObjectMap &getObjectMap();

View File

@@ -4418,6 +4418,10 @@ public:
} }
} }
else if (avatar->isLangolier())
{
skip_check = true;
}
} }
if (!skip_check && vobj->lineSegmentIntersect(mStart, mEnd, -1, mPickTransparent, mFaceHit, &intersection, mTexCoord, mNormal, mBinormal)) if (!skip_check && vobj->lineSegmentIntersect(mStart, mEnd, -1, mPickTransparent, mFaceHit, &intersection, mTexCoord, mNormal, mBinormal))

View File

@@ -757,9 +757,6 @@ bool idle_startup()
// We have at least some login information on a SLURL // We have at least some login information on a SLURL
firstname = gLoginHandler.getFirstName(); firstname = gLoginHandler.getFirstName();
lastname = gLoginHandler.getLastName(); lastname = gLoginHandler.getLastName();
// <edit>
gFullName = utf8str_tolower(firstname + " " + lastname);
// </edit>
web_login_key = gLoginHandler.getWebLoginKey(); web_login_key = gLoginHandler.getWebLoginKey();
// Show the login screen if we don't have everything // Show the login screen if we don't have everything
@@ -771,9 +768,6 @@ bool idle_startup()
LLSD cmd_line_login = gSavedSettings.getLLSD("UserLoginInfo"); LLSD cmd_line_login = gSavedSettings.getLLSD("UserLoginInfo");
firstname = cmd_line_login[0].asString(); firstname = cmd_line_login[0].asString();
lastname = cmd_line_login[1].asString(); lastname = cmd_line_login[1].asString();
// <edit>
gFullName = utf8str_tolower(firstname + " " + lastname);
// </edit>
LLMD5 pass((unsigned char*)cmd_line_login[2].asString().c_str()); LLMD5 pass((unsigned char*)cmd_line_login[2].asString().c_str());
char md5pass[33]; /* Flawfinder: ignore */ char md5pass[33]; /* Flawfinder: ignore */
@@ -791,9 +785,6 @@ bool idle_startup()
{ {
firstname = gSavedSettings.getString("FirstName"); firstname = gSavedSettings.getString("FirstName");
lastname = gSavedSettings.getString("LastName"); lastname = gSavedSettings.getString("LastName");
// <edit>
gFullName = utf8str_tolower(firstname + " " + lastname);
// </edit>
password = LLStartUp::loadPasswordFromDisk(); password = LLStartUp::loadPasswordFromDisk();
gSavedSettings.setBOOL("RememberPassword", TRUE); gSavedSettings.setBOOL("RememberPassword", TRUE);
@@ -809,9 +800,6 @@ bool idle_startup()
// a valid grid is selected // a valid grid is selected
firstname = gSavedSettings.getString("FirstName"); firstname = gSavedSettings.getString("FirstName");
lastname = gSavedSettings.getString("LastName"); lastname = gSavedSettings.getString("LastName");
// <edit>
gFullName = utf8str_tolower(firstname + " " + lastname);
// </edit>
password = LLStartUp::loadPasswordFromDisk(); password = LLStartUp::loadPasswordFromDisk();
show_connect_box = true; show_connect_box = true;
} }
@@ -895,9 +883,6 @@ bool idle_startup()
else else
{ {
LLPanelLogin::setFields(firstname, lastname, password); LLPanelLogin::setFields(firstname, lastname, password);
// <edit>
gFullName = utf8str_tolower(firstname + " " + lastname);
// </edit>
LLPanelLogin::giveFocus(); LLPanelLogin::giveFocus();
} }
display_startup(); display_startup();
@@ -969,9 +954,6 @@ bool idle_startup()
{ {
firstname = gLoginHandler.getFirstName(); firstname = gLoginHandler.getFirstName();
lastname = gLoginHandler.getLastName(); lastname = gLoginHandler.getLastName();
// <edit>
gFullName = utf8str_tolower(firstname + " " + lastname);
// </edit>
web_login_key = gLoginHandler.getWebLoginKey(); web_login_key = gLoginHandler.getWebLoginKey();
} }
@@ -990,15 +972,21 @@ bool idle_startup()
{ {
gSavedSettings.setString("FirstName", firstname); gSavedSettings.setString("FirstName", firstname);
gSavedSettings.setString("LastName", lastname); gSavedSettings.setString("LastName", lastname);
// <edit>
gFullName = utf8str_tolower(firstname + " " + lastname);
// </edit>
if (!gSavedSettings.controlExists("RememberLogin")) gSavedSettings.declareBOOL("RememberLogin", false, "Remember login", false); if (!gSavedSettings.controlExists("RememberLogin")) gSavedSettings.declareBOOL("RememberLogin", false, "Remember login", false);
gSavedSettings.setBOOL("RememberLogin", LLPanelLogin::getRememberLogin()); gSavedSettings.setBOOL("RememberLogin", LLPanelLogin::getRememberLogin());
LL_INFOS("AppInit") << "Attempting login as: " << firstname << " " << lastname << LL_ENDL; LL_INFOS("AppInit") << "Attempting login as: " << firstname << " " << lastname << LL_ENDL;
gDebugInfo["LoginName"] = firstname + " " + lastname; gDebugInfo["LoginName"] = firstname + " " + lastname;
} }
else
{
// User tried to login on a non-SecondLife grid with an empty lastname.
LLSD subs;
subs["GRIDNAME"] = gHippoGridManager->getConnectedGrid()->getGridName();
LLNotificationsUtil::add(firstname.empty() ? "EmptyFirstNameMessage" : "EmptyLastNameMessage", subs);
LLStartUp::setStartupState(STATE_LOGIN_SHOW);
return FALSE;
}
LLScriptEdCore::parseFunctions("lsl_functions_sl.xml"); //Singu Note: This parsing function essentially replaces the entirety of the lscript_library library LLScriptEdCore::parseFunctions("lsl_functions_sl.xml"); //Singu Note: This parsing function essentially replaces the entirety of the lscript_library library
@@ -4103,9 +4091,6 @@ bool process_login_success_response(std::string& password)
if(!text.empty()) lastname.assign(text); if(!text.empty()) lastname.assign(text);
gSavedSettings.setString("FirstName", firstname); gSavedSettings.setString("FirstName", firstname);
gSavedSettings.setString("LastName", lastname); gSavedSettings.setString("LastName", lastname);
// <edit>
gFullName = utf8str_tolower(firstname + " " + lastname);
// </edit>
if (gSavedSettings.getBOOL("RememberPassword")) if (gSavedSettings.getBOOL("RememberPassword"))
{ {

View File

@@ -725,11 +725,9 @@ void LLStatusBar::setHealth(S32 health)
{ {
if (mHealth > (health + gSavedSettings.getF32("UISndHealthReductionThreshold"))) if (mHealth > (health + gSavedSettings.getF32("UISndHealthReductionThreshold")))
{ {
LLVOAvatar *me; if (isAgentAvatarValid())
if ((me = gAgentAvatarp))
{ {
if (me->getSex() == SEX_FEMALE) if (gAgentAvatarp->getSex() == SEX_FEMALE)
{ {
make_ui_sound("UISndHealthReductionF"); make_ui_sound("UISndHealthReductionF");
} }

View File

@@ -253,8 +253,11 @@ void audio_update_wind(bool force_update)
// which is sufficient to completely turn off or turn on wind noise // which is sufficient to completely turn off or turn on wind noise
volume_delta = 1.f; volume_delta = 1.f;
} }
// mute wind entirely when the user asked
if (gSavedSettings.getBOOL("MuteWind")) static LLCachedControl<bool> MuteWind("MuteWind");
static LLCachedControl<bool> ContinueFlying("LiruContinueFlyingOnUnsit");
// mute wind entirely when the user asked or when the user is seated, but flying
if (MuteWind || (ContinueFlying && gAgentAvatarp&& gAgentAvatarp->isSitting()))
{ {
// volume decreases by itself // volume decreases by itself
gAudiop->mMaxWindGain = 0.f; gAudiop->mMaxWindGain = 0.f;

View File

@@ -188,7 +188,8 @@ void display_update_camera(bool tiling=false)
// Cut draw distance in half when customizing avatar, // Cut draw distance in half when customizing avatar,
// but on the viewer only. // but on the viewer only.
F32 final_far = gAgentCamera.mDrawDistance; F32 final_far = gAgentCamera.mDrawDistance;
if(tiling) //Don't animate clouds and water if tiling! static const LLCachedControl<bool> freeze_time("FreezeTime",false);
if(freeze_time || tiling) //Don't animate clouds and water if tiling!
{ {
LLViewerCamera::getInstance()->setFar(final_far); LLViewerCamera::getInstance()->setFar(final_far);
gViewerWindow->setup3DRender(); gViewerWindow->setup3DRender();
@@ -426,13 +427,22 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot, boo
const std::string& message = gAgent.getTeleportMessage(); const std::string& message = gAgent.getTeleportMessage();
switch( gAgent.getTeleportState() ) switch( gAgent.getTeleportState() )
{ {
case LLAgent::TELEPORT_PENDING:
gTeleportDisplayTimer.reset();
if(!hide_tp_screen)
gViewerWindow->setShowProgress(TRUE);
gViewerWindow->setProgressPercent(llmin(teleport_percent, 0.0f));
gAgent.setTeleportMessage(LLAgent::sTeleportProgressMessages["pending"]);
gViewerWindow->setProgressString(LLAgent::sTeleportProgressMessages["pending"]);
break;
case LLAgent::TELEPORT_START: case LLAgent::TELEPORT_START:
// Transition to REQUESTED. Viewer has sent some kind // Transition to REQUESTED. Viewer has sent some kind
// of TeleportRequest to the source simulator // of TeleportRequest to the source simulator
gTeleportDisplayTimer.reset(); gTeleportDisplayTimer.reset();
if(!hide_tp_screen) if(!hide_tp_screen)
gViewerWindow->setShowProgress(TRUE); gViewerWindow->setShowProgress(TRUE);
gViewerWindow->setProgressPercent(0); gViewerWindow->setProgressPercent(llmin(teleport_percent, 0.0f));
gAgent.setTeleportState( LLAgent::TELEPORT_REQUESTED ); gAgent.setTeleportState( LLAgent::TELEPORT_REQUESTED );
gAgent.setTeleportMessage( gAgent.setTeleportMessage(
LLAgent::sTeleportProgressMessages["requesting"]); LLAgent::sTeleportProgressMessages["requesting"]);

View File

@@ -55,6 +55,7 @@
#include "llwindow.h" #include "llwindow.h"
#include "llvieweraudio.h" #include "llvieweraudio.h"
#include "llweb.h" #include "llweb.h"
#include "llwebprofile.h"
#include "llfloateravatarinfo.h" // for getProfileURL() function #include "llfloateravatarinfo.h" // for getProfileURL() function
//#include "viewerversion.h" //#include "viewerversion.h"
@@ -140,12 +141,7 @@ public:
{ {
LL_DEBUGS("MediaAuth") << "status = " << status << ", reason = " << reason << LL_ENDL; LL_DEBUGS("MediaAuth") << "status = " << status << ", reason = " << reason << LL_ENDL;
LL_DEBUGS("MediaAuth") << headers << LL_ENDL; LL_DEBUGS("MediaAuth") << headers << LL_ENDL;
AIHTTPReceivedHeaders::range_type cookies; LLViewerMedia::openIDCookieResponse(get_cookie("agni_sl_session_id"));
if (headers.getValues("set-cookie", cookies))
{
for (AIHTTPReceivedHeaders::iterator_type cookie = cookies.first; cookie != cookies.second; ++cookie)
LLViewerMedia::openIDCookieResponse(cookie->second);
}
} }
/* virtual */ void completedRaw( /* virtual */ void completedRaw(
@@ -182,11 +178,29 @@ public:
LL_INFOS("MediaAuth") << "status = " << status << ", reason = " << reason << LL_ENDL; LL_INFOS("MediaAuth") << "status = " << status << ", reason = " << reason << LL_ENDL;
LL_INFOS("MediaAuth") << headers << LL_ENDL; LL_INFOS("MediaAuth") << headers << LL_ENDL;
bool found = false;
AIHTTPReceivedHeaders::range_type cookies; AIHTTPReceivedHeaders::range_type cookies;
if (headers.getValues("set-cookie", cookies)) if (headers.getValues("set-cookie", cookies))
{ {
for (AIHTTPReceivedHeaders::iterator_type cookie = cookies.first; cookie != cookies.second; ++cookie) for (AIHTTPReceivedHeaders::iterator_type cookie = cookies.first; cookie != cookies.second; ++cookie)
{
LLViewerMedia::getCookieStore()->setCookiesFromHost(cookie->second, mHost); LLViewerMedia::getCookieStore()->setCookiesFromHost(cookie->second, mHost);
std::string key = cookie->second.substr(0, cookie->second.find('='));
if (key == "_my_secondlife_session")
{
// Set cookie for snapshot publishing.
std::string auth_cookie = cookie->second.substr(0, cookie->second.find(";")); // strip path
LL_INFOS("MediaAuth") << "Setting openID auth cookie \"" << auth_cookie << "\"." << LL_ENDL;
LLWebProfile::setAuthCookie(auth_cookie);
found = true;
break;
}
}
}
if (!found)
{
llwarns << "LLViewerMediaWebProfileResponder did not receive a session ID cookie \"_my_secondlife_session\"! OpenID authentications will fail!" << llendl;
} }
} }

View File

@@ -178,14 +178,16 @@
#include "llinventorypanel.h" #include "llinventorypanel.h"
#include "llinventorybridge.h" #include "llinventorybridge.h"
#include "llkeyboard.h" #include "llkeyboard.h"
#include "llpanellogin.h" #include "llmakeoutfitdialog.h"
#include "llmenucommands.h" #include "llmenucommands.h"
#include "llmenugl.h" #include "llmenugl.h"
#include "llmimetypes.h" #include "llmimetypes.h"
#include "llmorphview.h" #include "llmorphview.h"
#include "llmenuoptionpathfindingrebakenavmesh.h"
#include "llmoveview.h" #include "llmoveview.h"
#include "llmutelist.h" #include "llmutelist.h"
#include "llnotify.h" #include "llnotify.h"
#include "llpanellogin.h"
#include "llpanelobject.h" #include "llpanelobject.h"
#include "llparcel.h" #include "llparcel.h"
@@ -5327,6 +5329,39 @@ class LLToolsEnablePathfindingView : public view_listener_t
} }
}; };
class LLToolsDoPathfindingRebakeRegion : public view_listener_t
{
bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
{
bool hasPathfinding = (LLPathfindingManager::getInstance() != NULL);
if (hasPathfinding)
{
LLMenuOptionPathfindingRebakeNavmesh::getInstance()->sendRequestRebakeNavmesh();
}
return hasPathfinding;
}
};
class LLToolsEnablePathfindingRebakeRegion : public view_listener_t
{
bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
{
bool returnValue = false;
if (LLPathfindingManager::getInstance() != NULL)
{
LLMenuOptionPathfindingRebakeNavmesh *rebakeInstance = LLMenuOptionPathfindingRebakeNavmesh::getInstance();
returnValue = (rebakeInstance->canRebakeRegion() &&
(rebakeInstance->getMode() == LLMenuOptionPathfindingRebakeNavmesh::kRebakeNavMesh_Available));
}
gMenuHolder->findControl(userdata["control"].asString())->setValue(returnValue);
return returnValue;
}
};
// Round the position of all root objects to the grid // Round the position of all root objects to the grid
class LLToolsSnapObjectXY : public view_listener_t class LLToolsSnapObjectXY : public view_listener_t
{ {
@@ -6490,6 +6525,10 @@ class LLShowFloater : public view_listener_t
gAgentCamera.changeCameraToCustomizeAvatar(); gAgentCamera.changeCameraToCustomizeAvatar();
} }
} }
else if (floater_name == "outfit")
{
new LLMakeOutfitDialog(false);
}
// Phoenix: Wolfspirit: Enabled Show Floater out of viewer menu // Phoenix: Wolfspirit: Enabled Show Floater out of viewer menu
else if (floater_name == "displayname") else if (floater_name == "displayname")
{ {
@@ -9511,7 +9550,8 @@ void initialize_menus()
addMenu(new LLToolsEnablePathfinding(), "Tools.EnablePathfinding"); addMenu(new LLToolsEnablePathfinding(), "Tools.EnablePathfinding");
addMenu(new LLToolsEnablePathfindingView(), "Tools.EnablePathfindingView"); addMenu(new LLToolsEnablePathfindingView(), "Tools.EnablePathfindingView");
addMenu(new LLToolsDoPathfindingRebakeRegion(), "Tools.DoPathfindingRebakeRegion");
addMenu(new LLToolsEnablePathfindingRebakeRegion(), "Tools.EnablePathfindingRebakeRegion");
/*addMenu(new LLToolsVisibleBuyObject(), "Tools.VisibleBuyObject"); /*addMenu(new LLToolsVisibleBuyObject(), "Tools.VisibleBuyObject");
addMenu(new LLToolsVisibleTakeObject(), "Tools.VisibleTakeObject");*/ addMenu(new LLToolsVisibleTakeObject(), "Tools.VisibleTakeObject");*/

View File

@@ -527,6 +527,7 @@ class LLFileTakeSnapshotToDisk : public view_listener_t
S32 width = gViewerWindow->getWindowDisplayWidth(); S32 width = gViewerWindow->getWindowDisplayWidth();
S32 height = gViewerWindow->getWindowDisplayHeight(); S32 height = gViewerWindow->getWindowDisplayHeight();
F32 ratio = (F32)width / height;
F32 supersample = 1.f; F32 supersample = 1.f;
if (gSavedSettings.getBOOL("HighResSnapshot")) if (gSavedSettings.getBOOL("HighResSnapshot"))
@@ -546,8 +547,7 @@ class LLFileTakeSnapshotToDisk : public view_listener_t
if (gViewerWindow->rawSnapshot(raw, if (gViewerWindow->rawSnapshot(raw,
width, width,
height, height,
TRUE, ratio,
FALSE,
gSavedSettings.getBOOL("RenderUIInSnapshot"), gSavedSettings.getBOOL("RenderUIInSnapshot"),
FALSE, FALSE,
LLViewerWindow::SNAPSHOT_TYPE_COLOR, LLViewerWindow::SNAPSHOT_TYPE_COLOR,
@@ -574,7 +574,7 @@ class LLFileTakeSnapshotToDisk : public view_listener_t
formatted->enableOverSize() ; formatted->enableOverSize() ;
formatted->encode(raw, 0); formatted->encode(raw, 0);
formatted->disableOverSize(); formatted->disableOverSize();
gViewerWindow->saveImageNumbered(formatted); gViewerWindow->saveImageNumbered(formatted, -1);
} }
return true; return true;
} }

View File

@@ -5385,7 +5385,10 @@ void process_avatar_sit_response(LLMessageSystem *mesgsys, void **user_data)
gAgentCamera.setForceMouselook(force_mouselook); gAgentCamera.setForceMouselook(force_mouselook);
// Forcing turning off flying here to prevent flying after pressing "Stand" // Forcing turning off flying here to prevent flying after pressing "Stand"
// to stand up from an object. See EXT-1655. // to stand up from an object. See EXT-1655.
gAgent.setFlying(FALSE); // Unless the user wants to.
static LLCachedControl<bool> ContinueFlying("LiruContinueFlyingOnUnsit");
if (!ContinueFlying)
gAgent.setFlying(FALSE);
LLViewerObject* object = gObjectList.findObject(sitObjectID); LLViewerObject* object = gObjectList.findObject(sitObjectID);
if (object) if (object)
@@ -5927,17 +5930,35 @@ static void process_money_balance_reply_extended(LLMessageSystem* msg)
} }
} }
bool handle_special_notification_callback(const LLSD& notification, const LLSD& response) bool handle_prompt_for_maturity_level_change_callback(const LLSD& notification, const LLSD& response)
{ {
S32 option = LLNotificationsUtil::getSelectedOption(notification, response); S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
if (0 == option) if (0 == option)
{ {
// set the preference to the maturity of the region we're calling // set the preference to the maturity of the region we're calling
int preferredMaturity = notification["payload"]["_region_access"].asInteger(); U8 preferredMaturity = static_cast<U8>(notification["payload"]["_region_access"].asInteger());
gSavedSettings.setU32("PreferredMaturity", preferredMaturity); gSavedSettings.setU32("PreferredMaturity", static_cast<U32>(preferredMaturity));
gAgent.sendMaturityPreferenceToServer(preferredMaturity); }
return false;
}
bool handle_prompt_for_maturity_level_change_and_reteleport_callback(const LLSD& notification, const LLSD& response)
{
S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
if (0 == option)
{
// set the preference to the maturity of the region we're calling
U8 preferredMaturity = static_cast<U8>(notification["payload"]["_region_access"].asInteger());
gSavedSettings.setU32("PreferredMaturity", static_cast<U32>(preferredMaturity));
gAgent.setMaturityRatingChangeDuringTeleport(preferredMaturity);
gAgent.restartFailedTeleportRequest();
}
else
{
gAgent.clearTeleportRequest();
} }
return false; return false;
@@ -5946,39 +5967,148 @@ bool handle_special_notification_callback(const LLSD& notification, const LLSD&
// some of the server notifications need special handling. This is where we do that. // some of the server notifications need special handling. This is where we do that.
bool handle_special_notification(std::string notificationID, LLSD& llsdBlock) bool handle_special_notification(std::string notificationID, LLSD& llsdBlock)
{ {
int regionAccess = llsdBlock["_region_access"].asInteger(); U8 regionAccess = static_cast<U8>(llsdBlock["_region_access"].asInteger());
llsdBlock["REGIONMATURITY"] = LLViewerRegion::accessToString(regionAccess); std::string regionMaturity = LLViewerRegion::accessToString(regionAccess);
LLStringUtil::toLower(regionMaturity);
// we're going to throw the LLSD in there in case anyone ever wants to use it llsdBlock["REGIONMATURITY"] = regionMaturity;
LLNotificationsUtil::add(notificationID+"_Notify", llsdBlock);
bool returnValue = false;
LLNotificationPtr maturityLevelNotification;
std::string notifySuffix = "_Notify";
if (regionAccess == SIM_ACCESS_MATURE) if (regionAccess == SIM_ACCESS_MATURE)
{ {
if (gAgent.isTeen()) if (gAgent.isTeen())
{ {
LLNotificationsUtil::add(notificationID+"_KB", llsdBlock); gAgent.clearTeleportRequest();
return true; maturityLevelNotification = LLNotificationsUtil::add(notificationID+"_AdultsOnlyContent", llsdBlock);
returnValue = true;
notifySuffix = "_NotifyAdultsOnly";
} }
else if (gAgent.prefersPG()) else if (gAgent.prefersPG())
{ {
LLNotificationsUtil::add(notificationID+"_Change", llsdBlock, llsdBlock, handle_special_notification_callback); maturityLevelNotification = LLNotificationsUtil::add(notificationID+"_Change", llsdBlock, llsdBlock, handle_prompt_for_maturity_level_change_callback);
return true; returnValue = true;
}
else if (LLStringUtil::compareStrings(notificationID, "RegionEntryAccessBlocked") == 0)
{
maturityLevelNotification = LLNotificationsUtil::add(notificationID+"_PreferencesOutOfSync", llsdBlock, llsdBlock);
returnValue = true;
} }
} }
else if (regionAccess == SIM_ACCESS_ADULT) else if (regionAccess == SIM_ACCESS_ADULT)
{ {
if (!gAgent.isAdult()) if (!gAgent.isAdult())
{ {
LLNotificationsUtil::add(notificationID+"_KB", llsdBlock); gAgent.clearTeleportRequest();
return true; maturityLevelNotification = LLNotificationsUtil::add(notificationID+"_AdultsOnlyContent", llsdBlock);
returnValue = true;
notifySuffix = "_NotifyAdultsOnly";
} }
else if (gAgent.prefersPG() || gAgent.prefersMature()) else if (gAgent.prefersPG() || gAgent.prefersMature())
{ {
LLNotificationsUtil::add(notificationID+"_Change", llsdBlock, llsdBlock, handle_special_notification_callback); maturityLevelNotification = LLNotificationsUtil::add(notificationID+"_Change", llsdBlock, llsdBlock, handle_prompt_for_maturity_level_change_callback);
return true; returnValue = true;
}
else if (LLStringUtil::compareStrings(notificationID, "RegionEntryAccessBlocked") == 0)
{
maturityLevelNotification = LLNotificationsUtil::add(notificationID+"_PreferencesOutOfSync", llsdBlock, llsdBlock);
returnValue = true;
} }
} }
return false;
if ((maturityLevelNotification == NULL) || maturityLevelNotification->isIgnored())
{
// Given a simple notification if no maturityLevelNotification is set or it is ignore
LLNotificationsUtil::add(notificationID + notifySuffix, llsdBlock);
}
return returnValue;
}
// some of the server notifications need special handling. This is where we do that.
bool handle_teleport_access_blocked(LLSD& llsdBlock)
{
std::string notificationID("TeleportEntryAccessBlocked");
U8 regionAccess = static_cast<U8>(llsdBlock["_region_access"].asInteger());
std::string regionMaturity = LLViewerRegion::accessToString(regionAccess);
LLStringUtil::toLower(regionMaturity);
llsdBlock["REGIONMATURITY"] = regionMaturity;
bool returnValue = false;
LLNotificationPtr maturityLevelNotification;
std::string notifySuffix = "_Notify";
if (regionAccess == SIM_ACCESS_MATURE)
{
if (gAgent.isTeen())
{
gAgent.clearTeleportRequest();
maturityLevelNotification = LLNotificationsUtil::add(notificationID+"_AdultsOnlyContent", llsdBlock);
returnValue = true;
notifySuffix = "_NotifyAdultsOnly";
}
else if (gAgent.prefersPG())
{
if (gAgent.hasRestartableFailedTeleportRequest())
{
maturityLevelNotification = LLNotificationsUtil::add(notificationID+"_ChangeAndReTeleport", llsdBlock, llsdBlock, handle_prompt_for_maturity_level_change_and_reteleport_callback);
returnValue = true;
}
else
{
gAgent.clearTeleportRequest();
maturityLevelNotification = LLNotificationsUtil::add(notificationID+"_Change", llsdBlock, llsdBlock, handle_prompt_for_maturity_level_change_callback);
returnValue = true;
}
}
else
{
gAgent.clearTeleportRequest();
maturityLevelNotification = LLNotificationsUtil::add(notificationID+"_PreferencesOutOfSync", llsdBlock, llsdBlock, handle_prompt_for_maturity_level_change_callback);
returnValue = true;
}
}
else if (regionAccess == SIM_ACCESS_ADULT)
{
if (!gAgent.isAdult())
{
gAgent.clearTeleportRequest();
maturityLevelNotification = LLNotificationsUtil::add(notificationID+"_AdultsOnlyContent", llsdBlock);
returnValue = true;
notifySuffix = "_NotifyAdultsOnly";
}
else if (gAgent.prefersPG() || gAgent.prefersMature())
{
if (gAgent.hasRestartableFailedTeleportRequest())
{
maturityLevelNotification = LLNotificationsUtil::add(notificationID+"_ChangeAndReTeleport", llsdBlock, llsdBlock, handle_prompt_for_maturity_level_change_and_reteleport_callback);
returnValue = true;
}
else
{
gAgent.clearTeleportRequest();
maturityLevelNotification = LLNotificationsUtil::add(notificationID+"_Change", llsdBlock, llsdBlock, handle_prompt_for_maturity_level_change_callback);
returnValue = true;
}
}
else
{
gAgent.clearTeleportRequest();
maturityLevelNotification = LLNotificationsUtil::add(notificationID+"_PreferencesOutOfSync", llsdBlock, llsdBlock, handle_prompt_for_maturity_level_change_callback);
returnValue = true;
}
}
if ((maturityLevelNotification == NULL) || maturityLevelNotification->isIgnored())
{
// Given a simple notification if no maturityLevelNotification is set or it is ignore
LLNotificationsUtil::add(notificationID + notifySuffix, llsdBlock);
}
return returnValue;
} }
bool attempt_standard_notification(LLMessageSystem* msgsystem) bool attempt_standard_notification(LLMessageSystem* msgsystem)
@@ -6022,16 +6152,20 @@ bool attempt_standard_notification(LLMessageSystem* msgsystem)
RegionEntryAccessBlocked RegionEntryAccessBlocked
RegionEntryAccessBlocked_Notify RegionEntryAccessBlocked_Notify
RegionEntryAccessBlocked_NotifyAdultsOnly
RegionEntryAccessBlocked_Change RegionEntryAccessBlocked_Change
RegionEntryAccessBlocked_KB RegionEntryAccessBlocked_AdultsOnlyContent
RegionEntryAccessBlocked_ChangeAndReTeleport
LandClaimAccessBlocked LandClaimAccessBlocked
LandClaimAccessBlocked_Notify LandClaimAccessBlocked_Notify
LandClaimAccessBlocked_NotifyAdultsOnly
LandClaimAccessBlocked_Change LandClaimAccessBlocked_Change
LandClaimAccessBlocked_KB LandClaimAccessBlocked_AdultsOnlyContent
LandBuyAccessBlocked LandBuyAccessBlocked
LandBuyAccessBlocked_Notify LandBuyAccessBlocked_Notify
LandBuyAccessBlocked_NotifyAdultsOnly
LandBuyAccessBlocked_Change LandBuyAccessBlocked_Change
LandBuyAccessBlocked_KB LandBuyAccessBlocked_AdultsOnlyContent
-----------------------------------------------------------------------*/ -----------------------------------------------------------------------*/
if (handle_special_notification(notificationID, llsdBlock)) if (handle_special_notification(notificationID, llsdBlock))
@@ -6083,6 +6217,30 @@ void process_alert_message(LLMessageSystem *msgsystem, void **user_data)
} }
} }
bool handle_not_age_verified_alert(const std::string &pAlertName)
{
LLNotificationPtr notification = LLNotificationsUtil::add(pAlertName);
if ((notification == NULL) || notification->isIgnored())
{
LLNotificationsUtil::add(pAlertName + "_Notify");
}
return true;
}
bool handle_special_alerts(const std::string &pAlertName)
{
bool isHandled = false;
if (LLStringUtil::compareStrings(pAlertName, "NotAgeVerified") == 0)
{
isHandled = handle_not_age_verified_alert(pAlertName);
}
return isHandled;
}
void process_alert_core(const std::string& message, BOOL modal) void process_alert_core(const std::string& message, BOOL modal)
{ {
// HACK -- handle callbacks for specific alerts // HACK -- handle callbacks for specific alerts
@@ -6106,7 +6264,10 @@ void process_alert_core(const std::string& message, BOOL modal)
// Allow the server to spawn a named alert so that server alerts can be // Allow the server to spawn a named alert so that server alerts can be
// translated out of English. // translated out of English.
std::string alert_name(message.substr(ALERT_PREFIX.length())); std::string alert_name(message.substr(ALERT_PREFIX.length()));
LLNotificationsUtil::add(alert_name); if (!handle_special_alerts(alert_name))
{
LLNotificationsUtil::add(alert_name);
}
} }
else if (message.find(NOTIFY_PREFIX) == 0) else if (message.find(NOTIFY_PREFIX) == 0)
{ {
@@ -6407,6 +6568,7 @@ bool script_question_cb(const LLSD& notification, const LLSD& response)
// ...with description on top // ...with description on top
LLNotificationsUtil::add("DebitPermissionDetails"); LLNotificationsUtil::add("DebitPermissionDetails");
return false;
} }
// check whether permissions were granted or denied // check whether permissions were granted or denied
@@ -6775,7 +6937,7 @@ void process_teleport_failed(LLMessageSystem *msg, void**)
else else
{ {
// change notification name in this special case // change notification name in this special case
if (handle_special_notification("RegionEntryAccessBlocked", llsd_block)) if (handle_teleport_access_blocked(llsd_block))
{ {
if( gAgent.getTeleportState() != LLAgent::TELEPORT_NONE ) if( gAgent.getTeleportState() != LLAgent::TELEPORT_NONE )
{ {
@@ -6844,8 +7006,9 @@ void process_teleport_local(LLMessageSystem *msg,void**)
} }
} }
static LLCachedControl<bool> fly_after_tp(gSavedSettings, "LiruFlyAfterTeleport");
// Sim tells us whether the new position is off the ground // Sim tells us whether the new position is off the ground
if (teleport_flags & TELEPORT_FLAGS_IS_FLYING) if (fly_after_tp || (teleport_flags & TELEPORT_FLAGS_IS_FLYING))
{ {
gAgent.setFlying(TRUE); gAgent.setFlying(TRUE);
} }

View File

@@ -243,6 +243,7 @@ LLViewerObject::LLViewerObject(const LLUUID &id, const LLPCode pcode, LLViewerRe
mTimeDilation(1.f), mTimeDilation(1.f),
mRotTime(0.f), mRotTime(0.f),
mAngularVelocityRot(), mAngularVelocityRot(),
mPreviousRotation(),
mState(0), mState(0),
mMedia(NULL), mMedia(NULL),
mClickAction(0), mClickAction(0),
@@ -272,7 +273,12 @@ LLViewerObject::LLViewerObject(const LLUUID &id, const LLPCode pcode, LLViewerRe
{ {
mPositionAgent = mRegionp->getOriginAgent(); mPositionAgent = mRegionp->getOriginAgent();
} }
resetRot();
static const LLCachedControl<bool> use_new_target_omega ("UseNewTargetOmegaCode", true);
if (use_new_target_omega)
{
resetRot();
}
LLViewerObject::sNumObjects++; LLViewerObject::sNumObjects++;
} }
@@ -2107,17 +2113,49 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
} }
} }
if (new_rot != getRotation() static const LLCachedControl<bool> use_new_target_omega ("UseNewTargetOmegaCode", true);
|| new_angv != old_angv) if (use_new_target_omega)
{ { // New, experimental code
if (new_angv != old_angv) if ((new_rot != getRotation()) || (new_angv != old_angv))
{ {
if (new_rot != mPreviousRotation)
{
resetRot();
}
else if (new_angv != old_angv)
{
if (flagUsePhysics())
{
resetRot();
}
else
{
mRotTime = 0.0f;
}
}
// Remember the last rotation value
mPreviousRotation = new_rot;
// Set the rotation of the object followed by adjusting for the accumulated angular velocity (llSetTargetOmega)
setRotation(new_rot * mAngularVelocityRot);
setChanged(ROTATED | SILHOUETTE);
}
}
else
{ // Old code
if (new_rot != mPreviousRotation || new_angv != old_angv)
{
if (new_rot != mPreviousRotation)
{
mPreviousRotation = new_rot;
setRotation(new_rot);
}
setChanged(ROTATED | SILHOUETTE);
resetRot(); resetRot();
} }
// Set the rotation of the object followed by adjusting for the accumulated angular velocity (llSetTargetOmega)
setRotation(new_rot * mAngularVelocityRot);
setChanged(ROTATED | SILHOUETTE);
} }
@@ -5511,8 +5549,12 @@ void LLViewerObject::applyAngularVelocity(F32 dt)
// calculate the delta increment based on the object's angular velocity // calculate the delta increment based on the object's angular velocity
dQ.setQuat(angle, ang_vel); dQ.setQuat(angle, ang_vel);
// accumulate the angular velocity rotations to re-apply in the case of an object update static const LLCachedControl<bool> use_new_target_omega ("UseNewTargetOmegaCode", true);
mAngularVelocityRot *= dQ; if (use_new_target_omega)
{
// accumulate the angular velocity rotations to re-apply in the case of an object update
mAngularVelocityRot *= dQ;
}
// Just apply the delta increment to the current rotation // Just apply the delta increment to the current rotation
setRotation(getRotation()*dQ); setRotation(getRotation()*dQ);
@@ -5524,8 +5566,28 @@ void LLViewerObject::resetRot()
{ {
mRotTime = 0.0f; mRotTime = 0.0f;
// Reset the accumulated angular velocity rotation static const LLCachedControl<bool> use_new_target_omega ("UseNewTargetOmegaCode", true);
mAngularVelocityRot.loadIdentity(); if(use_new_target_omega)
{
// Reset the accumulated angular velocity rotation
mAngularVelocityRot.loadIdentity();
}
}
//virtual
void LLViewerObject::setSelected(BOOL sel)
{
mUserSelected = sel;
static const LLCachedControl<bool> use_new_target_omega ("UseNewTargetOmegaCode", true);
if(use_new_target_omega)
{
resetRot();
}
else
{
mRotTime = 0.f;
}
} }
U32 LLViewerObject::getPartitionType() const U32 LLViewerObject::getPartitionType() const

View File

@@ -214,7 +214,7 @@ public:
LLViewerRegion* getRegion() const { return mRegionp; } LLViewerRegion* getRegion() const { return mRegionp; }
BOOL isSelected() const { return mUserSelected; } BOOL isSelected() const { return mUserSelected; }
virtual void setSelected(BOOL sel) { mUserSelected = sel; mRotTime = 0.f;} void setSelected(BOOL sel);
const LLUUID &getID() const { return mID; } const LLUUID &getID() const { return mID; }
U32 getLocalID() const { return mLocalID; } U32 getLocalID() const { return mLocalID; }
@@ -742,6 +742,7 @@ protected:
F32 mTimeDilation; // Time dilation sent with the object. F32 mTimeDilation; // Time dilation sent with the object.
F32 mRotTime; // Amount (in seconds) that object has rotated according to angular velocity (llSetTargetOmega) F32 mRotTime; // Amount (in seconds) that object has rotated according to angular velocity (llSetTargetOmega)
LLQuaternion mAngularVelocityRot; // accumulated rotation from the angular velocity computations LLQuaternion mAngularVelocityRot; // accumulated rotation from the angular velocity computations
LLQuaternion mPreviousRotation;
U8 mState; // legacy U8 mState; // legacy
LLViewerObjectMedia* mMedia; // NULL if no media associated LLViewerObjectMedia* mMedia; // NULL if no media associated

View File

@@ -1340,7 +1340,7 @@ void LLViewerObjectList::killAllObjects()
killObject(objectp); killObject(objectp);
// Object must be dead, or it's the LLVOAvatarSelf which never dies. // Object must be dead, or it's the LLVOAvatarSelf which never dies.
llassert((objectp == gAgentAvatarp) || objectp->isDead()); llassert((objectp == gAgentAvatarp) || objectp->isDead() || (objectp->asAvatar() && objectp->asAvatar()->isFrozenDead()));
} }
cleanDeadObjects(FALSE); cleanDeadObjects(FALSE);

View File

@@ -720,6 +720,31 @@ std::string LLViewerRegion::accessToShortString(U8 sim_access)
} }
} }
// static
U8 LLViewerRegion::shortStringToAccess(const std::string &sim_access)
{
U8 accessValue;
if (LLStringUtil::compareStrings(sim_access, "PG") == 0)
{
accessValue = SIM_ACCESS_PG;
}
else if (LLStringUtil::compareStrings(sim_access, "M") == 0)
{
accessValue = SIM_ACCESS_MATURE;
}
else if (LLStringUtil::compareStrings(sim_access, "A") == 0)
{
accessValue = SIM_ACCESS_ADULT;
}
else
{
accessValue = SIM_ACCESS_MIN;
}
return accessValue;
}
// static // static
void LLViewerRegion::processRegionInfo(LLMessageSystem* msg, void**) void LLViewerRegion::processRegionInfo(LLMessageSystem* msg, void**)
{ {
@@ -1927,3 +1952,9 @@ bool LLViewerRegion::meshRezEnabled() const
} }
} }
bool LLViewerRegion::dynamicPathfindingEnabled() const
{
return ( mSimulatorFeatures.has("DynamicPathfindingEnabled") &&
mSimulatorFeatures["DynamicPathfindingEnabled"].asBoolean());
}

View File

@@ -210,6 +210,7 @@ public:
// Returns "M", "PG", "A" etc. // Returns "M", "PG", "A" etc.
static std::string accessToShortString(U8 sim_access); static std::string accessToShortString(U8 sim_access);
static U8 shortStringToAccess(const std::string &sim_access);
// Return access icon name // Return access icon name
static std::string getAccessIcon(U8 sim_access); static std::string getAccessIcon(U8 sim_access);
@@ -293,6 +294,9 @@ public:
void getSimulatorFeatures(LLSD& info); void getSimulatorFeatures(LLSD& info);
void setSimulatorFeatures(const LLSD& info); void setSimulatorFeatures(const LLSD& info);
bool dynamicPathfindingEnabled() const;
typedef enum typedef enum
{ {
CACHE_MISS_TYPE_FULL = 0, CACHE_MISS_TYPE_FULL = 0,

View File

@@ -631,7 +631,7 @@ void LLViewerTextureList::updateImages(F32 max_time)
//Can't check gTeleportDisplay due to a process_teleport_local(), which sets it to true for local teleports... so: //Can't check gTeleportDisplay due to a process_teleport_local(), which sets it to true for local teleports... so:
// Do this case if IS teleporting but NOT local teleporting, AND either the TP screen is set to appear OR we just entered the sim (TELEPORT_START_ARRIVAL) // Do this case if IS teleporting but NOT local teleporting, AND either the TP screen is set to appear OR we just entered the sim (TELEPORT_START_ARRIVAL)
LLAgent::ETeleportState state = gAgent.getTeleportState(); LLAgent::ETeleportState state = gAgent.getTeleportState();
if(state != LLAgent::TELEPORT_NONE && state != LLAgent::TELEPORT_LOCAL && if(state != LLAgent::TELEPORT_NONE && state != LLAgent::TELEPORT_LOCAL && state != LLAgent::TELEPORT_PENDING &&
(!hide_tp_screen || state == LLAgent::TELEPORT_START_ARRIVAL || state == LLAgent::TELEPORT_ARRIVING)) (!hide_tp_screen || state == LLAgent::TELEPORT_START_ARRIVAL || state == LLAgent::TELEPORT_ARRIVING))
{ {
if(!cleared) if(!cleared)

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