Merge branch 'master' into UICleanup

This commit is contained in:
Shyotl
2013-05-27 19:19:38 -05:00
260 changed files with 7735 additions and 7937 deletions

2
.gitignore vendored
View File

@@ -24,3 +24,5 @@
/edited-files.txt
qtcreator-build/
/.pc
/build-*
/viewer-*

View File

@@ -614,6 +614,8 @@ void AIStateMachine::multiplex(event_type event)
// Continue in bs_multiplex.
// If the state is bs_multiplex we only need to run again when need_run was set again in the meantime or when this state machine isn't idle.
need_new_run = sub_state_r->need_run || !sub_state_r->idle;
// If this fails then the run state didn't change and neither idle() nor yield() was called.
llassert_always(!(need_new_run && !mYieldEngine && sub_state_r->run_state == run_state));
}
break;
case bs_abort:
@@ -786,10 +788,10 @@ AIStateMachine::state_type AIStateMachine::begin_loop(base_state_type base_state
return sub_state_w->run_state;
}
void AIStateMachine::run(LLPointer<AIStateMachine> parent, state_type new_parent_state, bool abort_parent, bool on_abort_signal_parent, AIEngine* default_engine)
void AIStateMachine::run(AIStateMachine* parent, state_type new_parent_state, bool abort_parent, bool on_abort_signal_parent, AIEngine* default_engine)
{
DoutEntering(dc::statemachine, "AIStateMachine::run(" <<
(void*)parent.get() << ", " <<
(void*)parent << ", " <<
(parent ? parent->state_str_impl(new_parent_state) : "NA") <<
", abort_parent = " << (abort_parent ? "true" : "false") <<
", on_abort_signal_parent = " << (on_abort_signal_parent ? "true" : "false") <<
@@ -1007,6 +1009,15 @@ void AIStateMachine::advance_state(state_type new_state)
Dout(dc::statemachine, "Ignored, because " << state_str_impl(sub_state_w->advance_state) << " >= " << state_str_impl(new_state) << ".");
return;
}
// Ignore call to advance_state when the current state is greater than the requested state: the new state would be
// ignored in begin_loop(), as is already remarked there: an advanced state that is not honored is not a reason to run.
// This call might as well not have happened. Not returning here is a bug because that is effectively a cont(), while
// the state change is and should be being ignored: the statemachine would start running it's current state (again).
if (sub_state_w->run_state > new_state)
{
Dout(dc::statemachine, "Ignored, because " << state_str_impl(sub_state_w->run_state) << " > " << state_str_impl(new_state) << " (current state).");
return;
}
// Increment state.
sub_state_w->advance_state = new_state;
// Void last call to idle(), if any.
@@ -1018,6 +1029,16 @@ void AIStateMachine::advance_state(state_type new_state)
#ifdef SHOW_ASSERT
// From this moment on.
mDebugAdvanceStatePending = true;
// If the new state is equal to the current state, then this should be considered to be a cont()
// because also equal states are ignored in begin_loop(). However, unlike a cont() we ignore a call
// to idle() when the statemachine is already running in this state (because that is a race condition
// and ignoring the idle() is the most logical thing to do then). Hence we treated this as a full
// fletched advance_state but need to tell the debug code that it's really also a cont().
if (sub_state_w->run_state == new_state)
{
// From this moment.
mDebugContPending = true;
}
#endif
}
if (!mMultiplexMutex.isSelfLocked())

View File

@@ -212,7 +212,7 @@ class AIStateMachine : public LLThreadSafeRefCount
public:
// These functions may be called directly after creation, or from within finish_impl(), or from the call back function.
void run(LLPointer<AIStateMachine> parent, state_type new_parent_state, bool abort_parent = true, bool on_abort_signal_parent = true, AIEngine* default_engine = &gMainThreadEngine);
void run(AIStateMachine* parent, state_type new_parent_state, bool abort_parent = true, bool on_abort_signal_parent = true, AIEngine* default_engine = &gMainThreadEngine);
void run(callback_type::signal_type::slot_type const& slot, AIEngine* default_engine = &gMainThreadEngine);
void run(void) { run(NULL, 0, false, true, mDefaultEngine); }

View File

@@ -101,7 +101,10 @@ void AIStateMachineThreadBase::multiplex_impl(state_type run_state)
break;
case wait_stopped:
if (!mThread->isStopped())
{
yield();
break;
}
// We're done!
//
// We can only get here when AIThreadImpl::done called cont(), (very

View File

@@ -103,12 +103,14 @@ if (LINUX)
-pthread
)
# Don't catch SIGCHLD in our base application class for the viewer
# some of our 3rd party libs may need their *own* SIGCHLD handler to work. Sigh!
# The viewer doesn't need to catch SIGCHLD anyway.
add_definitions(-DLL_IGNORE_SIGCHLD)
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -D_FORTIFY_SOURCE=2 ")
if(${CMAKE_C_COMPILER} MATCHES "gcc*")
# Don't catch SIGCHLD in our base application class for the viewer
# some of our 3rd party libs may need their *own* SIGCHLD handler to work. Sigh!
# The viewer doesn't need to catch SIGCHLD anyway.
add_definitions(-DLL_IGNORE_SIGCHLD)
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
find_program(GXX g++)
mark_as_advanced(GXX)
@@ -136,16 +138,6 @@ if (LINUX)
OUTPUT_VARIABLE CXX_VERSION
OUTPUT_STRIP_TRAILING_WHITESPACE)
# Here's a giant hack for Fedora 8, where we can't use
# _FORTIFY_SOURCE if we're using a compiler older than gcc 4.1.
if (${GXX_VERSION} STREQUAL ${CXX_VERSION})
add_definitions(-D_FORTIFY_SOURCE=2)
else (${GXX_VERSION} STREQUAL ${CXX_VERSION})
if (NOT ${GXX_VERSION} MATCHES " 4.1.*Red Hat")
add_definitions(-D_FORTIFY_SOURCE=2)
endif (NOT ${GXX_VERSION} MATCHES " 4.1.*Red Hat")
endif (${GXX_VERSION} STREQUAL ${CXX_VERSION})
#Lets actually get a numerical version of gxx's version
STRING(REGEX REPLACE ".* ([0-9])\\.([0-9])\\.([0-9]).*" "\\1\\2\\3" CXX_VERSION ${CXX_VERSION})
@@ -159,6 +151,11 @@ if (LINUX)
add_definitions(-Wno-unused-but-set-variable)
endif (NOT ${CXX_VERSION} LESS 460)
#gcc 4.8 boost spam wall
if(NOT ${CXX_VERSION} LESS 480)
add_definitions(-Wno-unused-local-typedefs)
endif (NOT ${CXX_VERSION} LESS 480)
# End of hacks.
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99")
@@ -184,39 +181,19 @@ if (LINUX)
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}${MARCH_FLAG} -mfpmath=sse,387 -msse2 ${GCC_EXTRA_OPTIMIZATIONS}")
set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO}${MARCH_FLAG} -mfpmath=sse,387 -msse2 ${GCC_EXTRA_OPTIMIZATIONS}")
endif (${ARCH} STREQUAL "x86_64")
elseif(${CMAKE_C_COMPILER} MATCHES "clang*")
find_program(CLANG clang)
mark_as_advanced(CLANG)
find_program(CLANGXX clang++)
mark_as_advanced(CLANGXX)
add_definitions(
-D_FORTIFY_SOURCE=2
)
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
if (NOT STANDALONE)
# this stops us requiring a really recent glibc at runtime
add_definitions(-fno-stack-protector)
endif (NOT STANDALONE)
if (NOT STANDALONE)
set(MARCH_FLAG " -march=pentium4")
endif (NOT STANDALONE)
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}${MARCH_FLAG} -fno-inline -msse2")
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}${MARCH_FLAG} -fno-inline -msse2")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}${MARCH_FLAG} -msse2")
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}${MARCH_FLAG} -msse2")
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}${MARCH_FLAG} -msse2")
set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO}${MARCH_FLAG} -msse2")
elseif(${CMAKE_C_COMPILER} MATCHES "icc*" AND ${CMAKE_CXX_COMPILER} MATCHES "icpc*")
find_program(ICC icc)
mark_as_advanced(ICC)
add_definitions(
-D_FORTIFY_SOURCE=2
)
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel")
if (NOT STANDALONE)
# this stops us requiring a really recent glibc at runtime
@@ -248,7 +225,8 @@ if (DARWIN)
add_definitions(-DLL_DARWIN=1 -D_XOPEN_SOURCE)
set(CMAKE_CXX_LINK_FLAGS "-Wl,-headerpad_max_install_names,-search_paths_first")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_CXX_LINK_FLAGS}")
if(${CMAKE_C_COMPILER} MATCHES "gcc*")
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mlong-branch")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mlong-branch")
# NOTE: it's critical that the optimization flag is put in front.
@@ -257,7 +235,7 @@ if (DARWIN)
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -O3 -msse3 -mtune=generic -mfpmath=sse ${GCC_EXTRA_OPTIMIZATIONS}")
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -O3 -msse3 -mtune=generic -mfpmath=sse ${GCC_EXTRA_OPTIMIZATIONS}")
set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} -O3 -msse3 -mtune=generic -mfpmath=sse ${GCC_EXTRA_OPTIMIZATIONS}")
elseif(${CMAKE_C_COMPILER} MATCHES "clang*")
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
# NOTE: it's critical that the optimization flag is put in front.
# NOTE: it's critical to have both CXX_FLAGS and C_FLAGS covered.
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O3 -msse3")
@@ -269,20 +247,21 @@ endif (DARWIN)
if (LINUX OR DARWIN)
if(${CMAKE_C_COMPILER} MATCHES "gcc*")
set(UNIX_WARNINGS "-Wall -Wno-sign-compare -Wno-trigraphs")
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
add_definitions(-DLL_GNUC=1)
set(UNIX_WARNINGS "-Wall -Wno-sign-compare -Wno-trigraphs")
set(UNIX_CXX_WARNINGS "${UNIX_WARNINGS} -Wno-reorder -Wno-non-virtual-dtor -Woverloaded-virtual")
elseif(${CMAKE_C_COMPILER} MATCHES "clang*")
set(UNIX_WARNINGS "-Wall -Wno-sign-compare -Wno-trigraphs -Wno-tautological-compare -Wno-char-subscripts -Wno-gnu -Wno-logical-op-parentheses -Wno-non-virtual-dtor")
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
add_definitions(-DLL_CLANG=1)
set(UNIX_WARNINGS "-Wall -Wno-sign-compare -Wno-trigraphs -Wno-tautological-compare -Wno-char-subscripts -Wno-gnu -Wno-logical-op-parentheses -Wno-non-virtual-dtor")
set(UNIX_WARNINGS "${UNIX_WARNINGS} -Woverloaded-virtual -Wno-parentheses-equality -Wno-reorder -Wno-unused-function -Wno-unused-value -Wno-unused-variable")
set(UNIX_CXX_WARNINGS "${UNIX_WARNINGS}")
elseif(${CMAKE_C_COMPILER} MATCHES "icc")
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel")
add_definitions(-DLL_ICC=1)
set(UNIX_WARNINGS "-wd327 -wd597 -wd858")
set(UNIX_CXX_WARNINGS "${UNIX_WARNINGS}")
endif()
endif ()
# Use -DDISABLE_FATAL_WARNINGS:BOOL=FALSE during configuration to enable fatal warnings.
set(DISABLE_FATAL_WARNINGS TRUE CACHE BOOL "Set this to FALSE to enable fatal warnings.")
if (NOT DISABLE_FATAL_WARNINGS)
set(UNIX_WARNINGS "${UNIX_WARNINGS} -Werror")
set(UNIX_CXX_WARNINGS "${UNIX_CXX_WARNINGS} -Werror")

View File

@@ -30,6 +30,7 @@ set(SCRIPTS_DIR ${CMAKE_SOURCE_DIR}/${SCRIPTS_PREFIX})
set(VIEWER_DIR ${CMAKE_SOURCE_DIR}/${VIEWER_PREFIX})
set(DISABLE_TCMALLOC OFF CACHE BOOL "Disable linkage of TCMalloc. (64bit builds automatically disable TCMalloc)")
set(LL_TESTS OFF CACHE BOOL "Build and run unit and integration tests (disable for build timing runs to reduce variation)")
set(DISABLE_FATAL_WARNINGS TRUE CACHE BOOL "Set this to FALSE to enable fatal warnings.")
set(LIBS_PREBUILT_DIR ${CMAKE_SOURCE_DIR}/../libraries CACHE PATH
"Location of prebuilt libraries.")

View File

@@ -45,7 +45,6 @@ import commands
class CommandError(Exception):
pass
def mkdir(path):
try:
os.mkdir(path)
@@ -54,15 +53,19 @@ def mkdir(path):
if err.errno != errno.EEXIST or not os.path.isdir(path):
raise
def getcwd():
cwd = os.getcwd()
if 'a' <= cwd[0] <= 'z' and cwd[1] == ':':
def prettyprint_path_for_cmake(path):
if 'a' <= path[0] <= 'z' and path[1] == ':':
# CMake wants DOS drive letters to be in uppercase. The above
# condition never asserts on platforms whose full path names
# always begin with a slash, so we don't need to test whether
# we are running on Windows.
cwd = cwd[0].upper() + cwd[1:]
return cwd
path = path[0].upper() + path[1:]
return path
def getcwd():
return prettyprint_path_for_cmake(os.getcwd())
source_indra = prettyprint_path_for_cmake(os.path.dirname(os.path.realpath(__file__)))
def quote(opts):
return '"' + '" "'.join([ opt.replace('"', '') for opt in opts ]) + '"'
@@ -150,7 +153,7 @@ class PlatformSetup(object):
simple = False
try:
os.chdir(d)
cmd = self.cmake_commandline(cwd, d, args, simple)
cmd = self.cmake_commandline(source_indra, d, args, simple)
print 'Running %r in %r' % (cmd, d)
self.run(cmd, 'cmake')
finally:
@@ -270,18 +273,9 @@ class LinuxSetup(UnixSetup):
return 'linux'
def build_dirs(self):
# Only build the server code if we have it.
platform_build = '%s-%s' % (self.platform(), self.build_type.lower())
if self.arch() == 'i686' and self.is_internal_tree():
return ['viewer-' + platform_build, 'server-' + platform_build]
elif self.arch() == 'x86_64' and self.is_internal_tree():
# the viewer does not build in 64bit -- kdu5 issues
# we can either use openjpeg, or overhaul our viewer to handle kdu5 or higher
# doug knows about kdu issues
return ['server-' + platform_build]
else:
return ['viewer-' + platform_build]
return ['viewer-' + platform_build]
def cmake_commandline(self, src_dir, build_dir, opts, simple):
args = dict(
@@ -293,31 +287,11 @@ class LinuxSetup(UnixSetup):
type=self.build_type.upper(),
project_name=self.project_name,
word_size=self.word_size,
cxx="g++"
)
if not self.is_internal_tree():
args.update({'cxx':'g++', 'server':'OFF', 'viewer':'ON'})
else:
if self.distcc:
distcc = self.find_in_path('distcc')
baseonly = True
else:
distcc = []
baseonly = False
if 'server' in build_dir:
gcc = distcc + self.find_in_path(
self.debian_sarge and 'g++-3.3' or 'g++-4.1',
'g++', baseonly)
args.update({'cxx': ' '.join(gcc), 'server': 'ON',
'viewer': 'OFF'})
else:
gcc41 = distcc + self.find_in_path('g++-4.1', 'g++', baseonly)
args.update({'cxx': ' '.join(gcc41),
'server': 'OFF',
'viewer': 'ON'})
cmd = (('cmake -DCMAKE_BUILD_TYPE:STRING=%(type)s '
'-G %(generator)r -DSERVER:BOOL=%(server)s '
'-DVIEWER:BOOL=%(viewer)s -DSTANDALONE:BOOL=%(standalone)s '
'-DUNATTENDED:BOOL=%(unattended)s '
'-G %(generator)r -DSTANDALONE:BOOL=%(standalone)s '
'-DWORD_SIZE:STRING=%(word_size)s '
'-DROOT_PROJECT_NAME:STRING=%(project_name)s '
'%(opts)s %(dir)r')

View File

@@ -1,13 +1,39 @@
cmake_minimum_required(VERSION 2.6.4)
# -*- cmake -*-
project(libhacd CXX C)
project(libhacd)
include(00-Common)
file (GLOB SOURCE_FILES *.cpp )
file (GLOB INCLUDE_FILES *.h )
set(libhacd_SOURCE_FILES
hacdGraph.cpp
hacdHACD.cpp
hacdICHull.cpp
hacdManifoldMesh.cpp
hacdMeshDecimator.cpp
hacdMicroAllocator.cpp
hacdRaycastMesh.cpp
)
set(libhacd_HEADER_FILES
hacdCircularList.h
hacdCircularList.inl
hacdGraph.h
hacdHACD.h
hacdICHull.h
hacdManifoldMesh.h
hacdMeshDecimator.h
hacdMicroAllocator.h
hacdRaycastMesh.h
hacdSArray.h
hacdVector.h
hacdVector.inl
hacdVersion.h
)
set_source_files_properties(${libhacd_HEADER_FILES}
PROPERTIES HEADER_FILE_ONLY TRUE)
IF(WINDOWS)
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
ENDIF(WINDOWS)
add_library(hacd ${SOURCE_FILES} ${INCLUDE_FILES})
add_library(hacd ${libhacd_SOURCE_FILES} ${libhacd_INCLUDE_FILES})

View File

@@ -76,6 +76,7 @@ namespace HACD
{
public:
virtual void operator()( char const *aMsg, double aProgress, double aConcavity, size_t aVertices) = 0;
virtual ~ICallback() {}
};
typedef ICallback* CallBackFunction;

View File

@@ -1,9 +1,35 @@
# -*- cmake -*-
project(libndhacd)
include(00-Common)
include_directories(${LIBS_OPEN_DIR}/libhacd)
set (SOURCE_FILES LLConvexDecomposition.cpp nd_hacdConvexDecomposition.cpp nd_hacdStructs.cpp nd_hacdUtils.cpp nd_EnterExitTracer.cpp nd_StructTracer.cpp )
file(GLOB HEADER_FILES *.h)
set (libndhacd_SOURCE_FILES
LLConvexDecomposition.cpp
nd_hacdConvexDecomposition.cpp
nd_hacdStructs.cpp
nd_hacdUtils.cpp
nd_EnterExitTracer.cpp
nd_StructTracer.cpp
)
add_library( nd_hacdConvexDecomposition STATIC ${SOURCE_FILES} ${HEADER_FILES})
set (libndhacd_HEADER_FILES
LLConvexDecomposition.h
ndConvexDecomposition.h
nd_hacdConvexDecomposition.h
nd_hacdStructs.h
nd_StructTracer.h
LLConvexDecompositionStubImpl.h
nd_EnterExitTracer.h
nd_hacdDefines.h
nd_hacdUtils.h
windowsincludes.h
)
set_source_files_properties(${libndhacd_HEADER_FILES}
PROPERTIES HEADER_FILE_ONLY TRUE)
add_library( nd_hacdConvexDecomposition STATIC ${libndhacd_SOURCE_FILES} ${libndhacd_HEADER_FILES})

View File

@@ -1,13 +1,34 @@
cmake_minimum_required(VERSION 2.6.4)
# -*- cmake -*-
project(libpathing)
include(00-Common)
include(LLCommon)
include(LLMath)
include_directories(
${LLCOMMON_INCLUDE_DIRS}
${LLMATH_INCLUDE_DIRS}
)
project(ndPathingLib CXX C)
if( MSVC )
add_definitions(-D_SECURE_SCL=0 -D_CRT_SECURE_NO_WARNINGS=1)
endif( MSVC )
file (GLOB SOURCE_FILES *.cpp )
file (GLOB INCLUDE_FILES *.h )
set(libpathing_SOURCE_FILES
llpathinglib.cpp
llphysicsextensions.cpp
)
add_library(nd_Pathing STATIC ${SOURCE_FILES} ${INCLUDE_FILES} )
set(libpathing_HEADER_FILES
llpathinglib.h
llphysicsextensions.h
)
set_source_files_properties(${libpathing_HEADER_FILES}
PROPERTIES HEADER_FILE_ONLY TRUE)
add_library(nd_Pathing STATIC ${libpathing_SOURCE_FILES} ${libpathing_HEADER_FILES} )
add_dependencies(nd_Pathing prepare)

View File

@@ -1,3 +1,4 @@
#include "sys.h"
#include "llpathinglib.h"
void LLPathingLib::initSystem()

View File

@@ -3,37 +3,10 @@
#include <vector>
#ifndef LL_V3MATH_H
class LLVector3
{
public:
float mV[3];
};
#endif
#ifndef LL_V4COLORU_H
class LLColor4U
{
public:
unsigned char mV[4];
};
#endif
#ifndef LL_LLUUID_H
class LLUUID
{
public:
unsigned char mData[16];
};
#endif
#ifndef LLQUATERNION_H
class LLQuaternion
{
public:
double mQ[4];
};
#endif
#include "v3math.h"
#include "v4coloru.h"
#include "llquaternion.h"
#include "lluuid.h"
class LLRender;
@@ -43,7 +16,7 @@ public:
enum LLPLResult
{
LLPL_NO_PATH,
LLPL_PATH_GENERATED_OK,
LLPL_PATH_GENERATED_OK
};
enum LLPLCharacterType
@@ -52,7 +25,7 @@ public:
LLPL_CHARACTER_TYPE_A,
LLPL_CHARACTER_TYPE_B,
LLPL_CHARACTER_TYPE_C,
LLPL_CHARACTER_TYPE_D,
LLPL_CHARACTER_TYPE_D
};
enum LLShapeType
@@ -60,13 +33,13 @@ public:
LLST_WalkableObjects = 1,
LLST_ObstacleObjects = 2,
LLST_MaterialPhantoms = 3,
LLST_ExclusionPhantoms = 4,
LLST_ExclusionPhantoms = 4
};
enum LLPLRenderType
{
LLPL_START,
LLPL_END,
LLPL_END
};
struct Vector
@@ -87,9 +60,9 @@ public:
operator LLVector3() const
{
LLVector3 ret;
ret.mV[0] = mX;
ret.mV[1] = mY;
ret.mV[2] = mZ;
ret.mV[0] = (F32) mX;
ret.mV[1] = (F32) mY;
ret.mV[2] = (F32) mZ;
return ret;
}
};

View File

@@ -473,6 +473,8 @@ const std::string LLTexLayerSet::getBodyRegionName() const
// virtual
void LLTexLayerSet::asLLSD(LLSD& sd) const
{
llassert_always(false); // broken function
#if 0
sd["visible"] = LLSD::Boolean(isVisible());
LLSD layer_list_sd;
layer_list_t::const_iterator layer_iter = mLayerList.begin();
@@ -492,6 +494,7 @@ void LLTexLayerSet::asLLSD(LLSD& sd) const
sd["layers"] = layer_list_sd;
sd["masks"] = mask_list_sd;
sd["info"] = info_sd;
#endif
}

View File

@@ -40,7 +40,6 @@
#include <map>
#include <deque>
#include "lluuidhashmap.h"
#include "llmotion.h"
#include "llpose.h"
#include "llframetimer.h"

View File

@@ -234,7 +234,7 @@ set(llcommon_HEADER_FILES
lltypeinfolookup.h
lluri.h
lluuid.h
lluuidhashmap.h
sguuidhash.h
llversionviewer.h.in
llworkerthread.h
metaclass.h

View File

@@ -67,7 +67,7 @@ class LL_COMMON_API AIFrameTimer
mutable Signal* mCallback; // Pointer to callback struct, or NULL when the object wasn't added to sTimerList yet.
public:
AIRunningFrameTimer(F64 expiration, AIFrameTimer* timer) : mExpire(LLFrameTimer::getElapsedSeconds() + expiration), mCallback(NULL), mTimer(timer) { }
AIRunningFrameTimer(F64 expiration, AIFrameTimer* timer) : mExpire(LLFrameTimer::getElapsedSeconds() + expiration), mTimer(timer), mCallback(NULL) { }
~AIRunningFrameTimer() { delete mCallback; }
// This function is called after the final object was added to sTimerList (where it is initialized in-place).
@@ -89,7 +89,7 @@ class LL_COMMON_API AIFrameTimer
#if LL_DEBUG
// May not copy this object after it was initialized.
AIRunningFrameTimer(AIRunningFrameTimer const& running_frame_timer) :
mExpire(running_frame_timer.mExpire), mCallback(running_frame_timer.mCallback), mTimer(running_frame_timer.mTimer)
mExpire(running_frame_timer.mExpire), mTimer(running_frame_timer.mTimer), mCallback(running_frame_timer.mCallback)
{ llassert(!mCallback); }
#endif
};

View File

@@ -61,6 +61,13 @@ typedef enum e_chat_audible_level
CHAT_AUDIBLE_FULLY = 1
} EChatAudible;
typedef enum e_chat_style
{
CHAT_STYLE_NORMAL,
CHAT_STYLE_IRC,
CHAT_STYLE_HISTORY
}EChatStyle;
// A piece of chat
class LLChat
{
@@ -80,7 +87,8 @@ public:
// [/RLVa:KB]
mTime(0.0),
mPosAgent(),
mURL()
mURL(),
mChatStyle(CHAT_STYLE_NORMAL)
{ }
LLChat(const LLChat &chat)
@@ -93,7 +101,8 @@ public:
mMuted(chat.mMuted),
mTime(chat.mTime),
mPosAgent(chat.mPosAgent),
mURL(chat.mURL)
mURL(chat.mURL),
mChatStyle(chat.mChatStyle)
{ }
std::string mText; // UTF-8 line of text
@@ -110,6 +119,7 @@ public:
F64 mTime; // viewer only, seconds from viewer start
LLVector3 mPosAgent;
std::string mURL;
EChatStyle mChatStyle;
};
#endif

View File

@@ -72,14 +72,14 @@
// Figure out differences between compilers
#if defined(__clang__) && defined(__GNUC__)
#if defined(__clang__)
#define CLANG_VERSION (__clang_major__ * 10000 \
+ __clang_minor__ * 100 \
+ __clang_patchlevel__)
#ifndef LL_CLANG
#define LL_CLANG 1
#endif
#elif defined (__ICC) && defined(__GNUC__)
#elif defined (__ICC)
#ifndef LL_ICC
#define LL_ICC 1
#endif

View File

@@ -178,7 +178,7 @@ struct CopyNewPointer
// helper function which returns true if key is in inmap.
template <typename T>
//Singu note: This has been generalized to support a broader range of map-esque containers
inline bool is_in_map(const T& inmap, typename const T::key_type& key)
inline bool is_in_map(const T& inmap, typename T::key_type const& key)
{
if(inmap.find(key) == inmap.end())
{
@@ -197,7 +197,7 @@ inline bool is_in_map(const T& inmap, typename const T::key_type& key)
//
//Singu note: This has been generalized to support a broader range of map-esque containers.
template <typename T>
inline typename T::mapped_type get_if_there(const T& inmap, typename const T::key_type& key, typename T::mapped_type default_value)
inline typename T::mapped_type get_if_there(const T& inmap, typename T::key_type const& key, typename T::mapped_type default_value)
{
// Typedef here avoids warnings because of new c++ naming rules.
typedef typename T::const_iterator map_iter;
@@ -222,7 +222,7 @@ inline typename T::mapped_type get_if_there(const T& inmap, typename const T::ke
// const char* baz = get_ptr_in_map(foo, 3); // baz == NULL
//Singu note: This has been generalized to support a broader range of map-esque containers
template <typename T>
inline typename T::mapped_type get_ptr_in_map(const T& inmap, typename const T::key_type& key)
inline typename T::mapped_type get_ptr_in_map(const T& inmap, typename T::key_type const& key)
{
return get_if_there(inmap,key,NULL);
};
@@ -265,7 +265,7 @@ inline typename T::iterator vector_replace_with_last(T& invec, typename T::itera
//
//Singu note: This has been generalized to support a broader range of sequence containers
template <typename T>
inline bool vector_replace_with_last(T& invec, typename const T::value_type& val)
inline bool vector_replace_with_last(T& invec, typename T::value_type const& val)
{
typename T::iterator iter = std::find(invec.begin(), invec.end(), val);
if (iter != invec.end())

View File

@@ -23,7 +23,7 @@
* $/LicenseInfo$
*/
#ifdef __GNUC__
#if LL_GNUC
// Generate code for inlines from llthread.h (needed for is_main_thread()).
#pragma implementation "llthread.h"
#endif
@@ -403,8 +403,8 @@ void LLCondition::broadcast()
//============================================================================
LLMutexBase::LLMutexBase() :
mLockingThread(AIThreadID::sNone),
mCount(0)
mCount(0),
mLockingThread(AIThreadID::sNone)
{
}

View File

@@ -27,7 +27,7 @@
#ifndef LL_LLTHREAD_H
#define LL_LLTHREAD_H
#ifdef __GNUC__
#if LL_GNUC
// Needed for is_main_thread() when compiling with optimization (relwithdebinfo).
// It doesn't hurt to just always specify it though.
#pragma interface

View File

@@ -171,14 +171,6 @@ void LLUUID::toString(std::string& out) const
(U8)(mData[15]));
}
// *TODO: deprecate
void LLUUID::toString(char *out) const
{
std::string buffer;
toString(buffer);
strcpy(out,buffer.c_str()); /* Flawfinder: ignore */
}
void LLUUID::toCompressedString(std::string& out) const
{
char bytes[UUID_BYTES+1];
@@ -187,13 +179,6 @@ void LLUUID::toCompressedString(std::string& out) const
out.assign(bytes, UUID_BYTES);
}
// *TODO: deprecate
void LLUUID::toCompressedString(char *out) const
{
memcpy(out, mData, UUID_BYTES); /* Flawfinder: ignore */
out[UUID_BYTES] = '\0';
}
std::string LLUUID::getString() const
{
return asString();
@@ -422,14 +407,9 @@ std::ostream& operator<<(std::ostream& s, const LLUUID &uuid)
std::istream& operator>>(std::istream &s, LLUUID &uuid)
{
U32 i;
char uuid_str[UUID_STR_LENGTH]; /* Flawfinder: ignore */
for (i = 0; i < UUID_STR_LENGTH-1; i++)
{
s >> uuid_str[i];
}
uuid_str[i] = '\0';
uuid.set(std::string(uuid_str));
std::string uuid_str;
s >> uuid_str;
uuid.set(uuid_str);
return s;
}

View File

@@ -106,9 +106,7 @@ public:
friend LL_COMMON_API std::ostream& operator<<(std::ostream& s, const LLUUID &uuid);
friend LL_COMMON_API std::istream& operator>>(std::istream& s, LLUUID &uuid);
void toString(char *out) const; // Does not allocate memory, needs 36 characters (including \0)
void toString(std::string& out) const;
void toCompressedString(char *out) const; // Does not allocate memory, needs 17 characters (including \0)
void toCompressedString(std::string& out) const;
std::string asString() const;

View File

@@ -1,589 +0,0 @@
/**
* @file lluuidhashmap.h
* @brief A uuid based hash map.
*
* $LicenseInfo:firstyear=2003&license=viewergpl$
*
* Copyright (c) 2003-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 LL_LLUUIDHASHMAP_H
#define LL_LLUUIDHASHMAP_H
#include "stdtypes.h"
#include "llerror.h"
#include "lluuid.h"
// UUID hash map
/*
LLUUIDHashMap<uuid_pair, 32> foo(test_equals);
LLUUIDHashMapIter<uuid_pair, 32> bar(&foo);
LLDynamicArray<LLUUID> source_ids;
const S32 COUNT = 100000;
S32 q;
for (q = 0; q < COUNT; q++)
{
llinfos << "Creating" << llendl;
LLUUID id;
id.generate();
//llinfos << q << ":" << id << llendl;
uuid_pair pair;
pair.mUUID = id;
pair.mValue = q;
foo.set(id, pair);
source_ids.put(id);
//ms_sleep(1);
}
uuid_pair cur;
llinfos << "Iterating" << llendl;
for (cur = bar.first(); !bar.done(); cur = bar.next())
{
if (source_ids[cur.mValue] != cur.mUUID)
{
llerrs << "Incorrect value iterated!" << llendl;
}
//llinfos << cur.mValue << ":" << cur.mUUID << llendl;
//ms_sleep(1);
}
llinfos << "Finding" << llendl;
for (q = 0; q < COUNT; q++)
{
cur = foo.get(source_ids[q]);
if (source_ids[cur.mValue] != cur.mUUID)
{
llerrs << "Incorrect value found!" << llendl;
}
//llinfos << res.mValue << ":" << res.mUUID << llendl;
//ms_sleep(1);
}
llinfos << "Removing" << llendl;
for (q = 0; q < COUNT/2; q++)
{
if (!foo.remove(source_ids[q]))
{
llerrs << "Remove failed!" << llendl;
}
//ms_sleep(1);
}
llinfos << "Iterating" << llendl;
for (cur = bar.first(); !bar.done(); cur = bar.next())
{
if (source_ids[cur.mValue] != cur.mUUID)
{
llerrs << "Incorrect value found!" << llendl;
}
//llinfos << cur.mValue << ":" << cur.mUUID << llendl;
//ms_sleep(1);
}
llinfos << "Done with UUID map test" << llendl;
return 0;
*/
//
// LLUUIDHashNode
//
template <class DATA, int SIZE>
class LLUUIDHashNode
{
public:
LLUUIDHashNode();
public:
S32 mCount;
U8 mKey[SIZE];
DATA mData[SIZE];
LLUUIDHashNode<DATA, SIZE> *mNextNodep;
};
//
// LLUUIDHashNode implementation
//
template <class DATA, int SIZE>
LLUUIDHashNode<DATA, SIZE>::LLUUIDHashNode()
{
mCount = 0;
mNextNodep = NULL;
}
template <class DATA_TYPE, int SIZE>
class LLUUIDHashMap
{
public:
// basic constructor including sorter
LLUUIDHashMap(BOOL (*equals)(const LLUUID &uuid, const DATA_TYPE &data),
const DATA_TYPE &null_data);
~LLUUIDHashMap();
inline DATA_TYPE &get(const LLUUID &uuid);
inline BOOL check(const LLUUID &uuid) const;
inline DATA_TYPE &set(const LLUUID &uuid, const DATA_TYPE &type);
inline BOOL remove(const LLUUID &uuid);
void removeAll();
inline S32 getLength() const; // Warning, NOT O(1!)
public:
BOOL (*mEquals)(const LLUUID &uuid, const DATA_TYPE &data);
LLUUIDHashNode<DATA_TYPE, SIZE> mNodes[256];
S32 mIterCount;
protected:
DATA_TYPE mNull;
};
//
// LLUUIDHashMap implementation
//
template <class DATA_TYPE, int SIZE>
LLUUIDHashMap<DATA_TYPE, SIZE>::LLUUIDHashMap(BOOL (*equals)(const LLUUID &uuid, const DATA_TYPE &data),
const DATA_TYPE &null_data)
: mEquals(equals),
mIterCount(0),
mNull(null_data)
{ }
template <class DATA_TYPE, int SIZE>
LLUUIDHashMap<DATA_TYPE, SIZE>::~LLUUIDHashMap()
{
removeAll();
}
template <class DATA_TYPE, int SIZE>
void LLUUIDHashMap<DATA_TYPE, SIZE>::removeAll()
{
S32 bin;
for (bin = 0; bin < 256; bin++)
{
LLUUIDHashNode<DATA_TYPE, SIZE>* nodep = &mNodes[bin];
BOOL first = TRUE;
while (nodep)
{
S32 i;
const S32 count = nodep->mCount;
// Iterate through all members of this node
for (i = 0; i < count; i++)
{
nodep->mData[i] = mNull;
}
nodep->mCount = 0;
// Done with all objects in this node, go to the next.
LLUUIDHashNode<DATA_TYPE, SIZE>* curp = nodep;
nodep = nodep->mNextNodep;
// Delete the node if it's not the first node
if (first)
{
first = FALSE;
curp->mNextNodep = NULL;
}
else
{
delete curp;
}
}
}
}
template <class DATA_TYPE, int SIZE>
inline S32 LLUUIDHashMap<DATA_TYPE, SIZE>::getLength() const
{
S32 count = 0;
S32 bin;
for (bin = 0; bin < 256; bin++)
{
LLUUIDHashNode<DATA_TYPE, SIZE>* nodep = (LLUUIDHashNode<DATA_TYPE, SIZE>*) &mNodes[bin];
while (nodep)
{
count += nodep->mCount;
nodep = nodep->mNextNodep;
}
}
return count;
}
template <class DATA_TYPE, int SIZE>
inline DATA_TYPE &LLUUIDHashMap<DATA_TYPE, SIZE>::get(const LLUUID &uuid)
{
LLUUIDHashNode<DATA_TYPE, SIZE>* nodep = &mNodes[uuid.mData[0]];
// Grab the second byte of the UUID, which is the key for the node data
const S32 second_byte = uuid.mData[1];
while (nodep)
{
S32 i;
const S32 count = nodep->mCount;
// Iterate through all members of this node
for (i = 0; i < count; i++)
{
if ((nodep->mKey[i] == second_byte) && mEquals(uuid, nodep->mData[i]))
{
// The second byte matched, and our equality test passed.
// We found it.
return nodep->mData[i];
}
}
// Done with all objects in this node, go to the next.
nodep = nodep->mNextNodep;
}
return mNull;
}
template <class DATA_TYPE, int SIZE>
inline BOOL LLUUIDHashMap<DATA_TYPE, SIZE>::check(const LLUUID &uuid) const
{
const LLUUIDHashNode<DATA_TYPE, SIZE>* nodep = &mNodes[uuid.mData[0]];
// Grab the second byte of the UUID, which is the key for the node data
const S32 second_byte = uuid.mData[1];
while (nodep)
{
S32 i;
const S32 count = nodep->mCount;
// Iterate through all members of this node
for (i = 0; i < count; i++)
{
if ((nodep->mKey[i] == second_byte) && mEquals(uuid, nodep->mData[i]))
{
// The second byte matched, and our equality test passed.
// We found it.
return TRUE;
}
}
// Done with all objects in this node, go to the next.
nodep = nodep->mNextNodep;
}
// Didn't find anything
return FALSE;
}
template <class DATA_TYPE, int SIZE>
inline DATA_TYPE &LLUUIDHashMap<DATA_TYPE, SIZE>::set(const LLUUID &uuid, const DATA_TYPE &data)
{
// Set is just like a normal find, except that if we find a match
// we replace it with the input value.
// If we don't find a match, we append to the end of the list.
LLUUIDHashNode<DATA_TYPE, SIZE>* nodep = &mNodes[uuid.mData[0]];
const S32 second_byte = uuid.mData[1];
while (1)
{
const S32 count = nodep->mCount;
S32 i;
for (i = 0; i < count; i++)
{
if ((nodep->mKey[i] == second_byte) && mEquals(uuid, nodep->mData[i]))
{
// We found a match for this key, replace the data with
// the incoming data.
nodep->mData[i] = data;
return nodep->mData[i];
}
}
if (!nodep->mNextNodep)
{
// We've iterated through all of the keys without finding a match
if (i < SIZE)
{
// There's still some space on this node, append
// the key and data to it.
nodep->mKey[i] = second_byte;
nodep->mData[i] = data;
nodep->mCount++;
return nodep->mData[i];
}
else
{
// This node is full, append a new node to the end.
nodep->mNextNodep = new LLUUIDHashNode<DATA_TYPE, SIZE>;
nodep->mNextNodep->mKey[0] = second_byte;
nodep->mNextNodep->mData[0] = data;
nodep->mNextNodep->mCount = 1;
return nodep->mNextNodep->mData[0];
}
}
// No match on this node, go to the next
nodep = nodep->mNextNodep;
}
}
template <class DATA_TYPE, int SIZE>
inline BOOL LLUUIDHashMap<DATA_TYPE, SIZE>::remove(const LLUUID &uuid)
{
if (mIterCount)
{
// We don't allow remove when we're iterating, it's bad karma!
llerrs << "Attempted remove while an outstanding iterator in LLUUIDHashMap!" << llendl;
}
// Remove is the trickiest operation.
// What we want to do is swap the last element of the last
// node if we find the one that we want to remove, but we have
// to deal with deleting the node from the tail if it's empty, but
// NOT if it's the only node left.
LLUUIDHashNode<DATA_TYPE, SIZE> *nodep = &mNodes[uuid.mData[0]];
// Not empty, we need to search through the nodes
const S32 second_byte = uuid.mData[1];
// A modification of the standard search algorithm.
while (nodep)
{
const S32 count = nodep->mCount;
S32 i;
for (i = 0; i < count; i++)
{
if ((nodep->mKey[i] == second_byte) && mEquals(uuid, nodep->mData[i]))
{
// We found the node that we want to remove.
// Find the last (and next-to-last) node, and the index of the last
// element. We could conceviably start from the node we're on,
// but that makes it more complicated, this is easier.
LLUUIDHashNode<DATA_TYPE, SIZE> *prevp = &mNodes[uuid.mData[0]];
LLUUIDHashNode<DATA_TYPE, SIZE> *lastp = prevp;
// Find the last and next-to-last
while (lastp->mNextNodep)
{
prevp = lastp;
lastp = lastp->mNextNodep;
}
// First, swap in the last to the current location.
nodep->mKey[i] = lastp->mKey[lastp->mCount - 1];
nodep->mData[i] = lastp->mData[lastp->mCount - 1];
// Now, we delete the entry
lastp->mCount--;
lastp->mData[lastp->mCount] = mNull;
if (!lastp->mCount)
{
// We deleted the last element!
if (lastp != &mNodes[uuid.mData[0]])
{
// Only blitz the node if it's not the head
// Set the previous node to point to NULL, then
// blitz the empty last node
prevp->mNextNodep = NULL;
delete lastp;
}
}
return TRUE;
}
}
// Iterate to the next node, we've scanned all the entries in this one.
nodep = nodep->mNextNodep;
}
return FALSE;
}
//
// LLUUIDHashMapIter
//
template <class DATA_TYPE, int SIZE>
class LLUUIDHashMapIter
{
public:
LLUUIDHashMapIter(LLUUIDHashMap<DATA_TYPE, SIZE> *hash_mapp);
~LLUUIDHashMapIter();
inline void reset();
inline void first();
inline void next();
inline BOOL done() const;
DATA_TYPE& operator*() const
{
return mCurHashNodep->mData[mCurHashNodeKey];
}
DATA_TYPE* operator->() const
{
return &(operator*());
}
protected:
LLUUIDHashMap<DATA_TYPE, SIZE> *mHashMapp;
LLUUIDHashNode<DATA_TYPE, SIZE> *mCurHashNodep;
S32 mCurHashMapNodeNum;
S32 mCurHashNodeKey;
DATA_TYPE mNull;
};
//
// LLUUIDHashMapIter Implementation
//
template <class DATA_TYPE, int SIZE>
LLUUIDHashMapIter<DATA_TYPE, SIZE>::LLUUIDHashMapIter(LLUUIDHashMap<DATA_TYPE, SIZE> *hash_mapp)
{
mHashMapp = hash_mapp;
mCurHashNodep = NULL;
mCurHashMapNodeNum = 0;
mCurHashNodeKey = 0;
}
template <class DATA_TYPE, int SIZE>
LLUUIDHashMapIter<DATA_TYPE, SIZE>::~LLUUIDHashMapIter()
{
reset();
}
template <class DATA_TYPE, int SIZE>
inline void LLUUIDHashMapIter<DATA_TYPE, SIZE>::reset()
{
if (mCurHashNodep)
{
// We're partway through an iteration, we can clean up now
mHashMapp->mIterCount--;
mCurHashNodep = NULL;
}
}
template <class DATA_TYPE, int SIZE>
inline void LLUUIDHashMapIter<DATA_TYPE, SIZE>::first()
{
// Iterate through until we find the first non-empty node;
S32 i;
for (i = 0; i < 256; i++)
{
if (mHashMapp->mNodes[i].mCount)
{
if (!mCurHashNodep)
{
// Increment, since it's no longer safe for us to do a remove
mHashMapp->mIterCount++;
}
mCurHashNodep = &mHashMapp->mNodes[i];
mCurHashMapNodeNum = i;
mCurHashNodeKey = 0;
//return mCurHashNodep->mData[0];
return;
}
}
// Completely empty!
mCurHashNodep = NULL;
//return mNull;
return;
}
template <class DATA_TYPE, int SIZE>
inline BOOL LLUUIDHashMapIter<DATA_TYPE, SIZE>::done() const
{
return mCurHashNodep ? FALSE : TRUE;
}
template <class DATA_TYPE, int SIZE>
inline void LLUUIDHashMapIter<DATA_TYPE, SIZE>::next()
{
// No current entry, this iterator is done
if (!mCurHashNodep)
{
//return mNull;
return;
}
// Go to the next element
mCurHashNodeKey++;
if (mCurHashNodeKey < mCurHashNodep->mCount)
{
// We're not done with this node, return the current element
//return mCurHashNodep->mData[mCurHashNodeKey];
return;
}
// Done with this node, move to the next
mCurHashNodep = mCurHashNodep->mNextNodep;
if (mCurHashNodep)
{
// Return the first element
mCurHashNodeKey = 0;
//return mCurHashNodep->mData[0];
return;
}
// Find the next non-empty node (keyed on the first byte)
mCurHashMapNodeNum++;
S32 i;
for (i = mCurHashMapNodeNum; i < 256; i++)
{
if (mHashMapp->mNodes[i].mCount)
{
// We found one that wasn't empty
mCurHashNodep = &mHashMapp->mNodes[i];
mCurHashMapNodeNum = i;
mCurHashNodeKey = 0;
//return mCurHashNodep->mData[0];
return;
}
}
// OK, we're done, nothing else to iterate
mCurHashNodep = NULL;
mHashMapp->mIterCount--; // Decrement since we're safe to do removes now
//return mNull;
}
#endif // LL_LLUUIDHASHMAP_H

View File

@@ -0,0 +1,36 @@
/* Copyright (C) 2013 Siana Gearz
*
* 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; either
* version 2.1 of the License, or (at your option) any later version.
*
* 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 */
#ifndef SGUUIDHASH_H
#define SGUUIDHASH_H
#include "lluuid.h"
#include <boost/functional/hash.hpp>
#include <boost/unordered_map.hpp>
namespace boost {
template<> class hash<LLUUID> {
public:
size_t operator()(const LLUUID& id ) const
{
return *reinterpret_cast<const size_t*>(id.mData);
}
};
}
#endif

View File

@@ -89,6 +89,10 @@ const U8 PERM_GROUP = 0x04;
const U8 PERM_EVERYONE = 0x08;
const U8 PERM_NEXT_OWNER = 0x10;
// Boolean values for "Set".
const U8 PERM_SET_TRUE = 0x1;
const U8 PERM_SET_FALSE = 0x0;
// This is just a quickie debugging key
// no modify: PERM_ALL & ~PERM_MODIFY = 0x7fffbfff
// no copy: PERM_ALL & ~PERM_COPY = 0x7fff7fff

View File

@@ -41,7 +41,7 @@ namespace expression {
//TODO: If we can find a better way to do this with boost::pheonix::bind lets do it
namespace { // anonymous
//namespace { // anonymous
template <typename T>
T min_glue(T a, T b)
@@ -91,7 +91,7 @@ struct lazy_bfunc_
}
};
} // end namespace anonymous
//} // end namespace anonymous
template <typename FPT, typename Iterator>
struct grammar

View File

@@ -52,7 +52,8 @@ class AIAverage {
U32 mN; // The number of calls to operator().
int const mNrOfBuckets; // Size of mData.
std::vector<Data> mData; // The buckets.
LLMutex mLock; // Mutex for all of the above data.
mutable LLMutex mLock; // Mutex for all of the above data.
public:
AIAverage(int number_of_buckets) : mCurrentClock(~(U64)0), mTail(0), mCurrentBucket(0), mSum(0), mN(0), mNrOfBuckets(number_of_buckets), mData(number_of_buckets)
@@ -88,7 +89,7 @@ class AIAverage {
mLock.unlock();
return sum;
}
double getAverage(double avg_no_data)
double getAverage(double avg_no_data) const
{
mLock.lock();
double avg = mSum;

View File

@@ -1248,10 +1248,10 @@ AIPerServicePtr CurlEasyRequest::getPerServicePtr(void)
return mPerServicePtr;
}
bool CurlEasyRequest::removeFromPerServiceQueue(AICurlEasyRequest const& easy_request) const
bool CurlEasyRequest::removeFromPerServiceQueue(AICurlEasyRequest const& easy_request, AICapabilityType capability_type) const
{
// Note that easy_request (must) represent(s) this object; it's just passed for convenience.
return mPerServicePtr && PerServiceRequestQueue_wat(*mPerServicePtr)->cancel(easy_request);
return mPerServicePtr && PerService_wat(*mPerServicePtr)->cancel(easy_request, capability_type);
}
std::string CurlEasyRequest::getLowercaseHostname(void) const
@@ -1269,7 +1269,8 @@ LLMutex BufferedCurlEasyRequest::sResponderCallbackMutex;
bool BufferedCurlEasyRequest::sShuttingDown = false;
AIAverage BufferedCurlEasyRequest::sHTTPBandwidth(25);
BufferedCurlEasyRequest::BufferedCurlEasyRequest() : mRequestTransferedBytes(0), mTotalRawBytes(0), mBufferEventsTarget(NULL), mStatus(HTTP_INTERNAL_ERROR_OTHER)
BufferedCurlEasyRequest::BufferedCurlEasyRequest() :
mRequestTransferedBytes(0), mTotalRawBytes(0), mStatus(HTTP_INTERNAL_ERROR_OTHER), mBufferEventsTarget(NULL), mCapabilityType(number_of_capability_types)
{
AICurlInterface::Stats::BufferedCurlEasyRequest_count++;
}
@@ -1401,6 +1402,9 @@ void BufferedCurlEasyRequest::prepRequest(AICurlEasyRequest_wat& curl_easy_reque
// Keep responder alive.
mResponder = responder;
// Cache capability type, because it will be needed even after the responder was removed.
mCapabilityType = responder->capability_type();
// Send header events to responder if needed.
if (mResponder->needsHeaders())
{

View File

@@ -42,10 +42,7 @@
#include "llcontrol.h"
AIPerService::threadsafe_instance_map_type AIPerService::sInstanceMap;
LLAtomicS32 AIPerService::sTotalQueued;
bool AIPerService::sQueueEmpty;
bool AIPerService::sQueueFull;
bool AIPerService::sRequestStarvation;
AIThreadSafeSimpleDC<AIPerService::TotalQueued> AIPerService::sTotalQueued;
#undef AICurlPrivate
@@ -54,14 +51,14 @@ namespace AICurlPrivate {
// Cached value of CurlConcurrentConnectionsPerService.
U32 CurlConcurrentConnectionsPerService;
// Friend functions of RefCountedThreadSafePerServiceRequestQueue
// Friend functions of RefCountedThreadSafePerService
void intrusive_ptr_add_ref(RefCountedThreadSafePerServiceRequestQueue* per_service)
void intrusive_ptr_add_ref(RefCountedThreadSafePerService* per_service)
{
per_service->mReferenceCount++;
}
void intrusive_ptr_release(RefCountedThreadSafePerServiceRequestQueue* per_service)
void intrusive_ptr_release(RefCountedThreadSafePerService* per_service)
{
if (--per_service->mReferenceCount == 0)
{
@@ -74,14 +71,24 @@ void intrusive_ptr_release(RefCountedThreadSafePerServiceRequestQueue* per_servi
using namespace AICurlPrivate;
AIPerService::AIPerService(void) :
mQueuedCommands(0), mAdded(0), mQueueEmpty(false),
mQueueFull(false), mRequestStarvation(false), mHTTPBandwidth(25), // 25 = 1000 ms / 40 ms.
mHTTPBandwidth(25), // 25 = 1000 ms / 40 ms.
mConcurrectConnections(CurlConcurrentConnectionsPerService),
mTotalAdded(0),
mApprovedFirst(0),
mUnapprovedFirst(0)
{
}
AIPerService::CapabilityType::CapabilityType(void) :
mApprovedRequests(0),
mQueuedCommands(0),
mAdded(0),
mFlags(0),
mMaxPipelinedRequests(CurlConcurrentConnectionsPerService)
{
}
AIPerService::~AIPerService()
AIPerService::CapabilityType::~CapabilityType()
{
}
@@ -194,7 +201,7 @@ AIPerServicePtr AIPerService::instance(std::string const& servicename)
AIPerService::iterator iter = instance_map_w->find(servicename);
if (iter == instance_map_w->end())
{
iter = instance_map_w->insert(instance_map_type::value_type(servicename, new RefCountedThreadSafePerServiceRequestQueue)).first;
iter = instance_map_w->insert(instance_map_type::value_type(servicename, new RefCountedThreadSafePerService)).first;
}
// Note: the creation of AIPerServicePtr MUST be protected by the lock on sInstanceMap (see release()).
return iter->second;
@@ -215,12 +222,20 @@ void AIPerService::release(AIPerServicePtr& instance)
// Therefore, recheck the condition now that we have locked sInstanceMap.
if (!instance->exactly_two_left())
{
// Some other thread added this host in the meantime.
// Some other thread added this service in the meantime.
return;
}
// The reference in the map is the last one; that means there can't be any curl easy requests queued for this host.
llassert(PerServiceRequestQueue_rat(*instance)->mQueuedRequests.empty());
// Find the host and erase it from the map.
#ifdef SHOW_ASSERT
{
// The reference in the map is the last one; that means there can't be any curl easy requests queued for this service.
PerService_rat per_service_r(*instance);
for (int i = 0; i < number_of_capability_types; ++i)
{
llassert(per_service_r->mCapabilityType[i].mQueuedRequests.empty());
}
}
#endif
// Find the service and erase it from the map.
iterator const end = instance_map_w->end();
for(iterator iter = instance_map_w->begin(); iter != end; ++iter)
{
@@ -231,7 +246,7 @@ void AIPerService::release(AIPerServicePtr& instance)
return;
}
}
// We should always find the host.
// We should always find the service.
llassert(false);
}
instance.reset();
@@ -239,30 +254,32 @@ void AIPerService::release(AIPerServicePtr& instance)
bool AIPerService::throttled() const
{
return mAdded >= mConcurrectConnections;
return mTotalAdded >= mConcurrectConnections;
}
void AIPerService::added_to_multi_handle(void)
void AIPerService::added_to_multi_handle(AICapabilityType capability_type)
{
++mAdded;
++mCapabilityType[capability_type].mAdded;
++mTotalAdded;
}
void AIPerService::removed_from_multi_handle(void)
void AIPerService::removed_from_multi_handle(AICapabilityType capability_type)
{
--mAdded;
llassert(mAdded >= 0);
--mCapabilityType[capability_type].mAdded;
--mTotalAdded;
llassert(mTotalAdded >= 0 && mCapabilityType[capability_type].mAdded >= 0);
}
void AIPerService::queue(AICurlEasyRequest const& easy_request)
void AIPerService::queue(AICurlEasyRequest const& easy_request, AICapabilityType capability_type)
{
mQueuedRequests.push_back(easy_request.get_ptr());
sTotalQueued++;
mCapabilityType[capability_type].mQueuedRequests.push_back(easy_request.get_ptr());
TotalQueued_wat(sTotalQueued)->count++;
}
bool AIPerService::cancel(AICurlEasyRequest const& easy_request)
bool AIPerService::cancel(AICurlEasyRequest const& easy_request, AICapabilityType capability_type)
{
queued_request_type::iterator const end = mQueuedRequests.end();
queued_request_type::iterator cur = std::find(mQueuedRequests.begin(), end, easy_request.get_ptr());
CapabilityType::queued_request_type::iterator const end = mCapabilityType[capability_type].mQueuedRequests.end();
CapabilityType::queued_request_type::iterator cur = std::find(mCapabilityType[capability_type].mQueuedRequests.begin(), end, easy_request.get_ptr());
if (cur == end)
return false; // Not found.
@@ -273,55 +290,122 @@ bool AIPerService::cancel(AICurlEasyRequest const& easy_request)
// want to break the order in which requests where added). Swap is also not
// thread-safe, but OK here because it only touches the objects in the deque,
// and the deque is protected by the lock on the AIPerService object.
queued_request_type::iterator prev = cur;
CapabilityType::queued_request_type::iterator prev = cur;
while (++cur != end)
{
prev->swap(*cur); // This is safe,
prev = cur;
}
mQueuedRequests.pop_back(); // if this is safe.
--sTotalQueued;
llassert(sTotalQueued >= 0);
mCapabilityType[capability_type].mQueuedRequests.pop_back(); // if this is safe.
TotalQueued_wat total_queued_w(sTotalQueued);
total_queued_w->count--;
llassert(total_queued_w->count >= 0);
return true;
}
void AIPerService::add_queued_to(curlthread::MultiHandle* multi_handle)
void AIPerService::add_queued_to(curlthread::MultiHandle* multi_handle, bool recursive)
{
if (!mQueuedRequests.empty())
int order[number_of_capability_types];
// The first two types are approved types, they should be the first to try.
// Try the one that has the largest queue first, if they the queues have equal size, try mApprovedFirst first.
size_t s0 = mCapabilityType[0].mQueuedRequests.size();
size_t s1 = mCapabilityType[1].mQueuedRequests.size();
if (s0 == s1)
{
multi_handle->add_easy_request(mQueuedRequests.front());
mQueuedRequests.pop_front();
llassert(sTotalQueued > 0);
if (!--sTotalQueued)
{
// We obtained a request from the queue, and after that there we no more request in any queue.
sQueueEmpty = true;
}
else
{
// We obtained a request from the queue, and even after that there was at least one more request in some queue.
sQueueFull = true;
}
if (mQueuedRequests.empty())
{
// We obtained a request from the queue, and after that there we no more request in the queue of this host.
mQueueEmpty = true;
}
else
{
// We obtained a request from the queue, and even after that there was at least one more request in the queue of this host.
mQueueFull = true;
}
order[0] = mApprovedFirst;
mApprovedFirst = 1 - mApprovedFirst;
order[1] = mApprovedFirst;
}
else if (s0 > s1)
{
order[0] = 0;
order[1] = 1;
}
else
{
// We can add a new request, but there is none in the queue!
mRequestStarvation = true;
if (sTotalQueued == 0)
order[0] = 1;
order[1] = 0;
}
// The next two types are unapproved types. Here, try them alternating regardless of queue size.
int n = mUnapprovedFirst;
for (int i = 2; i < number_of_capability_types; ++i, n = (n + 1) % (number_of_capability_types - 2))
{
order[i] = 2 + n;
}
mUnapprovedFirst = (mUnapprovedFirst + 1) % (number_of_capability_types - 2);
for (int i = 0; i < number_of_capability_types; ++i)
{
CapabilityType& ct(mCapabilityType[order[i]]);
if (!ct.mQueuedRequests.empty())
{
// The queue of every host is empty!
sRequestStarvation = true;
if (!multi_handle->add_easy_request(ct.mQueuedRequests.front(), true))
{
// Throttled. If this failed then every capability type will fail: we either are using too much bandwidth, or too many total connections.
// However, it MAY be that this service was thottled for using too much bandwidth by itself. Look if other services can be added.
break;
}
// Request was added, remove it from the queue.
ct.mQueuedRequests.pop_front();
if (ct.mQueuedRequests.empty())
{
// We obtained a request from the queue, and after that there we no more request in the queue of this service.
ct.mFlags |= ctf_empty;
}
else
{
// We obtained a request from the queue, and even after that there was at least one more request in the queue of this service.
ct.mFlags |= ctf_full;
}
TotalQueued_wat total_queued_w(sTotalQueued);
llassert(total_queued_w->count > 0);
if (!--(total_queued_w->count))
{
// We obtained a request from the queue, and after that there we no more request in any queue.
total_queued_w->empty = true;
}
else
{
// We obtained a request from the queue, and even after that there was at least one more request in some queue.
total_queued_w->full = true;
}
// We added something from a queue, so we're done.
return;
}
else
{
// We could add a new request, but there is none in the queue!
// Note that if this service does not serve this capability type,
// then obviously this queue was empty; however, in that case
// this variable will never be looked at, so it's ok to set it.
ct.mFlags |= ctf_starvation;
}
if (i == number_of_capability_types - 1)
{
// Last entry also empty. All queues of this service were empty. Check total connections.
TotalQueued_wat total_queued_w(sTotalQueued);
if (total_queued_w->count == 0)
{
// The queue of every service is empty!
total_queued_w->starvation = true;
return;
}
}
}
if (recursive)
{
return;
}
// Nothing from this service could be added, try other services.
instance_map_wat instance_map_w(sInstanceMap);
for (iterator service = instance_map_w->begin(); service != instance_map_w->end(); ++service)
{
PerService_wat per_service_w(*service->second);
if (&*per_service_w == this)
{
continue;
}
per_service_w->add_queued_to(multi_handle, true);
}
}
@@ -329,14 +413,18 @@ void AIPerService::add_queued_to(curlthread::MultiHandle* multi_handle)
void AIPerService::purge(void)
{
instance_map_wat instance_map_w(sInstanceMap);
for (iterator host = instance_map_w->begin(); host != instance_map_w->end(); ++host)
for (iterator service = instance_map_w->begin(); service != instance_map_w->end(); ++service)
{
Dout(dc::curl, "Purging queue of host \"" << host->first << "\".");
PerServiceRequestQueue_wat per_service_w(*host->second);
size_t s = per_service_w->mQueuedRequests.size();
per_service_w->mQueuedRequests.clear();
sTotalQueued -= s;
llassert(sTotalQueued >= 0);
Dout(dc::curl, "Purging queues of service \"" << service->first << "\".");
PerService_wat per_service_w(*service->second);
TotalQueued_wat total_queued_w(sTotalQueued);
for (int i = 0; i < number_of_capability_types; ++i)
{
size_t s = per_service_w->mCapabilityType[i].mQueuedRequests.size();
per_service_w->mCapabilityType[i].mQueuedRequests.clear();
total_queued_w->count -= s;
llassert(total_queued_w->count >= 0);
}
}
}
@@ -346,11 +434,31 @@ void AIPerService::adjust_concurrent_connections(int increment)
instance_map_wat instance_map_w(sInstanceMap);
for (AIPerService::iterator iter = instance_map_w->begin(); iter != instance_map_w->end(); ++iter)
{
PerServiceRequestQueue_wat per_service_w(*iter->second);
PerService_wat per_service_w(*iter->second);
U32 old_concurrent_connections = per_service_w->mConcurrectConnections;
per_service_w->mConcurrectConnections = llclamp(old_concurrent_connections + increment, (U32)1, CurlConcurrentConnectionsPerService);
increment = per_service_w->mConcurrectConnections - old_concurrent_connections;
per_service_w->mMaxPipelinedRequests = llmax(per_service_w->mMaxPipelinedRequests + increment, 0);
for (int i = 0; i < number_of_capability_types; ++i)
{
per_service_w->mCapabilityType[i].mMaxPipelinedRequests = llmax(per_service_w->mCapabilityType[i].mMaxPipelinedRequests + increment, (U32)0);
}
}
}
void AIPerService::Approvement::honored(void)
{
if (!mHonored)
{
mHonored = true;
AICurlPrivate::PerService_wat per_service_w(*mPerServicePtr);
llassert(per_service_w->mCapabilityType[mCapabilityType].mApprovedRequests > 0);
per_service_w->mCapabilityType[mCapabilityType].mApprovedRequests--;
}
}
void AIPerService::Approvement::not_honored(void)
{
honored();
llwarns << "Approvement for has not been honored." << llendl;
}

View File

@@ -53,7 +53,7 @@ class AIPerService;
namespace AICurlPrivate {
namespace curlthread { class MultiHandle; }
class RefCountedThreadSafePerServiceRequestQueue;
class RefCountedThreadSafePerService;
class ThreadSafeBufferedCurlEasyRequest;
// Forward declaration of BufferedCurlEasyRequestPtr (see aicurlprivate.h).
@@ -61,25 +61,37 @@ typedef boost::intrusive_ptr<ThreadSafeBufferedCurlEasyRequest> BufferedCurlEasy
// AIPerService objects are created by the curl thread and destructed by the main thread.
// We need locking.
typedef AIThreadSafeSimpleDC<AIPerService> threadsafe_PerServiceRequestQueue;
typedef AIAccessConst<AIPerService> PerServiceRequestQueue_crat;
typedef AIAccess<AIPerService> PerServiceRequestQueue_rat;
typedef AIAccess<AIPerService> PerServiceRequestQueue_wat;
typedef AIThreadSafeSimpleDC<AIPerService> threadsafe_PerService;
typedef AIAccessConst<AIPerService> PerService_crat;
typedef AIAccess<AIPerService> PerService_rat;
typedef AIAccess<AIPerService> PerService_wat;
} // namespace AICurlPrivate
// We can't put threadsafe_PerServiceRequestQueue in a std::map because you can't copy a mutex.
// We can't put threadsafe_PerService in a std::map because you can't copy a mutex.
// Therefore, use an intrusive pointer for the threadsafe type.
typedef boost::intrusive_ptr<AICurlPrivate::RefCountedThreadSafePerServiceRequestQueue> AIPerServicePtr;
typedef boost::intrusive_ptr<AICurlPrivate::RefCountedThreadSafePerService> AIPerServicePtr;
//-----------------------------------------------------------------------------
//
enum AICapabilityType { // {Capabilities} [Responders]
cap_texture = 0, // GetTexture [HTTPGetResponder]
cap_inventory = 1, // { FetchInventory2, FetchLib2 } [LLInventoryModel::fetchInventoryResponder], { FetchInventoryDescendents2, FetchLibDescendents2 } [LLInventoryModelFetchDescendentsResponder]
cap_mesh = 2, // GetMesh [LLMeshSkinInfoResponder, LLMeshDecompositionResponder, LLMeshPhysicsShapeResponder, LLMeshHeaderResponder, LLMeshLODResponder]
cap_other = 3, // All other capabilities
number_of_capability_types = 4
};
//-----------------------------------------------------------------------------
// AIPerService
// This class provides a static interface to create and maintain instances
// of AIPerService objects, so that at any moment there is at most
// one instance per hostname:port. Those instances then are used to queue curl
// requests when the maximum number of connections for that host already
// have been reached.
// This class provides a static interface to create and maintain instances of AIPerService objects,
// so that at any moment there is at most one instance per service (hostname:port).
// Those instances then are used to queue curl requests when the maximum number of connections
// for that service already have been reached. And to keep track of the bandwidth usage, and the
// number of queued requests in the pipeline, for this service.
class AIPerService {
private:
typedef std::map<std::string, AIPerServicePtr> instance_map_type;
@@ -89,12 +101,9 @@ class AIPerService {
static threadsafe_instance_map_type sInstanceMap; // Map of AIPerService instances with the hostname as key.
friend class AIThreadSafeSimpleDC<AIPerService>; //threadsafe_PerServiceRequestQueue
friend class AIThreadSafeSimpleDC<AIPerService>; // threadsafe_PerService
AIPerService(void);
public:
~AIPerService();
public:
typedef instance_map_type::iterator iterator;
typedef instance_map_type::const_iterator const_iterator;
@@ -112,53 +121,135 @@ class AIPerService {
static void purge(void);
private:
typedef std::deque<AICurlPrivate::BufferedCurlEasyRequestPtr> queued_request_type;
static U16 const ctf_empty = 1;
static U16 const ctf_full = 2;
static U16 const ctf_starvation = 4;
int mQueuedCommands; // Number of add commands (minus remove commands) with this host in the command queue.
int mAdded; // Number of active easy handles with this host.
queued_request_type mQueuedRequests; // Waiting (throttled) requests.
struct CapabilityType {
typedef std::deque<AICurlPrivate::BufferedCurlEasyRequestPtr> queued_request_type;
static LLAtomicS32 sTotalQueued; // The sum of mQueuedRequests.size() of all AIPerService objects together.
queued_request_type mQueuedRequests; // Waiting (throttled) requests.
U16 mApprovedRequests; // The number of approved requests by approveHTTPRequestFor that were not added to the command queue yet.
U16 mQueuedCommands; // Number of add commands (minus remove commands), for this service, in the command queue.
U16 mAdded; // Number of active easy handles with this service.
U16 mFlags; // ctf_empty: Set to true when the queue becomes precisely empty.
// ctf_full : Set to true when the queue is popped and then still isn't empty;
// ctf_starvation: Set to true when the queue was about to be popped but was already empty.
U32 mMaxPipelinedRequests; // The maximum number of accepted requests for this service and (approved) capability type, that didn't finish yet.
bool mQueueEmpty; // Set to true when the queue becomes precisely empty.
bool mQueueFull; // Set to true when the queue is popped and then still isn't empty;
bool mRequestStarvation; // Set to true when the queue was about to be popped but was already empty.
// Declare, not define, constructor and destructor - in order to avoid instantiation of queued_request_type from header.
CapabilityType(void);
~CapabilityType();
static bool sQueueEmpty; // Set to true when sTotalQueued becomes precisely zero as the result of popping any queue.
static bool sQueueFull; // Set to true when sTotalQueued is still larger than zero after popping any queue.
static bool sRequestStarvation; // Set to true when any queue was about to be popped when sTotalQueued was already zero.
S32 pipelined_requests(void) const { return mApprovedRequests + mQueuedCommands + mQueuedRequests.size() + mAdded; }
};
CapabilityType mCapabilityType[number_of_capability_types];
AIAverage mHTTPBandwidth; // Keeps track on number of bytes received for this service in the past second.
int mConcurrectConnections; // The maximum number of allowed concurrent connections to this service.
int mMaxPipelinedRequests; // The maximum number of accepted requests that didn't finish yet.
int mTotalAdded; // Number of active easy handles with this host.
int mApprovedFirst; // First capability type to try.
int mUnapprovedFirst; // First capability type to try after all approved types were tried.
// Global administration of the total number of queued requests of all services combined.
private:
struct TotalQueued {
S32 count; // The sum of mQueuedRequests.size() of all AIPerService objects together.
bool empty; // Set to true when count becomes precisely zero as the result of popping any queue.
bool full; // Set to true when count is still larger than zero after popping any queue.
bool starvation; // Set to true when any queue was about to be popped when count was already zero.
TotalQueued(void) : count(0), empty(false), full(false), starvation(false) { }
};
static AIThreadSafeSimpleDC<TotalQueued> sTotalQueued;
typedef AIAccessConst<TotalQueued> TotalQueued_crat;
typedef AIAccess<TotalQueued> TotalQueued_rat;
typedef AIAccess<TotalQueued> TotalQueued_wat;
public:
static S32 total_queued_size(void) { return TotalQueued_rat(sTotalQueued)->count; }
// Global administration of the maximum number of pipelined requests of all services combined.
private:
struct MaxPipelinedRequests {
S32 count; // The maximum total number of accepted requests that didn't finish yet.
U64 last_increment; // Last time that sMaxPipelinedRequests was incremented.
U64 last_decrement; // Last time that sMaxPipelinedRequests was decremented.
MaxPipelinedRequests(void) : count(32), last_increment(0), last_decrement(0) { }
};
static AIThreadSafeSimpleDC<MaxPipelinedRequests> sMaxPipelinedRequests;
typedef AIAccessConst<MaxPipelinedRequests> MaxPipelinedRequests_crat;
typedef AIAccess<MaxPipelinedRequests> MaxPipelinedRequests_rat;
typedef AIAccess<MaxPipelinedRequests> MaxPipelinedRequests_wat;
public:
static void setMaxPipelinedRequests(S32 count) { MaxPipelinedRequests_wat(sMaxPipelinedRequests)->count = count; }
static void incrementMaxPipelinedRequests(S32 increment) { MaxPipelinedRequests_wat(sMaxPipelinedRequests)->count += increment; }
// Global administration of throttle fraction (which is the same for all services).
private:
struct ThrottleFraction {
U32 fraction; // A value between 0 and 1024: each service is throttled when it uses more than max_bandwidth * (sThrottleFraction/1024) bandwidth.
AIAverage average; // Average of fraction over 25 * 40ms = 1 second.
U64 last_add; // Last time that faction was added to average.
ThrottleFraction(void) : fraction(1024), average(25), last_add(0) { }
};
static AIThreadSafeSimpleDC<ThrottleFraction> sThrottleFraction;
typedef AIAccessConst<ThrottleFraction> ThrottleFraction_crat;
typedef AIAccess<ThrottleFraction> ThrottleFraction_rat;
typedef AIAccess<ThrottleFraction> ThrottleFraction_wat;
static LLAtomicU32 sHTTPThrottleBandwidth125; // HTTPThrottleBandwidth times 125 (in bytes/s).
static bool sNoHTTPBandwidthThrottling; // Global override to disable bandwidth throttling.
public:
void added_to_command_queue(void) { ++mQueuedCommands; }
void removed_from_command_queue(void) { --mQueuedCommands; llassert(mQueuedCommands >= 0); }
void added_to_multi_handle(void); // Called when an easy handle for this host has been added to the multi handle.
void removed_from_multi_handle(void); // Called when an easy handle for this host is removed again from the multi handle.
void added_to_command_queue(AICapabilityType capability_type) { ++mCapabilityType[capability_type].mQueuedCommands; }
void removed_from_command_queue(AICapabilityType capability_type) { --mCapabilityType[capability_type].mQueuedCommands; llassert(mCapabilityType[capability_type].mQueuedCommands >= 0); }
void added_to_multi_handle(AICapabilityType capability_type); // Called when an easy handle for this host has been added to the multi handle.
void removed_from_multi_handle(AICapabilityType capability_type); // Called when an easy handle for this host is removed again from the multi handle.
bool throttled(void) const; // Returns true if the maximum number of allowed requests for this host have been added to the multi handle.
void queue(AICurlEasyRequest const& easy_request); // Add easy_request to the queue.
bool cancel(AICurlEasyRequest const& easy_request); // Remove easy_request from the queue (if it's there).
void queue(AICurlEasyRequest const& easy_request, AICapabilityType capability_type); // Add easy_request to the queue.
bool cancel(AICurlEasyRequest const& easy_request, AICapabilityType capability_type); // Remove easy_request from the queue (if it's there).
void add_queued_to(AICurlPrivate::curlthread::MultiHandle* mh);
void add_queued_to(AICurlPrivate::curlthread::MultiHandle* mh, bool recursive = false);
// Add queued easy handle (if any) to the multi handle. The request is removed from the queue,
// followed by either a call to added_to_multi_handle() or to queue() to add it back.
S32 pipelined_requests(void) const { return mQueuedCommands + mQueuedRequests.size() + mAdded; }
static S32 total_queued_size(void) { return sTotalQueued; }
S32 pipelined_requests(AICapabilityType capability_type) const { return mCapabilityType[capability_type].pipelined_requests(); }
AIAverage& bandwidth(void) { return mHTTPBandwidth; }
AIAverage const& bandwidth(void) const { return mHTTPBandwidth; }
static void setNoHTTPBandwidthThrottling(bool nb) { sNoHTTPBandwidthThrottling = nb; }
static void setHTTPThrottleBandwidth(F32 max_kbps) { sHTTPThrottleBandwidth125 = 125.f * max_kbps; }
static size_t getHTTPThrottleBandwidth125(void) { return sHTTPThrottleBandwidth125; }
// Called when CurlConcurrentConnectionsPerService changes.
static void adjust_concurrent_connections(int increment);
// Returns true if curl can handle another request for this host.
// Should return false if the maximum allowed HTTP bandwidth is reached, or when
// A helper class to decrement mApprovedRequests after requests approved by approveHTTPRequestFor were handled.
class Approvement : public LLThreadSafeRefCount {
private:
AIPerServicePtr mPerServicePtr;
AICapabilityType mCapabilityType;
bool mHonored;
public:
Approvement(AIPerServicePtr const& per_service, AICapabilityType capability_type) : mPerServicePtr(per_service), mCapabilityType(capability_type), mHonored(false) { }
~Approvement() { if (!mHonored) not_honored(); }
void honored(void);
void not_honored(void);
};
// The two following functions are static and have the AIPerService object passed
// as first argument as an AIPerServicePtr because that avoids the need of having
// the AIPerService object locked for the whole duration of the call.
// The functions only lock it when access is required.
// Returns approvement if curl can handle another request for this host.
// Should return NULL if the maximum allowed HTTP bandwidth is reached, or when
// the latency between request and actual delivery becomes too large.
static bool wantsMoreHTTPRequestsFor(AIPerServicePtr const& per_service, F32 max_kbps, bool no_bandwidth_throttling);
static Approvement* approveHTTPRequestFor(AIPerServicePtr const& per_service, AICapabilityType capability_type);
// Return true if too much bandwidth is being used.
static bool checkBandwidthUsage(AIPerServicePtr const& per_service, U64 sTime_40ms);
private:
// Disallow copying.
@@ -167,17 +258,17 @@ class AIPerService {
namespace AICurlPrivate {
class RefCountedThreadSafePerServiceRequestQueue : public threadsafe_PerServiceRequestQueue {
class RefCountedThreadSafePerService : public threadsafe_PerService {
public:
RefCountedThreadSafePerServiceRequestQueue(void) : mReferenceCount(0) { }
RefCountedThreadSafePerService(void) : mReferenceCount(0) { }
bool exactly_two_left(void) const { return mReferenceCount == 2; }
private:
// Used by AIPerServicePtr. Object is deleted when reference count reaches zero.
LLAtomicU32 mReferenceCount;
friend void intrusive_ptr_add_ref(RefCountedThreadSafePerServiceRequestQueue* p);
friend void intrusive_ptr_release(RefCountedThreadSafePerServiceRequestQueue* p);
friend void intrusive_ptr_add_ref(RefCountedThreadSafePerService* p);
friend void intrusive_ptr_release(RefCountedThreadSafePerService* p);
};
extern U32 CurlConcurrentConnectionsPerService;

View File

@@ -130,11 +130,17 @@ class CurlEasyHandle : public boost::noncopyable, protected AICurlEasyHandleEven
// Pause and unpause a connection.
CURLcode pause(int bitmask);
// Called if this request should be queued on the curl thread when too much bandwidth is being used.
void setApproved(AIPerService::Approvement* approved) { mApproved = approved; }
// Returns false when this request should be queued by the curl thread when too much bandwidth is being used.
bool approved(void) const { return mApproved; }
// Called when a request is queued for removal. In that case a race between the actual removal
// and revoking of the callbacks is harmless (and happens for the raw non-statemachine version).
void remove_queued(void) { mQueuedForRemoval = true; }
// In case it's added after being removed.
void add_queued(void) { mQueuedForRemoval = false; }
void add_queued(void) { mQueuedForRemoval = false; if (mApproved) { mApproved->honored(); } }
#ifdef DEBUG_CURLIO
void debug(bool debug) { if (mDebug) debug_curl_remove_easy(mEasyHandle); if (debug) debug_curl_add_easy(mEasyHandle); mDebug = debug; }
@@ -146,6 +152,7 @@ class CurlEasyHandle : public boost::noncopyable, protected AICurlEasyHandleEven
mutable char* mErrorBuffer;
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.
LLPointer<AIPerService::Approvement> mApproved; // When not set then the curl thread should check bandwidth usage and queue this request if too much is being used.
#ifdef DEBUG_CURLIO
bool mDebug;
#endif
@@ -351,8 +358,8 @@ class CurlEasyRequest : public CurlEasyHandle {
// PerService API.
AIPerServicePtr getPerServicePtr(void); // (Optionally create and) return a pointer to the unique
// AIPerService corresponding to mLowercaseServicename.
bool removeFromPerServiceQueue(AICurlEasyRequest const&) const; // Remove this request from the per-host queue, if queued at all.
// Returns true if it was queued.
bool removeFromPerServiceQueue(AICurlEasyRequest const&, AICapabilityType capability_type) const; // Remove this request from the per-host queue, if queued at all.
// Returns true if it was queued.
protected:
// Pass events to parent.
/*virtual*/ void added_to_multi_handle(AICurlEasyRequest_wat& curl_easy_request_w);
@@ -410,6 +417,7 @@ class BufferedCurlEasyRequest : public CurlEasyRequest {
U8* mLastRead; // Pointer into mInput where we last stopped reading (or NULL to start at the beginning).
buffer_ptr_t mOutput;
LLHTTPClient::ResponderPtr mResponder;
AICapabilityType mCapabilityType;
//U32 mBodyLimit; // From the old LLURLRequestDetail::mBodyLimit, but never used.
U32 mStatus; // HTTP status, decoded from the first header line.
std::string mReason; // The "reason" from the same header line.
@@ -452,6 +460,9 @@ class BufferedCurlEasyRequest : public CurlEasyRequest {
// Return true when prepRequest was already called and the object has not been
// invalidated as a result of calling timed_out().
bool isValid(void) const { return mResponder; }
// Return the capability type of this request.
AICapabilityType capability_type(void) const { llassert(mCapabilityType != number_of_capability_types); return mCapabilityType; }
};
inline ThreadSafeBufferedCurlEasyRequest* CurlEasyRequest::get_lockobj(void)

View File

@@ -206,8 +206,6 @@ int ioctlsocket(int fd, int, unsigned long* nonblocking_enable)
namespace AICurlPrivate {
LLAtomicS32 max_pipelined_requests(32);
enum command_st {
cmd_none,
cmd_add,
@@ -890,7 +888,7 @@ AICurlThread* AICurlThread::sInstance = NULL;
AICurlThread::AICurlThread(void) : LLThread("AICurlThread"),
mWakeUpFd_in(CURL_SOCKET_BAD),
mWakeUpFd(CURL_SOCKET_BAD),
mZeroTimeout(0), mRunning(true), mWakeUpFlag(false)
mZeroTimeout(0), mWakeUpFlag(false), mRunning(true)
{
create_wakeup_fds();
sInstance = this;
@@ -1327,19 +1325,30 @@ void AICurlThread::process_commands(AICurlMultiHandle_wat const& multi_handle_w)
// Access command_being_processed only.
{
command_being_processed_rat command_being_processed_r(command_being_processed);
AICapabilityType capability_type;
AIPerServicePtr per_service;
{
AICurlEasyRequest_wat easy_request_w(*command_being_processed_r->easy_request());
capability_type = easy_request_w->capability_type();
per_service = easy_request_w->getPerServicePtr();
}
switch(command_being_processed_r->command())
{
case cmd_none:
case cmd_boost: // FIXME: future stuff
break;
case cmd_add:
PerServiceRequestQueue_wat(*AICurlEasyRequest_wat(*command_being_processed_r->easy_request())->getPerServicePtr())->removed_from_command_queue();
multi_handle_w->add_easy_request(AICurlEasyRequest(command_being_processed_r->easy_request()));
{
multi_handle_w->add_easy_request(AICurlEasyRequest(command_being_processed_r->easy_request()), false);
PerService_wat(*per_service)->removed_from_command_queue(capability_type);
break;
}
case cmd_remove:
PerServiceRequestQueue_wat(*AICurlEasyRequest_wat(*command_being_processed_r->easy_request())->getPerServicePtr())->added_to_command_queue(); // Not really, but this has the same effect as 'removed a remove command'.
{
PerService_wat(*per_service)->added_to_command_queue(capability_type); // Not really, but this has the same effect as 'removed a remove command'.
multi_handle_w->remove_easy_request(AICurlEasyRequest(command_being_processed_r->easy_request()), true);
break;
}
}
// Done processing.
command_being_processed_wat command_being_processed_w(command_being_processed_r);
@@ -1703,40 +1712,53 @@ CURLMsg const* MultiHandle::info_read(int* msgs_in_queue) const
static U32 curl_max_total_concurrent_connections = 32; // Initialized on start up by startCurlThread().
void MultiHandle::add_easy_request(AICurlEasyRequest const& easy_request)
bool MultiHandle::add_easy_request(AICurlEasyRequest const& easy_request, bool from_queue)
{
bool throttled = true; // Default.
AICapabilityType capability_type;
AIPerServicePtr per_service;
{
AICurlEasyRequest_wat curl_easy_request_w(*easy_request);
capability_type = curl_easy_request_w->capability_type();
per_service = curl_easy_request_w->getPerServicePtr();
PerServiceRequestQueue_wat per_service_w(*per_service);
if (mAddedEasyRequests.size() < curl_max_total_concurrent_connections && !per_service_w->throttled())
// Never throttle on bandwidth if there are no handles running (sTotalAdded == 1, the long poll connection).
bool too_much_bandwidth = sTotalAdded > 1 && !curl_easy_request_w->approved() && AIPerService::checkBandwidthUsage(per_service, get_clock_count() * HTTPTimeout::sClockWidth_40ms);
PerService_wat per_service_w(*per_service);
if (!too_much_bandwidth && sTotalAdded < curl_max_total_concurrent_connections && !per_service_w->throttled())
{
curl_easy_request_w->set_timeout_opts();
if (curl_easy_request_w->add_handle_to_multi(curl_easy_request_w, mMultiHandle) == CURLM_OK)
{
per_service_w->added_to_multi_handle(); // (About to be) added to mAddedEasyRequests.
per_service_w->added_to_multi_handle(capability_type); // (About to be) added to mAddedEasyRequests.
throttled = false; // Fall through...
}
}
} // Release the lock on easy_request.
if (!throttled)
{ // ... to here.
std::pair<addedEasyRequests_type::iterator, bool> res = mAddedEasyRequests.insert(easy_request);
#ifdef SHOW_ASSERT
std::pair<addedEasyRequests_type::iterator, bool> res =
#endif
mAddedEasyRequests.insert(easy_request);
llassert(res.second); // May not have been added before.
sTotalAdded++;
llassert(sTotalAdded == mAddedEasyRequests.size());
Dout(dc::curl, "MultiHandle::add_easy_request: Added AICurlEasyRequest " << (void*)easy_request.get_ptr().get() <<
"; now processing " << mAddedEasyRequests.size() << " easy handles [running_handles = " << AICurlInterface::Stats::running_handles << "].");
return;
return true;
}
if (from_queue)
{
// Throttled. Do not add to queue, because it is already in the queue.
return false;
}
// The request could not be added, we have to queue it.
PerServiceRequestQueue_wat(*per_service)->queue(easy_request);
PerService_wat(*per_service)->queue(easy_request, capability_type);
#ifdef SHOW_ASSERT
// Not active yet, but it's no longer an error if next we try to remove the request.
AICurlEasyRequest_wat(*easy_request)->mRemovedPerCommand = false;
#endif
return true;
}
CURLMcode MultiHandle::remove_easy_request(AICurlEasyRequest const& easy_request, bool as_per_command)
@@ -1749,7 +1771,7 @@ CURLMcode MultiHandle::remove_easy_request(AICurlEasyRequest const& easy_request
#ifdef SHOW_ASSERT
bool removed =
#endif
easy_request_w->removeFromPerServiceQueue(easy_request);
easy_request_w->removeFromPerServiceQueue(easy_request, easy_request_w->capability_type());
#ifdef SHOW_ASSERT
if (removed)
{
@@ -1765,12 +1787,14 @@ CURLMcode MultiHandle::remove_easy_request(AICurlEasyRequest const& easy_request
CURLMcode MultiHandle::remove_easy_request(addedEasyRequests_type::iterator const& iter, bool as_per_command)
{
CURLMcode res;
AICapabilityType capability_type;
AIPerServicePtr per_service;
{
AICurlEasyRequest_wat curl_easy_request_w(**iter);
res = curl_easy_request_w->remove_handle_from_multi(curl_easy_request_w, mMultiHandle);
capability_type = curl_easy_request_w->capability_type();
per_service = curl_easy_request_w->getPerServicePtr();
PerServiceRequestQueue_wat(*per_service)->removed_from_multi_handle(); // (About to be) removed from mAddedEasyRequests.
PerService_wat(*per_service)->removed_from_multi_handle(capability_type); // (About to be) removed from mAddedEasyRequests.
#ifdef SHOW_ASSERT
curl_easy_request_w->mRemovedPerCommand = as_per_command;
#endif
@@ -1787,7 +1811,7 @@ CURLMcode MultiHandle::remove_easy_request(addedEasyRequests_type::iterator cons
#endif
// Attempt to add a queued request, if any.
PerServiceRequestQueue_wat(*per_service)->add_queued_to(this);
PerService_wat(*per_service)->add_queued_to(this);
return res;
}
@@ -2120,7 +2144,7 @@ void BufferedCurlEasyRequest::update_body_bandwidth(void)
if (raw_bytes > 0)
{
U64 const sTime_40ms = curlthread::HTTPTimeout::sTime_10ms >> 2;
AIAverage& http_bandwidth(PerServiceRequestQueue_wat(*getPerServicePtr())->bandwidth());
AIAverage& http_bandwidth(PerService_wat(*getPerServicePtr())->bandwidth());
http_bandwidth.addData(raw_bytes, sTime_40ms);
sHTTPBandwidth.addData(raw_bytes, sTime_40ms);
}
@@ -2215,7 +2239,7 @@ size_t BufferedCurlEasyRequest::curlHeaderCallback(char* data, size_t size, size
}
// Update HTTP bandwidth.
U64 const sTime_40ms = curlthread::HTTPTimeout::sTime_10ms >> 2;
AIAverage& http_bandwidth(PerServiceRequestQueue_wat(*self_w->getPerServicePtr())->bandwidth());
AIAverage& http_bandwidth(PerService_wat(*self_w->getPerServicePtr())->bandwidth());
http_bandwidth.addData(header_len, sTime_40ms);
sHTTPBandwidth.addData(header_len, sTime_40ms);
// Update timeout administration. This must be done after the status is already known.
@@ -2421,7 +2445,7 @@ void AICurlEasyRequest::addRequest(void)
command_queue_w->commands.push_back(Command(*this, cmd_add));
command_queue_w->size++;
AICurlEasyRequest_wat curl_easy_request_w(*get());
PerServiceRequestQueue_wat(*curl_easy_request_w->getPerServicePtr())->added_to_command_queue();
PerService_wat(*curl_easy_request_w->getPerServicePtr())->added_to_command_queue(curl_easy_request_w->capability_type());
curl_easy_request_w->add_queued();
}
// Something was added to the queue, wake up the thread to get it.
@@ -2485,7 +2509,7 @@ void AICurlEasyRequest::removeRequest(void)
command_queue_w->commands.push_back(Command(*this, cmd_remove));
command_queue_w->size--;
AICurlEasyRequest_wat curl_easy_request_w(*get());
PerServiceRequestQueue_wat(*curl_easy_request_w->getPerServicePtr())->removed_from_command_queue(); // Note really, but this has the same effect as 'added a remove command'.
PerService_wat(*curl_easy_request_w->getPerServicePtr())->removed_from_command_queue(curl_easy_request_w->capability_type()); // Note really, but this has the same effect as 'added a remove command'.
// Suppress warning that would otherwise happen if the callbacks are revoked before the curl thread removed the request.
curl_easy_request_w->remove_queued();
}
@@ -2511,7 +2535,8 @@ void startCurlThread(LLControlGroup* control_group)
curl_max_total_concurrent_connections = sConfigGroup->getU32("CurlMaxTotalConcurrentConnections");
CurlConcurrentConnectionsPerService = sConfigGroup->getU32("CurlConcurrentConnectionsPerService");
gNoVerifySSLCert = sConfigGroup->getBOOL("NoVerifySSLCert");
max_pipelined_requests = curl_max_total_concurrent_connections;
AIPerService::setMaxPipelinedRequests(curl_max_total_concurrent_connections);
AIPerService::setHTTPThrottleBandwidth(sConfigGroup->getF32("HTTPThrottleBandwidth"));
AICurlThread::sInstance = new AICurlThread;
AICurlThread::sInstance->start();
@@ -2524,7 +2549,7 @@ bool handleCurlMaxTotalConcurrentConnections(LLSD const& newvalue)
U32 old = curl_max_total_concurrent_connections;
curl_max_total_concurrent_connections = newvalue.asInteger();
max_pipelined_requests += curl_max_total_concurrent_connections - old;
AIPerService::incrementMaxPipelinedRequests(curl_max_total_concurrent_connections - old);
llinfos << "CurlMaxTotalConcurrentConnections set to " << curl_max_total_concurrent_connections << llendl;
return true;
}
@@ -2574,6 +2599,12 @@ size_t getHTTPBandwidth(void)
} // namespace AICurlInterface
// Global AIPerService members.
AIThreadSafeSimpleDC<AIPerService::MaxPipelinedRequests> AIPerService::sMaxPipelinedRequests;
AIThreadSafeSimpleDC<AIPerService::ThrottleFraction> AIPerService::sThrottleFraction;
LLAtomicU32 AIPerService::sHTTPThrottleBandwidth125(250000);
bool AIPerService::sNoHTTPBandwidthThrottling;
// Return true if we want at least one more HTTP request for this host.
//
// It's OK if this function is a bit fuzzy, but we don't want it to return
@@ -2599,162 +2630,185 @@ size_t getHTTPBandwidth(void)
// running requests (in MultiHandle::mAddedEasyRequests)).
//
//static
bool AIPerService::wantsMoreHTTPRequestsFor(AIPerServicePtr const& per_service, F32 max_kbps, bool no_bandwidth_throttling)
AIPerService::Approvement* AIPerService::approveHTTPRequestFor(AIPerServicePtr const& per_service, AICapabilityType capability_type)
{
using namespace AICurlPrivate;
using namespace AICurlPrivate::curlthread;
bool reject, equal, increment_threshold, decrement_threshold;
// Do certain things at most once every 40ms.
U64 const sTime_40ms = get_clock_count() * HTTPTimeout::sClockWidth_40ms; // Time in 40ms units.
// Cache all sTotalQueued info.
bool starvation, decrement_threshold;
S32 total_queued_or_added = MultiHandle::total_added_size();
{
TotalQueued_wat total_queued_w(sTotalQueued);
total_queued_or_added += total_queued_w->count;
starvation = total_queued_w->starvation;
decrement_threshold = total_queued_w->full && !total_queued_w->empty;
total_queued_w->empty = total_queued_w->full = false; // Reset flags.
}
// Whether or not we're going to approve a new request, decrement the global threshold first, when appropriate.
// Atomic read max_pipelined_requests for the below calculations.
S32 const max_pipelined_requests_cache = max_pipelined_requests;
decrement_threshold = sQueueFull && !sQueueEmpty;
// Reset flags.
sQueueEmpty = sQueueFull = false;
if (decrement_threshold)
{
if (max_pipelined_requests_cache > (S32)curl_max_total_concurrent_connections)
MaxPipelinedRequests_wat max_pipelined_requests_w(sMaxPipelinedRequests);
if (max_pipelined_requests_w->count > (S32)curl_max_total_concurrent_connections &&
sTime_40ms > max_pipelined_requests_w->last_decrement)
{
// Decrement the threshold because since the last call to this function at least one curl request finished
// and was replaced with another request from the queue, but the queue never ran empty: we have too many
// queued requests.
--max_pipelined_requests;
max_pipelined_requests_w->count--;
// Do this at most once every 40 ms.
max_pipelined_requests_w->last_decrement = sTime_40ms;
}
}
// Check if it's ok to get a new request for this particular service and update the per-service threshold.
AIAverage* http_bandwidth_ptr;
// Check if it's ok to get a new request for this particular capability type and update the per-capability-type threshold.
bool reject, equal, increment_threshold;
{
PerServiceRequestQueue_wat per_service_w(*per_service);
S32 const pipelined_requests_per_service = per_service_w->pipelined_requests();
reject = pipelined_requests_per_service >= per_service_w->mMaxPipelinedRequests;
equal = pipelined_requests_per_service == per_service_w->mMaxPipelinedRequests;
increment_threshold = per_service_w->mRequestStarvation;
decrement_threshold = per_service_w->mQueueFull && !per_service_w->mQueueEmpty;
// Reset flags.
per_service_w->mQueueFull = per_service_w->mQueueEmpty = per_service_w->mRequestStarvation = false;
// Grab per service bandwidth object.
http_bandwidth_ptr = &per_service_w->bandwidth();
PerService_wat per_service_w(*per_service);
CapabilityType& ct(per_service_w->mCapabilityType[capability_type]);
S32 const pipelined_requests_per_capability_type = ct.pipelined_requests();
reject = pipelined_requests_per_capability_type >= (S32)ct.mMaxPipelinedRequests;
equal = pipelined_requests_per_capability_type == ct.mMaxPipelinedRequests;
increment_threshold = ct.mFlags & ctf_starvation;
decrement_threshold = (ct.mFlags & (ctf_empty | ctf_full)) == ctf_full;
ct.mFlags = 0;
if (decrement_threshold)
{
if (per_service_w->mMaxPipelinedRequests > per_service_w->mConcurrectConnections)
if ((int)ct.mMaxPipelinedRequests > per_service_w->mConcurrectConnections)
{
per_service_w->mMaxPipelinedRequests--;
ct.mMaxPipelinedRequests--;
}
}
else if (increment_threshold && reject)
{
if (per_service_w->mMaxPipelinedRequests < 2 * per_service_w->mConcurrectConnections)
if ((int)ct.mMaxPipelinedRequests < 2 * per_service_w->mConcurrectConnections)
{
per_service_w->mMaxPipelinedRequests++;
ct.mMaxPipelinedRequests++;
// Immediately take the new threshold into account.
reject = !equal;
}
}
if (!reject)
{
// Before releasing the lock on per_service, stop other threads from getting a
// too small value from pipelined_requests() and approving too many requests.
ct.mApprovedRequests++;
}
}
if (reject)
{
// Too many request for this host already.
return false;
// Too many request for this service already.
return NULL;
}
if (!no_bandwidth_throttling)
// Throttle on bandwidth usage.
if (checkBandwidthUsage(per_service, sTime_40ms))
{
// Throttle on bandwidth usage.
static size_t throttle_fraction = 1024; // A value between 0 and 1024: each service is throttled when it uses more than max_bandwidth * (throttle_fraction/1024) bandwidth.
static AIAverage fraction(25); // Average over 25 * 40ms = 1 second.
static U64 last_sTime_40ms = 0;
// Truncate the sums to the last second, and get their value.
U64 const sTime_40ms = get_clock_count() * HTTPTimeout::sClockWidth_40ms; // Time in 40ms units.
size_t const max_bandwidth = 125.f * max_kbps; // Convert kbps to bytes per second.
size_t const total_bandwidth = BufferedCurlEasyRequest::sHTTPBandwidth.truncateData(sTime_40ms); // Bytes received in the past second.
size_t const service_bandwidth = http_bandwidth_ptr->truncateData(sTime_40ms); // Idem for just this service.
if (sTime_40ms > last_sTime_40ms)
{
// Only add throttle_fraction once every 40 ms at most.
// It's ok to ignore other values in the same 40 ms because the value only changes on the scale of 1 second.
fraction.addData(throttle_fraction, sTime_40ms);
last_sTime_40ms = sTime_40ms;
}
double fraction_avg = fraction.getAverage(1024.0); // throttle_fraction averaged over the past second, or 1024 if there is no data.
// Adjust throttle_fraction based on total bandwidth usage.
if (total_bandwidth == 0)
throttle_fraction = 1024;
else
{
// This is the main formula. It can be made plausible by assuming
// an equilibrium where total_bandwidth == max_bandwidth and
// thus throttle_fraction == fraction_avg for more than a second.
//
// Then, more bandwidth is being used (for example because another
// service starts downloading). Assuming that all services that use
// a significant portion of the bandwidth, the new service included,
// must be throttled (all using the same bandwidth; note that the
// new service is immediately throttled at the same value), then
// the limit should be reduced linear with the fraction:
// max_bandwidth / total_bandwidth.
//
// For example, let max_bandwidth be 1. Let there be two throttled
// services, each using 0.5 (fraction_avg = 1024/2). Lets the new
// service use what it can: also 0.5 - then without reduction the
// total_bandwidth would become 1.5, and throttle_fraction would
// become (1024/2) * 1/1.5 = 1024/3: from 2 to 3 services.
//
// In reality, total_bandwidth would rise linear from 1.0 to 1.5 in
// one second if the throttle fraction wasn't changed. However it is
// changed here. The end result is that any change more or less
// linear fades away in one second.
throttle_fraction = fraction_avg * max_bandwidth / total_bandwidth;
}
if (throttle_fraction > 1024)
throttle_fraction = 1024;
if (total_bandwidth > max_bandwidth)
{
throttle_fraction *= 0.95;
}
// Throttle this service if it uses too much bandwidth.
if (service_bandwidth > (max_bandwidth * throttle_fraction / 1024))
{
return false; // wait
}
// Too much bandwidth is being used, either in total or for this service.
PerService_wat(*per_service)->mCapabilityType[capability_type].mApprovedRequests--; // Not approved after all.
return NULL;
}
// Check if it's ok to get a new request based on the total number of requests and increment the threshold if appropriate.
{
command_queue_rat command_queue_r(command_queue);
S32 const pipelined_requests = command_queue_r->size + sTotalQueued + MultiHandle::total_added_size();
// We can't take the command being processed (command_being_processed) into account without
// introducing relatively long waiting times for some mutex (namely between when the command
// is moved from command_queue to command_being_processed, till it's actually being added to
// mAddedEasyRequests). The whole purpose of command_being_processed is to reduce the time
// that things are locked to micro seconds, so we'll just accept an off-by-one fuzziness
// here instead.
S32 const pipelined_requests = command_queue_rat(command_queue)->size + total_queued_or_added;
// We can't take the command being processed (command_being_processed) into account without
// introducing relatively long waiting times for some mutex (namely between when the command
// is moved from command_queue to command_being_processed, till it's actually being added to
// mAddedEasyRequests). The whole purpose of command_being_processed is to reduce the time
// that things are locked to micro seconds, so we'll just accept an off-by-one fuzziness
// here instead.
// The maximum number of requests that may be queued in command_queue is equal to the total number of requests
// that may exist in the pipeline minus the number of requests queued in AIPerService objects, minus
// the number of already running requests.
reject = pipelined_requests >= max_pipelined_requests_cache;
equal = pipelined_requests == max_pipelined_requests_cache;
increment_threshold = sRequestStarvation;
}
// The maximum number of requests that may be queued in command_queue is equal to the total number of requests
// that may exist in the pipeline minus the number of requests queued in AIPerService objects, minus
// the number of already running requests.
MaxPipelinedRequests_wat max_pipelined_requests_w(sMaxPipelinedRequests);
reject = pipelined_requests >= max_pipelined_requests_w->count;
equal = pipelined_requests == max_pipelined_requests_w->count;
increment_threshold = starvation;
if (increment_threshold && reject)
{
if (max_pipelined_requests_cache < 2 * (S32)curl_max_total_concurrent_connections)
if (max_pipelined_requests_w->count < 2 * (S32)curl_max_total_concurrent_connections &&
sTime_40ms > max_pipelined_requests_w->last_increment)
{
max_pipelined_requests++;
max_pipelined_requests_w->count++;
max_pipelined_requests_w->last_increment = sTime_40ms;
// Immediately take the new threshold into account.
reject = !equal;
}
}
return !reject;
if (reject)
{
PerService_wat(*per_service)->mCapabilityType[capability_type].mApprovedRequests--; // Not approved after all.
return NULL;
}
return new Approvement(per_service, capability_type);
}
bool AIPerService::checkBandwidthUsage(AIPerServicePtr const& per_service, U64 sTime_40ms)
{
if (sNoHTTPBandwidthThrottling)
return false;
using namespace AICurlPrivate;
// Truncate the sums to the last second, and get their value.
size_t const max_bandwidth = AIPerService::getHTTPThrottleBandwidth125();
size_t const total_bandwidth = BufferedCurlEasyRequest::sHTTPBandwidth.truncateData(sTime_40ms); // Bytes received in the past second.
size_t const service_bandwidth = PerService_wat(*per_service)->bandwidth().truncateData(sTime_40ms); // Idem for just this service.
ThrottleFraction_wat throttle_fraction_w(sThrottleFraction);
if (sTime_40ms > throttle_fraction_w->last_add)
{
throttle_fraction_w->average.addData(throttle_fraction_w->fraction, sTime_40ms);
// Only add throttle_fraction_w->fraction once every 40 ms at most.
// It's ok to ignore other values in the same 40 ms because the value only changes on the scale of 1 second.
throttle_fraction_w->last_add = sTime_40ms;
}
double fraction_avg = throttle_fraction_w->average.getAverage(1024.0); // throttle_fraction_w->fraction averaged over the past second, or 1024 if there is no data.
// Adjust the fraction based on total bandwidth usage.
if (total_bandwidth == 0)
throttle_fraction_w->fraction = 1024;
else
{
// This is the main formula. It can be made plausible by assuming
// an equilibrium where total_bandwidth == max_bandwidth and
// thus fraction == fraction_avg for more than a second.
//
// Then, more bandwidth is being used (for example because another
// service starts downloading). Assuming that all services that use
// a significant portion of the bandwidth, the new service included,
// must be throttled (all using the same bandwidth; note that the
// new service is immediately throttled at the same value), then
// the limit should be reduced linear with the fraction:
// max_bandwidth / total_bandwidth.
//
// For example, let max_bandwidth be 1. Let there be two throttled
// services, each using 0.5 (fraction_avg = 1024/2). Let the new
// service use what it can: also 0.5 - then without reduction the
// total_bandwidth would become 1.5, and fraction would
// become (1024/2) * 1/1.5 = 1024/3: from 2 to 3 services.
//
// In reality, total_bandwidth would rise linear from 1.0 to 1.5 in
// one second if the throttle fraction wasn't changed. However it is
// changed here. The end result is that any change more or less
// linear fades away in one second.
throttle_fraction_w->fraction = llmin(1024., fraction_avg * max_bandwidth / total_bandwidth + 0.5);
}
if (total_bandwidth > max_bandwidth)
{
throttle_fraction_w->fraction *= 0.95;
}
// Throttle this service if it uses too much bandwidth.
// Warning: this requires max_bandwidth * 1024 to fit in a size_t.
// On 32 bit that means that HTTPThrottleBandwidth must be less than 33554 kbps.
return (service_bandwidth > (max_bandwidth * throttle_fraction_w->fraction / 1024));
}

View File

@@ -59,7 +59,7 @@ class MultiHandle : public CurlMultiHandle
~MultiHandle();
// Add/remove an easy handle to/from a multi session.
void add_easy_request(AICurlEasyRequest const& easy_request);
bool add_easy_request(AICurlEasyRequest const& easy_request, bool from_queue);
CURLMcode remove_easy_request(AICurlEasyRequest const& easy_request, bool as_per_command = false);
// Reads/writes available data from a particular socket (non-blocking).

View File

@@ -201,7 +201,8 @@ void LLHTTPClient::request(
LLURLRequest::ERequestAction method,
Injector* body_injector,
LLHTTPClient::ResponderPtr responder,
AIHTTPHeaders& headers/*,*/
AIHTTPHeaders& headers,
AIPerService::Approvement* approved/*,*/
DEBUG_CURLIO_PARAM(EDebugCurl debug),
EKeepAlive keepalive,
EDoesAuthentication does_auth,
@@ -221,7 +222,7 @@ void LLHTTPClient::request(
LLURLRequest* req;
try
{
req = new LLURLRequest(method, url, body_injector, responder, headers, keepalive, does_auth, allow_compression);
req = new LLURLRequest(method, url, body_injector, responder, headers, approved, keepalive, does_auth, allow_compression);
#ifdef DEBUG_CURLIO
req->mCurlEasyRequest.debug(debug);
#endif
@@ -242,22 +243,22 @@ void LLHTTPClient::getByteRange(std::string const& url, S32 offset, S32 bytes, R
{
headers.addHeader("Range", llformat("bytes=%d-%d", offset, offset + bytes - 1));
}
request(url, HTTP_GET, NULL, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug));
request(url, HTTP_GET, NULL, responder, headers, NULL/*,*/ DEBUG_CURLIO_PARAM(debug));
}
void LLHTTPClient::head(std::string const& url, ResponderHeadersOnly* responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug))
{
request(url, HTTP_HEAD, NULL, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug));
request(url, HTTP_HEAD, NULL, responder, headers, NULL/*,*/ DEBUG_CURLIO_PARAM(debug));
}
void LLHTTPClient::get(std::string const& url, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug))
{
request(url, HTTP_GET, NULL, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug));
request(url, HTTP_GET, NULL, responder, headers, NULL/*,*/ DEBUG_CURLIO_PARAM(debug));
}
void LLHTTPClient::getHeaderOnly(std::string const& url, ResponderHeadersOnly* responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug))
{
request(url, HTTP_HEAD, NULL, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug));
request(url, HTTP_HEAD, NULL, responder, headers, NULL/*,*/ DEBUG_CURLIO_PARAM(debug));
}
void LLHTTPClient::get(std::string const& url, LLSD const& query, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug))
@@ -693,17 +694,22 @@ U32 LLHTTPClient::blockingGetRaw(const std::string& url, std::string& body/*,*/
void LLHTTPClient::put(std::string const& url, LLSD const& body, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug))
{
request(url, HTTP_PUT, new LLSDInjector(body), responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug), no_keep_alive, no_does_authentication, no_allow_compressed_reply);
request(url, HTTP_PUT, new LLSDInjector(body), responder, headers, NULL/*,*/ DEBUG_CURLIO_PARAM(debug), no_keep_alive, no_does_authentication, no_allow_compressed_reply);
}
void LLHTTPClient::post(std::string const& url, LLSD const& body, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug), EKeepAlive keepalive, AIStateMachine* parent, AIStateMachine::state_type new_parent_state)
{
request(url, HTTP_POST, new LLSDInjector(body), responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug), keepalive, no_does_authentication, allow_compressed_reply, parent, new_parent_state);
request(url, HTTP_POST, new LLSDInjector(body), responder, headers, NULL/*,*/ DEBUG_CURLIO_PARAM(debug), keepalive, no_does_authentication, allow_compressed_reply, parent, new_parent_state);
}
void LLHTTPClient::post_approved(std::string const& url, LLSD const& body, ResponderPtr responder, AIHTTPHeaders& headers, AIPerService::Approvement* approved/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug), EKeepAlive keepalive, AIStateMachine* parent, AIStateMachine::state_type new_parent_state)
{
request(url, HTTP_POST, new LLSDInjector(body), responder, headers, approved/*,*/ DEBUG_CURLIO_PARAM(debug), keepalive, no_does_authentication, allow_compressed_reply, parent, new_parent_state, &gMainThreadEngine);
}
void LLHTTPClient::postXMLRPC(std::string const& url, XMLRPC_REQUEST xmlrpc_request, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug), EKeepAlive keepalive)
{
request(url, HTTP_POST, new XMLRPCInjector(xmlrpc_request), responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug), keepalive, does_authentication, allow_compressed_reply);
request(url, HTTP_POST, new XMLRPCInjector(xmlrpc_request), responder, headers, NULL/*,*/ DEBUG_CURLIO_PARAM(debug), keepalive, does_authentication, allow_compressed_reply);
}
void LLHTTPClient::postXMLRPC(std::string const& url, char const* method, XMLRPC_VALUE value, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug), EKeepAlive keepalive)
@@ -714,33 +720,33 @@ void LLHTTPClient::postXMLRPC(std::string const& url, char const* method, XMLRPC
XMLRPC_RequestSetData(xmlrpc_request, value);
// 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.
request(url, HTTP_POST, new XMLRPCInjector(xmlrpc_request), responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug), keepalive, does_authentication, no_allow_compressed_reply);
request(url, HTTP_POST, new XMLRPCInjector(xmlrpc_request), responder, headers, NULL/*,*/ DEBUG_CURLIO_PARAM(debug), keepalive, does_authentication, no_allow_compressed_reply);
}
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, HTTP_POST, new RawInjector(data, size), responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug), keepalive);
request(url, HTTP_POST, new RawInjector(data, size), responder, headers, NULL/*,*/ DEBUG_CURLIO_PARAM(debug), keepalive);
}
void LLHTTPClient::postFile(std::string const& url, std::string const& filename, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug), EKeepAlive keepalive)
{
request(url, HTTP_POST, new FileInjector(filename), responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug), keepalive);
request(url, HTTP_POST, new FileInjector(filename), responder, headers, NULL/*,*/ DEBUG_CURLIO_PARAM(debug), keepalive);
}
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, HTTP_POST, new VFileInjector(uuid, asset_type), responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug), keepalive);
request(url, HTTP_POST, new VFileInjector(uuid, asset_type), responder, headers, NULL/*,*/ DEBUG_CURLIO_PARAM(debug), keepalive);
}
// static
void LLHTTPClient::del(std::string const& url, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug))
{
request(url, HTTP_DELETE, NULL, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug));
request(url, HTTP_DELETE, NULL, responder, headers, NULL/*,*/ DEBUG_CURLIO_PARAM(debug));
}
// static
void LLHTTPClient::move(std::string const& url, std::string const& destination, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug))
{
headers.addHeader("Destination", destination);
request(url, HTTP_MOVE, NULL, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug));
request(url, HTTP_MOVE, NULL, responder, headers, NULL/*,*/ DEBUG_CURLIO_PARAM(debug));
}

View File

@@ -38,6 +38,7 @@
#include "llassettype.h"
#include "llhttpstatuscodes.h"
#include "aihttpheaders.h"
#include "aicurlperservice.h"
class LLUUID;
class LLPumpIO;
@@ -223,6 +224,9 @@ public:
// 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(); }
// Returns the capability type used by this responder.
virtual AICapabilityType capability_type(void) const { return cap_other; }
// Timeout policy to use.
virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const = 0;
@@ -426,7 +430,8 @@ public:
ERequestAction method,
Injector* body_injector,
ResponderPtr responder,
AIHTTPHeaders& headers/*,*/
AIHTTPHeaders& headers,
AIPerService::Approvement* approved/*,*/
DEBUG_CURLIO_PARAM(EDebugCurl debug),
EKeepAlive keepalive = keep_alive,
EDoesAuthentication does_auth = no_does_authentication,
@@ -465,6 +470,10 @@ public:
static void post(std::string const& url, LLSD const& body, ResponderPtr responder/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off), EKeepAlive keepalive = keep_alive, AIStateMachine* parent = NULL, U32 new_parent_state = 0)
{ AIHTTPHeaders headers; post(url, body, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug), keepalive, parent, new_parent_state); }
static void post_approved(std::string const& url, LLSD const& body, ResponderPtr responder, AIHTTPHeaders& headers, AIPerService::Approvement* approved/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off), EKeepAlive keepalive = keep_alive, AIStateMachine* parent = NULL, U32 new_parent_state = 0);
static void post_approved(std::string const& url, LLSD const& body, ResponderPtr responder, AIPerService::Approvement* approved/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off), EKeepAlive keepalive = keep_alive, AIStateMachine* parent = NULL, U32 new_parent_state = 0)
{ AIHTTPHeaders headers; post_approved(url, body, responder, headers, approved/*,*/ DEBUG_CURLIO_PARAM(debug), keepalive, parent, new_parent_state); }
/** Takes ownership of request and deletes it when sent */
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/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off), EKeepAlive keepalive = keep_alive)

View File

@@ -75,10 +75,15 @@ std::string LLURLRequest::actionAsVerb(LLURLRequest::ERequestAction action)
// This might throw AICurlNoEasyHandle.
LLURLRequest::LLURLRequest(LLURLRequest::ERequestAction action, std::string const& url, Injector* body,
LLHTTPClient::ResponderPtr responder, AIHTTPHeaders& headers, bool keepalive, bool is_auth, bool compression) :
LLHTTPClient::ResponderPtr responder, AIHTTPHeaders& headers, AIPerService::Approvement* approved,
bool keepalive, bool is_auth, bool compression) :
mAction(action), mURL(url), mKeepAlive(keepalive), mIsAuth(is_auth), mNoCompression(!compression),
mBody(body), mResponder(responder), mHeaders(headers), mResponderNameCache(responder ? responder->getName() : "<uninitialized>")
{
if (approved)
{
AICurlEasyRequest_wat(*mCurlEasyRequest)->setApproved(approved);
}
}
void LLURLRequest::initialize_impl(void)

View File

@@ -64,7 +64,10 @@ class LLURLRequest : public AICurlEasyRequestStateMachine {
* @param action One of the ERequestAction enumerations.
* @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 keepalive, bool is_auth, bool no_compression);
LLURLRequest(ERequestAction action, std::string const& url, Injector* body,
LLHTTPClient::ResponderPtr responder, AIHTTPHeaders& headers,
AIPerService::Approvement* approved,
bool keepalive, bool is_auth, bool no_compression);
/**
* @brief Cached value of responder->getName() as passed to the constructor.

View File

@@ -261,7 +261,7 @@ U32 LLXferManager::numActiveListEntries(LLXfer *list_head)
while (list_head)
{
if ((list_head->mStatus == e_LL_XFER_IN_PROGRESS))
if (list_head->mStatus == e_LL_XFER_IN_PROGRESS)
{
num_entries++;
}

0
indra/llplugin/slplugin/slplugin_info.plist Executable file → Normal file
View File

View File

@@ -450,6 +450,7 @@ void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 width, S32 height, LLTex
gGL.getTexUnit(0)->bind(image, true);
gGL.color4fv(color.mV);
gGL.diffuseColor4fv(color.mV); //workaround: Intel HD 4000
const S32 NUM_VERTICES = 9 * 4; // 9 quads
LLVector2 uv[NUM_VERTICES];

View File

@@ -2397,7 +2397,6 @@ void LLMenuGL::arrange( void )
// Scrolling support
item_list_t::iterator first_visible_item_iter;
item_list_t::iterator first_hidden_item_iter = mItems.end();
//S32 height_before_first_visible_item = -1;
//S32 visible_items_height = 0;
//U32 scrollable_items_cnt = 0;
@@ -2895,9 +2894,6 @@ LLMenuItemGL* LLMenuGL::highlightNextItem(LLMenuItemGL* cur_item, BOOL skip_disa
next_item_iter = cur_item_iter;
next_item_iter++;
// First visible item position in the items list
item_list_t::iterator first_visible_item_iter = std::find(mItems.begin(), mItems.end(), mFirstVisibleItem);
if (next_item_iter == mItems.end())
{
next_item_iter = mItems.begin();
@@ -2973,9 +2969,6 @@ LLMenuItemGL* LLMenuGL::highlightPrevItem(LLMenuItemGL* cur_item, BOOL skip_disa
prev_item_iter = cur_item_iter;
prev_item_iter++;
// First visible item reverse position in the items list
item_list_t::reverse_iterator first_visible_item_iter = std::find(mItems.rbegin(), mItems.rend(), mFirstVisibleItem);
if (prev_item_iter == mItems.rend())
{
prev_item_iter = mItems.rbegin();

View File

@@ -280,8 +280,6 @@ void LLMultiSliderCtrl::updateText()
void LLMultiSliderCtrl::onEditorCommit(const LLSD& value)
{
llassert( caller == mEditor );
BOOL success = FALSE;
F32 val = mCurValue;
F32 saved_val = mCurValue;

View File

@@ -944,10 +944,10 @@ const LLTextSegment* LLTextEditor::getPreviousSegment() const
{
// find segment index at character to left of cursor (or rightmost edge of selection)
S32 idx = llmax(0, getSegmentIdxAtOffset(mCursorPos) - 1);
return idx >= 0 ? mSegments[idx] : NULL;
return idx >= 0 ? mSegments[idx] : LLTextSegmentPtr();
}
void LLTextEditor::getSelectedSegments(std::vector<const LLTextSegmentPtr>& segments) const
void LLTextEditor::getSelectedSegments(std::vector<LLTextSegmentPtr>& segments) const
{
S32 left = hasSelection() ? llmin(mSelectionStart, mSelectionEnd) : mCursorPos;
S32 right = hasSelection() ? llmax(mSelectionStart, mSelectionEnd) : mCursorPos;
@@ -4512,13 +4512,13 @@ LLTextSegment* LLTextEditor::getSegmentAtLocalPos( S32 x, S32 y ) const
// Find the cursor position at the requested local screen position
S32 offset = getCursorPosFromLocalCoord( x, y, FALSE );
S32 idx = getSegmentIdxAtOffset(offset);
return idx >= 0 ? mSegments[idx] : NULL;
return idx >= 0 ? mSegments[idx] : LLTextSegmentPtr();
}
const LLTextSegment* LLTextEditor::getSegmentAtOffset(S32 offset) const
{
S32 idx = getSegmentIdxAtOffset(offset);
return idx >= 0 ? mSegments[idx] : NULL;
return idx >= 0 ? mSegments[idx] : LLTextSegmentPtr();
}
S32 LLTextEditor::getSegmentIdxAtOffset(S32 offset) const

View File

@@ -293,7 +293,7 @@ public:
const LLTextSegment* getCurrentSegment() const { return getSegmentAtOffset(mCursorPos); }
const LLTextSegment* getPreviousSegment() const;
void getSelectedSegments(std::vector<const LLTextSegmentPtr>& segments) const;
void getSelectedSegments(std::vector<LLTextSegmentPtr>& segments) const;
static bool isPartOfWord(llwchar c) { return ( (c == '_') || (c == '\'') || LLStringOps::isAlnum((char)c)); }

0
indra/llwindow/glh/glh_linear.h Executable file → Normal file
View File

View File

@@ -41,8 +41,8 @@ class LLPreeditor;
class LLWindowCallbacks;
static const S32 MIN_WINDOW_WIDTH = 864;
static const S32 MIN_WINDOW_HEIGHT = 472;
const S32 MIN_WINDOW_WIDTH = 256;
const S32 MIN_WINDOW_HEIGHT = 256;
// Refer to llwindow_test in test/common/llwindow for usage example

View File

@@ -226,7 +226,6 @@ set(viewer_SOURCE_FILES
llfloatermodeluploadbase.cpp
llfloatermute.cpp
llfloaternamedesc.cpp
llfloaternewim.cpp
llfloaternotificationsconsole.cpp
llfloaterobjectiminfo.cpp
llfloateropenobject.cpp
@@ -335,7 +334,6 @@ set(viewer_SOURCE_FILES
llpanelavatar.cpp
llpanelclassified.cpp
llpanelcontents.cpp
llpaneldebug.cpp
llpaneldirbrowser.cpp
llpaneldirclassified.cpp
llpaneldirevents.cpp
@@ -725,7 +723,6 @@ set(viewer_HEADER_FILES
llfloatermodeluploadbase.h
llfloatermute.h
llfloaternamedesc.h
llfloaternewim.h
llfloaternotificationsconsole.h
llfloaterobjectiminfo.h
llfloateropenobject.h
@@ -834,7 +831,6 @@ set(viewer_HEADER_FILES
llpanelavatar.h
llpanelclassified.h
llpanelcontents.h
llpaneldebug.h
llpaneldirbrowser.h
llpaneldirclassified.h
llpaneldirevents.h

View File

@@ -9,6 +9,17 @@
<string>settings_rlv.xml</string>
</array>
<key>PhoenixIMAnnounceStealFocus</key>
<map>
<key>Comment</key>
<string>Open a new IM tab when another person begins typing to you and announce that they are doing so.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>UseNewTargetOmegaCode</key>
<map>
<key>Comment</key>
@@ -175,7 +186,10 @@
<key>HTTPThrottleBandwidth</key>
<map>
<key>Comment</key>
<string>The bandwidth (in kbit/s) to strive for</string>
<string>The bandwidth (in kbit/s) to strive for. Smaller values might reduce network
congestion (sim ping time, aka avatar responsiveness). Higher values might download
textures and the inventory faster, although in some cases a too high value might
actually slow that down due to serverside throttling. If unsure, choose 2000.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
@@ -648,6 +662,17 @@
<key>Value</key>
<integer>0</integer>
</map>
<key>LiruItalicizeActions</key>
<map>
<key>Comment</key>
<string>When enabled, /me chat will be italicized.</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>
@@ -4338,6 +4363,17 @@ This should be as low as possible, but too low may break functionality</string>
<key>Value</key>
<real>0.700</real>
</map>
<key>ConsoleBottomOffset</key>
<map>
<key>Comment</key>
<string>User definable offset between the bottom of the chat console and the bottom of the window; increase to move text in the console up</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>S32</string>
<key>Value</key>
<real>0</real>
</map>
<key>ConsoleBufferSize</key>
<map>
<key>Comment</key>
@@ -4468,7 +4504,7 @@ This should be as low as possible, but too low may break functionality</string>
<key>Type</key>
<string>U32</string>
<key>Value</key>
<integer>16</integer>
<integer>8</integer>
</map>
<key>CurlTimeoutDNSLookup</key>
<map>
@@ -6839,6 +6875,19 @@ This should be as low as possible, but too low may break functionality</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>RadarUpdateEnabled</key>
<map>
<key>Comment</key>
<string>When false, pauses the radar until further notice, good for banning someone who just left.</string>
<key>Persist</key>
<integer>0</integer>
<key>HideFromEditor</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>1</integer>
</map>
<key>RadarUpdateRate</key>
<map>
<key>Comment</key>
@@ -15546,6 +15595,17 @@ This should be as low as possible, but too low may break functionality</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>InstantMessagesFriendsOnly</key>
<map>
<key>Comment</key>
<string>Only accept instant messages from residents on your friends list</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>AutoDisengageMic</key>
<map>
<key>Comment</key>
@@ -16393,6 +16453,17 @@ This should be as low as possible, but too low may break functionality</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>ClearBeaconAfterTeleport</key>
<map>
<key>Comment</key>
<string>Clear the red tracker beacon after you teleport</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>LogTextureDownloadsToViewerLog</key>
<map>
<key>Comment</key>

View File

@@ -199,9 +199,9 @@
</map>
<!-- End AO -->
<!-- Ascent Account-Specific (Always) -->
<!-- Ascent Account-Specific (Always) -->
<key>AscentContactGroups</key>
<map>
<key>Comment</key>
@@ -215,72 +215,7 @@
<string />
</array>
</map>
<key>AscentInstantMessageResponse</key>
<map>
<key>Comment</key>
<string>Auto response to instant messages</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>String</string>
<key>Value</key>
<string>This is an autoresponse!</string>
</map>
<key>AscentInstantMessageResponseAnyone</key>
<map>
<key>Comment</key>
<string>Whether to auto-respond to anyone</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>AscentInstantMessageResponseFriends</key>
<map>
<key>Comment</key>
<string>Whether to auto-respond to non-friends</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>AscentInstantMessageResponseItem</key>
<map>
<key>Comment</key>
<string>Whether to send a item along with the autoresponse</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>AscentInstantMessageResponseItemData</key>
<map>
<key>Comment</key>
<string>UUID</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>String</string>
<key>Value</key>
<string></string>
</map>
<key>AscentInstantMessageResponseMuted</key>
<map>
<key>Comment</key>
<string>Whether to auto-respond to muted people</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>AscentInstantMessageResponseRepeat</key>
<map>
<key>Comment</key>
@@ -292,21 +227,11 @@
<key>Value</key>
<integer>0</integer>
</map>
<key>AscentInstantMessageShowOnTyping</key>
<map>
<key>Comment</key>
<string>Whether to perform the autorespond the moment they begin to type instead of waiting for a actual message</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>AscentInstantMessageShowResponded</key>
<map>
<key>Comment</key>
<string>Whether to hide IMs entirely from those you have chosen to send autoresponses</string>
<string>Whether to perform the autorespond the moment they begin to type instead of waiting for an actual message</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
@@ -314,6 +239,219 @@
<key>Value</key>
<integer>0</integer>
</map>
<!-- Autoresponse Section -->
<key>AutoresponseAnyone</key>
<map>
<key>Comment</key>
<string>Whether to send autoresponse to anyone who isn't muted (or just friends, if AutoresponseAnyoneFriendsOnly)</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>AutoresponseAnyoneFriendsOnly</key>
<map>
<key>Comment</key>
<string>Whether to send AutoresponseAnyone to friends only</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>AutoresponseAnyoneItem</key>
<map>
<key>Comment</key>
<string>Whether to send a item along with AutoresponseAnyone</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>AutoresponseAnyoneItemID</key>
<map>
<key>Comment</key>
<string>UUID of item to send along with AutoresponseAnyone</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>String</string>
<key>Value</key>
<string/>
</map>
<key>AutoresponseAnyoneMessage</key>
<map>
<key>Comment</key>
<string>Message to send as the autoresponse to AutoresponseAnyone</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>String</string>
<key>Value</key>
<string>This is an autoresponse!</string>
</map>
<key>AutoresponseAnyoneShow</key>
<map>
<key>Comment</key>
<string>Whether to show that AutoresponseAnyone's were sent</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>AutoresponseNonFriends</key>
<map>
<key>Comment</key>
<string>Whether to send autoresponse to nonfriends, separately using a different response</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>AutoresponseNonFriendsItem</key>
<map>
<key>Comment</key>
<string>Whether to send a item along with AutoresponseNonFriends</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>AutoresponseNonFriendsItemID</key>
<map>
<key>Comment</key>
<string>UUID of item to send along with AutoresponseNonFriends</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>String</string>
<key>Value</key>
<string/>
</map>
<key>AutoresponseNonFriendsMessage</key>
<map>
<key>Comment</key>
<string>Message to send as the autoresponse to AutoresponseNonFriends</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>String</string>
<key>Value</key>
<string>This is an autoresponse!</string>
</map>
<key>AutoresponseNonFriendsShow</key>
<map>
<key>Comment</key>
<string>Whether to show that AutoresponseNonFriends's were sent</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>AutoresponseMuted</key>
<map>
<key>Comment</key>
<string>Whether to send autoresponse to muted people</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>AutoresponseMutedItem</key>
<map>
<key>Comment</key>
<string>Whether to send a item along with AutoresponseMuted</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>AutoresponseMutedItemID</key>
<map>
<key>Comment</key>
<string>UUID of item to send along with AutoresponseMuted</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>String</string>
<key>Value</key>
<string/>
</map>
<key>AutoresponseMutedMessage</key>
<map>
<key>Comment</key>
<string>Message to send as the autoresponse to AutoresponseMuted</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>String</string>
<key>Value</key>
<string>This is an autoresponse!</string>
</map>
<key>BusyModeResponse</key>
<map>
<key>Comment</key>
<string>Auto response to instant messages while in busy mode.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>String</string>
<key>Value</key>
<string>The Resident you messaged is in 'busy mode' which means they have requested not to be disturbed. Your message will still be shown in their IM panel for later viewing.</string>
</map>
<key>BusyModeResponseItem</key>
<map>
<key>Comment</key>
<string>Whether to send a item along with BusyModeResponse</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>BusyModeResponseItemID</key>
<map>
<key>Comment</key>
<string>UUID of item to send along with BusyModeResponse</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>String</string>
<key>Value</key>
<string/>
</map>
<key>BusyModeResponseShow</key>
<map>
<key>Comment</key>
<string>Whether to show that BusyModeResponses were sent</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>EveryoneExport</key>
<map>
<key>Comment</key>
@@ -336,84 +474,7 @@
<key>Value</key>
<integer>1</integer>
</map>
<key>BusyModeResponse</key>
<map>
<key>Comment</key>
<string>Auto response to instant messages while in busy mode.</string>
</map>
<key>AO.Settings</key>
<map>
<key>Comment</key>
<string>List for animation overrider</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>LLSD</string>
<key>Value</key>
<array>
<string/>
</array>
</map>
<key>Responder.Settings</key>
<map>
<key>Comment</key>
<string>New organization to the Auto-Respond settings for keeping clean</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>LLSD</string>
<key>Value</key>
<map>
<key>Message</key>
<string>This is an autoresponse!</string>
</map>
</map>
<!-- Ascent Account-Specific (Always) -->
<!-- General additions -->
<key>rkeastInventoryPreviousCount</key>
<map>
<key>Comment</key>
<string>Used to keep track of the number of items in inventory when fetching for progress reasons. DO NOT EDIT.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>S32</string>
<key>Value</key>
<integer>-1</integer>
</map>
<key>rkeastInventorySearchType</key>
<map>
<key>Comment</key>
<string>Controls what type of inventory search we perform.</string>
<key>Persist</key>
<integer>0</integer>
<key>Type</key>
<string>U32</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>rkeastInventoryPartialSearch</key>
<map>
<key>Comment</key>
<string>Toggles whether to search using partial search filters on normal (name, desc, creator) searches.</string>
<key>Persist</key>
<integer>0</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>BusyModeResponse</key>
<map>
<key>Comment</key>
<string>Auto response to instant messages while in busy mode.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>String</string>
<key>Value</key>
<string>The Resident you messaged is in 'busy mode' which means they have requested not to be disturbed. Your message will still be shown in their IM panel for later viewing.</string>
</map>
<key>IMLogTimestamp</key>
<map>
<key>Comment</key>

View File

@@ -14,72 +14,7 @@
<string />
</array>
</map>
<key>AscentInstantMessageResponse</key>
<map>
<key>Comment</key>
<string>Auto response to instant messages</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>String</string>
<key>Value</key>
<string>This is an autoresponse!</string>
</map>
<key>AscentInstantMessageResponseAnyone</key>
<map>
<key>Comment</key>
<string>Whether to auto-respond to anyone</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>AscentInstantMessageResponseFriends</key>
<map>
<key>Comment</key>
<string>Whether to auto-respond to non-friends</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>AscentInstantMessageResponseItem</key>
<map>
<key>Comment</key>
<string>Whether to send a item along with the autoresponse</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>AscentInstantMessageResponseItemData</key>
<map>
<key>Comment</key>
<string>UUID</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>String</string>
<key>Value</key>
<string></string>
</map>
<key>AscentInstantMessageResponseMuted</key>
<map>
<key>Comment</key>
<string>Whether to auto-respond to muted people</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>AscentInstantMessageResponseRepeat</key>
<map>
<key>Comment</key>
@@ -91,21 +26,11 @@
<key>Value</key>
<integer>0</integer>
</map>
<key>AscentInstantMessageShowOnTyping</key>
<map>
<key>Comment</key>
<string>Whether to perform the autorespond the moment they begin to type instead of waiting for a actual message</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>AscentInstantMessageShowResponded</key>
<map>
<key>Comment</key>
<string>Whether to hide IMs entirely from those you have chosen to send autoresponses</string>
<string>Whether to perform the autorespond the moment they begin to type instead of waiting for an actual message</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
@@ -113,5 +38,216 @@
<key>Value</key>
<integer>0</integer>
</map>
<!-- Autoresponse Section -->
<key>AutoresponseAnyone</key>
<map>
<key>Comment</key>
<string>Whether to send autoresponse to anyone who isn't muted (or just friends, if AutoresponseAnyoneFriendsOnly)</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>AutoresponseAnyoneFriendsOnly</key>
<map>
<key>Comment</key>
<string>Whether to send AutoresponseAnyone to friends only</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>AutoresponseAnyoneItem</key>
<map>
<key>Comment</key>
<string>Whether to send a item along with AutoresponseAnyone</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>AutoresponseAnyoneItemID</key>
<map>
<key>Comment</key>
<string>UUID of item to send along with AutoresponseAnyone</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>String</string>
<key>Value</key>
<string/>
</map>
<key>AutoresponseAnyoneMessage</key>
<map>
<key>Comment</key>
<string>Message to send as the autoresponse to AutoresponseAnyone</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>String</string>
<key>Value</key>
<string>This is an autoresponse!</string>
</map>
<key>AutoresponseAnyoneShow</key>
<map>
<key>Comment</key>
<string>Whether to show that AutoresponseAnyone's were sent</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>AutoresponseNonFriends</key>
<map>
<key>Comment</key>
<string>Whether to send autoresponse to nonfriends, separately using a different response</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>AutoresponseNonFriendsItem</key>
<map>
<key>Comment</key>
<string>Whether to send a item along with AutoresponseNonFriends</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>AutoresponseNonFriendsItemID</key>
<map>
<key>Comment</key>
<string>UUID of item to send along with AutoresponseNonFriends</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>String</string>
<key>Value</key>
<string/>
</map>
<key>AutoresponseNonFriendsMessage</key>
<map>
<key>Comment</key>
<string>Message to send as the autoresponse to AutoresponseNonFriends</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>String</string>
<key>Value</key>
<string>This is an autoresponse!</string>
</map>
<key>AutoresponseNonFriendsShow</key>
<map>
<key>Comment</key>
<string>Whether to show that AutoresponseNonFriends's were sent</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>AutoresponseMuted</key>
<map>
<key>Comment</key>
<string>Whether to send autoresponse to muted people</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>AutoresponseMutedItem</key>
<map>
<key>Comment</key>
<string>Whether to send a item along with AutoresponseMuted</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>AutoresponseMutedItemID</key>
<map>
<key>Comment</key>
<string>UUID of item to send along with AutoresponseMuted</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>String</string>
<key>Value</key>
<string/>
</map>
<key>AutoresponseMutedMessage</key>
<map>
<key>Comment</key>
<string>Message to send as the autoresponse to AutoresponseMuted</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>String</string>
<key>Value</key>
<string>This is an autoresponse!</string>
</map>
<key>BusyModeResponse</key>
<map>
<key>Comment</key>
<string>Auto response to instant messages while in busy mode.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>String</string>
<key>Value</key>
<string>The Resident you messaged is in 'busy mode' which means they have requested not to be disturbed. Your message will still be shown in their IM panel for later viewing.</string>
</map>
<key>BusyModeResponseItem</key>
<map>
<key>Comment</key>
<string>Whether to send a item along with BusyModeResponse</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>BusyModeResponseItemID</key>
<map>
<key>Comment</key>
<string>UUID of item to send along with BusyModeResponse</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>String</string>
<key>Value</key>
<string/>
</map>
<key>BusyModeResponseShow</key>
<map>
<key>Comment</key>
<string>Whether to show that BusyModeResponses were sent</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
</map>
</llsd>
</llsd>

View File

@@ -0,0 +1,42 @@
/**
* @file solidcolorV.glsl
*
* $LicenseInfo:firstyear=2007&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2007, 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$
*/
uniform mat4 modelview_projection_matrix;
uniform vec4 color;
ATTRIBUTE vec3 position;
ATTRIBUTE vec2 texcoord0;
VARYING vec4 vertex_color;
VARYING vec2 vary_texcoord0;
void main()
{
gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0);
vertex_color = color;
vary_texcoord0 = texcoord0;
}

View File

View File

View File

View File

View File

@@ -46,8 +46,6 @@
#include "llstartup.h"
LLDropTarget* mObjectDropTarget;
LLPrefsAscentChat* LLPrefsAscentChat::sInst;
LLPrefsAscentChat::LLPrefsAscentChat()
{
@@ -62,44 +60,31 @@ LLPrefsAscentChat::LLPrefsAscentChat()
childSetCommitCallback("time_format_combobox", onCommitTimeDate, this);
childSetCommitCallback("date_format_combobox", onCommitTimeDate, this);
childSetCommitCallback("AscentInstantMessageResponseAnyone", onCommitAutoResponse, this);
childSetCommitCallback("AscentInstantMessageResponseFriends", onCommitAutoResponse, this);
childSetCommitCallback("AscentInstantMessageResponseMuted", onCommitAutoResponse, this);
childSetCommitCallback("AscentInstantMessageShowOnTyping", onCommitAutoResponse, this);
childSetCommitCallback("AscentInstantMessageShowResponded", onCommitAutoResponse, this);
childSetCommitCallback("AscentInstantMessageResponseRepeat", onCommitAutoResponse, this);
childSetCommitCallback("AscentInstantMessageResponseItem", onCommitAutoResponse, this);
if(sInst)delete sInst; sInst = this;
LLView* target_view = getChild<LLView>("im_give_drop_target_rect");
if (target_view)
bool started = (LLStartUp::getStartupState() == STATE_STARTED);
if (!started) // Disable autoresponse when not logged in
{
const std::string drop="drop target";
if (mObjectDropTarget) delete mObjectDropTarget;
mObjectDropTarget = new LLDropTarget(drop, target_view->getRect(), SinguIMResponseItemDrop);//, mAvatarID);
addChild(mObjectDropTarget);
LLView* autoresponse = getChildView("Autoresponse");
autoresponse->setAllChildrenEnabled(false);
autoresponse->setToolTip(LLTrans::getString("NotLoggedIn"));
}
bool started = LLStartUp::getStartupState() == STATE_STARTED;
if (started)
{
LLUUID itemid = (LLUUID)gSavedPerAccountSettings.getString("AscentInstantMessageResponseItemData");
LLViewerInventoryItem* item = gInventory.getItem(itemid);
if (item)
{
LLStringUtil::format_map_t args;
args["[ITEM]"] = item->getName();
childSetValue("im_give_disp_rect_txt", LLTrans::getString("CurrentlySetTo", args));
}
else if (itemid.isNull())
childSetValue("im_give_disp_rect_txt", LLTrans::getString("CurrentlyNotSet"));
else
childSetValue("im_give_disp_rect_txt", LLTrans::getString("CurrentlySetToAnItemNotOnThisAccount"));
}
else childSetValue("im_give_disp_rect_txt", LLTrans::getString("NotLoggedIn"));
childSetCommitCallback("im_response", onCommitAutoResponse, this);
// Saved per account settings aren't detected by control_name, therefore autoresponse controls get their values here and have them saved during apply.
childSetValue("AscentInstantMessageResponseRepeat", gSavedPerAccountSettings.getBOOL("AscentInstantMessageResponseRepeat"));
childSetValue("AutoresponseAnyone", gSavedPerAccountSettings.getBOOL("AutoresponseAnyone"));
childSetValue("AutoresponseAnyoneFriendsOnly", gSavedPerAccountSettings.getBOOL("AutoresponseAnyoneFriendsOnly"));
childSetValue("AutoresponseAnyoneItem", gSavedPerAccountSettings.getBOOL("AutoresponseAnyoneItem"));
childSetValue("AutoresponseAnyoneMessage", gSavedPerAccountSettings.getString("AutoresponseAnyoneMessage"));
childSetValue("AutoresponseAnyoneShow", gSavedPerAccountSettings.getBOOL("AutoresponseAnyoneShow"));
childSetValue("AutoresponseNonFriends", gSavedPerAccountSettings.getBOOL("AutoresponseNonFriends"));
childSetValue("AutoresponseNonFriendsItem", gSavedPerAccountSettings.getBOOL("AutoresponseNonFriendsItem"));
childSetValue("AutoresponseNonFriendsMessage", gSavedPerAccountSettings.getString("AutoresponseNonFriendsMessage"));
childSetValue("AutoresponseNonFriendsShow", gSavedPerAccountSettings.getBOOL("AutoresponseNonFriendsShow"));
childSetValue("AutoresponseMuted", gSavedPerAccountSettings.getBOOL("AutoresponseMuted"));
childSetValue("AutoresponseMutedItem", gSavedPerAccountSettings.getBOOL("AutoresponseMutedItem"));
childSetValue("AutoresponseMutedMessage", gSavedPerAccountSettings.getString("AutoresponseMutedMessage"));
childSetValue("BusyModeResponse", gSavedPerAccountSettings.getString("BusyModeResponse"));
childSetValue("BusyModeResponseItem", gSavedPerAccountSettings.getBOOL("BusyModeResponseItem"));
childSetValue("BusyModeResponseShow", gSavedPerAccountSettings.getBOOL("BusyModeResponseShow"));
childSetEnabled("reset_antispam", started);
childSetCommitCallback("reset_antispam", onCommitResetAS, this);
@@ -122,8 +107,6 @@ LLPrefsAscentChat::LLPrefsAscentChat()
LLPrefsAscentChat::~LLPrefsAscentChat()
{
sInst=NULL;
delete mObjectDropTarget; mObjectDropTarget=NULL;
}
//static
@@ -231,30 +214,6 @@ void LLPrefsAscentChat::onCommitTimeDate(LLUICtrl* ctrl, void* userdata)
gSavedSettings.setString("TimestampFormat", timestamp);
}
//static
void LLPrefsAscentChat::onCommitAutoResponse(LLUICtrl* ctrl, void* user_data)
{
LLPrefsAscentChat* self = (LLPrefsAscentChat*)user_data;
gSavedPerAccountSettings.setBOOL("AscentInstantMessageResponseAnyone", self->childGetValue("AscentInstantMessageResponseAnyone"));
gSavedPerAccountSettings.setBOOL("AscentInstantMessageResponseFriends", self->childGetValue("AscentInstantMessageResponseFriends"));
gSavedPerAccountSettings.setBOOL("AscentInstantMessageResponseMuted", self->childGetValue("AscentInstantMessageResponseMuted"));
gSavedPerAccountSettings.setBOOL("AscentInstantMessageShowOnTyping", self->childGetValue("AscentInstantMessageShowOnTyping"));
gSavedPerAccountSettings.setBOOL("AscentInstantMessageShowResponded", self->childGetValue("AscentInstantMessageShowResponded"));
gSavedPerAccountSettings.setBOOL("AscentInstantMessageResponseRepeat", self->childGetValue("AscentInstantMessageResponseRepeat"));
gSavedPerAccountSettings.setBOOL("AscentInstantMessageResponseItem", self->childGetValue("AscentInstantMessageResponseItem"));
gSavedPerAccountSettings.setString("AscentInstantMessageResponse", self->childGetValue("im_response"));
}
//static
void LLPrefsAscentChat::SinguIMResponseItemDrop(LLViewerInventoryItem* item)
{
gSavedPerAccountSettings.setString("AscentInstantMessageResponseItemData", item->getUUID().asString());
LLStringUtil::format_map_t args;
args["[ITEM]"] = item->getName();
sInst->childSetValue("im_give_disp_rect_txt", LLTrans::getString("CurrentlySetTo", args));
}
//static
void LLPrefsAscentChat::onCommitResetAS(LLUICtrl*, void*)
{
@@ -327,6 +286,7 @@ void LLPrefsAscentChat::refreshValues()
//Chat/IM -----------------------------------------------------------------------------
mIMAnnounceIncoming = gSavedSettings.getBOOL("AscentInstantMessageAnnounceIncoming");
mHideTypingNotification = gSavedSettings.getBOOL("AscentHideTypingNotification");
mInstantMessagesFriendsOnly = gSavedSettings.getBOOL("InstantMessagesFriendsOnly");
mShowGroupNameInChatIM = gSavedSettings.getBOOL("OptionShowGroupNameInChatIM");
mShowDisplayNameChanges = gSavedSettings.getBOOL("ShowDisplayNameChanges");
mUseTypingBubbles = gSavedSettings.getBOOL("UseTypingBubbles");
@@ -365,24 +325,40 @@ void LLPrefsAscentChat::refreshValues()
tempTimeFormat = mTimeFormat;
tempDateFormat = mDateFormat;
mIMResponseAnyone = gSavedPerAccountSettings.getBOOL("AscentInstantMessageResponseAnyone");
mIMResponseFriends = gSavedPerAccountSettings.getBOOL("AscentInstantMessageResponseFriends");
mIMResponseMuted = gSavedPerAccountSettings.getBOOL("AscentInstantMessageResponseMuted");
mIMShowOnTyping = gSavedPerAccountSettings.getBOOL("AscentInstantMessageShowOnTyping");
mIMShowResponded = gSavedPerAccountSettings.getBOOL("AscentInstantMessageShowResponded");
mIMResponseRepeat = gSavedPerAccountSettings.getBOOL("AscentInstantMessageResponseRepeat");
mIMResponseItem = gSavedPerAccountSettings.getBOOL("AscentInstantMessageResponseItem");
mIMResponseText = gSavedPerAccountSettings.getString("AscentInstantMessageResponse");
//Chat UI -----------------------------------------------------------------------------
mWoLfVerticalIMTabs = gSavedSettings.getBOOL("WoLfVerticalIMTabs");
mOtherChatsTornOff = gSavedSettings.getBOOL("OtherChatsTornOff");
mIMAnnounceStealFocus = gSavedSettings.getBOOL("PhoenixIMAnnounceStealFocus");
mShowLocalChatFloaterBar = gSavedSettings.getBOOL("ShowLocalChatFloaterBar");
mHorizButt = gSavedSettings.getBOOL("ContactsUseHorizontalButtons");
mOneLineIMButt = gSavedSettings.getBOOL("UseConciseIMButtons");
mOneLineGroupButt = gSavedSettings.getBOOL("UseConciseGroupChatButtons");
mOneLineConfButt = gSavedSettings.getBOOL("UseConciseConferenceButtons");
mOnlyComm = gSavedSettings.getBOOL("CommunicateSpecificShortcut");
mItalicizeActions = gSavedSettings.getBOOL("LiruItalicizeActions");
//Autoresponse ------------------------------------------------------------------------
mIMResponseAnyoneItemID = gSavedPerAccountSettings.getString("AutoresponseAnyoneItemID");
mIMResponseNonFriendsItemID = gSavedPerAccountSettings.getString("AutoresponseNonFriendsItemID");
mIMResponseMutedItemID = gSavedPerAccountSettings.getString("AutoresponseMutedItemID");
mIMResponseBusyItemID = gSavedPerAccountSettings.getString("BusyModeResponseItemID");
gSavedPerAccountSettings.setBOOL("AscentInstantMessageResponseRepeat", childGetValue("AscentInstantMessageResponseRepeat"));
gSavedPerAccountSettings.setBOOL("AutoresponseAnyone", childGetValue("AutoresponseAnyone"));
gSavedPerAccountSettings.setBOOL("AutoresponseAnyoneFriendsOnly", childGetValue("AutoresponseAnyoneFriendsOnly"));
gSavedPerAccountSettings.setBOOL("AutoresponseAnyoneItem", childGetValue("AutoresponseAnyoneItem"));
gSavedPerAccountSettings.setString("AutoresponseAnyoneMessage", childGetValue("AutoresponseAnyoneMessage"));
gSavedPerAccountSettings.setBOOL("AutoresponseAnyoneShow", childGetValue("AutoresponseAnyoneShow"));
gSavedPerAccountSettings.setBOOL("AutoresponseNonFriends", childGetValue("AutoresponseNonFriends"));
gSavedPerAccountSettings.setBOOL("AutoresponseNonFriendsItem", childGetValue("AutoresponseNonFriendsItem"));
gSavedPerAccountSettings.setString("AutoresponseNonFriendsMessage", childGetValue("AutoresponseNonFriendsMessage"));
gSavedPerAccountSettings.setBOOL("AutoresponseNonFriendsShow", childGetValue("AutoresponseNonFriendsShow"));
gSavedPerAccountSettings.setBOOL("AutoresponseMuted", childGetValue("AutoresponseMuted"));
gSavedPerAccountSettings.setBOOL("AutoresponseMutedItem", childGetValue("AutoresponseMutedItem"));
gSavedPerAccountSettings.setString("AutoresponseMutedMessage", childGetValue("AutoresponseMutedMessage"));
gSavedPerAccountSettings.setString("BusyModeResponse", childGetValue("BusyModeResponse"));
gSavedPerAccountSettings.setBOOL("BusyModeResponseItem", childGetValue("BusyModeResponseItem"));
gSavedPerAccountSettings.setBOOL("BusyModeResponseShow", childGetValue("BusyModeResponseShow"));
//Spam --------------------------------------------------------------------------------
mEnableAS = gSavedSettings.getBOOL("AntiSpamEnabled");
@@ -434,19 +410,6 @@ void LLPrefsAscentChat::refresh()
combo->setCurrentByIndex(mDateFormat);
}
childSetValue("AscentInstantMessageResponseAnyone", mIMResponseAnyone);
childSetValue("AscentInstantMessageResponseFriends", mIMResponseFriends);
childSetValue("AscentInstantMessageResponseMuted", mIMResponseMuted);
childSetValue("AscentInstantMessageShowOnTyping", mIMShowOnTyping);
childSetValue("AscentInstantMessageShowResponded", mIMShowResponded);
childSetValue("AscentInstantMessageResponseRepeat", mIMResponseRepeat);
childSetValue("AscentInstantMessageResponseItem", mIMResponseItem);
LLWString auto_response = utf8str_to_wstring( gSavedPerAccountSettings.getString("AscentInstantMessageResponse") );
LLWStringUtil::replaceChar(auto_response, '^', '\n');
LLWStringUtil::replaceChar(auto_response, '%', ' ');
childSetText("im_response", wstring_to_utf8str(auto_response));
//Antispam ------------------------------------------------------------------------
// sensitivity tuners
childSetEnabled("spammsg_checkbox", mEnableAS);
@@ -544,6 +507,7 @@ void LLPrefsAscentChat::cancel()
//Chat/IM -----------------------------------------------------------------------------
gSavedSettings.setBOOL("AscentInstantMessageAnnounceIncoming", mIMAnnounceIncoming);
gSavedSettings.setBOOL("AscentHideTypingNotification", mHideTypingNotification);
gSavedSettings.setBOOL("InstantMessagesFriendsOnly", mInstantMessagesFriendsOnly);
gSavedSettings.setBOOL("OptionShowGroupNameInChatIM", mShowGroupNameInChatIM);
gSavedSettings.setBOOL("ShowDisplayNameChanges", mShowDisplayNameChanges);
gSavedSettings.setBOOL("UseTypingBubbles", mUseTypingBubbles);
@@ -595,24 +559,23 @@ void LLPrefsAscentChat::cancel()
gSavedSettings.setString("LongTimeFormat", long_time);
gSavedSettings.setString("TimestampFormat", timestamp);
gSavedPerAccountSettings.setBOOL("AscentInstantMessageResponseAnyone", mIMResponseAnyone);
gSavedPerAccountSettings.setBOOL("AscentInstantMessageResponseFriends", mIMResponseFriends);
gSavedPerAccountSettings.setBOOL("AscentInstantMessageResponseMuted", mIMResponseMuted);
gSavedPerAccountSettings.setBOOL("AscentInstantMessageShowOnTyping", mIMShowOnTyping);
gSavedPerAccountSettings.setBOOL("AscentInstantMessageShowResponded", mIMShowResponded);
gSavedPerAccountSettings.setBOOL("AscentInstantMessageResponseRepeat", mIMResponseRepeat);
gSavedPerAccountSettings.setBOOL("AscentInstantMessageResponseItem", mIMResponseItem);
gSavedPerAccountSettings.setString("AscentInstantMessageResponse", mIMResponseText);
//Chat UI -----------------------------------------------------------------------------
gSavedSettings.setBOOL("WoLfVerticalIMTabs", mWoLfVerticalIMTabs);
gSavedSettings.setBOOL("OtherChatsTornOff", mOtherChatsTornOff);
gSavedSettings.setBOOL("PhoenixIMAnnounceStealFocus", mIMAnnounceStealFocus);
gSavedSettings.setBOOL("ShowLocalChatFloaterBar", mShowLocalChatFloaterBar);
gSavedSettings.setBOOL("ContactsUseHorizontalButtons", mHorizButt);
gSavedSettings.setBOOL("UseConciseIMButtons", mOneLineIMButt);
gSavedSettings.setBOOL("UseConciseGroupChatButtons", mOneLineGroupButt);
gSavedSettings.setBOOL("UseConciseConferenceButtons", mOneLineConfButt);
gSavedSettings.setBOOL("CommunicateSpecificShortcut", mOnlyComm);
gSavedSettings.setBOOL("LiruItalicizeActions", mItalicizeActions);
//Autoresponse ------------------------------------------------------------------------
gSavedPerAccountSettings.setString("AutoresponseAnyoneItemID", mIMResponseAnyoneItemID);
gSavedPerAccountSettings.setString("AutoresponseNonFriendsItemID", mIMResponseNonFriendsItemID);
gSavedPerAccountSettings.setString("AutoresponseMutedItemID", mIMResponseMutedItemID);
gSavedPerAccountSettings.setString("BusyModeResponseItemID", mIMResponseBusyItemID);
//Spam --------------------------------------------------------------------------------
gSavedSettings.setBOOL("AntiSpamEnabled", mEnableAS);
@@ -632,7 +595,7 @@ void LLPrefsAscentChat::cancel()
gSavedSettings.setU32("_NACL_AntiSpamSoundMulti", mSoundMulti);
gSavedSettings.setU32("_NACL_AntiSpamNewlines", mNewLines);
gSavedSettings.setU32("_NACL_AntiSpamSoundPreloadMulti", mPreloadMulti);
gSavedSettings.setBOOL("EnableGestureSounds", mEnableGestureSounds);
gSavedSettings.setBOOL("EnableGestureSounds", mEnableGestureSounds);
//Text Options ------------------------------------------------------------------------
gSavedSettings.setBOOL("SpellDisplay", mSpellDisplay);
@@ -649,8 +612,6 @@ void LLPrefsAscentChat::cancel()
// Update local copy so cancel has no effect
void LLPrefsAscentChat::apply()
{
gSavedPerAccountSettings.setString("AscentInstantMessageResponse", childGetValue("im_response"));
refreshValues();
refresh();
}

View File

@@ -34,8 +34,6 @@
#include "llpanel.h"
#include "lldroptarget.h"
class LLPrefsAscentChat : public LLPanel
{
@@ -55,7 +53,6 @@ protected:
static void onSpellEditCustom(void* data);
static void onSpellBaseComboBoxCommit(LLUICtrl* ctrl, void* userdata);
static void onCommitTimeDate(LLUICtrl* ctrl, void *userdata);
static void onCommitAutoResponse(LLUICtrl* ctrl, void* user_data);
static void onCommitResetAS(LLUICtrl*,void*);
static void onCommitEnableAS(LLUICtrl*, void*);
static void onCommitDialogBlock(LLUICtrl*, void*);
@@ -64,6 +61,7 @@ protected:
//Chat/IM -----------------------------------------------------------------------------
BOOL mIMAnnounceIncoming;
BOOL mHideTypingNotification;
bool mInstantMessagesFriendsOnly;
BOOL mShowGroupNameInChatIM;
bool mShowDisplayNameChanges;
bool mUseTypingBubbles;
@@ -79,24 +77,23 @@ protected:
BOOL mSecondsInChatAndIMs;
BOOL mSecondsInLog;
BOOL mIMResponseAnyone;
BOOL mIMResponseFriends;
BOOL mIMResponseMuted;
BOOL mIMShowOnTyping;
BOOL mIMShowResponded;
BOOL mIMResponseRepeat;
BOOL mIMResponseItem;
std::string mIMResponseText;
//Chat UI -----------------------------------------------------------------------------
bool mWoLfVerticalIMTabs;
bool mOtherChatsTornOff;
bool mIMAnnounceStealFocus;
bool mShowLocalChatFloaterBar;
bool mHorizButt;
bool mOneLineIMButt;
bool mOneLineGroupButt;
bool mOneLineConfButt;
bool mOnlyComm;
bool mItalicizeActions;
//Autoresponse ------------------------------------------------------------------------
std::string mIMResponseAnyoneItemID;
std::string mIMResponseNonFriendsItemID;
std::string mIMResponseMutedItemID;
std::string mIMResponseBusyItemID;
//Spam --------------------------------------------------------------------------------
BOOL mEnableAS;
@@ -128,9 +125,6 @@ protected:
LLColor4 mKeywordsColor;
BOOL mKeywordsPlaySound;
LLUUID mKeywordsSound;
private:
static LLPrefsAscentChat* sInst;
static void SinguIMResponseItemDrop(LLViewerInventoryItem* item);
};
#endif

View File

@@ -44,12 +44,8 @@
#include "lltexturectrl.h"
#include "lluictrlfactory.h"
#include "llviewercontrol.h"
#include "llstartup.h"
#include "lltrans.h"
LLDropTarget* mBuildDropTarget;
LLPrefsAscentSys* LLPrefsAscentSys::sInst;
LLPrefsAscentSys::LLPrefsAscentSys()
{
LLUICtrlFactory::getInstance()->buildPanel(this, "panel_preferences_ascent_system.xml");
@@ -91,42 +87,12 @@ LLPrefsAscentSys::LLPrefsAscentSys()
getChild<LLTextureCtrl>("texture control")->setDefaultImageAssetID(LLUUID(gSavedSettings.getString("EmeraldBuildPrefs_Texture")));
childSetCommitCallback("texture control", onCommitTexturePicker, this);
if(sInst)delete sInst; sInst = this;
LLView* target_view = getChild<LLView>("build_item_drop_target_rect");
if (target_view)
{
const std::string drop="drop target";
if (mBuildDropTarget) delete mBuildDropTarget;
mBuildDropTarget = new LLDropTarget(drop, target_view->getRect(), SinguBuildItemDrop);//, mAvatarID);
addChild(mBuildDropTarget);
}
if (LLStartUp::getStartupState() == STATE_STARTED)
{
LLUUID itemid = (LLUUID)gSavedPerAccountSettings.getString("EmeraldBuildPrefs_Item");
LLViewerInventoryItem* item = gInventory.getItem(itemid);
if (item)
{
LLStringUtil::format_map_t args;
args["[ITEM]"] = item->getName();
childSetValue("build_item_add_disp_rect_txt", LLTrans::getString("CurrentlySetTo", args));
}
else if (itemid.isNull())
childSetValue("build_item_add_disp_rect_txt", LLTrans::getString("CurrentlyNotSet"));
else
childSetValue("build_item_add_disp_rect_txt", LLTrans::getString("CurrentlySetToAnItemNotOnThisAccount"));
}
else childSetValue("build_item_add_disp_rect_txt", LLTrans::getString("NotLoggedIn"));
refreshValues();
refresh();
}
LLPrefsAscentSys::~LLPrefsAscentSys()
{
sInst=NULL;
delete mBuildDropTarget; mBuildDropTarget=NULL;
}
//static
@@ -253,21 +219,13 @@ void LLPrefsAscentSys::onCommitTexturePicker(LLUICtrl* ctrl, void* userdata)
if(image_ctrl) gSavedSettings.setString("EmeraldBuildPrefs_Texture", image_ctrl->getImageAssetID().asString());
}
//static
void LLPrefsAscentSys::SinguBuildItemDrop(LLViewerInventoryItem* item)
{
gSavedPerAccountSettings.setString("EmeraldBuildPrefs_Item", item->getUUID().asString());
LLStringUtil::format_map_t args;
args["[ITEM]"] = item->getName();
sInst->childSetValue("build_item_add_disp_rect_txt", LLTrans::getString("CurrentlySetTo", args));
}
void LLPrefsAscentSys::refreshValues()
{
//General -----------------------------------------------------------------------------
mDoubleClickTeleport = gSavedSettings.getBOOL("DoubleClickTeleport");
mResetCameraAfterTP = gSavedSettings.getBOOL("OptionRotateCamAfterLocalTP");
mOffsetTPByUserHeight = gSavedSettings.getBOOL("OptionOffsetTPByAgentHeight");
mClearBeaconAfterTeleport = gSavedSettings.getBOOL("ClearBeaconAfterTeleport");
mLiruFlyAfterTeleport = gSavedSettings.getBOOL("LiruFlyAfterTeleport");
mLiruContinueFlying = gSavedSettings.getBOOL("LiruContinueFlyingOnUnsit");
mPreviewAnimInWorld = gSavedSettings.getBOOL("PreviewAnimInWorld");
@@ -323,6 +281,7 @@ void LLPrefsAscentSys::refreshValues()
mColor = gSavedSettings.getColor4("EmeraldBuildPrefs_Color");
mFullBright = gSavedSettings.getBOOL("EmeraldBuildPrefs_FullBright");
mGlow = gSavedSettings.getF32("EmeraldBuildPrefs_Glow");
mItem = gSavedPerAccountSettings.getString("EmeraldBuildPrefs_Item");
mMaterial = gSavedSettings.getString("BuildPrefs_Material");
mNextCopy = gSavedSettings.getBOOL("NextOwnerCopy");
mNextMod = gSavedSettings.getBOOL("NextOwnerModify");
@@ -420,6 +379,7 @@ void LLPrefsAscentSys::cancel()
gSavedSettings.setBOOL("DoubleClickTeleport", mDoubleClickTeleport);
gSavedSettings.setBOOL("OptionRotateCamAfterLocalTP", mResetCameraAfterTP);
gSavedSettings.setBOOL("OptionOffsetTPByAgentHeight", mOffsetTPByUserHeight);
gSavedSettings.setBOOL("ClearBeaconAfterTeleport", mClearBeaconAfterTeleport);
gSavedSettings.setBOOL("LiruFlyAfterTeleport", mLiruFlyAfterTeleport);
gSavedSettings.setBOOL("LiruContinueFlyingOnUnsit", mLiruContinueFlying);
gSavedSettings.setBOOL("PreviewAnimInWorld", mPreviewAnimInWorld);
@@ -474,6 +434,7 @@ void LLPrefsAscentSys::cancel()
gSavedSettings.setColor4("EmeraldBuildPrefs_Color", mColor);
gSavedSettings.setBOOL("EmeraldBuildPrefs_FullBright", mFullBright);
gSavedSettings.setF32("EmeraldBuildPrefs_Glow", mGlow);
gSavedPerAccountSettings.setString("EmeraldBuildPrefs_Item", mItem);
gSavedSettings.setString("BuildPrefs_Material", mMaterial);
gSavedSettings.setBOOL("NextOwnerCopy", mNextCopy);
gSavedSettings.setBOOL("NextOwnerModify", mNextMod);

View File

@@ -34,8 +34,6 @@
#include "llpanel.h"
#include "lldroptarget.h"
class LLPrefsAscentSys : public LLPanel
{
@@ -58,6 +56,7 @@ protected:
BOOL mDoubleClickTeleport;
BOOL mResetCameraAfterTP;
BOOL mOffsetTPByUserHeight;
bool mClearBeaconAfterTeleport;
bool mLiruFlyAfterTeleport;
bool mLiruContinueFlying;
BOOL mPreviewAnimInWorld;
@@ -107,11 +106,13 @@ protected:
bool mDisableClickSitOtherOwner;
BOOL mDisplayScriptJumps;
F32 mNumScriptDiff;
//Build -------------------------------------------------------------------------------
F32 mAlpha;
LLColor4 mColor;
BOOL mFullBright;
F32 mGlow;
std::string mItem;
std::string mMaterial;
BOOL mNextCopy;
BOOL mNextMod;
@@ -124,9 +125,6 @@ protected:
F32 mXsize;
F32 mYsize;
F32 mZsize;
private:
static LLPrefsAscentSys* sInst;
static void SinguBuildItemDrop(LLViewerInventoryItem* item);
};
#endif

View File

@@ -136,73 +136,6 @@ BOOL AOInvTimer::tick()
}
return FALSE;
}
// NC DROP -------------------------------------------------------
class AONoteCardDropTarget : public LLView
{
public:
AONoteCardDropTarget(const std::string& name, const LLRect& rect, void (*callback)(LLViewerInventoryItem*));
~AONoteCardDropTarget();
void doDrop(EDragAndDropType cargo_type, void* cargo_data);
//
// LLView functionality
virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
EDragAndDropType cargo_type,
void* cargo_data,
EAcceptance* accept,
std::string& tooltip_msg);
protected:
void (*mDownCallback)(LLViewerInventoryItem*);
};
AONoteCardDropTarget::AONoteCardDropTarget(const std::string& name, const LLRect& rect,
void (*callback)(LLViewerInventoryItem*)) :
LLView(name, rect, NOT_MOUSE_OPAQUE, FOLLOWS_ALL),
mDownCallback(callback)
{
}
AONoteCardDropTarget::~AONoteCardDropTarget()
{
}
void AONoteCardDropTarget::doDrop(EDragAndDropType cargo_type, void* cargo_data)
{
// llinfos << "AONoteCardDropTarget::doDrop()" << llendl;
}
BOOL AONoteCardDropTarget::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
EDragAndDropType cargo_type,
void* cargo_data,
EAcceptance* accept,
std::string& tooltip_msg)
{
BOOL handled = FALSE;
if(getParent())
{
handled = TRUE;
LLViewerInventoryItem* inv_item = (LLViewerInventoryItem*)cargo_data;
if(gInventory.getItem(inv_item->getUUID()))
{
*accept = ACCEPT_YES_COPY_SINGLE;
if(drop)
{
mDownCallback(inv_item);
}
}
else
{
*accept = ACCEPT_NO;
}
}
return handled;
}
AONoteCardDropTarget * LLFloaterAO::mAOItemDropTarget;
// STUFF -------------------------------------------------------
@@ -283,8 +216,6 @@ LLFloaterAO::~LLFloaterAO()
mcomboBox_lands = 0;
mcomboBox_standups = 0;
mcomboBox_prejumps = 0;
delete mAOItemDropTarget;
mAOItemDropTarget = NULL;
// llinfos << "floater destroyed" << llendl;
}
@@ -315,39 +246,6 @@ bool LLFloaterAO::getInstance()
BOOL LLFloaterAO::postBuild()
{
LLView *target_view = getChild<LLView>("ao_notecard");
if(target_view)
{
if (mAOItemDropTarget)
{
delete mAOItemDropTarget;
}
mAOItemDropTarget = new AONoteCardDropTarget("drop target", target_view->getRect(), AOItemDrop);//, mAvatarID);
addChild(mAOItemDropTarget);
}
if(LLStartUp::getStartupState() == STATE_STARTED)
{
LLUUID itemidimport = (LLUUID)gSavedPerAccountSettings.getString("AOConfigNotecardID");
LLViewerInventoryItem* itemimport = gInventory.getItem(itemidimport);
if(itemimport)
{
LLStringUtil::format_map_t args;
args["[ITEM]"] = itemimport->getName();
childSetValue("ao_nc_text", LLTrans::getString("CurrentlySetTo", args));
}
else if(itemidimport.isNull())
{
childSetValue("ao_nc_text", LLTrans::getString("CurrentlyNotSet"));
}
else
{
childSetValue("ao_nc_text", LLTrans::getString("CurrentlySetToAnItemNotOnThisAccount"));
}
}
else
{
childSetValue("ao_nc_text", LLTrans::getString("NotLoggedIn"));
}
childSetAction("more_btn", onClickMore, this);
childSetAction("less_btn", onClickLess, this);
@@ -793,14 +691,6 @@ void LLFloaterAO::setCurrentStandId(const LLUUID& id)
mCurrentStandId = id;
}
void LLFloaterAO::AOItemDrop(LLViewerInventoryItem* item)
{
gSavedPerAccountSettings.setString("AOConfigNotecardID", item->getUUID().asString());
LLStringUtil::format_map_t args;
args["[ITEM]"] = item->getName();
sInstance->childSetValue("ao_nc_text", LLTrans::getString("CurrentlySetTo", args));
}
LLUUID LLFloaterAO::GetAnimID(const LLUUID& id)
{
for (std::vector<struct_overrides>::iterator iter = mAOOverrides.begin(); iter != mAOOverrides.end(); ++iter)
@@ -1383,7 +1273,7 @@ BOOL LLFloaterAO::SetDefault(void* userdata, LLUUID ao_id, std::string defaultan
if (sInstance && (userdata))
{
LLComboBox *box = (LLComboBox *) userdata;
if (LLUUID::null == ao_id)
if (ao_id.isNull())
{
box->clear();
box->removeall();

View File

@@ -8,8 +8,6 @@
#include "lleventtimer.h"
class AONoteCardDropTarget;
const int STATE_AGENT_IDLE = 0;
const int STATE_AGENT_WALK = 1;
const int STATE_AGENT_RUN = 2;
@@ -113,8 +111,6 @@ private:
static int mAnimationState;
static LLUUID mCurrentStandId;
static AONoteCardDropTarget* mAOItemDropTarget;
static void AOItemDrop(LLViewerInventoryItem* item);
static void onSpinnerCommit(LLUICtrl* ctrl);
static void onComboBoxCommit(LLUICtrl* ctrl);
static BOOL SetDefault(void *userdata, LLUUID ao_id, std::string defaultanim);

View File

@@ -252,7 +252,6 @@ private:
LLButton* mUploadBtn;
LLScrollListCtrl* mBitmapList;
LLScrollListCtrl* mUsedList;
LLTextureCtrl* mTextureView;
LLCheckBoxCtrl* mUpdateChkBox;

View File

@@ -57,7 +57,6 @@ extern AIHTTPTimeoutPolicy iamHereVoice_timeout;
FloaterVoiceLicense::FloaterVoiceLicense(const LLSD& key)
: LLModalDialog( std::string(" "), 100, 100 ),
mWebBrowserWindowId( 0 ),
mLoadCompleteCount( 0 )
{
LLUICtrlFactory::getInstance()->buildFloater(this, "floater_voice_license.xml");

View File

@@ -66,7 +66,6 @@ public:
/*virtual*/ void handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event);
private:
int mWebBrowserWindowId;
int mLoadCompleteCount;
};

View File

@@ -157,7 +157,7 @@ void HBFloaterGroupTitles::onActivate(void* userdata)
// Set the title
LLGroupMgr::getInstance()->sendGroupTitleUpdate(group_id, item->getUUID());
// Force a refresh via the observer
if (group_id == LLUUID::null)
if (group_id.isNull())
{
group_id = old_group_id;
}

View File

@@ -236,7 +236,7 @@ void ImportTracker::get_update(S32 newid, BOOL justCreated, BOOL createSelected)
msg->nextBlockFast(_PREHASH_ObjectData);
msg->addU32Fast(_PREHASH_ObjectLocalID, (U32)newid);
msg->addU8Fast(_PREHASH_Field, PERM_NEXT_OWNER);
msg->addBOOLFast(_PREHASH_Set, PERM_ITEM_UNRESTRICTED);
msg->addU8Fast(_PREHASH_Set, PERM_SET_TRUE);
U32 flags = 0;
if ( gSavedSettings.getBOOL("NextOwnerCopy") )
{
@@ -718,7 +718,7 @@ void ImportTracker::send_properties(LLSD& prim, int counter)
msg->nextBlockFast(_PREHASH_ObjectData);
msg->addU32Fast(_PREHASH_ObjectLocalID, prim["LocalID"].asInteger());
msg->addU8Fast(_PREHASH_Field, PERM_NEXT_OWNER);
msg->addBOOLFast(_PREHASH_Set, PERM_ITEM_UNRESTRICTED);
msg->addU8Fast(_PREHASH_Set, PERM_SET_TRUE);
msg->addU32Fast(_PREHASH_Mask, U32(atoi(prim["next_owner_mask"].asString().c_str())));
*//*msg->sendReliable(gAgent.getRegion()->getHost());
@@ -732,7 +732,7 @@ void ImportTracker::send_properties(LLSD& prim, int counter)
msg->nextBlockFast(_PREHASH_ObjectData);
msg->addU32Fast(_PREHASH_ObjectLocalID, prim["LocalID"].asInteger());
msg->addU8Fast(_PREHASH_Field, PERM_GROUP);
msg->addBOOLFast(_PREHASH_Set, PERM_ITEM_UNRESTRICTED);
msg->addU8Fast(_PREHASH_Set, PERM_SET_TRUE);
msg->addU32Fast(_PREHASH_Mask, U32(atoi(prim["group_mask"].asString().c_str())));
*//*msg->sendReliable(gAgent.getRegion()->getHost());
@@ -746,7 +746,7 @@ void ImportTracker::send_properties(LLSD& prim, int counter)
msg->nextBlockFast(_PREHASH_ObjectData);
msg->addU32Fast(_PREHASH_ObjectLocalID, prim["LocalID"].asInteger());
msg->addU8Fast(_PREHASH_Field, PERM_EVERYONE);
msg->addBOOLFast(_PREHASH_Set, PERM_ITEM_UNRESTRICTED);
msg->addU8Fast(_PREHASH_Set, PERM_SET_TRUE);
msg->addU32Fast(_PREHASH_Mask, U32(atoi(prim["everyone_mask"].asString().c_str())));
msg->sendReliable(gAgent.getRegion()->getHost());

View File

Before

Width:  |  Height:  |  Size: 256 KiB

After

Width:  |  Height:  |  Size: 256 KiB

View File

Before

Width:  |  Height:  |  Size: 254 KiB

After

Width:  |  Height:  |  Size: 254 KiB

View File

Before

Width:  |  Height:  |  Size: 359 KiB

After

Width:  |  Height:  |  Size: 359 KiB

View File

@@ -154,7 +154,7 @@ export SL_OPT="`cat gridargs.dat` $@"
eval ${SL_ENV} ${SL_CMD} ${SL_OPT} || LL_RUN_ERR=runerr
# Handle any resulting errors
if [ -n "$LL_RUN_ERR" ]; then
if [ "$LL_RUN_ERR" = "runerr" ]; then
# generic error running the binary
echo '*** Bad shutdown. ***'
fi

View File

@@ -666,11 +666,13 @@ void LLAgent::setFlying(BOOL fly)
return;
}
/* Singu Note: We don't take off while sitting, don't bother with this check, let us toggle fly whenever.
// don't allow taking off while sitting
if (fly && gAgentAvatarp->isSitting())
{
return;
}
*/
}
if (fly)
@@ -883,11 +885,6 @@ void LLAgent::setRegion(LLViewerRegion *regionp)
//-----------------------------------------------------------------------------
// getRegion()
//-----------------------------------------------------------------------------
LLViewerRegion *LLAgent::getRegion() const
{
return mRegionp;
}
const LLHost& LLAgent::getRegionHost() const
{
@@ -3862,7 +3859,7 @@ bool LLAgent::teleportCore(bool is_local)
// close the map panel so we can see our destination.
// we don't close search floater, see EXT-5840.
LLFloaterWorldMap::hide(NULL);
LLFloaterWorldMap::hide();
// hide land floater too - it'll be out of date
LLFloaterLand::hideInstance();

View File

@@ -242,7 +242,7 @@ private:
//--------------------------------------------------------------------
public:
void setRegion(LLViewerRegion *regionp);
LLViewerRegion *getRegion() const;
LLViewerRegion *getRegion() const { return mRegionp; }
const LLHost& getRegionHost() const;
BOOL inPrelude();
std::string getSLURL() const; //Return uri for current region

View File

@@ -910,7 +910,6 @@ void LLAgentCamera::cameraZoomIn(const F32 fraction)
}
LLVector3d camera_offset(mCameraFocusOffsetTarget);
LLVector3d camera_offset_unit(mCameraFocusOffsetTarget);
F32 min_zoom = 0.f;//LAND_MIN_ZOOM;
F32 current_distance = (F32)camera_offset_unit.normalize();
@@ -988,7 +987,6 @@ void LLAgentCamera::cameraOrbitIn(const F32 meters)
}
else
{
LLVector3d camera_offset(mCameraFocusOffsetTarget);
LLVector3d camera_offset_unit(mCameraFocusOffsetTarget);
F32 current_distance = (F32)camera_offset_unit.normalize();
F32 new_distance = current_distance - meters;

View File

@@ -3921,14 +3921,14 @@ void LLAppearanceMgr::removeItemsFromAvatar(const uuid_vec_t& ids_to_remove)
bool fUpdateAppearance = false;
for (uuid_vec_t::const_iterator it = ids_to_remove.begin(); it != ids_to_remove.end(); ++it)
{
const LLInventoryItem* linked_item = gInventory.getLinkedItem(*it);
if ( (rlv_handler_t::isEnabled()) && (!rlvPredCanRemoveItem(linked_item)) )
const LLUUID& linked_item_id = gInventory.getLinkedItemID(*it);
if ( (rlv_handler_t::isEnabled()) && (!rlvPredCanRemoveItem(gInventory.getItem(linked_item_id))) )
{
continue;
}
fUpdateAppearance = true;
removeCOFItemLinks(linked_item->getUUID());
removeCOFItemLinks(linked_item_id);
}
if (fUpdateAppearance)
@@ -3948,18 +3948,14 @@ void LLAppearanceMgr::removeItemsFromAvatar(const uuid_vec_t& ids_to_remove)
void LLAppearanceMgr::removeItemFromAvatar(const LLUUID& id_to_remove)
{
// [RLVa:KB] - Checked: 2013-02-12 (RLVa-1.4.8)
const LLInventoryItem* linked_item = gInventory.getLinkedItem(id_to_remove);
if ( (rlv_handler_t::isEnabled()) && (!rlvPredCanRemoveItem(linked_item)) )
LLUUID linked_item_id = gInventory.getLinkedItemID(id_to_remove);
if ( (rlv_handler_t::isEnabled()) && (!rlvPredCanRemoveItem(gInventory.getItem(linked_item_id))) )
{
return;
}
removeCOFItemLinks(linked_item->getUUID());
updateAppearanceFromCOF();
// [/RLVA:KB]
// LLUUID linked_item_id = gInventory.getLinkedItemID(id_to_remove);
// removeCOFItemLinks(linked_item_id);
// updateAppearanceFromCOF();
removeCOFItemLinks(linked_item_id);
updateAppearanceFromCOF();
}
bool LLAppearanceMgr::moveWearable(LLViewerInventoryItem* item, bool closer_to_body)

View File

@@ -546,16 +546,31 @@ F32 LLDrawable::updateXform(BOOL undamped)
}
}
if ((mCurrentScale != target_scale) ||
(!isRoot() &&
(dist_squared >= MIN_INTERPOLATE_DISTANCE_SQUARED ||
!mVObjp->getAngularVelocity().isExactlyZero() ||
target_pos != mXform.getPosition() ||
target_rot != mXform.getRotation())))
{ //child prim moving or scale change requires immediate rebuild
LLVector3 vec = mCurrentScale-target_scale;
if (vec*vec > MIN_INTERPOLATE_DISTANCE_SQUARED)
{ //scale change requires immediate rebuild
mCurrentScale = target_scale;
gPipeline.markRebuild(this, LLDrawable::REBUILD_POSITION, TRUE);
}
else if (!isRoot() &&
(!mVObjp->getAngularVelocity().isExactlyZero() ||
dist_squared > 0.f))
{ //child prim moving relative to parent, tag as needing to be rendered atomically and rebuild
dist_squared = 1.f; //keep this object on the move list
if (!isState(LLDrawable::ANIMATED_CHILD))
{
setState(LLDrawable::ANIMATED_CHILD);
gPipeline.markRebuild(this, LLDrawable::REBUILD_ALL, TRUE);
mVObjp->dirtySpatialGroup();
}
}
else if (!isRoot() && (
dist_vec_squared(old_pos, target_pos) > 0.f
|| old_rot != target_rot ))
{ //fix for BUG-860, MAINT-2275, MAINT-1742, MAINT-2247
gPipeline.markRebuild(this, LLDrawable::REBUILD_POSITION, TRUE);
}
else if (!getVOVolume() && !isAvatar())
{
movePartition();

View File

@@ -40,24 +40,127 @@
#include "llviewerprecompiledheaders.h"
#include "lldroptarget.h"
#include "lltooldraganddrop.h"
#include "llinventorymodel.h"
LLDropTarget::LLDropTarget(const std::string& name, const LLRect& rect, const LLUUID& agent_id) :
LLView(name, rect, NOT_MOUSE_OPAQUE, FOLLOWS_ALL),
mAgentID(agent_id),
mDownCallback(NULL)
#include "llinventorymodel.h"
#include "llstartup.h"
#include "lltextbox.h"
#include "lltooldraganddrop.h"
#include "lltrans.h"
static LLRegisterWidget<LLDropTarget> r("drop_target");
static std::string currently_set_to(const LLViewerInventoryItem* item)
{
LLStringUtil::format_map_t args;
args["[ITEM]"] = item->getName();
return LLTrans::getString("CurrentlySetTo", args);
}
LLDropTarget::LLDropTarget(const std::string& name, const LLRect& rect, void (*callback)(LLViewerInventoryItem*)) :
LLView(name, rect, NOT_MOUSE_OPAQUE, FOLLOWS_ALL),
mDownCallback(callback)
LLDropTarget::LLDropTarget(const LLDropTarget::Params& p)
: LLView(p)
{
setToolTip(std::string(p.tool_tip));
mText = new LLTextBox("drop_text", p.rect, p.label);
addChild(mText);
setControlName(p.control_name, NULL);
mText->setOrigin(0, 0);
mText->setFollows(FOLLOWS_NONE);
mText->setHAlign(LLFontGL::HCENTER);
mText->setBorderVisible(true);
mText->setBorderColor(LLUI::sColorsGroup->getColor("DefaultHighlightLight"));
if (p.fill_parent) fillParent(getParent());
}
LLDropTarget::~LLDropTarget()
{
delete mText;
}
// static
LLView* LLDropTarget::fromXML(LLXMLNodePtr node, LLView* parent, LLUICtrlFactory* factory)
{
LLDropTarget* target = new LLDropTarget();
target->initFromXML(node, parent);
return target;
}
// virtual
void LLDropTarget::initFromXML(LLXMLNodePtr node, LLView* parent)
{
LLView::initFromXML(node, parent);
const LLRect& rect = getRect();
mText->setRect(LLRect(0, rect.getHeight(), rect.getWidth(), 0));
if (node->hasAttribute("name")) // Views can't have names, but drop targets can
{
std::string name;
node->getAttributeString("name", name);
setName(name);
}
if (node->hasAttribute("label"))
{
std::string label;
node->getAttributeString("label", label);
mText->setText(label);
}
if (node->hasAttribute("fill_parent"))
{
bool fill;
node->getAttribute_bool("fill_parent", fill);
if (fill) fillParent(parent);
}
}
// virtual
void LLDropTarget::setControlName(const std::string& control_name, LLView* context)
{
if (control_name.empty()) // The "empty set"
{
mControl = NULL;
return; // This DropTarget never changes text, it isn't tied to a control
}
std::string text;
if (LLStartUp::getStartupState() != STATE_STARTED) // Too early for PerAccount
{
text = LLTrans::getString("NotLoggedIn");
}
else
{
mControl = gSavedPerAccountSettings.getControl(control_name);
const LLUUID id(mControl->getValue().asString());
if (id.isNull())
text = LLTrans::getString("CurrentlyNotSet");
else if (LLViewerInventoryItem* item = gInventory.getItem(id))
text = currently_set_to(item);
else
text = LLTrans::getString("CurrentlySetToAnItemNotOnThisAccount");
}
mText->setText(text);
}
void LLDropTarget::fillParent(const LLView* parent)
{
if (!parent) return; // No parent to fill
const std::string& tool_tip = getToolTip();
if (!tool_tip.empty()) // Don't tool_tip the entire parent
{
mText->setToolTip(tool_tip);
setToolTip(LLStringExplicit(""));
}
// The following block enlarges the target, but maintains the desired size for the text and border
mText->setRect(getRect()); // mText takes over the old rectangle, since the position will now be relative to the parent's rectangle for the text.
const LLRect& parent_rect = parent->getRect();
setRect(LLRect(0, parent_rect.getHeight(), parent_rect.getWidth(), 0));
}
void LLDropTarget::doDrop(EDragAndDropType cargo_type, void* cargo_data)
@@ -67,17 +170,23 @@ void LLDropTarget::doDrop(EDragAndDropType cargo_type, void* cargo_data)
BOOL LLDropTarget::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EDragAndDropType cargo_type, void* cargo_data, EAcceptance* accept, std::string& tooltip_msg)
{
if(!getParent()) return false;
if(!mDownCallback) LLToolDragAndDrop::handleGiveDragAndDrop(mAgentID, LLUUID::null, drop, cargo_type, cargo_data, accept);
else
if (mEntityID.isNull())
{
LLViewerInventoryItem* inv_item = (LLViewerInventoryItem*)cargo_data;
if (gInventory.getItem(inv_item->getUUID()))
if (LLViewerInventoryItem* inv_item = static_cast<LLViewerInventoryItem*>(cargo_data))
{
*accept = ACCEPT_YES_COPY_SINGLE;
if (drop) mDownCallback(inv_item);
if (drop)
{
mText->setText(currently_set_to(inv_item));
if (mControl) mControl->setValue(inv_item->getUUID().asString());
}
}
else *accept = ACCEPT_NO;
else
{
*accept = ACCEPT_NO;
}
return true;
}
return true;
return getParent() ? LLToolDragAndDrop::handleGiveDragAndDrop(mEntityID, LLUUID::null, drop, cargo_type, cargo_data, accept) : false;
}

View File

@@ -42,23 +42,44 @@
#include "stdtypes.h"
#include "llview.h"
class LLViewerInventoryItem;
class LLDropTarget : public LLView
{
public:
LLDropTarget(const std::string& name, const LLRect& rect, void (*callback)(LLViewerInventoryItem*));
LLDropTarget(const std::string& name, const LLRect& rect, const LLUUID& agent_id);
struct Params : public LLInitParam::Block<Params, LLView::Params>
{
Optional<std::string> control_name; // Control to change on item drop (Per Account only)
Optional<std::string> label; // Label for the LLTextBox, used when label doesn't dynamically change on drop
Optional<bool> fill_parent; // Whether or not to fill the direct parent, to have a larger drop target. If true, the next sibling must explicitly define its rect without deltas.
Params()
: control_name("control_name", "")
, label("label", "")
, fill_parent("fill_parent", false)
{
changeDefault(mouse_opaque, false);
changeDefault(follows.flags, FOLLOWS_ALL);
}
};
LLDropTarget(const Params& p = Params());
~LLDropTarget();
void doDrop(EDragAndDropType cargo_type, void* cargo_data);
virtual void doDrop(EDragAndDropType cargo_type, void* cargo_data);
//
// LLView functionality
virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EDragAndDropType cargo_type, void* cargo_data, EAcceptance* accept, std::string& tooltip_msg);
void setAgentID(const LLUUID &agent_id){ mAgentID = agent_id;}
static LLView* fromXML(LLXMLNodePtr node, LLView* parent, class LLUICtrlFactory* factory);
virtual void initFromXML(LLXMLNodePtr node, LLView* parent);
virtual void setControlName(const std::string& control, LLView* context);
void fillParent(const LLView* parent);
void setEntityID(const LLUUID& id) { mEntityID = id;}
protected:
LLUUID mAgentID;
void (*mDownCallback)(LLViewerInventoryItem*);
LLUUID mEntityID;
private:
LLControlVariable* mControl;
class LLTextBox* mText;
};
#endif // LLDROPTARGET_H

View File

@@ -1051,8 +1051,8 @@ void LLSpeakerMgr::update(BOOL resort_ok)
{
LLUUID speaker_id = speaker_it->first;
LLSpeaker* speakerp = speaker_it->second;
speaker_map_t::iterator cur_speaker_it = speaker_it++;
speaker_it++;
if (voice_channel_active && gVoiceClient->getVoiceEnabled(speaker_id))
{

View File

@@ -40,7 +40,12 @@
// viewer project includes
#include "llagentdata.h"
#include "llcommandhandler.h"
#include "llimview.h"
#include "llfloaterfriends.h"
#include "llfloatermute.h"
#include "llmenucommands.h"
#include "llpanelavatar.h"
#include "llviewermessage.h"
#include "lluictrlfactory.h"
#include "llweb.h"
@@ -60,24 +65,92 @@ const LLRect FAI_RECT(0, 530, 420, 0);
class LLAgentHandler : public LLCommandHandler
{
public:
void verbCallback(const std::string& verb, LLUUID agent_id, const LLAvatarName& avatar_name)
{
if (verb == "im")
{
gIMMgr->setFloaterOpen(TRUE);
gIMMgr->addSession( avatar_name.getCompleteName(), IM_NOTHING_SPECIAL, agent_id);
return;
}
if (verb == "requestfriend")
{
LLPanelFriends::requestFriendshipDialog( agent_id, avatar_name.getCompleteName() );
return;
}
if (verb == "mute")
{
LLFloaterMute::getInstance()->open();
LLMute mute(agent_id, avatar_name.getCompleteName(), LLMute::AGENT);
LLMuteList::getInstance()->add(mute);
return;
}
if (verb == "unmute")
{
LLMute mute(agent_id, avatar_name.getCompleteName(), LLMute::AGENT);
LLMuteList::getInstance()->remove(mute);
return;
}
}
// requires trusted browser to trigger
LLAgentHandler() : LLCommandHandler("agent", true) { }
bool handle(const LLSD& params, const LLSD& query_map,
LLMediaCtrl* web)
{
if (params.size() < 2) return false;
if (params.size() < 2)
{
return false;
}
LLUUID agent_id;
if (!agent_id.set(params[0], FALSE))
{
return false;
}
if (params[1].asString() == "about")
const std::string verb = params[1].asString();
if (verb == "about")
{
LLFloaterAvatarInfo::show(agent_id);
return true;
}
if (verb == "pay")
{
handle_pay_by_id(agent_id);
return true;
}
if (verb == "offerteleport")
{
handle_lure(agent_id);
return true;
}
if ((verb == "im") || (verb == "requestfriend") || (verb == "unmute"))
{
LLAvatarNameCache::get(agent_id, boost::bind(&LLAgentHandler::verbCallback, this, verb, _1, _2));
return true;
}
if (verb == "mute")
{
if (LLMuteList::getInstance()->isMuted(agent_id))
{
LLFloaterMute::getInstance()->open();
LLFloaterMute::getInstance()->selectMute(agent_id);
}
else
{
LLAvatarNameCache::get(agent_id, boost::bind(&LLAgentHandler::verbCallback, this, verb, _1, _2));
}
return true;
}
return false;
}
};

View File

@@ -315,7 +315,7 @@ const LLAvatarListEntry::ACTIVITY_TYPE LLAvatarListEntry::getActivity()
LLFloaterAvatarList::LLFloaterAvatarList() : LLFloater(std::string("radar")),
mTracking(false),
mUpdate(true),
mUpdate("RadarUpdateEnabled"),
mDirtyAvatarSorting(false),
mUpdateRate(gSavedSettings.getU32("RadarUpdateRate") * 3 + 3),
mAvatarList(NULL)
@@ -415,12 +415,12 @@ BOOL LLFloaterAvatarList::postBuild()
getChild<LLRadioGroup>("update_rate")->setSelectedIndex(gSavedSettings.getU32("RadarUpdateRate"));
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));
gSavedSettings.getControl("RadarColumnMarkHidden")->getSignal()->connect(boost::bind(&LLFloaterAvatarList::assessColumns, this));
gSavedSettings.getControl("RadarColumnPositionHidden")->getSignal()->connect(boost::bind(&LLFloaterAvatarList::assessColumns, this));
gSavedSettings.getControl("RadarColumnAltitudeHidden")->getSignal()->connect(boost::bind(&LLFloaterAvatarList::assessColumns, this));
gSavedSettings.getControl("RadarColumnActivityHidden")->getSignal()->connect(boost::bind(&LLFloaterAvatarList::assessColumns, this));
gSavedSettings.getControl("RadarColumnAgeHidden")->getSignal()->connect(boost::bind(&LLFloaterAvatarList::assessColumns, this));
gSavedSettings.getControl("RadarColumnTimeHidden")->getSignal()->connect(boost::bind(&LLFloaterAvatarList::assessColumns, this));
// Get a pointer to the scroll list from the interface
mAvatarList = getChild<LLScrollListCtrl>("avatar_list");
@@ -438,7 +438,7 @@ BOOL LLFloaterAvatarList::postBuild()
if(gHippoGridManager->getConnectedGrid()->isSecondLife())
childSetVisible("hide_client", false);
else
getChild<LLCheckboxCtrl>("hide_client")->setCommitCallback(boost::bind(&LLFloaterAvatarList::assessColumns, this));
gSavedSettings.getControl("RadarColumnClientHidden")->getSignal()->connect(boost::bind(&LLFloaterAvatarList::assessColumns, this));
return TRUE;
}
@@ -529,17 +529,11 @@ void LLFloaterAvatarList::updateAvatarList()
//llinfos << "radar refresh: updating map" << llendl;
// Check whether updates are enabled
LLCheckboxCtrl* check = getChild<LLCheckboxCtrl>("update_enabled_cb");
if (check && !check->getValue())
if (!mUpdate)
{
mUpdate = FALSE;
refreshTracker();
return;
}
else
{
mUpdate = TRUE;
}
//moved to pipeline to prevent a crash
//gPipeline.forAllVisibleDrawables(updateParticleActivity);
@@ -1186,7 +1180,7 @@ void LLFloaterAvatarList::onClickTrack()
if (mTracking && mTrackedAvatar == agent_id)
{
LLTracker::stopTracking(NULL);
LLTracker::stopTracking(false);
mTracking = FALSE;
}
else
@@ -1203,7 +1197,7 @@ void LLFloaterAvatarList::refreshTracker()
{
if (!mTracking) return;
if (LLTracker::isTracking(NULL))
if (LLTracker::isTracking())
{
if(LLAvatarListEntry* entry = getAvatarEntry(mTrackedAvatar))
{
@@ -1215,7 +1209,7 @@ void LLFloaterAvatarList::refreshTracker()
}
else
{ // Tracker stopped.
LLTracker::stopTracking(NULL);
LLTracker::stopTracking(false);
mTracking = FALSE;
// llinfos << "Tracking stopped." << llendl;
}
@@ -1248,19 +1242,18 @@ LLAvatarListEntry * LLFloaterAvatarList::getAvatarEntry(LLUUID avatar)
BOOL LLFloaterAvatarList::handleKeyHere(KEY key, MASK mask)
{
LLFloaterAvatarList* self = getInstance();
LLScrollListItem* item = self->mAvatarList->getFirstSelected();
LLScrollListItem* item = mAvatarList->getFirstSelected();
if(item)
{
LLUUID agent_id = item->getUUID();
if (( KEY_RETURN == key ) && (MASK_NONE == mask))
{
self->setFocusAvatar(agent_id);
setFocusAvatar(agent_id);
return TRUE;
}
else if (( KEY_RETURN == key ) && (MASK_CONTROL == mask))
{
LLAvatarListEntry* entry = self->getAvatarEntry(agent_id);
const LLAvatarListEntry* entry = getAvatarEntry(agent_id);
if (entry)
{
// llinfos << "Trying to teleport to " << entry->getName() << " at " << entry->getPosition() << llendl;
@@ -1272,7 +1265,7 @@ BOOL LLFloaterAvatarList::handleKeyHere(KEY key, MASK mask)
if (( KEY_RETURN == key ) && (MASK_SHIFT == mask))
{
uuid_vec_t ids = self->mAvatarList->getSelectedIDs();
uuid_vec_t ids = mAvatarList->getSelectedIDs();
if (ids.size() > 0)
{
if (ids.size() == 1)
@@ -1385,12 +1378,7 @@ void LLFloaterAvatarList::onClickGetKey()
if (NULL == item) return;
LLUUID agent_id = item->getUUID();
char buffer[UUID_STR_LENGTH]; /*Flawfinder: ignore*/
agent_id.toString(buffer);
gViewerWindow->mWindow->copyTextToClipboard(utf8str_to_wstring(buffer));
gViewerWindow->mWindow->copyTextToClipboard(utf8str_to_wstring(item->getUUID().asString()));
}
void LLFloaterAvatarList::sendKeys()
@@ -1419,11 +1407,11 @@ void LLFloaterAvatarList::sendKeys()
std::ostringstream ids;
int num_ids = 0;
for (int i = 0; i < regionp->mMapAvatarIDs.count(); i++)
for (int i = 0; i < regionp->mMapAvatarIDs.count(); ++i)
{
const LLUUID &id = regionp->mMapAvatarIDs.get(i);
ids << "," << id.asString();
ids << "," << id;
++num_ids;

View File

@@ -354,7 +354,7 @@ private:
/**
* @brief TRUE when Updating
*/
bool mUpdate;
const LLCachedControl<bool> mUpdate;
/**
* @brief Update rate (if min frames per update)

View File

@@ -91,18 +91,12 @@ private:
void doCheckUncheckAll(BOOL check);
private:
// UI
LLScrollListCtrl* mMessages;
LLButton* mCloseBtn;
// Object Queue
LLDynamicArray<LLUUID> mObjectIDs;
LLUUID mCurrentObjectID;
BOOL mDone;
LLUUID mID;
const char* mStartString;
};
#endif

View File

@@ -38,54 +38,32 @@
#include "llviewerprecompiledheaders.h"
#include "llfloaterchat.h"
#include "llfloateractivespeakers.h"
#include "llfloaterscriptdebug.h"
#include "llchat.h"
#include "llfontgl.h"
#include "llrect.h"
#include "llerror.h"
#include "llstring.h"
#include "message.h"
// project include
#include "llagent.h"
#include "llbutton.h"
#include "llcheckboxctrl.h"
#include "llcombobox.h"
#include "llconsole.h"
#include "llfloaterchatterbox.h"
#include "llfloatermute.h"
#include "llkeyboard.h"
//#include "lllineeditor.h"
#include "llmutelist.h"
//#include "llresizehandle.h"
#include "llchatbar.h"
#include "llstatusbar.h"
#include "llviewertexteditor.h"
#include "llviewergesture.h" // for triggering gestures
#include "llviewermessage.h"
#include "llviewerwindow.h"
#include "llviewercontrol.h"
#include "lluictrlfactory.h"
#include "llchatbar.h"
#include "lllogchat.h"
#include "lltexteditor.h"
#include "lltextparser.h"
#include "llfloaterhtml.h"
#include "llweb.h"
#include "llstylemap.h"
#include "ascentkeyword.h"
// linden library includes
#include "llaudioengine.h"
#include "llchat.h"
#include "llfontgl.h"
#include "llrect.h"
#include "llerror.h"
#include "llstring.h"
#include "llcheckboxctrl.h"
#include "llcombobox.h"
#include "lltextparser.h"
#include "lltrans.h"
#include "llwindow.h"
#include "message.h"
// project include
#include "ascentkeyword.h"
#include "llagent.h"
#include "llchatbar.h"
#include "llconsole.h"
#include "llfloateractivespeakers.h"
#include "llfloaterchatterbox.h"
#include "llfloatermute.h"
#include "llfloaterscriptdebug.h"
#include "lllogchat.h"
#include "llmutelist.h"
#include "llstylemap.h"
#include "lluictrlfactory.h"
#include "llviewermessage.h"
#include "llviewertexteditor.h"
#include "llviewerwindow.h"
#include "llweb.h"
// [RLVa:KB]
#include "rlvhandler.h"
@@ -94,7 +72,8 @@
//
// Global statics
//
LLColor4 get_text_color(const LLChat& chat);
LLColor4 agent_chat_color(const LLUUID& id, const std::string&, bool local_chat = true);
LLColor4 get_text_color(const LLChat& chat, bool from_im = false);
//
// Member Functions
@@ -187,13 +166,12 @@ void LLFloaterChat::handleVisibilityChange(BOOL new_visibility)
// virtual
void LLFloaterChat::onFocusReceived()
{
LLView* chat_editor = getChildView("Chat Editor");
if (getVisible() && childIsVisible("Chat Editor"))
LLUICtrl* chat_editor = getChild<LLUICtrl>("Chat Editor");
if (getVisible() && chat_editor->getVisible())
{
gFocusMgr.setKeyboardFocus(chat_editor);
LLUICtrl * ctrl = static_cast<LLUICtrl*>(chat_editor);
ctrl->setFocus(TRUE);
chat_editor->setFocus(TRUE);
}
LLFloater::onFocusReceived();
@@ -227,9 +205,9 @@ void add_timestamped_line(LLViewerTextEditor* edit, LLChat chat, const LLColor4&
// If the msg is from an agent (not yourself though),
// extract out the sender name and replace it with the hotlinked name.
if (chat.mSourceType == CHAT_SOURCE_AGENT &&
// chat.mFromID != LLUUID::null)
// chat.mFromID.notNull())
// [RLVa:KB] - Version: 1.23.4 | Checked: 2009-07-08 (RLVa-1.0.0e)
chat.mFromID != LLUUID::null &&
chat.mFromID.notNull() &&
(!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) )
// [/RLVa:KB]
{
@@ -238,20 +216,27 @@ void add_timestamped_line(LLViewerTextEditor* edit, LLChat chat, const LLColor4&
if(chat.mSourceType == CHAT_SOURCE_OBJECT && !chat.mFromName.length())
{
chat.mFromName = "(no name)";
chat.mFromName = LLTrans::getString("Unnamed");
line = chat.mFromName + line;
}
static const LLCachedControl<bool> italicize("LiruItalicizeActions");
bool is_irc = italicize && chat.mChatStyle == CHAT_STYLE_IRC;
// If the chat line has an associated url, link it up to the name.
if (!chat.mURL.empty()
&& (line.length() > chat.mFromName.length() && line.find(chat.mFromName,0) == 0))
{
std::string start_line = line.substr(0, chat.mFromName.length() + 1);
line = line.substr(chat.mFromName.length() + 1);
const LLStyleSP &sourceStyle = LLStyleMap::instance().lookup(chat.mFromID,chat.mURL);
LLStyleSP sourceStyle = LLStyleMap::instance().lookup(chat.mFromID,chat.mURL);
sourceStyle->mItalic = is_irc;
edit->appendStyledText(start_line, false, prepend_newline, sourceStyle);
prepend_newline = false;
}
edit->appendColoredText(line, false, prepend_newline, color);
LLStyleSP style(new LLStyle);
style->setColor(color);
style->mItalic = is_irc;
edit->appendStyledText(line, false, prepend_newline, style);
}
void log_chat_text(const LLChat& chat)
@@ -439,7 +424,7 @@ void LLFloaterChat::addChat(const LLChat& chat,
BOOL from_instant_message,
BOOL local_agent)
{
LLColor4 text_color = get_text_color(chat);
LLColor4 text_color = get_text_color(chat, from_instant_message);
BOOL invisible_script_debug_chat =
chat.mChatType == CHAT_TYPE_DEBUG_MSG
@@ -474,14 +459,6 @@ void LLFloaterChat::addChat(const LLChat& chat,
&& gConsole
&& !local_agent)
{
if (chat.mSourceType == CHAT_SOURCE_SYSTEM)
{
text_color = gSavedSettings.getColor("SystemChatColor");
}
else if(from_instant_message)
{
text_color = gSavedSettings.getColor("IMChatColor");
}
// We display anything if it's not an IM. If it's an IM, check pref...
if ( !from_instant_message || gSavedSettings.getBOOL("IMInChatConsole") )
{
@@ -547,7 +524,7 @@ void LLFloaterChat::triggerAlerts(const std::string& text)
}
}
LLColor4 get_text_color(const LLChat& chat)
LLColor4 get_text_color(const LLChat& chat, bool from_im)
{
LLColor4 text_color;
@@ -567,48 +544,7 @@ LLColor4 get_text_color(const LLChat& chat)
text_color = gSavedSettings.getColor4("SystemChatColor");
break;
case CHAT_SOURCE_AGENT:
if (chat.mFromID.isNull())
{
text_color = gSavedSettings.getColor4("SystemChatColor");
}
else
{
if(gAgent.getID() == chat.mFromID)
{
text_color = gSavedSettings.getColor4("UserChatColor");
}
else
{
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");
}
}
}
text_color = agent_chat_color(chat.mFromID, chat.mFromName, !from_im);
break;
case CHAT_SOURCE_OBJECT:
if (chat.mChatType == CHAT_TYPE_DEBUG_MSG)
@@ -751,13 +687,12 @@ void LLFloaterChat::hide(LLFloater* instance, const LLSD& key)
BOOL LLFloaterChat::focusFirstItem(BOOL prefer_text_fields, BOOL focus_flash )
{
LLView* chat_editor = getChildView("Chat Editor");
if (getVisible() && childIsVisible("Chat Editor"))
LLUICtrl* chat_editor = getChild<LLUICtrl>("Chat Editor");
if (getVisible() && chat_editor->getVisible())
{
gFocusMgr.setKeyboardFocus(chat_editor);
LLUICtrl * ctrl = static_cast<LLUICtrl*>(chat_editor);
ctrl->setFocus(TRUE);
chat_editor->setFocus(TRUE);
return TRUE;
}

View File

@@ -189,6 +189,7 @@ LLFloaterCustomize::~LLFloaterCustomize()
BOOL LLFloaterCustomize::postBuild()
{
getChild<LLUICtrl>("Make Outfit")->setCommitCallback(boost::bind(&LLFloaterCustomize::onBtnMakeOutfit, this));
getChild<LLUICtrl>("Save Outfit")->setCommitCallback(boost::bind(&LLAppearanceMgr::updateBaseOutfit, LLAppearanceMgr::getInstance()));
getChild<LLUICtrl>("Ok")->setCommitCallback(boost::bind(&LLFloaterCustomize::onBtnOk, this));
getChild<LLUICtrl>("Cancel")->setCommitCallback(boost::bind(&LLFloater::onClickClose, this));

View File

@@ -97,7 +97,7 @@ public:
return false;
}
if (tokens[1].asString() == "about")
if ((tokens[1].asString() == "about") || (tokens[1].asString() == "inspect"))
{
LLFloaterGroupInfo::showFromUUID(group_id);
return true;

View File

@@ -300,7 +300,7 @@ void LLFloaterLandHoldings::buttonCore(S32 which)
break;
case 1:
gFloaterWorldMap->trackLocation(pos_global);
LLFloaterWorldMap::show(NULL, TRUE);
LLFloaterWorldMap::show(true);
break;
default:
break;

View File

@@ -1,250 +0,0 @@
/**
* @file llfloaternewim.cpp
* @brief Panel allowing the user to create a new IM session.
*
* $LicenseInfo:firstyear=2001&license=viewergpl$
*
* Copyright (c) 2001-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 "llfloaternewim.h"
#include "lluictrlfactory.h"
#include "llnamelistctrl.h"
#include "llresmgr.h"
#include "lltabcontainer.h"
#include "llimview.h"
S32 COL_1_WIDTH = 200;
static std::string sOnlineDescriptor = "*";
LLFloaterNewIM::LLFloaterNewIM()
{
LLUICtrlFactory::getInstance()->buildFloater(this, "floater_new_im.xml");
}
BOOL LLFloaterNewIM::postBuild()
{
requires<LLButton>("start_btn");
requires<LLButton>("close_btn");
requires<LLNameListCtrl>("user_list");
if (checkRequirements())
{
childSetAction("start_btn", &LLFloaterNewIM::onStart, this);
childSetAction("close_btn", &LLFloaterNewIM::onClickClose, this);
mSelectionList = getChild<LLNameListCtrl>("user_list");
if (mSelectionList)
{
mSelectionList->setDoubleClickCallback(boost::bind(&LLFloaterNewIM::onStart,this));
}
else
{
llwarns << "LLUICtrlFactory::getNameListByName() returned NULL for 'user_list'" << llendl;
}
sOnlineDescriptor = getString("online_descriptor");
setDefaultBtn("start_btn");
return TRUE;
}
return FALSE;
}
LLFloaterNewIM::~LLFloaterNewIM()
{
clearAllTargets();
}
void LLFloaterNewIM::clearAllTargets()
{
mSelectionList->deleteAllItems();
}
void LLFloaterNewIM::addSpecial(const LLUUID& uuid, const std::string& name,
void* data, BOOL bold, BOOL online)
{
LLSD row;
row["id"] = uuid;
row["name"] = name;
row["target"] = LLNameListCtrl::SPECIAL;
row["columns"][0]["value"] = name;
row["columns"][0]["width"] = COL_1_WIDTH;
row["columns"][0]["font"] = "SANSSERIF";
row["columns"][0]["font-style"] = bold ? "BOLD" : "NORMAL";
row["columns"][1]["value"] = online ? sOnlineDescriptor : "";
row["columns"][1]["font"] = "SANSSERIF";
row["columns"][1]["font-style"] = "BOLD";
LLScrollListItem* itemp = mSelectionList->addElement(row);
itemp->setUserdata(data);
if (mSelectionList->getFirstSelectedIndex() == -1)
{
mSelectionList->selectFirstItem();
}
}
void LLFloaterNewIM::addGroup(const LLUUID& uuid, void* data, BOOL bold, BOOL online)
{
LLSD row;
row["id"] = uuid;
row["target"] = LLNameListCtrl::GROUP;
row["columns"][0]["value"] = ""; // name will be looked up
row["columns"][0]["width"] = COL_1_WIDTH;
row["columns"][0]["font"] = "SANSSERIF";
row["columns"][0]["font-style"] = bold ? "BOLD" : "NORMAL";
row["columns"][1]["value"] = online ? sOnlineDescriptor : "";
row["columns"][1]["font"] = "SANSSERIF";
row["columns"][1]["font-style"] = "BOLD";
LLScrollListItem* itemp = mSelectionList->addElement(row);
itemp->setUserdata(data);
if (mSelectionList->getFirstSelectedIndex() == -1)
{
mSelectionList->selectFirstItem();
}
}
void LLFloaterNewIM::addAgent(const LLUUID& uuid, void* data, BOOL online)
{
LLSD row;
row["id"] = uuid;
row["target"] = LLNameListCtrl::INDIVIDUAL;
row["columns"][0]["value"] = "";
row["columns"][0]["width"] = COL_1_WIDTH;
row["columns"][0]["font"] = "SANSSERIF";
row["columns"][0]["font-style"] = online ? "BOLD" : "NORMAL";
row["columns"][1]["value"] = online ? sOnlineDescriptor : "";
row["columns"][1]["font"] = "SANSSERIF";
row["columns"][1]["font-style"] = "BOLD";
LLScrollListItem* itemp = mSelectionList->addElement(row);
itemp->setUserdata(data);
if (mSelectionList->getFirstSelectedIndex() == -1)
{
mSelectionList->selectFirstItem();
}
}
BOOL LLFloaterNewIM::isUUIDAvailable(const LLUUID& uuid)
{
std::vector<LLScrollListItem*> data_list = mSelectionList->getAllData();
std::vector<LLScrollListItem*>::iterator data_itor;
for (data_itor = data_list.begin(); data_itor != data_list.end(); ++data_itor)
{
LLScrollListItem* item = *data_itor;
if(item->getUUID() == uuid)
{
return TRUE;
}
}
return FALSE;
}
void LLFloaterNewIM::onStart(void* userdata)
{
LLFloaterNewIM* self = (LLFloaterNewIM*) userdata;
LLScrollListItem* item = self->mSelectionList->getFirstSelected();
if(item)
{
const LLScrollListCell* cell = item->getColumn(0);
std::string name(cell->getValue());
// *NOTE: Do a live detrmination of what type of session it
// should be. If we restrict the new im panel to online users,
// then we can remove some of this code.
EInstantMessage type;
EInstantMessage* t = (EInstantMessage*)item->getUserdata();
if(t) type = (*t);
else type = LLIMMgr::defaultIMTypeForAgent(item->getUUID());
gIMMgr->addSession(name, type, item->getUUID());
make_ui_sound("UISndStartIM");
}
else
{
make_ui_sound("UISndInvalidOp");
}
}
// static
void LLFloaterNewIM::onClickClose(void *userdata)
{
gIMMgr->setFloaterOpen(FALSE);
}
BOOL LLFloaterNewIM::handleKeyHere(KEY key, MASK mask)
{
BOOL handled = LLFloater::handleKeyHere(key, mask);
if (KEY_ESCAPE == key && mask == MASK_NONE)
{
handled = TRUE;
// Close talk panel on escape
gIMMgr->toggle(NULL);
}
// Might need to call base class here if not handled
return handled;
}
BOOL LLFloaterNewIM::canClose()
{
if (getHost())
{
LLMultiFloater* hostp = (LLMultiFloater*)getHost();
// if we are the only tab in the im view, go ahead and close
return hostp->getFloaterCount() == 1;
}
return TRUE;
}
void LLFloaterNewIM::close(bool app_quitting)
{
if (getHost())
{
LLMultiFloater* hostp = (LLMultiFloater*)getHost();
hostp->close();
}
else
{
LLFloater::close(app_quitting);
}
}
S32 LLFloaterNewIM::getScrollPos()
{
return mSelectionList->getScrollPos();
}
void LLFloaterNewIM::setScrollPos( S32 pos )
{
mSelectionList->setScrollPos( pos );
}

View File

@@ -1,77 +0,0 @@
/**
* @file llfloaternewim.h
* @brief Panel allowing the user to create a new IM session.
*
* $LicenseInfo:firstyear=2001&license=viewergpl$
*
* Copyright (c) 2001-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 LL_FLOATER_NEW_IM_H
#define LL_FLOATER_NEW_IM_H
#include "llfloater.h"
class LLNameListCtrl;
class LLFloaterNewIM : public LLFloater
{
public:
LLFloaterNewIM();
/*virtual*/ ~LLFloaterNewIM();
/*virtual*/ BOOL postBuild();
/*virtual*/ BOOL handleKeyHere(KEY key, MASK mask);
virtual BOOL canClose();
virtual void close(bool app_quitting);
static void onStart(void* userdata);
static void onClickClose(void* userdata);
void clearAllTargets();
// add a scroll list item which has everything specified - useful
// for special IM targets like everyone.
void addSpecial(const LLUUID& uuid, const std::string& name,
void* data, BOOL bold, BOOL online);
// add a scroll list item for an agent - the name will be autoupdated
// as it appears
void addAgent(const LLUUID& uuid, void* data, BOOL online);
void addGroup(const LLUUID& uuid, void* data, BOOL bold, BOOL online);
void addDefaultTargets();
BOOL isUUIDAvailable(const LLUUID& uuid);
S32 getScrollPos();
void setScrollPos( S32 pos );
protected:
LLNameListCtrl* mSelectionList;
};
#endif // LL_NEWIMPANEL_H

View File

@@ -122,12 +122,12 @@ void LLPermissionsView::addPermissionsData(const std::string& object_name, const
y -= LINE + VPAD;
LLRect btn_rect(HPAD, y + BTN_HEIGHT, 120, y);
LLButton* button = new LLButton(std::string("Revoke permissions"), btn_rect, LLStringUtil::null, std::bind(&LLPermissionsView::revokePermissions, object_id, permissions_flags));
LLButton* button = new LLButton(std::string("Revoke permissions"), btn_rect, LLStringUtil::null, boost::bind(&LLPermissionsView::revokePermissions, object_id, permissions_flags));
button->setFollows(FOLLOWS_LEFT | FOLLOWS_BOTTOM);
addChild(button);
/*btn_rect.set(HPAD + 120 + HPAD, y + BTN_HEIGHT, HPAD + 120 + HPAD + 120, y);
button = new LLButton(std::string("Find in world"), btn_rect, LLStringUtil::null, std::bind(&LLPermissionsView::findObject, object_id, permissions_flags));
button = new LLButton(std::string("Find in world"), btn_rect, LLStringUtil::null, boost::bind(&LLPermissionsView::findObject, object_id, permissions_flags));
button->setFollows(FOLLOWS_LEFT | FOLLOWS_BOTTOM);
addChild(button);*/
}

View File

@@ -54,7 +54,6 @@
#include "llpanelnetwork.h"
#include "llpanelaudioprefs.h"
#include "llpaneldisplay.h"
#include "llpaneldebug.h"
#include "llpanelgeneral.h"
#include "llpanelinput.h"
#include "llpanellogin.h"

View File

@@ -46,7 +46,6 @@ class LLPanelGeneral;
class LLPanelInput;
class LLPanelDisplay;
class LLPanelAudioPrefs;
class LLPanelDebug;
class LLPanelNetwork;
class LLPanelWeb;
class LLMessageSystem;
@@ -90,7 +89,6 @@ private:
LLPanelNetwork *mNetworkPanel;
LLPanelDisplay *mDisplayPanel;
LLPanelAudioPrefs *mAudioPanel;
// LLPanelDebug *mDebugPanel;
LLPrefsChat *mPrefsChat;
LLPrefsVoice *mPrefsVoice;
LLPrefsIM *mPrefsIM;

View File

@@ -52,7 +52,7 @@ class LLTextBox;
class LLPropertiesObserver;
class LLFloaterProperties : public LLFloater, LLInstanceTracker<LLFloaterProperties, LLUUID>
class LLFloaterProperties : public LLFloater, public LLInstanceTracker<LLFloaterProperties, LLUUID>
{
public:
static LLFloaterProperties* find(const LLUUID& item_id,

View File

@@ -1,12 +1,11 @@
/**
* @file llfloaterreporter.cpp
* @brief Bug and abuse reports.
* @brief Abuse reports.
*
* $LicenseInfo:firstyear=2002&license=viewergpl$
*
* Second Life Viewer Source Code
* 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
@@ -39,30 +38,23 @@
// linden library includes
#include "llassetstorage.h"
#include "llavatarnamecache.h"
#include "llcachename.h"
#include "llfontgl.h"
#include "llgl.h" // for renderer
#include "llimagej2c.h"
#include "llinventory.h"
#include "llnotificationsutil.h"
#include "llstring.h"
#include "llsys.h"
#include "sgversion.h"
#include "message.h"
#include "v3math.h"
// viewer project includes
#include "llagent.h"
#include "llbutton.h"
#include "llcheckboxctrl.h"
#include "llinventorypanel.h"
#include "lllineeditor.h"
#include "lltexturectrl.h"
#include "llscrolllistctrl.h"
#include "llimview.h"
#include "lltextbox.h"
#include "lldispatcher.h"
#include "llviewertexteditor.h"
#include "llviewerobject.h"
#include "llviewerregion.h"
#include "llcombobox.h"
@@ -80,7 +72,7 @@
#include "llfloateravatarpicker.h"
#include "lldir.h"
#include "llselectmgr.h"
#include "llviewerbuild.h"
#include "sgversion.h"
#include "lluictrlfactory.h"
#include "llviewernetwork.h"
@@ -88,10 +80,6 @@
#include "lltrans.h"
// [RLVa:KB]
#include "rlvhandler.h"
// [/RLVa:KB]
const U32 INCLUDE_SCREENSHOT = 0x01 << 0;
class AIHTTPTimeoutPolicy;
@@ -101,125 +89,23 @@ extern AIHTTPTimeoutPolicy userReportResponder_timeout;
// Globals
//-----------------------------------------------------------------------------
// this map keeps track of current reporter instances
// there can only be one instance of each reporter type
LLMap< EReportType, LLFloaterReporter* > gReporterInstances;
// keeps track of where email is going to - global to avoid a pile
// of static/non-static access outside my control
namespace {
static BOOL gDialogVisible = FALSE;
}
//-----------------------------------------------------------------------------
// Member functions
//-----------------------------------------------------------------------------
LLFloaterReporter::LLFloaterReporter(
const std::string& name,
const LLRect& rect,
const std::string& title,
EReportType report_type)
:
LLFloater(name, rect, title),
mReportType(report_type),
LLFloaterReporter::LLFloaterReporter()
: LLFloater(),
mReportType(COMPLAINT_REPORT),
mObjectID(),
mScreenID(),
mAbuserID(),
mOwnerName(),
mDeselectOnClose( FALSE ),
mPicking( FALSE),
mPosition(),
mCopyrightWarningSeen( FALSE ),
mResourceDatap(new LLResourceData())
{
if (report_type == BUG_REPORT)
{
LLUICtrlFactory::getInstance()->buildFloater(this, "floater_report_bug.xml");
}
else
{
LLUICtrlFactory::getInstance()->buildFloater(this, "floater_report_abuse.xml");
}
childSetText("abuse_location_edit", gAgent.getSLURL() );
// [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e) | Modified: RLVa-1.0.0a
if (rlv_handler_t::isEnabled())
{
// Can't filter these since they get sent as part of the report so just hide them instead
if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC))
{
childSetVisible("abuse_location_edit", false);
childSetVisible("pos_field", false);
}
if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES))
{
childSetVisible("owner_name", false);
childSetVisible("abuser_name_edit", false);
}
}
// [/RLVa:KB]
LLButton* pick_btn = getChild<LLButton>("pick_btn");
if (pick_btn)
{
// XUI: Why aren't these in viewerart.ini?
pick_btn->setImages( std::string("UIImgFaceUUID"),
std::string("UIImgFaceSelectedUUID") );
childSetAction("pick_btn", onClickObjPicker, this);
}
if (report_type != BUG_REPORT)
{
// abuser name is selected from a list
LLLineEditor* le = getChild<LLLineEditor>("abuser_name_edit");
le->setEnabled( FALSE );
}
childSetAction("select_abuser", onClickSelectAbuser, this);
childSetAction("send_btn", onClickSend, this);
childSetAction("cancel_btn", onClickCancel, this);
enableControls(TRUE);
// convert the position to a string
LLVector3d pos = gAgent.getPositionGlobal();
LLViewerRegion *regionp = gAgent.getRegion();
if (regionp)
{
pos -= regionp->getOriginGlobal();
}
setPosBox(pos);
gReporterInstances.addData(report_type, this);
// Take a screenshot, but don't draw this floater.
setVisible(FALSE);
takeScreenshot();
setVisible(TRUE);
// Default text to be blank
childSetText("object_name", LLStringUtil::null);
childSetText("owner_name", LLStringUtil::null);
childSetFocus("summary_edit");
mDefaultSummary = childGetText("details_edit");
gDialogVisible = TRUE;
// only request details for abuse reports (not BUG reports)
if (report_type != BUG_REPORT)
{
// send a message and ask for information about this region -
// result comes back in processRegionInfo(..)
LLMessageSystem* msg = gMessageSystem;
msg->newMessage("RequestRegionInfo");
msg->nextBlock("AgentData");
msg->addUUID("AgentID", gAgent.getID());
msg->addUUID("SessionID", gAgent.getSessionID());
gAgent.sendReliableMessage();
};
LLUICtrlFactory::getInstance()->buildFloater(this, "floater_report_abuse.xml");
}
// static
@@ -228,16 +114,77 @@ void LLFloaterReporter::processRegionInfo(LLMessageSystem* msg)
U32 region_flags;
msg->getU32("RegionInfo", "RegionFlags", region_flags);
if ( gDialogVisible )
if (LLFloaterReporter::instanceExists() && LLFloaterReporter::getInstance()->getVisible())
{
LLNotificationsUtil::add("HelpReportAbuseEmailLL");
};
}
}
// virtual
BOOL LLFloaterReporter::postBuild()
{
getChild<LLUICtrl>("abuse_location_edit")->setValue(gAgent.getSLURL());
enableControls(TRUE);
// convert the position to a string
LLVector3d pos = gAgent.getPositionGlobal();
LLViewerRegion *regionp = gAgent.getRegion();
if (regionp)
{
getChild<LLUICtrl>("sim_field")->setValue(regionp->getName());
pos -= regionp->getOriginGlobal();
}
setPosBox(pos);
// Take a screenshot, but don't draw this floater.
setVisible(FALSE);
takeScreenshot();
setVisible(TRUE);
// Default text to be blank
getChild<LLUICtrl>("object_name")->setValue(LLStringUtil::null);
getChild<LLUICtrl>("owner_name")->setValue(LLStringUtil::null);
mOwnerName = LLStringUtil::null;
getChild<LLUICtrl>("summary_edit")->setFocus(TRUE);
mDefaultSummary = getChild<LLUICtrl>("details_edit")->getValue().asString();
// send a message and ask for information about this region -
// result comes back in processRegionInfo(..)
LLMessageSystem* msg = gMessageSystem;
msg->newMessage("RequestRegionInfo");
msg->nextBlock("AgentData");
msg->addUUID("AgentID", gAgent.getID());
msg->addUUID("SessionID", gAgent.getSessionID());
gAgent.sendReliableMessage();
// abuser name is selected from a list
LLUICtrl* le = getChild<LLUICtrl>("abuser_name_edit");
le->setEnabled( false );
LLButton* pick_btn = getChild<LLButton>("pick_btn");
// XUI: Why aren't these in viewerart.ini?
pick_btn->setImages(std::string("UIImgFaceUUID"),
std::string("UIImgFaceSelectedUUID") );
childSetAction("pick_btn", onClickObjPicker, this);
childSetAction("select_abuser", boost::bind(&LLFloaterReporter::onClickSelectAbuser, this));
childSetAction("send_btn", onClickSend, this);
childSetAction("cancel_btn", onClickCancel, this);
// grab the user's name
std::string reporter;
gAgent.buildFullname(reporter);
getChild<LLUICtrl>("reporter_field")->setValue(reporter);
center();
return TRUE;
}
// virtual
LLFloaterReporter::~LLFloaterReporter()
{
gReporterInstances.removeData(mReportType);
// child views automatically deleted
mObjectID = LLUUID::null;
@@ -252,27 +199,26 @@ LLFloaterReporter::~LLFloaterReporter()
mMCDList.clear();
delete mResourceDatap;
gDialogVisible = FALSE;
}
// virtual
void LLFloaterReporter::draw()
{
childSetEnabled("screen_check", TRUE );
getChildView("screen_check")->setEnabled(TRUE );
LLFloater::draw();
}
void LLFloaterReporter::enableControls(BOOL enable)
{
childSetEnabled("category_combo", enable);
childSetEnabled("screen_check", enable);
childDisable("screenshot");
childSetEnabled("pick_btn", enable);
childSetEnabled("summary_edit", enable);
childSetEnabled("details_edit", enable);
childSetEnabled("send_btn", enable);
childSetEnabled("cancel_btn", enable);
getChildView("category_combo")->setEnabled(enable);
getChildView("screen_check")->setEnabled(enable);
getChildView("screenshot")->setEnabled(false);
getChildView("pick_btn")->setEnabled(enable);
getChildView("summary_edit")->setEnabled(enable);
getChildView("details_edit")->setEnabled(enable);
getChildView("send_btn")->setEnabled(enable);
getChildView("cancel_btn")->setEnabled(enable);
}
void LLFloaterReporter::getObjectInfo(const LLUUID& object_id)
@@ -287,28 +233,29 @@ void LLFloaterReporter::getObjectInfo(const LLUUID& object_id)
mObjectID = object_id;
if (LLUUID::null != mObjectID)
if (mObjectID.notNull())
{
// get object info for the user's benefit
LLViewerObject* objectp = NULL;
objectp = gObjectList.findObject( mObjectID );
if (objectp)
if (LLViewerObject* objectp = gObjectList.findObject(mObjectID))
{
if ( objectp->isAttachment() )
{
objectp = (LLViewerObject*)objectp->getRoot();
mObjectID = objectp->getID();
}
// correct the region and position information
LLViewerRegion *regionp = objectp->getRegion();
if (regionp)
{
childSetText("sim_field", regionp->getName());
getChild<LLUICtrl>("sim_field")->setValue(regionp->getName());
// [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0a)
/*
if ( (rlv_handler_t::isEnabled()) && (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC)) )
{
childSetText("sim_field", RlvStrings::getString(RLV_STRING_HIDDEN_REGION));
}
*/
// [/RLVa:KB]
LLVector3d global_pos;
global_pos.setVec(objectp->getPositionRegion());
@@ -317,38 +264,14 @@ void LLFloaterReporter::getObjectInfo(const LLUUID& object_id)
if (objectp->isAvatar())
{
// we have the information we need
std::string object_owner;
LLNameValue* firstname = objectp->getNVPair("FirstName");
LLNameValue* lastname = objectp->getNVPair("LastName");
if (firstname && lastname)
{
object_owner.append(firstname->getString());
object_owner.append(1, ' ');
object_owner.append(lastname->getString());
}
else
{
object_owner.append("Unknown");
}
childSetText("object_name", object_owner);
// [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e) | Added: RVLa-1.0.0e
if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES))
{
childSetVisible("object_name", false); // Hide the object name if the picked object represents an avataz
}
// [/RLVa:KB]
childSetText("owner_name", object_owner);
childSetText("abuser_name_edit", object_owner);
mAbuserID = object_id;
setFromAvatarID(mObjectID);
}
else
{
// we have to query the simulator for information
// about this object
LLMessageSystem* msg = gMessageSystem;
U32 request_flags = (mReportType == BUG_REPORT) ? BUG_REPORT_REQUEST : COMPLAINT_REPORT_REQUEST;
U32 request_flags = COMPLAINT_REPORT_REQUEST;
msg->newMessageFast(_PREHASH_RequestObjectPropertiesFamily);
msg->nextBlockFast(_PREHASH_AgentData);
msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
@@ -363,28 +286,50 @@ void LLFloaterReporter::getObjectInfo(const LLUUID& object_id)
}
}
// static
void LLFloaterReporter::onClickSelectAbuser(void *userdata)
void LLFloaterReporter::onClickSelectAbuser()
{
LLFloaterReporter *self = (LLFloaterReporter *)userdata;
gFloaterView->getParentFloater(self)->addDependentFloater(LLFloaterAvatarPicker::show(boost::bind(&LLFloaterReporter::callbackAvatarID, self, _1, _2), FALSE, TRUE ));
LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show(boost::bind(&LLFloaterReporter::callbackAvatarID, this, _1, _2), FALSE, TRUE );
if (picker)
{
gFloaterView->getParentFloater(this)->addDependentFloater(picker);
}
}
void LLFloaterReporter::callbackAvatarID(const uuid_vec_t& ids, const std::vector<LLAvatarName>& names)
{
if (ids.empty() || names.empty()) return;
// this should never be called in a bug report but here for safety.
if ( mReportType != BUG_REPORT )
{
childSetText("abuser_name_edit", names[0].getCompleteName() );
getChild<LLUICtrl>("abuser_name_edit")->setValue(names[0].getCompleteName());
mAbuserID = ids[0];
mAbuserID = ids[0];
refresh();
};
refresh();
}
void LLFloaterReporter::setFromAvatarID(const LLUUID& avatar_id)
{
mAbuserID = mObjectID = avatar_id;
std::string avatar_link;
if (LLAvatarNameCache::getPNSName(avatar_id, avatar_link))
{
getChild<LLUICtrl>("owner_name")->setValue(avatar_link);
getChild<LLUICtrl>("object_name")->setValue(avatar_link);
getChild<LLUICtrl>("abuser_name_edit")->setValue(avatar_link);
return;
}
LLAvatarNameCache::get(avatar_id, boost::bind(&LLFloaterReporter::onAvatarNameCache, this, _1, _2));
}
void LLFloaterReporter::onAvatarNameCache(const LLUUID& avatar_id, const LLAvatarName& av_name)
{
std::string avatar_link;
LLAvatarNameCache::getPNSName(av_name, avatar_link);
getChild<LLUICtrl>("owner_name")->setValue(avatar_link);
getChild<LLUICtrl>("object_name")->setValue(avatar_link);
getChild<LLUICtrl>("abuser_name_edit")->setValue(avatar_link);
}
@@ -400,39 +345,34 @@ void LLFloaterReporter::onClickSend(void *userdata)
if(self->validateReport())
{
// only show copyright alert for abuse reports
if ( self->mReportType != BUG_REPORT )
const int IP_CONTENT_REMOVAL = 66;
const int IP_PERMISSONS_EXPLOIT = 37;
LLComboBox* combo = self->getChild<LLComboBox>( "category_combo");
int category_value = combo->getSelectedValue().asInteger();
if ( ! self->mCopyrightWarningSeen )
{
const int IP_CONTENT_REMOVAL = 66;
const int IP_PERMISSONS_EXPLOIT = 37;
LLComboBox* combo = self->getChild<LLComboBox>( "category_combo");
int category_value = combo->getSelectedValue().asInteger();
if ( ! self->mCopyrightWarningSeen )
std::string details_lc = self->getChild<LLUICtrl>("details_edit")->getValue().asString();
LLStringUtil::toLower( details_lc );
std::string summary_lc = self->getChild<LLUICtrl>("summary_edit")->getValue().asString();
LLStringUtil::toLower( summary_lc );
if ( details_lc.find( "copyright" ) != std::string::npos ||
summary_lc.find( "copyright" ) != std::string::npos ||
category_value == IP_CONTENT_REMOVAL ||
category_value == IP_PERMISSONS_EXPLOIT)
{
std::string details_lc = self->childGetText("details_edit");
LLStringUtil::toLower( details_lc );
std::string summary_lc = self->childGetText("summary_edit");
LLStringUtil::toLower( summary_lc );
if ( details_lc.find( "copyright" ) != std::string::npos ||
summary_lc.find( "copyright" ) != std::string::npos ||
category_value == IP_CONTENT_REMOVAL ||
category_value == IP_PERMISSONS_EXPLOIT)
{
LLNotificationsUtil::add("HelpReportAbuseContainsCopyright");
self->mCopyrightWarningSeen = TRUE;
return;
}
}
else if (category_value == IP_CONTENT_REMOVAL)
{
// IP_CONTENT_REMOVAL *always* shows the dialog -
// ergo you can never send that abuse report type.
LLNotificationsUtil::add("HelpReportAbuseContainsCopyright");
self->mCopyrightWarningSeen = TRUE;
return;
}
}
else if (category_value == IP_CONTENT_REMOVAL)
{
// IP_CONTENT_REMOVAL *always* shows the dialog -
// ergo you can never send that abuse report type.
LLNotificationsUtil::add("HelpReportAbuseContainsCopyright");
return;
}
LLUploadDialog::modalUploadDialog(LLTrans::getString("uploading_abuse_report"));
// *TODO don't upload image if checkbox isn't checked
@@ -445,10 +385,10 @@ void LLFloaterReporter::onClickSend(void *userdata)
}
else
{
if(self->childGetValue("screen_check"))
if(self->getChild<LLUICtrl>("screen_check")->getValue())
{
self->childDisable("send_btn");
self->childDisable("cancel_btn");
self->getChildView("send_btn")->setEnabled(FALSE);
self->getChildView("cancel_btn")->setEnabled(FALSE);
// the callback from uploading the image calls sendReportViaLegacy()
self->uploadImage();
}
@@ -486,8 +426,9 @@ void LLFloaterReporter::onClickObjPicker(void *userdata)
LLToolObjPicker::getInstance()->setExitCallback(LLFloaterReporter::closePickTool, self);
LLToolMgr::getInstance()->setTransientTool(LLToolObjPicker::getInstance());
self->mPicking = TRUE;
self->childSetText("object_name", LLStringUtil::null);
self->childSetText("owner_name", LLStringUtil::null);
self->getChild<LLUICtrl>("object_name")->setValue(LLStringUtil::null);
self->getChild<LLUICtrl>("owner_name")->setValue(LLStringUtil::null);
self->mOwnerName = LLStringUtil::null;
LLButton* pick_btn = self->getChild<LLButton>("pick_btn");
if (pick_btn) pick_btn->setToggleState(TRUE);
}
@@ -511,62 +452,34 @@ void LLFloaterReporter::closePickTool(void *userdata)
// static
void LLFloaterReporter::showFromMenu(EReportType report_type)
{
if (gReporterInstances.checkData(report_type))
if (COMPLAINT_REPORT != report_type)
{
// ...bring that window to front
LLFloaterReporter *f = gReporterInstances.getData(report_type);
f->open(); /* Flawfinder: ignore */
llwarns << "Unknown LLViewerReporter type : " << report_type << llendl;
return;
}
else
LLFloaterReporter* f = getInstance();
if (f)
{
LLFloaterReporter *f;
if (BUG_REPORT == report_type)
{
f = LLFloaterReporter::createNewBugReporter();
}
else if (COMPLAINT_REPORT == report_type)
{
f = LLFloaterReporter::createNewAbuseReporter();
}
else
{
llwarns << "Unknown LLViewerReporter type : " << report_type << llendl;
return;
}
f->center();
if (report_type == BUG_REPORT)
{
LLNotificationsUtil::add("HelpReportBug");
}
else
{
// popup for abuse reports is triggered elsewhere
}
// grab the user's name
std::string fullname;
gAgent.buildFullname(fullname);
f->childSetText("reporter_field", fullname);
f->setReportType(report_type);
}
}
// static
void LLFloaterReporter::showFromObject(const LLUUID& object_id)
void LLFloaterReporter::show(const LLUUID& object_id, const std::string& avatar_name)
{
LLFloaterReporter* f = createNewAbuseReporter();
f->center();
f->setFocus(TRUE);
LLFloaterReporter* f = getInstance();
// grab the user's name
std::string fullname;
gAgent.buildFullname(fullname);
f->childSetText("reporter_field", fullname);
// Request info for this object
f->getObjectInfo(object_id);
if (avatar_name.empty())
{
// Request info for this object
f->getObjectInfo(object_id);
}
else
{
f->setFromAvatarID(object_id);
}
// Need to deselect on close
f->mDeselectOnClose = TRUE;
@@ -576,55 +489,33 @@ void LLFloaterReporter::showFromObject(const LLUUID& object_id)
// static
LLFloaterReporter* LLFloaterReporter::getReporter(EReportType report_type)
void LLFloaterReporter::showFromObject(const LLUUID& object_id)
{
LLFloaterReporter *self = NULL;
if (gReporterInstances.checkData(report_type))
{
// ...bring that window to front
self = gReporterInstances.getData(report_type);
}
return self;
show(object_id);
}
LLFloaterReporter* LLFloaterReporter::createNewAbuseReporter()
// static
void LLFloaterReporter::showFromAvatar(const LLUUID& avatar_id, const std::string avatar_name)
{
return new LLFloaterReporter("complaint_reporter",
LLRect(),
"Report Abuse",
COMPLAINT_REPORT);
show(avatar_id, avatar_name);
}
//static
LLFloaterReporter* LLFloaterReporter::createNewBugReporter()
{
return new LLFloaterReporter("bug_reporter",
LLRect(),
"Report Bug",
BUG_REPORT);
}
void LLFloaterReporter::setPickedObjectProperties(const std::string& object_name, const std::string& owner_name, const LLUUID owner_id)
{
childSetText("object_name", object_name);
// [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e) | Added: RVLa-1.0.0e
if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES))
{
childSetVisible("object_name", true); // Show the object name if the picked object is actually an object
}
// [/RLVa:KB]
childSetText("owner_name", owner_name);
childSetText("abuser_name_edit", owner_name);
getChild<LLUICtrl>("object_name")->setValue(object_name);
getChild<LLUICtrl>("owner_name")->setValue(owner_name);
getChild<LLUICtrl>("abuser_name_edit")->setValue(owner_name);
mAbuserID = owner_id;
mOwnerName = owner_name;
}
bool LLFloaterReporter::validateReport()
{
// Ensure user selected a category from the list
LLSD category_sd = childGetValue("category_combo");
LLSD category_sd = getChild<LLUICtrl>("category_combo")->getValue();
U8 category = (U8)category_sd.asInteger();
if(category >= 100) //This is here for reasons (like shenanigans)
{
@@ -633,55 +524,39 @@ bool LLFloaterReporter::validateReport()
}
if (category == 0)
{
if ( mReportType != BUG_REPORT )
{
LLNotificationsUtil::add("HelpReportAbuseSelectCategory");
}
else
{
LLNotificationsUtil::add("HelpReportAbuseAbuserNameEmpty");
}
LLNotificationsUtil::add("HelpReportAbuseSelectCategory");
return false;
}
if ( mReportType != BUG_REPORT )
{
if ( childGetText("abuser_name_edit").empty() )
{
LLNotificationsUtil::add("HelpReportAbuseAbuserLocationEmpty");
return false;
};
if ( childGetText("abuse_location_edit").empty() )
{
LLNotificationsUtil::add("HelpReportAbuseAbuserLocationEmpty");
return false;
};
};
if ( childGetText("summary_edit").empty() )
if ( getChild<LLUICtrl>("abuser_name_edit")->getValue().asString().empty() )
{
if ( mReportType != BUG_REPORT )
{
LLNotificationsUtil::add("HelpReportAbuseSummaryEmpty");
}
else
{
LLNotificationsUtil::add("HelpReportBugSummaryEmpty");
}
LLNotificationsUtil::add("HelpReportAbuseAbuserNameEmpty");
return false;
}
if ( getChild<LLUICtrl>("abuse_location_edit")->getValue().asString().empty() )
{
LLNotificationsUtil::add("HelpReportAbuseAbuserLocationEmpty");
return false;
}
if ( getChild<LLUICtrl>("abuse_location_edit")->getValue().asString().empty() )
{
LLNotificationsUtil::add("HelpReportAbuseAbuserLocationEmpty");
return false;
}
if ( getChild<LLUICtrl>("summary_edit")->getValue().asString().empty() )
{
LLNotificationsUtil::add("HelpReportAbuseSummaryEmpty");
return false;
};
if ( childGetText("details_edit") == mDefaultSummary )
if ( getChild<LLUICtrl>("details_edit")->getValue().asString() == mDefaultSummary )
{
if ( mReportType != BUG_REPORT )
{
LLNotificationsUtil::add("HelpReportAbuseDetailsEmpty");
}
else
{
LLNotificationsUtil::add("HelpReportBugDetailsEmpty");
}
return false;
};
return true;
@@ -710,65 +585,45 @@ LLSD LLFloaterReporter::gatherReport()
#if LL_WINDOWS
const char* platform = "Win";
const char* short_platform = "O:W";
#elif LL_DARWIN
const char* platform = "Mac";
const char* short_platform = "O:M";
#elif LL_LINUX
const char* platform = "Lnx";
const char* short_platform = "O:L";
#elif LL_SOLARIS
const char* platform = "Sol";
const char* short_platform = "O:S";
#else
const char* platform = "???";
const char* short_platform = "O:?";
#endif
if ( mReportType == BUG_REPORT)
{
summary << short_platform << " V" << gVersionMajor << "."
<< gVersionMinor << "."
<< gVersionPatch << "."
<< gVersionBuild
<< " (" << regionp->getName() << ")"
<< "[" << category_name << "] "
<< "\"" << childGetValue("summary_edit").asString() << "\"";
}
else
{
summary << ""
<< " |" << regionp->getName() << "|" // region reporter is currently in.
<< " (" << childGetText("abuse_location_edit") << ")" // region abuse occured in (freeform text - no LLRegionPicker tool)
<< " [" << category_name << "] " // updated category
<< " {" << childGetText("abuser_name_edit") << "} " // name of abuse entered in report (chosen using LLAvatarPicker)
<< " \"" << childGetValue("summary_edit").asString() << "\""; // summary as entered
};
summary << ""
<< " |" << regionp->getName() << "|" // region reporter is currently in.
<< " (" << getChild<LLUICtrl>("abuse_location_edit")->getValue().asString() << ")" // region abuse occured in (freeform text - no LLRegionPicker tool)
<< " [" << category_name << "] " // updated category
<< " {" << getChild<LLUICtrl>("abuser_name_edit")->getValue().asString() << "} " // name of abuse entered in report (chosen using LLAvatarPicker)
<< " \"" << getChild<LLUICtrl>("summary_edit")->getValue().asString() << "\""; // summary as entered
std::ostringstream details;
if (mReportType != BUG_REPORT)
{
details << "V" << gVersionMajor << "." // client version moved to body of email for abuse reports
<< gVersionMinor << "."
<< gVersionPatch << "."
<< gVersionBuild << std::endl << std::endl;
}
std::string object_name = childGetText("object_name");
std::string owner_name = childGetText("owner_name");
if (!object_name.empty() && !owner_name.empty())
details << "V" << gVersionMajor << "." // client version moved to body of email for abuse reports
<< gVersionMinor << "."
<< gVersionPatch << "."
<< gVersionBuild << std::endl << std::endl;
std::string object_name = getChild<LLUICtrl>("object_name")->getValue().asString();
if (!object_name.empty() && !mOwnerName.empty())
{
details << "Object: " << object_name << "\n";
details << "Owner: " << owner_name << "\n";
details << "Owner: " << mOwnerName << "\n";
}
if ( mReportType != BUG_REPORT )
{
details << "Abuser name: " << childGetText("abuser_name_edit") << " \n";
details << "Abuser location: " << childGetText("abuse_location_edit") << " \n";
};
details << childGetValue("details_edit").asString();
details << "Abuser name: " << getChild<LLUICtrl>("abuser_name_edit")->getValue().asString() << " \n";
details << "Abuser location: " << getChild<LLUICtrl>("abuse_location_edit")->getValue().asString() << " \n";
details << getChild<LLUICtrl>("details_edit")->getValue().asString();
std::string version_string;
version_string = llformat(
@@ -784,14 +639,14 @@ LLSD LLFloaterReporter::gatherReport()
// only send a screenshot ID if we're asked to and the email is
// going to LL - Estate Owners cannot see the screenshot asset
LLUUID screenshot_id = LLUUID::null;
if (childGetValue("screen_check"))
if (getChild<LLUICtrl>("screen_check")->getValue())
{
screenshot_id = childGetValue("screenshot");
};
screenshot_id = getChild<LLUICtrl>("screenshot")->getValue();
}
LLSD report = LLSD::emptyMap();
report["report-type"] = (U8) mReportType;
report["category"] = childGetValue("category_combo");
report["category"] = getChild<LLUICtrl>("category_combo")->getValue();
report["position"] = mPosition.getValue();
report["check-flags"] = (U8)0; // this is not used
report["screenshot-id"] = screenshot_id;
@@ -877,7 +732,7 @@ public:
void LLFloaterReporter::sendReportViaCaps(std::string url, std::string sshot_url, const LLSD& report)
{
if(childGetValue("screen_check").asBoolean() && !sshot_url.empty())
if(getChild<LLUICtrl>("screen_check")->getValue().asBoolean() && !sshot_url.empty())
{
// try to upload screenshot
LLHTTPClient::post(sshot_url, report, new LLUserReportScreenshotResponder(report,
@@ -893,11 +748,11 @@ void LLFloaterReporter::sendReportViaCaps(std::string url, std::string sshot_url
void LLFloaterReporter::takeScreenshot()
{
const S32 IMAGE_WIDTH = 1024;
const S32 IMAGE_HEIGHT = 768;
// Warning: This crops left and right in case of wide-screen monitor:
const S32 IMAGE_WIDTH = 1024; //gViewerWindow->getWindowWidthRaw();
const S32 IMAGE_HEIGHT = 768; //gViewerWindow->getWindowHeightRaw();
LLPointer<LLImageRaw> raw = new LLImageRaw;
// 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;
@@ -911,15 +766,11 @@ void LLFloaterReporter::takeScreenshot()
mResourceDatap->mExpectedUploadCost = 0; // we expect that abuse screenshots are free
mResourceDatap->mAssetInfo.mTransactionID.generate();
mResourceDatap->mAssetInfo.mUuid = mResourceDatap->mAssetInfo.mTransactionID.makeAssetID(gAgent.getSecureSessionID());
if (BUG_REPORT == mReportType)
if (COMPLAINT_REPORT == mReportType)
{
mResourceDatap->mAssetInfo.mType = LLAssetType::AT_TEXTURE;
mResourceDatap->mPreferredLocation = LLFolderType::EType(-1);
}
else if (COMPLAINT_REPORT == mReportType)
{
mResourceDatap->mAssetInfo.mType = LLAssetType::AT_TEXTURE;
mResourceDatap->mPreferredLocation = LLFolderType::EType(-2);
mResourceDatap->mPreferredLocation = LLFolderType::EType(LLResourceData::INVALID_LOCATION);
}
else
{
@@ -987,11 +838,7 @@ void LLFloaterReporter::uploadDoneCallback(const LLUUID &uuid, void *user_data,
}
EReportType report_type = UNKNOWN_REPORT;
if (data->mPreferredLocation == -1)
{
report_type = BUG_REPORT;
}
else if (data->mPreferredLocation == -2)
if (data->mPreferredLocation == LLResourceData::INVALID_LOCATION)
{
report_type = COMPLAINT_REPORT;
}
@@ -1000,7 +847,7 @@ void LLFloaterReporter::uploadDoneCallback(const LLUUID &uuid, void *user_data,
llwarns << "Unknown report type : " << data->mPreferredLocation << llendl;
}
LLFloaterReporter *self = getReporter(report_type);
LLFloaterReporter *self = getInstance();
if (self)
{
self->mScreenID = uuid;
@@ -1018,38 +865,38 @@ void LLFloaterReporter::setPosBox(const LLVector3d &pos)
mPosition.mV[VX],
mPosition.mV[VY],
mPosition.mV[VZ]);
childSetText("pos_field", pos_string);
getChild<LLUICtrl>("pos_field")->setValue(pos_string);
}
void LLFloaterReporter::setDescription(const std::string& description, LLMeanCollisionData *mcd)
{
LLFloaterReporter *self = gReporterInstances[COMPLAINT_REPORT];
if (self)
{
self->childSetText("details_edit", description);
//void LLFloaterReporter::setDescription(const std::string& description, LLMeanCollisionData *mcd)
//{
// LLFloaterReporter *self = getInstance();
// if (self)
// {
// self->getChild<LLUICtrl>("details_edit")->setValue(description);
for_each(self->mMCDList.begin(), self->mMCDList.end(), DeletePointer());
self->mMCDList.clear();
if (mcd)
{
self->mMCDList.push_back(new LLMeanCollisionData(mcd));
}
}
}
// for_each(self->mMCDList.begin(), self->mMCDList.end(), DeletePointer());
// self->mMCDList.clear();
// if (mcd)
// {
// self->mMCDList.push_back(new LLMeanCollisionData(mcd));
// }
// }
//}
void LLFloaterReporter::addDescription(const std::string& description, LLMeanCollisionData *mcd)
{
LLFloaterReporter *self = gReporterInstances[COMPLAINT_REPORT];
if (self)
{
LLTextEditor* text = self->getChild<LLTextEditor>("details_edit");
if (text)
{
text->insertText(description);
}
if (mcd)
{
self->mMCDList.push_back(new LLMeanCollisionData(mcd));
}
}
}
//void LLFloaterReporter::addDescription(const std::string& description, LLMeanCollisionData *mcd)
//{
// LLFloaterReporter *self = getInstance();
// if (self)
// {
// LLTextEditor* text = self->getChild<LLTextEditor>("details_edit");
// if (text)
// {
// text->insertText(description);
// }
// if (mcd)
// {
// self->mMCDList.push_back(new LLMeanCollisionData(mcd));
// }
// }
//}

View File

@@ -1,13 +1,12 @@
/**
* @file llfloaterreporter.h
* @author Andrew Meadows
* @brief Bug and abuse reports.
* @brief Abuse reports.
*
* $LicenseInfo:firstyear=2006&license=viewergpl$
*
* Second Life Viewer Source Code
* Copyright (c) 2006-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
@@ -49,7 +48,7 @@ class LLMeanCollisionData;
struct LLResourceData;
// these flags are used to label info requests to the server
const U32 BUG_REPORT_REQUEST = 0x01 << 0;
//const U32 BUG_REPORT_REQUEST = 0x01 << 0; // DEPRECATED
const U32 COMPLAINT_REPORT_REQUEST = 0x01 << 1;
const U32 OBJECT_PAY_REQUEST = 0x01 << 2;
@@ -74,48 +73,45 @@ enum EReportType
{
NULL_REPORT = 0, // don't use this value anywhere
UNKNOWN_REPORT = 1,
BUG_REPORT = 2,
//BUG_REPORT = 2, // DEPRECATED
COMPLAINT_REPORT = 3,
CS_REQUEST_REPORT = 4
};
class LLFloaterReporter
: public LLFloater
: public LLFloater, public LLSingleton<LLFloaterReporter>
{
public:
LLFloaterReporter(const std::string& name,
const LLRect &rect,
const std::string& title,
EReportType = UNKNOWN_REPORT);
LLFloaterReporter();
/*virtual*/ ~LLFloaterReporter();
/*virtual*/ BOOL postBuild();
virtual void draw();
void setReportType(EReportType type) { mReportType = type; }
// Enables all buttons
static void showFromMenu(EReportType report_type);
static void showFromObject(const LLUUID& object_id);
static void showFromAvatar(const LLUUID& avatar_id, const std::string avatar_name);
static void onClickSend (void *userdata);
static void onClickCancel (void *userdata);
static void onClickObjPicker (void *userdata);
static void onClickSelectAbuser (void *userdata);
void onClickSelectAbuser ();
static void closePickTool (void *userdata);
static void uploadDoneCallback(const LLUUID &uuid, void* user_data, S32 result, LLExtStat ext_status);
static void addDescription(const std::string& description, LLMeanCollisionData *mcd = NULL);
static void setDescription(const std::string& description, LLMeanCollisionData *mcd = NULL);
// returns a pointer to reporter of report_type
static LLFloaterReporter* getReporter(EReportType report_type);
static LLFloaterReporter* createNewAbuseReporter();
static LLFloaterReporter* createNewBugReporter();
// static
static void processRegionInfo(LLMessageSystem* msg);
void setPickedObjectProperties(const std::string& object_name, const std::string& owner_name, const LLUUID owner_id);
private:
static void show(const LLUUID& object_id, const std::string& avatar_name = LLStringUtil::null);
void takeScreenshot();
void sendReportViaCaps(std::string url);
void uploadImage();
@@ -128,12 +124,16 @@ private:
void enableControls(BOOL own_avatar);
void getObjectInfo(const LLUUID& object_id);
void callbackAvatarID(const uuid_vec_t& ids, const std::vector<LLAvatarName>& names);
void setFromAvatarID(const LLUUID& avatar_id);
void onAvatarNameCache(const LLUUID& avatar_id, const LLAvatarName& av_name);
private:
EReportType mReportType;
LLUUID mObjectID;
LLUUID mScreenID;
LLUUID mAbuserID;
// Store the real name, not the link, for upstream reporting
std::string mOwnerName;
BOOL mDeselectOnClose;
BOOL mPicking;
LLVector3 mPosition;

View File

@@ -353,7 +353,7 @@ void LLFloaterTeleportHistory::onShowOnMap(void* data)
// point world map at position
gFloaterWorldMap->trackURL(region, x, y, z);
LLFloaterWorldMap::show(NULL, TRUE);
LLFloaterWorldMap::show(true);
}
// static

View File

@@ -85,7 +85,6 @@ LLFloaterTOS::LLFloaterTOS(ETOSType type, const std::string & message)
: LLModalDialog( std::string(" "), 100, 100 ),
mType(type),
mMessage(message),
mWebBrowserWindowId( 0 ),
mLoadCompleteCount( 0 )
{
}

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