diff --git a/indra/CMakeLists.txt b/indra/CMakeLists.txt index f80c1a15e..fc7b0a878 100644 --- a/indra/CMakeLists.txt +++ b/indra/CMakeLists.txt @@ -30,8 +30,6 @@ include(BuildVersion) include(UnixInstall) -set (DISABLE_FATAL_WARNINGS CACHE BOOL TRUE) - if (NOT CMAKE_CONFIGURATION_TYPES AND NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE Release CACHE STRING "Build type. One of: Debug Release RelWithDebInfo" FORCE) diff --git a/indra/aistatemachine/aistatemachine.cpp b/indra/aistatemachine/aistatemachine.cpp index dedec3bd7..46bda0ad3 100644 --- a/indra/aistatemachine/aistatemachine.cpp +++ b/indra/aistatemachine/aistatemachine.cpp @@ -352,8 +352,13 @@ void AIEngine::mainloop(void) void AIEngine::flush(void) { - DoutEntering(dc::statemachine, "AIEngine::flush [" << mName << "]"); engine_state_type_wat engine_state_w(mEngineState); + DoutEntering(dc::statemachine, "AIEngine::flush [" << mName << "]: calling force_killed() on " << engine_state_w->list.size() << " state machines."); + for (queued_type::iterator iter = engine_state_w->list.begin(); iter != engine_state_w->list.end(); ++iter) + { + // To avoid an assertion in ~AIStateMachine. + iter->statemachine().force_killed(); + } engine_state_w->list.clear(); } @@ -368,7 +373,7 @@ void AIEngine::setMaxCount(F32 StateMachineMaxTime) sMaxCount = calc_clock_frequency() * StateMachineMaxTime / 1000; } -#ifdef CWDEBUG +#if defined(CWDEBUG) || defined(DEBUG_CURLIO) char const* AIStateMachine::event_str(event_type event) { switch(event) @@ -906,6 +911,12 @@ void AIStateMachine::callback(void) } } +void AIStateMachine::force_killed(void) +{ + multiplex_state_type_wat state_w(mState); + state_w->base_state = bs_killed; +} + void AIStateMachine::kill(void) { DoutEntering(dc::statemachine, "AIStateMachine::kill() [" << (void*)this << "]"); diff --git a/indra/aistatemachine/aistatemachine.h b/indra/aistatemachine/aistatemachine.h index 10031a834..9b5b0aab6 100644 --- a/indra/aistatemachine/aistatemachine.h +++ b/indra/aistatemachine/aistatemachine.h @@ -146,12 +146,15 @@ class AIStateMachine : public LLThreadSafeRefCount typedef AIAccessConst multiplex_state_type_crat; typedef AIAccess multiplex_state_type_rat; typedef AIAccess multiplex_state_type_wat; + + protected: // Sub state. AIThreadSafeSimpleDC mSubState; typedef AIAccessConst sub_state_type_crat; typedef AIAccess sub_state_type_rat; typedef AIAccess sub_state_type_wat; + private: // Mutex protecting everything below and making sure only one thread runs the state machine at a time. LLMutex mMultiplexMutex; // Mutex that is locked while calling *_impl() functions and the call back. @@ -271,7 +274,7 @@ class AIStateMachine : public LLThreadSafeRefCount // Return stringified state, for debugging purposes. char const* state_str(base_state_type state); -#ifdef CWDEBUG +#if defined(CWDEBUG) || defined(DEBUG_CURLIO) char const* event_str(event_type event); #endif @@ -300,8 +303,9 @@ class AIStateMachine : public LLThreadSafeRefCount mSleep = 0; return mSleep != 0; } + void force_killed(void); // Called from AIEngine::flush(). - friend class AIEngine; // Calls multiplex(). + friend class AIEngine; // Calls multiplex() and force_killed(). }; bool AIEngine::QueueElementComp::operator()(QueueElement const& e1, QueueElement const& e2) const diff --git a/indra/aistatemachine/aistatemachinethread.cpp b/indra/aistatemachine/aistatemachinethread.cpp index 030bd0a5a..f45d1e845 100644 --- a/indra/aistatemachine/aistatemachinethread.cpp +++ b/indra/aistatemachine/aistatemachinethread.cpp @@ -33,12 +33,12 @@ class AIStateMachineThreadBase::Thread : public LLThread { private: - LLPointer mImpl; + LLPointer mImpl; bool mNeedCleanup; public: - Thread(AIThreadImpl* impl) : + Thread(AIStateMachineThreadBase* impl) : #ifdef LL_DEBUG - LLThread(impl->getName()), + LLThread(impl->impl().getName()), #else LLThread("AIStateMachineThreadBase::Thread"), #endif @@ -46,7 +46,7 @@ class AIStateMachineThreadBase::Thread : public LLThread { protected: /*virtual*/ void run(void) { - mNeedCleanup = mImpl->thread_done(mImpl->run()); + mNeedCleanup = mImpl->impl().thread_done(mImpl->impl().run()); } /*virtual*/ void terminated(void) { @@ -65,7 +65,7 @@ class AIStateMachineThreadBase::Thread : public LLThread { } public: // TODO: Implement a thread pool. For now, just create a new one every time. - static Thread* allocate(AIThreadImpl* impl) { return new Thread(impl); } + static Thread* allocate(AIStateMachineThreadBase* impl) { return new Thread(impl); } static void completed(Thread* threadp) { delete threadp; } }; @@ -93,7 +93,7 @@ void AIStateMachineThreadBase::multiplex_impl(state_type run_state) switch(run_state) { case start_thread: - mThread = Thread::allocate(mImpl); + mThread = Thread::allocate(this); // Set next state. set_state(wait_stopped); idle(); // Wait till the thread returns. @@ -124,10 +124,10 @@ void AIStateMachineThreadBase::abort_impl(void) { if (mThread) { - // If this AIStateMachineThreadBase still exists then the first base class of - // AIStateMachineThread, LLPointer, also still exists - // and therefore mImpl is valid. - bool need_cleanup = mImpl->state_machine_done(mThread); // Signal the fact that we aborted. + // If this AIStateMachineThreadBase still exists then the AIStateMachineThread + // that is derived from it still exists and therefore its member THREAD_IMPL also still exists + // and therefore impl() is valid. + bool need_cleanup = impl().state_machine_done(mThread); // Signal the fact that we aborted. if (need_cleanup) { // This is an unlikely race condition. We have been aborted by our parent, diff --git a/indra/aistatemachine/aistatemachinethread.h b/indra/aistatemachine/aistatemachinethread.h index 85b2ff108..780060bb6 100644 --- a/indra/aistatemachine/aistatemachinethread.h +++ b/indra/aistatemachine/aistatemachinethread.h @@ -73,11 +73,11 @@ enum hello_world_state_type { // The statemachine class (this is almost a template). class HelloWorld : public AIStateMachine { private: - AIStateMachineThread mHelloWorld; + LLPointer > mHelloWorld; bool mErr; public: - HelloWorld() : mErr(false) { } + HelloWorld() : mHelloWorld(new AIStateMachineThread), mErr(false) { } // Print to stderr or stdout? void init(bool err) { mErr = err; } @@ -108,7 +108,7 @@ class HelloWorld : public AIStateMachine { void HelloWorld::initialize_impl(void) { - mHelloWorld->init(mErr); // Initialize the thread object. + mHelloWorld->thread_impl().init(mErr); // Initialize the thread object. set_state(HelloWorld_start); } @@ -118,14 +118,14 @@ void HelloWorld::multiplex_impl(state_type run_state) { case HelloWorld_start: { - mHelloWorld.run(this, HelloWorld_done); // Run HelloWorldThread and set the state of 'this' to HelloWorld_done when finished. + mHelloWorld->run(this, HelloWorld_done); // Run HelloWorldThread and set the state of 'this' to HelloWorld_done when finished. idle(HelloWorld_start); // Always go idle after starting a thread! break; } case HelloWorld_done: { // We're done. Lets also abort when the thread reported no success. - if (mHelloWorld->successful()) // Read output/result of thread object. + if (mHelloWorld->thread_impl().successful()) // Read output/result of thread object. finish(); else abort(); @@ -139,9 +139,9 @@ void HelloWorld::multiplex_impl(state_type run_state) class AIStateMachineThreadBase; // Derive from this to implement the code that must run in another thread. -class AIThreadImpl : public LLThreadSafeRefCount { +class AIThreadImpl { private: - template friend struct AIStateMachineThread; + template friend class AIStateMachineThread; typedef AIAccess StateMachineThread_wat; AIThreadSafeSimpleDC mStateMachineThread; @@ -158,6 +158,9 @@ class AIThreadImpl : public LLThreadSafeRefCount { public: char const* getName(void) const { return mName; } #endif + + protected: + virtual ~AIThreadImpl() { } }; // The base class for statemachine threads. @@ -178,7 +181,7 @@ class AIStateMachineThreadBase : public AIStateMachine { static state_type const max_state = wait_stopped + 1; protected: - AIStateMachineThreadBase(AIThreadImpl* impl) : mImpl(impl) { ref(); /* Never call delete */ } + AIStateMachineThreadBase(void) { } private: // Handle initializing the object. @@ -193,9 +196,11 @@ class AIStateMachineThreadBase : public AIStateMachine { // Implemenation of state_str for run states. /*virtual*/ char const* state_str_impl(state_type run_state) const; + // Returns a reference to the implementation code that needs to be run in the thread. + virtual AIThreadImpl& impl(void) = 0; + private: Thread* mThread; // The thread that the code is run in. - AIThreadImpl* mImpl; // Pointer to the implementation code that needs to be run in the thread. bool mAbort; // (Inverse of) return value of AIThreadImpl::run(). Only valid in state wait_stopped. public: @@ -206,14 +211,22 @@ class AIStateMachineThreadBase : public AIStateMachine { // The state machine that runs T::run() in a thread. // THREAD_IMPL Must be derived from AIThreadImpl. template -struct AIStateMachineThread : public LLPointer, public AIStateMachineThreadBase { - // Constructor. - AIStateMachineThread(void) : - LLPointer(new THREAD_IMPL), - AIStateMachineThreadBase(LLPointer::get()) - { - *AIThreadImpl::StateMachineThread_wat(static_cast(LLPointer::get())->mStateMachineThread) = this; - } +class AIStateMachineThread : public AIStateMachineThreadBase { + private: + THREAD_IMPL mThreadImpl; + + public: + // Constructor. + AIStateMachineThread(void) + { + *AIThreadImpl::StateMachineThread_wat(mThreadImpl.mStateMachineThread) = this; + } + + // Accessor. + THREAD_IMPL& thread_impl(void) { return mThreadImpl; } + + protected: + /*virtual*/ AIThreadImpl& impl(void) { return mThreadImpl; } }; #endif diff --git a/indra/cmake/00-Common.cmake b/indra/cmake/00-Common.cmake index 6bfa9f9f6..449186a08 100644 --- a/indra/cmake/00-Common.cmake +++ b/indra/cmake/00-Common.cmake @@ -34,7 +34,7 @@ if (WINDOWS) endif (MSVC10) # Remove default /Zm1000 flag that cmake inserts - string (REPLACE "/Zm1000" " " CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS}) + string (REPLACE "/Zm1000" " " CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") # Don't build DLLs. set(BUILD_SHARED_LIBS OFF) @@ -270,10 +270,10 @@ endif (DARWIN) if (LINUX OR DARWIN) if(${CMAKE_C_COMPILER} MATCHES "gcc*") - set(UNIX_WARNINGS "-Wall -Wno-sign-compare -Wno-trigraphs") + 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 ") + 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") @@ -281,8 +281,11 @@ if (LINUX OR DARWIN) set(UNIX_CXX_WARNINGS "${UNIX_WARNINGS}") 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") endif (NOT DISABLE_FATAL_WARNINGS) set(CMAKE_C_FLAGS "${UNIX_WARNINGS} ${CMAKE_C_FLAGS}") @@ -333,4 +336,6 @@ MARK_AS_ADVANCED( CMAKE_SHARED_LINKER_FLAGS_RELEASE ) +include(GooglePerfTools) + endif(NOT DEFINED ${CMAKE_CURRENT_LIST_FILE}_INCLUDED) diff --git a/indra/cmake/GooglePerfTools.cmake b/indra/cmake/GooglePerfTools.cmake index 3ad669c94..d92c39ded 100644 --- a/indra/cmake/GooglePerfTools.cmake +++ b/indra/cmake/GooglePerfTools.cmake @@ -1,4 +1,5 @@ # -*- cmake -*- + include(Prebuilt) if(WORD_SIZE EQUAL 64) @@ -47,9 +48,14 @@ else (USE_GOOGLE_PERFTOOLS) endif (USE_GOOGLE_PERFTOOLS) if (NOT(DISABLE_TCMALLOC OR USE_GOOGLE_PERFTOOLS OR STANDALONE)) - message(STATUS "Building with Google TCMalloc") - set(TCMALLOC_FLAG -DLL_USE_TCMALLOC=1) - include_directories(${GOOGLE_PERFTOOLS_INCLUDE_DIR}) - set(GOOGLE_PERFTOOLS_LIBRARIES ${TCMALLOC_LIBRARIES}) + if (NOT STATUS_Building_with_Google_TCMalloc) + message(STATUS "Building with Google TCMalloc") + set(STATUS_Building_with_Google_TCMalloc true PARENT_SCOPE) + endif (NOT STATUS_Building_with_Google_TCMalloc) + set(TCMALLOC_FLAG -DLL_USE_TCMALLOC=1) + include_directories(${GOOGLE_PERFTOOLS_INCLUDE_DIR}) + set(GOOGLE_PERFTOOLS_LIBRARIES ${TCMALLOC_LIBRARIES}) set(GOOGLE_PERFTOOLS_LINKER_FLAGS ${TCMALLOC_LINKER_FLAGS}) endif() + +add_definitions(${TCMALLOC_FLAG}) \ No newline at end of file diff --git a/indra/cmake/Linking.cmake b/indra/cmake/Linking.cmake index 4b34ff47d..00754ec36 100644 --- a/indra/cmake/Linking.cmake +++ b/indra/cmake/Linking.cmake @@ -1,4 +1,8 @@ # -*- cmake -*- +if(NOT DEFINED ${CMAKE_CURRENT_LIST_FILE}_INCLUDED) +set(${CMAKE_CURRENT_LIST_FILE}_INCLUDED "YES") + +include(Variables) if (NOT STANDALONE) if (WINDOWS) @@ -45,3 +49,5 @@ else (WINDOWS) endif (WINDOWS) mark_as_advanced(DL_LIBRARY PTHREAD_LIBRARY WINDOWS_LIBRARIES) + +endif(NOT DEFINED ${CMAKE_CURRENT_LIST_FILE}_INCLUDED) diff --git a/indra/cmake/Prebuilt.cmake b/indra/cmake/Prebuilt.cmake index 6dd9c47bd..2295a7574 100644 --- a/indra/cmake/Prebuilt.cmake +++ b/indra/cmake/Prebuilt.cmake @@ -1,5 +1,8 @@ # -*- cmake -*- +if(NOT DEFINED ${CMAKE_CURRENT_LIST_FILE}_INCLUDED) +set(${CMAKE_CURRENT_LIST_FILE}_INCLUDED "YES") + macro (use_prebuilt_binary _binary) if(NOT STANDALONE) get_property(PREBUILT_PACKAGES TARGET prepare PROPERTY PREBUILT) @@ -9,3 +12,5 @@ macro (use_prebuilt_binary _binary) endif(_index LESS 0) endif(NOT STANDALONE) endmacro (use_prebuilt_binary _binary) + +endif(NOT DEFINED ${CMAKE_CURRENT_LIST_FILE}_INCLUDED) diff --git a/indra/cmake/Variables.cmake b/indra/cmake/Variables.cmake index 9815c8096..5bc3e2156 100644 --- a/indra/cmake/Variables.cmake +++ b/indra/cmake/Variables.cmake @@ -92,29 +92,25 @@ if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") set(DARWIN 1) if(${CMAKE_GENERATOR} MATCHES Xcode) - execute_process( - COMMAND sh -c "xcodebuild -version | grep Xcode | cut -d ' ' -f2 | cut -d'.' -f1-2" - OUTPUT_VARIABLE XCODE_VERSION ) - - # To support a different SDK update these Xcode settings: - if (XCODE_VERSION GREATER 4.2) - set(CMAKE_OSX_DEPLOYMENT_TARGET 10.6) - else (XCODE_VERSION GREATER 4.2) + #SDK Compiler and Deployment targets for XCode + if (${XCODE_VERSION} VERSION_LESS 4.0.0) + set(CMAKE_OSX_SYSROOT /Developer/SDKs/MacOSX10.5.sdk) set(CMAKE_OSX_DEPLOYMENT_TARGET 10.5) - endif (XCODE_VERSION GREATER 4.2) + else (${XCODE_VERSION} VERSION_LESS 4.0.0) + set(CMAKE_OSX_SYSROOT /Developer/SDKs/MacOSX10.6.sdk) + set(CMAKE_OSX_DEPLOYMENT_TARGET 10.6) + endif (${XCODE_VERSION} VERSION_LESS 4.0.0) else(${CMAKE_GENERATOR} MATCHES Xcode) + set(CMAKE_OSX_SYSROOT /Developer/SDKs/MacOSX10.6.sdk) set(CMAKE_OSX_DEPLOYMENT_TARGET 10.6) endif(${CMAKE_GENERATOR} MATCHES Xcode) - set(CMAKE_OSX_SYSROOT /Developer/SDKs/MacOSX10.6.sdk) set(CMAKE_XCODE_ATTRIBUTE_GCC_VERSION "com.apple.compilers.llvmgcc42") set(CMAKE_XCODE_ATTRIBUTE_DEBUG_INFORMATION_FORMAT dwarf-with-dsym) # Build only for i386 by default, system default on MacOSX 10.6 is x86_64 - if (NOT CMAKE_OSX_ARCHITECTURES) - set(CMAKE_OSX_ARCHITECTURES i386) - endif (NOT CMAKE_OSX_ARCHITECTURES) + set(CMAKE_OSX_ARCHITECTURES i386) set(ARCH i386) set(WORD_SIZE 32) diff --git a/indra/libpathing/CMakeLists.txt b/indra/libpathing/CMakeLists.txt index 12d409f20..087faec05 100644 --- a/indra/libpathing/CMakeLists.txt +++ b/indra/libpathing/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.6.4) project(ndPathingLib CXX C) if( MSVC ) - add_definitions(-D_HAS_ITERATOR_DEBUGGING=0 -D_SECURE_SCL=0 -D_CRT_SECURE_NO_WARNINGS=1) + add_definitions(-D_SECURE_SCL=0 -D_CRT_SECURE_NO_WARNINGS=1) endif( MSVC ) file (GLOB SOURCE_FILES *.cpp ) diff --git a/indra/llappearance/llavatarappearance.cpp b/indra/llappearance/llavatarappearance.cpp index 385546798..1d05da7f3 100644 --- a/indra/llappearance/llavatarappearance.cpp +++ b/indra/llappearance/llavatarappearance.cpp @@ -465,7 +465,7 @@ void LLAvatarAppearance::computeBodySize() LLVector3 old_offset = mAvatarOffset; - mAvatarOffset.mV[VZ] = getVisualParamWeight(11001); + mAvatarOffset.mV[VZ] = getVisualParamWeight(AVATAR_HOVER); mPelvisToFoot = hip.mV[VZ] * pelvis_scale.mV[VZ] - knee.mV[VZ] * hip_scale.mV[VZ] - @@ -489,6 +489,25 @@ void LLAvatarAppearance::computeBodySize() mAvatarOffset.mV[VX] = 0.0f; mAvatarOffset.mV[VY] = 0.0f; + // Certain configurations of avatars can force the overall height (with offset) to go negative. + // Enforce a constraint to make sure we don't go below 0.1 meters. + // Camera positioning and other things start to break down when your avatar is "walking" while being fully underground + if (new_body_size.mV[VZ] + mAvatarOffset.mV[VZ] < 0.1f) + { + mAvatarOffset.mV[VZ] = -(new_body_size.mV[VZ] - 0.11f); // avoid floating point rounding making the above check continue to fail. + + llassert(new_body_size.mV[VZ] + mAvatarOffset.mV[VZ] >= 0.1f); + + if (mWearableData && isSelf()) + { + LLWearable* shape = mWearableData->getWearable(LLWearableType::WT_SHAPE, 0); + if (shape) + { + shape->setVisualParamWeight(AVATAR_HOVER, mAvatarOffset.mV[VZ], false); + } + } + } + if (new_body_size != mBodySize || old_offset != mAvatarOffset) { mBodySize = new_body_size; diff --git a/indra/llappearance/llavatarappearancedefines.h b/indra/llappearance/llavatarappearancedefines.h index 496f85c10..8a1d2c470 100644 --- a/indra/llappearance/llavatarappearancedefines.h +++ b/indra/llappearance/llavatarappearancedefines.h @@ -41,6 +41,8 @@ extern const S32 SCRATCH_TEX_WIDTH; extern const S32 SCRATCH_TEX_HEIGHT; extern const S32 IMPOSTOR_PERIOD; +static const U32 AVATAR_HOVER = 11001; + //-------------------------------------------------------------------- // Enums //-------------------------------------------------------------------- diff --git a/indra/llaudio/llaudioengine_fmodex.cpp b/indra/llaudio/llaudioengine_fmodex.cpp index 984e63ca9..4b4108701 100644 --- a/indra/llaudio/llaudioengine_fmodex.cpp +++ b/indra/llaudio/llaudioengine_fmodex.cpp @@ -152,8 +152,8 @@ bool LLAudioEngine_FMODEX::init(const S32 num_channels, void* userdata) << ")! You should be using FMOD Ex" << FMOD_VERSION << LL_ENDL; } - result = mSystem->setSoftwareFormat(44100, FMOD_SOUND_FORMAT_PCM16, 0, 0, FMOD_DSP_RESAMPLER_LINEAR); - Check_FMOD_Error(result,"FMOD::System::setSoftwareFormat"); +// result = mSystem->setSoftwareFormat(44100, FMOD_SOUND_FORMAT_PCM16, 0, 0, FMOD_DSP_RESAMPLER_LINEAR); +// Check_FMOD_Error(result,"FMOD::System::setSoftwareFormat"); // In this case, all sounds, PLUS wind and stream will be software. result = mSystem->setSoftwareChannels(num_channels + 2); diff --git a/indra/llaudio/llstreamingaudio_fmodex.cpp b/indra/llaudio/llstreamingaudio_fmodex.cpp index 60c637806..9e3e406c7 100644 --- a/indra/llaudio/llstreamingaudio_fmodex.cpp +++ b/indra/llaudio/llstreamingaudio_fmodex.cpp @@ -431,7 +431,7 @@ LLAudioStreamManagerFMODEX::LLAudioStreamManagerFMODEX(FMOD::System *system, con exinfo.cbsize = sizeof(exinfo); exinfo.suggestedsoundtype = FMOD_SOUND_TYPE_OGGVORBIS; //Hint to speed up loading.*/ - FMOD_RESULT result = mSystem->createStream(url.c_str(), FMOD_2D | FMOD_NONBLOCKING | FMOD_MPEGSEARCH | FMOD_IGNORETAGS, 0, &mInternetStream); + FMOD_RESULT result = mSystem->createStream(url.c_str(), FMOD_2D | FMOD_NONBLOCKING | FMOD_IGNORETAGS, 0, &mInternetStream); if (result!= FMOD_OK) { diff --git a/indra/llcommon/aithreadid.h b/indra/llcommon/aithreadid.h index cc7197b21..6b2c08516 100644 --- a/indra/llcommon/aithreadid.h +++ b/indra/llcommon/aithreadid.h @@ -33,7 +33,7 @@ #include // apr_os_thread_t, apr_os_thread_current(), apr_os_thread_equal(). #include // std::ostream. -#include "llpreprocessor.h" // LL_COMMON_API, LL_COMMON_API_TLS +#include "llpreprocessor.h" // LL_COMMON_API, LL_COMMON_API_TLS, LL_UNLIKELY // Lightweight wrapper around apr_os_thread_t. // This class introduces no extra assembly code after optimization; it's only intend is to provide type-safety. @@ -87,6 +87,16 @@ public: #endif }; +// Debugging function. +inline bool is_single_threaded(AIThreadID& thread_id) +{ + if (LL_UNLIKELY(thread_id.is_no_thread())) + { + thread_id.reset(); + } + return thread_id.equals_current_thread(); +} + // Legacy function. inline bool is_main_thread(void) { diff --git a/indra/llcommon/lldarray.h b/indra/llcommon/lldarray.h index 293695411..b6834796b 100644 --- a/indra/llcommon/lldarray.h +++ b/indra/llcommon/lldarray.h @@ -153,7 +153,7 @@ inline S32 LLDynamicArray::put(const Type &obj) template inline void LLDynamicArray::operator+=(const LLDynamicArray &other) { - insert(this->end(), other.begin(), other.end()); + this->insert(this->end(), other.begin(), other.end()); } //-------------------------------------------------------- diff --git a/indra/llcommon/llfile.h b/indra/llcommon/llfile.h index 6d2bb8f13..12eb04932 100644 --- a/indra/llcommon/llfile.h +++ b/indra/llcommon/llfile.h @@ -95,7 +95,19 @@ public: namespace { #if LL_WINDOWS -typedef std::filebuf _Myfb; +//typedef std::filebuf _Myfb; +//Singu note: Wrap around std::filebuf to override the open procedure. +// The client encodes filepaths in UTF-8, however Windows uses UTF-16 encoding natively. +// Need to convert paths to UTF-16 before calling std::filebuf::open. +struct _Myfb : public std::filebuf +{ + _Myfb() : std::filebuf() {} + _Myfb(_Filet* file) : std::filebuf(file) {} + _Myt *open(const char *filename, std::ios_base::openmode mode, int prot = (int)std::ios_base::_Openprot) + { + return std::filebuf::open(utf8str_to_utf16str(filename).c_str(),mode,prot); + } +}; #else typedef __gnu_cxx::stdio_filebuf< char > _Myfb; typedef std::__c_file _Filet; diff --git a/indra/llcommon/llmemory.h b/indra/llcommon/llmemory.h index 8a0e0e66d..0762dc3f4 100644 --- a/indra/llcommon/llmemory.h +++ b/indra/llcommon/llmemory.h @@ -57,13 +57,12 @@ inline void ll_aligned_free( void* ptr ) free( ((void**)ptr)[-1] ); } -#if !LL_USE_TCMALLOC inline void* ll_aligned_malloc_16(size_t size) // returned hunk MUST be freed with ll_aligned_free_16(). { -#if defined(LL_WINDOWS) - return _aligned_malloc(size, 16); -#elif defined(LL_DARWIN) +#if (LL_DARWIN || LL_USE_TCMALLOC) return malloc(size); // default osx malloc is 16 byte aligned. +#elif LL_WINDOWS + return _aligned_malloc(size, 16); #else void *rtn; if (LL_LIKELY(0 == posix_memalign(&rtn, 16, size))) @@ -75,10 +74,10 @@ inline void* ll_aligned_malloc_16(size_t size) // returned hunk MUST be freed wi inline void ll_aligned_free_16(void *p) { -#if defined(LL_WINDOWS) +#if (LL_DARWIN || LL_USE_TCMALLOC) + free(p); +#elif LL_WINDOWS _aligned_free(p); -#elif defined(LL_DARWIN) - return free(p); #else free(p); // posix_memalign() is compatible with heap deallocator #endif @@ -86,10 +85,10 @@ inline void ll_aligned_free_16(void *p) inline void* ll_aligned_realloc_16(void* ptr, size_t size, size_t old_size) // returned hunk MUST be freed with ll_aligned_free_16(). { -#if defined(LL_WINDOWS) - return _aligned_realloc(ptr, size, 16); -#elif defined(LL_DARWIN) +#if (LL_DARWIN || LL_USE_TCMALLOC) return realloc(ptr,size); // default osx malloc is 16 byte aligned. +#elif LL_WINDOWS + return _aligned_realloc(ptr, size, 16); #else //FIXME: memcpy is SLOW void* ret = ll_aligned_malloc_16(size); @@ -106,18 +105,11 @@ inline void* ll_aligned_realloc_16(void* ptr, size_t size, size_t old_size) // r #endif } -#else // USE_TCMALLOC -// ll_aligned_foo_16 are not needed with tcmalloc -#define ll_aligned_malloc_16 malloc -#define ll_aligned_realloc_16(a,b,c) realloc(a,b) -#define ll_aligned_free_16 free -#endif // USE_TCMALLOC - inline void* ll_aligned_malloc_32(size_t size) // returned hunk MUST be freed with ll_aligned_free_32(). { -#if defined(LL_WINDOWS) +#if LL_WINDOWS return _aligned_malloc(size, 32); -#elif defined(LL_DARWIN) +#elif LL_DARWIN return ll_aligned_malloc( size, 32 ); #else void *rtn; @@ -130,9 +122,9 @@ inline void* ll_aligned_malloc_32(size_t size) // returned hunk MUST be freed wi inline void ll_aligned_free_32(void *p) { -#if defined(LL_WINDOWS) +#if LL_WINDOWS _aligned_free(p); -#elif defined(LL_DARWIN) +#elif LL_DARWIN ll_aligned_free( p ); #else free(p); // posix_memalign() is compatible with heap deallocator diff --git a/indra/llcommon/llstl.h b/indra/llcommon/llstl.h index 5c0e04fc7..2e872751f 100644 --- a/indra/llcommon/llstl.h +++ b/indra/llcommon/llstl.h @@ -180,7 +180,6 @@ template //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) { - typedef typename T::const_iterator map_iter; if(inmap.find(key) == inmap.end()) { return false; diff --git a/indra/llcommon/lltimer.cpp b/indra/llcommon/lltimer.cpp index 7e5d648fa..e77d8b63a 100644 --- a/indra/llcommon/lltimer.cpp +++ b/indra/llcommon/lltimer.cpp @@ -251,7 +251,7 @@ U64 totalTime() } else { - if (current_clock_count >= gLastTotalTimeClockCount) + if (LL_LIKELY(current_clock_count >= gLastTotalTimeClockCount)) { // No wrapping, we're all okay. gTotalTimeClockCount += current_clock_count - gLastTotalTimeClockCount; diff --git a/indra/llcommon/llversionviewer.h.in b/indra/llcommon/llversionviewer.h.in index 030623505..e1fa1cab3 100644 --- a/indra/llcommon/llversionviewer.h.in +++ b/indra/llcommon/llversionviewer.h.in @@ -34,8 +34,8 @@ #define LL_LLVERSIONVIEWER_H const S32 LL_VERSION_MAJOR = 1; -const S32 LL_VERSION_MINOR = 7; -const S32 LL_VERSION_PATCH = 3; +const S32 LL_VERSION_MINOR = 8; +const S32 LL_VERSION_PATCH = 0; const S32 LL_VERSION_BUILD = ${vBUILD}; const char * const LL_CHANNEL = "${VIEWER_CHANNEL}"; diff --git a/indra/llcrashlogger/llcrashlogger.cpp b/indra/llcrashlogger/llcrashlogger.cpp index c09361144..e072b5c79 100644 --- a/indra/llcrashlogger/llcrashlogger.cpp +++ b/indra/llcrashlogger/llcrashlogger.cpp @@ -390,11 +390,6 @@ bool LLCrashLogger::init() // Start state machine thread. startEngineThread(); - // Start curl thread. - AICurlInterface::startCurlThread(64, // CurlMaxTotalConcurrentConnections - 8, // CurlConcurrentConnectionsPerHost - true); // NoVerifySSLCert - // We assume that all the logs we're looking for reside on the current drive gDirUtilp->initAppDirs("SecondLife"); @@ -414,6 +409,9 @@ bool LLCrashLogger::init() return false; } + // Start curl thread. + AICurlInterface::startCurlThread(&mCrashSettings); + gServicePump = new LLPumpIO; //If we've opened the crash logger, assume we can delete the marker file if it exists diff --git a/indra/llinventory/llpermissions.cpp b/indra/llinventory/llpermissions.cpp index 34354e3e8..f41fce8ed 100644 --- a/indra/llinventory/llpermissions.cpp +++ b/indra/llinventory/llpermissions.cpp @@ -1022,6 +1022,16 @@ void mask_to_string(U32 mask, char* str) { *str = ' '; } + str++; + + if (mask & PERM_EXPORT) + { + *str = 'E'; + } + else + { + *str = ' '; + } str++; *str = '\0'; } diff --git a/indra/llinventory/llpermissionsflags.h b/indra/llinventory/llpermissionsflags.h index f810929d6..02224d0c8 100644 --- a/indra/llinventory/llpermissionsflags.h +++ b/indra/llinventory/llpermissionsflags.h @@ -52,6 +52,9 @@ const PermissionBit PERM_MODIFY = (1 << 14); // 0x00004000 // objects, allow copy const PermissionBit PERM_COPY = (1 << 15); // 0x00008000 +// objects, allow exporting +const PermissionBit PERM_EXPORT = (1 << 16); // 0x00010000 + // parcels, allow entry, deprecated //const PermissionBit PERM_ENTER = (1 << 16); // 0x00010000 diff --git a/indra/llmath/llmatrix3a.cpp b/indra/llmath/llmatrix3a.cpp index ab077abcb..ad008e9d3 100644 --- a/indra/llmath/llmatrix3a.cpp +++ b/indra/llmath/llmatrix3a.cpp @@ -24,6 +24,7 @@ * $/LicenseInfo$ */ +#include "sys.h" #include "llmath.h" static LL_ALIGN_16(const F32 M_IDENT_3A[12]) = diff --git a/indra/llmessage/CMakeLists.txt b/indra/llmessage/CMakeLists.txt index ebee8c548..53e890040 100644 --- a/indra/llmessage/CMakeLists.txt +++ b/indra/llmessage/CMakeLists.txt @@ -22,9 +22,10 @@ include_directories( ) set(llmessage_SOURCE_FILES + aiaverage.cpp aicurl.cpp aicurleasyrequeststatemachine.cpp - aicurlperhost.cpp + aicurlperservice.cpp aicurlthread.cpp aihttpheaders.cpp aihttptimeout.cpp @@ -109,9 +110,10 @@ set(llmessage_SOURCE_FILES set(llmessage_HEADER_FILES CMakeLists.txt + aiaverage.h aicurl.h aicurleasyrequeststatemachine.h - aicurlperhost.h + aicurlperservice.h aicurlprivate.h aicurlthread.h aihttpheaders.h diff --git a/indra/llmessage/aiaverage.cpp b/indra/llmessage/aiaverage.cpp new file mode 100644 index 000000000..10aafd852 --- /dev/null +++ b/indra/llmessage/aiaverage.cpp @@ -0,0 +1,81 @@ +/** + * @file aiaverage.cpp + * @brief Implementation of AIAverage + * + * Copyright (c) 2013, Aleric Inglewood. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * 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. + * + * CHANGELOG + * and additional copyright holders. + * + * 11/04/2013 + * Initial version, written by Aleric Inglewood @ SL + */ + +#include "sys.h" +#include "aiaverage.h" +#include "llerror.h" // llassert + +void AIAverage::cleanup(U64 clock_tick) +{ + // This expression can fail because the curl thread caches the time in + // sTime_10ms for the duration of an entire loop. Therefore, the time can + // go into the next 40ms and a texture fetch worker thread might call + // cleanup() with that time, setting mCurrentClock to a value (one) + // larger than sTime_10ms / 4. Next, the curl thread can continue to call + // this function with the smaller value; in that case just add the new + // data to the current bucket. + // + // Or, this is just the one-time initialization that happens the first + // time this is called. In that case initialize just mCurrentClock: + // the rest is already initialized upon construction. + if (LL_LIKELY(clock_tick > mCurrentClock)) + { + // Advance to the next bucket. + ++mCurrentBucket; + mCurrentBucket %= mNrOfBuckets; + // Initialize the new bucket. + mData[mCurrentBucket].time = clock_tick; + // Clean up old buckets. + U64 old_time = clock_tick - mNrOfBuckets; + if (LL_UNLIKELY(mTail == mCurrentBucket) || // Extremely unlikely: only happens when data was added EVERY clock tick for the past mNrOfBuckets clock ticks. + mData[mTail].time <= old_time) + { + do + { + mSum -= mData[mTail].sum; + mN -= mData[mTail].n; + mData[mTail].sum = 0; + mData[mTail].n = 0; + ++mTail; + if (LL_UNLIKELY(mTail == mNrOfBuckets)) + { + mTail = 0; + } + } + while (mData[mTail].time <= old_time); + } + // This was set to zero when mTail passed this point (likely not this call, but a few calls ago). + llassert(mData[mCurrentBucket].sum == 0 && + mData[mCurrentBucket].n == 0); + } + mCurrentClock = clock_tick; + return; +} + diff --git a/indra/llmessage/aiaverage.h b/indra/llmessage/aiaverage.h new file mode 100644 index 000000000..f8f344df6 --- /dev/null +++ b/indra/llmessage/aiaverage.h @@ -0,0 +1,108 @@ +/** + * @file aiaverage.h + * @brief Definition of class AIAverage + * + * Copyright (c) 2013, Aleric Inglewood. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * 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. + * + * CHANGELOG + * and additional copyright holders. + * + * 11/04/2013 + * Initial version, written by Aleric Inglewood @ SL + */ + +#ifndef AIAVERAGE_H +#define AIAVERAGE_H + +#include "llpreprocessor.h" +#include "stdtypes.h" // U32, U64 +#include "llthread.h" // LLMutex +#include // size_t +#include + +class AIAverage { + private: + struct Data { + U32 sum; // Accumulated sum of the 'n' passed to operator()(size_t n, U64 clock_tick) with clock_tick == time. + U32 n; // The number of calls to operator(). + U64 time; // The clock_tick as passed to operator()(size_t n, U64 clock_tick) that sum corresponds to. + }; + + U64 mCurrentClock; // The current (last) time that operator() was called with, or -1 when not initialized. + int mTail; // The oldest bucket with still valid data. + int mCurrentBucket; // The bucket that corresponds to mCurrentClock. + size_t mSum; // The sum of all the 'n' passed to operator()(size_t n, U64 clock_tick) for all passed mNrOfBuckets time units. + U32 mN; // The number of calls to operator(). + int const mNrOfBuckets; // Size of mData. + std::vector mData; // The buckets. + 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) + { + // Fill mData with all zeroes (much faster than adding a constructor to Data). + std::memset(&*mData.begin(), 0, number_of_buckets * sizeof(Data)); + } + size_t addData(U32 n, U64 clock_tick) + { + DoutEntering(dc::curl, "AIAverage::addData(" << n << ", " << clock_tick << ")"); + mLock.lock(); + if (LL_UNLIKELY(clock_tick != mCurrentClock)) + { + cleanup(clock_tick); + } + mSum += n; + mN += 1; + mData[mCurrentBucket].sum += n; + mData[mCurrentBucket].n += 1; + size_t sum = mSum; + mLock.unlock(); + Dout(dc::curl, "Current sum: " << sum << ", average: " << (sum / mN)); + return sum; + } + size_t truncateData(U64 clock_tick) + { + mLock.lock(); + if (clock_tick != mCurrentClock) + { + cleanup(clock_tick); + } + size_t sum = mSum; + mLock.unlock(); + return sum; + } + double getAverage(double avg_no_data) + { + mLock.lock(); + double avg = mSum; + llassert(mN != 0 || mSum == 0); + if (LL_UNLIKELY(mN == 0)) + avg = avg_no_data; + else + avg /= mN; + mLock.unlock(); + return avg; + } + + private: + void cleanup(U64 clock_tick); +}; + +#endif // AIAVERAGE diff --git a/indra/llmessage/aicurl.cpp b/indra/llmessage/aicurl.cpp index 3e3e510e1..06c7f0ab4 100644 --- a/indra/llmessage/aicurl.cpp +++ b/indra/llmessage/aicurl.cpp @@ -58,7 +58,7 @@ #include "aihttpheaders.h" #include "aihttptimeoutpolicy.h" #include "aicurleasyrequeststatemachine.h" -#include "aicurlperhost.h" +#include "aicurlperservice.h" //================================================================================== // Debug Settings @@ -298,6 +298,7 @@ LLAtomicU32 Stats::easy_init_errors; LLAtomicU32 Stats::easy_cleanup_calls; LLAtomicU32 Stats::multi_calls; LLAtomicU32 Stats::multi_errors; +LLAtomicU32 Stats::running_handles; LLAtomicU32 Stats::AICurlEasyRequest_count; LLAtomicU32 Stats::AICurlEasyRequestStateMachine_count; LLAtomicU32 Stats::BufferedCurlEasyRequest_count; @@ -460,6 +461,12 @@ void setCAPath(std::string const& path) CertificateAuthority_w->path = path; } +// THREAD-SAFE +U32 getNumHTTPRunning(void) +{ + return Stats::running_handles; +} + //static void Stats::print(void) { @@ -952,9 +959,9 @@ CurlEasyRequest::~CurlEasyRequest() // be available anymore. send_handle_events_to(NULL); revokeCallbacks(); - if (mPerHostPtr) + if (mPerServicePtr) { - PerHostRequestQueue::release(mPerHostPtr); + AIPerService::release(mPerServicePtr); } // This wasn't freed yet if the request never finished. curl_slist_free_all(mHeaders); @@ -1084,56 +1091,6 @@ void CurlEasyRequest::applyDefaultOptions(void) ); } -// url must be of the form -// (see http://www.ietf.org/rfc/rfc3986.txt Appendix A for definitions not given here): -// -// url = sheme ":" hier-part [ "?" query ] [ "#" fragment ] -// hier-part = "//" authority path-abempty -// authority = [ userinfo "@" ] host [ ":" port ] -// path-abempty = *( "/" segment ) -// -// That is, a hier-part of the form '/ path-absolute', '/ path-rootless' or -// '/ path-empty' is NOT allowed here. This should be safe because we only -// call this function for curl access, any file access would use APR. -// -// However, as a special exception, this function allows: -// -// url = authority path-abempty -// -// without the 'sheme ":" "//"' parts. -// -// As follows from the ABNF (see RFC, Appendix A): -// - authority is either terminated by a '/' or by the end of the string because -// neither userinfo, host nor port may contain a '/'. -// - userinfo does not contain a '@', and if it exists, is always terminated by a '@'. -// - port does not contain a ':', and if it exists is always prepended by a ':'. -// -// Only called by CurlEasyRequest::finalizeRequest. -static std::string extract_canonical_hostname(std::string const& url) -{ - std::string::size_type pos; - std::string::size_type authority = 0; // Default if there is no sheme. - if ((pos = url.find("://")) != url.npos && pos < url.find('/')) authority = pos + 3; // Skip the "sheme://" if any, the second find is to avoid finding a "://" as part of path-abempty. - std::string::size_type host = authority; // Default if there is no userinfo. - if ((pos = url.find('@', authority)) != url.npos) host = pos + 1; // Skip the "userinfo@" if any. - authority = url.length() - 1; // Default last character of host if there is no path-abempty. - if ((pos = url.find('/', host)) != url.npos) authority = pos - 1; // Point to last character of host. - std::string::size_type len = url.find_last_not_of(":0123456789", authority) - host + 1; // Skip trailing ":port", if any. - std::string hostname(url, host, len); -#if APR_CHARSET_EBCDIC -#error Not implemented -#else - // Convert hostname to lowercase in a way that we compare two hostnames equal iff libcurl does. - for (std::string::iterator iter = hostname.begin(); iter != hostname.end(); ++iter) - { - int c = *iter; - if (c >= 'A' && c <= 'Z') - *iter = c + ('a' - 'A'); - } -#endif - return hostname; -} - void CurlEasyRequest::finalizeRequest(std::string const& url, AIHTTPTimeoutPolicy const& policy, AICurlEasyRequestStateMachine* state_machine) { DoutCurlEntering("CurlEasyRequest::finalizeRequest(\"" << url << "\", " << policy.name() << ", " << (void*)state_machine << ")"); @@ -1156,8 +1113,8 @@ void CurlEasyRequest::finalizeRequest(std::string const& url, AIHTTPTimeoutPolic #endif setopt(CURLOPT_HTTPHEADER, mHeaders); setoptString(CURLOPT_URL, url); - llassert(!mPerHostPtr); - mLowercaseHostname = extract_canonical_hostname(url); + llassert(!mPerServicePtr); + mLowercaseServicename = AIPerService::extract_canonical_servicename(url); mTimeoutPolicy = &policy; state_machine->setTotalDelayTimeout(policy.getTotalDelay()); // The following line is a bit tricky: we store a pointer to the object without increasing its reference count. @@ -1183,7 +1140,7 @@ void CurlEasyRequest::finalizeRequest(std::string const& url, AIHTTPTimeoutPolic // // get less connect time, while it still (also) has to wait for this DNS lookup. void CurlEasyRequest::set_timeout_opts(void) { - setopt(CURLOPT_CONNECTTIMEOUT, mTimeoutPolicy->getConnectTimeout(mLowercaseHostname)); + setopt(CURLOPT_CONNECTTIMEOUT, mTimeoutPolicy->getConnectTimeout(getLowercaseHostname())); setopt(CURLOPT_TIMEOUT, mTimeoutPolicy->getCurlTransaction()); } @@ -1279,22 +1236,27 @@ void CurlEasyRequest::queued_for_removal(AICurlEasyRequest_wat& curl_easy_reques } #endif -PerHostRequestQueuePtr CurlEasyRequest::getPerHostPtr(void) +AIPerServicePtr CurlEasyRequest::getPerServicePtr(void) { - if (!mPerHostPtr) + if (!mPerServicePtr) { - // mPerHostPtr is really just a speed-up cache. - // The reason we can cache it is because mLowercaseHostname is only set + // mPerServicePtr is really just a speed-up cache. + // The reason we can cache it is because mLowercaseServicename is only set // in finalizeRequest which may only be called once: it never changes. - mPerHostPtr = PerHostRequestQueue::instance(mLowercaseHostname); + mPerServicePtr = AIPerService::instance(mLowercaseServicename); } - return mPerHostPtr; + return mPerServicePtr; } -bool CurlEasyRequest::removeFromPerHostQueue(AICurlEasyRequest const& easy_request) const +bool CurlEasyRequest::removeFromPerServiceQueue(AICurlEasyRequest const& easy_request) const { // Note that easy_request (must) represent(s) this object; it's just passed for convenience. - return mPerHostPtr && PerHostRequestQueue_wat(*mPerHostPtr)->cancel(easy_request); + return mPerServicePtr && PerServiceRequestQueue_wat(*mPerServicePtr)->cancel(easy_request); +} + +std::string CurlEasyRequest::getLowercaseHostname(void) const +{ + return mLowercaseServicename.substr(0, mLowercaseServicename.find_last_of(':')); } //----------------------------------------------------------------------------- @@ -1305,8 +1267,9 @@ static int const HTTP_REDIRECTS_DEFAULT = 10; LLChannelDescriptors const BufferedCurlEasyRequest::sChannels; LLMutex BufferedCurlEasyRequest::sResponderCallbackMutex; bool BufferedCurlEasyRequest::sShuttingDown = false; +AIAverage BufferedCurlEasyRequest::sHTTPBandwidth(25); -BufferedCurlEasyRequest::BufferedCurlEasyRequest() : mRequestTransferedBytes(0), mResponseTransferedBytes(0), mBufferEventsTarget(NULL), mStatus(HTTP_INTERNAL_ERROR_OTHER) +BufferedCurlEasyRequest::BufferedCurlEasyRequest() : mRequestTransferedBytes(0), mTotalRawBytes(0), mBufferEventsTarget(NULL), mStatus(HTTP_INTERNAL_ERROR_OTHER) { AICurlInterface::Stats::BufferedCurlEasyRequest_count++; } @@ -1370,7 +1333,7 @@ void BufferedCurlEasyRequest::resetState(void) mOutput.reset(); mInput.reset(); mRequestTransferedBytes = 0; - mResponseTransferedBytes = 0; + mTotalRawBytes = 0; mBufferEventsTarget = NULL; mStatus = HTTP_INTERNAL_ERROR_OTHER; } diff --git a/indra/llmessage/aicurl.h b/indra/llmessage/aicurl.h index 9244839b7..d15c72cd8 100644 --- a/indra/llmessage/aicurl.h +++ b/indra/llmessage/aicurl.h @@ -52,6 +52,7 @@ #include "stdtypes.h" // U16, S32, U32, F64 #include "llatomic.h" // LLAtomicU32 #include "aithreadsafe.h" +#include "aicurlperservice.h" // AIPerServicePtr // Debug Settings. extern bool gNoVerifySSLCert; @@ -60,6 +61,7 @@ class LLSD; class LLBufferArray; class LLChannelDescriptors; class AIHTTPTimeoutPolicy; +class LLControlGroup; // Some pretty printing for curl easy handle related things: // Print the lock object related to the current easy handle in every debug output. @@ -133,6 +135,7 @@ struct Stats { static LLAtomicU32 easy_cleanup_calls; static LLAtomicU32 multi_calls; static LLAtomicU32 multi_errors; + static LLAtomicU32 running_handles; static LLAtomicU32 AICurlEasyRequest_count; static LLAtomicU32 AICurlEasyRequestStateMachine_count; static LLAtomicU32 BufferedCurlEasyRequest_count; @@ -153,7 +156,7 @@ struct Stats { // Called to handle changes in Debug Settings. bool handleCurlMaxTotalConcurrentConnections(LLSD const& newvalue); -bool handleCurlConcurrentConnectionsPerHost(LLSD const& newvalue); +bool handleCurlConcurrentConnectionsPerService(LLSD const& newvalue); bool handleNoVerifySSLCert(LLSD const& newvalue); // Called once at start of application (from newview/llappviewer.cpp by main thread (before threads are created)), @@ -161,7 +164,7 @@ bool handleNoVerifySSLCert(LLSD const& newvalue); void initCurl(void); // Called once at start of application (from LLAppViewer::initThreads), starts AICurlThread. -void startCurlThread(U32 CurlMaxTotalConcurrentConnections, U32 CurlConcurrentConnectionsPerHost, bool NoVerifySSLCert); +void startCurlThread(LLControlGroup* control_group); // Called once at the end of application before terminating other threads (most notably the texture thread workers) // with the purpose to stop the curl thread from doing any call backs to running responders: the responders sometimes @@ -185,6 +188,22 @@ void setCAFile(std::string const& file); // Can be used to set the path to the Certificate Authority file. void setCAPath(std::string const& file); +// Returns number of queued 'add' commands minus the number of queued 'remove' commands. +U32 getNumHTTPCommands(void); + +// Returns the number of queued requests. +U32 getNumHTTPQueued(void); + +// Returns the number of curl requests currently added to the multi handle. +U32 getNumHTTPAdded(void); + +// This used to be LLAppViewer::getTextureFetch()->getNumHTTPRequests(). +// Returns the number of active curl easy handles (that are actually attempting to download something). +U32 getNumHTTPRunning(void); + +// Cache for gSavedSettings so we have access from llmessage. +extern LLControlGroup* sConfigGroup; + } // namespace AICurlInterface // Forward declaration (see aicurlprivate.h). diff --git a/indra/llmessage/aicurlperhost.cpp b/indra/llmessage/aicurlperhost.cpp deleted file mode 100644 index b444ba6df..000000000 --- a/indra/llmessage/aicurlperhost.cpp +++ /dev/null @@ -1,175 +0,0 @@ -/** - * @file aiperhost.cpp - * @brief Implementation of PerHostRequestQueue - * - * Copyright (c) 2012, Aleric Inglewood. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * This program 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * 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. - * - * CHANGELOG - * and additional copyright holders. - * - * 04/11/2012 - * Initial version, written by Aleric Inglewood @ SL - */ - -#include "sys.h" -#include "aicurlperhost.h" -#include "aicurlthread.h" - -#undef AICurlPrivate - -namespace AICurlPrivate { - -PerHostRequestQueue::threadsafe_instance_map_type PerHostRequestQueue::sInstanceMap; -U32 curl_concurrent_connections_per_host; - -//static -PerHostRequestQueuePtr PerHostRequestQueue::instance(std::string const& hostname) -{ - llassert(!hostname.empty()); - instance_map_wat instance_map_w(sInstanceMap); - PerHostRequestQueue::iterator iter = instance_map_w->find(hostname); - if (iter == instance_map_w->end()) - { - iter = instance_map_w->insert(instance_map_type::value_type(hostname, new RefCountedThreadSafePerHostRequestQueue)).first; - } - // Note: the creation of PerHostRequestQueuePtr MUST be protected by the lock on sInstanceMap (see release()). - return iter->second; -} - -//static -void PerHostRequestQueue::release(PerHostRequestQueuePtr& instance) -{ - if (instance->exactly_two_left()) // Being 'instance' and the one in sInstanceMap. - { - // The viewer can be have left main() we can't access the global sInstanceMap anymore. - if (LLApp::isStopped()) - { - return; - } - instance_map_wat instance_map_w(sInstanceMap); - // It is possible that 'exactly_two_left' is not up to date anymore. - // Therefore, recheck the condition now that we have locked sInstanceMap. - if (!instance->exactly_two_left()) - { - // Some other thread added this host 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(PerHostRequestQueue_wat(*instance)->mQueuedRequests.empty()); - // Find the host and erase it from the map. - iterator const end = instance_map_w->end(); - for(iterator iter = instance_map_w->begin(); iter != end; ++iter) - { - if (instance == iter->second) - { - instance_map_w->erase(iter); - instance.reset(); - return; - } - } - // We should always find the host. - llassert(false); - } - instance.reset(); -} - -bool PerHostRequestQueue::throttled() const -{ - llassert(mAdded <= int(curl_concurrent_connections_per_host)); - return mAdded == int(curl_concurrent_connections_per_host); -} - -void PerHostRequestQueue::added_to_multi_handle(void) -{ - llassert(mAdded < int(curl_concurrent_connections_per_host)); - ++mAdded; -} - -void PerHostRequestQueue::removed_from_multi_handle(void) -{ - --mAdded; - llassert(mAdded >= 0); -} - -void PerHostRequestQueue::queue(AICurlEasyRequest const& easy_request) -{ - mQueuedRequests.push_back(easy_request.get_ptr()); -} - -bool PerHostRequestQueue::cancel(AICurlEasyRequest const& easy_request) -{ - queued_request_type::iterator const end = mQueuedRequests.end(); - queued_request_type::iterator cur = std::find(mQueuedRequests.begin(), end, easy_request.get_ptr()); - - if (cur == end) - return false; // Not found. - - // We can't use erase because that uses assignment to move elements, - // because it isn't thread-safe. Therefore, move the element that we found to - // the back with swap (could just swap with the end immediately, but I don't - // 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 PerHostRequestQueue object. - queued_request_type::iterator prev = cur; - while (++cur != end) - { - prev->swap(*cur); // This is safe, - prev = cur; - } - mQueuedRequests.pop_back(); // if this is safe. - return true; -} - -void PerHostRequestQueue::add_queued_to(curlthread::MultiHandle* multi_handle) -{ - if (!mQueuedRequests.empty()) - { - multi_handle->add_easy_request(mQueuedRequests.front()); - mQueuedRequests.pop_front(); - } -} - -//static -void PerHostRequestQueue::purge(void) -{ - instance_map_wat instance_map_w(sInstanceMap); - for (iterator host = instance_map_w->begin(); host != instance_map_w->end(); ++host) - { - Dout(dc::curl, "Purging queue of host \"" << host->first << "\"."); - PerHostRequestQueue_wat(*host->second)->mQueuedRequests.clear(); - } -} - -// Friend functions of RefCountedThreadSafePerHostRequestQueue - -void intrusive_ptr_add_ref(RefCountedThreadSafePerHostRequestQueue* per_host) -{ - per_host->mReferenceCount++; -} - -void intrusive_ptr_release(RefCountedThreadSafePerHostRequestQueue* per_host) -{ - if (--per_host->mReferenceCount == 0) - { - delete per_host; - } -} - -} // namespace AICurlPrivate diff --git a/indra/llmessage/aicurlperhost.h b/indra/llmessage/aicurlperhost.h deleted file mode 100644 index c464d490c..000000000 --- a/indra/llmessage/aicurlperhost.h +++ /dev/null @@ -1,135 +0,0 @@ -/** - * @file aicurlperhost.h - * @brief Definition of class PerHostRequestQueue - * - * Copyright (c) 2012, Aleric Inglewood. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * This program 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * 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. - * - * CHANGELOG - * and additional copyright holders. - * - * 04/11/2012 - * Initial version, written by Aleric Inglewood @ SL - */ - -#ifndef AICURLPERHOST_H -#define AICURLPERHOST_H - -#include "llerror.h" // llassert -#include -#include -#include -#include -#include "aithreadsafe.h" - -class AICurlEasyRequest; - -namespace AICurlPrivate { -namespace curlthread { class MultiHandle; } - -class PerHostRequestQueue; -class RefCountedThreadSafePerHostRequestQueue; -class ThreadSafeBufferedCurlEasyRequest; - -// Forward declaration of BufferedCurlEasyRequestPtr (see aicurlprivate.h). -typedef boost::intrusive_ptr BufferedCurlEasyRequestPtr; - -// PerHostRequestQueue objects are created by the curl thread and destructed by the main thread. -// We need locking. -typedef AIThreadSafeSimpleDC threadsafe_PerHostRequestQueue; -typedef AIAccessConst PerHostRequestQueue_crat; -typedef AIAccess PerHostRequestQueue_rat; -typedef AIAccess PerHostRequestQueue_wat; - -// We can't put threadsafe_PerHostRequestQueue in a std::map because you can't copy a mutex. -// Therefore, use an intrusive pointer for the threadsafe type. -typedef boost::intrusive_ptr PerHostRequestQueuePtr; - -//----------------------------------------------------------------------------- -// PerHostRequestQueue - -// This class provides a static interface to create and maintain instances -// of PerHostRequestQueue objects, so that at any moment there is at most -// one instance per hostname. Those instances then are used to queue curl -// requests when the maximum number of connections for that host already -// have been reached. -class PerHostRequestQueue { - private: - typedef std::map instance_map_type; - typedef AIThreadSafeSimpleDC threadsafe_instance_map_type; - typedef AIAccess instance_map_rat; - typedef AIAccess instance_map_wat; - - static threadsafe_instance_map_type sInstanceMap; // Map of PerHostRequestQueue instances with the hostname as key. - - friend class AIThreadSafeSimpleDC; //threadsafe_PerHostRequestQueue - PerHostRequestQueue(void) : mAdded(0) { } - - public: - typedef instance_map_type::iterator iterator; - typedef instance_map_type::const_iterator const_iterator; - - // Return (possibly create) a unique instance for the given hostname. - static PerHostRequestQueuePtr instance(std::string const& hostname); - - // Release instance (object will be deleted if this was the last instance). - static void release(PerHostRequestQueuePtr& instance); - - // Remove everything. Called upon viewer exit. - static void purge(void); - - private: - typedef std::deque queued_request_type; - - int mAdded; // Number of active easy handles with this host. - queued_request_type mQueuedRequests; // Waiting (throttled) requests. - - public: - 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. - 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 add_queued_to(curlthread::MultiHandle* mh); // 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. - private: - // Disallow copying. - PerHostRequestQueue(PerHostRequestQueue const&) { } -}; - -class RefCountedThreadSafePerHostRequestQueue : public threadsafe_PerHostRequestQueue { - public: - RefCountedThreadSafePerHostRequestQueue(void) : mReferenceCount(0) { } - bool exactly_two_left(void) const { return mReferenceCount == 2; } - - private: - // Used by PerHostRequestQueuePtr. Object is deleted when reference count reaches zero. - LLAtomicU32 mReferenceCount; - - friend void intrusive_ptr_add_ref(RefCountedThreadSafePerHostRequestQueue* p); - friend void intrusive_ptr_release(RefCountedThreadSafePerHostRequestQueue* p); -}; - -extern U32 curl_concurrent_connections_per_host; - -} // namespace AICurlPrivate - -#endif // AICURLPERHOST_H diff --git a/indra/llmessage/aicurlperservice.cpp b/indra/llmessage/aicurlperservice.cpp new file mode 100644 index 000000000..28721c1e9 --- /dev/null +++ b/indra/llmessage/aicurlperservice.cpp @@ -0,0 +1,356 @@ +/** + * @file aiperservice.cpp + * @brief Implementation of AIPerService + * + * Copyright (c) 2012, 2013, Aleric Inglewood. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * 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. + * + * CHANGELOG + * and additional copyright holders. + * + * 04/11/2012 + * Initial version, written by Aleric Inglewood @ SL + * + * 06/04/2013 + * Renamed AICurlPrivate::PerHostRequestQueue[Ptr] to AIPerHostRequestQueue[Ptr] + * to allow public access. + * + * 09/04/2013 + * Renamed everything "host" to "service" and use "hostname:port" as key + * instead of just "hostname". + */ + +#include "sys.h" +#include "aicurlperservice.h" +#include "aicurlthread.h" +#include "llcontrol.h" + +AIPerService::threadsafe_instance_map_type AIPerService::sInstanceMap; +LLAtomicS32 AIPerService::sTotalQueued; +bool AIPerService::sQueueEmpty; +bool AIPerService::sQueueFull; +bool AIPerService::sRequestStarvation; + +#undef AICurlPrivate + +namespace AICurlPrivate { + +// Cached value of CurlConcurrentConnectionsPerService. +U32 CurlConcurrentConnectionsPerService; + +// Friend functions of RefCountedThreadSafePerServiceRequestQueue + +void intrusive_ptr_add_ref(RefCountedThreadSafePerServiceRequestQueue* per_service) +{ + per_service->mReferenceCount++; +} + +void intrusive_ptr_release(RefCountedThreadSafePerServiceRequestQueue* per_service) +{ + if (--per_service->mReferenceCount == 0) + { + delete per_service; + } +} + +} // namespace AICurlPrivate + +using namespace AICurlPrivate; + +AIPerService::AIPerService(void) : + mQueuedCommands(0), mAdded(0), mQueueEmpty(false), + mQueueFull(false), mRequestStarvation(false), mHTTPBandwidth(25), // 25 = 1000 ms / 40 ms. + mConcurrectConnections(CurlConcurrentConnectionsPerService), + mMaxPipelinedRequests(CurlConcurrentConnectionsPerService) +{ +} + +AIPerService::~AIPerService() +{ +} + +// Fake copy constructor. +AIPerService::AIPerService(AIPerService const&) : mHTTPBandwidth(0) +{ +} + +// url must be of the form +// (see http://www.ietf.org/rfc/rfc3986.txt Appendix A for definitions not given here): +// +// url = sheme ":" hier-part [ "?" query ] [ "#" fragment ] +// hier-part = "//" authority path-abempty +// authority = [ userinfo "@" ] host [ ":" port ] +// path-abempty = *( "/" segment ) +// +// That is, a hier-part of the form '/ path-absolute', '/ path-rootless' or +// '/ path-empty' is NOT allowed here. This should be safe because we only +// call this function for curl access, any file access would use APR. +// +// However, as a special exception, this function allows: +// +// url = authority path-abempty +// +// without the 'sheme ":" "//"' parts. +// +// As follows from the ABNF (see RFC, Appendix A): +// - authority is either terminated by a '/' or by the end of the string because +// neither userinfo, host nor port may contain a '/'. +// - userinfo does not contain a '@', and if it exists, is always terminated by a '@'. +// - port does not contain a ':', and if it exists is always prepended by a ':'. +// +//static +std::string AIPerService::extract_canonical_servicename(std::string const& url) +{ + char const* p = url.data(); + char const* const end = p + url.size(); + char const* sheme_colon = NULL; + char const* sheme_slash = NULL; + char const* first_ampersand = NULL; + char const* port_colon = NULL; + std::string servicename; + char const* hostname = p; // Default in the case there is no "sheme://userinfo@". + while (p < end) + { + int c = *p; + if (c == ':') + { + if (!port_colon && LLStringOps::isDigit(p[1])) + { + port_colon = p; + } + else if (!sheme_colon && !sheme_slash && !first_ampersand && !port_colon) + { + // Found a colon before any slash or ampersand: this has to be the colon between the sheme and the hier-part. + sheme_colon = p; + } + } + else if (c == '/') + { + if (!sheme_slash && sheme_colon && sheme_colon == p - 1 && !first_ampersand && p[1] == '/') + { + // Found the first '/' in the first occurance of the sequence "://". + sheme_slash = p; + hostname = ++p + 1; // Point hostname to the start of the authority, the default when there is no "userinfo@" part. + servicename.clear(); // Remove the sheme. + } + else + { + // Found slash that is not part of the "sheme://" string. Signals end of authority. + // We're done. + break; + } + } + else if (c == '@') + { + if (!first_ampersand) + { + first_ampersand = p; + hostname = p + 1; + servicename.clear(); // Remove the "userinfo@" + } + } + if (p >= hostname) + { + // Convert hostname to lowercase in a way that we compare two hostnames equal iff libcurl does. +#if APR_CHARSET_EBCDIC +#error Not implemented +#else + if (c >= 'A' && c <= 'Z') + c += ('a' - 'A'); +#endif + servicename += c; + } + ++p; + } + // Strip of any trailing ":80". + if (p - 3 == port_colon && p[-1] == '0' && p[-2] == '8') + { + return servicename.substr(0, p - hostname - 3); + } + return servicename; +} + +//static +AIPerServicePtr AIPerService::instance(std::string const& servicename) +{ + llassert(!servicename.empty()); + instance_map_wat instance_map_w(sInstanceMap); + 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; + } + // Note: the creation of AIPerServicePtr MUST be protected by the lock on sInstanceMap (see release()). + return iter->second; +} + +//static +void AIPerService::release(AIPerServicePtr& instance) +{ + if (instance->exactly_two_left()) // Being 'instance' and the one in sInstanceMap. + { + // The viewer can be have left main() we can't access the global sInstanceMap anymore. + if (LLApp::isStopped()) + { + return; + } + instance_map_wat instance_map_w(sInstanceMap); + // It is possible that 'exactly_two_left' is not up to date anymore. + // Therefore, recheck the condition now that we have locked sInstanceMap. + if (!instance->exactly_two_left()) + { + // Some other thread added this host 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. + iterator const end = instance_map_w->end(); + for(iterator iter = instance_map_w->begin(); iter != end; ++iter) + { + if (instance == iter->second) + { + instance_map_w->erase(iter); + instance.reset(); + return; + } + } + // We should always find the host. + llassert(false); + } + instance.reset(); +} + +bool AIPerService::throttled() const +{ + return mAdded >= mConcurrectConnections; +} + +void AIPerService::added_to_multi_handle(void) +{ + ++mAdded; +} + +void AIPerService::removed_from_multi_handle(void) +{ + --mAdded; + llassert(mAdded >= 0); +} + +void AIPerService::queue(AICurlEasyRequest const& easy_request) +{ + mQueuedRequests.push_back(easy_request.get_ptr()); + sTotalQueued++; +} + +bool AIPerService::cancel(AICurlEasyRequest const& easy_request) +{ + queued_request_type::iterator const end = mQueuedRequests.end(); + queued_request_type::iterator cur = std::find(mQueuedRequests.begin(), end, easy_request.get_ptr()); + + if (cur == end) + return false; // Not found. + + // We can't use erase because that uses assignment to move elements, + // because it isn't thread-safe. Therefore, move the element that we found to + // the back with swap (could just swap with the end immediately, but I don't + // 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; + while (++cur != end) + { + prev->swap(*cur); // This is safe, + prev = cur; + } + mQueuedRequests.pop_back(); // if this is safe. + --sTotalQueued; + llassert(sTotalQueued >= 0); + return true; +} + +void AIPerService::add_queued_to(curlthread::MultiHandle* multi_handle) +{ + if (!mQueuedRequests.empty()) + { + 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; + } + } + else + { + // We can add a new request, but there is none in the queue! + mRequestStarvation = true; + if (sTotalQueued == 0) + { + // The queue of every host is empty! + sRequestStarvation = true; + } + } +} + +//static +void AIPerService::purge(void) +{ + instance_map_wat instance_map_w(sInstanceMap); + for (iterator host = instance_map_w->begin(); host != instance_map_w->end(); ++host) + { + 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); + } +} + +//static +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); + 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); + } +} + diff --git a/indra/llmessage/aicurlperservice.h b/indra/llmessage/aicurlperservice.h new file mode 100644 index 000000000..20271aeb3 --- /dev/null +++ b/indra/llmessage/aicurlperservice.h @@ -0,0 +1,187 @@ +/** + * @file aicurlperservice.h + * @brief Definition of class AIPerService + * + * Copyright (c) 2012, 2013, Aleric Inglewood. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * 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. + * + * CHANGELOG + * and additional copyright holders. + * + * 04/11/2012 + * Initial version, written by Aleric Inglewood @ SL + * + * 06/04/2013 + * Renamed AIPrivate::PerHostRequestQueue[Ptr] to AIPerHostRequestQueue[Ptr] + * to allow public access. + * + * 09/04/2013 + * Renamed everything "host" to "service" and use "hostname:port" as key + * instead of just "hostname". + */ + +#ifndef AICURLPERSERVICE_H +#define AICURLPERSERVICE_H + +#include "llerror.h" // llassert +#include +#include +#include +#include +#include "aithreadsafe.h" +#include "aiaverage.h" + +class AICurlEasyRequest; +class AIPerService; + +namespace AICurlPrivate { +namespace curlthread { class MultiHandle; } + +class RefCountedThreadSafePerServiceRequestQueue; +class ThreadSafeBufferedCurlEasyRequest; + +// Forward declaration of BufferedCurlEasyRequestPtr (see aicurlprivate.h). +typedef boost::intrusive_ptr BufferedCurlEasyRequestPtr; + +// AIPerService objects are created by the curl thread and destructed by the main thread. +// We need locking. +typedef AIThreadSafeSimpleDC threadsafe_PerServiceRequestQueue; +typedef AIAccessConst PerServiceRequestQueue_crat; +typedef AIAccess PerServiceRequestQueue_rat; +typedef AIAccess PerServiceRequestQueue_wat; + +} // namespace AICurlPrivate + +// We can't put threadsafe_PerServiceRequestQueue in a std::map because you can't copy a mutex. +// Therefore, use an intrusive pointer for the threadsafe type. +typedef boost::intrusive_ptr AIPerServicePtr; + +//----------------------------------------------------------------------------- +// 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. +class AIPerService { + private: + typedef std::map instance_map_type; + typedef AIThreadSafeSimpleDC threadsafe_instance_map_type; + typedef AIAccess instance_map_rat; + typedef AIAccess instance_map_wat; + + static threadsafe_instance_map_type sInstanceMap; // Map of AIPerService instances with the hostname as key. + + friend class AIThreadSafeSimpleDC; //threadsafe_PerServiceRequestQueue + AIPerService(void); + + public: + ~AIPerService(); + + public: + typedef instance_map_type::iterator iterator; + typedef instance_map_type::const_iterator const_iterator; + + // Utility function; extract canonical (lowercase) hostname and port from url. + static std::string extract_canonical_servicename(std::string const& url); + + // Return (possibly create) a unique instance for the given hostname. + static AIPerServicePtr instance(std::string const& servicename); + + // Release instance (object will be deleted if this was the last instance). + static void release(AIPerServicePtr& instance); + + // Remove everything. Called upon viewer exit. + static void purge(void); + + private: + typedef std::deque queued_request_type; + + 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. + + static LLAtomicS32 sTotalQueued; // The sum of mQueuedRequests.size() of all AIPerService objects together. + + 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. + + 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. + + 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. + + 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. + 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 add_queued_to(AICurlPrivate::curlthread::MultiHandle* mh); + // 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; } + + AIAverage& bandwidth(void) { return mHTTPBandwidth; } + AIAverage const& bandwidth(void) const { return mHTTPBandwidth; } + + // 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 + // the latency between request and actual delivery becomes too large. + static bool wantsMoreHTTPRequestsFor(AIPerServicePtr const& per_service, F32 max_kbps, bool no_bandwidth_throttling); + + private: + // Disallow copying. + AIPerService(AIPerService const&); +}; + +namespace AICurlPrivate { + +class RefCountedThreadSafePerServiceRequestQueue : public threadsafe_PerServiceRequestQueue { + public: + RefCountedThreadSafePerServiceRequestQueue(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); +}; + +extern U32 CurlConcurrentConnectionsPerService; + +} // namespace AICurlPrivate + +#endif // AICURLPERSERVICE_H diff --git a/indra/llmessage/aicurlprivate.h b/indra/llmessage/aicurlprivate.h index cfd4b5d91..57e6d9210 100644 --- a/indra/llmessage/aicurlprivate.h +++ b/indra/llmessage/aicurlprivate.h @@ -34,7 +34,7 @@ #include #include "llatomic.h" #include "llrefcount.h" -#include "aicurlperhost.h" +#include "aicurlperservice.h" #include "aihttptimeout.h" #include "llhttpclient.h" @@ -304,8 +304,8 @@ class CurlEasyRequest : public CurlEasyHandle { CURLcode mResult; //AIFIXME: this does not belong in the request object, but belongs in the response object. AIHTTPTimeoutPolicy const* mTimeoutPolicy; - std::string mLowercaseHostname; // Lowercase hostname (canonicalized) extracted from the url. - PerHostRequestQueuePtr mPerHostPtr; // Pointer to the corresponding PerHostRequestQueue. + std::string mLowercaseServicename; // Lowercase hostname:port (canonicalized) extracted from the url. + AIPerServicePtr mPerServicePtr; // Pointer to the corresponding AIPerService. LLPointer mTimeout;// Timeout administration object associated with last created CurlSocketInfo. bool mTimeoutIsOrphan; // Set to true when mTimeout is not (yet) associated with a CurlSocketInfo. #if defined(CWDEBUG) || defined(DEBUG_CURLIO) @@ -316,7 +316,8 @@ class CurlEasyRequest : public CurlEasyHandle { public: // These two are only valid after finalizeRequest. AIHTTPTimeoutPolicy const* getTimeoutPolicy(void) const { return mTimeoutPolicy; } - std::string const& getLowercaseHostname(void) const { return mLowercaseHostname; } + std::string const& getLowercaseServicename(void) const { return mLowercaseServicename; } + std::string getLowercaseHostname(void) const; // Called by CurlSocketInfo to allow access to the last (after a redirect) HTTPTimeout object related to this request. // This creates mTimeout (unless mTimeoutIsOrphan is set in which case it adopts the orphan). LLPointer& get_timeout_object(void); @@ -347,10 +348,10 @@ class CurlEasyRequest : public CurlEasyHandle { inline ThreadSafeBufferedCurlEasyRequest* get_lockobj(void); inline ThreadSafeBufferedCurlEasyRequest const* get_lockobj(void) const; - // PerHost API. - PerHostRequestQueuePtr getPerHostPtr(void); // (Optionally create and) return a pointer to the unique - // PerHostRequestQueue corresponding to mLowercaseHostname. - bool removeFromPerHostQueue(AICurlEasyRequest const&) const; // Remove this request from the per-host queue, if queued at all. + // 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. protected: // Pass events to parent. @@ -395,6 +396,9 @@ class BufferedCurlEasyRequest : public CurlEasyRequest { // Post-initialization, set the parent to pass the events to. void send_buffer_events_to(AIBufferedCurlEasyRequestEvents* target) { mBufferEventsTarget = target; } + // Called whenever new body data was (might be) received. Keeps track of the used HTTP bandwidth. + void update_body_bandwidth(void); + protected: // Events from this class. /*virtual*/ void received_HTTP_header(void); @@ -410,13 +414,14 @@ class BufferedCurlEasyRequest : public CurlEasyRequest { U32 mStatus; // HTTP status, decoded from the first header line. std::string mReason; // The "reason" from the same header line. U32 mRequestTransferedBytes; - U32 mResponseTransferedBytes; + size_t mTotalRawBytes; // Raw body data (still, possibly, compressed) received from the server so far. AIBufferedCurlEasyRequestEvents* mBufferEventsTarget; public: static LLChannelDescriptors const sChannels; // Channel object for mInput (channel out()) and mOutput (channel in()). static LLMutex sResponderCallbackMutex; // Locked while calling back any overridden ResponderBase::finished and/or accessing sShuttingDown. static bool sShuttingDown; // If true, no additional calls to ResponderBase::finished will be made anymore. + static AIAverage sHTTPBandwidth; // HTTP bandwidth usage of all services combined. private: // This class may only be created by constructing a ThreadSafeBufferedCurlEasyRequest. diff --git a/indra/llmessage/aicurlthread.cpp b/indra/llmessage/aicurlthread.cpp index 64b35c683..8b4f1a022 100644 --- a/indra/llmessage/aicurlthread.cpp +++ b/indra/llmessage/aicurlthread.cpp @@ -32,10 +32,12 @@ #include "aicurlthread.h" #include "aihttptimeoutpolicy.h" #include "aihttptimeout.h" -#include "aicurlperhost.h" +#include "aicurlperservice.h" +#include "aiaverage.h" #include "lltimer.h" // ms_sleep, get_clock_count #include "llhttpstatuscodes.h" #include "llbuffer.h" +#include "llcontrol.h" #include #if !LL_WINDOWS #include @@ -204,6 +206,8 @@ int ioctlsocket(int fd, int, unsigned long* nonblocking_enable) namespace AICurlPrivate { +LLAtomicS32 max_pipelined_requests(32); + enum command_st { cmd_none, cmd_add, @@ -264,9 +268,15 @@ void Command::reset(void) // // If at this point addRequest is called again, then it is detected that the ThreadSafeBufferedCurlEasyRequest is active. +struct command_queue_st { + std::deque commands; // The commands + size_t size; // Number of add commands in the queue minus the number of remove commands. +}; + // Multi-threaded queue for passing Command objects from the main-thread to the curl-thread. -AIThreadSafeSimpleDC > command_queue; -typedef AIAccess > command_queue_wat; +AIThreadSafeSimpleDC command_queue; // Fills 'size' with zero, because it's a global. +typedef AIAccess command_queue_wat; +typedef AIAccess command_queue_rat; AIThreadSafeDC command_being_processed; typedef AIWriteAccess command_being_processed_wat; @@ -1289,7 +1299,7 @@ void AICurlThread::process_commands(AICurlMultiHandle_wat const& multi_handle_w) // Access command_queue, and move command to command_being_processed. { command_queue_wat command_queue_w(command_queue); - if (command_queue_w->empty()) + if (command_queue_w->commands.empty()) { mWakeUpFlagMutex.lock(); mWakeUpFlag = false; @@ -1297,8 +1307,22 @@ void AICurlThread::process_commands(AICurlMultiHandle_wat const& multi_handle_w) break; } // Move the next command from the queue into command_being_processed. - *command_being_processed_wat(command_being_processed) = command_queue_w->front(); - command_queue_w->pop_front(); + command_st command; + { + command_being_processed_wat command_being_processed_w(command_being_processed); + *command_being_processed_w = command_queue_w->commands.front(); + command = command_being_processed_w->command(); + } + // Update the size: the number netto number of pending requests in the command queue. + command_queue_w->commands.pop_front(); + if (command == cmd_add) + { + command_queue_w->size--; + } + else if (command == cmd_remove) + { + command_queue_w->size++; + } } // Access command_being_processed only. { @@ -1309,9 +1333,11 @@ void AICurlThread::process_commands(AICurlMultiHandle_wat const& multi_handle_w) 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())); 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'. multi_handle_w->remove_easy_request(AICurlEasyRequest(command_being_processed_r->easy_request()), true); break; } @@ -1520,8 +1546,8 @@ void AICurlThread::run(void) continue; } // Clock count used for timeouts. - HTTPTimeout::sClockCount = get_clock_count(); - Dout(dc::curl, "HTTPTimeout::sClockCount = " << HTTPTimeout::sClockCount); + HTTPTimeout::sTime_10ms = get_clock_count() * HTTPTimeout::sClockWidth_10ms; + Dout(dc::curl, "HTTPTimeout::sTime_10ms = " << HTTPTimeout::sTime_10ms); if (ready == 0) { multi_handle_w->socket_action(CURL_SOCKET_TIMEOUT, 0); @@ -1553,7 +1579,7 @@ void AICurlThread::run(void) multi_handle_w->check_msg_queue(); } // Clear the queued requests. - PerHostRequestQueue::purge(); + AIPerService::purge(); } AICurlMultiHandle::destroyInstance(); } @@ -1561,6 +1587,8 @@ void AICurlThread::run(void) //----------------------------------------------------------------------------- // MultiHandle +LLAtomicU32 MultiHandle::sTotalAdded; + MultiHandle::MultiHandle(void) : mTimeout(-1), mReadPollSet(NULL), mWritePollSet(NULL) { mReadPollSet = new PollSet; @@ -1653,6 +1681,7 @@ CURLMcode MultiHandle::socket_action(curl_socket_t sockfd, int ev_bitmask) } while(res == CURLM_CALL_MULTI_PERFORM); llassert(mAddedEasyRequests.size() >= (size_t)running_handles); + AICurlInterface::Stats::running_handles = running_handles; return res; } @@ -1677,17 +1706,17 @@ static U32 curl_max_total_concurrent_connections = 32; // Initialized on st void MultiHandle::add_easy_request(AICurlEasyRequest const& easy_request) { bool throttled = true; // Default. - PerHostRequestQueuePtr per_host; + AIPerServicePtr per_service; { AICurlEasyRequest_wat curl_easy_request_w(*easy_request); - per_host = curl_easy_request_w->getPerHostPtr(); - PerHostRequestQueue_wat per_host_w(*per_host); - if (mAddedEasyRequests.size() < curl_max_total_concurrent_connections && !per_host_w->throttled()) + 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()) { curl_easy_request_w->set_timeout_opts(); if (curl_easy_request_w->add_handle_to_multi(curl_easy_request_w, mMultiHandle) == CURLM_OK) { - per_host_w->added_to_multi_handle(); // (About to be) added to mAddedEasyRequests. + per_service_w->added_to_multi_handle(); // (About to be) added to mAddedEasyRequests. throttled = false; // Fall through... } } @@ -1696,11 +1725,14 @@ void MultiHandle::add_easy_request(AICurlEasyRequest const& easy_request) { // ... to here. std::pair res = mAddedEasyRequests.insert(easy_request); llassert(res.second); // May not have been added before. - Dout(dc::curl, "MultiHandle::add_easy_request: Added AICurlEasyRequest " << (void*)easy_request.get_ptr().get() << "; now processing " << mAddedEasyRequests.size() << " easy handles."); + 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; } // The request could not be added, we have to queue it. - PerHostRequestQueue_wat(*per_host)->queue(easy_request); + PerServiceRequestQueue_wat(*per_service)->queue(easy_request); #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; @@ -1717,7 +1749,7 @@ CURLMcode MultiHandle::remove_easy_request(AICurlEasyRequest const& easy_request #ifdef SHOW_ASSERT bool removed = #endif - easy_request_w->removeFromPerHostQueue(easy_request); + easy_request_w->removeFromPerServiceQueue(easy_request); #ifdef SHOW_ASSERT if (removed) { @@ -1733,12 +1765,12 @@ 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; - PerHostRequestQueuePtr per_host; + AIPerServicePtr per_service; { AICurlEasyRequest_wat curl_easy_request_w(**iter); res = curl_easy_request_w->remove_handle_from_multi(curl_easy_request_w, mMultiHandle); - per_host = curl_easy_request_w->getPerHostPtr(); - PerHostRequestQueue_wat(*per_host)->removed_from_multi_handle(); // (About to be) removed from mAddedEasyRequests. + per_service = curl_easy_request_w->getPerServicePtr(); + PerServiceRequestQueue_wat(*per_service)->removed_from_multi_handle(); // (About to be) removed from mAddedEasyRequests. #ifdef SHOW_ASSERT curl_easy_request_w->mRemovedPerCommand = as_per_command; #endif @@ -1747,12 +1779,15 @@ CURLMcode MultiHandle::remove_easy_request(addedEasyRequests_type::iterator cons ThreadSafeBufferedCurlEasyRequest* lockobj = iter->get_ptr().get(); #endif mAddedEasyRequests.erase(iter); + --sTotalAdded; + llassert(sTotalAdded == mAddedEasyRequests.size()); #if CWDEBUG - Dout(dc::curl, "MultiHandle::remove_easy_request: Removed AICurlEasyRequest " << (void*)lockobj << "; now processing " << mAddedEasyRequests.size() << " easy handles."); + Dout(dc::curl, "MultiHandle::remove_easy_request: Removed AICurlEasyRequest " << (void*)lockobj << + "; now processing " << mAddedEasyRequests.size() << " easy handles [running_handles = " << AICurlInterface::Stats::running_handles << "]."); #endif // Attempt to add a queued request, if any. - PerHostRequestQueue_wat(*per_host)->add_queued_to(this); + PerServiceRequestQueue_wat(*per_service)->add_queued_to(this); return res; } @@ -1795,6 +1830,8 @@ void MultiHandle::check_msg_queue(void) void MultiHandle::finish_easy_request(AICurlEasyRequest const& easy_request, CURLcode result) { AICurlEasyRequest_wat curl_easy_request_w(*easy_request); + // Final body bandwidth update. + curl_easy_request_w->update_body_bandwidth(); // Store the result in the easy handle. curl_easy_request_w->storeResult(result); #ifdef CWDEBUG @@ -1926,7 +1963,8 @@ void clearCommandQueue(void) { // Clear the command queue now in order to avoid the global deinitialization order fiasco. command_queue_wat command_queue_w(command_queue); - command_queue_w->clear(); + command_queue_w->commands.clear(); + command_queue_w->size = 0; } //----------------------------------------------------------------------------- @@ -1988,10 +2026,10 @@ void BufferedCurlEasyRequest::processOutput(void) if (responseCode == HTTP_INTERNAL_ERROR_LOW_SPEED) { // Rewrite error to something understandable. - responseReason = llformat("Connection to \"%s\" stalled: download speed dropped below %u bytes/s for %u seconds (up till that point, %s received a total of %u bytes). " + responseReason = llformat("Connection to \"%s\" stalled: download speed dropped below %u bytes/s for %u seconds (up till that point, %s received a total of %lu bytes). " "To change these values, go to Advanced --> Debug Settings and change CurlTimeoutLowSpeedLimit and CurlTimeoutLowSpeedTime respectively.", mResponder->getURL().c_str(), mResponder->getHTTPTimeoutPolicy().getLowSpeedLimit(), mResponder->getHTTPTimeoutPolicy().getLowSpeedTime(), - mResponder->getName(), mResponseTransferedBytes); + mResponder->getName(), mTotalRawBytes); } setopt(CURLOPT_FRESH_CONNECT, TRUE); } @@ -2058,7 +2096,9 @@ size_t BufferedCurlEasyRequest::curlWriteCallback(char* data, size_t size, size_ // BufferedCurlEasyRequest::setBodyLimit is never called, so buffer_w->mBodyLimit is infinite. //S32 bytes = llmin(size * nmemb, buffer_w->mBodyLimit); buffer_w->mBodyLimit -= bytes; self_w->getOutput()->append(sChannels.in(), (U8 const*)data, bytes); - self_w->mResponseTransferedBytes += bytes; // Accumulate data received from the server. + // Update HTTP bandwith. + self_w->update_body_bandwidth(); + // Update timeout administration. if (self_w->httptimeout()->data_received(bytes)) // Update timeout administration. { // Transfer timed out. Return 0 which will abort with error CURLE_WRITE_ERROR. @@ -2067,6 +2107,25 @@ size_t BufferedCurlEasyRequest::curlWriteCallback(char* data, size_t size, size_ return bytes; } +void BufferedCurlEasyRequest::update_body_bandwidth(void) +{ + double size_download; // Total amount of raw bytes received so far (ie. still compressed, 'bytes' is uncompressed). + getinfo(CURLINFO_SIZE_DOWNLOAD, &size_download); + size_t total_raw_bytes = size_download; + size_t raw_bytes = total_raw_bytes - mTotalRawBytes; + mTotalRawBytes = total_raw_bytes; + // Note that in some cases (like HTTP_PARTIAL_CONTENT), the output of CURLINFO_SIZE_DOWNLOAD lags + // behind and will return 0 the first time, and the value of the previous chunk the next time. + // The last call from MultiHandle::finish_easy_request recorrects this, in that case. + if (raw_bytes > 0) + { + U64 const sTime_40ms = curlthread::HTTPTimeout::sTime_10ms >> 2; + AIAverage& http_bandwidth(PerServiceRequestQueue_wat(*getPerServicePtr())->bandwidth()); + http_bandwidth.addData(raw_bytes, sTime_40ms); + sHTTPBandwidth.addData(raw_bytes, sTime_40ms); + } +} + //static size_t BufferedCurlEasyRequest::curlReadCallback(char* data, size_t size, size_t nmemb, void* user_data) { @@ -2124,7 +2183,7 @@ size_t BufferedCurlEasyRequest::curlHeaderCallback(char* data, size_t size, size std::string::iterator pos3 = std::find(pos2, end, '\r'); U32 status = 0; std::string reason; - if (pos3 != end && std::isdigit(*pos1)) + if (pos3 != end && LLStringOps::isDigit(*pos1)) { status = atoi(&header_line[pos1 - begin]); reason.assign(pos2, pos3); @@ -2154,6 +2213,11 @@ size_t BufferedCurlEasyRequest::curlHeaderCallback(char* data, size_t size, size self_w->httptimeout()->being_redirected(); } } + // Update HTTP bandwidth. + U64 const sTime_40ms = curlthread::HTTPTimeout::sTime_10ms >> 2; + AIAverage& http_bandwidth(PerServiceRequestQueue_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. if (self_w->httptimeout()->data_received(header_len/*,*/ ASSERT_ONLY_COMMA(self_w->upload_error_status()))) { @@ -2328,7 +2392,7 @@ void AICurlEasyRequest::addRequest(void) // Find the last command added. command_st cmd = cmd_none; - for (std::deque::iterator iter = command_queue_w->begin(); iter != command_queue_w->end(); ++iter) + for (std::deque::iterator iter = command_queue_w->commands.begin(); iter != command_queue_w->commands.end(); ++iter) { if (*iter == *this) { @@ -2354,8 +2418,11 @@ void AICurlEasyRequest::addRequest(void) } #endif // Add a command to add the new request to the multi session to the command queue. - command_queue_w->push_back(Command(*this, cmd_add)); - AICurlEasyRequest_wat(*get())->add_queued(); + 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(); + curl_easy_request_w->add_queued(); } // Something was added to the queue, wake up the thread to get it. wakeUpCurlThread(); @@ -2378,7 +2445,7 @@ void AICurlEasyRequest::removeRequest(void) // Find the last command added. command_st cmd = cmd_none; - for (std::deque::iterator iter = command_queue_w->begin(); iter != command_queue_w->end(); ++iter) + for (std::deque::iterator iter = command_queue_w->commands.begin(); iter != command_queue_w->commands.end(); ++iter) { if (*iter == *this) { @@ -2415,9 +2482,12 @@ void AICurlEasyRequest::removeRequest(void) } #endif // Add a command to remove this request from the multi session to the command queue. - command_queue_w->push_back(Command(*this, cmd_remove)); + command_queue_w->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'. // Suppress warning that would otherwise happen if the callbacks are revoked before the curl thread removed the request. - AICurlEasyRequest_wat(*get())->remove_queued(); + curl_easy_request_w->remove_queued(); } // Something was added to the queue, wake up the thread to get it. wakeUpCurlThread(); @@ -2427,7 +2497,9 @@ void AICurlEasyRequest::removeRequest(void) namespace AICurlInterface { -void startCurlThread(U32 CurlMaxTotalConcurrentConnections, U32 CurlConcurrentConnectionsPerHost, bool NoVerifySSLCert) +LLControlGroup* sConfigGroup; + +void startCurlThread(LLControlGroup* control_group) { using namespace AICurlPrivate; using namespace AICurlPrivate::curlthread; @@ -2435,9 +2507,11 @@ void startCurlThread(U32 CurlMaxTotalConcurrentConnections, U32 CurlConcurrentCo llassert(is_main_thread()); // Cache Debug Settings. - curl_max_total_concurrent_connections = CurlMaxTotalConcurrentConnections; - curl_concurrent_connections_per_host = CurlConcurrentConnectionsPerHost; - gNoVerifySSLCert = NoVerifySSLCert; + sConfigGroup = 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; AICurlThread::sInstance = new AICurlThread; AICurlThread::sInstance->start(); @@ -2445,19 +2519,24 @@ void startCurlThread(U32 CurlMaxTotalConcurrentConnections, U32 CurlConcurrentCo bool handleCurlMaxTotalConcurrentConnections(LLSD const& newvalue) { + using namespace AICurlPrivate; using namespace AICurlPrivate::curlthread; + U32 old = curl_max_total_concurrent_connections; curl_max_total_concurrent_connections = newvalue.asInteger(); + max_pipelined_requests += curl_max_total_concurrent_connections - old; llinfos << "CurlMaxTotalConcurrentConnections set to " << curl_max_total_concurrent_connections << llendl; return true; } -bool handleCurlConcurrentConnectionsPerHost(LLSD const& newvalue) +bool handleCurlConcurrentConnectionsPerService(LLSD const& newvalue) { using namespace AICurlPrivate; - curl_concurrent_connections_per_host = newvalue.asInteger(); - llinfos << "CurlConcurrentConnectionsPerHost set to " << curl_concurrent_connections_per_host << llendl; + U32 new_concurrent_connections = newvalue.asInteger(); + AIPerService::adjust_concurrent_connections(new_concurrent_connections - CurlConcurrentConnectionsPerService); + CurlConcurrentConnectionsPerService = new_concurrent_connections; + llinfos << "CurlConcurrentConnectionsPerService set to " << CurlConcurrentConnectionsPerService << llendl; return true; } @@ -2467,5 +2546,215 @@ bool handleNoVerifySSLCert(LLSD const& newvalue) return true; } +U32 getNumHTTPCommands(void) +{ + using namespace AICurlPrivate; + + command_queue_rat command_queue_r(command_queue); + return command_queue_r->size; +} + +U32 getNumHTTPQueued(void) +{ + return AIPerService::total_queued_size(); +} + +U32 getNumHTTPAdded(void) +{ + return AICurlPrivate::curlthread::MultiHandle::total_added_size(); +} + +size_t getHTTPBandwidth(void) +{ + using namespace AICurlPrivate; + + U64 const sTime_40ms = get_clock_count() * curlthread::HTTPTimeout::sClockWidth_40ms; + return BufferedCurlEasyRequest::sHTTPBandwidth.truncateData(sTime_40ms); +} + } // namespace AICurlInterface +// 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 +// true a hundred times on a row when it is called fast in a loop. +// Hence the following consideration: +// +// This function is called only from LLTextureFetchWorker::doWork, and when it returns true +// then doWork will call LLHTTPClient::request with a NULL default engine (signaling that +// it is OK to run in any thread). +// +// At the end, LLHTTPClient::request calls AIStateMachine::run, which in turn calls +// AIStateMachine::reset at the end. Because NULL is passed as default_engine, reset will +// call AIStateMachine::multiplex to immediately start running the state machine. This +// causes it to go through the states bs_reset, bs_initialize and then bs_multiplex with +// run state AICurlEasyRequestStateMachine_addRequest. Finally, in this state, multiplex +// calls AICurlEasyRequestStateMachine::multiplex_impl which then calls AICurlEasyRequest::addRequest +// which causes an increment of command_queue_w->size and AIPerService::mQueuedCommands. +// +// It is therefore guaranteed that in one loop of LLTextureFetchWorker::doWork, +// this size is incremented; stopping this function from returning true once we reached the +// threshold of "pipelines" requests (the sum of requests in the command queue, the ones +// throttled and queued in AIPerService::mQueuedRequests and the already +// running requests (in MultiHandle::mAddedEasyRequests)). +// +//static +bool AIPerService::wantsMoreHTTPRequestsFor(AIPerServicePtr const& per_service, F32 max_kbps, bool no_bandwidth_throttling) +{ + using namespace AICurlPrivate; + using namespace AICurlPrivate::curlthread; + + bool reject, equal, increment_threshold, decrement_threshold; + + // 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) + { + // 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; + } + } + + // Check if it's ok to get a new request for this particular service and update the per-service threshold. + + AIAverage* http_bandwidth_ptr; + + { + 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(); + if (decrement_threshold) + { + if (per_service_w->mMaxPipelinedRequests > per_service_w->mConcurrectConnections) + { + per_service_w->mMaxPipelinedRequests--; + } + } + else if (increment_threshold && reject) + { + if (per_service_w->mMaxPipelinedRequests < 2 * per_service_w->mConcurrectConnections) + { + per_service_w->mMaxPipelinedRequests++; + // Immediately take the new threshold into account. + reject = !equal; + } + } + } + if (reject) + { + // Too many request for this host already. + return false; + } + + if (!no_bandwidth_throttling) + { + // 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 + } + } + + // 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. + + // 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; + } + if (increment_threshold && reject) + { + if (max_pipelined_requests_cache < 2 * (S32)curl_max_total_concurrent_connections) + { + max_pipelined_requests++; + // Immediately take the new threshold into account. + reject = !equal; + } + } + return !reject; +} + diff --git a/indra/llmessage/aicurlthread.h b/indra/llmessage/aicurlthread.h index fc29ac1fc..9f71b015c 100644 --- a/indra/llmessage/aicurlthread.h +++ b/indra/llmessage/aicurlthread.h @@ -75,12 +75,13 @@ class MultiHandle : public CurlMultiHandle typedef std::set addedEasyRequests_type; addedEasyRequests_type mAddedEasyRequests; // All easy requests currently added to the multi handle. long mTimeout; // The last timeout in ms as set by the callback CURLMOPT_TIMERFUNCTION. + static LLAtomicU32 sTotalAdded; // The (sum of the) size of mAddedEasyRequests (of every MultiHandle, but there is only one). private: // Store result and trigger events for easy request. void finish_easy_request(AICurlEasyRequest const& easy_request, CURLcode result); // Remove easy request at iter (must exist). - // Note that it's possible that a new request from a PerHostRequestQueue::mQueuedRequests is inserted before iter. + // Note that it's possible that a new request from a AIPerService::mQueuedRequests is inserted before iter. CURLMcode remove_easy_request(addedEasyRequests_type::iterator const& iter, bool as_per_command); static int socket_callback(CURL* easy, curl_socket_t s, int action, void* userp, void* socketp); @@ -96,6 +97,9 @@ class MultiHandle : public CurlMultiHandle // Called from the main loop every time select() timed out. void handle_stalls(void); + // Return the total number of added curl requests. + static U32 total_added_size(void) { return sTotalAdded; } + public: //----------------------------------------------------------------------------- // Curl socket administration: diff --git a/indra/llmessage/aihttptimeout.cpp b/indra/llmessage/aihttptimeout.cpp index 0f99e23d2..22dbb1cfd 100644 --- a/indra/llmessage/aihttptimeout.cpp +++ b/indra/llmessage/aihttptimeout.cpp @@ -75,6 +75,7 @@ namespace AICurlPrivate { class BufferedCurlEasyRequest { public: char const* getLowercaseHostname(void) const { return "hostname.com"; } + char const* getLowercaseServicename(void) const { return "hostname.com:12047"; } void getinfo(const int&, double* p) { *p = 0.1; } }; @@ -96,8 +97,9 @@ namespace curlthread { // HTTPTimeout //static -F64 const HTTPTimeout::sClockWidth = 1.0 / calc_clock_frequency(); // Time between two clock ticks, in seconds. -U64 HTTPTimeout::sClockCount; // Clock count, set once per select() exit. +F64 const HTTPTimeout::sClockWidth_10ms = 100.0 / calc_clock_frequency(); // Time between two clock ticks, in 10ms units. +F64 const HTTPTimeout::sClockWidth_40ms = HTTPTimeout::sClockWidth_10ms * 0.25; // Time between two clock ticks, in 40ms units. +U64 HTTPTimeout::sTime_10ms; // Time in 10ms units, set once per select() exit. // CURL-THREAD // This is called when body data was sent to the server socket. @@ -125,7 +127,7 @@ bool HTTPTimeout::data_sent(size_t n, bool finished) // | | void HTTPTimeout::reset_lowspeed(void) { - mLowSpeedClock = sClockCount; + mLowSpeedClock = sTime_10ms; mLowSpeedOn = true; mLastBytesSent = false; // We're just starting! mLastSecond = -1; // This causes lowspeed to initialize the rest. @@ -162,8 +164,8 @@ void HTTPTimeout::upload_finished(void) // We finished uploading (if there was a body to upload at all), so no more transfer rate timeouts. mLowSpeedOn = false; // Timeout if the server doesn't reply quick enough. - mStalled = sClockCount + mPolicy->getReplyDelay() / sClockWidth; - DoutCurl("upload_finished: mStalled set to sClockCount (" << sClockCount << ") + " << (mStalled - sClockCount) << " (" << mPolicy->getReplyDelay() << " seconds)"); + mStalled = sTime_10ms + 100 * mPolicy->getReplyDelay(); + DoutCurl("upload_finished: mStalled set to Time_10ms (" << sTime_10ms << ") + " << (mStalled - sTime_10ms) << " (" << mPolicy->getReplyDelay() << " seconds)"); } // CURL-THREAD @@ -230,8 +232,7 @@ bool HTTPTimeout::lowspeed(size_t bytes, bool finished) // less than low_speed_limit, we abort. // When are we? - S32 second = (sClockCount - mLowSpeedClock) * sClockWidth; - llassert(sClockWidth > 0.0); + S32 second = (sTime_10ms - mLowSpeedClock) / 100; // This REALLY should never happen, but due to another bug it did happened // and caused something so evil and hard to find that... NEVER AGAIN! llassert(second >= 0); @@ -315,8 +316,8 @@ bool HTTPTimeout::lowspeed(size_t bytes, bool finished) // Just give these bytes 4 more seconds to be written to the socket (after which we'll // assume that the 'upload finished' detection failed and we'll wait another ReplyDelay // seconds before finally, actually timing out. - mStalled = sClockCount + 4 / sClockWidth; - DoutCurl("mStalled set to sClockCount (" << sClockCount << ") + " << (mStalled - sClockCount) << " (4 seconds)"); + mStalled = sTime_10ms + 400; // 4 seconds into the future. + DoutCurl("mStalled set to sTime_10ms (" << sTime_10ms << ") + 400 (4 seconds)"); return false; } // The average transfer rate over the passed low_speed_time seconds is too low. Abort the transfer. @@ -368,8 +369,8 @@ bool HTTPTimeout::lowspeed(size_t bytes, bool finished) while(total_bytes >= mintotalbytes); } // If this function isn't called again within max_stall_time seconds, we stalled. - mStalled = sClockCount + max_stall_time / sClockWidth; - DoutCurl("mStalled set to sClockCount (" << sClockCount << ") + " << (mStalled - sClockCount) << " (" << max_stall_time << " seconds)"); + mStalled = sTime_10ms + 100 * max_stall_time; + DoutCurl("mStalled set to sTime_10ms (" << sTime_10ms << ") + " << (mStalled - sTime_10ms) << " (" << max_stall_time << " seconds)"); return false; } @@ -435,7 +436,7 @@ bool HTTPTimeout::maybe_upload_finished(void) void HTTPTimeout::print_diagnostics(CurlEasyRequest const* curl_easy_request, char const* eff_url) { #ifndef HTTPTIMEOUT_TESTSUITE - llwarns << "Request to \"" << curl_easy_request->getLowercaseHostname() << "\" timed out for " << curl_easy_request->getTimeoutPolicy()->name() << llendl; + llwarns << "Request to \"" << curl_easy_request->getLowercaseServicename() << "\" timed out for " << curl_easy_request->getTimeoutPolicy()->name() << llendl; llinfos << "Effective URL: \"" << eff_url << "\"." << llendl; double namelookup_time, connect_time, appconnect_time, pretransfer_time, starttransfer_time; curl_easy_request->getinfo(CURLINFO_NAMELOOKUP_TIME, &namelookup_time); diff --git a/indra/llmessage/aihttptimeout.h b/indra/llmessage/aihttptimeout.h index 2c5442075..1af96c9c7 100644 --- a/indra/llmessage/aihttptimeout.h +++ b/indra/llmessage/aihttptimeout.h @@ -85,11 +85,12 @@ class HTTPTimeout : public LLRefCount { S32 mLastSecond; // The time at which lowspeed() was last called, in seconds since mLowSpeedClock. S32 mOverwriteSecond; // The second at which the first bucket of this transfer will be overwritten. U32 mTotalBytes; // The sum of all bytes in mBuckets. - U64 mLowSpeedClock; // Clock count at which low speed detection (re)started. - U64 mStalled; // The clock count at which this transaction is considered to be stalling if nothing is transfered anymore. + U64 mLowSpeedClock; // The time (sTime_10ms) at which low speed detection (re)started. + U64 mStalled; // The time (sTime_10ms) at which this transaction is considered to be stalling if nothing is transfered anymore. public: - static F64 const sClockWidth; // Time between two clock ticks in seconds. - static U64 sClockCount; // Clock count used as 'now' during one loop of the main loop. + static F64 const sClockWidth_10ms; // Time between two clock ticks in 10 ms units. + static F64 const sClockWidth_40ms; // Time between two clock ticks in 40 ms units. + static U64 sTime_10ms; // Time since the epoch in 10 ms units. #if defined(CWDEBUG) || defined(DEBUG_CURLIO) ThreadSafeBufferedCurlEasyRequest* mLockObj; #endif @@ -121,7 +122,7 @@ class HTTPTimeout : public LLRefCount { void done(AICurlEasyRequest_wat const& curlEasyRequest_w, CURLcode code); // Returns true when we REALLY timed out. Might call upload_finished heuristically. - bool has_stalled(void) { return mStalled < sClockCount && !maybe_upload_finished(); } + bool has_stalled(void) { return mStalled < sTime_10ms && !maybe_upload_finished(); } // Called from BufferedCurlEasyRequest::processOutput if a timeout occurred. void print_diagnostics(CurlEasyRequest const* curl_easy_request, char const* eff_url); diff --git a/indra/llmessage/aihttptimeoutpolicy.cpp b/indra/llmessage/aihttptimeoutpolicy.cpp index d5e0dd3b6..840532e43 100644 --- a/indra/llmessage/aihttptimeoutpolicy.cpp +++ b/indra/llmessage/aihttptimeoutpolicy.cpp @@ -707,6 +707,13 @@ AIHTTPTimeoutPolicyBase connect_40s(AIHTTPTimeoutPolicyBase::getDebugSettingsCur connectOp40s ); +// This used to be FETCHING_TIMEOUT (for HTTP textures), being a 15 second timeout from start of request till finishing receiving all data. +// That seems way to demanding however; lets use a 15 second reply delay demand instead. +Reply replyOp15s(15); +AIHTTPTimeoutPolicyBase reply_15s(AIHTTPTimeoutPolicyBase::getDebugSettingsCurlTimeout(), + replyOp15s + ); + // End of policy definitions. //======================================================================================================= @@ -899,7 +906,7 @@ P2(gamingDataReceived, transfer_18s); P2(groupMemberDataResponder, transfer_300s); P2(groupProposalBallotResponder, transfer_300s); P(homeLocationResponder); -P(HTTPGetResponder); +P2(HTTPGetResponder, reply_15s); P(iamHereLogin); P(iamHere); P(iamHereVoice); diff --git a/indra/llmessage/message.cpp b/indra/llmessage/message.cpp index 8f60d2a7d..814d407d0 100644 --- a/indra/llmessage/message.cpp +++ b/indra/llmessage/message.cpp @@ -50,7 +50,6 @@ #include "lldarray.h" #include "lldir.h" #include "llerror.h" -#include "llerrorlegacy.h" #include "llfasttimer.h" #include "llhttpclient.h" #include "llhttpnodeadapter.h" diff --git a/indra/llplugin/slplugin/CMakeLists.txt b/indra/llplugin/slplugin/CMakeLists.txt index e377434b1..381782ed6 100644 --- a/indra/llplugin/slplugin/CMakeLists.txt +++ b/indra/llplugin/slplugin/CMakeLists.txt @@ -6,7 +6,6 @@ include(LLPlugin) include(Linking) include(PluginAPI) include(LLMessage) -include(GooglePerfTools) include_directories( ${LLPLUGIN_INCLUDE_DIRS} diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h index 80ed916b0..aadb2c811 100644 --- a/indra/llui/llfloater.h +++ b/indra/llui/llfloater.h @@ -219,10 +219,6 @@ public: virtual void saveAs() {} virtual void saveAsType(BOOL type=false) {} - // - virtual LLUUID getItemID() { return LLUUID::null; } - // - void setSnapTarget(LLHandle handle) { mSnappedTo = handle; } void clearSnapTarget() { mSnappedTo.markDead(); } LLHandle getSnapTarget() const { return mSnappedTo; } diff --git a/indra/llui/lluictrl.h b/indra/llui/lluictrl.h index 499d49e54..ed3ea6244 100644 --- a/indra/llui/lluictrl.h +++ b/indra/llui/lluictrl.h @@ -111,7 +111,7 @@ public: BOOL focusNextItem(BOOL text_entry_only); BOOL focusPrevItem(BOOL text_entry_only); - BOOL focusFirstItem(BOOL prefer_text_fields = FALSE, BOOL focus_flash = TRUE ); + virtual BOOL focusFirstItem(BOOL prefer_text_fields = FALSE, BOOL focus_flash = TRUE ); BOOL focusLastItem(BOOL prefer_text_fields = FALSE); // Non Virtuals diff --git a/indra/lscript/lscript_byteformat.h b/indra/lscript/lscript_byteformat.h index bf810817b..09c8b1281 100644 --- a/indra/lscript/lscript_byteformat.h +++ b/indra/lscript/lscript_byteformat.h @@ -536,6 +536,7 @@ typedef enum e_lscript_runtime_permissions SCRIPT_PERMISSION_TRACK_CAMERA, SCRIPT_PERMISSION_CONTROL_CAMERA, SCRIPT_PERMISSION_TELEPORT, + SCRIPT_PERMISSION_OVERRIDE_ANIMATIONS, SCRIPT_PERMISSION_EOF } LSCRIPTRunTimePermissions; @@ -553,6 +554,7 @@ const U32 LSCRIPTRunTimePermissionBits[SCRIPT_PERMISSION_EOF] = (0x1 << 10),// SCRIPT_PERMISSION_TRACK_CAMERA (0x1 << 11),// SCRIPT_PERMISSION_CONTROL_CAMERA (0x1 << 12),// SCRIPT_PERMISSION_TELEPORT + (0x1 << 15),// SCRIPT_PERMISSION_OVERRIDE_ANIMATIONS }; // http_request string constants diff --git a/indra/lscript/lscript_library/lscript_library.cpp b/indra/lscript/lscript_library/lscript_library.cpp index 4837b4f6b..3d91fafe8 100644 --- a/indra/lscript/lscript_library/lscript_library.cpp +++ b/indra/lscript/lscript_library/lscript_library.cpp @@ -532,6 +532,14 @@ void LLScriptLibrary::init() addFunction(10.f, 0.f, dummy_func, "llUpdateCharacter", NULL, "l"); addFunction(10.f, 0.f, dummy_func, "llWanderWithin", NULL, "vvl"); + // Server RC LeTigre 12.10.12.265819 new function + addFunction(0.f, 0.f, dummy_func, "llGetSimStats", "f", "i"); + + // Server RC LeTigre 13.03.22.272565 new function + addFunction(0.f, 0.f, dummy_func, "llSetAnimationOverride", NULL, "ss"); + addFunction(0.f, 0.f, dummy_func, "llGetAnimationOverride", "s", "s"); + addFunction(0.f, 0.f, dummy_func, "llResetAnimationOverride", NULL, "s"); + // SL-LSL Functions to be added above this line // --------------------------------------------- // NOTE bytecode placement no longer applies, viewers do not compile scripts anymore (confirmed with LL, also noted by Phoenix/Firestorm team.) diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 9e3abed3e..f3cc6d444 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -38,7 +38,6 @@ include(LLXML) #include(LScript) include(Linking) include(NDOF) -include(GooglePerfTools) include(StateMachine) include(TemplateCheck) include(UI) @@ -90,6 +89,7 @@ set(viewer_SOURCE_FILES floaterao.cpp floaterlocalassetbrowse.cpp floatervoicelicense.cpp + generichandlers.cpp hbfloatergrouptitles.cpp hippofloaterxml.cpp hippogridmanager.cpp @@ -97,6 +97,7 @@ set(viewer_SOURCE_FILES hippopanelgrids.cpp importtracker.cpp jcfloaterareasearch.cpp + lfsimfeaturehandler.cpp lggdicdownload.cpp lgghunspell_wrapper.cpp llaccountingcostmanager.cpp @@ -184,6 +185,7 @@ set(viewer_SOURCE_FILES llfloaterbuycontents.cpp llfloaterbuycurrency.cpp llfloaterbuyland.cpp + llfloaterbvhpreview.cpp llfloatercamera.cpp llfloaterchat.cpp llfloaterchatterbox.cpp @@ -590,6 +592,7 @@ set(viewer_HEADER_FILES floaterao.h floaterlocalassetbrowse.h floatervoicelicense.h + generichandlers.h hbfloatergrouptitles.h hippofloaterxml.h hippogridmanager.h @@ -597,6 +600,7 @@ set(viewer_HEADER_FILES hippopanelgrids.h importtracker.h jcfloaterareasearch.h + lfsimfeaturehandler.h lggdicdownload.h lgghunspell_wrapper.h llaccountingcostmanager.h @@ -685,6 +689,7 @@ set(viewer_HEADER_FILES llfloaterbuycontents.h llfloaterbuycurrency.h llfloaterbuyland.h + llfloaterbvhpreview.h llfloatercamera.h llfloaterchat.h llfloaterchatterbox.h diff --git a/indra/newview/app_settings/keywords.ini b/indra/newview/app_settings/keywords.ini index b084a5894..d43e54989 100644 --- a/indra/newview/app_settings/keywords.ini +++ b/indra/newview/app_settings/keywords.ini @@ -52,7 +52,7 @@ changed changed( integer change ):Triggered various event change the task:(tes remote_data remote_data(integer event_type, key channel, key message_id, string sender,integer idata, string sdata):Triggered by various XML-RPC calls (event_type will be one of REMOTE_DATA_CHANNEL, REMOTE_DATA_REQUEST, REMOTE_DATA_REPLY) http_response http_response(key request_id, integer status, list metadata, string body):Triggered when task receives a response to one of its llHTTPRequests http_request http_request(key id, string method, string body):Triggered when task receives an http request against a public URL -transaction_result transaction_result(key id, integer success, string data):Triggered when task receives asynchronous data. +transaction_result transaction_result(key id, integer success, string data): Triggered when currency is given to task path_update path_update(integer type, list reserved):Triggered when the state of a pathfinder character changes. Note; "list reserved" is not currently used # integer constants @@ -99,6 +99,7 @@ PERMISSION_CHANGE_LINKS Passed to llRequestPermissions library function to req PERMISSION_TRACK_CAMERA Passed to llRequestPermissions library function to request permission to track agent's camera PERMISSION_CONTROL_CAMERA Passed to llRequestPermissions library function to request permission to change agent's camera PERMISSION_TELEPORT Passed to llRequestPermissions library function to request permission to teleport agent +PERMISSION_OVERRIDE_ANIMATIONS Passed to llRequestPermissions library function to request permission to override agent's animations DEBUG_CHANNEL Chat channel reserved for debug and error messages from scripts PUBLIC_CHANNEL Chat channel that broadcasts to all nearby users diff --git a/indra/newview/app_settings/lsl_functions_sl.xml b/indra/newview/app_settings/lsl_functions_sl.xml index 51074f13e..563414c6e 100644 --- a/indra/newview/app_settings/lsl_functions_sl.xml +++ b/indra/newview/app_settings/lsl_functions_sl.xml @@ -1013,5 +1013,12 @@ llGetSimStats + + llSetAnimationOverride + + llGetAnimationOverride + + llResetAnimationOverride + \ No newline at end of file diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 2b7f2fb86..61f8f21bc 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -171,40 +171,7 @@ Value 1 - - HTTPRequestRate - - Comment - Number of HTTP texture requests fired per second. - Persist - 1 - Type - U32 - Value - 30 - - HTTPMaxRequests - - Comment - Maximum number of simultaneous HTTP requests in progress. - Persist - 1 - Type - U32 - Value - 12 - - HTTPMinRequests - - Comment - Attempt to maintain at least this many HTTP requests in progress by ignoring bandwidth - Persist - 1 - Type - U32 - Value - 2 - + HTTPThrottleBandwidth Comment @@ -726,6 +693,17 @@ Found in Advanced->Rendering->Info Displays Value 0 + FakeAway + + HideFromEditor + 1 + Persist + 0 + Type + Boolean + Value + 0 + InstantMessageLogPathAnyAccount Comment @@ -4481,10 +4459,10 @@ This should be as low as possible, but too low may break functionality Value 64 - CurlConcurrentConnectionsPerHost + CurlConcurrentConnectionsPerService Comment - Maximum number of simultaneous curl connections per host + Maximum number of simultaneous curl connections per host:port service Persist 0 Type @@ -4943,7 +4921,18 @@ This should be as low as possible, but too low may break functionality Value -1 - DebugStatModeTexture + DebugStatModeHTTPTexture + + Comment + Mode of stat in Statistics floater + Persist + 1 + Type + S32 + Value + -1 + + DebugStatModeUDPTexture Comment Mode of stat in Statistics floater @@ -5526,6 +5515,28 @@ This should be as low as possible, but too low may break functionality Value 1 + ClickActionBuyEnabled + + Comment + Enable click to buy actions in tool pie menu + Persist + 1 + Type + Boolean + Value + 1 + + ClickActionPayEnabled + + Comment + Enable click to pay actions in tool pie menu + Persist + 1 + Type + Boolean + Value + 1 + DoubleClickAutoPilot Comment @@ -5570,10 +5581,21 @@ This should be as low as possible, but too low may break functionality Value 0.10000000149 + DragAndDropDistanceThreshold + + Comment + Number of pixels that mouse should move before triggering drag and drop mode + Persist + 1 + Type + S32 + Value + 3 + DropShadowButton Comment - Drop shadow width for buttons (pixels) + Drop shadow width for buttons (pixels) Persist 1 Type @@ -5680,6 +5702,17 @@ This should be as low as possible, but too low may break functionality Value 1 + EnableGrab + + Comment + Use Ctrl+mouse to grab and manipulate objects + Persist + 1 + Type + Boolean + Value + 1 + EnableGestureSounds Comment @@ -13041,6 +13074,17 @@ This should be as low as possible, but too low may break functionality Value 0 + DisableClickSitOtherOwner + + Comment + Never sit by clicking a prim that isn't owned by you + Persist + 1 + Type + Boolean + Value + 0 + PlayIMSound Comment @@ -15107,6 +15151,17 @@ This should be as low as possible, but too low may break functionality Value 0 + UseTypingBubbles + + Comment + Show typing indicator in avatar nametags + Persist + 1 + Type + Boolean + Value + 0 + UseDebugMenus Comment @@ -16393,6 +16448,17 @@ This should be as low as possible, but too low may break functionality Value 1 + ClickToWalk + + Comment + Click in world to walk to location + Persist + 1 + Type + Boolean + Value + 0 + SimulateFBOFailure Comment diff --git a/indra/newview/app_settings/settings_crash_behavior.xml b/indra/newview/app_settings/settings_crash_behavior.xml index f588db5cb..433583bee 100644 --- a/indra/newview/app_settings/settings_crash_behavior.xml +++ b/indra/newview/app_settings/settings_crash_behavior.xml @@ -1,15 +1,48 @@ - + CrashSubmitBehavior - - Comment - Controls behavior when viewer crashes (0 = ask before sending crash report, 1 = always send crash report, 2 = never send crash report) - Persist - 2 - Type - S32 - Value - 2 - + + Comment + Controls behavior when viewer crashes (0 = ask before sending crash report, 1 = always send crash report, 2 = never send crash report) + Persist + 2 + Type + S32 + Value + 2 + CurlMaxTotalConcurrentConnections + + Comment + Maximum total number of simultaneous curl connections + Persist + 1 + Type + U32 + Value + 64 + + CurlConcurrentConnectionsPerService + + Comment + Maximum number of simultaneous curl connections per host:port service + Persist + 0 + Type + U32 + Value + 16 + + NoVerifySSLCert + + Comment + Do not verify SSL certificates. + Persist + 1 + Type + Boolean + Value + 1 + + diff --git a/indra/newview/app_settings/settings_per_account.xml b/indra/newview/app_settings/settings_per_account.xml index d30cb4343..b591a82db 100644 --- a/indra/newview/app_settings/settings_per_account.xml +++ b/indra/newview/app_settings/settings_per_account.xml @@ -314,6 +314,17 @@ Value 0 + EveryoneExport + + Comment + Whether content you upload has exportability permission by default + Persist + 1 + Type + Boolean + Value + 0 + RLVaLoginLastLocation Comment diff --git a/indra/newview/ascentprefschat.cpp b/indra/newview/ascentprefschat.cpp index 599ab0c66..f24724279 100644 --- a/indra/newview/ascentprefschat.cpp +++ b/indra/newview/ascentprefschat.cpp @@ -329,6 +329,7 @@ void LLPrefsAscentChat::refreshValues() mHideTypingNotification = gSavedSettings.getBOOL("AscentHideTypingNotification"); mShowGroupNameInChatIM = gSavedSettings.getBOOL("OptionShowGroupNameInChatIM"); mShowDisplayNameChanges = gSavedSettings.getBOOL("ShowDisplayNameChanges"); + mUseTypingBubbles = gSavedSettings.getBOOL("UseTypingBubbles"); mPlayTypingSound = gSavedSettings.getBOOL("PlayTypingSound"); mHideNotificationsInChat = gSavedSettings.getBOOL("HideNotificationsInChat"); mEnableMUPose = gSavedSettings.getBOOL("AscentAllowMUpose"); @@ -545,6 +546,7 @@ void LLPrefsAscentChat::cancel() gSavedSettings.setBOOL("AscentHideTypingNotification", mHideTypingNotification); gSavedSettings.setBOOL("OptionShowGroupNameInChatIM", mShowGroupNameInChatIM); gSavedSettings.setBOOL("ShowDisplayNameChanges", mShowDisplayNameChanges); + gSavedSettings.setBOOL("UseTypingBubbles", mUseTypingBubbles); gSavedSettings.setBOOL("PlayTypingSound", mPlayTypingSound); gSavedSettings.setBOOL("HideNotificationsInChat", mHideNotificationsInChat); gSavedSettings.setBOOL("AscentAllowMUpose", mEnableMUPose); diff --git a/indra/newview/ascentprefschat.h b/indra/newview/ascentprefschat.h index 291645b42..04fa1a69c 100644 --- a/indra/newview/ascentprefschat.h +++ b/indra/newview/ascentprefschat.h @@ -66,6 +66,7 @@ protected: BOOL mHideTypingNotification; BOOL mShowGroupNameInChatIM; bool mShowDisplayNameChanges; + bool mUseTypingBubbles; BOOL mPlayTypingSound; BOOL mHideNotificationsInChat; BOOL mEnableMUPose; diff --git a/indra/newview/ascentprefssys.cpp b/indra/newview/ascentprefssys.cpp index 68d4a1f03..a0477fdda 100644 --- a/indra/newview/ascentprefssys.cpp +++ b/indra/newview/ascentprefssys.cpp @@ -80,6 +80,9 @@ LLPrefsAscentSys::LLPrefsAscentSys() childSetCommitCallback("AscentCmdLineTP2", onCommitCmdLine, this); childSetCommitCallback("SinguCmdLineAway", onCommitCmdLine, this); + //Security ---------------------------------------------------------------------------- + childSetCommitCallback("disable_click_sit_check", onCommitCheckBox, this); + //Build ------------------------------------------------------------------------------- childSetCommitCallback("next_owner_copy", onCommitCheckBox, this); childSetEnabled("next_owner_transfer", gSavedSettings.getBOOL("NextOwnerCopy")); @@ -129,59 +132,57 @@ LLPrefsAscentSys::~LLPrefsAscentSys() //static void LLPrefsAscentSys::onCommitCheckBox(LLUICtrl* ctrl, void* user_data) { - LLPrefsAscentSys* self = (LLPrefsAscentSys*)user_data; + LLPrefsAscentSys* self = static_cast(user_data); // llinfos << "Change to " << ctrl->getControlName() << " aka " << ctrl->getName() << llendl; - - if (ctrl->getName() == "speed_rez_check") - { - bool enabled = self->childGetValue("speed_rez_check").asBoolean(); - self->childSetEnabled("speed_rez_interval", enabled); - self->childSetEnabled("speed_rez_seconds", enabled); - } - else if (ctrl->getName() == "double_click_teleport_check") - { - bool enabled = self->childGetValue("double_click_teleport_check").asBoolean(); - self->childSetEnabled("center_after_teleport_check", enabled); - self->childSetEnabled("offset_teleport_check", enabled); - } - else if (ctrl->getName() == "system_folder_check") - { - bool enabled = self->childGetValue("system_folder_check").asBoolean(); - self->childSetEnabled("temp_in_system_check", enabled); - } - else if (ctrl->getName() == "enable_clouds") - { - bool enabled = self->childGetValue("enable_clouds").asBoolean(); - self->childSetEnabled("enable_classic_clouds", enabled); - } - else if (ctrl->getName() == "power_user_check") - { - bool enabled = self->childGetValue("power_user_check").asBoolean(); - self->childSetEnabled("power_user_confirm_check", enabled); - self->childSetValue("power_user_confirm_check", false); - } - else if (ctrl->getName() == "power_user_confirm_check") - { - bool enabled = self->childGetValue("power_user_confirm_check").asBoolean(); - gSavedSettings.setBOOL("AscentPowerfulWizard", enabled); - - if (enabled) - { - LLVector3d lpos_global = gAgent.getPositionGlobal(); - gAudiop->triggerSound(LLUUID("58a38e89-44c6-c52b-deb8-9f1ddc527319"), gAgent.getID(), 1.0f, LLAudioEngine::AUDIO_TYPE_UI, lpos_global); - LLChat chat; - chat.mSourceType = CHAT_SOURCE_SYSTEM; - chat.mText = LLTrans::getString("PowerUser1") + "\n" + LLTrans::getString("PowerUser2") + "\n" + LLTrans::getString("Unlocked:") + "\n" + LLTrans::getString("PowerUser3") + "\n- " + LLTrans::getString("RightClick") + " > " + LLTrans::getString("PowerUser4") + "\n- " + LLTrans::getString("RightClick") + " > " + LLTrans::getString("PowerUser5"); - LLFloaterChat::addChat(chat); - } - } - else if (ctrl->getName() == "next_owner_copy") + const std::string name = ctrl->getName(); + bool enabled = ctrl->getValue().asBoolean(); + if (name == "speed_rez_check") { - bool copy = gSavedSettings.getBOOL("NextOwnerCopy"); - if (!copy) gSavedSettings.setBOOL("NextOwnerTransfer", true); - self->childSetEnabled("next_owner_transfer", copy); + self->childSetEnabled("speed_rez_interval", enabled); + self->childSetEnabled("speed_rez_seconds", enabled); + } + else if (name == "double_click_teleport_check") + { + self->childSetEnabled("center_after_teleport_check", enabled); + self->childSetEnabled("offset_teleport_check", enabled); + } + else if (name == "system_folder_check") + { + self->childSetEnabled("temp_in_system_check", enabled); + } + else if (name == "enable_clouds") + { + self->childSetEnabled("enable_classic_clouds", enabled); + } + else if (name == "power_user_check") + { + self->childSetEnabled("power_user_confirm_check", enabled); + self->childSetValue("power_user_confirm_check", false); + } + else if (name == "power_user_confirm_check") + { + gSavedSettings.setBOOL("AscentPowerfulWizard", enabled); + + if (enabled) + { + LLVector3d lpos_global = gAgent.getPositionGlobal(); + gAudiop->triggerSound(LLUUID("58a38e89-44c6-c52b-deb8-9f1ddc527319"), gAgent.getID(), 1.0f, LLAudioEngine::AUDIO_TYPE_UI, lpos_global); + LLChat chat; + chat.mSourceType = CHAT_SOURCE_SYSTEM; + chat.mText = LLTrans::getString("PowerUser1") + "\n" + LLTrans::getString("PowerUser2") + "\n" + LLTrans::getString("Unlocked:") + "\n" + LLTrans::getString("PowerUser3") + "\n- " + LLTrans::getString("RightClick") + " > " + LLTrans::getString("PowerUser4") + "\n- " + LLTrans::getString("RightClick") + " > " + LLTrans::getString("PowerUser5"); + LLFloaterChat::addChat(chat); + } + } + else if (name == "disable_click_sit_check") + { + self->childSetEnabled("disable_click_sit_own_check", !enabled); + } + else if (name == "next_owner_copy") + { + if (!enabled) gSavedSettings.setBOOL("NextOwnerTransfer", true); + self->childSetEnabled("next_owner_transfer", enabled); } } @@ -313,6 +314,7 @@ void LLPrefsAscentSys::refreshValues() mDetachBridge = gSavedSettings.getBOOL("SGDetachBridge"); mRevokePermsOnStandUp = gSavedSettings.getBOOL("RevokePermsOnStandUp"); mDisableClickSit = gSavedSettings.getBOOL("DisableClickSit"); + mDisableClickSitOtherOwner = gSavedSettings.getBOOL("DisableClickSitOtherOwner"); mDisplayScriptJumps = gSavedSettings.getBOOL("AscentDisplayTotalScriptJumps"); mNumScriptDiff = gSavedSettings.getF32("Ascentnumscriptdiff"); @@ -463,6 +465,7 @@ void LLPrefsAscentSys::cancel() gSavedSettings.setBOOL("SGDetachBridge", mDetachBridge); gSavedSettings.setBOOL("RevokePermsOnStandUp", mRevokePermsOnStandUp); gSavedSettings.setBOOL("DisableClickSit", mDisableClickSit); + gSavedSettings.setBOOL("DisableClickSitOtherOwner", mDisableClickSitOtherOwner); gSavedSettings.setBOOL("AscentDisplayTotalScriptJumps", mDisplayScriptJumps); gSavedSettings.setF32("Ascentnumscriptdiff", mNumScriptDiff); diff --git a/indra/newview/ascentprefssys.h b/indra/newview/ascentprefssys.h index 73765ee39..60cf4f4de 100644 --- a/indra/newview/ascentprefssys.h +++ b/indra/newview/ascentprefssys.h @@ -104,6 +104,7 @@ protected: BOOL mDetachBridge; BOOL mRevokePermsOnStandUp; BOOL mDisableClickSit; + bool mDisableClickSitOtherOwner; BOOL mDisplayScriptJumps; F32 mNumScriptDiff; //Build ------------------------------------------------------------------------------- diff --git a/indra/newview/generichandlers.cpp b/indra/newview/generichandlers.cpp new file mode 100644 index 000000000..8c1a9fc42 --- /dev/null +++ b/indra/newview/generichandlers.cpp @@ -0,0 +1,75 @@ +/* + * Copyright (c) The Singularity dev Team and Melanie Thielker + * Refer to the singularity project for a full lst of copyright holders + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Neither the name of the Singularity Viewwer Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "llviewerprecompiledheaders.h" +#include "generichandlers.h" +#include "llviewergenericmessage.h" +#include "llviewerinventory.h" +#include "llappearancemgr.h" +#include "llviewerregion.h" +#include "llagent.h" + +GenericHandlers *gGenericHandlers = NULL; + +class DispatchReplaceOutfit : public LLDispatchHandler +{ +public: + virtual bool operator()( + const LLDispatcher* dispatcher, + const std::string& key, + const LLUUID& invoice, + const sparam_t& strings) + { + if (strings.size() != 1) return false; + LLUUID folder_id(strings[0]); + + bool success = false; + LLViewerInventoryCategory *cat = gInventory.getCategory(folder_id); + if (cat != NULL) + { + LLAppearanceMgr::instance().wearInventoryCategory(cat, FALSE, FALSE); + success = true; + } + + LLViewerRegion* regionp = gAgent.getRegion(); + if (!regionp) return true; + + std::string url = regionp->getCapability("WearablesLoaded"); + if (url.empty()) return true; + + LLSD data = LLSD(success); + + LLHTTPClient::post(url, data, new LLHTTPClient::ResponderIgnore); + + return true; + } +}; + +static DispatchReplaceOutfit sDispatchReplaceOutfit; + +GenericHandlers::GenericHandlers() +{ + gGenericDispatcher.addHandler("replaceoutfit", &sDispatchReplaceOutfit); +} + diff --git a/indra/newview/generichandlers.h b/indra/newview/generichandlers.h new file mode 100644 index 000000000..2a1210b57 --- /dev/null +++ b/indra/newview/generichandlers.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) The Singularity dev Team and Melanie Thielker + * Refer to the singularity project for a full lst of copyright holders + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Neither the name of the Singularity Viewwer Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +class GenericHandlers +{ +public: + GenericHandlers(); +}; + +extern GenericHandlers *gGenericHandlers; diff --git a/indra/newview/hippofloaterxml.cpp b/indra/newview/hippofloaterxml.cpp index d8af038a6..76aa9abcf 100644 --- a/indra/newview/hippofloaterxml.cpp +++ b/indra/newview/hippofloaterxml.cpp @@ -40,6 +40,8 @@ #include #include +#include "llavatarnamecache.h" +#include "llfloateravatarpicker.h" #include "llviewerwindow.h" @@ -58,10 +60,12 @@ class HippoFloaterXmlImpl : public LLFloater BOOL postBuild(); void onClose(bool quitting); - static bool execute(LLUICtrl *ctrl, + static bool execute(LLFloater *floater, LLUICtrl *ctrl, const std::string &cmds, std::string::size_type &offset, std::string &response); + U32 mChannel; + private: std::string mName; bool mIsNotifyOnClose; @@ -160,7 +164,7 @@ void XmlData::release(const std::string &floaterName) // create HippoFloaterXmlImpl HippoFloaterXmlImpl::HippoFloaterXmlImpl(const std::string &name, const std::string &xml) : - mName(name), mIsNotifyOnClose(false) + mName(name), mIsNotifyOnClose(false), mChannel(CHANNEL) { gInstances[mName] = this; LLUICtrlFactory::getInstance()->buildFloaterFromBuffer(this, xml); @@ -218,10 +222,10 @@ void HippoFloaterXml::execute(const std::string &cmds) if (token == "{") { if (floater) { std::string response; - if (!floater->execute(floater, cmds, offset, response)) + if (!floater->execute(floater, floater, cmds, offset, response)) break; if (!response.empty()) - send_chat_from_viewer(response, CHAT_TYPE_WHISPER, CHANNEL); + send_chat_from_viewer(response, CHAT_TYPE_WHISPER, floater->mChannel); } } else @@ -265,29 +269,56 @@ void HippoFloaterXml::execute(const std::string &cmds) // ******************************************************************** // generic notification callbacks -static void notifyCallback(void *c) +static void notifyCallback(void *c, void *f) { + HippoFloaterXmlImpl* floaterp = (HippoFloaterXmlImpl*)f; + LLUICtrl *ctrl = (LLUICtrl *)c; std::string msg = "NOTIFY:"; msg += ctrl->getName(); msg += ':'; msg += ctrl->getValue().asString(); - send_chat_from_viewer(msg, CHAT_TYPE_WHISPER, CHANNEL); + send_chat_from_viewer(msg, CHAT_TYPE_WHISPER, floaterp->mChannel); +} + +void callbackAvatarPick(void *c, void *f, const uuid_vec_t& ids, const std::vector& names) +{ + HippoFloaterXmlImpl* floaterp = (HippoFloaterXmlImpl*)f; + + LLUICtrl *ctrl = (LLUICtrl *)c; + + LLUUID id = ids[0]; + + std::string msg = "PICKER:"; + msg += ctrl->getName(); + msg += ':'; + msg += id.asString(); + msg += ':'; + msg += names[0].getCompleteName(); + send_chat_from_viewer(msg, CHAT_TYPE_WHISPER, floaterp->mChannel); +} + +static void pickerCallback(void *c, void *f) +{ + LLUICtrl *ctrl = (LLUICtrl *)c; + HippoFloaterXmlImpl* floaterp = (HippoFloaterXmlImpl*)f; + + floaterp->addDependentFloater(LLFloaterAvatarPicker::show(boost::bind(&callbackAvatarPick, ctrl, floaterp, _1, _2), FALSE, TRUE)); + //send_chat_from_viewer(msg, CHAT_TYPE_WHISPER, CHANNEL); } void HippoFloaterXmlImpl::onClose(bool quitting) { if (mIsNotifyOnClose) send_chat_from_viewer("NOTIFY:" + mName + ":closed", - CHAT_TYPE_WHISPER, CHANNEL); + CHAT_TYPE_WHISPER, mChannel); LLFloater::onClose(quitting); } - // ******************************************************************** // execute commands on instance -bool HippoFloaterXmlImpl::execute(LLUICtrl *ctrl, +bool HippoFloaterXmlImpl::execute(LLFloater *floater, LLUICtrl *ctrl, const std::string &cmds, std::string::size_type &offset, std::string &response) { @@ -313,24 +344,38 @@ bool HippoFloaterXmlImpl::execute(LLUICtrl *ctrl, if (!child) return false; if (!cmdGetToken(cmds, offset, token)) return false; if (token != "{") return false; - if (!execute(child, cmds, offset, response)) + if (!execute(floater, child, cmds, offset, response)) return false; } else if (key == "setValue") { ctrl->setValue(value); + } else if (key == "channel") { + if (HippoFloaterXmlImpl *floater = dynamic_cast(ctrl)) { + floater->mChannel = atoi(value.c_str()); + } } else if (key == "setLabel") { /*ctrl->setLabel(value);*/ } else if (key == "setVisible") { ctrl->setVisible(value != "0"); + } else if (key == "setEnabled") { + ctrl->setEnabled(value != "0"); } else if (key == "notify") { bool set = (value != "0"); - if (HippoFloaterXmlImpl *floater = dynamic_cast(ctrl)) { - floater->mIsNotifyOnClose = set; + if (HippoFloaterXmlImpl *floaterp = dynamic_cast(ctrl)) { + floaterp->mIsNotifyOnClose = set; } else { if (set) - ctrl->setCommitCallback(boost::bind(¬ifyCallback, _1), ctrl); + ctrl->setCommitCallback(boost::bind(¬ifyCallback, _1, floater), ctrl); else ctrl->setCommitCallback(0); } + } else if (key == "picker") { + bool set = (value != "0"); + if (!dynamic_cast(ctrl)) { + if (set) + ctrl->setCommitCallback(boost::bind(&pickerCallback, _1, floater), ctrl); + else + ctrl->setCommitCallback(0); + } } } } diff --git a/indra/newview/hippogridmanager.cpp b/indra/newview/hippogridmanager.cpp index bab5eb8dd..93168da88 100644 --- a/indra/newview/hippogridmanager.cpp +++ b/indra/newview/hippogridmanager.cpp @@ -52,13 +52,16 @@ HippoGridInfo::HippoGridInfo(const std::string& gridName) : mXmlState(XML_VOID), mVoiceConnector("SLVoice"), mIsInProductionGrid(false), + mIsInAvination(false), mRenderCompat(true), mInvLinks(false), mAutoUpdate(false), mMaxAgentGroups(-1), mCurrencySymbol("OS$"), + mCurrencyText("OS Dollars"), mRealCurrencySymbol("US$"), - mDirectoryFee(30) + mDirectoryFee(30), + mUPCSupported(false) { } @@ -66,37 +69,6 @@ HippoGridInfo::HippoGridInfo(const std::string& gridName) : // ******************************************************************** // Getters -HippoGridInfo::Platform HippoGridInfo::getPlatform() -{ - return mPlatform; -} - -bool HippoGridInfo::isOpenSimulator() const -{ - return (mPlatform == HippoGridInfo::PLATFORM_OPENSIM || mPlatform == HippoGridInfo::PLATFORM_AURORA); -} - -bool HippoGridInfo::isAurora() const -{ - return (mPlatform == HippoGridInfo::PLATFORM_AURORA); -} - -bool HippoGridInfo::isSecondLife() const -{ - return (mPlatform == HippoGridInfo::PLATFORM_SECONDLIFE); -} - -bool HippoGridInfo::isInProductionGrid() const -{ - llassert(mPlatform == HippoGridInfo::PLATFORM_SECONDLIFE); - return mIsInProductionGrid; -} - -const std::string& HippoGridInfo::getGridName() const -{ - return mGridName; -} - const std::string& HippoGridInfo::getGridOwner() const { if(isSecondLife()) @@ -110,68 +82,6 @@ const std::string& HippoGridInfo::getGridOwner() const } } -const std::string& HippoGridInfo::getLoginUri() const -{ - return mLoginUri; -} - -const std::string& HippoGridInfo::getLoginPage() const -{ - return mLoginPage; -} - -const std::string& HippoGridInfo::getHelperUri() const -{ - return mHelperUri; -} - -const std::string& HippoGridInfo::getWebSite() const -{ - return mWebSite; -} - -const std::string& HippoGridInfo::getSupportUrl() const -{ - return mSupportUrl; -} - -const std::string& HippoGridInfo::getRegisterUrl() const -{ - return mRegisterUrl; -} - -const std::string& HippoGridInfo::getPasswordUrl() const -{ - return mPasswordUrl; -} - -const std::string& HippoGridInfo::getSearchUrl() const -{ - return mSearchUrl; -} - -const std::string& HippoGridInfo::getGridMessage() const -{ - return mGridMessage; -} - -bool HippoGridInfo::isRenderCompat() const -{ - return mRenderCompat; -} - -const std::string& HippoGridInfo::getCurrencySymbol() const -{ - return mCurrencySymbol; -} - -const std::string& HippoGridInfo::getRealCurrencySymbol() const -{ - return mRealCurrencySymbol; -} - - - // ******************************************************************** // Setters @@ -181,6 +91,7 @@ void HippoGridInfo::setPlatform(Platform platform) if (mPlatform == PLATFORM_SECONDLIFE) { mCurrencySymbol = "L$"; + mCurrencyText = "Linden Dollars"; } } @@ -240,6 +151,10 @@ void HippoGridInfo::setGridNick(std::string gridNick) { mIsInProductionGrid = true; } + if(gridNick == "avination") + { + mIsInAvination = true; + } } void HippoGridInfo::setLoginUri(const std::string& loginUri) @@ -250,6 +165,11 @@ void HippoGridInfo::setLoginUri(const std::string& loginUri) { mIsInProductionGrid = true; } + if (utf8str_tolower(LLURI(uri).hostName()) == "login.avination.com" || + utf8str_tolower(LLURI(uri).hostName()) == "login.avination.net") + { + mIsInAvination = true; + } } void HippoGridInfo::setLoginPage(const std::string& loginPage) @@ -303,6 +223,11 @@ void HippoGridInfo::setCurrencySymbol(const std::string& sym) mCurrencySymbol = sym.substr(0, 3); } +void HippoGridInfo::setCurrencyText(const std::string& text) +{ + mCurrencyText = text; +} + void HippoGridInfo::setRealCurrencySymbol(const std::string& sym) { mRealCurrencySymbol = sym.substr(0, 3); @@ -456,8 +381,11 @@ void HippoGridInfo::onXmlCharacterData(void* userData, const XML_Char* s, int le { case XML_GRIDNICK: { - if (self->mGridNick == "") self->mGridNick.assign(s, len); - self->mGridNick = sanitizeGridNick(self->mGridNick); + if (self->mGridNick == "") + { + self->mGridNick.assign(s, len); + self->mGridNick = sanitizeGridNick(self->mGridNick); + } break; } @@ -489,7 +417,15 @@ void HippoGridInfo::onXmlCharacterData(void* userData, const XML_Char* s, int le break; } - case XML_GRIDNAME: self->mGridName.assign(s, len); break; + case XML_GRIDNAME: + { + if (self->mGridName == "") + { + self->mGridName.assign(s, len); + } + break; + } + case XML_LOGINPAGE: self->mLoginPage.assign(s, len); break; case XML_WEBSITE: self->mWebSite.assign(s, len); break; case XML_SUPPORT: self->mSupportUrl.assign(s, len); break; @@ -676,6 +612,19 @@ void HippoGridInfo::setAutoUpdate(bool b) mAutoUpdate = b; } +bool HippoGridInfo::getUPCSupported() +{ + if(isSecondLife()) + return false; + else + return mUPCSupported; +} + +void HippoGridInfo::setUPCSupported(bool b) +{ + mUPCSupported = b; +} + // ******************************************************************** // ******************************************************************** // HippoGridManager @@ -747,13 +696,6 @@ HippoGridInfo* HippoGridManager::getGrid(const std::string& grid) const } } - -HippoGridInfo* HippoGridManager::getConnectedGrid() const -{ - return (mConnectedGrid)? mConnectedGrid: getCurrentGrid(); -} - - HippoGridInfo* HippoGridManager::getCurrentGrid() const { HippoGridInfo* grid = getGrid(mCurrentGrid); diff --git a/indra/newview/hippogridmanager.h b/indra/newview/hippogridmanager.h index 310033af7..9562d563f 100644 --- a/indra/newview/hippogridmanager.h +++ b/indra/newview/hippogridmanager.h @@ -36,31 +36,33 @@ public: explicit HippoGridInfo(const std::string& gridName); - Platform getPlatform(); - bool isOpenSimulator() const; - bool isAurora() const; - bool isSecondLife() const; - bool isInProductionGrid() const; // Should only be called if isSecondLife() returns true. - const std::string& getGridName() const; + Platform getPlatform() { return mPlatform; } + bool isOpenSimulator() const { return (mPlatform == PLATFORM_OPENSIM || mPlatform == PLATFORM_AURORA); } + bool isAurora() const { return (mPlatform == PLATFORM_AURORA); } + bool isSecondLife() const { return (mPlatform == PLATFORM_SECONDLIFE); } + bool isAvination() const { return mIsInAvination; } + bool isInProductionGrid() const { llassert(mPlatform == PLATFORM_SECONDLIFE); return mIsInProductionGrid; } // Should only be called if isSecondLife() returns true. + const std::string& getGridName() const { return mGridName; } const std::string& getGridOwner() const; - const std::string& getLoginUri() const; - const std::string& getLoginPage() const; - const std::string& getHelperUri() const; - const std::string& getWebSite() const; - const std::string& getSupportUrl() const; - const std::string& getRegisterUrl() const; - const std::string& getPasswordUrl() const; + const std::string& getLoginUri() const { return mLoginUri; } + const std::string& getLoginPage() const { return mLoginPage; } + const std::string& getHelperUri() const { return mHelperUri; } + const std::string& getWebSite() const { return mWebSite; } + const std::string& getSupportUrl() const { return mSupportUrl; } + const std::string& getRegisterUrl() const { return mRegisterUrl; } + const std::string& getPasswordUrl() const { return mPasswordUrl; } // Returns the url base used for the Web Search tab - const std::string& getSearchUrl() const; - const std::string& getGridMessage() const; + const std::string& getSearchUrl() const { return mSearchUrl; } + const std::string& getGridMessage() const { return mGridMessage; } const std::string& getVoiceConnector() const { return mVoiceConnector; } std::string getSearchUrl(SearchType ty, bool is_web) const; - bool isRenderCompat() const; - std::string getGridNick(); + bool isRenderCompat() const { return mRenderCompat; } + std::string getGridNick(); int getMaxAgentGroups() const { return mMaxAgentGroups; } - const std::string& getCurrencySymbol() const; - const std::string& getRealCurrencySymbol() const; + const std::string& getCurrencySymbol() const { return mCurrencySymbol; } + const std::string& getCurrencyText() const { return mCurrencyText; } + const std::string& getRealCurrencySymbol() const { return mRealCurrencySymbol; } std::string getUploadFee() const; std::string getGroupCreationFee() const; std::string getDirectoryFee() const; @@ -82,8 +84,11 @@ public: void setRenderCompat(bool compat); void setMaxAgentGroups(int max) { mMaxAgentGroups = max; } void setVoiceConnector(const std::string& vc) { mVoiceConnector = vc; } + void setUPCSupported(bool on); + bool getUPCSupported(); void setCurrencySymbol(const std::string& sym); + void setCurrencyText(const std::string& text); void setRealCurrencySymbol(const std::string& sym); void setDirectoryFee(int fee); bool supportsInvLinks(); @@ -113,12 +118,15 @@ private: std::string mSearchUrl; std::string mVoiceConnector; bool mIsInProductionGrid; + bool mIsInAvination; bool mRenderCompat; bool mInvLinks; bool mAutoUpdate; + bool mUPCSupported; int mMaxAgentGroups; std::string mCurrencySymbol; + std::string mCurrencyText; std::string mRealCurrencySymbol; int mDirectoryFee; std::string mGridMessage; @@ -152,7 +160,8 @@ public: void discardAndReload(); HippoGridInfo* getGrid(const std::string& grid) const; - HippoGridInfo* getConnectedGrid() const; + HippoGridInfo* getConnectedGrid() const { return mConnectedGrid ? mConnectedGrid : getCurrentGrid(); } + HippoGridInfo* getCurrentGrid() const; const std::string& getDefaultGridNick() const; const std::string& getCurrentGridNick() const; diff --git a/indra/newview/hippopanelgrids.cpp b/indra/newview/hippopanelgrids.cpp index 61ebcdde2..6af943c5b 100644 --- a/indra/newview/hippopanelgrids.cpp +++ b/indra/newview/hippopanelgrids.cpp @@ -133,7 +133,7 @@ BOOL HippoPanelGridsImpl::postBuild() requires("btn_add"); requires("btn_copy"); requires("btn_default"); - //requires("btn_gridinfo"); + requires("btn_gridinfo"); requires("btn_help_render_compat"); if (!checkRequirements()) return false; @@ -146,7 +146,7 @@ BOOL HippoPanelGridsImpl::postBuild() childSetAction("btn_add", onClickAdd, this); childSetAction("btn_copy", onClickCopy, this); childSetAction("btn_default", onClickDefault, this); - //childSetAction("btn_gridinfo", onClickGridInfo, this); + childSetAction("btn_gridinfo", onClickGridInfo, this); childSetAction("btn_help_render_compat", onClickHelpRenderCompat, this); childSetAction("btn_advanced", onClickAdvanced, this); diff --git a/indra/newview/lfsimfeaturehandler.cpp b/indra/newview/lfsimfeaturehandler.cpp new file mode 100644 index 000000000..bce7124ae --- /dev/null +++ b/indra/newview/lfsimfeaturehandler.cpp @@ -0,0 +1,66 @@ +/* Copyright (C) 2013 Liru Færs + * + * 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 */ + +#include "llviewerprecompiledheaders.h" + +#include "lfsimfeaturehandler.h" + +#include "llagent.h" +#include "llenvmanager.h" +#include "llviewerregion.h" +#include "hippogridmanager.h" + +LFSimFeatureHandler::LFSimFeatureHandler() +: mSupportsExport(false) +{ + if (!gHippoGridManager->getCurrentGrid()->isSecondLife()) // Remove this line if we ever handle SecondLife sim features + LLEnvManagerNew::instance().setRegionChangeCallback(boost::bind(&LFSimFeatureHandler::handleRegionChange, this)); +} + +void LFSimFeatureHandler::handleRegionChange() +{ + if (LLViewerRegion* region = gAgent.getRegion()) + { + if (region->getFeaturesReceived()) + { + setSupportedFeatures(); + } + else + { + region->setFeaturesReceivedCallback(boost::bind(&LFSimFeatureHandler::setSupportedFeatures, this)); + } + } +} + +void LFSimFeatureHandler::setSupportedFeatures() +{ + if (LLViewerRegion* region = gAgent.getRegion()) + { + LLSD info; + region->getSimulatorFeatures(info); + //if (!gHippoGridManager->getCurrentGrid()->isSecondLife()) // Non-SL specific sim features + { + mSupportsExport = info.has("ExportSupported"); + } + } +} + +boost::signals2::connection LFSimFeatureHandler::setSupportsExportCallback(const boost::signals2::signal::slot_type& slot) +{ + return mSupportsExport.connect(slot); +} + diff --git a/indra/newview/lfsimfeaturehandler.h b/indra/newview/lfsimfeaturehandler.h new file mode 100644 index 000000000..070d6ba1e --- /dev/null +++ b/indra/newview/lfsimfeaturehandler.h @@ -0,0 +1,70 @@ +/* Copyright (C) 2013 Liru Færs + * + * 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 LFSIMFEATUREHANDLER_H +#define LFSIMFEATUREHANDLER_H + +#include "llsingleton.h" + +template +class SignaledType +{ +public: + SignaledType(Type b) : mValue(b) {} + + template + boost::signals2::connection connect(Slot slot) { return mSignal.connect(slot); } + + SignaledType& operator =(Type val) + { + if (val != mValue) + { + mValue = val; + mSignal(); + } + return *this; + } + operator Type() const { return mValue; } + +private: + boost::signals2::signal mSignal; + Type mValue; +}; + +class LFSimFeatureHandler : public LLSingleton +{ +protected: + friend class LLSingleton; + LFSimFeatureHandler(); + +public: + void handleRegionChange(); + void setSupportedFeatures(); + + // Connection setters + boost::signals2::connection setSupportsExportCallback(const boost::signals2::signal::slot_type& slot); + + // Accessors + bool simSupportsExport() const { return mSupportsExport; } + +private: + // SignaledTypes + SignaledType mSupportsExport; +}; + +#endif //LFSIMFEATUREHANDLER_H + diff --git a/indra/newview/linux_tools/client-readme-voice.txt b/indra/newview/linux_tools/client-readme-voice.txt index 23a42f484..aa04a5704 100644 --- a/indra/newview/linux_tools/client-readme-voice.txt +++ b/indra/newview/linux_tools/client-readme-voice.txt @@ -4,14 +4,20 @@ Second Life - Linux Voice Support README WHAT IS IT? -=-=-=-=-=- -Linux Voice Support is a new feature in testing which allows users -of the Linux Second Life client to participate in voice-chat with other -residents and groups inside Second Life, with an appropriate -headset/microphone. +Linux Voice Support is a feature in testing which allows users of the Linux +Second Life client to participate in voice-chat with other residents and +groups inside Second Life, with an appropriate headset/microphone. Linux Voice Support is currently EXPERIMENTAL and is known to still have some compatibility issues. +SINGULARITY MULTI-VOICE +-=-=-=-=-=-=-=-=-=-=-=- +Singularity multi-voice is an experimental feature that allows you to run multiple +SLVoice daemons at the same time, in order to do this, the debug setting VoiceMultiInstance +must be TRUE, this allows multiple instances of the viewer to run concurrently and +each connect to voice. + REQUIREMENTS -=-=-=-=-=-= @@ -29,6 +35,13 @@ systems: * Fedora Core 6 with (unknown) audio chipset * Ubuntu 8.04 (Hardy) with (unknown) audio chipset +TESTING YOUR SETTINGS +-=-=-=-=-=-=-=-=-=-=- + +* The Second Life region 'Voice Echo Canyon' is a great place for testing +your hardware settings and quality - it will 'echo' your voice back to you +when you speak. + KNOWN PROBLEMS -=-=-=-=-=-=-= @@ -41,12 +54,12 @@ TROUBLESHOOTING PROBLEM 1: I don't see a white dot over the head of my avatar or other Voice-using avatars. SOLUTION: -a. Ensure that 'Enable voice chat' is enabled in the Voice Chat - preferences window and that you are in a voice-enabled area (you - will see a blue headphone icon in the SL menu-bar). +a. Ensure that 'Enable voice chat' is enabled in the 'Voice Chat' section of the + Preferences window, and that you are in a voice-enabled area + (you will see a blue headphone icon in the SL menu-bar). b. If the above does not help, exit Second Life and ensure that any remaining 'SLVoice' processes (as reported by 'ps', 'top' or similar) - are killed. + are killed before restarting. PROBLEM 2: I have a white dot over my head but I never see (or hear!) anyone except myself listed in the Active Speakers dialog when I'm sure that other @@ -65,12 +78,13 @@ c. Update to the latest version of ALSA manually. For a guide, see the PROBLEM 3: I can hear other people, but they cannot hear me. SOLUTION: -a. Ensure that you have the 'Talk' button activated while you are trying to - speak. +a. Ensure that you have the 'Talk' button (at the bottom of the Second Life + window)activated while you are trying to speak. b. Ensure that your microphone jack is inserted into the correct socket of your sound card, where appropriate. -c. Use your system mixer-setting program or the 'alsamixer' program to ensure - that microphone input is set as the active input source and is not muted. +c. Use your system mixer-setting program (such as the PulseAudio 'volume + control' applet or the ALSA 'alsamixer' program) to ensure that microphone + input is set as the active input source and is not muted. d. Verify that audio input works in other applications, i.e. Audacity PROBLEM 4: Other people just hear bursts of loud noise when I speak. diff --git a/indra/newview/linux_tools/client-readme.txt b/indra/newview/linux_tools/client-readme.txt index 99c973f7e..f9f60c833 100644 --- a/indra/newview/linux_tools/client-readme.txt +++ b/indra/newview/linux_tools/client-readme.txt @@ -15,7 +15,7 @@ Life itself - please see . 5.3. Blank window after minimizing it 5.4. Audio 5.5. 'Alt' key for camera controls doesn't work - 5.6. In-world streaming movie/music playback + 5.6. In-world streaming movie, music and Flash playback 6. Advanced Troubleshooting 6.1. Audio 6.2. OpenGL @@ -75,10 +75,11 @@ Life Linux client is very similar to that for Windows, as detailed at: 3. INSTALLING & RUNNING -=-=-=-=-=-=-=-=-=-=-=- -The Second Life Linux client entirely runs out of the directory you have -unpacked it into - no installation step is required. +The Singularity Linux client can entirely run from the directory you have +unpacked it into - no installation step is required. If you wish to +perform a separate installation step anyway, you may run './install.sh' -Run ./secondlife from the installation directory to start Second Life. +Run ./singularity from the installation directory to start Singularity. For in-world MOVIE and MUSIC PLAYBACK, you will need (32-bit) GStreamer 0.10 installed on your system. This is optional - it is not required for general @@ -168,12 +169,15 @@ SOLUTION:- Some window managers eat the Alt key for their own purposes; you example, the 'Windows' key!) which will allow the Alt key to function properly with mouse actions in Second Life and other applications. -PROBLEM 6:- In-world movie and/or music playback doesn't work for me. +PROBLEM 6:- In-world movie, music, or Flash playback doesn't work for me. SOLUTION:- You need to have a working installation of GStreamer 0.10; this is usually an optional package for most versions of Linux. If you have installed GStreamer 0.10 and you can play some music/movies but not others then you need to install a wider selection of GStreamer plugins, either - from your vendor or an appropriate third party. + from your vendor (i.e. the 'Ugly' plugins) or an appropriate third party. + For Flash playback, you need to have Flash 10 installed for your normal + web browser (for example, Firefox). PulseAudio is required for Flash + volume control / muting to fully function inside Second Life. 6. ADVANCED TROUBLESHOOTING diff --git a/indra/newview/linux_tools/install.sh b/indra/newview/linux_tools/install.sh new file mode 100644 index 000000000..86d020671 --- /dev/null +++ b/indra/newview/linux_tools/install.sh @@ -0,0 +1,106 @@ +#!/bin/bash + +# Install Singularity Viewer. This script can install the viewer both +# system-wide and for an individual user. + +VT102_STYLE_NORMAL='\E[0m' +VT102_COLOR_RED='\E[31m' + +SCRIPTSRC=`readlink -f "$0" || echo "$0"` +RUN_PATH=`dirname "${SCRIPTSRC}" || echo .` +tarball_path=${RUN_PATH} + +function prompt() +{ + local prompt=$1 + local input + + echo -n "$prompt" + + while read input; do + case $input in + [Yy]* ) + return 1 + ;; + [Nn]* ) + return 0 + ;; + * ) + echo "Please enter yes or no." + echo -n "$prompt" + esac + done +} + +function die() +{ + warn $1 + exit 1 +} + +function warn() +{ + echo -n -e $VT102_COLOR_RED + echo $1 + echo -n -e $VT102_STYLE_NORMAL +} + +function homedir_install() +{ + warn "You are not running as a privileged user, so you will only be able" + warn "to install Singularity Viewer in your home directory. If you" + warn "would like to install Singularity Viewer system-wide, please run" + warn "this script as the root user, or with the 'sudo' command." + echo + + prompt "Proceed with the installation? [Y/N]: " + if [[ $? == 0 ]]; then + exit 0 + fi + + install_to_prefix "$HOME/.singularity-install" + $HOME/.singularity-install/refresh_desktop_app_entry.sh +} + +function root_install() +{ + local default_prefix="/opt/singularity-install" + + echo -n "Enter the desired installation directory [${default_prefix}]: "; + read + if [[ "$REPLY" = "" ]] ; then + local install_prefix=$default_prefix + else + local install_prefix=$REPLY + fi + + install_to_prefix "$install_prefix" + + mkdir -p /usr/local/share/applications + ${install_prefix}/refresh_desktop_app_entry.sh +} + +function install_to_prefix() +{ + test -e "$1" && backup_previous_installation "$1" + mkdir -p "$1" || die "Failed to create installation directory!" + + echo " - Installing to $1" + + cp -a "${tarball_path}"/* "$1/" || die "Failed to complete the installation!" +} + +function backup_previous_installation() +{ + local backup_dir="$1".backup-$(date -I) + echo " - Backing up previous installation to $backup_dir" + + mv "$1" "$backup_dir" || die "Failed to create backup of existing installation!" +} + + +if [ "$UID" == "0" ]; then + root_install +else + homedir_install +fi diff --git a/indra/newview/linux_tools/refresh_desktop_app_entry.sh b/indra/newview/linux_tools/refresh_desktop_app_entry.sh new file mode 100755 index 000000000..9412c840c --- /dev/null +++ b/indra/newview/linux_tools/refresh_desktop_app_entry.sh @@ -0,0 +1,36 @@ +#!/bin/bash + +SCRIPTSRC=`readlink -f "$0" || echo "$0"` +RUN_PATH=`dirname "${SCRIPTSRC}" || echo .` + +install_prefix=${RUN_PATH} + +function install_desktop_entry() +{ + local installation_prefix="$1" + local desktop_entries_dir="$2" + + local desktop_entry="\ +[Desktop Entry]\n\ +Name=Singularity\n\ +Comment=Client for Online Virtual Worlds, such as Second Life\n\ +Exec=${installation_prefix}/singularity\n\ +Icon=${installation_prefix}/singularity_icon.png\n\ +Terminal=false\n\ +Type=Application\n\ +Categories=Application;Network;\n\ +StartupNotify=true\n\ +X-Desktop-File-Install-Version=3.0" + + echo " - Installing menu entries in ${desktop_entries_dir}" + mkdir -vp "${desktop_entries_dir}" + echo -e $desktop_entry > "${desktop_entries_dir}/singularity-viewer.desktop" || "Failed to install application menu!" +} + +if [ "$UID" == "0" ]; then + # system-wide + install_desktop_entry "$install_prefix" /usr/local/share/applications +else + # user-specific + install_desktop_entry "$install_prefix" "$HOME/.local/share/applications" +fi diff --git a/indra/newview/linux_tools/wrapper.sh b/indra/newview/linux_tools/wrapper.sh index e406e3c71..0806df29d 100755 --- a/indra/newview/linux_tools/wrapper.sh +++ b/indra/newview/linux_tools/wrapper.sh @@ -4,10 +4,10 @@ ## These options are for self-assisted troubleshooting during this beta ## testing phase; you should not usually need to touch them. -## - Avoids using any OpenAL audio driver. -#export LL_BAD_OPENAL_DRIVER=x ## - Avoids using any FMOD Ex audio driver. #export LL_BAD_FMODEX_DRIVER=x +## - Avoids using any OpenAL audio driver. +#export LL_BAD_OPENAL_DRIVER=x ## - Avoids using any FMOD audio driver. #export LL_BAD_FMOD_DRIVER=x @@ -20,7 +20,6 @@ ## - Avoids using the FMOD or FMOD Ex ESD audio driver. #export LL_BAD_FMOD_ESD=x - ## - Avoids the optional OpenGL extensions which have proven most problematic ## on some hardware. Disabling this option may cause BETTER PERFORMANCE but ## may also cause CRASHES and hangs on some unstable combinations of drivers @@ -109,6 +108,10 @@ cd "${RUN_PATH}" # Re-register the secondlife:// protocol handler every launch, for now. ./register_secondlifeprotocol.sh + +# Re-register the application with the desktop system every launch, for now. +./refresh_desktop_app_entry.sh + ## Before we mess with LD_LIBRARY_PATH, save the old one to restore for ## subprocesses that care. export SAVED_LD_LIBRARY_PATH="${LD_LIBRARY_PATH}" @@ -138,7 +141,7 @@ if [ -n "$LL_TCMALLOC" ]; then fi export VIEWER_BINARY='singularity-do-not-run-directly' -BINARY_TYPE=$(expr match "$(file -b bin/$VIEWER_BINARY)" '\(.*executable\)') +BINARY_TYPE=$(expr match "$(file -b bin/$VIEWER_BINARY)" '\(.*executable\)' | sed -e 's/ / /g') if [ "${BINARY_TYPE}" == "ELF 64-bit LSB executable" ]; then SL_ENV+='LD_LIBRARY_PATH="`pwd`/lib64:`pwd`/lib32:$LD_LIBRARY_PATH"' else @@ -147,16 +150,11 @@ fi export SL_CMD='$LL_WRAPPER bin/$VIEWER_BINARY' export SL_OPT="`cat gridargs.dat` $@" -# Run the program +# Run the program. eval ${SL_ENV} ${SL_CMD} ${SL_OPT} || LL_RUN_ERR=runerr # Handle any resulting errors if [ -n "$LL_RUN_ERR" ]; then - LL_RUN_ERR_MSG="" - if [ "$LL_RUN_ERR" = "runerr" ]; then - # generic error running the binary - echo '*** Bad shutdown. ***' - - - fi + # generic error running the binary + echo '*** Bad shutdown. ***' fi diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index 2610a2732..1f46baa7e 100644 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -229,9 +229,6 @@ private: // Statics // -BOOL LLAgent::exlPhantom = 0; -BOOL LLAgent::mForceTPose = 0; - const F32 LLAgent::TYPING_TIMEOUT_SECS = 5.f; std::map LLAgent::sTeleportErrorMessages; @@ -652,17 +649,6 @@ BOOL LLAgent::getFlying() const return mControlFlags & AGENT_CONTROL_FLY; } -// Better Set Phantom options ~Charbl -void LLAgent::setPhantom(BOOL phantom) -{ - exlPhantom = phantom; -} - -BOOL LLAgent::getPhantom() -{ - return exlPhantom; -} - //----------------------------------------------------------------------------- // setFlying() //----------------------------------------------------------------------------- @@ -727,8 +713,14 @@ void LLAgent::setFlying(BOOL fly) //----------------------------------------------------------------------------- // toggleFlying() //----------------------------------------------------------------------------- +// static void LLAgent::toggleFlying() { + if ( gAgent.mAutoPilot ) + { + LLToolPie::instance().stopClickToWalk(); + } + BOOL fly = !gAgent.getFlying(); gAgent.setFlying( fly ); @@ -758,20 +750,6 @@ void LLAgent::standUp() // [/RLVa:KB] } -void LLAgent::togglePhantom() -{ - BOOL phan = !(exlPhantom); - - setPhantom( phan ); -} - -void LLAgent::toggleTPosed() -{ - BOOL posed = !(mForceTPose); - - setTPosed(posed); -} - void LLAgent::handleServerBakeRegionTransition(const LLUUID& region_id) { llinfos << "called" << llendl; @@ -1315,17 +1293,6 @@ LLQuaternion LLAgent::getQuat() const //----------------------------------------------------------------------------- U32 LLAgent::getControlFlags() { -/* - // HACK -- avoids maintenance of control flags when camera mode is turned on or off, - // only worries about it when the flags are measured - if (mCameraMode == CAMERA_MODE_MOUSELOOK) - { - if ( !(mControlFlags & AGENT_CONTROL_MOUSELOOK) ) - { - mControlFlags |= AGENT_CONTROL_MOUSELOOK; - } - } -*/ return mControlFlags; } @@ -1419,9 +1386,8 @@ void LLAgent::setAFK() //----------------------------------------------------------------------------- void LLAgent::clearAFK() { + if (gSavedSettings.getBOOL("FakeAway")) return; gAwayTriggerTimer.reset(); - if (!gSavedSettings.controlExists("FakeAway")) gSavedSettings.declareBOOL("FakeAway", FALSE, "", NO_PERSIST); - if (gSavedSettings.getBOOL("FakeAway") == TRUE) return; // Gods can sometimes get into away state (via gestures) // without setting the appropriate control flag. JC @@ -1917,8 +1883,7 @@ BOOL LLAgent::needsRenderHead() //----------------------------------------------------------------------------- void LLAgent::startTyping() { - if (gSavedSettings.getBOOL("FakeAway")) - return; + if (gSavedSettings.getBOOL("FakeAway")) return; mTypingTimer.reset(); if (getRenderState() & AGENT_STATE_TYPING) @@ -2035,6 +2000,7 @@ void LLAgent::endAnimationUpdateUI() { (*mMouselookModeOutSignal)(); } + // Only pop if we have pushed... if (TRUE == mViewsPushed) { @@ -4092,6 +4058,7 @@ void LLAgent::teleportViaLandmark(const LLUUID& landmark_asset_id) return; } // [/RLVa:KB] + mTeleportRequest = LLTeleportRequestPtr(new LLTeleportRequestViaLandmark(landmark_asset_id)); startTeleportRequest(); } @@ -4189,6 +4156,7 @@ void LLAgent::teleportViaLocation(const LLVector3d& pos_global) } } // [/RLVa:KB] + mTeleportRequest = LLTeleportRequestPtr(new LLTeleportRequestViaLocation(pos_global)); startTeleportRequest(); } @@ -4261,6 +4229,7 @@ void LLAgent::teleportViaLocationLookAt(const LLVector3d& pos_global) return; } // [/RLVa:KB] + mTeleportRequest = LLTeleportRequestPtr(new LLTeleportRequestViaLocationLookAt(pos_global)); startTeleportRequest(); } @@ -4729,6 +4698,16 @@ void LLAgent::sendAgentUpdateUserInfo(bool im_via_email, const std::string& dire gMessageSystem->addString("DirectoryVisibility", directory_visibility); gAgent.sendReliableMessage(); } + +void LLAgent::dumpGroupInfo() +{ + llinfos << "group " << mGroupName << llendl; + llinfos << "ID " << mGroupID << llendl; + llinfos << "powers " << mGroupPowers << llendl; + llinfos << "title " << mGroupTitle << llendl; + //llinfos << "insig " << mGroupInsigniaID << llendl; +} + // Draw a representation of current autopilot target void LLAgent::renderAutoPilotTarget() { @@ -4974,4 +4953,5 @@ void LLTeleportRequestViaLocationLookAt::restartTeleport() { gAgent.doTeleportViaLocationLookAt(getPosGlobal()); } + // EOF diff --git a/indra/newview/llagent.h b/indra/newview/llagent.h index 51b8c2e6e..6ae193677 100644 --- a/indra/newview/llagent.h +++ b/indra/newview/llagent.h @@ -94,12 +94,13 @@ struct LLGroupData // forward declarations -// - +//------------------------------------------------------------------------ +// LLAgent +//------------------------------------------------------------------------ class LLAgent : public LLOldEvents::LLObservable { LOG_CLASS(LLAgent); - + public: friend class LLAgentDropGroupViewerNode; @@ -160,7 +161,7 @@ public: public: void getName(std::string& name); //Legacy void buildFullname(std::string &name) const; //Legacy - // *TODO remove, is not used as of August 20, 2009 + //*TODO remove, is not used as of August 20, 2009 void buildFullnameAndTitle(std::string &name) const; //-------------------------------------------------------------------- @@ -169,11 +170,11 @@ public: public: // On the very first login, gender isn't chosen until the user clicks // in a dialog. We don't render the avatar until they choose. - BOOL isGenderChosen() const { return mGenderChosen; } - void setGenderChosen(BOOL b) { mGenderChosen = b; } - private: + BOOL isGenderChosen() const { return mGenderChosen; } + void setGenderChosen(BOOL b) { mGenderChosen = b; } +private: BOOL mGenderChosen; - + /** Identity ** ** *******************************************************************************/ @@ -182,7 +183,7 @@ public: ** ** ** POSITION **/ - + //-------------------------------------------------------------------- // Position //-------------------------------------------------------------------- @@ -215,9 +216,9 @@ public: void resetAxes(); void resetAxes(const LLVector3 &look_at); // Makes reasonable left and up // The following three get*Axis functions return direction avatar is looking, not camera. - const LLVector3& getAtAxis() const { return mFrameAgent.getAtAxis(); } - const LLVector3& getUpAxis() const { return mFrameAgent.getUpAxis(); } - const LLVector3& getLeftAxis() const { return mFrameAgent.getLeftAxis(); } + const LLVector3& getAtAxis() const { return mFrameAgent.getAtAxis(); } + const LLVector3& getUpAxis() const { return mFrameAgent.getUpAxis(); } + const LLVector3& getLeftAxis() const { return mFrameAgent.getLeftAxis(); } LLQuaternion getQuat() const; // Returns the quat that represents the rotation of the agent in the absolute frame private: LLVector3d mAgentOriginGlobal; // Origin of agent coords from global coords @@ -229,7 +230,7 @@ private: //-------------------------------------------------------------------- public: void setStartPosition(U32 location_id); // Marks current location as start, sends information to servers - void setHomePosRegion( const U64& region_handle, const LLVector3& pos_region ); + void setHomePosRegion(const U64& region_handle, const LLVector3& pos_region); BOOL getHomePosGlobal(LLVector3d* pos_global); private: BOOL mHaveHomePosition; @@ -277,18 +278,18 @@ public: private: std::set mRegionsVisited; // Stat - what distinct regions has the avatar been to? F64 mDistanceTraveled; // Stat - how far has the avatar moved? - LLVector3d mLastPositionGlobal; // Used to calculate travel distance + LLVector3d mLastPositionGlobal; // Used to calculate travel distance /** Position ** ** *******************************************************************************/ - + /******************************************************************************** ** ** ** ACTIONS **/ - - //-------------------------------------------------------------------- + + //-------------------------------------------------------------------- // Fidget //-------------------------------------------------------------------- // Trigger random fidget animations @@ -311,7 +312,7 @@ public: static void toggleFlying(); static bool enableFlying(); BOOL canFly(); // Does this parcel allow you to fly? - + //-------------------------------------------------------------------- // Chat //-------------------------------------------------------------------- @@ -405,7 +406,7 @@ public: BOOL getBusy() const; private: BOOL mIsBusy; - + //-------------------------------------------------------------------- // Grab //-------------------------------------------------------------------- @@ -443,7 +444,7 @@ private: //-------------------------------------------------------------------- // Animations - //-------------------------------------------------------------------- + //-------------------------------------------------------------------- public: void stopCurrentAnimations(); void requestStopMotion(LLMotion* motion); @@ -675,7 +676,7 @@ public: // ! BACKWARDS COMPATIBILITY ! This function can go away after the AO transition (see llstartup.cpp). void setAOTransition(); private: - LLAgentAccess *mAgentAccess; + LLAgentAccess * mAgentAccess; //-------------------------------------------------------------------- // God @@ -720,7 +721,8 @@ public: bool isAdult() const; void setTeen(bool teen); void setMaturity(char text); - static int convertTextToMaturity(char text); + static int convertTextToMaturity(char text); + private: bool mIsDoSendMaturityPreferenceToServer; unsigned int mMaturityPreferenceRequestId; @@ -743,7 +745,6 @@ private: bool validateMaturity(const LLSD& newvalue); - /** Access ** ** *******************************************************************************/ @@ -778,20 +779,20 @@ private: // HUD //-------------------------------------------------------------------- public: - const LLColor4 &getEffectColor(); - void setEffectColor(const LLColor4 &color); + const LLColor4 &getEffectColor(); + void setEffectColor(const LLColor4 &color); private: LLColor4 *mEffectColor; /** Rendering ** ** *******************************************************************************/ - + /******************************************************************************** ** ** ** GROUPS **/ - + public: const LLUUID &getGroupID() const { return mGroupID; } // Get group information by group_id, or FALSE if not in group. @@ -828,7 +829,7 @@ public: private: std::string mGroupTitle; // Honorific, like "Sir" BOOL mHideGroupTitle; - + //-------------------------------------------------------------------- // Group Powers //-------------------------------------------------------------------- @@ -882,54 +883,22 @@ public: /** Messaging ** ** - *******************************************************************************/ + *******************************************************************************/ /******************************************************************************** ** ** ** DEBUGGING **/ - + public: - static void clearVisualParams(void *); + void dumpGroupInfo(); + static void clearVisualParams(void *); friend std::ostream& operator<<(std::ostream &s, const LLAgent &sphere); /** Debugging ** ** *******************************************************************************/ -/******************************************************************************** - ** ** - ** Phantom mode! - **/ - - public: - static BOOL getPhantom(); - static void setPhantom(BOOL phantom); - static void togglePhantom(); -private: - static BOOL exlPhantom; -/** PHANTOM - ** ** - *******************************************************************************/ - -/******************************************************************************** - ** ** - ** Depreciated stuff. Move when ready. - **/ -public: - //What's this t-posed stuff from? - static BOOL isTPosed() { return mForceTPose; } - static void setTPosed(BOOL TPose) { mForceTPose = TPose; } - static void toggleTPosed(); - -private: - static BOOL mForceTPose; - - -/** DEPRECIATED - ** ** - *******************************************************************************/ - }; extern LLAgent gAgent; diff --git a/indra/newview/llagentwearablesfetch.cpp b/indra/newview/llagentwearablesfetch.cpp index a1c60e921..3b48606a5 100644 --- a/indra/newview/llagentwearablesfetch.cpp +++ b/indra/newview/llagentwearablesfetch.cpp @@ -135,7 +135,7 @@ void LLInitialWearablesFetch::processContents() LLInventoryModel::cat_array_t cat_array; LLInventoryModel::item_array_t wearable_array; LLFindWearables is_wearable; - llassert_always(mComplete.size() != 0); + llassert(mComplete.size() != 0); gInventory.collectDescendentsIf(mComplete.front(), cat_array, wearable_array, LLInventoryModel::EXCLUDE_TRASH, is_wearable); diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index b561143ff..0a8e23bbe 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -3,10 +3,9 @@ * @brief The LLAppViewer class definitions * * $LicenseInfo:firstyear=2007&license=viewergpl$ - * + * Second Life Viewer Source Code * Copyright (c) 2007-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 @@ -30,8 +29,8 @@ * $/LicenseInfo$ */ - #include "llviewerprecompiledheaders.h" + #include "llappviewer.h" #include "hippogridmanager.h" @@ -56,14 +55,13 @@ #include "llmeshrepository.h" #include "llmodaldialog.h" #include "llpumpio.h" -#include "llimpanel.h" #include "llmimetypes.h" #include "llstartup.h" #include "llfocusmgr.h" #include "llviewerjoystick.h" -#include "llfloaterjoystick.h" #include "llares.h" -#include "llfloatersnapshot.h" +#include "llcurl.h" +#include "llcalc.h" #include "lltexturestats.h" #include "llviewerwindow.h" #include "llviewerdisplay.h" @@ -80,7 +78,9 @@ #include "llfirstuse.h" #include "llrender.h" #include "llvector4a.h" -#include "llfontfreetype.h" +#include "llimpanel.h" // For LLVoiceClient and LLVoiceChannel +#include "llvoavatarself.h" +#include "llprogressview.h" #include "llvocache.h" #include "llvopartgroup.h" #include "llfloaterteleporthistory.h" @@ -92,10 +92,10 @@ #include "llavatarnamecache.h" #include "lldiriterator.h" #include "llimagej2c.h" +#include "llmemory.h" #include "llprimitive.h" #include "llnotifications.h" #include "llnotificationsutil.h" -#include "llcurl.h" #include #if LL_WINDOWS @@ -121,7 +121,6 @@ #include "aihttptimeoutpolicy.h" // // The files below handle dependencies from cleanup. -#include "llcalc.h" #include "llkeyframemotion.h" #include "llworldmap.h" #include "llhudmanager.h" @@ -133,7 +132,6 @@ #include "llviewermenu.h" #include "llselectmgr.h" #include "lltrans.h" -#include "lltrans.h" #include "lltracker.h" #include "llviewerparcelmgr.h" #include "llworldmapview.h" @@ -144,15 +142,12 @@ #include "lldebugview.h" #include "llconsole.h" #include "llcontainerview.h" -#include "llfloaterstats.h" #include "llhoverview.h" -#include "llfloatermemleak.h" #include "llsdserialize.h" #include "llworld.h" #include "llhudeffecttrail.h" -#include "llhudeffectlookat.h" #include "llvectorperfoptions.h" #include "llurlsimstring.h" #include "llwatchdog.h" @@ -160,24 +155,23 @@ // Included so that constants/settings might be initialized // in save_settings_to_globals() #include "llbutton.h" -#include "llcombobox.h" #include "llstatusbar.h" #include "llsurface.h" #include "llvosky.h" #include "llvotree.h" -#include "llvoavatarself.h" #include "llfolderview.h" #include "lltoolbar.h" #include "llframestats.h" #include "llagentpilot.h" -#include "llsrv.h" #include "llvovolume.h" #include "llflexibleobject.h" #include "llvosurfacepatch.h" +#include "llcommandlineparser.h" +#include "llfloatermemleak.h" +#include "llfloatersnapshot.h" #include "llfloaterinventory.h" // includes for idle() idleShutdown() -#include "floaterao.h" #include "llviewercontrol.h" #include "lleventnotifier.h" #include "llcallbacklist.h" @@ -192,10 +186,7 @@ #include "llviewerthrottle.h" #include "llparcel.h" #include "llviewerassetstats.h" -#include "llcommandlineparser.h" -#include "llprogressview.h" -#include "llmemory.h" #include "llmainlooprepeater.h" // [RLVa:KB] @@ -223,12 +214,6 @@ //---------------------------------------------------------------------------- // viewer.cpp - these are only used in viewer, should be easily moved. - - - - - - #if LL_DARWIN extern void init_apple_menu(const char* product); #endif // LL_DARWIN @@ -486,6 +471,7 @@ static void settings_to_globals() LLSurface::setTextureSize(gSavedSettings.getU32("RegionTextureSize")); LLRender::sGLCoreProfile = gSavedSettings.getBOOL("RenderGLCoreProfile"); + LLImageGL::sGlobalUseAnisotropic = gSavedSettings.getBOOL("RenderAnisotropic"); LLImageGL::sCompressTextures = gSavedSettings.getBOOL("RenderCompressTextures"); LLVOVolume::sLODFactor = gSavedSettings.getF32("RenderVolumeLODFactor"); @@ -1199,6 +1185,7 @@ bool LLAppViewer::mainLoop() // canonical per-frame event mainloop.post(newFrame); + if (!LLApp::isExiting()) { pingMainloopTimeout("Main:JoystickKeyboard"); @@ -1206,7 +1193,7 @@ bool LLAppViewer::mainLoop() // Scan keyboard for movement keys. Command keys and typing // are handled by windows callbacks. Don't do this until we're // done initializing. JC - if (gViewerWindow->mWindow->getVisible() + if (gViewerWindow->mWindow->getVisible() && gViewerWindow->getActive() && !gViewerWindow->getWindow()->getMinimized() && LLStartUp::getStartupState() == STATE_STARTED @@ -1323,7 +1310,6 @@ bool LLAppViewer::mainLoop() ms_sleep(500); } - const F64 max_idle_time = run_multiple_threads ? 0.0 : llmin(.005*10.0*gFrameIntervalSeconds, 0.005); // 50ms/second, no more than 5ms/frame idleTimer.reset(); while(1) @@ -1385,7 +1371,6 @@ bool LLAppViewer::mainLoop() pingMainloopTimeout("Main:End"); } - } catch(std::bad_alloc) { @@ -1741,7 +1726,8 @@ bool LLAppViewer::cleanup() writeDebugInfo(); if(!gDirUtilp->getLindenUserDir(true).empty()) - LLViewerMedia::saveCookieFile(); + LLViewerMedia::saveCookieFile(); + // Stop the plugin read thread if it's running. LLPluginProcessParent::setUseReadThread(false); // Stop curl responder call backs. @@ -1761,11 +1747,11 @@ bool LLAppViewer::cleanup() pending += LLAppViewer::getTextureFetch()->update(1); // unpauses the texture fetch thread pending += LLVFSThread::updateClass(0); pending += LLLFSThread::updateClass(0); - if (pending == 0) + if (!pending) { break; } - if (idleTimer.getElapsedTimeF64() >= max_idle_time) + else if (idleTimer.getElapsedTimeF64() >= max_idle_time) { llwarns << "Quitting with pending background tasks." << llendl; break; @@ -1910,9 +1896,7 @@ bool LLAppViewer::initThreads() // State machine thread. startEngineThread(); - AICurlInterface::startCurlThread(gSavedSettings.getU32("CurlMaxTotalConcurrentConnections"), - gSavedSettings.getU32("CurlConcurrentConnectionsPerHost"), - gSavedSettings.getBOOL("NoVerifySSLCert")); + AICurlInterface::startCurlThread(&gSavedSettings); LLImage::initClass(); @@ -1930,6 +1914,7 @@ bool LLAppViewer::initThreads() // Mesh streaming and caching gMeshRepo.init(); + // *FIX: no error handling here! return true; } @@ -2125,20 +2110,14 @@ bool LLAppViewer::initConfiguration() if(!loadSettingsFromDirectory(settings_w, "Default", set_defaults)) { std::ostringstream msg; - msg << "Second Life could not load its default settings file. \n" - << "The installation may be corrupted. \n"; - - OSMessageBox( - msg.str(), - LLStringUtil::null, - OSMB_OK); - + msg << "Unable to load default settings file. The installation may be corrupted."; + OSMessageBox(msg.str(),LLStringUtil::null,OSMB_OK); return false; } LLUICtrlFactory::getInstance()->setupPaths(); // setup paths for LLTrans based on settings files only LLTrans::parseStrings("strings.xml", default_trans_args); - + //COA vars in gSavedSettings will be linked to gSavedPerAccountSettings entries that will be created if not present. //Signals will be shared between linked vars. gSavedSettings.connectCOAVars(gSavedPerAccountSettings); @@ -2168,8 +2147,8 @@ bool LLAppViewer::initConfiguration() // timeout for mac and linux. There is no call stack info // on these platform to help debug. #ifndef LL_RELEASE_FOR_DOWNLOAD - gSavedSettings.setBOOL("WatchdogEnabled", FALSE); gSavedSettings.setBOOL("QAMode", TRUE ); + gSavedSettings.setBOOL("WatchdogEnabled", 0); #endif #ifndef LL_WINDOWS @@ -2213,6 +2192,7 @@ bool LLAppViewer::initConfiguration() LLControlGroupCLP clp; std::string cmd_line_config = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "cmd_line.xml"); + clp.configure(cmd_line_config, &gSavedSettings); if(!initParseCommandLine(clp)) @@ -2248,9 +2228,8 @@ bool LLAppViewer::initConfiguration() clp.notify(); // Register the core crash option as soon as we can - // if we want gdb post-mortum on cores we need to be up and running + // if we want gdb post-mortem on cores we need to be up and running // ASAP or we might miss init issue etc. - if(clp.hasOption("disablecrashlogger")) { llwarns << "Crashes will be handled by system, stack trace logs and crash logger are both disabled" <getControl(name); - // if(c) - // { - // c->setDefault(value); - // } - // else - // { - // llwarns << "'--setdefault' specified with unknown setting: '" - // << name << "'." << llendl; - // } - // } - //} - } - if(clp.hasOption("set")) { const LLCommandLineParser::token_vector_t& set_values = clp.getOption("set"); @@ -2551,7 +2500,7 @@ bool LLAppViewer::initConfiguration() if ( nextLoginLocation.length() ) { LLURLSimString::setString( nextLoginLocation ); - }; + } gLastRunVersion = gSavedSettings.getString("LastRunVersion"); @@ -2743,7 +2692,6 @@ void LLAppViewer::writeSystemInfo() gDebugInfo["SLLog"] = LLError::logFileName(); gDebugInfo["ClientInfo"]["Name"] = gVersionChannel; - gDebugInfo["ClientInfo"]["MajorVersion"] = gVersionMajor; gDebugInfo["ClientInfo"]["MinorVersion"] = gVersionMinor; gDebugInfo["ClientInfo"]["PatchVersion"] = gVersionPatch; @@ -2751,7 +2699,6 @@ void LLAppViewer::writeSystemInfo() gDebugInfo["CAFilename"] = gDirUtilp->getCAFile(); - //need to put in something to lie about this stuff gDebugInfo["CPUInfo"]["CPUString"] = gSysCPU.getCPUString(); gDebugInfo["CPUInfo"]["CPUFamily"] = gSysCPU.getFamily(); gDebugInfo["CPUInfo"]["CPUMhz"] = gSysCPU.getMHz(); @@ -2764,10 +2711,10 @@ void LLAppViewer::writeSystemInfo() gDebugInfo["OSInfo"] = getOSInfo().getOSStringSimple(); // The user is not logged on yet, but record the current grid choice login url - // which may have been the intended grid. This can b + // which may have been the intended grid. gDebugInfo["GridName"] = LLViewerLogin::getInstance()->getGridLabel(); - // *FIX:Mani - move this ddown in llappviewerwin32 + // *FIX:Mani - move this down in llappviewerwin32 #ifdef LL_WINDOWS DWORD thread_id = GetCurrentThreadId(); gDebugInfo["MainloopThreadID"] = (S32)thread_id; @@ -2817,6 +2764,7 @@ void LLAppViewer::handleViewerCrash() llinfos << "Last render pool type: " << LLPipeline::sCurRenderPoolType << llendl ; LLMemory::logMemoryInfo(true) ; + //print out recorded call stacks if there are any. LLError::LLCallStacks::print(); @@ -2845,7 +2793,6 @@ void LLAppViewer::handleViewerCrash() //We already do this in writeSystemInfo(), but we do it again here to make /sure/ we have a version //to check against no matter what - gDebugInfo["ClientInfo"]["Name"] = gVersionChannel; gDebugInfo["ClientInfo"]["MajorVersion"] = gVersionMajor; @@ -3023,13 +2970,11 @@ void LLAppViewer::initMarkerFile() std::string llerror_marker_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, LLERROR_MARKER_FILE_NAME); std::string error_marker_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, ERROR_MARKER_FILE_NAME); - if (LLAPRFile::isExist(mMarkerFileName, LL_APR_RB) && !anotherInstanceRunning()) { gLastExecEvent = LAST_EXEC_FROZE; LL_INFOS("MarkerFile") << "Exec marker found: program froze on previous execution" << LL_ENDL; } - if(LLAPRFile::isExist(logout_marker_file, LL_APR_RB)) { gLastExecEvent = LAST_EXEC_LOGOUT_FROZE; @@ -3741,17 +3686,6 @@ void LLAppViewer::loadNameCache() { if(gCacheName->importFile(cache_file)) return; } - - // Try to load from the legacy format. This should go away after a - // while. Phoenix 2008-01-30 -#if 0 - LLFILE* name_cache_fp = LLFile::fopen(name_cache, "r"); // Flawfinder: ignore - if (name_cache_fp) - { - gCacheName->importFile(name_cache_fp); - fclose(name_cache_fp); - } -#endif } void LLAppViewer::saveNameCache() @@ -3804,6 +3738,7 @@ static LLFastTimer::DeclareTimer FTM_WORLD_UPDATE("Update World"); static LLFastTimer::DeclareTimer FTM_NETWORK("Network"); static LLFastTimer::DeclareTimer FTM_AGENT_NETWORK("Agent Network"); static LLFastTimer::DeclareTimer FTM_VLMANAGER("VL Manager"); + /////////////////////////////////////////////////////// // idle() // @@ -3864,7 +3799,6 @@ void LLAppViewer::idle() // // Special case idle if still starting up // - if (LLStartUp::getStartupState() < STATE_STARTED) { // Skip rest if idle startup returns false (essentially, no world yet) @@ -3916,10 +3850,7 @@ void LLAppViewer::idle() LLFastTimer t(FTM_AGENT_UPDATE); // Send avatar and camera info last_control_flags = gAgent.getControlFlags(); - if(!gAgent.getPhantom()) - { - send_agent_update(TRUE); - } + send_agent_update(TRUE); agent_update_timer.reset(); } } @@ -3929,7 +3860,6 @@ void LLAppViewer::idle() // Manage statistics // // - { // Initialize the viewer_stats_timer with an already elapsed time // of SEND_STATS_PERIOD so that the initial stats report will @@ -4328,7 +4258,6 @@ void LLAppViewer::sendLogoutRequest() { if(!mLogoutRequestSent && gMessageSystem) { - LLMessageSystem* msg = gMessageSystem; msg->newMessageFast(_PREHASH_LogoutRequest); msg->nextBlockFast(_PREHASH_AgentData); @@ -4432,6 +4361,7 @@ static LLFastTimer::DeclareTimer FTM_RETRANSMIT("Retransmit"); static LLFastTimer::DeclareTimer FTM_TIMEOUT_CHECK("Timeout Check"); static LLFastTimer::DeclareTimer FTM_DYNAMIC_THROTTLE("Dynamic Throttle"); static LLFastTimer::DeclareTimer FTM_CHECK_REGION_CIRCUIT("Check Region Circuit"); + void LLAppViewer::idleNetwork() { pingMainloopTimeout("idleNetwork"); @@ -4449,7 +4379,8 @@ void LLAppViewer::idleNetwork() // Read all available packets from network const S64 frame_count = gFrameCount; // U32->S64 F32 total_time = 0.0f; - while (gMessageSystem->checkAllMessages(frame_count, gServicePump)) + + while (gMessageSystem->checkAllMessages(frame_count, gServicePump)) { if (gDoDisconnect) { diff --git a/indra/newview/llassetuploadresponders.cpp b/indra/newview/llassetuploadresponders.cpp index 77a0558f1..de8da30e6 100644 --- a/indra/newview/llassetuploadresponders.cpp +++ b/indra/newview/llassetuploadresponders.cpp @@ -3,10 +3,9 @@ * @brief Processes responses received for asset upload requests. * * $LicenseInfo:firstyear=2007&license=viewergpl$ - * + * Second Life Viewer Source Code * Copyright (c) 2007-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 @@ -53,7 +52,6 @@ #include "llviewerobject.h" #include "llviewercontrol.h" #include "llviewerobjectlist.h" -#include "llviewermenufile.h" #include "llviewertexlayer.h" #include "llviewerwindow.h" #include "lltrans.h" @@ -255,6 +253,7 @@ void LLAssetUploadResponder::result(const LLSD& content) lldebugs << "LLAssetUploadResponder::result from capabilities" << llendl; std::string state = content["state"]; + if (state == "upload") { uploadUpload(content); @@ -343,6 +342,7 @@ void LLNewAgentInventoryResponder::error(U32 statusNum, const std::string& reaso //LLImportColladaAssetCache::getInstance()->assetUploaded(mVFileID, LLUUID(), FALSE); } + //virtual void LLNewAgentInventoryResponder::uploadFailure(const LLSD& content) { @@ -351,6 +351,7 @@ void LLNewAgentInventoryResponder::uploadFailure(const LLSD& content) (*mCallBack)(false, mUserData); } LLAssetUploadResponder::uploadFailure(content); + //LLImportColladaAssetCache::getInstance()->assetUploaded(mVFileID, content["new_asset"], FALSE); } @@ -397,10 +398,14 @@ void LLNewAgentInventoryResponder::uploadComplete(const LLSD& content) // continue uploading for bulk uploads - if (!gUploadQueue.empty()) + /* Singu Note: sUploadQueue was never getting populated, anywhere! Therefore, this entire block never was reached. + ** I have condensed it to here in the hopes it may one day see use. Apparently, it came in with Siana's prep work + ** for mesh upload (697dd7e9298282590f8cf858a58335f70302532b), but we never needed it. + static std::deque sUploadQueue; + if (!sUploadQueue.empty()) { - std::string next_file = gUploadQueue.front(); - gUploadQueue.pop_front(); + std::string next_file = sUploadQueue.front(); + sUploadQueue.pop_front(); if (next_file.empty()) return; std::string name = gDirUtilp->getBaseFileName(next_file, true); @@ -448,6 +453,7 @@ void LLNewAgentInventoryResponder::uploadComplete(const LLSD& content) expected_upload_cost, userdata); } + */ } LLSendTexLayerResponder::LLSendTexLayerResponder(const LLSD& post_data, @@ -698,6 +704,7 @@ void LLUpdateTaskInventoryResponder::uploadComplete(const LLSD& content) } } + ///////////////////////////////////////////////////// // LLNewAgentInventoryVariablePriceResponder::Impl // ///////////////////////////////////////////////////// @@ -1165,3 +1172,4 @@ void LLNewAgentInventoryVariablePriceResponder::showConfirmationDialog( boost::intrusive_ptr(this))); } } + diff --git a/indra/newview/llestateinfomodel.h b/indra/newview/llestateinfomodel.h index 56391eda9..30e83b140 100644 --- a/indra/newview/llestateinfomodel.h +++ b/indra/newview/llestateinfomodel.h @@ -56,7 +56,8 @@ public: const std::string& getName() const { return mName; } const LLUUID& getOwnerID() const { return mOwnerID; } U32 getID() const { return mID; } - F32 getSunHour() const { return getUseFixedSun() ? mSunHour : 0.f; } + F32 getSunHour() const { return mSunHour; } + bool getGlobalTime() const { return !(mSunHour || getUseFixedSun()); } // setters void setUseFixedSun(bool val); diff --git a/indra/newview/lleventpoll.cpp b/indra/newview/lleventpoll.cpp index 3efc942da..75d3c4eda 100644 --- a/indra/newview/lleventpoll.cpp +++ b/indra/newview/lleventpoll.cpp @@ -237,7 +237,7 @@ namespace if (!content.get("events") || !content.get("id")) { - llwarns << "received event poll with no events or id key" << llendl; + //llwarns << "received event poll with no events or id key" << llendl; makeRequest(); return; } diff --git a/indra/newview/llfloateranimpreview.cpp b/indra/newview/llfloateranimpreview.cpp index b869580f6..8fdfc1a93 100644 --- a/indra/newview/llfloateranimpreview.cpp +++ b/indra/newview/llfloateranimpreview.cpp @@ -2,9 +2,7 @@ * @file llfloateranimpreview.cpp * @brief LLFloaterAnimPreview class implementation * - * $LicenseInfo:firstyear=2004&license=viewergpl$ - * - * Copyright (c) 2004-2009, Linden Research, Inc. + * Copyright (c) 2012, Linden Research, Inc. * * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab @@ -31,1596 +29,18 @@ */ #include "llviewerprecompiledheaders.h" - #include "llfloateranimpreview.h" -#include "llbvhloader.h" -#include "lldatapacker.h" -#include "lldir.h" -#include "llnotificationsutil.h" -#include "llvfile.h" -#include "llapr.h" -#include "llstring.h" - -#include "llagent.h" -#include "llanimationstates.h" -#include "llbbox.h" -#include "llbutton.h" -#include "llcheckboxctrl.h" -#include "llcombobox.h" -#include "lldrawable.h" -#include "lldrawpoolavatar.h" -#include "llrender.h" -#include "llface.h" -#include "llfocusmgr.h" -#include "llkeyframemotion.h" -#include "lllineeditor.h" -#include "llfloaterperms.h" -#include "llsliderctrl.h" -#include "llspinctrl.h" -#include "lltextbox.h" -#include "lltoolmgr.h" -#include "llui.h" -#include "llviewercamera.h" -#include "llviewerobjectlist.h" -#include "llviewerwindow.h" -#include "llviewermenufile.h" // upload_new_resource() -#include "llvoavatarself.h" -#include "pipeline.h" -#include "lluictrlfactory.h" -#include "llviewercontrol.h" - -#include "hippogridmanager.h" - -// -#include "llinventorymodel.h" // gInventoryModel -// - -S32 LLFloaterAnimPreview::sUploadAmount = 10; - -const S32 PREVIEW_BORDER_WIDTH = 2; -const S32 PREVIEW_RESIZE_HANDLE_SIZE = S32(RESIZE_HANDLE_WIDTH * OO_SQRT2) + PREVIEW_BORDER_WIDTH; -const S32 PREVIEW_HPAD = PREVIEW_RESIZE_HANDLE_SIZE; -const S32 PREF_BUTTON_HEIGHT = 16; -const S32 PREVIEW_TEXTURE_HEIGHT = 300; - -const F32 PREVIEW_CAMERA_DISTANCE = 4.f; - -const F32 MIN_CAMERA_ZOOM = 0.5f; -const F32 MAX_CAMERA_ZOOM = 10.f; - -const F32 BASE_ANIM_TIME_OFFSET = 5.f; - -// -struct LLSaveInfo +LLFloaterAnimPreview::LLFloaterAnimPreview(LLSD const& filename) : LLFloaterNameDesc(filename) { - LLSaveInfo(const LLUUID& item_id, const LLUUID& object_id, const std::string& desc, - const LLTransactionID tid) - : mItemUUID(item_id), mObjectUUID(object_id), mDesc(desc), mTransactionID(tid) - { - } - - LLUUID mItemUUID; - LLUUID mObjectUUID; - std::string mDesc; - LLTransactionID mTransactionID; -}; -// - -std::string STATUS[] = -{ - "E_ST_OK", - "E_ST_EOF", - "E_ST_NO_CONSTRAINT", - "E_ST_NO_FILE", - "E_ST_NO_HIER", - "E_ST_NO_JOINT", - "E_ST_NO_NAME", - "E_ST_NO_OFFSET", - "E_ST_NO_CHANNELS", - "E_ST_NO_ROTATION", - "E_ST_NO_AXIS", - "E_ST_NO_MOTION", - "E_ST_NO_FRAMES", - "E_ST_NO_FRAME_TIME", - "E_ST_NO_POS", - "E_ST_NO_ROT", - "E_ST_NO_XLT_FILE", - "E_ST_NO_XLT_HEADER", - "E_ST_NO_XLT_NAME", - "E_ST_NO_XLT_IGNORE", - "E_ST_NO_XLT_RELATIVE", - "E_ST_NO_XLT_OUTNAME", - "E_ST_NO_XLT_MATRIX", - "E_ST_NO_XLT_MERGECHILD", - "E_ST_NO_XLT_MERGEPARENT", - "E_ST_NO_XLT_PRIORITY", - "E_ST_NO_XLT_LOOP", - "E_ST_NO_XLT_EASEIN", - "E_ST_NO_XLT_EASEOUT", - "E_ST_NO_XLT_HAND", - "E_ST_NO_XLT_EMOTE", -"E_ST_BAD_ROOT" -}; - - -//----------------------------------------------------------------------------- -// LLFloaterAnimPreview() -//----------------------------------------------------------------------------- -LLFloaterAnimPreview::LLFloaterAnimPreview(const std::string& filename, void* item) : - LLFloaterNameDesc(filename) -{ - // - mItem = item; - // - - mLastMouseX = 0; - mLastMouseY = 0; - - mIDList["Standing"] = ANIM_AGENT_STAND; - mIDList["Walking"] = ANIM_AGENT_FEMALE_WALK; - mIDList["Sitting"] = ANIM_AGENT_SIT_FEMALE; - mIDList["Flying"] = ANIM_AGENT_HOVER; - - mIDList["[None]"] = LLUUID::null; - mIDList["Aaaaah"] = ANIM_AGENT_EXPRESS_OPEN_MOUTH; - mIDList["Afraid"] = ANIM_AGENT_EXPRESS_AFRAID; - mIDList["Angry"] = ANIM_AGENT_EXPRESS_ANGER; - mIDList["Big Smile"] = ANIM_AGENT_EXPRESS_TOOTHSMILE; - mIDList["Bored"] = ANIM_AGENT_EXPRESS_BORED; - mIDList["Cry"] = ANIM_AGENT_EXPRESS_CRY; - mIDList["Disdain"] = ANIM_AGENT_EXPRESS_DISDAIN; - mIDList["Embarrassed"] = ANIM_AGENT_EXPRESS_EMBARRASSED; - mIDList["Frown"] = ANIM_AGENT_EXPRESS_FROWN; - mIDList["Kiss"] = ANIM_AGENT_EXPRESS_KISS; - mIDList["Laugh"] = ANIM_AGENT_EXPRESS_LAUGH; - mIDList["Plllppt"] = ANIM_AGENT_EXPRESS_TONGUE_OUT; - mIDList["Repulsed"] = ANIM_AGENT_EXPRESS_REPULSED; - mIDList["Sad"] = ANIM_AGENT_EXPRESS_SAD; - mIDList["Shrug"] = ANIM_AGENT_EXPRESS_SHRUG; - mIDList["Smile"] = ANIM_AGENT_EXPRESS_SMILE; - mIDList["Surprise"] = ANIM_AGENT_EXPRESS_SURPRISE; - mIDList["Wink"] = ANIM_AGENT_EXPRESS_WINK; - mIDList["Worry"] = ANIM_AGENT_EXPRESS_WORRY; } -//----------------------------------------------------------------------------- -// setAnimCallbacks() -//----------------------------------------------------------------------------- -void LLFloaterAnimPreview::setAnimCallbacks() -{ - childSetCommitCallback("playback_slider", onSliderMove, this); - - childSetCommitCallback("preview_base_anim", onCommitBaseAnim, this); - childSetValue("preview_base_anim", "Standing"); - - childSetCommitCallback("priority", onCommitPriority, this); - childSetCommitCallback("loop_check", onCommitLoop, this); - childSetCommitCallback("loop_in_point", onCommitLoopIn, this); - childSetValidate("loop_in_point", validateLoopIn); - childSetCommitCallback("loop_out_point", onCommitLoopOut, this); - childSetValidate("loop_out_point", validateLoopOut); - - childSetCommitCallback("hand_pose_combo", onCommitHandPose, this); - - childSetCommitCallback("emote_combo", onCommitEmote, this); - childSetValue("emote_combo", "[None]"); - - childSetCommitCallback("ease_in_time", onCommitEaseIn, this); - childSetValidate("ease_in_time", validateEaseIn); - childSetCommitCallback("ease_out_time", onCommitEaseOut, this); - childSetValidate("ease_out_time", validateEaseOut); -} - -//----------------------------------------------------------------------------- -// postBuild() -//----------------------------------------------------------------------------- BOOL LLFloaterAnimPreview::postBuild() { - LLRect r; - LLKeyframeMotion* motionp = NULL; - LLBVHLoader* loaderp = NULL; - if (!LLFloaterNameDesc::postBuild()) { return FALSE; } - - mInWorld = gSavedSettings.getBOOL("PreviewAnimInWorld"); - - childSetCommitCallback("name_form", onCommitName, this); - - if (gSavedSettings.getBOOL("AscentPowerfulWizard")) - { - childSetMaxValue("priority", 7); - } - - childSetLabelArg("ok_btn", "[UPLOADFEE]", gHippoGridManager->getConnectedGrid()->getUploadFee()); - childSetAction("ok_btn", onBtnOK, this); - setDefaultBtn(); - - if (mInWorld) - { - r = getRect(); - translate(0, 230); - reshape(r.getWidth(), r.getHeight() - 230); - childSetValue("bad_animation_text", getString("in_world")); - childShow("bad_animation_text"); - } - else - { - childHide("bad_animation_text"); - } - - mPreviewRect.set(PREVIEW_HPAD, - PREVIEW_TEXTURE_HEIGHT, - getRect().getWidth() - PREVIEW_HPAD, - PREVIEW_HPAD + PREF_BUTTON_HEIGHT + PREVIEW_HPAD); - mPreviewImageRect.set(0.f, 1.f, 1.f, 0.f); - - S32 y = mPreviewRect.mTop + BTN_HEIGHT; - S32 btn_left = PREVIEW_HPAD; - - r.set( btn_left, y, btn_left + 32, y - BTN_HEIGHT ); - mPlayButton = getChild( "play_btn"); - if (!mPlayButton) - { - mPlayButton = new LLButton("play_btn"); - } - mPlayButton->setClickedCallback(boost::bind(&LLFloaterAnimPreview::onBtnPlay,this)); - mPlayButton->setImages(std::string("button_anim_play.tga"), - std::string("button_anim_play_selected.tga")); - - mPlayButton->setImageDisabled(NULL); - mPlayButton->setImageDisabledSelected(NULL); - - mPlayButton->setScaleImage(TRUE); - - mStopButton = getChild( "stop_btn"); - if (!mStopButton) - { - mStopButton = new LLButton("stop_btn"); - } - mStopButton->setClickedCallback(boost::bind(&LLFloaterAnimPreview::onBtnStop, this)); - mStopButton->setImages(std::string("button_anim_stop.tga"), - std::string("button_anim_stop_selected.tga")); - - mStopButton->setImageDisabled(NULL); - mStopButton->setImageDisabledSelected(NULL); - - mStopButton->setScaleImage(TRUE); - - r.set(r.mRight + PREVIEW_HPAD, y, getRect().getWidth() - PREVIEW_HPAD, y - BTN_HEIGHT); - //childSetCommitCallback("playback_slider", onSliderMove, this); - - //childSetCommitCallback("preview_base_anim", onCommitBaseAnim, this); - //childSetValue("preview_base_anim", "Standing"); - - //childSetCommitCallback("priority", onCommitPriority, this); - //childSetCommitCallback("loop_check", onCommitLoop, this); - //childSetCommitCallback("loop_in_point", onCommitLoopIn, this); - //childSetValidate("loop_in_point", validateLoopIn); - //childSetCommitCallback("loop_out_point", onCommitLoopOut, this); - //childSetValidate("loop_out_point", validateLoopOut); - - //childSetCommitCallback("hand_pose_combo", onCommitHandPose, this); - - //childSetCommitCallback("emote_combo", onCommitEmote, this); - //childSetValue("emote_combo", "[None]"); - - //childSetCommitCallback("ease_in_time", onCommitEaseIn, this); - //childSetValidate("ease_in_time", validateEaseIn); - //childSetCommitCallback("ease_out_time", onCommitEaseOut, this); - //childSetValidate("ease_out_time", validateEaseOut); - - // moved declaration from below - BOOL success = false; - // - - std::string exten = gDirUtilp->getExtension(mFilename); - if (exten == "bvh") - { - // loading a bvh file - - // now load bvh file - S32 file_size; - - LLAPRFile infile(mFilenameAndPath, LL_APR_RB, &file_size); - - if (!infile.getFileHandle()) - { - llwarns << "Can't open BVH file:" << mFilename << llendl; - } - else - { - char* file_buffer; - - file_buffer = new char[file_size + 1]; - - if (file_size == infile.read(file_buffer, file_size)) - { - file_buffer[file_size] = '\0'; - llinfos << "Loading BVH file " << mFilename << llendl; - ELoadStatus load_status = E_ST_OK; - S32 line_number = 0; - loaderp = new LLBVHLoader(file_buffer, load_status, line_number); - std::string status = getString(STATUS[load_status]); - - if(load_status == E_ST_NO_XLT_FILE) - { - llwarns << "NOTE: No translation table found." << llendl; - } - else - { - llwarns << "ERROR: [line: " << line_number << "] " << status << llendl; - } - } - - infile.close() ; - delete[] file_buffer; - - // moved everything bvh from below - if(loaderp && loaderp->isInitialized() && loaderp->getDuration() <= MAX_ANIM_DURATION) - { - mTransactionID.generate(); - mMotionID = mTransactionID.makeAssetID(gAgent.getSecureSessionID()); - - mAnimPreview = new LLPreviewAnimation(256, 256); - - // motion will be returned, but it will be in a load-pending state, as this is a new motion - // this motion will not request an asset transfer until next update, so we have a chance to - // load the keyframe data locally - if (mInWorld) - { - motionp = (LLKeyframeMotion*)gAgentAvatarp->createMotion(mMotionID); - } - else - { - motionp = (LLKeyframeMotion*)mAnimPreview->getDummyAvatar()->createMotion(mMotionID); - } - - // create data buffer for keyframe initialization - S32 buffer_size = loaderp->getOutputSize(); - U8* buffer = new U8[buffer_size]; - - LLDataPackerBinaryBuffer dp(buffer, buffer_size); - - // pass animation data through memory buffer - loaderp->serialize(dp); - dp.reset(); - success = motionp && motionp->deserialize(dp); - } - else - { - success = false; - if ( loaderp ) - { - if (loaderp->getDuration() > MAX_ANIM_DURATION) - { - LLUIString out_str = getString("anim_too_long"); - out_str.setArg("[LENGTH]", llformat("%.1f", loaderp->getDuration())); - out_str.setArg("[MAX_LENGTH]", llformat("%.1f", MAX_ANIM_DURATION)); - getChild("bad_animation_text")->setValue(out_str.getString()); - } - else - { - LLUIString out_str = getString("failed_file_read"); - out_str.setArg("[STATUS]", getString(STATUS[loaderp->getStatus()])); - getChild("bad_animation_text")->setValue(out_str.getString()); - } - } - - //setEnabled(FALSE); - mMotionID.setNull(); - mAnimPreview = NULL; - } - // - } - } - // - else if(exten == "animatn") - { - S32 file_size; - LLAPRFile raw_animatn(mFilenameAndPath, LL_APR_RB, &file_size); - - if (!raw_animatn.getFileHandle()) - { - llwarns << "Can't open animatn file:" << mFilename << llendl; - } - else - { - char* file_buffer; - - file_buffer = new char[file_size + 1]; - - if (file_size == raw_animatn.read(file_buffer, file_size)) - { - file_buffer[file_size] = '\0'; - llinfos << "Loading animatn file " << mFilename << llendl; - mTransactionID.generate(); - mMotionID = mTransactionID.makeAssetID(gAgent.getSecureSessionID()); - mAnimPreview = new LLPreviewAnimation(256, 256); - motionp = (LLKeyframeMotion*)mAnimPreview->getDummyAvatar()->createMotion(mMotionID); - LLDataPackerBinaryBuffer dp((U8*)file_buffer, file_size); - dp.reset(); - success = motionp && motionp->deserialize(dp); - } - - raw_animatn.close(); - delete[] file_buffer; - } - } - // - - if (success) - { - setAnimCallbacks() ; - - if (!mInWorld) - { - const LLBBoxLocal &pelvis_bbox = motionp->getPelvisBBox(); - - LLVector3 temp = pelvis_bbox.getCenter(); - // only consider XY? - //temp.mV[VZ] = 0.f; - F32 pelvis_offset = temp.magVec(); - - temp = pelvis_bbox.getExtent(); - //temp.mV[VZ] = 0.f; - F32 pelvis_max_displacement = pelvis_offset + (temp.magVec() * 0.5f) + 1.f; - - F32 camera_zoom = LLViewerCamera::getInstance()->getDefaultFOV() / (2.f * atan(pelvis_max_displacement / PREVIEW_CAMERA_DISTANCE)); - - mAnimPreview->setZoom(camera_zoom); - } - - motionp->setName(childGetValue("name_form").asString()); - if (!mInWorld) - { - mAnimPreview->getDummyAvatar()->startMotion(mMotionID); - } - childSetMinValue("playback_slider", 0.0); - childSetMaxValue("playback_slider", 1.0); - - childSetValue("loop_check", LLSD(motionp->getLoop())); - childSetValue("loop_in_point", LLSD(motionp->getLoopIn() / motionp->getDuration() * 100.f)); - childSetValue("loop_out_point", LLSD(motionp->getLoopOut() / motionp->getDuration() * 100.f)); - childSetValue("priority", LLSD((F32)motionp->getPriority())); - childSetValue("hand_pose_combo", LLHandMotion::getHandPoseName(motionp->getHandPose())); - childSetValue("ease_in_time", LLSD(motionp->getEaseInDuration())); - childSetValue("ease_out_time", LLSD(motionp->getEaseOutDuration())); - setEnabled(TRUE); - std::string seconds_string; - seconds_string = llformat(" - %.2f seconds", motionp->getDuration()); - - setTitle(mFilename + std::string(seconds_string)); - } - else - { - mAnimPreview = NULL; - mMotionID.setNull(); - childSetValue("bad_animation_text", getString("failed_to_initialize")); - } - - - refresh(); - - delete loaderp; - + getChild("ok_btn")->setCommitCallback(boost::bind(&LLFloaterNameDesc::onBtnOK, this)); return TRUE; } - -//----------------------------------------------------------------------------- -// LLFloaterAnimPreview() -//----------------------------------------------------------------------------- -LLFloaterAnimPreview::~LLFloaterAnimPreview() -{ - if (mInWorld) - { - LLVOAvatar* avatarp = gAgentAvatarp; - if (avatarp) - { - if (mMotionID.notNull()) - { - avatarp->stopMotion(mMotionID, TRUE); - avatarp->removeMotion(mMotionID); - } - avatarp->deactivateAllMotions(); - avatarp->startMotion(ANIM_AGENT_HEAD_ROT); - avatarp->startMotion(ANIM_AGENT_EYE); - avatarp->startMotion(ANIM_AGENT_BODY_NOISE); - avatarp->startMotion(ANIM_AGENT_BREATHE_ROT); - avatarp->startMotion(ANIM_AGENT_HAND_MOTION); - avatarp->startMotion(ANIM_AGENT_PELVIS_FIX); - avatarp->startMotion(ANIM_AGENT_STAND, BASE_ANIM_TIME_OFFSET); - } - } - mAnimPreview = NULL; - - setEnabled(FALSE); -} - -//----------------------------------------------------------------------------- -// draw() -//----------------------------------------------------------------------------- -void LLFloaterAnimPreview::draw() -{ - LLFloater::draw(); - LLRect r = getRect(); - - refresh(); - - if (mMotionID.notNull() && mAnimPreview && !mInWorld) - { - gGL.color3f(1.f, 1.f, 1.f); - - gGL.getTexUnit(0)->bind(mAnimPreview); - - gGL.begin( LLRender::QUADS ); - { - gGL.texCoord2f(0.f, 1.f); - gGL.vertex2i(PREVIEW_HPAD, PREVIEW_TEXTURE_HEIGHT); - gGL.texCoord2f(0.f, 0.f); - gGL.vertex2i(PREVIEW_HPAD, PREVIEW_HPAD + PREF_BUTTON_HEIGHT + PREVIEW_HPAD); - gGL.texCoord2f(1.f, 0.f); - gGL.vertex2i(r.getWidth() - PREVIEW_HPAD, PREVIEW_HPAD + PREF_BUTTON_HEIGHT + PREVIEW_HPAD); - gGL.texCoord2f(1.f, 1.f); - gGL.vertex2i(r.getWidth() - PREVIEW_HPAD, PREVIEW_TEXTURE_HEIGHT); - } - gGL.end(); - - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - - LLVOAvatar* avatarp = mAnimPreview->getDummyAvatar(); - if (!avatarp->areAnimationsPaused()) - { - mAnimPreview->requestUpdate(); - } - } -} - -//----------------------------------------------------------------------------- -// resetMotion() -//----------------------------------------------------------------------------- -void LLFloaterAnimPreview::resetMotion() -{ - LLVOAvatar* avatarp; - if (mInWorld) - { - avatarp = gAgentAvatarp; - } - else - { - avatarp = mAnimPreview->getDummyAvatar(); - } - if (!avatarp) - { - return; - } - - BOOL paused = avatarp->areAnimationsPaused(); - - // *TODO: Fix awful casting hack - LLKeyframeMotion* motionp = (LLKeyframeMotion*)avatarp->findMotion(mMotionID); - - // Set emotion - std::string emote = childGetValue("emote_combo").asString(); - motionp->setEmote(mIDList[emote]); - - LLUUID base_id = mIDList[childGetValue("preview_base_anim").asString()]; - avatarp->deactivateAllMotions(); - avatarp->startMotion(base_id, BASE_ANIM_TIME_OFFSET); - avatarp->startMotion(mMotionID, 0.0f); - childSetValue("playback_slider", 0.0f); - - // Set pose - std::string handpose = childGetValue("hand_pose_combo").asString(); - avatarp->startMotion( ANIM_AGENT_HAND_MOTION, 0.0f ); - motionp->setHandPose(LLHandMotion::getHandPose(handpose)); - - if (paused) - { - mPauseRequest = avatarp->requestPause(); - } - else - { - mPauseRequest = NULL; - } -} - -//----------------------------------------------------------------------------- -// handleMouseDown() -//----------------------------------------------------------------------------- -BOOL LLFloaterAnimPreview::handleMouseDown(S32 x, S32 y, MASK mask) -{ - if (!mInWorld && mPreviewRect.pointInRect(x, y)) - { - bringToFront( x, y ); - gFocusMgr.setMouseCapture(this); - gViewerWindow->hideCursor(); - mLastMouseX = x; - mLastMouseY = y; - return TRUE; - } - - return LLFloater::handleMouseDown(x, y, mask); -} - -//----------------------------------------------------------------------------- -// handleMouseUp() -//----------------------------------------------------------------------------- -BOOL LLFloaterAnimPreview::handleMouseUp(S32 x, S32 y, MASK mask) -{ - if (!mInWorld) - { - gFocusMgr.setMouseCapture(FALSE); - gViewerWindow->showCursor(); - } - return LLFloater::handleMouseUp(x, y, mask); -} - -//----------------------------------------------------------------------------- -// handleHover() -//----------------------------------------------------------------------------- -BOOL LLFloaterAnimPreview::handleHover(S32 x, S32 y, MASK mask) -{ - if (mInWorld) - { - return TRUE; - } - - MASK local_mask = mask & ~MASK_ALT; - - if (mAnimPreview && hasMouseCapture()) - { - if (local_mask == MASK_PAN) - { - // pan here - mAnimPreview->pan((F32)(x - mLastMouseX) * -0.005f, (F32)(y - mLastMouseY) * -0.005f); - } - else if (local_mask == MASK_ORBIT) - { - F32 yaw_radians = (F32)(x - mLastMouseX) * -0.01f; - F32 pitch_radians = (F32)(y - mLastMouseY) * 0.02f; - - mAnimPreview->rotate(yaw_radians, pitch_radians); - } - else - { - F32 yaw_radians = (F32)(x - mLastMouseX) * -0.01f; - F32 zoom_amt = (F32)(y - mLastMouseY) * 0.02f; - - mAnimPreview->rotate(yaw_radians, 0.f); - mAnimPreview->zoom(zoom_amt); - } - - mAnimPreview->requestUpdate(); - - LLUI::setMousePositionLocal(this, mLastMouseX, mLastMouseY); - } - - if (!mPreviewRect.pointInRect(x, y) || !mAnimPreview) - { - return LLFloater::handleHover(x, y, mask); - } - else if (local_mask == MASK_ORBIT) - { - gViewerWindow->setCursor(UI_CURSOR_TOOLCAMERA); - } - else if (local_mask == MASK_PAN) - { - gViewerWindow->setCursor(UI_CURSOR_TOOLPAN); - } - else - { - gViewerWindow->setCursor(UI_CURSOR_TOOLZOOMIN); - } - - return TRUE; -} - -//----------------------------------------------------------------------------- -// handleScrollWheel() -//----------------------------------------------------------------------------- -BOOL LLFloaterAnimPreview::handleScrollWheel(S32 x, S32 y, S32 clicks) -{ - if (!mInWorld) - { - mAnimPreview->zoom((F32)clicks * -0.2f); - mAnimPreview->requestUpdate(); - } - return TRUE; -} - -//----------------------------------------------------------------------------- -// onMouseCaptureLost() -//----------------------------------------------------------------------------- -void LLFloaterAnimPreview::onMouseCaptureLost() -{ - if (!mInWorld) - { - gViewerWindow->showCursor(); - } -} - -//----------------------------------------------------------------------------- -// onBtnPlay() -//----------------------------------------------------------------------------- -void LLFloaterAnimPreview::onBtnPlay() -{ - if (!getEnabled()) - return; - - if (mMotionID.notNull()) - { - LLVOAvatar* avatarp; - if (mInWorld) - { - if (!gAgentAvatarp) - { - return; - } - avatarp = gAgentAvatarp; - } - else - { - if (!mAnimPreview) - { - return; - } - avatarp = mAnimPreview->getDummyAvatar(); - } - - if(!avatarp->isMotionActive(mMotionID)) - { - resetMotion(); - mPauseRequest = NULL; - } - else - { - if (avatarp->areAnimationsPaused()) - { - mPauseRequest = NULL; - } - else - { - mPauseRequest = avatarp->requestPause(); - } - } - } -} - -//----------------------------------------------------------------------------- -// onBtnStop() -//----------------------------------------------------------------------------- -void LLFloaterAnimPreview::onBtnStop() -{ - if (!getEnabled()) - return; - - if (mMotionID.notNull()) - { - LLVOAvatar* avatarp; - if (mInWorld) - { - if (!gAgentAvatarp) - { - return; - } - avatarp = gAgentAvatarp; - } - else - { - if (!mAnimPreview) - { - return; - } - avatarp = mAnimPreview->getDummyAvatar(); - } - resetMotion(); - mPauseRequest = avatarp->requestPause(); - } -} - -//----------------------------------------------------------------------------- -// onSliderMove() -//----------------------------------------------------------------------------- -void LLFloaterAnimPreview::onSliderMove(LLUICtrl* ctrl, void*user_data) -{ - LLFloaterAnimPreview* previewp = (LLFloaterAnimPreview*)user_data; - if (!previewp->getEnabled()) - return; - - LLVOAvatar* avatarp; - if (previewp->mInWorld) - { - if (!gAgentAvatarp) - { - return; - } - avatarp = gAgentAvatarp; - } - else - { - if (!previewp->mAnimPreview) - { - return; - } - avatarp = previewp->mAnimPreview->getDummyAvatar(); - } - F32 slider_value = (F32)previewp->childGetValue("playback_slider").asReal(); - LLUUID base_id = previewp->mIDList[previewp->childGetValue("preview_base_anim").asString()]; - LLMotion* motionp = avatarp->findMotion(previewp->mMotionID); - F32 duration = motionp->getDuration();// + motionp->getEaseOutDuration(); - F32 delta_time = duration * slider_value; - avatarp->deactivateAllMotions(); - avatarp->startMotion(base_id, delta_time + BASE_ANIM_TIME_OFFSET); - avatarp->startMotion(previewp->mMotionID, delta_time); - previewp->mPauseRequest = avatarp->requestPause(); - previewp->refresh(); -} - -//----------------------------------------------------------------------------- -// onCommitBaseAnim() -//----------------------------------------------------------------------------- -void LLFloaterAnimPreview::onCommitBaseAnim(LLUICtrl* ctrl, void* data) -{ - LLFloaterAnimPreview* previewp = (LLFloaterAnimPreview*)data; - if (!previewp->getEnabled()) - return; - - LLVOAvatar* avatarp; - if (previewp->mInWorld) - { - if (!gAgentAvatarp) - { - return; - } - avatarp = gAgentAvatarp; - } - else - { - if (!previewp->mAnimPreview) - { - return; - } - avatarp = previewp->mAnimPreview->getDummyAvatar(); - } - - BOOL paused = avatarp->areAnimationsPaused(); - - // stop all other possible base motions - avatarp->stopMotion(ANIM_AGENT_STAND, TRUE); - avatarp->stopMotion(ANIM_AGENT_WALK, TRUE); - avatarp->stopMotion(ANIM_AGENT_SIT, TRUE); - avatarp->stopMotion(ANIM_AGENT_HOVER, TRUE); - - previewp->resetMotion(); - - if (!paused) - { - previewp->mPauseRequest = NULL; - } -} - -//----------------------------------------------------------------------------- -// onCommitLoop() -//----------------------------------------------------------------------------- -void LLFloaterAnimPreview::onCommitLoop(LLUICtrl* ctrl, void* data) -{ - LLFloaterAnimPreview* previewp = (LLFloaterAnimPreview*)data; - if (!previewp->getEnabled()) - return; - - LLVOAvatar* avatarp; - if (previewp->mInWorld) - { - if (!gAgentAvatarp) - { - return; - } - avatarp = gAgentAvatarp; - } - else - { - if (!previewp->mAnimPreview) - { - return; - } - avatarp = previewp->mAnimPreview->getDummyAvatar(); - } - LLKeyframeMotion* motionp = (LLKeyframeMotion*)avatarp->findMotion(previewp->mMotionID); - - if (motionp) - { - motionp->setLoop(previewp->childGetValue("loop_check").asBoolean()); - motionp->setLoopIn((F32)previewp->childGetValue("loop_in_point").asReal() * 0.01f * motionp->getDuration()); - motionp->setLoopOut((F32)previewp->childGetValue("loop_out_point").asReal() * 0.01f * motionp->getDuration()); - } -} - -//----------------------------------------------------------------------------- -// onCommitLoopIn() -//----------------------------------------------------------------------------- -void LLFloaterAnimPreview::onCommitLoopIn(LLUICtrl* ctrl, void* data) -{ - LLFloaterAnimPreview* previewp = (LLFloaterAnimPreview*)data; - if (!previewp->getEnabled()) - return; - - LLVOAvatar* avatarp; - if (previewp->mInWorld) - { - if (!gAgentAvatarp) - { - return; - } - avatarp = gAgentAvatarp; - } - else - { - if (!previewp->mAnimPreview) - { - return; - } - avatarp = previewp->mAnimPreview->getDummyAvatar(); - } - LLKeyframeMotion* motionp = (LLKeyframeMotion*)avatarp->findMotion(previewp->mMotionID); - - if (motionp) - { - motionp->setLoopIn((F32)previewp->childGetValue("loop_in_point").asReal() / 100.f); - previewp->resetMotion(); - previewp->childSetValue("loop_check", LLSD(TRUE)); - onCommitLoop(ctrl, data); - } -} - -//----------------------------------------------------------------------------- -// onCommitLoopOut() -//----------------------------------------------------------------------------- -void LLFloaterAnimPreview::onCommitLoopOut(LLUICtrl* ctrl, void* data) -{ - LLFloaterAnimPreview* previewp = (LLFloaterAnimPreview*)data; - if (!previewp->getEnabled()) - return; - - LLVOAvatar* avatarp; - if (previewp->mInWorld) - { - if (!gAgentAvatarp) - { - return; - } - avatarp = gAgentAvatarp; - } - else - { - if (!previewp->mAnimPreview) - { - return; - } - avatarp = previewp->mAnimPreview->getDummyAvatar(); - } - LLKeyframeMotion* motionp = (LLKeyframeMotion*)avatarp->findMotion(previewp->mMotionID); - - if (motionp) - { - motionp->setLoopOut((F32)previewp->childGetValue("loop_out_point").asReal() * 0.01f * motionp->getDuration()); - previewp->resetMotion(); - previewp->childSetValue("loop_check", LLSD(TRUE)); - onCommitLoop(ctrl, data); - } -} - -//----------------------------------------------------------------------------- -// onCommitName() -//----------------------------------------------------------------------------- -void LLFloaterAnimPreview::onCommitName(LLUICtrl* ctrl, void* data) -{ - LLFloaterAnimPreview* previewp = (LLFloaterAnimPreview*)data; - if (!previewp->getEnabled()) - return; - - LLVOAvatar* avatarp; - if (previewp->mInWorld) - { - if (!gAgentAvatarp) - { - return; - } - avatarp = gAgentAvatarp; - } - else - { - if (!previewp->mAnimPreview) - { - return; - } - avatarp = previewp->mAnimPreview->getDummyAvatar(); - } - LLKeyframeMotion* motionp = (LLKeyframeMotion*)avatarp->findMotion(previewp->mMotionID); - - if (motionp) - { - motionp->setName(previewp->childGetValue("name_form").asString()); - } - - LLFloaterNameDesc::doCommit(ctrl, data); -} - -//----------------------------------------------------------------------------- -// onCommitHandPose() -//----------------------------------------------------------------------------- -void LLFloaterAnimPreview::onCommitHandPose(LLUICtrl* ctrl, void* data) -{ - LLFloaterAnimPreview* previewp = (LLFloaterAnimPreview*)data; - if (!previewp->getEnabled()) - return; - - previewp->resetMotion(); // sets hand pose -} - -//----------------------------------------------------------------------------- -// onCommitEmote() -//----------------------------------------------------------------------------- -void LLFloaterAnimPreview::onCommitEmote(LLUICtrl* ctrl, void* data) -{ - LLFloaterAnimPreview* previewp = (LLFloaterAnimPreview*)data; - if (!previewp->getEnabled()) - return; - - previewp->resetMotion(); // ssts emote -} - -//----------------------------------------------------------------------------- -// onCommitPriority() -//----------------------------------------------------------------------------- -void LLFloaterAnimPreview::onCommitPriority(LLUICtrl* ctrl, void* data) -{ - LLFloaterAnimPreview* previewp = (LLFloaterAnimPreview*)data; - if (!previewp->getEnabled()) - return; - - LLVOAvatar* avatarp; - if (previewp->mInWorld) - { - if (!gAgentAvatarp) - { - return; - } - avatarp = gAgentAvatarp; - } - else - { - if (!previewp->mAnimPreview) - { - return; - } - avatarp = previewp->mAnimPreview->getDummyAvatar(); - } - LLKeyframeMotion* motionp = (LLKeyframeMotion*)avatarp->findMotion(previewp->mMotionID); - - motionp->setPriority(llfloor((F32)previewp->childGetValue("priority").asReal())); -} - -//----------------------------------------------------------------------------- -// onCommitEaseIn() -//----------------------------------------------------------------------------- -void LLFloaterAnimPreview::onCommitEaseIn(LLUICtrl* ctrl, void* data) -{ - LLFloaterAnimPreview* previewp = (LLFloaterAnimPreview*)data; - if (!previewp->getEnabled()) - return; - - LLVOAvatar* avatarp; - if (previewp->mInWorld) - { - if (!gAgentAvatarp) - { - return; - } - avatarp = gAgentAvatarp; - } - else - { - if (!previewp->mAnimPreview) - { - return; - } - avatarp = previewp->mAnimPreview->getDummyAvatar(); - } - LLKeyframeMotion* motionp = (LLKeyframeMotion*)avatarp->findMotion(previewp->mMotionID); - - motionp->setEaseIn((F32)previewp->childGetValue("ease_in_time").asReal()); - previewp->resetMotion(); -} - -//----------------------------------------------------------------------------- -// onCommitEaseOut() -//----------------------------------------------------------------------------- -void LLFloaterAnimPreview::onCommitEaseOut(LLUICtrl* ctrl, void* data) -{ - LLFloaterAnimPreview* previewp = (LLFloaterAnimPreview*)data; - if (!previewp->getEnabled()) - return; - - LLVOAvatar* avatarp; - if (previewp->mInWorld) - { - if (!gAgentAvatarp) - { - return; - } - avatarp = gAgentAvatarp; - } - else - { - if (!previewp->mAnimPreview) - { - return; - } - avatarp = previewp->mAnimPreview->getDummyAvatar(); - } - LLKeyframeMotion* motionp = (LLKeyframeMotion*)avatarp->findMotion(previewp->mMotionID); - - motionp->setEaseOut((F32)previewp->childGetValue("ease_out_time").asReal()); - previewp->resetMotion(); -} - -//----------------------------------------------------------------------------- -// validateEaseIn() -//----------------------------------------------------------------------------- -BOOL LLFloaterAnimPreview::validateEaseIn(LLUICtrl* spin, void* data) -{ - LLFloaterAnimPreview* previewp = (LLFloaterAnimPreview*)data; - if (!previewp->getEnabled()) - return FALSE; - - LLVOAvatar* avatarp; - if (previewp->mInWorld) - { - if (!gAgentAvatarp) - { - return FALSE; - } - avatarp = gAgentAvatarp; - } - else - { - if (!previewp->mAnimPreview) - { - return FALSE; - } - avatarp = previewp->mAnimPreview->getDummyAvatar(); - } - LLKeyframeMotion* motionp = (LLKeyframeMotion*)avatarp->findMotion(previewp->mMotionID); - - if (!motionp->getLoop()) - { - F32 new_ease_in = llclamp((F32)previewp->childGetValue("ease_in_time").asReal(), 0.f, motionp->getDuration() - motionp->getEaseOutDuration()); - previewp->childSetValue("ease_in_time", LLSD(new_ease_in)); - } - - return TRUE; -} - -//----------------------------------------------------------------------------- -// validateEaseOut() -//----------------------------------------------------------------------------- -BOOL LLFloaterAnimPreview::validateEaseOut(LLUICtrl* spin, void* data) -{ - LLFloaterAnimPreview* previewp = (LLFloaterAnimPreview*)data; - - if (!previewp->getEnabled()) - return FALSE; - - LLVOAvatar* avatarp; - if (previewp->mInWorld) - { - if (!gAgentAvatarp) - { - return FALSE; - } - avatarp = gAgentAvatarp; - } - else - { - if (!previewp->mAnimPreview) - { - return FALSE; - } - avatarp = previewp->mAnimPreview->getDummyAvatar(); - } - LLKeyframeMotion* motionp = (LLKeyframeMotion*)avatarp->findMotion(previewp->mMotionID); - - if (!motionp->getLoop()) - { - F32 new_ease_out = llclamp((F32)previewp->childGetValue("ease_out_time").asReal(), 0.f, motionp->getDuration() - motionp->getEaseInDuration()); - previewp->childSetValue("ease_out_time", LLSD(new_ease_out)); - } - - return TRUE; -} - -//----------------------------------------------------------------------------- -// validateLoopIn() -//----------------------------------------------------------------------------- -BOOL LLFloaterAnimPreview::validateLoopIn(LLUICtrl* ctrl, void* data) -{ - LLFloaterAnimPreview* previewp = (LLFloaterAnimPreview*)data; - if (!previewp->getEnabled()) - return FALSE; - - F32 loop_in_value = (F32)previewp->childGetValue("loop_in_point").asReal(); - F32 loop_out_value = (F32)previewp->childGetValue("loop_out_point").asReal(); - - if (loop_in_value < 0.f) - { - loop_in_value = 0.f; - } - else if (loop_in_value > 100.f) - { - loop_in_value = 100.f; - } - else if (loop_in_value > loop_out_value) - { - loop_in_value = loop_out_value; - } - - previewp->childSetValue("loop_in_point", LLSD(loop_in_value)); - return TRUE; -} - -//----------------------------------------------------------------------------- -// validateLoopOut() -//----------------------------------------------------------------------------- -BOOL LLFloaterAnimPreview::validateLoopOut(LLUICtrl* spin, void* data) -{ - LLFloaterAnimPreview* previewp = (LLFloaterAnimPreview*)data; - if (!previewp->getEnabled()) - return FALSE; - - F32 loop_out_value = (F32)previewp->childGetValue("loop_out_point").asReal(); - F32 loop_in_value = (F32)previewp->childGetValue("loop_in_point").asReal(); - - if (loop_out_value < 0.f) - { - loop_out_value = 0.f; - } - else if (loop_out_value > 100.f) - { - loop_out_value = 100.f; - } - else if (loop_out_value < loop_in_value) - { - loop_out_value = loop_in_value; - } - - previewp->childSetValue("loop_out_point", LLSD(loop_out_value)); - return TRUE; -} - - -//----------------------------------------------------------------------------- -// refresh() -//----------------------------------------------------------------------------- -void LLFloaterAnimPreview::refresh() -{ - if (!mAnimPreview) - { - childShow("bad_animation_text"); - mPlayButton->setEnabled(FALSE); - mStopButton->setEnabled(FALSE); - childDisable("ok_btn"); - } - else - { - if (!mInWorld) - { - childHide("bad_animation_text"); - } - mPlayButton->setEnabled(TRUE); - LLVOAvatar* avatarp; - if (mInWorld) - { - avatarp = gAgentAvatarp; - } - else - { - avatarp = mAnimPreview->getDummyAvatar(); - } - if (avatarp->isMotionActive(mMotionID)) - { - mStopButton->setEnabled(TRUE); - LLKeyframeMotion* motionp = (LLKeyframeMotion*)avatarp->findMotion(mMotionID); - if (avatarp->areAnimationsPaused()) - { - - mPlayButton->setImages(std::string("button_anim_play.tga"), - std::string("button_anim_play_selected.tga")); - - } - else - { - if (motionp) - { - F32 fraction_complete = motionp->getLastUpdateTime() / motionp->getDuration(); - childSetValue("playback_slider", fraction_complete); - } - mPlayButton->setImages(std::string("button_anim_pause.tga"), - std::string("button_anim_pause_selected.tga")); - - } - } - else - { - mPauseRequest = avatarp->requestPause(); - mPlayButton->setImages(std::string("button_anim_play.tga"), - std::string("button_anim_play_selected.tga")); - - mStopButton->setEnabled(TRUE); // stop also resets, leave enabled. - } - childEnable("ok_btn"); - if (!mInWorld) - { - mAnimPreview->requestUpdate(); - } - } -} - -//----------------------------------------------------------------------------- -// onBtnOK() -//----------------------------------------------------------------------------- -void LLFloaterAnimPreview::onBtnOK(void* userdata) -{ - LLFloaterAnimPreview* floaterp = (LLFloaterAnimPreview*)userdata; - if (!floaterp->getEnabled()) return; - - if ((!floaterp->mInWorld && floaterp->mAnimPreview) || (floaterp->mInWorld && gAgentAvatarp)) - { - LLKeyframeMotion* motionp; - if (floaterp->mInWorld) - { - motionp = (LLKeyframeMotion*)gAgentAvatarp->findMotion(floaterp->mMotionID); - } - else - { - motionp = (LLKeyframeMotion*)floaterp->mAnimPreview->getDummyAvatar()->findMotion(floaterp->mMotionID); - } - - S32 file_size = motionp->getFileSize(); - U8* buffer = new U8[file_size]; - - LLDataPackerBinaryBuffer dp(buffer, file_size); - if (motionp->serialize(dp)) - { - LLVFile file(gVFS, motionp->getID(), LLAssetType::AT_ANIMATION, LLVFile::APPEND); - - S32 size = dp.getCurrentSize(); - file.setMaxSize(size); - if (file.write((U8*)buffer, size)) - { - std::string name = floaterp->childGetValue("name_form").asString(); - std::string desc = floaterp->childGetValue("description_form").asString(); - LLAssetStorage::LLStoreAssetCallback callback = NULL; - S32 expected_upload_cost = sUploadAmount; - void *userdata = NULL; - - // - if(floaterp->mItem) - { - // Update existing item instead of creating a new one - LLViewerInventoryItem* item = (LLViewerInventoryItem*)floaterp->mItem; - LLSaveInfo* info = new LLSaveInfo(item->getUUID(), LLUUID::null, desc, floaterp->mTransactionID); - gAssetStorage->storeAssetData(floaterp->mTransactionID, LLAssetType::AT_ANIMATION, NULL, info, FALSE); - - // I guess I will do this now because the floater is closing... - LLPointer new_item = new LLViewerInventoryItem(item); - new_item->setDescription(desc); - new_item->setTransactionID(floaterp->mTransactionID); - new_item->setAssetUUID(motionp->getID()); - new_item->updateServer(FALSE); - gInventory.updateItem(new_item); - gInventory.notifyObservers(); - } - else - // - { - upload_new_resource(floaterp->mTransactionID, // tid - LLAssetType::AT_ANIMATION, - name, - desc, - 0, - LLFolderType::FT_NONE, - LLInventoryType::IT_ANIMATION, - LLFloaterPerms::getNextOwnerPerms(), LLFloaterPerms::getGroupPerms(), LLFloaterPerms::getEveryonePerms(), - name, - callback, expected_upload_cost, userdata); - } - } - else - { - llwarns << "Failure writing animation data." << llendl; - LLNotificationsUtil::add("WriteAnimationFail"); - } - } - - delete [] buffer; - // clear out cache for motion data - if (floaterp->mInWorld) - { - gAgentAvatarp->removeMotion(floaterp->mMotionID); - gAgentAvatarp->deactivateAllMotions(); - } - else - { - floaterp->mAnimPreview->getDummyAvatar()->removeMotion(floaterp->mMotionID); - } - LLKeyframeDataCache::removeKeyframeData(floaterp->mMotionID); - } - - floaterp->close(false); -} - -//----------------------------------------------------------------------------- -// LLPreviewAnimation -//----------------------------------------------------------------------------- -LLPreviewAnimation::LLPreviewAnimation(S32 width, S32 height) : LLViewerDynamicTexture(width, height, 3, ORDER_MIDDLE, FALSE) -{ - mNeedsUpdate = TRUE; - mCameraDistance = PREVIEW_CAMERA_DISTANCE; - mCameraYaw = 0.f; - mCameraPitch = 0.f; - mCameraZoom = 1.f; - - mDummyAvatar = (LLVOAvatar*)gObjectList.createObjectViewer(LL_PCODE_LEGACY_AVATAR, gAgent.getRegion()); - mDummyAvatar->createDrawable(&gPipeline); - mDummyAvatar->mIsDummy = TRUE; - mDummyAvatar->mSpecialRenderMode = 1; - mDummyAvatar->setPositionAgent(LLVector3::zero); - mDummyAvatar->slamPosition(); - mDummyAvatar->updateJointLODs(); - mDummyAvatar->updateGeometry(mDummyAvatar->mDrawable); - mDummyAvatar->startMotion(ANIM_AGENT_STAND, BASE_ANIM_TIME_OFFSET); - mDummyAvatar->hideSkirt(); - //gPipeline.markVisible(mDummyAvatar->mDrawable, *LLViewerCamera::getInstance()); - - // stop extraneous animations - mDummyAvatar->stopMotion( ANIM_AGENT_HEAD_ROT, TRUE ); - mDummyAvatar->stopMotion( ANIM_AGENT_EYE, TRUE ); - mDummyAvatar->stopMotion( ANIM_AGENT_BODY_NOISE, TRUE ); - mDummyAvatar->stopMotion( ANIM_AGENT_BREATHE_ROT, TRUE ); -} - -//----------------------------------------------------------------------------- -// LLPreviewAnimation() -//----------------------------------------------------------------------------- -LLPreviewAnimation::~LLPreviewAnimation() -{ - mDummyAvatar->markDead(); -} - -//virtual -S8 LLPreviewAnimation::getType() const -{ - return LLViewerDynamicTexture::LL_PREVIEW_ANIMATION ; -} - -//----------------------------------------------------------------------------- -// update() -//----------------------------------------------------------------------------- -BOOL LLPreviewAnimation::render() -{ - mNeedsUpdate = FALSE; - LLVOAvatar* avatarp = mDummyAvatar; - - gGL.matrixMode(LLRender::MM_PROJECTION); - gGL.pushMatrix(); - gGL.loadIdentity(); - gGL.ortho(0.0f, mFullWidth, 0.0f, mFullHeight, -1.0f, 1.0f); - - gGL.matrixMode(LLRender::MM_MODELVIEW); - gGL.pushMatrix(); - gGL.loadIdentity(); - - if (LLGLSLShader::sNoFixedFunction) - { - gUIProgram.bind(); - } - - LLGLSUIDefault def; - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - gGL.color4f(0.15f, 0.2f, 0.3f, 1.f); - - gl_rect_2d_simple( mFullWidth, mFullHeight ); - - gGL.matrixMode(LLRender::MM_PROJECTION); - gGL.popMatrix(); - - gGL.matrixMode(LLRender::MM_MODELVIEW); - gGL.popMatrix(); - - gGL.flush(); - - LLVector3 target_pos = avatarp->mRoot->getWorldPosition(); - - LLQuaternion camera_rot = LLQuaternion(mCameraPitch, LLVector3::y_axis) * - LLQuaternion(mCameraYaw, LLVector3::z_axis); - - LLQuaternion av_rot = avatarp->mRoot->getWorldRotation() * camera_rot; - LLViewerCamera::getInstance()->setOriginAndLookAt( - target_pos + ((LLVector3(mCameraDistance, 0.f, 0.f) + mCameraOffset) * av_rot), // camera - LLVector3::z_axis, // up - target_pos + (mCameraOffset * av_rot) ); // point of interest - - LLViewerCamera::getInstance()->setView(LLViewerCamera::getInstance()->getDefaultFOV() / mCameraZoom); - LLViewerCamera::getInstance()->setPerspective(FALSE, mOrigin.mX, mOrigin.mY, mFullWidth, mFullHeight, FALSE); - - mCameraRelPos = LLViewerCamera::getInstance()->getOrigin() - avatarp->mHeadp->getWorldPosition(); - - //avatarp->setAnimationData("LookAtPoint", (void *)&mCameraRelPos); - - //SJB: Animation is updated in LLVOAvatar::updateCharacter - - if (avatarp->mDrawable.notNull()) - { - avatarp->updateLOD(); - - LLVertexBuffer::unbind(); - LLGLDepthTest gls_depth(GL_TRUE); - - LLDrawPoolAvatar *avatarPoolp = (LLDrawPoolAvatar *)avatarp->mDrawable->getFace(0)->getPool(); - avatarp->dirtyMesh(); - avatarPoolp->renderAvatars(avatarp); // renders only one avatar - } - - gGL.color4f(1,1,1,1); - return TRUE; -} - -//----------------------------------------------------------------------------- -// requestUpdate() -//----------------------------------------------------------------------------- -void LLPreviewAnimation::requestUpdate() -{ - mNeedsUpdate = TRUE; -} - -//----------------------------------------------------------------------------- -// rotate() -//----------------------------------------------------------------------------- -void LLPreviewAnimation::rotate(F32 yaw_radians, F32 pitch_radians) -{ - mCameraYaw = mCameraYaw + yaw_radians; - - mCameraPitch = llclamp(mCameraPitch + pitch_radians, F_PI_BY_TWO * -0.8f, F_PI_BY_TWO * 0.8f); -} - -//----------------------------------------------------------------------------- -// zoom() -//----------------------------------------------------------------------------- -void LLPreviewAnimation::zoom(F32 zoom_delta) -{ - setZoom(mCameraZoom + zoom_delta); -} - -//----------------------------------------------------------------------------- -// setZoom() -//----------------------------------------------------------------------------- -void LLPreviewAnimation::setZoom(F32 zoom_amt) -{ - mCameraZoom = llclamp(zoom_amt, MIN_CAMERA_ZOOM, MAX_CAMERA_ZOOM); -} - -//----------------------------------------------------------------------------- -// pan() -//----------------------------------------------------------------------------- -void LLPreviewAnimation::pan(F32 right, F32 up) -{ - mCameraOffset.mV[VY] = llclamp(mCameraOffset.mV[VY] + right * mCameraDistance / mCameraZoom, -1.f, 1.f); - mCameraOffset.mV[VZ] = llclamp(mCameraOffset.mV[VZ] + up * mCameraDistance / mCameraZoom, -1.f, 1.f); -} - - - diff --git a/indra/newview/llfloateranimpreview.h b/indra/newview/llfloateranimpreview.h index d38a94de1..7603286e7 100644 --- a/indra/newview/llfloateranimpreview.h +++ b/indra/newview/llfloateranimpreview.h @@ -2,9 +2,7 @@ * @file llfloateranimpreview.h * @brief LLFloaterAnimPreview class definition * - * $LicenseInfo:firstyear=2004&license=viewergpl$ - * - * Copyright (c) 2004-2009, Linden Research, Inc. + * Copyright (c) 2012, Linden Research, Inc. * * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab @@ -34,112 +32,11 @@ #define LL_LLFLOATERANIMPREVIEW_H #include "llfloaternamedesc.h" -#include "lldynamictexture.h" -#include "llcharacter.h" -#include "llquaternion.h" -class LLVOAvatar; -class LLViewerJointMesh; - -class LLPreviewAnimation : public LLViewerDynamicTexture -{ -protected: - virtual ~LLPreviewAnimation(); - -public: - LLPreviewAnimation(S32 width, S32 height); - - /*virtual*/ S8 getType() const ; - - BOOL render(); - void requestUpdate(); - void rotate(F32 yaw_radians, F32 pitch_radians); - void zoom(F32 zoom_delta); - void setZoom(F32 zoom_amt); - void pan(F32 right, F32 up); - virtual BOOL needsUpdate() { return mNeedsUpdate; } - - LLVOAvatar* getDummyAvatar() { return mDummyAvatar; } - -protected: - BOOL mNeedsUpdate; - F32 mCameraDistance; - F32 mCameraYaw; - F32 mCameraPitch; - F32 mCameraZoom; - LLVector3 mCameraOffset; - LLVector3 mCameraRelPos; - LLPointer mDummyAvatar; -}; - -class LLFloaterAnimPreview : public LLFloaterNameDesc -{ -public: - // - LLFloaterAnimPreview(const std::string& filename, void* item = NULL); - // - virtual ~LLFloaterAnimPreview(); - - BOOL postBuild(); - - BOOL handleMouseDown(S32 x, S32 y, MASK mask); - BOOL handleMouseUp(S32 x, S32 y, MASK mask); - BOOL handleHover(S32 x, S32 y, MASK mask); - BOOL handleScrollWheel(S32 x, S32 y, S32 clicks); - void onMouseCaptureLost(); - - void refresh(); - - void onBtnPlay(); - void onBtnStop(); - static void setUploadAmount(S32 amount) { sUploadAmount = amount; } - static void onSliderMove(LLUICtrl*, void*); - static void onCommitBaseAnim(LLUICtrl*, void*); - static void onCommitLoop(LLUICtrl*, void*); - static void onCommitLoopIn(LLUICtrl*, void*); - static void onCommitLoopOut(LLUICtrl*, void*); - static BOOL validateLoopIn(LLUICtrl*, void*); - static BOOL validateLoopOut(LLUICtrl*, void*); - static void onCommitName(LLUICtrl*, void*); - static void onCommitHandPose(LLUICtrl*, void*); - static void onCommitEmote(LLUICtrl*, void*); - static void onCommitPriority(LLUICtrl*, void*); - static void onCommitEaseIn(LLUICtrl*, void*); - static void onCommitEaseOut(LLUICtrl*, void*); - static BOOL validateEaseIn(LLUICtrl*, void*); - static BOOL validateEaseOut(LLUICtrl*, void*); - static void onBtnOK(void*); - static void onSaveComplete(const LLUUID& asset_uuid, - LLAssetType::EType type, - void* user_data, - S32 status, LLExtStat ext_status); -private: - void setAnimCallbacks() ; - -protected: - void draw(); - void resetMotion(); - - LLPointer< LLPreviewAnimation> mAnimPreview; - S32 mLastMouseX; - S32 mLastMouseY; - LLButton* mPlayButton; - LLButton* mStopButton; - LLRect mPreviewRect; - LLRectf mPreviewImageRect; - LLAssetID mMotionID; - LLTransactionID mTransactionID; - BOOL mEnabled; - BOOL mInWorld; - LLAnimPauseRequest mPauseRequest; - - std::map mIDList; - - static S32 sUploadAmount; - - // - void* mItem; - // +class LLFloaterAnimPreview : public LLFloaterNameDesc { + public: + LLFloaterAnimPreview(LLSD const& filename); + virtual BOOL postBuild(void); }; #endif // LL_LLFLOATERANIMPREVIEW_H diff --git a/indra/newview/llfloaterblacklist.cpp b/indra/newview/llfloaterblacklist.cpp index 44e03ed16..0f5098e16 100644 --- a/indra/newview/llfloaterblacklist.cpp +++ b/indra/newview/llfloaterblacklist.cpp @@ -43,6 +43,25 @@ void LLFloaterBlacklist::show() sInstance->open(); } } +// static +void LLFloaterBlacklist::toggle() +{ + if (sInstance && sInstance->getVisible()) + { + delete sInstance; + } + else + { + show(); + } +} +// static +BOOL LLFloaterBlacklist::visible() +{ + if (sInstance && sInstance->getVisible()) + return TRUE; + return FALSE; +} BOOL LLFloaterBlacklist::postBuild() { childSetAction("add_btn", onClickAdd, this); diff --git a/indra/newview/llfloaterblacklist.h b/indra/newview/llfloaterblacklist.h index 6851e1a1e..9b5c4171f 100644 --- a/indra/newview/llfloaterblacklist.h +++ b/indra/newview/llfloaterblacklist.h @@ -11,6 +11,8 @@ public: LLFloaterBlacklist(); ~LLFloaterBlacklist(); static void show(); + static void toggle(); + static BOOL visible(); BOOL postBuild(); void refresh(); static LLFloaterBlacklist* getInstance() { return sInstance; }; diff --git a/indra/newview/llfloaterbvhpreview.cpp b/indra/newview/llfloaterbvhpreview.cpp new file mode 100644 index 000000000..a5eb65b01 --- /dev/null +++ b/indra/newview/llfloaterbvhpreview.cpp @@ -0,0 +1,1628 @@ +/** + * @file llfloaterbvhpreview.cpp + * @brief LLFloaterBvhPreview class implementation + * + * $LicenseInfo:firstyear=2004&license=viewergpl$ + * + * Copyright (c) 2004-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 "llfloaterbvhpreview.h" + +#include "llbvhloader.h" +#include "lldatapacker.h" +#include "lldir.h" +#include "llnotificationsutil.h" +#include "llvfile.h" +#include "llapr.h" +#include "llstring.h" + +#include "llagent.h" +#include "llanimationstates.h" +#include "llbbox.h" +#include "llbutton.h" +#include "llcheckboxctrl.h" +#include "llcombobox.h" +#include "lldrawable.h" +#include "lldrawpoolavatar.h" +#include "llrender.h" +#include "llface.h" +#include "llfocusmgr.h" +#include "llkeyframemotion.h" +#include "lllineeditor.h" +#include "llfloaterperms.h" +#include "llsliderctrl.h" +#include "llspinctrl.h" +#include "lltextbox.h" +#include "lltoolmgr.h" +#include "llui.h" +#include "llviewercamera.h" +#include "llviewerobjectlist.h" +#include "llviewerwindow.h" +#include "llviewermenufile.h" // upload_new_resource() +#include "llvoavatarself.h" +#include "pipeline.h" +#include "lluictrlfactory.h" +#include "llviewercontrol.h" + +#include "hippogridmanager.h" + +// +#include "llinventorymodel.h" // gInventoryModel +// + +S32 LLFloaterBvhPreview::sUploadAmount = 10; + +const S32 PREVIEW_BORDER_WIDTH = 2; +const S32 PREVIEW_RESIZE_HANDLE_SIZE = S32(RESIZE_HANDLE_WIDTH * OO_SQRT2) + PREVIEW_BORDER_WIDTH; +const S32 PREVIEW_HPAD = PREVIEW_RESIZE_HANDLE_SIZE; +const S32 PREF_BUTTON_HEIGHT = 16; +const S32 PREVIEW_TEXTURE_HEIGHT = 300; + +const F32 PREVIEW_CAMERA_DISTANCE = 4.f; + +const F32 MIN_CAMERA_ZOOM = 0.5f; +const F32 MAX_CAMERA_ZOOM = 10.f; + +const F32 BASE_ANIM_TIME_OFFSET = 5.f; + +// +struct LLSaveInfo +{ + LLSaveInfo(const LLUUID& item_id, const LLUUID& object_id, const std::string& desc, + const LLTransactionID tid) + : mItemUUID(item_id), mObjectUUID(object_id), mDesc(desc), mTransactionID(tid) + { + } + + LLUUID mItemUUID; + LLUUID mObjectUUID; + std::string mDesc; + LLTransactionID mTransactionID; +}; +// + +std::string STATUS[] = +{ + "E_ST_OK", + "E_ST_EOF", + "E_ST_NO_CONSTRAINT", + "E_ST_NO_FILE", + "E_ST_NO_HIER", + "E_ST_NO_JOINT", + "E_ST_NO_NAME", + "E_ST_NO_OFFSET", + "E_ST_NO_CHANNELS", + "E_ST_NO_ROTATION", + "E_ST_NO_AXIS", + "E_ST_NO_MOTION", + "E_ST_NO_FRAMES", + "E_ST_NO_FRAME_TIME", + "E_ST_NO_POS", + "E_ST_NO_ROT", + "E_ST_NO_XLT_FILE", + "E_ST_NO_XLT_HEADER", + "E_ST_NO_XLT_NAME", + "E_ST_NO_XLT_IGNORE", + "E_ST_NO_XLT_RELATIVE", + "E_ST_NO_XLT_OUTNAME", + "E_ST_NO_XLT_MATRIX", + "E_ST_NO_XLT_MERGECHILD", + "E_ST_NO_XLT_MERGEPARENT", + "E_ST_NO_XLT_PRIORITY", + "E_ST_NO_XLT_LOOP", + "E_ST_NO_XLT_EASEIN", + "E_ST_NO_XLT_EASEOUT", + "E_ST_NO_XLT_HAND", + "E_ST_NO_XLT_EMOTE", +"E_ST_BAD_ROOT" +}; + + +//----------------------------------------------------------------------------- +// LLFloaterBvhPreview() +//----------------------------------------------------------------------------- +LLFloaterBvhPreview::LLFloaterBvhPreview(const std::string& filename, void* item) : + LLFloaterNameDesc(filename) +{ + // + mItem = item; + // + + mLastMouseX = 0; + mLastMouseY = 0; + + mIDList["Standing"] = ANIM_AGENT_STAND; + mIDList["Walking"] = ANIM_AGENT_FEMALE_WALK; + mIDList["Sitting"] = ANIM_AGENT_SIT_FEMALE; + mIDList["Flying"] = ANIM_AGENT_HOVER; + + mIDList["[None]"] = LLUUID::null; + mIDList["Aaaaah"] = ANIM_AGENT_EXPRESS_OPEN_MOUTH; + mIDList["Afraid"] = ANIM_AGENT_EXPRESS_AFRAID; + mIDList["Angry"] = ANIM_AGENT_EXPRESS_ANGER; + mIDList["Big Smile"] = ANIM_AGENT_EXPRESS_TOOTHSMILE; + mIDList["Bored"] = ANIM_AGENT_EXPRESS_BORED; + mIDList["Cry"] = ANIM_AGENT_EXPRESS_CRY; + mIDList["Disdain"] = ANIM_AGENT_EXPRESS_DISDAIN; + mIDList["Embarrassed"] = ANIM_AGENT_EXPRESS_EMBARRASSED; + mIDList["Frown"] = ANIM_AGENT_EXPRESS_FROWN; + mIDList["Kiss"] = ANIM_AGENT_EXPRESS_KISS; + mIDList["Laugh"] = ANIM_AGENT_EXPRESS_LAUGH; + mIDList["Plllppt"] = ANIM_AGENT_EXPRESS_TONGUE_OUT; + mIDList["Repulsed"] = ANIM_AGENT_EXPRESS_REPULSED; + mIDList["Sad"] = ANIM_AGENT_EXPRESS_SAD; + mIDList["Shrug"] = ANIM_AGENT_EXPRESS_SHRUG; + mIDList["Smile"] = ANIM_AGENT_EXPRESS_SMILE; + mIDList["Surprise"] = ANIM_AGENT_EXPRESS_SURPRISE; + mIDList["Wink"] = ANIM_AGENT_EXPRESS_WINK; + mIDList["Worry"] = ANIM_AGENT_EXPRESS_WORRY; +} + +//----------------------------------------------------------------------------- +// setAnimCallbacks() +//----------------------------------------------------------------------------- +void LLFloaterBvhPreview::setAnimCallbacks() +{ + childSetCommitCallback("playback_slider", onSliderMove, this); + + childSetCommitCallback("preview_base_anim", onCommitBaseAnim, this); + childSetValue("preview_base_anim", "Standing"); + + childSetCommitCallback("priority", onCommitPriority, this); + childSetCommitCallback("loop_check", onCommitLoop, this); + childSetCommitCallback("loop_in_point", onCommitLoopIn, this); + childSetValidate("loop_in_point", validateLoopIn); + childSetCommitCallback("loop_out_point", onCommitLoopOut, this); + childSetValidate("loop_out_point", validateLoopOut); + + childSetCommitCallback("hand_pose_combo", onCommitHandPose, this); + + childSetCommitCallback("emote_combo", onCommitEmote, this); + childSetValue("emote_combo", "[None]"); + + childSetCommitCallback("ease_in_time", onCommitEaseIn, this); + childSetValidate("ease_in_time", validateEaseIn); + childSetCommitCallback("ease_out_time", onCommitEaseOut, this); + childSetValidate("ease_out_time", validateEaseOut); +} + +//----------------------------------------------------------------------------- +// postBuild() +//----------------------------------------------------------------------------- +BOOL LLFloaterBvhPreview::postBuild() +{ + LLRect r; + LLKeyframeMotion* motionp = NULL; + LLBVHLoader* loaderp = NULL; + + if (!LLFloaterNameDesc::postBuild()) + { + return FALSE; + } + + mInWorld = gSavedSettings.getBOOL("PreviewAnimInWorld"); + + childSetCommitCallback("name_form", onCommitName, this); + + if (gSavedSettings.getBOOL("AscentPowerfulWizard")) + { + childSetMaxValue("priority", 7); + } + + childSetLabelArg("ok_btn", "[UPLOADFEE]", gHippoGridManager->getConnectedGrid()->getUploadFee()); + childSetAction("ok_btn", onBtnOK, this); + setDefaultBtn(); + + if (mInWorld) + { + r = getRect(); + translate(0, 230); + reshape(r.getWidth(), r.getHeight() - 230); + childSetValue("bad_animation_text", getString("in_world")); + childShow("bad_animation_text"); + } + else + { + childHide("bad_animation_text"); + } + + mPreviewRect.set(PREVIEW_HPAD, + PREVIEW_TEXTURE_HEIGHT, + getRect().getWidth() - PREVIEW_HPAD, + PREVIEW_HPAD + PREF_BUTTON_HEIGHT + PREVIEW_HPAD); + mPreviewImageRect.set(0.f, 1.f, 1.f, 0.f); + + S32 y = mPreviewRect.mTop + BTN_HEIGHT; + S32 btn_left = PREVIEW_HPAD; + + r.set( btn_left, y, btn_left + 32, y - BTN_HEIGHT ); + mPlayButton = getChild( "play_btn"); + if (!mPlayButton) + { + mPlayButton = new LLButton("play_btn"); + } + mPlayButton->setClickedCallback(boost::bind(&LLFloaterBvhPreview::onBtnPlay,this)); + + mPlayButton->setImages(std::string("button_anim_play.tga"), + std::string("button_anim_play_selected.tga")); + + mPlayButton->setImageDisabled(NULL); + mPlayButton->setImageDisabledSelected(NULL); + + mPlayButton->setScaleImage(TRUE); + + mStopButton = getChild( "stop_btn"); + if (!mStopButton) + { + mStopButton = new LLButton("stop_btn"); + } + mStopButton->setClickedCallback(boost::bind(&LLFloaterBvhPreview::onBtnStop, this)); + + mStopButton->setImages(std::string("button_anim_stop.tga"), + std::string("button_anim_stop_selected.tga")); + + mStopButton->setImageDisabled(NULL); + mStopButton->setImageDisabledSelected(NULL); + + mStopButton->setScaleImage(TRUE); + + r.set(r.mRight + PREVIEW_HPAD, y, getRect().getWidth() - PREVIEW_HPAD, y - BTN_HEIGHT); + //childSetCommitCallback("playback_slider", onSliderMove, this); + + //childSetCommitCallback("preview_base_anim", onCommitBaseAnim, this); + //childSetValue("preview_base_anim", "Standing"); + + //childSetCommitCallback("priority", onCommitPriority, this); + //childSetCommitCallback("loop_check", onCommitLoop, this); + //childSetCommitCallback("loop_in_point", onCommitLoopIn, this); + //childSetValidate("loop_in_point", validateLoopIn); + //childSetCommitCallback("loop_out_point", onCommitLoopOut, this); + //childSetValidate("loop_out_point", validateLoopOut); + + //childSetCommitCallback("hand_pose_combo", onCommitHandPose, this); + + //childSetCommitCallback("emote_combo", onCommitEmote, this); + //childSetValue("emote_combo", "[None]"); + + //childSetCommitCallback("ease_in_time", onCommitEaseIn, this); + //childSetValidate("ease_in_time", validateEaseIn); + //childSetCommitCallback("ease_out_time", onCommitEaseOut, this); + //childSetValidate("ease_out_time", validateEaseOut); + + // moved declaration from below + BOOL success = false; + // + + std::string exten = gDirUtilp->getExtension(mFilename); + if (exten == "bvh") + { + // loading a bvh file + + // now load bvh file + S32 file_size; + + LLAPRFile infile(mFilenameAndPath, LL_APR_RB, &file_size); + + if (!infile.getFileHandle()) + { + llwarns << "Can't open BVH file:" << mFilename << llendl; + } + else + { + char* file_buffer; + + file_buffer = new char[file_size + 1]; + + if (file_size == infile.read(file_buffer, file_size)) + { + file_buffer[file_size] = '\0'; + llinfos << "Loading BVH file " << mFilename << llendl; + ELoadStatus load_status = E_ST_OK; + S32 line_number = 0; + loaderp = new LLBVHLoader(file_buffer, load_status, line_number); + std::string status = getString(STATUS[load_status]); + + if(load_status == E_ST_NO_XLT_FILE) + { + llwarns << "NOTE: No translation table found." << llendl; + } + else + { + llwarns << "ERROR: [line: " << line_number << "] " << status << llendl; + } + } + + infile.close() ; + delete[] file_buffer; + + // moved everything bvh from below + if(loaderp && loaderp->isInitialized() && loaderp->getDuration() <= MAX_ANIM_DURATION) + { + mTransactionID.generate(); + mMotionID = mTransactionID.makeAssetID(gAgent.getSecureSessionID()); + + mAnimPreview = new LLPreviewAnimation(256, 256); + + // motion will be returned, but it will be in a load-pending state, as this is a new motion + // this motion will not request an asset transfer until next update, so we have a chance to + // load the keyframe data locally + if (mInWorld) + { + motionp = (LLKeyframeMotion*)gAgentAvatarp->createMotion(mMotionID); + } + else + { + motionp = (LLKeyframeMotion*)mAnimPreview->getDummyAvatar()->createMotion(mMotionID); + } + + // create data buffer for keyframe initialization + S32 buffer_size = loaderp->getOutputSize(); + U8* buffer = new U8[buffer_size]; + + LLDataPackerBinaryBuffer dp(buffer, buffer_size); + + // pass animation data through memory buffer + loaderp->serialize(dp); + dp.reset(); + success = motionp && motionp->deserialize(dp); + } + else + { + success = false; + if ( loaderp ) + { + if (loaderp->getDuration() > MAX_ANIM_DURATION) + { + LLUIString out_str = getString("anim_too_long"); + out_str.setArg("[LENGTH]", llformat("%.1f", loaderp->getDuration())); + out_str.setArg("[MAX_LENGTH]", llformat("%.1f", MAX_ANIM_DURATION)); + getChild("bad_animation_text")->setValue(out_str.getString()); + } + else + { + LLUIString out_str = getString("failed_file_read"); + out_str.setArg("[STATUS]", getString(STATUS[loaderp->getStatus()])); + getChild("bad_animation_text")->setValue(out_str.getString()); + } + } + + //setEnabled(FALSE); + mMotionID.setNull(); + mAnimPreview = NULL; + } + // + } + } + // + else if(exten == "animatn") + { + S32 file_size; + LLAPRFile raw_animatn(mFilenameAndPath, LL_APR_RB, &file_size); + + if (!raw_animatn.getFileHandle()) + { + llwarns << "Can't open animatn file:" << mFilename << llendl; + } + else + { + char* file_buffer; + + file_buffer = new char[file_size + 1]; + + if (file_size == raw_animatn.read(file_buffer, file_size)) + { + file_buffer[file_size] = '\0'; + llinfos << "Loading animatn file " << mFilename << llendl; + mTransactionID.generate(); + mMotionID = mTransactionID.makeAssetID(gAgent.getSecureSessionID()); + mAnimPreview = new LLPreviewAnimation(256, 256); + motionp = (LLKeyframeMotion*)mAnimPreview->getDummyAvatar()->createMotion(mMotionID); + LLDataPackerBinaryBuffer dp((U8*)file_buffer, file_size); + dp.reset(); + success = motionp && motionp->deserialize(dp); + } + + raw_animatn.close(); + delete[] file_buffer; + } + } + // + + if (success) + { + setAnimCallbacks() ; + + if (!mInWorld) + { + const LLBBoxLocal &pelvis_bbox = motionp->getPelvisBBox(); + + LLVector3 temp = pelvis_bbox.getCenter(); + // only consider XY? + //temp.mV[VZ] = 0.f; + F32 pelvis_offset = temp.magVec(); + + temp = pelvis_bbox.getExtent(); + //temp.mV[VZ] = 0.f; + F32 pelvis_max_displacement = pelvis_offset + (temp.magVec() * 0.5f) + 1.f; + + F32 camera_zoom = LLViewerCamera::getInstance()->getDefaultFOV() / (2.f * atan(pelvis_max_displacement / PREVIEW_CAMERA_DISTANCE)); + + mAnimPreview->setZoom(camera_zoom); + } + + motionp->setName(childGetValue("name_form").asString()); + if (!mInWorld) + { + mAnimPreview->getDummyAvatar()->startMotion(mMotionID); + } + childSetMinValue("playback_slider", 0.0); + childSetMaxValue("playback_slider", 1.0); + + childSetValue("loop_check", LLSD(motionp->getLoop())); + childSetValue("loop_in_point", LLSD(motionp->getLoopIn() / motionp->getDuration() * 100.f)); + childSetValue("loop_out_point", LLSD(motionp->getLoopOut() / motionp->getDuration() * 100.f)); + childSetValue("priority", LLSD((F32)motionp->getPriority())); + childSetValue("hand_pose_combo", LLHandMotion::getHandPoseName(motionp->getHandPose())); + childSetValue("ease_in_time", LLSD(motionp->getEaseInDuration())); + childSetValue("ease_out_time", LLSD(motionp->getEaseOutDuration())); + setEnabled(TRUE); + std::string seconds_string; + seconds_string = llformat(" - %.2f seconds", motionp->getDuration()); + + setTitle(mFilename + std::string(seconds_string)); + } + else + { + mAnimPreview = NULL; + mMotionID.setNull(); + childSetValue("bad_animation_text", getString("failed_to_initialize")); + } + + + refresh(); + + delete loaderp; + + return TRUE; +} + +//----------------------------------------------------------------------------- +// LLFloaterBvhPreview() +//----------------------------------------------------------------------------- +LLFloaterBvhPreview::~LLFloaterBvhPreview() +{ + if (mInWorld) + { + LLVOAvatar* avatarp = gAgentAvatarp; + if (avatarp) + { + if (mMotionID.notNull()) + { + avatarp->stopMotion(mMotionID, TRUE); + avatarp->removeMotion(mMotionID); + } + avatarp->deactivateAllMotions(); + avatarp->startMotion(ANIM_AGENT_HEAD_ROT); + avatarp->startMotion(ANIM_AGENT_EYE); + avatarp->startMotion(ANIM_AGENT_BODY_NOISE); + avatarp->startMotion(ANIM_AGENT_BREATHE_ROT); + avatarp->startMotion(ANIM_AGENT_HAND_MOTION); + avatarp->startMotion(ANIM_AGENT_PELVIS_FIX); + avatarp->startMotion(ANIM_AGENT_STAND, BASE_ANIM_TIME_OFFSET); + } + } + mAnimPreview = NULL; + + setEnabled(FALSE); +} + +//----------------------------------------------------------------------------- +// draw() +//----------------------------------------------------------------------------- +void LLFloaterBvhPreview::draw() +{ + LLFloater::draw(); + LLRect r = getRect(); + + refresh(); + + if (mMotionID.notNull() && mAnimPreview && !mInWorld) + { + gGL.color3f(1.f, 1.f, 1.f); + + gGL.getTexUnit(0)->bind(mAnimPreview); + + gGL.begin( LLRender::QUADS ); + { + gGL.texCoord2f(0.f, 1.f); + gGL.vertex2i(PREVIEW_HPAD, PREVIEW_TEXTURE_HEIGHT); + gGL.texCoord2f(0.f, 0.f); + gGL.vertex2i(PREVIEW_HPAD, PREVIEW_HPAD + PREF_BUTTON_HEIGHT + PREVIEW_HPAD); + gGL.texCoord2f(1.f, 0.f); + gGL.vertex2i(r.getWidth() - PREVIEW_HPAD, PREVIEW_HPAD + PREF_BUTTON_HEIGHT + PREVIEW_HPAD); + gGL.texCoord2f(1.f, 1.f); + gGL.vertex2i(r.getWidth() - PREVIEW_HPAD, PREVIEW_TEXTURE_HEIGHT); + } + gGL.end(); + + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + + LLVOAvatar* avatarp = mAnimPreview->getDummyAvatar(); + if (!avatarp->areAnimationsPaused()) + { + mAnimPreview->requestUpdate(); + } + } +} + +//----------------------------------------------------------------------------- +// resetMotion() +//----------------------------------------------------------------------------- +void LLFloaterBvhPreview::resetMotion() +{ + LLVOAvatar* avatarp; + if (mInWorld) + { + avatarp = gAgentAvatarp; + } + else + { + avatarp = mAnimPreview->getDummyAvatar(); + } + if (!avatarp) + { + return; + } + + BOOL paused = avatarp->areAnimationsPaused(); + + // *TODO: Fix awful casting hack + LLKeyframeMotion* motionp = (LLKeyframeMotion*)avatarp->findMotion(mMotionID); + + // Set emotion + std::string emote = childGetValue("emote_combo").asString(); + motionp->setEmote(mIDList[emote]); + + LLUUID base_id = mIDList[childGetValue("preview_base_anim").asString()]; + avatarp->deactivateAllMotions(); + avatarp->startMotion(base_id, BASE_ANIM_TIME_OFFSET); + avatarp->startMotion(mMotionID, 0.0f); + childSetValue("playback_slider", 0.0f); + + // Set pose + std::string handpose = childGetValue("hand_pose_combo").asString(); + avatarp->startMotion( ANIM_AGENT_HAND_MOTION, 0.0f ); + motionp->setHandPose(LLHandMotion::getHandPose(handpose)); + + if (paused) + { + mPauseRequest = avatarp->requestPause(); + } + else + { + mPauseRequest = NULL; + } +} + +//----------------------------------------------------------------------------- +// handleMouseDown() +//----------------------------------------------------------------------------- +BOOL LLFloaterBvhPreview::handleMouseDown(S32 x, S32 y, MASK mask) +{ + if (!mInWorld && mPreviewRect.pointInRect(x, y)) + { + bringToFront( x, y ); + gFocusMgr.setMouseCapture(this); + gViewerWindow->hideCursor(); + mLastMouseX = x; + mLastMouseY = y; + return TRUE; + } + + return LLFloater::handleMouseDown(x, y, mask); +} + +//----------------------------------------------------------------------------- +// handleMouseUp() +//----------------------------------------------------------------------------- +BOOL LLFloaterBvhPreview::handleMouseUp(S32 x, S32 y, MASK mask) +{ + if (!mInWorld) + { + gFocusMgr.setMouseCapture(FALSE); + gViewerWindow->showCursor(); + } + return LLFloater::handleMouseUp(x, y, mask); +} + +//----------------------------------------------------------------------------- +// handleHover() +//----------------------------------------------------------------------------- +BOOL LLFloaterBvhPreview::handleHover(S32 x, S32 y, MASK mask) +{ + if (mInWorld) + { + return TRUE; + } + + MASK local_mask = mask & ~MASK_ALT; + + if (mAnimPreview && hasMouseCapture()) + { + if (local_mask == MASK_PAN) + { + // pan here + mAnimPreview->pan((F32)(x - mLastMouseX) * -0.005f, (F32)(y - mLastMouseY) * -0.005f); + } + else if (local_mask == MASK_ORBIT) + { + F32 yaw_radians = (F32)(x - mLastMouseX) * -0.01f; + F32 pitch_radians = (F32)(y - mLastMouseY) * 0.02f; + + mAnimPreview->rotate(yaw_radians, pitch_radians); + } + else + { + F32 yaw_radians = (F32)(x - mLastMouseX) * -0.01f; + F32 zoom_amt = (F32)(y - mLastMouseY) * 0.02f; + + mAnimPreview->rotate(yaw_radians, 0.f); + mAnimPreview->zoom(zoom_amt); + } + + mAnimPreview->requestUpdate(); + + LLUI::setMousePositionLocal(this, mLastMouseX, mLastMouseY); + } + + if (!mPreviewRect.pointInRect(x, y) || !mAnimPreview) + { + return LLFloater::handleHover(x, y, mask); + } + else if (local_mask == MASK_ORBIT) + { + gViewerWindow->setCursor(UI_CURSOR_TOOLCAMERA); + } + else if (local_mask == MASK_PAN) + { + gViewerWindow->setCursor(UI_CURSOR_TOOLPAN); + } + else + { + gViewerWindow->setCursor(UI_CURSOR_TOOLZOOMIN); + } + + return TRUE; +} + +//----------------------------------------------------------------------------- +// handleScrollWheel() +//----------------------------------------------------------------------------- +BOOL LLFloaterBvhPreview::handleScrollWheel(S32 x, S32 y, S32 clicks) +{ + if (!mInWorld) + { + mAnimPreview->zoom((F32)clicks * -0.2f); + mAnimPreview->requestUpdate(); + } + return TRUE; +} + +//----------------------------------------------------------------------------- +// onMouseCaptureLost() +//----------------------------------------------------------------------------- +void LLFloaterBvhPreview::onMouseCaptureLost() +{ + if (!mInWorld) + { + gViewerWindow->showCursor(); + } +} + +//----------------------------------------------------------------------------- +// onBtnPlay() +//----------------------------------------------------------------------------- +void LLFloaterBvhPreview::onBtnPlay() +{ + if (!getEnabled()) + return; + + if (mMotionID.notNull()) + { + LLVOAvatar* avatarp; + if (mInWorld) + { + if (!gAgentAvatarp) + { + return; + } + avatarp = gAgentAvatarp; + } + else + { + if (!mAnimPreview) + { + return; + } + avatarp = mAnimPreview->getDummyAvatar(); + } + + if(!avatarp->isMotionActive(mMotionID)) + { + resetMotion(); + mPauseRequest = NULL; + } + else + { + if (avatarp->areAnimationsPaused()) + { + mPauseRequest = NULL; + } + else + { + mPauseRequest = avatarp->requestPause(); + } + } + } +} + +//----------------------------------------------------------------------------- +// onBtnStop() +//----------------------------------------------------------------------------- +void LLFloaterBvhPreview::onBtnStop() +{ + if (!getEnabled()) + return; + + if (mMotionID.notNull()) + { + LLVOAvatar* avatarp; + if (mInWorld) + { + if (!gAgentAvatarp) + { + return; + } + avatarp = gAgentAvatarp; + } + else + { + if (!mAnimPreview) + { + return; + } + avatarp = mAnimPreview->getDummyAvatar(); + } + resetMotion(); + mPauseRequest = avatarp->requestPause(); + } +} + +//----------------------------------------------------------------------------- +// onSliderMove() +//----------------------------------------------------------------------------- +void LLFloaterBvhPreview::onSliderMove(LLUICtrl* ctrl, void*user_data) +{ + LLFloaterBvhPreview* previewp = (LLFloaterBvhPreview*)user_data; + if (!previewp->getEnabled()) + return; + + LLVOAvatar* avatarp; + if (previewp->mInWorld) + { + if (!gAgentAvatarp) + { + return; + } + avatarp = gAgentAvatarp; + } + else + { + if (!previewp->mAnimPreview) + { + return; + } + avatarp = previewp->mAnimPreview->getDummyAvatar(); + } + F32 slider_value = (F32)previewp->childGetValue("playback_slider").asReal(); + LLUUID base_id = previewp->mIDList[previewp->childGetValue("preview_base_anim").asString()]; + LLMotion* motionp = avatarp->findMotion(previewp->mMotionID); + F32 duration = motionp->getDuration();// + motionp->getEaseOutDuration(); + F32 delta_time = duration * slider_value; + avatarp->deactivateAllMotions(); + avatarp->startMotion(base_id, delta_time + BASE_ANIM_TIME_OFFSET); + avatarp->startMotion(previewp->mMotionID, delta_time); + previewp->mPauseRequest = avatarp->requestPause(); + previewp->refresh(); +} + +//----------------------------------------------------------------------------- +// onCommitBaseAnim() +//----------------------------------------------------------------------------- +void LLFloaterBvhPreview::onCommitBaseAnim(LLUICtrl* ctrl, void* data) +{ + LLFloaterBvhPreview* previewp = (LLFloaterBvhPreview*)data; + if (!previewp->getEnabled()) + return; + + LLVOAvatar* avatarp; + if (previewp->mInWorld) + { + if (!gAgentAvatarp) + { + return; + } + avatarp = gAgentAvatarp; + } + else + { + if (!previewp->mAnimPreview) + { + return; + } + avatarp = previewp->mAnimPreview->getDummyAvatar(); + } + + BOOL paused = avatarp->areAnimationsPaused(); + + // stop all other possible base motions + avatarp->stopMotion(ANIM_AGENT_STAND, TRUE); + avatarp->stopMotion(ANIM_AGENT_WALK, TRUE); + avatarp->stopMotion(ANIM_AGENT_SIT, TRUE); + avatarp->stopMotion(ANIM_AGENT_HOVER, TRUE); + + previewp->resetMotion(); + + if (!paused) + { + previewp->mPauseRequest = NULL; + } +} + +//----------------------------------------------------------------------------- +// onCommitLoop() +//----------------------------------------------------------------------------- +void LLFloaterBvhPreview::onCommitLoop(LLUICtrl* ctrl, void* data) +{ + LLFloaterBvhPreview* previewp = (LLFloaterBvhPreview*)data; + if (!previewp->getEnabled()) + return; + + LLVOAvatar* avatarp; + if (previewp->mInWorld) + { + if (!gAgentAvatarp) + { + return; + } + avatarp = gAgentAvatarp; + } + else + { + if (!previewp->mAnimPreview) + { + return; + } + avatarp = previewp->mAnimPreview->getDummyAvatar(); + } + LLKeyframeMotion* motionp = (LLKeyframeMotion*)avatarp->findMotion(previewp->mMotionID); + + if (motionp) + { + motionp->setLoop(previewp->childGetValue("loop_check").asBoolean()); + motionp->setLoopIn((F32)previewp->childGetValue("loop_in_point").asReal() * 0.01f * motionp->getDuration()); + motionp->setLoopOut((F32)previewp->childGetValue("loop_out_point").asReal() * 0.01f * motionp->getDuration()); + } +} + +//----------------------------------------------------------------------------- +// onCommitLoopIn() +//----------------------------------------------------------------------------- +void LLFloaterBvhPreview::onCommitLoopIn(LLUICtrl* ctrl, void* data) +{ + LLFloaterBvhPreview* previewp = (LLFloaterBvhPreview*)data; + if (!previewp->getEnabled()) + return; + + LLVOAvatar* avatarp; + if (previewp->mInWorld) + { + if (!gAgentAvatarp) + { + return; + } + avatarp = gAgentAvatarp; + } + else + { + if (!previewp->mAnimPreview) + { + return; + } + avatarp = previewp->mAnimPreview->getDummyAvatar(); + } + LLKeyframeMotion* motionp = (LLKeyframeMotion*)avatarp->findMotion(previewp->mMotionID); + + if (motionp) + { + motionp->setLoopIn((F32)previewp->childGetValue("loop_in_point").asReal() / 100.f); + previewp->resetMotion(); + previewp->childSetValue("loop_check", LLSD(TRUE)); + onCommitLoop(ctrl, data); + } +} + +//----------------------------------------------------------------------------- +// onCommitLoopOut() +//----------------------------------------------------------------------------- +void LLFloaterBvhPreview::onCommitLoopOut(LLUICtrl* ctrl, void* data) +{ + LLFloaterBvhPreview* previewp = (LLFloaterBvhPreview*)data; + if (!previewp->getEnabled()) + return; + + LLVOAvatar* avatarp; + if (previewp->mInWorld) + { + if (!gAgentAvatarp) + { + return; + } + avatarp = gAgentAvatarp; + } + else + { + if (!previewp->mAnimPreview) + { + return; + } + avatarp = previewp->mAnimPreview->getDummyAvatar(); + } + LLKeyframeMotion* motionp = (LLKeyframeMotion*)avatarp->findMotion(previewp->mMotionID); + + if (motionp) + { + motionp->setLoopOut((F32)previewp->childGetValue("loop_out_point").asReal() * 0.01f * motionp->getDuration()); + previewp->resetMotion(); + previewp->childSetValue("loop_check", LLSD(TRUE)); + onCommitLoop(ctrl, data); + } +} + +//----------------------------------------------------------------------------- +// onCommitName() +//----------------------------------------------------------------------------- +void LLFloaterBvhPreview::onCommitName(LLUICtrl* ctrl, void* data) +{ + LLFloaterBvhPreview* previewp = (LLFloaterBvhPreview*)data; + if (!previewp->getEnabled()) + return; + + LLVOAvatar* avatarp; + if (previewp->mInWorld) + { + if (!gAgentAvatarp) + { + return; + } + avatarp = gAgentAvatarp; + } + else + { + if (!previewp->mAnimPreview) + { + return; + } + avatarp = previewp->mAnimPreview->getDummyAvatar(); + } + LLKeyframeMotion* motionp = (LLKeyframeMotion*)avatarp->findMotion(previewp->mMotionID); + + if (motionp) + { + motionp->setName(previewp->childGetValue("name_form").asString()); + } + + LLFloaterNameDesc::doCommit(ctrl, data); +} + +//----------------------------------------------------------------------------- +// onCommitHandPose() +//----------------------------------------------------------------------------- +void LLFloaterBvhPreview::onCommitHandPose(LLUICtrl* ctrl, void* data) +{ + LLFloaterBvhPreview* previewp = (LLFloaterBvhPreview*)data; + if (!previewp->getEnabled()) + return; + + previewp->resetMotion(); // sets hand pose +} + +//----------------------------------------------------------------------------- +// onCommitEmote() +//----------------------------------------------------------------------------- +void LLFloaterBvhPreview::onCommitEmote(LLUICtrl* ctrl, void* data) +{ + LLFloaterBvhPreview* previewp = (LLFloaterBvhPreview*)data; + if (!previewp->getEnabled()) + return; + + previewp->resetMotion(); // ssts emote +} + +//----------------------------------------------------------------------------- +// onCommitPriority() +//----------------------------------------------------------------------------- +void LLFloaterBvhPreview::onCommitPriority(LLUICtrl* ctrl, void* data) +{ + LLFloaterBvhPreview* previewp = (LLFloaterBvhPreview*)data; + if (!previewp->getEnabled()) + return; + + LLVOAvatar* avatarp; + if (previewp->mInWorld) + { + if (!gAgentAvatarp) + { + return; + } + avatarp = gAgentAvatarp; + } + else + { + if (!previewp->mAnimPreview) + { + return; + } + avatarp = previewp->mAnimPreview->getDummyAvatar(); + } + LLKeyframeMotion* motionp = (LLKeyframeMotion*)avatarp->findMotion(previewp->mMotionID); + + motionp->setPriority(llfloor((F32)previewp->childGetValue("priority").asReal())); +} + +//----------------------------------------------------------------------------- +// onCommitEaseIn() +//----------------------------------------------------------------------------- +void LLFloaterBvhPreview::onCommitEaseIn(LLUICtrl* ctrl, void* data) +{ + LLFloaterBvhPreview* previewp = (LLFloaterBvhPreview*)data; + if (!previewp->getEnabled()) + return; + + LLVOAvatar* avatarp; + if (previewp->mInWorld) + { + if (!gAgentAvatarp) + { + return; + } + avatarp = gAgentAvatarp; + } + else + { + if (!previewp->mAnimPreview) + { + return; + } + avatarp = previewp->mAnimPreview->getDummyAvatar(); + } + LLKeyframeMotion* motionp = (LLKeyframeMotion*)avatarp->findMotion(previewp->mMotionID); + + motionp->setEaseIn((F32)previewp->childGetValue("ease_in_time").asReal()); + previewp->resetMotion(); +} + +//----------------------------------------------------------------------------- +// onCommitEaseOut() +//----------------------------------------------------------------------------- +void LLFloaterBvhPreview::onCommitEaseOut(LLUICtrl* ctrl, void* data) +{ + LLFloaterBvhPreview* previewp = (LLFloaterBvhPreview*)data; + if (!previewp->getEnabled()) + return; + + LLVOAvatar* avatarp; + if (previewp->mInWorld) + { + if (!gAgentAvatarp) + { + return; + } + avatarp = gAgentAvatarp; + } + else + { + if (!previewp->mAnimPreview) + { + return; + } + avatarp = previewp->mAnimPreview->getDummyAvatar(); + } + LLKeyframeMotion* motionp = (LLKeyframeMotion*)avatarp->findMotion(previewp->mMotionID); + + motionp->setEaseOut((F32)previewp->childGetValue("ease_out_time").asReal()); + previewp->resetMotion(); +} + +//----------------------------------------------------------------------------- +// validateEaseIn() +//----------------------------------------------------------------------------- +BOOL LLFloaterBvhPreview::validateEaseIn(LLUICtrl* spin, void* data) +{ + LLFloaterBvhPreview* previewp = (LLFloaterBvhPreview*)data; + if (!previewp->getEnabled()) + return FALSE; + + LLVOAvatar* avatarp; + if (previewp->mInWorld) + { + if (!gAgentAvatarp) + { + return FALSE; + } + avatarp = gAgentAvatarp; + } + else + { + if (!previewp->mAnimPreview) + { + return FALSE; + } + avatarp = previewp->mAnimPreview->getDummyAvatar(); + } + LLKeyframeMotion* motionp = (LLKeyframeMotion*)avatarp->findMotion(previewp->mMotionID); + + if (!motionp->getLoop()) + { + F32 new_ease_in = llclamp((F32)previewp->childGetValue("ease_in_time").asReal(), 0.f, motionp->getDuration() - motionp->getEaseOutDuration()); + previewp->childSetValue("ease_in_time", LLSD(new_ease_in)); + } + + return TRUE; +} + +//----------------------------------------------------------------------------- +// validateEaseOut() +//----------------------------------------------------------------------------- +BOOL LLFloaterBvhPreview::validateEaseOut(LLUICtrl* spin, void* data) +{ + LLFloaterBvhPreview* previewp = (LLFloaterBvhPreview*)data; + + if (!previewp->getEnabled()) + return FALSE; + + LLVOAvatar* avatarp; + if (previewp->mInWorld) + { + if (!gAgentAvatarp) + { + return FALSE; + } + avatarp = gAgentAvatarp; + } + else + { + if (!previewp->mAnimPreview) + { + return FALSE; + } + avatarp = previewp->mAnimPreview->getDummyAvatar(); + } + LLKeyframeMotion* motionp = (LLKeyframeMotion*)avatarp->findMotion(previewp->mMotionID); + + if (!motionp->getLoop()) + { + F32 new_ease_out = llclamp((F32)previewp->childGetValue("ease_out_time").asReal(), 0.f, motionp->getDuration() - motionp->getEaseInDuration()); + previewp->childSetValue("ease_out_time", LLSD(new_ease_out)); + } + + return TRUE; +} + +//----------------------------------------------------------------------------- +// validateLoopIn() +//----------------------------------------------------------------------------- +BOOL LLFloaterBvhPreview::validateLoopIn(LLUICtrl* ctrl, void* data) +{ + LLFloaterBvhPreview* previewp = (LLFloaterBvhPreview*)data; + if (!previewp->getEnabled()) + return FALSE; + + F32 loop_in_value = (F32)previewp->childGetValue("loop_in_point").asReal(); + F32 loop_out_value = (F32)previewp->childGetValue("loop_out_point").asReal(); + + if (loop_in_value < 0.f) + { + loop_in_value = 0.f; + } + else if (loop_in_value > 100.f) + { + loop_in_value = 100.f; + } + else if (loop_in_value > loop_out_value) + { + loop_in_value = loop_out_value; + } + + previewp->childSetValue("loop_in_point", LLSD(loop_in_value)); + return TRUE; +} + +//----------------------------------------------------------------------------- +// validateLoopOut() +//----------------------------------------------------------------------------- +BOOL LLFloaterBvhPreview::validateLoopOut(LLUICtrl* spin, void* data) +{ + LLFloaterBvhPreview* previewp = (LLFloaterBvhPreview*)data; + if (!previewp->getEnabled()) + return FALSE; + + F32 loop_out_value = (F32)previewp->childGetValue("loop_out_point").asReal(); + F32 loop_in_value = (F32)previewp->childGetValue("loop_in_point").asReal(); + + if (loop_out_value < 0.f) + { + loop_out_value = 0.f; + } + else if (loop_out_value > 100.f) + { + loop_out_value = 100.f; + } + else if (loop_out_value < loop_in_value) + { + loop_out_value = loop_in_value; + } + + previewp->childSetValue("loop_out_point", LLSD(loop_out_value)); + return TRUE; +} + + +//----------------------------------------------------------------------------- +// refresh() +//----------------------------------------------------------------------------- +void LLFloaterBvhPreview::refresh() +{ + if (!mAnimPreview) + { + childShow("bad_animation_text"); + mPlayButton->setEnabled(FALSE); + mStopButton->setEnabled(FALSE); + childDisable("ok_btn"); + } + else + { + if (!mInWorld) + { + childHide("bad_animation_text"); + } + mPlayButton->setEnabled(TRUE); + LLVOAvatar* avatarp; + if (mInWorld) + { + avatarp = gAgentAvatarp; + } + else + { + avatarp = mAnimPreview->getDummyAvatar(); + } + if (avatarp->isMotionActive(mMotionID)) + { + mStopButton->setEnabled(TRUE); + LLKeyframeMotion* motionp = (LLKeyframeMotion*)avatarp->findMotion(mMotionID); + if (avatarp->areAnimationsPaused()) + { + + mPlayButton->setImages(std::string("button_anim_play.tga"), + std::string("button_anim_play_selected.tga")); + + } + else + { + if (motionp) + { + F32 fraction_complete = motionp->getLastUpdateTime() / motionp->getDuration(); + childSetValue("playback_slider", fraction_complete); + } + mPlayButton->setImages(std::string("button_anim_pause.tga"), + std::string("button_anim_pause_selected.tga")); + + } + } + else + { + mPauseRequest = avatarp->requestPause(); + mPlayButton->setImages(std::string("button_anim_play.tga"), + std::string("button_anim_play_selected.tga")); + + mStopButton->setEnabled(TRUE); // stop also resets, leave enabled. + } + childEnable("ok_btn"); + if (!mInWorld) + { + mAnimPreview->requestUpdate(); + } + } +} + +//----------------------------------------------------------------------------- +// onBtnOK() +//----------------------------------------------------------------------------- +void LLFloaterBvhPreview::onBtnOK(void* userdata) +{ + LLFloaterBvhPreview* floaterp = (LLFloaterBvhPreview*)userdata; + if (!floaterp->getEnabled()) return; + + if ((!floaterp->mInWorld && floaterp->mAnimPreview) || (floaterp->mInWorld && gAgentAvatarp)) + { + LLKeyframeMotion* motionp; + if (floaterp->mInWorld) + { + motionp = (LLKeyframeMotion*)gAgentAvatarp->findMotion(floaterp->mMotionID); + } + else + { + motionp = (LLKeyframeMotion*)floaterp->mAnimPreview->getDummyAvatar()->findMotion(floaterp->mMotionID); + } + + S32 file_size = motionp->getFileSize(); + U8* buffer = new U8[file_size]; + + LLDataPackerBinaryBuffer dp(buffer, file_size); + if (motionp->serialize(dp)) + { + LLVFile file(gVFS, motionp->getID(), LLAssetType::AT_ANIMATION, LLVFile::APPEND); + + S32 size = dp.getCurrentSize(); + file.setMaxSize(size); + if (file.write((U8*)buffer, size)) + { + std::string name = floaterp->childGetValue("name_form").asString(); + std::string desc = floaterp->childGetValue("description_form").asString(); + LLAssetStorage::LLStoreAssetCallback callback = NULL; + S32 expected_upload_cost = sUploadAmount; + void *userdata = NULL; + + // + if(floaterp->mItem) + { + // Update existing item instead of creating a new one + LLViewerInventoryItem* item = (LLViewerInventoryItem*)floaterp->mItem; + LLSaveInfo* info = new LLSaveInfo(item->getUUID(), LLUUID::null, desc, floaterp->mTransactionID); + gAssetStorage->storeAssetData(floaterp->mTransactionID, LLAssetType::AT_ANIMATION, NULL, info, FALSE); + + // I guess I will do this now because the floater is closing... + LLPointer new_item = new LLViewerInventoryItem(item); + new_item->setDescription(desc); + new_item->setTransactionID(floaterp->mTransactionID); + new_item->setAssetUUID(motionp->getID()); + new_item->updateServer(FALSE); + gInventory.updateItem(new_item); + gInventory.notifyObservers(); + } + else + // + { + upload_new_resource(floaterp->mTransactionID, // tid + LLAssetType::AT_ANIMATION, + name, + desc, + 0, + LLFolderType::FT_NONE, + LLInventoryType::IT_ANIMATION, + LLFloaterPerms::getNextOwnerPerms(), LLFloaterPerms::getGroupPerms(), LLFloaterPerms::getEveryonePerms(), + name, + callback, expected_upload_cost, userdata); + } + } + else + { + llwarns << "Failure writing animation data." << llendl; + LLNotificationsUtil::add("WriteAnimationFail"); + } + } + + delete [] buffer; + // clear out cache for motion data + if (floaterp->mInWorld) + { + gAgentAvatarp->removeMotion(floaterp->mMotionID); + gAgentAvatarp->deactivateAllMotions(); + } + else + { + floaterp->mAnimPreview->getDummyAvatar()->removeMotion(floaterp->mMotionID); + } + LLKeyframeDataCache::removeKeyframeData(floaterp->mMotionID); + } + + floaterp->close(false); +} + +//----------------------------------------------------------------------------- +// LLPreviewAnimation +//----------------------------------------------------------------------------- +LLPreviewAnimation::LLPreviewAnimation(S32 width, S32 height) : LLViewerDynamicTexture(width, height, 3, ORDER_MIDDLE, FALSE) +{ + mNeedsUpdate = TRUE; + mCameraDistance = PREVIEW_CAMERA_DISTANCE; + mCameraYaw = 0.f; + mCameraPitch = 0.f; + mCameraZoom = 1.f; + + mDummyAvatar = (LLVOAvatar*)gObjectList.createObjectViewer(LL_PCODE_LEGACY_AVATAR, gAgent.getRegion()); + mDummyAvatar->createDrawable(&gPipeline); + mDummyAvatar->mIsDummy = TRUE; + mDummyAvatar->mSpecialRenderMode = 1; + mDummyAvatar->setPositionAgent(LLVector3::zero); + mDummyAvatar->slamPosition(); + mDummyAvatar->updateJointLODs(); + mDummyAvatar->updateGeometry(mDummyAvatar->mDrawable); + mDummyAvatar->startMotion(ANIM_AGENT_STAND, BASE_ANIM_TIME_OFFSET); + mDummyAvatar->hideSkirt(); + //gPipeline.markVisible(mDummyAvatar->mDrawable, *LLViewerCamera::getInstance()); + + // stop extraneous animations + mDummyAvatar->stopMotion( ANIM_AGENT_HEAD_ROT, TRUE ); + mDummyAvatar->stopMotion( ANIM_AGENT_EYE, TRUE ); + mDummyAvatar->stopMotion( ANIM_AGENT_BODY_NOISE, TRUE ); + mDummyAvatar->stopMotion( ANIM_AGENT_BREATHE_ROT, TRUE ); +} + +//----------------------------------------------------------------------------- +// LLPreviewAnimation() +//----------------------------------------------------------------------------- +LLPreviewAnimation::~LLPreviewAnimation() +{ + mDummyAvatar->markDead(); +} + +//virtual +S8 LLPreviewAnimation::getType() const +{ + return LLViewerDynamicTexture::LL_PREVIEW_ANIMATION ; +} + +//----------------------------------------------------------------------------- +// update() +//----------------------------------------------------------------------------- +BOOL LLPreviewAnimation::render() +{ + mNeedsUpdate = FALSE; + LLVOAvatar* avatarp = mDummyAvatar; + + gGL.matrixMode(LLRender::MM_PROJECTION); + gGL.pushMatrix(); + gGL.loadIdentity(); + gGL.ortho(0.0f, mFullWidth, 0.0f, mFullHeight, -1.0f, 1.0f); + + gGL.matrixMode(LLRender::MM_MODELVIEW); + gGL.pushMatrix(); + gGL.loadIdentity(); + + if (LLGLSLShader::sNoFixedFunction) + { + gUIProgram.bind(); + } + + LLGLSUIDefault def; + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + gGL.color4f(0.15f, 0.2f, 0.3f, 1.f); + + gl_rect_2d_simple( mFullWidth, mFullHeight ); + + gGL.matrixMode(LLRender::MM_PROJECTION); + gGL.popMatrix(); + + gGL.matrixMode(LLRender::MM_MODELVIEW); + gGL.popMatrix(); + + gGL.flush(); + + LLVector3 target_pos = avatarp->mRoot->getWorldPosition(); + + LLQuaternion camera_rot = LLQuaternion(mCameraPitch, LLVector3::y_axis) * + LLQuaternion(mCameraYaw, LLVector3::z_axis); + + LLQuaternion av_rot = avatarp->mRoot->getWorldRotation() * camera_rot; + LLViewerCamera::getInstance()->setOriginAndLookAt( + target_pos + ((LLVector3(mCameraDistance, 0.f, 0.f) + mCameraOffset) * av_rot), // camera + LLVector3::z_axis, // up + target_pos + (mCameraOffset * av_rot) ); // point of interest + + LLViewerCamera::getInstance()->setView(LLViewerCamera::getInstance()->getDefaultFOV() / mCameraZoom); + LLViewerCamera::getInstance()->setPerspective(FALSE, mOrigin.mX, mOrigin.mY, mFullWidth, mFullHeight, FALSE); + + mCameraRelPos = LLViewerCamera::getInstance()->getOrigin() - avatarp->mHeadp->getWorldPosition(); + + //avatarp->setAnimationData("LookAtPoint", (void *)&mCameraRelPos); + + //SJB: Animation is updated in LLVOAvatar::updateCharacter + + if (avatarp->mDrawable.notNull()) + { + avatarp->updateLOD(); + + LLVertexBuffer::unbind(); + LLGLDepthTest gls_depth(GL_TRUE); + + LLDrawPoolAvatar *avatarPoolp = (LLDrawPoolAvatar *)avatarp->mDrawable->getFace(0)->getPool(); + avatarp->dirtyMesh(); + avatarPoolp->renderAvatars(avatarp); // renders only one avatar + } + + gGL.color4f(1,1,1,1); + return TRUE; +} + +//----------------------------------------------------------------------------- +// requestUpdate() +//----------------------------------------------------------------------------- +void LLPreviewAnimation::requestUpdate() +{ + mNeedsUpdate = TRUE; +} + +//----------------------------------------------------------------------------- +// rotate() +//----------------------------------------------------------------------------- +void LLPreviewAnimation::rotate(F32 yaw_radians, F32 pitch_radians) +{ + mCameraYaw = mCameraYaw + yaw_radians; + + mCameraPitch = llclamp(mCameraPitch + pitch_radians, F_PI_BY_TWO * -0.8f, F_PI_BY_TWO * 0.8f); +} + +//----------------------------------------------------------------------------- +// zoom() +//----------------------------------------------------------------------------- +void LLPreviewAnimation::zoom(F32 zoom_delta) +{ + setZoom(mCameraZoom + zoom_delta); +} + +//----------------------------------------------------------------------------- +// setZoom() +//----------------------------------------------------------------------------- +void LLPreviewAnimation::setZoom(F32 zoom_amt) +{ + mCameraZoom = llclamp(zoom_amt, MIN_CAMERA_ZOOM, MAX_CAMERA_ZOOM); +} + +//----------------------------------------------------------------------------- +// pan() +//----------------------------------------------------------------------------- +void LLPreviewAnimation::pan(F32 right, F32 up) +{ + mCameraOffset.mV[VY] = llclamp(mCameraOffset.mV[VY] + right * mCameraDistance / mCameraZoom, -1.f, 1.f); + mCameraOffset.mV[VZ] = llclamp(mCameraOffset.mV[VZ] + up * mCameraDistance / mCameraZoom, -1.f, 1.f); +} + + + diff --git a/indra/newview/llfloaterbvhpreview.h b/indra/newview/llfloaterbvhpreview.h new file mode 100644 index 000000000..78b9db6a0 --- /dev/null +++ b/indra/newview/llfloaterbvhpreview.h @@ -0,0 +1,145 @@ +/** + * @file llfloaterbvhpreview.h + * @brief LLFloaterBvhPreview class definition + * + * $LicenseInfo:firstyear=2004&license=viewergpl$ + * + * Copyright (c) 2004-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_LLFLOATERBVHPREVIEW_H +#define LL_LLFLOATERBVHPREVIEW_H + +#include "llfloaternamedesc.h" +#include "lldynamictexture.h" +#include "llcharacter.h" +#include "llquaternion.h" + +class LLVOAvatar; +class LLViewerJointMesh; + +class LLPreviewAnimation : public LLViewerDynamicTexture +{ +protected: + virtual ~LLPreviewAnimation(); + +public: + LLPreviewAnimation(S32 width, S32 height); + + /*virtual*/ S8 getType() const ; + + BOOL render(); + void requestUpdate(); + void rotate(F32 yaw_radians, F32 pitch_radians); + void zoom(F32 zoom_delta); + void setZoom(F32 zoom_amt); + void pan(F32 right, F32 up); + virtual BOOL needsUpdate() { return mNeedsUpdate; } + + LLVOAvatar* getDummyAvatar() { return mDummyAvatar; } + +protected: + BOOL mNeedsUpdate; + F32 mCameraDistance; + F32 mCameraYaw; + F32 mCameraPitch; + F32 mCameraZoom; + LLVector3 mCameraOffset; + LLVector3 mCameraRelPos; + LLPointer mDummyAvatar; +}; + +class LLFloaterBvhPreview : public LLFloaterNameDesc +{ +public: + // + LLFloaterBvhPreview(const std::string& filename, void* item = NULL); + // + virtual ~LLFloaterBvhPreview(); + + BOOL postBuild(); + + BOOL handleMouseDown(S32 x, S32 y, MASK mask); + BOOL handleMouseUp(S32 x, S32 y, MASK mask); + BOOL handleHover(S32 x, S32 y, MASK mask); + BOOL handleScrollWheel(S32 x, S32 y, S32 clicks); + void onMouseCaptureLost(); + + void refresh(); + + void onBtnPlay(); + void onBtnStop(); + static void setUploadAmount(S32 amount) { sUploadAmount = amount; } + static void onSliderMove(LLUICtrl*, void*); + static void onCommitBaseAnim(LLUICtrl*, void*); + static void onCommitLoop(LLUICtrl*, void*); + static void onCommitLoopIn(LLUICtrl*, void*); + static void onCommitLoopOut(LLUICtrl*, void*); + static BOOL validateLoopIn(LLUICtrl*, void*); + static BOOL validateLoopOut(LLUICtrl*, void*); + static void onCommitName(LLUICtrl*, void*); + static void onCommitHandPose(LLUICtrl*, void*); + static void onCommitEmote(LLUICtrl*, void*); + static void onCommitPriority(LLUICtrl*, void*); + static void onCommitEaseIn(LLUICtrl*, void*); + static void onCommitEaseOut(LLUICtrl*, void*); + static BOOL validateEaseIn(LLUICtrl*, void*); + static BOOL validateEaseOut(LLUICtrl*, void*); + static void onBtnOK(void*); + static void onSaveComplete(const LLUUID& asset_uuid, + LLAssetType::EType type, + void* user_data, + S32 status, LLExtStat ext_status); +private: + void setAnimCallbacks() ; + +protected: + void draw(); + void resetMotion(); + + LLPointer< LLPreviewAnimation> mAnimPreview; + S32 mLastMouseX; + S32 mLastMouseY; + LLButton* mPlayButton; + LLButton* mStopButton; + LLRect mPreviewRect; + LLRectf mPreviewImageRect; + LLAssetID mMotionID; + LLTransactionID mTransactionID; + BOOL mEnabled; + BOOL mInWorld; + LLAnimPauseRequest mPauseRequest; + + std::map mIDList; + + static S32 sUploadAmount; + + // + void* mItem; + // +}; + +#endif // LL_LLFLOATERBVHPREVIEW_H diff --git a/indra/newview/llfloaterchat.cpp b/indra/newview/llfloaterchat.cpp index 7e1cfcd73..01ed3f0c1 100644 --- a/indra/newview/llfloaterchat.cpp +++ b/indra/newview/llfloaterchat.cpp @@ -179,13 +179,26 @@ void LLFloaterChat::handleVisibilityChange(BOOL new_visibility) if (new_visibility) { LLFloaterChatterBox::getInstance()->setFloaterFlashing(this, FALSE); - // Work around the chat bar no longer focusing from within the layout_stack - gFocusMgr.setKeyboardFocus(getChildView("Chat Editor")); } LLFloater::handleVisibilityChange(new_visibility); } +// virtual +void LLFloaterChat::onFocusReceived() +{ + LLView* chat_editor = getChildView("Chat Editor"); + if (getVisible() && childIsVisible("Chat Editor")) + { + gFocusMgr.setKeyboardFocus(chat_editor); + + LLUICtrl * ctrl = static_cast(chat_editor); + ctrl->setFocus(TRUE); + } + + LLFloater::onFocusReceived(); +} + void LLFloaterChat::setMinimized(BOOL minimized) { LLFloater::setMinimized(minimized); @@ -735,3 +748,20 @@ void LLFloaterChat::hide(LLFloater* instance, const LLSD& key) VisibilityPolicy::hide(instance, key); } } + +BOOL LLFloaterChat::focusFirstItem(BOOL prefer_text_fields, BOOL focus_flash ) +{ + LLView* chat_editor = getChildView("Chat Editor"); + if (getVisible() && childIsVisible("Chat Editor")) + { + gFocusMgr.setKeyboardFocus(chat_editor); + + LLUICtrl * ctrl = static_cast(chat_editor); + ctrl->setFocus(TRUE); + + return TRUE; + } + + return LLUICtrl::focusFirstItem(prefer_text_fields, focus_flash); +} + diff --git a/indra/newview/llfloaterchat.h b/indra/newview/llfloaterchat.h index a3ef23fd0..3c7cbc4c5 100644 --- a/indra/newview/llfloaterchat.h +++ b/indra/newview/llfloaterchat.h @@ -63,6 +63,7 @@ public: virtual void draw(); virtual BOOL postBuild(); virtual void onClose(bool app_quitting); + virtual void onFocusReceived(); virtual void handleVisibilityChange(BOOL cur_visibility); virtual void setMinimized(BOOL); void updateConsoleVisibility(); @@ -97,6 +98,8 @@ public: LLPanelActiveSpeakers* mPanel; BOOL mScrolledToEnd; + BOOL focusFirstItem(BOOL prefer_text_fields = FALSE, BOOL focus_flash = TRUE ); + CachedUICtrl mToggleActiveSpeakersBtn; CachedUICtrl mChatPanel; }; diff --git a/indra/newview/llfloaterexploreanimations.cpp b/indra/newview/llfloaterexploreanimations.cpp index 9a973c8c8..6267b31c5 100644 --- a/indra/newview/llfloaterexploreanimations.cpp +++ b/indra/newview/llfloaterexploreanimations.cpp @@ -4,7 +4,7 @@ #include "llfloaterexploreanimations.h" #include "lluictrlfactory.h" #include "llscrolllistctrl.h" -#include "llfloateranimpreview.h" +#include "llfloaterbvhpreview.h" #include "llvoavatar.h" #include "lllocalinventory.h" #include "llviewercamera.h" diff --git a/indra/newview/llfloaterexploreanimations.h b/indra/newview/llfloaterexploreanimations.h index 27c4af3c1..383b16e6d 100644 --- a/indra/newview/llfloaterexploreanimations.h +++ b/indra/newview/llfloaterexploreanimations.h @@ -3,7 +3,7 @@ #define LL_LLFLOATEREXPLOREANIMATIONS_H #include "llfloater.h" -#include "llfloateranimpreview.h" +#include "llfloaterbvhpreview.h" #include "llviewerwindow.h" // gViewerWindow class LLAnimHistoryItem diff --git a/indra/newview/llfloaterexploresounds.cpp b/indra/newview/llfloaterexploresounds.cpp index 4ce0cf111..0e3934e2f 100644 --- a/indra/newview/llfloaterexploresounds.cpp +++ b/indra/newview/llfloaterexploresounds.cpp @@ -68,6 +68,13 @@ void LLFloaterExploreSounds::toggle() else LLFloaterExploreSounds::sInstance = new LLFloaterExploreSounds(); } +BOOL LLFloaterExploreSounds::visible() +{ + if (LLFloaterExploreSounds::sInstance) + return TRUE; + return FALSE; +} + void LLFloaterExploreSounds::close(bool app_quitting) { LLFloater::close(app_quitting); diff --git a/indra/newview/llfloaterexploresounds.h b/indra/newview/llfloaterexploresounds.h index 4bdcae820..7bb7ae1c5 100644 --- a/indra/newview/llfloaterexploresounds.h +++ b/indra/newview/llfloaterexploresounds.h @@ -36,6 +36,7 @@ public: static LLFloaterExploreSounds* sInstance; static void toggle(); + static BOOL visible(); }; #endif diff --git a/indra/newview/llfloateroutbox.cpp b/indra/newview/llfloateroutbox.cpp index 33208767f..07b626de9 100644 --- a/indra/newview/llfloateroutbox.cpp +++ b/indra/newview/llfloateroutbox.cpp @@ -86,7 +86,7 @@ public: if (added_category_type == LLFolderType::FT_OUTBOX) { - mOutboxFloater->setupOutbox(added_category->getUUID()); + mOutboxFloater->initializeMarketPlace(); } } } @@ -152,13 +152,17 @@ BOOL LLFloaterOutbox::postBuild() // // Set up the outbox inventory view // - mOutboxInventoryPanel = getChild("panel_outbox_inventory"); + llassert(mOutboxInventoryPanel); mOutboxTopLevelDropZone = getChild("outbox_generic_drag_target"); LLFocusableElement::setFocusReceivedCallback(boost::bind(&LLFloaterOutbox::onFocusReceived, this)); + // Observe category creation to catch outbox creation (moot if already existing) + mCategoryAddedObserver = new LLOutboxAddedObserver(this); + gInventory.addObserver(mCategoryAddedObserver); + return TRUE; } @@ -179,34 +183,26 @@ void LLFloaterOutbox::onClose(bool app_quitting) void LLFloaterOutbox::onOpen() { // - // Look for an outbox and set up the inventory API + // Initialize the Market Place or go update the outbox // - if (mOutboxId.isNull()) + if (LLMarketplaceInventoryImporter::getInstance()->getMarketPlaceStatus() == MarketplaceStatusCodes::MARKET_PLACE_NOT_INITIALIZED) { - const bool do_not_create_folder = false; - const bool do_not_find_in_library = false; - - const LLUUID outbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, do_not_create_folder, do_not_find_in_library); - - if (outbox_id.isNull()) - { - // Observe category creation to catch outbox creation - mCategoryAddedObserver = new LLOutboxAddedObserver(this); - gInventory.addObserver(mCategoryAddedObserver); - } - else - { - setupOutbox(outbox_id); - } + initializeMarketPlace(); + } + else + { + setupOutbox(); } + // + // Update the floater view + // updateView(); // // Trigger fetch of outbox contents // - fetchOutboxContents(); } @@ -223,13 +219,22 @@ void LLFloaterOutbox::fetchOutboxContents() } } -void LLFloaterOutbox::setupOutbox(const LLUUID& outboxId) +void LLFloaterOutbox::setupOutbox() { - llassert(outboxId.notNull()); - llassert(mOutboxId.isNull()); - llassert(mCategoriesObserver == NULL); + if (LLMarketplaceInventoryImporter::getInstance()->getMarketPlaceStatus() != MarketplaceStatusCodes::MARKET_PLACE_MERCHANT) + { + // If we are *not* a merchant or we have no market place connection established yet, do nothing + return; + } - mOutboxId = outboxId; + // We are a merchant. Get the outbox, create it if needs be. + mOutboxId = gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, true, false); + if (mOutboxId.isNull()) + { + // We should never get there unles inventory fails badly + llerrs << "Inventory problem: failure to create the outbox for a merchant!" << llendl; + return; + } // No longer need to observe new category creation if (mCategoryAddedObserver && gInventory.containsObserver(mCategoryAddedObserver)) @@ -238,14 +243,19 @@ void LLFloaterOutbox::setupOutbox(const LLUUID& outboxId) delete mCategoryAddedObserver; mCategoryAddedObserver = NULL; } + llassert(!mCategoryAddedObserver); // Create observer for outbox modifications - mCategoriesObserver = new LLInventoryCategoriesObserver(); - gInventory.addObserver(mCategoriesObserver); + if (mCategoriesObserver == NULL) + { + mCategoriesObserver = new LLInventoryCategoriesObserver(); + gInventory.addObserver(mCategoriesObserver); + mCategoriesObserver->addCategory(mOutboxId, boost::bind(&LLFloaterOutbox::onOutboxChanged, this)); + } + llassert(mCategoriesObserver); - mCategoriesObserver->addCategory(mOutboxId, boost::bind(&LLFloaterOutbox::onOutboxChanged, this)); - - llassert(mOutboxInventoryPanel); + // Set up the outbox inventory view + // Singu Note: we handle this in postBuild, grabbing the panel from the built xml. // Reshape the inventory to the proper size LLRect inventory_placeholder_rect = mInventoryPlaceholder->getRect(); @@ -255,8 +265,12 @@ void LLFloaterOutbox::setupOutbox(const LLUUID& outboxId) mOutboxInventoryPanel->setSortOrder(LLInventoryFilter::SO_FOLDERS_BY_NAME); mOutboxInventoryPanel->getFilter()->markDefault(); + // Get the content of the outbox fetchOutboxContents(); +} +void LLFloaterOutbox::initializeMarketPlace() +{ // // Initialize the marketplace import API // @@ -330,6 +344,7 @@ void LLFloaterOutbox::updateView() { mOutboxInventoryPanel->setVisible(TRUE); mInventoryPlaceholder->setVisible(FALSE); + mOutboxTopLevelDropZone->setVisible(TRUE); } else { @@ -338,13 +353,18 @@ void LLFloaterOutbox::updateView() mOutboxInventoryPanel->setVisible(FALSE); } + // Show the drop zone if there is an outbox folder + mOutboxTopLevelDropZone->setVisible(mOutboxId.notNull()); + mInventoryPlaceholder->setVisible(TRUE); std::string outbox_text; + std::string outbox_text2; std::string outbox_title; std::string outbox_tooltip; const LLSD& subs = getMarketplaceStringSubstitutions(); + U32 mkt_status = LLMarketplaceInventoryImporter::getInstance()->getMarketPlaceStatus(); // Text styles for marketplace hyperlinks std::string subs_link; @@ -352,28 +372,54 @@ void LLFloaterOutbox::updateView() if (mOutboxId.notNull()) { + // "Outbox is empty!" message strings outbox_text = LLTrans::getString("InventoryOutboxNoItems"); subs_link = "[MARKETPLACE_DASHBOARD_URL]"; subs_text = " " + LLTrans::getString("InventoryOutboxNoItemsSubs"); + outbox_text2 = LLTrans::getString("InventoryOutboxNoItems2"); outbox_title = LLTrans::getString("InventoryOutboxNoItemsTitle"); outbox_tooltip = LLTrans::getString("InventoryOutboxNoItemsTooltip"); } - else + else if (mkt_status <= MarketplaceStatusCodes::MARKET_PLACE_INITIALIZING) { + // "Initializing!" message strings + outbox_text = LLTrans::getString("InventoryOutboxInitializing"); + subs_link = "[MARKETPLACE_CREATE_STORE_URL]"; + subs_text = " " + LLTrans::getString("InventoryOutboxInitializingSubs"); + outbox_text2 = LLTrans::getString("InventoryOutboxInitializing2"); + outbox_title = LLTrans::getString("InventoryOutboxInitializingTitle"); + outbox_tooltip = LLTrans::getString("InventoryOutboxInitializingTooltip"); + } + else if (mkt_status == MarketplaceStatusCodes::MARKET_PLACE_NOT_MERCHANT) + { + // "Not a merchant!" message strings outbox_text = LLTrans::getString("InventoryOutboxNotMerchant"); subs_link = "[MARKETPLACE_CREATE_STORE_URL]"; subs_text = " " + LLTrans::getString("InventoryOutboxNotMerchantSubs"); + outbox_text2 = LLTrans::getString("InventoryOutboxNotMerchant2"); outbox_title = LLTrans::getString("InventoryOutboxNotMerchantTitle"); outbox_tooltip = LLTrans::getString("InventoryOutboxNotMerchantTooltip"); } + else + { + // "Errors!" message strings + outbox_text = LLTrans::getString("InventoryOutboxError"); + subs_link = "[MARKETPLACE_CREATE_STORE_URL]"; + subs_text = " " + LLTrans::getString("InventoryOutboxErrorSubs"); + outbox_text2 = " " + LLTrans::getString("InventoryOutboxError2"); + outbox_title = LLTrans::getString("InventoryOutboxErrorTitle"); + outbox_tooltip = LLTrans::getString("InventoryOutboxErrorTooltip"); + } mInventoryText->clear(); - mInventoryText->appendColoredText(outbox_text, false, false, gColors.getColor("TextFgReadOnlyColor")); + const LLColor4 color = gColors.getColor("TextFgReadOnlyColor"); + mInventoryText->appendColoredText(outbox_text, false, false, color); LLStringUtil::format(subs_link, subs); LLStyleSP subs_link_style(new LLStyle); subs_link_style->setLinkHREF(subs_link); subs_link_style->setColor(gSavedSettings.getColor4("HTMLLinkColor")); mInventoryText->appendStyledText(subs_text, false, false, subs_link_style); + mInventoryText->appendColoredText(outbox_text2, false, false, color); mInventoryTitle->setValue(outbox_title); mInventoryPlaceholder->getParent()->setToolTip(outbox_tooltip); } @@ -498,6 +544,11 @@ void LLFloaterOutbox::importReportResults(U32 status, const LLSD& content) void LLFloaterOutbox::importStatusChanged(bool inProgress) { + if (mOutboxId.isNull() && (LLMarketplaceInventoryImporter::getInstance()->getMarketPlaceStatus() == MarketplaceStatusCodes::MARKET_PLACE_MERCHANT)) + { + setupOutbox(); + } + if (inProgress) { if (mImportBusy) @@ -515,6 +566,7 @@ void LLFloaterOutbox::importStatusChanged(bool inProgress) } else { + setStatusString(""); mImportBusy = false; mImportButton->setEnabled(mOutboxItemCount > 0); mInventoryImportInProgress->setVisible(false); @@ -525,7 +577,7 @@ void LLFloaterOutbox::importStatusChanged(bool inProgress) void LLFloaterOutbox::initializationReportError(U32 status, const LLSD& content) { - if (status != MarketplaceErrorCodes::IMPORT_DONE) + if (status >= MarketplaceErrorCodes::IMPORT_BAD_REQUEST) { char status_string[16]; sprintf(status_string, "%d", status); diff --git a/indra/newview/llfloateroutbox.h b/indra/newview/llfloateroutbox.h index 92f301416..9f9222cb6 100644 --- a/indra/newview/llfloateroutbox.h +++ b/indra/newview/llfloateroutbox.h @@ -55,7 +55,7 @@ public: LLFloaterOutbox(const LLSD& key); ~LLFloaterOutbox(); - void setupOutbox(const LLUUID& outboxId); + void initializeMarketPlace(); // virtuals BOOL postBuild(); @@ -71,6 +71,7 @@ public: // void onMouseLeave(S32 x, S32 y, MASK mask); protected: + void setupOutbox(); void fetchOutboxContents(); void importReportResults(U32 status, const LLSD& content); diff --git a/indra/newview/llfloaterperms.cpp b/indra/newview/llfloaterperms.cpp index 15c13be54..a85abb1a6 100644 --- a/indra/newview/llfloaterperms.cpp +++ b/indra/newview/llfloaterperms.cpp @@ -32,6 +32,7 @@ */ #include "llviewerprecompiledheaders.h" +#include "lfsimfeaturehandler.h" #include "llcheckboxctrl.h" #include "llfloaterperms.h" #include "llnotificationsutil.h" @@ -39,7 +40,35 @@ #include "llviewerwindow.h" #include "lluictrlfactory.h" #include "llpermissions.h" +#include "hippogridmanager.h" +namespace +{ + bool everyone_export; + void handle_checkboxes(LLUICtrl* ctrl, const LLSD& value) + { + LLPanel* view = static_cast(ctrl->getParent()); + if (ctrl->getName() == "everyone_export") + { + view->childSetEnabled("next_owner_copy", !value); + view->childSetEnabled("next_owner_modify", !value); + view->childSetEnabled("next_owner_transfer", !value); + } + else + { + if (ctrl->getName() == "next_owner_copy") + { + if (!value) // Implements fair use + gSavedSettings.setBOOL("NextOwnerTransfer", true); + view->childSetEnabled("next_owner_transfer", value); + } + if (!value) // If any of these are unchecked, export can no longer be checked. + view->childSetEnabled("everyone_export", false); + else + view->childSetEnabled("everyone_export", LFSimFeatureHandler::instance().simSupportsExport() && (LLFloaterPerms::getNextOwnerPerms() & PERM_ITEM_UNRESTRICTED) == PERM_ITEM_UNRESTRICTED); + } + } +} LLFloaterPerms::LLFloaterPerms(const LLSD& seed) { @@ -48,11 +77,35 @@ LLFloaterPerms::LLFloaterPerms(const LLSD& seed) BOOL LLFloaterPerms::postBuild() { - childSetEnabled("next_owner_transfer", gSavedSettings.getBOOL("NextOwnerCopy")); + //handle_checkboxes + { + bool export_support = LFSimFeatureHandler::instance().simSupportsExport(); + const U32 next_owner_perms = getNextOwnerPerms(); + childSetEnabled("everyone_export", export_support && (next_owner_perms & PERM_ITEM_UNRESTRICTED) == PERM_ITEM_UNRESTRICTED); + if (!gHippoGridManager->getCurrentGrid()->isSecondLife()) + childSetVisible("everyone_export", false); + + if (!(next_owner_perms & PERM_COPY)) + { + childSetEnabled("next_owner_transfer", false); + } + else if (export_support) + { + bool export_off = !gSavedPerAccountSettings.getBOOL("EveryoneExport"); + childSetEnabled("next_owner_copy", export_off); + childSetEnabled("next_owner_modify", export_off); + childSetEnabled("next_owner_transfer", export_off); + } + else // Set EveryoneExport false, just in case. + gSavedPerAccountSettings.setBOOL("EveryoneExport", false); + } childSetAction("help", onClickHelp, this); childSetAction("ok", onClickOK, this); childSetAction("cancel", onClickCancel, this); - childSetCommitCallback("next_owner_copy", &onCommitCopy, this); + getChild("next_owner_copy")->setCommitCallback(handle_checkboxes); + getChild("next_owner_modify")->setCommitCallback(handle_checkboxes); + getChild("next_owner_transfer")->setCommitCallback(handle_checkboxes); + getChild("everyone_export")->setCommitCallback(handle_checkboxes); refresh(); @@ -75,20 +128,6 @@ void LLFloaterPerms::onClickCancel(void* data) self->close(); } -//static -void LLFloaterPerms::onCommitCopy(LLUICtrl* ctrl, void* data) -{ - LLFloaterPerms* self = static_cast(data); - // Implements fair use - BOOL copyable = gSavedSettings.getBOOL("NextOwnerCopy"); - if(!copyable) - { - gSavedSettings.setBOOL("NextOwnerTransfer", TRUE); - } - LLCheckBoxCtrl* xfer = self->getChild("next_owner_transfer"); - xfer->setEnabled(copyable); -} - void LLFloaterPerms::ok() { refresh(); // Changes were already applied to saved settings. Refreshing internal values makes it official. @@ -101,6 +140,7 @@ void LLFloaterPerms::cancel() gSavedSettings.setBOOL("NextOwnerCopy", mNextOwnerCopy); gSavedSettings.setBOOL("NextOwnerModify", mNextOwnerModify); gSavedSettings.setBOOL("NextOwnerTransfer", mNextOwnerTransfer); + gSavedPerAccountSettings.setBOOL("EveryoneExport", everyone_export); } void LLFloaterPerms::refresh() @@ -110,6 +150,7 @@ void LLFloaterPerms::refresh() mNextOwnerCopy = gSavedSettings.getBOOL("NextOwnerCopy"); mNextOwnerModify = gSavedSettings.getBOOL("NextOwnerModify"); mNextOwnerTransfer = gSavedSettings.getBOOL("NextOwnerTransfer"); + everyone_export = gSavedPerAccountSettings.getBOOL("EveryoneExport"); } void LLFloaterPerms::onClose(bool app_quitting) @@ -129,7 +170,12 @@ U32 LLFloaterPerms::getGroupPerms(std::string prefix) //static U32 LLFloaterPerms::getEveryonePerms(std::string prefix) { - return gSavedSettings.getBOOL(prefix+"EveryoneCopy") ? PERM_COPY : PERM_NONE; + U32 flags = PERM_NONE; + if (LFSimFeatureHandler::instance().simSupportsExport() && prefix.empty() && gSavedPerAccountSettings.getBOOL("EveryoneExport")) // TODO: Bulk enable export? + flags |= PERM_EXPORT; + if (gSavedSettings.getBOOL(prefix+"EveryoneCopy")) + flags |= PERM_COPY; + return flags; } //static diff --git a/indra/newview/llfloaterperms.h b/indra/newview/llfloaterperms.h index 805039efe..9193b5983 100644 --- a/indra/newview/llfloaterperms.h +++ b/indra/newview/llfloaterperms.h @@ -47,7 +47,6 @@ public: void cancel(); static void onClickOK(void*); static void onClickCancel(void*); - static void onCommitCopy(LLUICtrl* ctrl, void* data); // Convenience methods to get current permission preference bitfields from saved settings: static U32 getEveryonePerms(std::string prefix=""); // prefix + "EveryoneCopy" static U32 getGroupPerms(std::string prefix=""); // prefix + "ShareWithGroup" diff --git a/indra/newview/llfloaterproperties.cpp b/indra/newview/llfloaterproperties.cpp index b54c0a126..84d8f0650 100644 --- a/indra/newview/llfloaterproperties.cpp +++ b/indra/newview/llfloaterproperties.cpp @@ -60,6 +60,7 @@ #include "lluictrlfactory.h" +#include "lfsimfeaturehandler.h" #include "hippogridmanager.h" @@ -67,6 +68,8 @@ #include "rlvhandler.h" // [/RLVa:KB] +bool can_set_export(const U32& base, const U32& own, const U32& next); + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Class LLPropertiesObserver // @@ -178,6 +181,9 @@ BOOL LLFloaterProperties::postBuild() // everyone permissions getChild("CheckEveryoneCopy")->setCommitCallback(boost::bind(&LLFloaterProperties::onCommitPermissions, this)); getChild("CheckEveryoneMove")->setCommitCallback(boost::bind(&LLFloaterProperties::onCommitPermissions, this)); + getChild("CheckExport")->setCommitCallback(boost::bind(&LLFloaterProperties::onCommitPermissions, this)); + if (!gHippoGridManager->getCurrentGrid()->isSecondLife()) + LFSimFeatureHandler::instance().setSupportsExportCallback(boost::bind(&LLFloaterProperties::refresh, this)); // next owner permissions getChild("CheckNextOwnerModify")->setCommitCallback(boost::bind(&LLFloaterProperties::onCommitPermissions, this)); getChild("CheckNextOwnerCopy")->setCommitCallback(boost::bind(&LLFloaterProperties::onCommitPermissions, this)); @@ -223,11 +229,13 @@ void LLFloaterProperties::refresh() "CheckOwnerModify", "CheckOwnerCopy", "CheckOwnerTransfer", + "CheckOwnerExport", "CheckGroupCopy", "CheckGroupMod", "CheckGroupMove", "CheckEveryoneCopy", "CheckEveryoneMove", + "CheckExport", "CheckNextOwnerModify", "CheckNextOwnerCopy", "CheckNextOwnerTransfer", @@ -411,6 +419,12 @@ void LLFloaterProperties::refreshFromItem(LLInventoryItem* item) getChildView("CheckOwnerTransfer")->setEnabled(FALSE); getChild("CheckOwnerTransfer")->setValue(LLSD((BOOL)(owner_mask & PERM_TRANSFER))); + bool supports_export = LFSimFeatureHandler::instance().simSupportsExport(); + getChildView("CheckOwnerExport")->setEnabled(false); + getChild("CheckOwnerExport")->setValue(LLSD((BOOL)(supports_export && owner_mask & PERM_EXPORT))); + if (!gHippoGridManager->getCurrentGrid()->isSecondLife()) + getChildView("CheckOwnerExport")->setVisible(false); + /////////////////////// // DEBUG PERMISSIONS // /////////////////////// @@ -433,11 +447,15 @@ void LLFloaterProperties::refreshFromItem(LLInventoryItem* item) perm_string = "B: "; perm_string += mask_to_string(base_mask); + if (!supports_export && base_mask & PERM_EXPORT) // Hide Export when not available + perm_string.erase(perm_string.find_last_of("E")); getChild("BaseMaskDebug")->setValue(perm_string); getChildView("BaseMaskDebug")->setVisible(TRUE); perm_string = "O: "; perm_string += mask_to_string(owner_mask); + if (!supports_export && owner_mask & PERM_EXPORT) // Hide Export when not available + perm_string.erase(perm_string.find_last_of("E")); getChild("OwnerMaskDebug")->setValue(perm_string); getChildView("OwnerMaskDebug")->setVisible(TRUE); @@ -450,9 +468,11 @@ void LLFloaterProperties::refreshFromItem(LLInventoryItem* item) perm_string = "E"; perm_string += overwrite_everyone ? "*: " : ": "; perm_string += mask_to_string(everyone_mask); + if (!supports_export && everyone_mask & PERM_EXPORT) // Hide Export when not available + perm_string.erase(perm_string.find_last_of("E")); getChild("EveryoneMaskDebug")->setValue(perm_string); getChildView("EveryoneMaskDebug")->setVisible(TRUE); - + perm_string = "N"; perm_string += slam_perm ? "*: " : ": "; perm_string += mask_to_string(next_owner_mask); @@ -493,6 +513,8 @@ void LLFloaterProperties::refreshFromItem(LLInventoryItem* item) getChild("CheckEveryoneCopy")->setEnabled(FALSE); getChild("CheckEveryoneMove")->setEnabled(FALSE); } + getChild("CheckExport")->setEnabled(supports_export && item->getType() != LLAssetType::AT_OBJECT && gAgentID == item->getCreatorUUID() + && can_set_export(base_mask, owner_mask, next_owner_mask)); // Set values. BOOL is_group_copy = (group_mask & PERM_COPY) ? TRUE : FALSE; @@ -505,6 +527,7 @@ void LLFloaterProperties::refreshFromItem(LLInventoryItem* item) getChild("CheckEveryoneCopy")->setValue(LLSD((BOOL)(everyone_mask & PERM_COPY))); getChild("CheckEveryoneMove")->setValue(LLSD((BOOL)(everyone_mask & PERM_MOVE))); + getChild("CheckExport")->setValue(LLSD((BOOL)(supports_export && everyone_mask & PERM_EXPORT))); /////////////// // SALE INFO // @@ -519,10 +542,11 @@ void LLFloaterProperties::refreshFromItem(LLInventoryItem* item) getChildView("SaleLabel")->setEnabled(is_complete); getChildView("CheckPurchase")->setEnabled(is_complete); - getChildView("NextOwnerLabel")->setEnabled(TRUE); - getChildView("CheckNextOwnerModify")->setEnabled((base_mask & PERM_MODIFY) && !cannot_restrict_permissions); - getChildView("CheckNextOwnerCopy")->setEnabled((base_mask & PERM_COPY) && !cannot_restrict_permissions); - getChildView("CheckNextOwnerTransfer")->setEnabled((next_owner_mask & PERM_COPY) && !cannot_restrict_permissions); + bool no_export = !(everyone_mask & PERM_EXPORT); // Next owner perms can't be changed if set + getChildView("NextOwnerLabel")->setEnabled(no_export); + getChildView("CheckNextOwnerModify")->setEnabled(no_export && (base_mask & PERM_MODIFY) && !cannot_restrict_permissions); + getChildView("CheckNextOwnerCopy")->setEnabled(no_export && (base_mask & PERM_COPY) && !cannot_restrict_permissions); + getChildView("CheckNextOwnerTransfer")->setEnabled(no_export && (next_owner_mask & PERM_COPY) && !cannot_restrict_permissions); getChildView("RadioSaleType")->setEnabled(is_complete && is_for_sale); getChildView("TextPrice")->setEnabled(is_complete && is_for_sale); @@ -670,7 +694,6 @@ void LLFloaterProperties::onCommitDescription() } } -// static void LLFloaterProperties::onCommitPermissions() { //llinfos << "LLFloaterProperties::onCommitPermissions()" << llendl; @@ -710,6 +733,11 @@ void LLFloaterProperties::onCommitPermissions() perm.setEveryoneBits(gAgent.getID(), gAgent.getGroupID(), CheckEveryoneCopy->get(), PERM_COPY); } + LLCheckBoxCtrl* CheckExport = getChild("CheckExport"); + if(CheckExport) + { + perm.setEveryoneBits(gAgent.getID(), gAgent.getGroupID(), CheckExport->get(), PERM_EXPORT); + } LLCheckBoxCtrl* CheckNextOwnerModify = getChild("CheckNextOwnerModify"); if(CheckNextOwnerModify) diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp index 5d06c7135..7aa6c1745 100644 --- a/indra/newview/llfloaterregioninfo.cpp +++ b/indra/newview/llfloaterregioninfo.cpp @@ -159,6 +159,39 @@ void unpack_request_params( */ +namespace +{ + void on_caps_received(LLTabContainer* tab) + { + if (!tab) return; + const LLViewerRegion* region = gAgent.getRegion(); + tab->enableTabButton(tab->getIndexForPanel(tab->getPanelByName("panel_env_info")), region && !region->getCapability("EnvironmentSettings").empty()); + } + + void handle_opposite(const bool& off, LLUICtrl* opposite) + { + opposite->setEnabled(!off); + if (off) opposite->setValue(false); + } + + void on_change_use_other_sun(const LLSD& param, LLUICtrl* opposite, LLUICtrl* slider) + { + handle_opposite(param.asBoolean(), opposite); + slider->setEnabled(false); + } + + void on_change_fixed_sun(const LLSD& param, LLUICtrl* opposite, LLUICtrl* slider) + { + bool fixed_sun = param.asBoolean(); + handle_opposite(fixed_sun, opposite); + slider->setEnabled(fixed_sun); + } + + const float get_sun_hour(const LLUICtrl* sun_hour) + { + return sun_hour->getEnabled() ? sun_hour->getValue().asFloat() : 0.f; + } +} bool estate_dispatch_initialized = false; @@ -351,6 +384,15 @@ void LLFloaterRegionInfo::processRegionInfo(LLMessageSystem* msg) LLTrans::findString(sim_type, sim_type); // try localizing sim product name } + // Disable Environment Tab when not supported + if (region) + { + if (region->capabilitiesReceived()) + on_caps_received(tab); + else + region->setCapabilitiesReceivedCallback(boost::bind(on_caps_received, tab)); + } + // GENERAL PANEL panel = tab->getChild("General"); panel->getChild("region_text")->setValue(LLSD(sim_name)); @@ -628,6 +670,27 @@ bool LLPanelRegionGeneralInfo::refreshFromRegion(LLViewerRegion* region) getChildView("im_btn")->setEnabled(allow_modify); getChildView("manage_telehub_btn")->setEnabled(allow_modify); + // Support Legacy Region Environment + { + const LLRegionInfoModel& region_info = LLRegionInfoModel::instance(); + bool estate_sun = region_info.mUseEstateSun; + getChild("use_estate_sun_check")->setValue(estate_sun); + getChild("fixed_sun_check")->setEnabled(allow_modify && !estate_sun); + getChild("sun_hour_slider")->setEnabled(allow_modify && !estate_sun); + if (estate_sun) + { + getChild("use_estate_sun_check")->setEnabled(allow_modify); + getChild("fixed_sun_check")->setValue(false); + } + else + { + bool fixed_sun = region_info.getUseFixedSun(); + getChild("use_estate_sun_check")->setEnabled(allow_modify && !fixed_sun); + getChild("fixed_sun_check")->setValue(fixed_sun); + getChild("sun_hour_slider")->setValue(region_info.mSunHour); + } + } + // Data gets filled in by processRegionInfo return LLPanelRegionInfo::refreshFromRegion(region); @@ -646,6 +709,9 @@ BOOL LLPanelRegionGeneralInfo::postBuild() initCtrl("access_combo"); initCtrl("restrict_pushobject"); initCtrl("block_parcel_search_check"); + initCtrl("use_estate_sun_check"); + initCtrl("fixed_sun_check"); + initCtrl("sun_hour_slider"); initHelpBtn("terraform_help", "HelpRegionBlockTerraform"); initHelpBtn("fly_help", "HelpRegionBlockFly"); @@ -657,12 +723,23 @@ BOOL LLPanelRegionGeneralInfo::postBuild() initHelpBtn("land_resell_help", "HelpRegionLandResell"); initHelpBtn("parcel_changes_help", "HelpParcelChanges"); initHelpBtn("parcel_search_help", "HelpRegionSearch"); + initHelpBtn("use_estate_sun_help", "HelpRegionUseEstateSun"); + initHelpBtn("fixed_sun_help", "HelpRegionFixedSun"); childSetAction("kick_btn", boost::bind(&LLPanelRegionGeneralInfo::onClickKick, this)); childSetAction("kick_all_btn", onClickKickAll, this); childSetAction("im_btn", onClickMessage, this); childSetAction("manage_telehub_btn", boost::bind(&LLPanelRegionGeneralInfo::onClickManageTelehub, this)); + // Set up the Legacy Region Environment checkboxes + { + LLUICtrl* estate_sun = getChild("use_estate_sun_check"); + LLUICtrl* fixed_sun = getChild("fixed_sun_check"); + LLUICtrl* hour_slider = getChild("sun_hour_slider"); + estate_sun->setCommitCallback(boost::bind(on_change_use_other_sun, _2, fixed_sun, hour_slider)); + fixed_sun->setCommitCallback(boost::bind(on_change_fixed_sun, _2, estate_sun, hour_slider)); + } + return LLPanelRegionInfo::postBuild(); } @@ -838,6 +915,13 @@ BOOL LLPanelRegionGeneralInfo::sendUpdate() sendEstateOwnerMessage(gMessageSystem, "setregioninfo", invoice, strings); } + // Send the Legacy Region Environment + LLRegionInfoModel& region_info = LLRegionInfoModel::instance(); + region_info.mUseEstateSun = getChild("use_estate_sun_check")->getValue().asBoolean(); + region_info.setUseFixedSun(getChild("fixed_sun_check")->getValue().asBoolean()); + region_info.mSunHour = get_sun_hour(getChild("sun_hour_slider")); + region_info.sendRegionTerrain(LLFloaterRegionInfo::getLastInvoice()); + // if we changed access levels, tell user about it LLViewerRegion* region = gAgent.getRegion(); if (region && (getChild("access_combo")->getValue().asInteger() != region->getSimAccess()) ) @@ -2014,11 +2098,16 @@ BOOL LLPanelEstateInfo::postBuild() { // set up the callbacks for the generic controls initCtrl("externally_visible_check"); + initCtrl("use_global_time_check"); + initCtrl("fixed_sun_check"); + initCtrl("sun_hour_slider"); initCtrl("allow_direct_teleport"); initCtrl("limit_payment"); initCtrl("limit_age_verified"); initCtrl("voice_chat_check"); initHelpBtn("estate_manager_help", "HelpEstateEstateManager"); + initHelpBtn("use_global_time_help", "HelpEstateUseGlobalTime"); + initHelpBtn("fixed_sun_help", "HelpEstateFixedSun"); initHelpBtn("externally_visible_help", "HelpEstateExternallyVisible"); initHelpBtn("allow_direct_teleport_help", "HelpEstateAllowDirectTeleport"); initHelpBtn("allow_resident_help", "HelpEstateAllowResident"); @@ -2026,6 +2115,15 @@ BOOL LLPanelEstateInfo::postBuild() initHelpBtn("ban_resident_help", "HelpEstateBanResident"); initHelpBtn("voice_chat_help", "HelpEstateVoiceChat"); + // Set up the Legacy Estate Environment checkboxes + { + LLUICtrl* global_time = getChild("use_global_time_check"); + LLUICtrl* fixed_sun = getChild("fixed_sun_check"); + LLUICtrl* hour_slider = getChild("sun_hour_slider"); + global_time->setCommitCallback(boost::bind(on_change_use_other_sun, _2, fixed_sun, hour_slider)); + fixed_sun->setCommitCallback(boost::bind(on_change_fixed_sun, _2, global_time, hour_slider)); + } + getChild("allowed_avatar_name_list")->setCommitCallback(boost::bind(&LLPanelEstateInfo::onChangeChildCtrl, this, _1)); LLNameListCtrl *avatar_name_list = getChild("allowed_avatar_name_list"); if (avatar_name_list) @@ -2105,14 +2203,36 @@ void LLPanelEstateInfo::refreshFromEstate() getChild("limit_payment")->setValue(estate_info.getDenyAnonymous()); getChild("limit_age_verified")->setValue(estate_info.getDenyAgeUnverified()); - // Ensure appriopriate state of the management UI + // Ensure appropriate state of the management UI updateControls(gAgent.getRegion()); + // Support Legacy Estate Environment + { + const LLEstateInfoModel& estate_info = LLEstateInfoModel::instance(); + bool global_time = estate_info.getGlobalTime(); + getChild("use_global_time_check")->setValue(global_time); + getChild("fixed_sun_check")->setEnabled(!global_time); + getChild("sun_hour_slider")->setEnabled(!global_time); + if (global_time) + { + getChild("use_global_time_check")->setEnabled(true); + getChild("fixed_sun_check")->setValue(false); + } + else + { + bool fixed_sun = estate_info.getUseFixedSun(); + getChild("use_global_time_check")->setEnabled(!fixed_sun); + getChild("fixed_sun_check")->setValue(fixed_sun); + F32 sun_hour = estate_info.getSunHour(); + if (sun_hour < 6.0f) sun_hour += 24.0f; + getChild("sun_hour_slider")->setValue(sun_hour); + } + } refresh(); } BOOL LLPanelEstateInfo::sendUpdate() { - llinfos << "LLPanelEsateInfo::sendUpdate()" << llendl; + llinfos << "LLPanelEstateInfo::sendUpdate()" << llendl; LLNotification::Params params("ChangeLindenEstate"); params.functor(boost::bind(&LLPanelEstateInfo::callbackChangeLindenEstate, this, _1, _2)); @@ -2140,8 +2260,9 @@ bool LLPanelEstateInfo::callbackChangeLindenEstate(const LLSD& notification, con LLEstateInfoModel& estate_info = LLEstateInfoModel::instance(); // update model - estate_info.setUseFixedSun(false); // we don't support fixed sun estates anymore estate_info.setIsExternallyVisible(getChild("externally_visible_check")->getValue().asBoolean()); + estate_info.setUseFixedSun(getChild("fixed_sun_check")->getValue().asBoolean()); + estate_info.setSunHour(get_sun_hour(getChild("sun_hour_slider"))); estate_info.setAllowDirectTeleport(getChild("allow_direct_teleport")->getValue().asBoolean()); estate_info.setDenyAnonymous(getChild("limit_payment")->getValue().asBoolean()); estate_info.setDenyAgeUnverified(getChild("limit_age_verified")->getValue().asBoolean()); diff --git a/indra/newview/llfloaterreporter.cpp b/indra/newview/llfloaterreporter.cpp index 06d1590b1..102d950f5 100644 --- a/indra/newview/llfloaterreporter.cpp +++ b/indra/newview/llfloaterreporter.cpp @@ -88,10 +88,6 @@ #include "lltrans.h" -// -#include "llviewercontrol.h" -// - // [RLVa:KB] #include "rlvhandler.h" // [/RLVa:KB] diff --git a/indra/newview/llfloaterstats.cpp b/indra/newview/llfloaterstats.cpp index a60619882..342e4fa45 100644 --- a/indra/newview/llfloaterstats.cpp +++ b/indra/newview/llfloaterstats.cpp @@ -238,25 +238,53 @@ void LLFloaterStats::buildStats() // Network statistics LLStatView *net_statviewp = stat_viewp->addStatView("network stat view", "Network", "OpenDebugStatNet", rect); - stat_barp = net_statviewp->addStat("Packets In", &(LLViewerStats::getInstance()->mPacketsInStat), "DebugStatModePacketsIn"); + stat_barp = net_statviewp->addStat("UDP Packets In", &(LLViewerStats::getInstance()->mPacketsInStat), "DebugStatModePacketsIn"); stat_barp->setUnitLabel("/sec"); - stat_barp = net_statviewp->addStat("Packets Out", &(LLViewerStats::getInstance()->mPacketsOutStat), "DebugStatModePacketsOut"); + stat_barp = net_statviewp->addStat("UDP Packets Out", &(LLViewerStats::getInstance()->mPacketsOutStat), "DebugStatModePacketsOut"); stat_barp->setUnitLabel("/sec"); - stat_barp = net_statviewp->addStat("Objects", &(LLViewerStats::getInstance()->mObjectKBitStat), "DebugStatModeObjects"); + stat_barp = net_statviewp->addStat("HTTP Textures", &(LLViewerStats::getInstance()->mHTTPTextureKBitStat), "DebugStatModeHTTPTexture"); stat_barp->setUnitLabel(" kbps"); + stat_barp->mMinBar = 0.f; + stat_barp->mMaxBar = gSavedSettings.getF32("HTTPThrottleBandwidth"); + stat_barp->mMaxBar *= llclamp(2.0 - (stat_barp->mMaxBar - 400.f) / 3600.f, 1.0, 2.0); // Allow for overshoot (allow more for low bandwidth values). + stat_barp->mTickSpacing = 1.f; + while (stat_barp->mTickSpacing < stat_barp->mMaxBar / 8) + stat_barp->mTickSpacing *= 2.f; + stat_barp->mLabelSpacing = 2 * stat_barp->mTickSpacing; + stat_barp->mPerSec = FALSE; + stat_barp->mDisplayMean = FALSE; - stat_barp = net_statviewp->addStat("Texture", &(LLViewerStats::getInstance()->mTextureKBitStat), "DebugStatModeTexture"); + stat_barp = net_statviewp->addStat("UDP Textures", &(LLViewerStats::getInstance()->mUDPTextureKBitStat), "DebugStatModeUDPTexture"); stat_barp->setUnitLabel(" kbps"); + stat_barp->mMinBar = 0.f; + stat_barp->mMaxBar = 1024.f; + stat_barp->mTickSpacing = 128.f; + stat_barp->mLabelSpacing = 256.f; - stat_barp = net_statviewp->addStat("Asset", &(LLViewerStats::getInstance()->mAssetKBitStat), "DebugStatModeAsset"); + stat_barp = net_statviewp->addStat("Objects (UDP)", &(LLViewerStats::getInstance()->mObjectKBitStat), "DebugStatModeObjects"); stat_barp->setUnitLabel(" kbps"); + stat_barp->mMinBar = 0.f; + stat_barp->mMaxBar = 1024.f; + stat_barp->mTickSpacing = 128.f; + stat_barp->mLabelSpacing = 256.f; - stat_barp = net_statviewp->addStat("Layers", &(LLViewerStats::getInstance()->mLayersKBitStat), "DebugStatModeLayers"); + stat_barp = net_statviewp->addStat("Assets (UDP)", &(LLViewerStats::getInstance()->mAssetKBitStat), "DebugStatModeAsset"); stat_barp->setUnitLabel(" kbps"); + stat_barp->mMinBar = 0.f; + stat_barp->mMaxBar = 1024.f; + stat_barp->mTickSpacing = 128.f; + stat_barp->mLabelSpacing = 256.f; - stat_barp = net_statviewp->addStat("Actual In", &(LLViewerStats::getInstance()->mActualInKBitStat), + stat_barp = net_statviewp->addStat("Layers (UDP)", &(LLViewerStats::getInstance()->mLayersKBitStat), "DebugStatModeLayers"); + stat_barp->setUnitLabel(" kbps"); + stat_barp->mMinBar = 0.f; + stat_barp->mMaxBar = 1024.f; + stat_barp->mTickSpacing = 128.f; + stat_barp->mLabelSpacing = 256.f; + + stat_barp = net_statviewp->addStat("Actual In (UDP)", &(LLViewerStats::getInstance()->mActualInKBitStat), "DebugStatModeActualIn", TRUE, FALSE); stat_barp->setUnitLabel(" kbps"); stat_barp->mMinBar = 0.f; @@ -264,7 +292,7 @@ void LLFloaterStats::buildStats() stat_barp->mTickSpacing = 128.f; stat_barp->mLabelSpacing = 256.f; - stat_barp = net_statviewp->addStat("Actual Out", &(LLViewerStats::getInstance()->mActualOutKBitStat), + stat_barp = net_statviewp->addStat("Actual Out (UDP)", &(LLViewerStats::getInstance()->mActualOutKBitStat), "DebugStatModeActualOut", TRUE, FALSE); stat_barp->setUnitLabel(" kbps"); stat_barp->mMinBar = 0.f; diff --git a/indra/newview/llimpanel.cpp b/indra/newview/llimpanel.cpp index f94bc7a36..707f3d929 100644 --- a/indra/newview/llimpanel.cpp +++ b/indra/newview/llimpanel.cpp @@ -2590,3 +2590,32 @@ const bool LLFloaterIMPanel::isModerator(const LLUUID& speaker_id) return FALSE; } +BOOL LLFloaterIMPanel::focusFirstItem(BOOL prefer_text_fields, BOOL focus_flash ) +{ + LLView* chat_editor = getChildView("chat_editor"); + if (getVisible() && childIsVisible("chat_editor")) + { + gFocusMgr.setKeyboardFocus(chat_editor); + + LLUICtrl * ctrl = static_cast(chat_editor); + ctrl->setFocus(TRUE); + + return TRUE; + } + + return LLUICtrl::focusFirstItem(prefer_text_fields, focus_flash); +} + +void LLFloaterIMPanel::onFocusReceived() +{ + LLView* chat_editor = getChildView("chat_editor"); + if (getVisible() && childIsVisible("chat_editor")) + { + gFocusMgr.setKeyboardFocus(chat_editor); + + LLUICtrl * ctrl = static_cast(chat_editor); + ctrl->setFocus(TRUE); + } + + LLFloater::onFocusReceived(); +} diff --git a/indra/newview/llimpanel.h b/indra/newview/llimpanel.h index 1efb551df..95f5eb41e 100644 --- a/indra/newview/llimpanel.h +++ b/indra/newview/llimpanel.h @@ -231,6 +231,9 @@ public: void *cargo_data, EAcceptance *accept, std::string& tooltip_msg); + BOOL focusFirstItem(BOOL prefer_text_fields = FALSE, BOOL focus_flash = TRUE ); + + void onFocusReceived(); void onInputEditorFocusReceived(); void onInputEditorFocusLost(); void onInputEditorKeystroke(LLLineEditor* caller); diff --git a/indra/newview/llinventoryactions.cpp b/indra/newview/llinventoryactions.cpp index 5f0c183ee..ed0c6c54e 100644 --- a/indra/newview/llinventoryactions.cpp +++ b/indra/newview/llinventoryactions.cpp @@ -31,79 +31,26 @@ */ #include "llviewerprecompiledheaders.h" - -#include // for std::pair<> - -#include "llinventorypanel.h" -#include "llpanelobjectinventory.h" -#include "llinventorybridge.h" - -#include "message.h" - -#include "llagent.h" #include "llagentwearables.h" -#include "llcallingcard.h" -#include "llcheckboxctrl.h" // for radio buttons -#include "llfoldervieweventlistener.h" -#include "llnotificationsutil.h" -#include "llradiogroup.h" -#include "llspinctrl.h" -#include "lltextbox.h" -#include "llui.h" - - -#include "llviewercontrol.h" -#include "llfirstuse.h" -#include "llfloateravatarinfo.h" -#include "llfloaterchat.h" -#include "llfloatercustomize.h" -#include "llfloaterinventory.h" -#include "llfloaterproperties.h" -#include "llfocusmgr.h" -#include "llfolderview.h" -#include "llgesturemgr.h" -#include "lliconctrl.h" +#include "llimview.h" #include "llinventoryfunctions.h" +#include "llinventorybridge.h" #include "llinventoryclipboard.h" #include "llinventorymodelbackgroundfetch.h" -#include "lllineeditor.h" +#include "llinventorypanel.h" #include "llmakeoutfitdialog.h" -#include "llmenugl.h" -#include "llpreviewanim.h" -#include "llpreviewgesture.h" -#include "llpreviewlandmark.h" -#include "llpreviewnotecard.h" -#include "llpreviewscript.h" -#include "llpreviewsound.h" -#include "llpreviewtexture.h" -#include "llresmgr.h" -#include "llscrollcontainer.h" -#include "llimview.h" -#include "lltooldraganddrop.h" -#include "llviewertexturelist.h" -#include "llviewerinventory.h" -#include "llviewerobjectlist.h" -#include "llviewerwindow.h" +#include "llnotificationsutil.h" +#include "llpanelmaininventory.h" +#include "llpanelobjectinventory.h" +#include "llpreview.h" // For LLMultiPreview +#include "llfoldervieweventlistener.h" +#include "lltrans.h" #include "llvoavatarself.h" -#include "llwearable.h" -#include "llwearablelist.h" -#include "llviewermessage.h" -#include "llviewerregion.h" -#include "lltabcontainer.h" -#include "lluictrlfactory.h" -#include "llselectmgr.h" -// -#include "lllocalinventory.h" -#include "statemachine/aifilepicker.h" -// +extern LLUUID gAgentID; using namespace LLOldEvents; -const std::string NEW_LSL_NAME = "New Script"; // *TODO:Translate? (probably not) -const std::string NEW_NOTECARD_NAME = "New Note"; // *TODO:Translate? (probably not) -const std::string NEW_GESTURE_NAME = "New Gesture"; // *TODO:Translate? (probably not) - typedef LLMemberListener object_inventory_listener_t; typedef LLMemberListener inventory_listener_t; typedef LLMemberListener inventory_panel_listener_t; @@ -116,42 +63,39 @@ bool doToSelected(LLFolderView* folder, std::string action) folder->startRenamingSelectedItem(); return true; } - if ("delete" == action) + else if ("delete" == action) { folder->removeSelectedItems(); return true; } - - if ("copy" == action || "cut" == action) + else if ("copy" == action || "cut" == action) { LLInventoryClipboard::instance().reset(); } std::set selected_items = folder->getSelectionList(); - LLMultiPreview* multi_previewp = NULL; - LLMultiProperties* multi_propertiesp = NULL; + LLMultiFloater* multi_floaterp = NULL; if (("task_open" == action || "open" == action) && selected_items.size() > 1) { S32 left, top; gFloaterView->getNewFloaterPosition(&left, &top); - multi_previewp = new LLMultiPreview(LLRect(left, top, left + 300, top - 100)); - gFloaterView->addChild(multi_previewp); + multi_floaterp = new LLMultiPreview(LLRect(left, top, left + 300, top - 100)); + gFloaterView->addChild(multi_floaterp); - LLFloater::setFloaterHost(multi_previewp); - + LLFloater::setFloaterHost(multi_floaterp); } else if (("task_properties" == action || "properties" == action) && selected_items.size() > 1) { S32 left, top; gFloaterView->getNewFloaterPosition(&left, &top); - multi_propertiesp = new LLMultiProperties(LLRect(left, top, left + 100, top - 100)); - gFloaterView->addChild(multi_propertiesp); + multi_floaterp = new LLMultiProperties(LLRect(left, top, left + 100, top - 100)); + gFloaterView->addChild(multi_floaterp); - LLFloater::setFloaterHost(multi_propertiesp); + LLFloater::setFloaterHost(multi_floaterp); } std::set::iterator set_iter; @@ -167,13 +111,9 @@ bool doToSelected(LLFolderView* folder, std::string action) } LLFloater::setFloaterHost(NULL); - if (multi_previewp) + if (multi_floaterp) { - multi_previewp->open(); - } - else if (multi_propertiesp) - { - multi_propertiesp->open(); /*Flawfinder: ignore*/ + multi_floaterp->open(); } return true; @@ -183,12 +123,11 @@ class LLDoToSelectedPanel : public object_inventory_listener_t { bool handleEvent(LLPointer event, const LLSD& userdata) { - std::string action = userdata.asString(); LLPanelObjectInventory *panel = mPtr; LLFolderView* folder = panel->getRootFolder(); if(!folder) return true; - return doToSelected(folder, action); + return doToSelected(folder, userdata.asString()); } }; @@ -196,12 +135,11 @@ class LLDoToSelectedFloater : public inventory_listener_t { bool handleEvent(LLPointer event, const LLSD& userdata) { - std::string action = userdata.asString(); LLInventoryPanel *panel = mPtr->getPanel(); LLFolderView* folder = panel->getRootFolder(); if(!folder) return true; - return doToSelected(folder, action); + return doToSelected(folder, userdata.asString()); } }; @@ -209,12 +147,11 @@ class LLDoToSelected : public inventory_panel_listener_t { bool handleEvent(LLPointer event, const LLSD& userdata) { - std::string action = userdata.asString(); LLInventoryPanel *panel = mPtr; LLFolderView* folder = panel->getRootFolder(); if(!folder) return true; - return doToSelected(folder, action); + return doToSelected(folder, userdata.asString()); } }; @@ -356,7 +293,7 @@ void do_create(LLInventoryModel *model, LLInventoryPanel *ptr, std::string type, else if ("lsl" == type) { LLUUID parent_id = self ? self->getUUID() : model->findCategoryUUIDForType(LLFolderType::FT_LSL_TEXT); - ptr->createNewItem(NEW_LSL_NAME, + ptr->createNewItem(LLTrans::getString("New Script"), parent_id, LLAssetType::AT_LSL_TEXT, LLInventoryType::IT_LSL, @@ -365,7 +302,7 @@ void do_create(LLInventoryModel *model, LLInventoryPanel *ptr, std::string type, else if ("notecard" == type) { LLUUID parent_id = self ? self->getUUID() : model->findCategoryUUIDForType(LLFolderType::FT_NOTECARD); - ptr->createNewItem(NEW_NOTECARD_NAME, + ptr->createNewItem(LLTrans::getString("New Note"), parent_id, LLAssetType::AT_NOTECARD, LLInventoryType::IT_NOTECARD, @@ -374,7 +311,7 @@ void do_create(LLInventoryModel *model, LLInventoryPanel *ptr, std::string type, else if ("gesture" == type) { LLUUID parent_id = self ? self->getUUID() : model->findCategoryUUIDForType(LLFolderType::FT_GESTURE); - ptr->createNewItem(NEW_GESTURE_NAME, + ptr->createNewItem(LLTrans::getString("New Gesture"), parent_id, LLAssetType::AT_GESTURE, LLInventoryType::IT_GESTURE, @@ -383,11 +320,11 @@ void do_create(LLInventoryModel *model, LLInventoryPanel *ptr, std::string type, else if ("outfit" == type) { new LLMakeOutfitDialog(false); + return; } else { - LLWearableType::EType wear_type = LLWearableType::typeNameToType(type); - LLAgentWearables::createWearable(wear_type, false, self ? self->getUUID() : LLUUID::null); + LLAgentWearables::createWearable(LLWearableType::typeNameToType(type), false, self ? self->getUUID() : LLUUID::null); } ptr->getRootFolder()->setNeedsAutoRename(TRUE); } @@ -411,14 +348,6 @@ class LLDoCreateFloater : public inventory_listener_t LLInventoryModel* model = mPtr->getPanel()->getModel(); if(!model) return false; std::string type = userdata.asString(); - // - if(type == "pretend") - { - LLFloaterNewLocalInventory* floater = new LLFloaterNewLocalInventory(); - floater->center(); - } - else - // do_create(model, mPtr->getPanel(), type); return true; } @@ -484,28 +413,6 @@ class LLSetSortBy : public inventory_listener_t } }; -// -class LLLoadInvCacheFloater : public inventory_listener_t -{ - bool handleEvent(LLPointer event, const LLSD& userdata) - { - LLInventoryModel* model = mPtr->getPanel()->getModel(); - if(!model) return false; - AIFilePicker* filepicker = AIFilePicker::create(); - filepicker->open(FFLOAD_INVGZ, "", "invgz"); - filepicker->run(boost::bind(&LLLoadInvCacheFloater::filepicker_callback, this, filepicker)); - return true; - } - - void filepicker_callback(AIFilePicker* filepicker) - { - if(filepicker->hasFilename()) - { - LLLocalInventory::loadInvCache(filepicker->getFilename()); - } - } -}; - class LLRefreshInvModel : public inventory_listener_t { bool handleEvent(LLPointer event, const LLSD& userdata) @@ -522,8 +429,7 @@ class LLSetSearchType : public inventory_listener_t { bool handleEvent(LLPointer event, const LLSD& userdata) { - std::string toggle = userdata.asString(); - U32 flags = mPtr->getActivePanel()->getRootFolder()->toggleSearchType(toggle); + U32 flags = mPtr->getActivePanel()->getRootFolder()->toggleSearchType(userdata.asString()); mPtr->getControl("Inventory.SearchName")->setValue((BOOL)(flags & 1)); mPtr->getControl("Inventory.SearchDesc")->setValue((BOOL)(flags & 2)); mPtr->getControl("Inventory.SearchCreator")->setValue((BOOL)(flags & 4)); @@ -546,8 +452,7 @@ class LLBeginIMSession : public inventory_panel_listener_t LLDynamicArray members; EInstantMessage type = IM_SESSION_CONFERENCE_START; - std::set::const_iterator iter; - for (iter = selected_items.begin(); iter != selected_items.end(); iter++) + for (std::set::const_iterator iter = selected_items.begin(); iter != selected_items.end(); iter++) { LLUUID item = *iter; @@ -577,11 +482,10 @@ class LLBeginIMSession : public inventory_panel_listener_t { // create the session gIMMgr->setFloaterOpen(TRUE); - S32 i; - + LLAvatarTracker& at = LLAvatarTracker::instance(); LLUUID id; - for(i = 0; i < count; ++i) + for(S32 i = 0; i < count; ++i) { id = item_array.get(i)->getCreatorUUID(); if(at.isBuddyOnline(id)) @@ -660,27 +564,28 @@ class LLAttachObject : public inventory_panel_listener_t break; } } - if (attachmentp == NULL) + if (!attachmentp) { return true; } - LLViewerInventoryItem* item = (LLViewerInventoryItem*)gInventory.getItem(id); - - if(item && gInventory.isObjectDescendentOf(id, gInventory.getRootFolderID())) + if (LLViewerInventoryItem* item = (LLViewerInventoryItem*)gInventory.getItem(id)) { - rez_attachment(item, attachmentp); // don't replace if called from an "Attach To..." menu - } - else if(item && item->isFinished()) - { - // must be in library. copy it to our inventory and put it on. - LLPointer cb = new LLBoostFuncInventoryCallback(boost::bind(rez_attachment_cb, _1, attachmentp, false)); - copy_inventory_item( - gAgent.getID(), - item->getPermissions().getOwner(), - item->getUUID(), - LLUUID::null, - std::string(), - cb); + if(gInventory.isObjectDescendentOf(id, gInventory.getRootFolderID())) + { + rez_attachment(item, attachmentp); // don't replace if called from an "Attach To..." menu + } + else if(item->isFinished()) + { + // must be in library. copy it to our inventory and put it on. + LLPointer cb = new LLBoostFuncInventoryCallback(boost::bind(rez_attachment_cb, _1, attachmentp, false)); + copy_inventory_item( + gAgentID, + item->getPermissions().getOwner(), + item->getUUID(), + LLUUID::null, + std::string(), + cb); + } } gFocusMgr.setKeyboardFocus(NULL); @@ -688,16 +593,6 @@ class LLAttachObject : public inventory_panel_listener_t } }; -/* -class LL : public listener_t -{ - bool handleEvent(LLPointer event, const LLSD& userdata) - { - return true; - } -}; -*/ - void init_object_inventory_panel_actions(LLPanelObjectInventory *panel) { (new LLDoToSelectedPanel())->registerListener(panel, "Inventory.DoToSelected"); @@ -709,9 +604,6 @@ void init_inventory_actions(LLInventoryView *floater) (new LLCloseAllFoldersFloater())->registerListener(floater, "Inventory.CloseAllFolders"); (new LLEmptyTrashFloater())->registerListener(floater, "Inventory.EmptyTrash"); (new LLDoCreateFloater())->registerListener(floater, "Inventory.DoCreate"); - // - (new LLLoadInvCacheFloater())->registerListener(floater, "Inventory.LoadInvCache"); - // (new LLNewWindow())->registerListener(floater, "Inventory.NewWindow"); (new LLShowFilters())->registerListener(floater, "Inventory.ShowFilters"); @@ -719,7 +611,6 @@ void init_inventory_actions(LLInventoryView *floater) (new LLSetSortBy())->registerListener(floater, "Inventory.SetSortBy"); (new LLSetSearchType())->registerListener(floater, "Inventory.SetSearchType"); - } void init_inventory_panel_actions(LLInventoryPanel *panel) diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 6316714b1..a68754942 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -3,10 +3,9 @@ * @brief Implementation of the Inventory-Folder-View-Bridge classes. * * $LicenseInfo:firstyear=2001&license=viewergpl$ - * + * Second Life Viewer Source Code * 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 @@ -31,18 +30,8 @@ */ #include "llviewerprecompiledheaders.h" - -#include // for std::pair<> - #include "llinventorybridge.h" -#include "message.h" - -#include "llcheckboxctrl.h" // for radio buttons -#include "llradiogroup.h" -#include "llspinctrl.h" -#include "lltextbox.h" -#include "llui.h" #include "lluictrlfactory.h" #include "llagent.h" @@ -55,15 +44,12 @@ #include "llfloateravatarinfo.h" #include "llfloaterchat.h" #include "llfloatercustomize.h" -#include "llfloaterinventory.h" #include "llfloateropenobject.h" #include "llfloaterproperties.h" #include "llfloaterworldmap.h" -#include "llfocusmgr.h" #include "llfolderview.h" #include "llgesturemgr.h" #include "llgiveinventory.h" -#include "lliconctrl.h" #include "llimview.h" #include "llinventoryclipboard.h" #include "llinventorydefines.h" @@ -72,9 +58,7 @@ #include "llinventorymodel.h" #include "llinventorymodelbackgroundfetch.h" #include "llinventorypanel.h" -#include "lllineeditor.h" #include "llmarketplacefunctions.h" -#include "llmenugl.h" #include "llnotifications.h" #include "llnotificationsutil.h" #include "llpreviewanim.h" @@ -84,40 +68,19 @@ #include "llpreviewscript.h" #include "llpreviewsound.h" #include "llpreviewtexture.h" -#include "llresmgr.h" #include "llselectmgr.h" -#include "llscrollcontainer.h" #include "lltooldraganddrop.h" -#include "lltabcontainer.h" #include "lltrans.h" #include "llviewerassettype.h" -#include "llviewercontrol.h" #include "llviewerfoldertype.h" -#include "llviewerinventory.h" #include "llviewermessage.h" #include "llviewerobjectlist.h" #include "llviewerregion.h" -#include "llviewertexturelist.h" #include "llviewerwindow.h" #include "llvoavatar.h" -#include "llfoldertype.h" #include "llwearable.h" #include "llwearablelist.h" -// -#include "llappviewer.h" // System Folders -#include "llfloateranimpreview.h" // for reuploads -#include "llfloaterimagepreview.h" // for reuploads -#include "statemachine/aifilepicker.h" -// - -// Editing wearables from inventory is an include-hungry feature -.- -SG -#include "llviewerparcelmgr.h" -#include "llfloatertools.h" -#include "lltoolcomp.h" -#include "llviewerjoystick.h" -#include "lltoolmgr.h" - #include "hippogridmanager.h" // [RLVa:KB] @@ -125,6 +88,8 @@ #include "rlvlocks.h" // [/RLVa:KB] +extern LLUUID gSystemFolderRoot; + // Marketplace outbox current disabled #define ENABLE_MERCHANT_OUTBOX_CONTEXT_MENU 1 #define ENABLE_MERCHANT_SEND_TO_MARKETPLACE_CONTEXT_MENU 1 @@ -229,22 +194,6 @@ public: } }; -// -void gotImageForSaveItemAs(BOOL success, - LLViewerTexture *src_vi, - LLImageRaw* src, - LLImageRaw* aux_src, - S32 discard_level, - BOOL final, - void* userdata); -void gotAssetForSaveItemAs(LLVFS *vfs, - const LLUUID& asset_uuid, - LLAssetType::EType type, - void* user_data, S32 status, LLExtStat ext_status); -// - - - // +=================================================+ // | LLInvFVBridge | // +=================================================+ @@ -434,9 +383,6 @@ void LLInvFVBridge::removeBatchNoCheck(LLDynamicArraygetParentUUID() == trash_id) continue; move_ids.push_back(item->getUUID()); - // don't do stuff that messes with gMessageSystem - //LLPreview::hide(item->getUUID()); - // --update[item->getParentUUID()]; ++update[trash_id]; // @@ -475,6 +421,7 @@ void LLInvFVBridge::removeBatchNoCheck(LLDynamicArraysetEnabled(enabled); } } @@ -893,7 +841,6 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id, void LLInvFVBridge::buildContextMenu(LLMenuGL& menu, U32 flags) { - // *TODO: Translate lldebugs << "LLInvFVBridge::buildContextMenu()" << llendl; menuentry_vec_t items; menuentry_vec_t disabled_items; @@ -1556,19 +1503,6 @@ void LLItemBridge::performAction(LLInventoryModel* model, std::string action) folder_view_itemp->getListener()->pasteLinkFromClipboard(); return; } - - // - else if("reupload" == action) - { - LLInventoryItem* item = model->getItem(mUUID); - if (item && item->getType() == LLAssetType::AT_TEXTURE) - { - AIFilePicker* filepicker = AIFilePicker::create(); - filepicker->open(FFLOAD_IMAGE, "", "image"); - filepicker->run(boost::bind(&LLItemBridge::showFloaterImagePreview, item, filepicker)); - } - } - // else if (isMarketplaceCopyAction(action)) { llinfos << "Copy item to marketplace action!" << llendl; @@ -1581,16 +1515,6 @@ void LLItemBridge::performAction(LLInventoryModel* model, std::string action) } } -// static -void LLItemBridge::showFloaterImagePreview(LLInventoryItem* item, AIFilePicker* filepicker) -{ - if (filepicker->hasFilename()) - { - LLFloaterImagePreview* floaterp = new LLFloaterImagePreview(filepicker->getFilename(), item); - LLUICtrlFactory::getInstance()->buildFloater(floaterp, "floater_image_preview.xml"); - } -} - void LLItemBridge::selectItem() { LLViewerInventoryItem* item = static_cast(getItem()); @@ -1634,17 +1558,17 @@ void LLItemBridge::restoreToWorld() itemp->packMessage(msg); msg->sendReliable(gAgent.getRegion()->getHost()); - //remove local inventory copy, sim will deal with permissions and removing the item - //from the actual inventory if its a no-copy etc - if(!itemp->getPermissions().allowCopyBy(gAgent.getID())) - { + //remove local inventory copy, sim will deal with permissions and removing the item + //from the actual inventory if its a no-copy etc + if(!itemp->getPermissions().allowCopyBy(gAgent.getID())) + { remove_from_inventory = true; - } + } - // Check if it's in the trash. (again similar to the normal rez logic) + // Check if it's in the trash. (again similar to the normal rez logic) const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH); - if(gInventory.isObjectDescendentOf(itemp->getUUID(), trash_id)) - { + if(gInventory.isObjectDescendentOf(itemp->getUUID(), trash_id)) + { remove_from_inventory = true; } } @@ -1689,7 +1613,7 @@ PermissionMask LLItemBridge::getPermissionMask() const if (item) perm_mask = item->getPermissionMask(); return perm_mask; } - + const std::string& LLItemBridge::getDisplayName() const { if(mDisplayName.empty()) @@ -1701,9 +1625,9 @@ const std::string& LLItemBridge::getDisplayName() const void LLItemBridge::buildDisplayName(LLInventoryItem* item, std::string& name) { - if(item) + if(item) { - name.assign(item->getName()); + name.assign(item->getName()); } else { @@ -1741,7 +1665,7 @@ std::string LLItemBridge::getLabelSuffix() const static std::string BROKEN_LINK = LLTrans::getString("broken_link"); std::string suffix; LLInventoryItem* item = getItem(); - if(item) + if(item) { // Any type can have the link suffix... BOOL broken_link = LLAssetType::lookupIsLinkType(item->getType()); @@ -1770,7 +1694,7 @@ std::string LLItemBridge::getLabelSuffix() const { suffix += NO_XFER; } - + BOOL temp = item->getPermissions().getGroup() == gAgent.getID(); if (temp) @@ -2017,7 +1941,6 @@ void LLFolderBridge::selectItem() { } - // Iterate through a folder's children to determine if // all the children are removable. class LLIsItemRemovable : public LLFolderViewFunctor @@ -2147,7 +2070,6 @@ BOOL LLFolderBridge::isClipboardPasteable() const } - BOOL LLFolderBridge::isClipboardPasteableAsLink() const { // Check normal paste-as-link permissions @@ -2288,7 +2210,7 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, LLInventoryModel* model = getInventoryModel(); if (!inv_cat) return FALSE; // shouldn't happen, but in case item is incorrectly parented in which case inv_cat will be NULL - if(!model) return FALSE; + if (!model) return FALSE; if (!isAgentAvatarValid()) return FALSE; if (!isAgentInventory()) return FALSE; // cannot drag categories into library @@ -2759,9 +2681,9 @@ void LLRightClickInventoryFetchDescendentsObserver::execute(bool clear_observer) // Move to next if current folder empty if ((item_count == 0) && (cat_count == 0)) - { + { continue; - } + } uuid_vec_t ids; LLRightClickInventoryFetchObserver* outfit = NULL; @@ -2834,7 +2756,7 @@ void LLRightClickInventoryFetchDescendentsObserver::execute(bool clear_observer) //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Class LLInventoryWearObserver // -// Observer for "copy and wear" operation to support knowing +// Observer for "copy and wear" operation to support knowing // when the all of the contents have been added to inventory. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ class LLInventoryCopyAndWearObserver : public LLInventoryObserver @@ -2857,7 +2779,7 @@ void LLInventoryCopyAndWearObserver::changed(U32 mask) { if((mask & (LLInventoryObserver::ADD)) != 0) { - if (!mFolderAdded) + if (!mFolderAdded) { const std::set& changed_items = gInventory.getChangedIDs(); @@ -2865,7 +2787,7 @@ void LLInventoryCopyAndWearObserver::changed(U32 mask) std::set::const_iterator id_end = changed_items.end(); for (;id_it != id_end; ++id_it) { - if ((*id_it) == mCatID) + if ((*id_it) == mCatID) { mFolderAdded = TRUE; break; @@ -2873,13 +2795,13 @@ void LLInventoryCopyAndWearObserver::changed(U32 mask) } } - if (mFolderAdded) + if (mFolderAdded) { LLViewerInventoryCategory* category = gInventory.getCategory(mCatID); if (NULL == category) { llwarns << "gInventory.getCategory(" << mCatID - << ") was NULL" << llendl; + << ") was NULL" << llendl; } else { @@ -2890,7 +2812,7 @@ void LLInventoryCopyAndWearObserver::changed(U32 mask) LLAppearanceMgr::instance().wearInventoryCategory(category, FALSE, FALSE); delete this; } - } + } } } @@ -2961,10 +2883,10 @@ void LLFolderBridge::performAction(LLInventoryModel* model, std::string action) if(!model) return; LLViewerInventoryCategory* cat = getCategory(); if(!cat) return; - - remove_inventory_category_from_avatar ( cat ); + + remove_inventory_category_from_avatar( cat ); return; - } + } else if ("purge" == action) { purgeItem(model, mUUID); @@ -3123,6 +3045,7 @@ BOOL LLFolderBridge::removeItem() return TRUE; } + BOOL LLFolderBridge::removeSystemFolder() { const LLViewerInventoryCategory *cat = getCategory(); @@ -3405,7 +3328,7 @@ void LLFolderBridge::buildContextMenuBaseOptions(U32 flags) { // This is the lost+found folder. mItems.push_back(std::string("Empty Lost And Found")); - + mDisabledItems.push_back(std::string("New Folder")); mDisabledItems.push_back(std::string("New Script")); mDisabledItems.push_back(std::string("New Note")); @@ -3413,7 +3336,6 @@ void LLFolderBridge::buildContextMenuBaseOptions(U32 flags) mDisabledItems.push_back(std::string("New Clothes")); mDisabledItems.push_back(std::string("New Body Parts")); } - if(trash_id == mUUID) { // This is the trash. @@ -3431,7 +3353,7 @@ void LLFolderBridge::buildContextMenuBaseOptions(U32 flags) } else if(isAgentInventory()) // do not allow creating in library { - LLViewerInventoryCategory *cat = getCategory(); + LLViewerInventoryCategory *cat = getCategory(); // BAP removed protected check to re-enable standard ops in untyped folders. // Not sure what the right thing is to do here. if (!isCOFFolder() && cat && (cat->getPreferredType() != LLFolderType::FT_OUTFIT)) @@ -3475,7 +3397,7 @@ void LLFolderBridge::buildContextMenuBaseOptions(U32 flags) { mCallingCards=TRUE; } - + LLFindWearables is_wearable; LLIsType is_object( LLAssetType::AT_OBJECT ); LLIsType is_gesture( LLAssetType::AT_GESTURE ); @@ -3497,14 +3419,13 @@ void LLFolderBridge::buildContextMenuBaseOptions(U32 flags) void LLFolderBridge::buildContextMenuFolderOptions(U32 flags) { - // *TODO: Translate - + // Build folder specific options back up LLInventoryModel* model = getInventoryModel(); if(!model) return; const LLInventoryCategory* category = model->getCategory(mUUID); if(!category) return; - + const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH); if (trash_id == mUUID) return; if (isItemInTrash()) return; @@ -3518,7 +3439,7 @@ void LLFolderBridge::buildContextMenuFolderOptions(U32 flags) const bool is_outfit = (type == LLFolderType::FT_OUTFIT); // [/SL:KB] - // Only enable calling-card related options for non-default folders. + // Only enable calling-card related options for non-system folders. if (!is_system_folder) { LLIsType is_callingcard(LLAssetType::AT_CALLINGCARD); @@ -3555,7 +3476,7 @@ void LLFolderBridge::buildContextMenuFolderOptions(U32 flags) { mItems.push_back(std::string("Folder Wearables Separator")); - // Only enable add/replace outfit for non-default folders. + // Only enable add/replace outfit for non-system folders. if (!is_system_folder) { if (InventoryLinksEnabled() && @@ -3565,7 +3486,8 @@ void LLFolderBridge::buildContextMenuFolderOptions(U32 flags) mItems.push_back(std::string("Add To Outfit")); } else if(!InventoryLinksEnabled()) - mItems.push_back(std::string("Wearable And Object Wear")); + mItems.push_back(std::string("Wearable And Object Wear")); + mItems.push_back(std::string("Replace Outfit")); } mItems.push_back(std::string("Remove From Outfit")); @@ -3597,7 +3519,7 @@ void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags) LLInventoryModel* model = getInventoryModel(); if(!model) return; - + buildContextMenuBaseOptions(flags); // Add menu items that are dependent on the contents of the folder. @@ -3849,9 +3771,9 @@ bool move_task_inventory_callback(const LLSD& notification, const LLSD& response } two_uuids_list_t::iterator move_it; - for (move_it = move_inv->mMoveList.begin(); - move_it != move_inv->mMoveList.end(); - ++move_it) + for (move_it = move_inv->mMoveList.begin(); + move_it != move_inv->mMoveList.end(); + ++move_it) { object->moveInventory(move_it->first, move_it->second); } @@ -3956,8 +3878,8 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, { LLInventoryModel* model = getInventoryModel(); - if(!model || !inv_item) return FALSE; - if(!isAgentInventory()) return FALSE; // cannot drag into library + if (!model || !inv_item) return FALSE; + if (!isAgentInventory()) return FALSE; // cannot drag into library if (!isAgentAvatarValid()) return FALSE; LLInventoryPanel* destination_panel = mInventoryPanel.get(); @@ -3993,22 +3915,22 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, switch (inv_item->getActualType()) { - //case LLFolderType::FT_ROOT_CATEGORY: - // is_movable = FALSE; - // break; + //case LLFolderType::FT_ROOT_CATEGORY: + // is_movable = FALSE; + // break; - case LLAssetType::AT_CATEGORY: - is_movable = !LLFolderType::lookupIsProtectedType(((LLInventoryCategory*)inv_item)->getPreferredType()); - break; - default: - break; + case LLAssetType::AT_CATEGORY: + is_movable = !LLFolderType::lookupIsProtectedType(((LLInventoryCategory*)inv_item)->getPreferredType()); + break; + default: + break; } - + // Can't explicitly drag things out of the COF. if (move_is_outof_current_outfit) { is_movable = FALSE; } - + // [RLVa:KB] - Checked: 2011-03-29 (RLVa-1.3.0g) | Modified: RLVa-1.3.0g if ( (rlv_handler_t::isEnabled()) && (is_movable) ) { @@ -4103,7 +4025,7 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, if (!active_folder_view) return false; } - if(accept && drop) + if (accept && drop) { if (inv_item->getType() == LLAssetType::AT_GESTURE && LLGestureMgr::instance().isGestureActive(inv_item->getUUID()) && move_is_into_trash) @@ -4117,9 +4039,27 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, active_panel->unSelectAll(); } + //-------------------------------------------------------------------------------- + // Destination folder logic + // + + /* Singu TODO: Favorites + // REORDER + // (only reorder the item in Favorites folder) + if ((mUUID == inv_item->getParentUUID()) && move_is_into_favorites) + { + LLFolderViewItem* itemp = destination_panel->getRootFolder()->getDraggingOverItem(); + if (itemp) + { + LLUUID srcItemId = inv_item->getUUID(); + LLUUID destItemId = itemp->getListener()->getUUID(); + gInventory.rearrangeFavoriteLandmarks(srcItemId, destItemId); + } + } + // FAVORITES folder // (copy the item) - if (move_is_into_favorites) + else */if (move_is_into_favorites) { dropToFavorites(inv_item); } @@ -4161,13 +4101,13 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, //-------------------------------------------------------------------------------- } } - else if(LLToolDragAndDrop::SOURCE_WORLD == source) + else if (LLToolDragAndDrop::SOURCE_WORLD == source) { // Make sure the object exists. If we allowed dragging from // anonymous objects, it would be possible to bypass // permissions. object = gObjectList.findObject(inv_item->getParentUUID()); - if(!object) + if (!object) { llinfos << "Object not found for drop." << llendl; return FALSE; @@ -4177,7 +4117,7 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, // move/copy this item. LLPermissions perm(inv_item->getPermissions()); BOOL is_move = FALSE; - if((perm.allowCopyBy(gAgent.getID(), gAgent.getGroupID()) + if ((perm.allowCopyBy(gAgent.getID(), gAgent.getGroupID()) && perm.allowTransferTo(gAgent.getID()))) // || gAgent.isGodlike()) { @@ -4227,12 +4167,12 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, { // store dad inventory item to select added one later. See EXT-4347 set_dad_inventory_item(inv_item, mUUID); + LLNotification::Params params("MoveInventoryFromObject"); params.functor(boost::bind(move_task_inventory_callback, _1, _2, move_inv)); LLNotifications::instance().forceResponse(params, 0); } } - } else if(LLToolDragAndDrop::SOURCE_NOTECARD == source) { @@ -4376,23 +4316,6 @@ void LLTextureBridge::openItem() } } -// virtual -void LLTextureBridge::performAction(LLInventoryModel* model, std::string action) -{ - // TODO - /*if ("save_as" == action) - { - LLFloaterReg::showInstance("preview_texture", LLSD(mUUID), TAKE_FOCUS_YES); - LLPreviewTexture* preview_texture = LLFloaterReg::findTypedInstance("preview_texture", mUUID); - if (preview_texture) - { - preview_texture->openToSave(); - } - } - else*/ - LLItemBridge::performAction(model, action); -} - void LLTextureBridge::buildContextMenu(LLMenuGL& menu, U32 flags) { lldebugs << "LLTextureBridge::buildContextMenu()" << llendl; @@ -4412,8 +4335,9 @@ void LLTextureBridge::buildContextMenu(LLMenuGL& menu, U32 flags) items.push_back(std::string("Properties")); getClipboardEntries(true, items, disabled_items, flags); - //TODO - /*items.push_back(std::string("Texture Separator")); + + /* Singu TODO + items.push_back(std::string("Texture Separator")); items.push_back(std::string("Save As")); if (!canSaveTexture()) { @@ -4423,6 +4347,21 @@ void LLTextureBridge::buildContextMenu(LLMenuGL& menu, U32 flags) hide_context_entries(menu, items, disabled_items); } +// virtual +void LLTextureBridge::performAction(LLInventoryModel* model, std::string action) +{ + /* Singu TODO + if ("save_as" == action) + { + LLFloaterReg::showInstance("preview_texture", LLSD(mUUID), TAKE_FOCUS_YES); + LLPreviewTexture* preview_texture = LLFloaterReg::findTypedInstance("preview_texture", mUUID); + if (preview_texture) + { + preview_texture->openToSave(); + } + } + else*/ LLItemBridge::performAction(model, action); +} // +=================================================+ // | LLSoundBridge | @@ -4430,8 +4369,8 @@ void LLTextureBridge::buildContextMenu(LLMenuGL& menu, U32 flags) void LLSoundBridge::openItem() { - LLViewerInventoryItem* item = getItem(); - if(item) + const LLViewerInventoryItem* item = getItem(); + if (item) { LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel()); } @@ -4553,6 +4492,7 @@ void LLLandmarkBridge::buildContextMenu(LLMenuGL& menu, U32 flags) { disabled_items.push_back(std::string("Teleport To Landmark")); } + hide_context_entries(menu, items, disabled_items); } @@ -4590,7 +4530,7 @@ void LLLandmarkBridge::performAction(LLInventoryModel* model, std::string action open_landmark(item, std::string(" Landmark: ") + item->getName(), FALSE); } } - else + else { LLItemBridge::performAction(model, action); } @@ -4660,9 +4600,9 @@ public: LLCallingCardObserver(LLCallingCardBridge* bridge) : mBridgep(bridge) {} virtual ~LLCallingCardObserver() { mBridgep = NULL; } virtual void changed(U32 mask) -{ - mBridgep->refreshFolderViewItem(); -} + { + mBridgep->refreshFolderViewItem(); + } protected: LLCallingCardBridge* mBridgep; }; @@ -4764,7 +4704,6 @@ void LLCallingCardBridge::openItem() void LLCallingCardBridge::buildContextMenu(LLMenuGL& menu, U32 flags) { - // *TODO: Translate lldebugs << "LLCallingCardBridge::buildContextMenu()" << llendl; menuentry_vec_t items; menuentry_vec_t disabled_items; @@ -4779,10 +4718,12 @@ void LLCallingCardBridge::buildContextMenu(LLMenuGL& menu, U32 flags) } else { + /* Singu Note: Multiple profiles get opened in a multifloater if ((flags & FIRST_SELECTED_ITEM) == 0) { disabled_items.push_back(std::string("Open")); } + */ addOpenRightClickMenuOption(items); items.push_back(std::string("Properties")); @@ -4859,7 +4800,7 @@ BOOL LLCallingCardBridge::dragOrDrop(MASK mask, BOOL drop, } break; } - case DAD_CATEGORY: + case DAD_CATEGORY: { LLInventoryCategory* inv_cat = (LLInventoryCategory*)cargo_data; if( gInventory.getCategory( inv_cat->getUUID() ) ) @@ -4881,8 +4822,8 @@ BOOL LLCallingCardBridge::dragOrDrop(MASK mask, BOOL drop, } break; } - default: - break; + default: + break; } } return rv; @@ -4956,7 +4897,6 @@ void LLNotecardBridge::openItem() } } - // +=================================================+ // | LLGestureBridge | // +=================================================+ @@ -5086,7 +5026,6 @@ BOOL LLGestureBridge::removeItem() void LLGestureBridge::buildContextMenu(LLMenuGL& menu, U32 flags) { - // *TODO: Translate lldebugs << "LLGestureBridge::buildContextMenu()" << llendl; menuentry_vec_t items; menuentry_vec_t disabled_items; @@ -5139,7 +5078,6 @@ void LLGestureBridge::playGesture(const LLUUID& item_id) void LLAnimationBridge::buildContextMenu(LLMenuGL& menu, U32 flags) { - // *TODO: Translate menuentry_vec_t items; menuentry_vec_t disabled_items; @@ -5168,7 +5106,6 @@ void LLAnimationBridge::buildContextMenu(LLMenuGL& menu, U32 flags) } hide_context_entries(menu, items, disabled_items); - } // virtual @@ -5177,28 +5114,28 @@ void LLAnimationBridge::performAction(LLInventoryModel* model, std::string actio if ((action == "playworld") || (action == "playlocal")) { // See if we can bring an existing preview to the front - if(LLPreview::show( mUUID )) + if (LLPreview::show(mUUID)) return; - if( getItem() ) + if (getItem()) { LLPreviewAnim::e_activation_type activate = LLPreviewAnim::NONE; if ("playworld" == action) activate = LLPreviewAnim::PLAY; if ("playlocal" == action) activate = LLPreviewAnim::AUDITION; - S32 left, top; - gFloaterView->getNewFloaterPosition(&left, &top); - LLRect rect = gSavedSettings.getRect("PreviewAnimRect"); - rect.translate( left - rect.mLeft, top - rect.mTop ); - LLPreviewAnim* preview = new LLPreviewAnim("preview anim", - rect, - "Animations: " + getItem()->getName(), - mUUID, - activate); - // Force to be entirely onscreen. - gFloaterView->adjustToFitScreen(preview, FALSE); - } + S32 left, top; + gFloaterView->getNewFloaterPosition(&left, &top); + LLRect rect = gSavedSettings.getRect("PreviewAnimRect"); + rect.translate( left - rect.mLeft, top - rect.mTop ); + LLPreviewAnim* preview = new LLPreviewAnim("preview anim", + rect, + "Animations: " + getItem()->getName(), + mUUID, + activate); + // Force to be entirely onscreen. + gFloaterView->adjustToFitScreen(preview, FALSE); } + } else { LLItemBridge::performAction(model, action); @@ -5243,7 +5180,7 @@ LLObjectBridge::LLObjectBridge(LLInventoryPanel* inventory, LLUIImagePtr LLObjectBridge::getIcon() const { - return LLInventoryIcon::getIcon(LLAssetType::AT_OBJECT, mInvType, mAttachPt, mIsMultiObject ); + return LLInventoryIcon::getIcon(LLAssetType::AT_OBJECT, mInvType, mAttachPt, mIsMultiObject); } LLInventoryObject* LLObjectBridge::getObject() const @@ -5267,7 +5204,7 @@ void LLObjectBridge::performAction(LLInventoryModel* model, std::string action) item = (LLViewerInventoryItem*)gInventory.getItem(object_id); if(item && gInventory.isObjectDescendentOf(object_id, gInventory.getRootFolderID())) { - rez_attachment(item, NULL, true); + rez_attachment(item, NULL, true); // Replace if "Wear"ing. } else if(item && item->isFinished()) { @@ -5293,52 +5230,7 @@ void LLObjectBridge::performAction(LLInventoryModel* model, std::string action) } else if ("edit" == action) { - if (gRlvHandler.hasBehaviour(RLV_BHVR_EDIT)) - return; - LLVOAvatar* avatarp = gAgentAvatarp; - if (!avatarp) - return; - LLViewerObject* objectp = avatarp->getWornAttachment(mUUID); - if (!objectp) - return; - - // [Selective copy/paste from LLObjectEdit::handleEvent()] - LLViewerParcelMgr::getInstance()->deselectLand(); - LLSelectMgr::getInstance()->deselectAll(); - - if (gAgentCamera.getFocusOnAvatar() && !LLToolMgr::getInstance()->inEdit()) - { - if (objectp->isHUDAttachment() || !gSavedSettings.getBOOL("EditCameraMovement")) - { - // always freeze camera in space, even if camera doesn't move - // so, for example, follow cam scripts can't affect you when in build mode - gAgentCamera.setFocusGlobal(gAgentCamera.calcFocusPositionTargetGlobal(), LLUUID::null); - gAgentCamera.setFocusOnAvatar(FALSE, ANIMATE); - } - else - { - gAgentCamera.setFocusOnAvatar(FALSE, ANIMATE); - - // zoom in on object center instead of where we clicked, as we need to see the manipulator handles - gAgentCamera.setFocusGlobal(objectp->getPositionGlobal(), objectp->getID()); - gAgentCamera.cameraZoomIn(0.666f); - gAgentCamera.cameraOrbitOver( 30.f * DEG_TO_RAD ); - gViewerWindow->moveCursorToCenter(); - } - } - - gFloaterTools->open(); - - LLToolMgr::getInstance()->setCurrentToolset(gBasicToolset); - gFloaterTools->setEditTool( LLToolCompTranslate::getInstance() ); - - LLViewerJoystick::getInstance()->moveObjects(true); - LLViewerJoystick::getInstance()->setNeedsReset(true); - - LLSelectMgr::getInstance()->selectObjectAndFamily(objectp); - - // Could be first use - LLFirstUse::useBuild(); + handle_attachment_edit(mUUID); } else LLItemBridge::performAction(model, action); } @@ -5359,25 +5251,14 @@ std::string LLObjectBridge::getLabelSuffix() const { return LLItemBridge::getLabelSuffix() + LLTrans::getString("worn"); } - bool unsupportedPoint = false; //Unsupported points are given special names, translate them as they're named, not later. std::string attachment_point_name = gAgentAvatarp->getAttachedPointName(mUUID); if (attachment_point_name == LLStringUtil::null) // Error condition, invalid attach point { attachment_point_name = "Invalid Attachment"; - std::map >::iterator iter = gAgentAvatarp->mUnsupportedAttachmentPoints.begin(); - std::map >::iterator end = gAgentAvatarp->mUnsupportedAttachmentPoints.end(); - for( ; iter != end; ++iter) - { - if((*iter).second.first == mUUID) - { - attachment_point_name = llformat((LLTrans::getString("unsupported point")+" %d)").c_str(), (*iter).first); - } - } - unsupportedPoint = attachment_point_name != "Invalid Attachment"; } // e.g. "(worn on ...)" / "(attached to ...)" LLStringUtil::format_map_t args; - args["[ATTACHMENT_POINT]"] = unsupportedPoint ? attachment_point_name : LLTrans::getString(attachment_point_name); + args["[ATTACHMENT_POINT]"] = LLTrans::getString(attachment_point_name); if(gRlvAttachmentLocks.canDetach(getItem())) return LLItemBridge::getLabelSuffix() + LLTrans::getString("WornOnAttachmentPoint", args); @@ -5464,7 +5345,7 @@ bool confirm_attachment_rez(const LLSD& notification, const LLSD& response) { LLUUID item_id = notification["payload"]["item_id"].asUUID(); LLViewerInventoryItem* itemp = gInventory.getItem(item_id); - + if (itemp) { /* @@ -5545,13 +5426,6 @@ void LLObjectBridge::buildContextMenu(LLMenuGL& menu, U32 flags) disabled_items.push_back(std::string("Detach From Yourself")); // [/RLVa:KB] } - else - // testzone attachpt - if( gAgentAvatarp->isWearingUnsupportedAttachment( mUUID ) ) - { - items.push_back(std::string("Detach From Yourself")); - } - // else if (!isItemInTrash() && !isLinkedObjectInTrash() && !isLinkedObjectMissing() && !isCOFFolder()) { items.push_back(std::string("Wearable And Object Separator")); @@ -5562,7 +5436,7 @@ void LLObjectBridge::buildContextMenu(LLMenuGL& menu, U32 flags) items.push_back(std::string("Attach To HUD")); // commented out for DEV-32347 - AND Commented back in for non-morons. -HgB items.push_back(std::string("Restore to Last Position")); - + if (!gAgentAvatarp->canAttachMoreObjects()) { disabled_items.push_back(std::string("Wearable And Object Wear")); @@ -5638,7 +5512,6 @@ BOOL LLObjectBridge::renameItem(const std::string& new_name) buildDisplayName(new_item, mDisplayName); new_item->updateServer(FALSE); model->updateItem(new_item); - model->notifyObservers(); if (isAgentAvatarValid()) @@ -5824,6 +5697,7 @@ std::string LLWearableBridge::getLabelSuffix() const { return LLItemBridge::getLabelSuffix() + LLTrans::getString("locked"); } + // e.g. "(worn)" return LLItemBridge::getLabelSuffix() + LLTrans::getString("worn"); } else @@ -5911,7 +5785,6 @@ void LLWearableBridge::openItem() void LLWearableBridge::buildContextMenu(LLMenuGL& menu, U32 flags) { - // *TODO: Translate lldebugs << "LLWearableBridge::buildContextMenu()" << llendl; menuentry_vec_t items; menuentry_vec_t disabled_items; @@ -5953,7 +5826,7 @@ void LLWearableBridge::buildContextMenu(LLMenuGL& menu, U32 flags) getClipboardEntries(true, items, disabled_items, flags); items.push_back(std::string("Wearable And Object Separator")); - + items.push_back(std::string("Wearable Edit")); /*// [RLVa:KB] - Checked: 2011-09-16 (RLVa-1.1.4a) | Added: RLVa-1.1.4a if ( (rlv_handler_t::isEnabled()) && (!gRlvWearableLocks.canRemove(item)) ) @@ -6071,6 +5944,7 @@ void LLWearableBridge::onWearOnAvatar(void* user_data) void LLWearableBridge::wearOnAvatar() { + // TODO: investigate wearables may not be loaded at this point EXT-8231 // Don't wear anything until initial wearables are loaded, can // destroy clothing items. if (!gAgentWearables.areWearablesLoaded()) @@ -6165,7 +6039,7 @@ BOOL LLWearableBridge::canEditOnAvatar(void* user_data) return (get_is_item_worn(self->mUUID)); } -// static +// static void LLWearableBridge::onEditOnAvatar(void* user_data) { LLWearableBridge* self = (LLWearableBridge*)user_data; @@ -6259,7 +6133,7 @@ void LLWearableBridge::removeFromAvatar() // +=================================================+ // | LLLinkItemBridge | // +=================================================+ -// For broken links +// For broken item links std::string LLLinkItemBridge::sPrefix("Link: "); @@ -6326,7 +6200,6 @@ void LLMeshBridge::previewItem() } } - void LLMeshBridge::buildContextMenu(LLMenuGL& menu, U32 flags) { lldebugs << "LLMeshBridge::buildContextMenu()" << llendl; @@ -6398,7 +6271,7 @@ void LLLinkFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags) { items.push_back(std::string("Find Original")); addDeleteContextMenuOptions(items, disabled_items); - } + } hide_context_entries(menu, items, disabled_items); } void LLLinkFolderBridge::performAction(LLInventoryModel* model, std::string action) @@ -6492,8 +6365,7 @@ class LLTextureBridgeAction: public LLInvFVBridgeAction public: virtual void doIt() { - LLViewerInventoryItem* item = getItem(); - if (item) + if (const LLViewerInventoryItem* item = getItem()) { open_texture(mUUID, std::string("Texture: ") + item->getName(), FALSE); } @@ -6550,7 +6422,7 @@ public: payload["asset_id"] = item->getAssetUUID(); payload["item_id"] = item->getUUID(); - + LLSD args; args["LOCATION"] = item->getName(); @@ -6641,7 +6513,6 @@ public: // See if we can bring an existing preview to the front if(!LLPreview::show( mUUID )) { - S32 left, top; gFloaterView->getNewFloaterPosition(&left, &top); LLRect rect = gSavedSettings.getRect("PreviewAnimRect"); @@ -6761,14 +6632,18 @@ void LLWearableBridgeAction::wearOnAvatar() { // TODO: investigate wearables may not be loaded at this point EXT-8231 - static LLCachedControl add(gSavedSettings, "LiruAddNotReplace"); LLViewerInventoryItem* item = getItem(); if(item) { if (get_is_item_worn(item)) + { LLAppearanceMgr::instance().removeItemFromAvatar(item->getUUID()); + } else + { + static LLCachedControl add(gSavedSettings, "LiruAddNotReplace"); LLAppearanceMgr::instance().wearItemOnAvatar(item->getUUID(), true, !add); + } } } @@ -6816,6 +6691,10 @@ LLInvFVBridgeAction* LLInvFVBridgeAction::createAction(LLAssetType::EType asset_ return action; } +/** Bridge Actions + ** + ********************************************************************************/ + /************************************************************************/ /* Recent Inventory Panel related classes */ /************************************************************************/ @@ -6840,27 +6719,14 @@ LLInvFVBridge* LLRecentInventoryBridgeBuilder::createBridge( U32 flags /*= 0x00*/ ) const { LLInvFVBridge* new_listener = NULL; - switch(asset_type) + if (asset_type == LLAssetType::AT_CATEGORY + && actual_asset_type != LLAssetType::AT_LINK_FOLDER) { - case LLAssetType::AT_CATEGORY: - if (actual_asset_type == LLAssetType::AT_LINK_FOLDER) - { - // *TODO: Create a link folder handler instead if it is necessary - new_listener = LLInventoryFVBridgeBuilder::createBridge( - asset_type, - actual_asset_type, - inv_type, - inventory, - root, - uuid, - flags); - break; - } new_listener = new LLRecentItemsFolderBridge(inv_type, inventory, root, uuid); - break; - default: - new_listener = LLInventoryFVBridgeBuilder::createBridge( - asset_type, + } + else + { + new_listener = LLInventoryFVBridgeBuilder::createBridge(asset_type, actual_asset_type, inv_type, inventory, @@ -6869,8 +6735,6 @@ LLInvFVBridge* LLRecentInventoryBridgeBuilder::createBridge( flags); } return new_listener; - } - // EOF diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index e863b878e..f854e8607 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -74,7 +74,6 @@ BOOL LLInventoryModel::sFirstTimeInViewer2 = TRUE; ///---------------------------------------------------------------------------- //BOOL decompress_file(const char* src_filename, const char* dst_filename); - const char CACHE_FORMAT_STRING[] = "%s.inv"; struct InventoryIDPtrLess @@ -531,8 +530,8 @@ private: LLUUID LLInventoryModel::createNewCategory(const LLUUID& parent_id, LLFolderType::EType preferred_type, const std::string& pname, - void (*callback)(const LLSD&, void*)/*=NULL*/, - void* user_data/*=NULL*/) + void (*callback)(const LLSD&, void*), //Default to NULL + void* user_data) //Default to NULL { LLUUID id; if(!isInventoryUsable()) @@ -1101,9 +1100,6 @@ void LLInventoryModel::changeItemParent(LLViewerInventoryItem* item, const LLUUID& new_parent_id, BOOL restamp) { - // - bool send_parent_update = gInventory.isObjectDescendentOf(item->getUUID(), gInventory.getRootFolderID()); - // if (item->getParentUUID() == new_parent_id) { LL_DEBUGS("Inventory") << "'" << item->getName() << "' (" << item->getUUID() @@ -1124,7 +1120,7 @@ void LLInventoryModel::changeItemParent(LLViewerInventoryItem* item, LLPointer new_item = new LLViewerInventoryItem(item); new_item->setParent(new_parent_id); // - if(send_parent_update) + if(gInventory.isObjectDescendentOf(item->getUUID(), gInventory.getRootFolderID())) // new_item->updateParentOnServer(restamp); updateItem(new_item); @@ -1255,7 +1251,7 @@ void LLInventoryModel::purgeDescendentsOf(const LLUUID& id) return; } LLPointer cat = getCategory(id); - if(cat.notNull()) + if (cat.notNull()) { if (LLInventoryClipboard::instance().hasContents() && LLInventoryClipboard::instance().isCutMode()) { @@ -1291,7 +1287,7 @@ void LLInventoryModel::purgeDescendentsOf(const LLUUID& id) // Fast purge // do the cache accounting llinfos << "LLInventoryModel::purgeDescendentsOf " << cat->getName() - << llendl; + << llendl; S32 descendents = cat->getDescendentCount(); if(descendents > 0) { @@ -1326,6 +1322,7 @@ void LLInventoryModel::purgeDescendentsOf(const LLUUID& id) { deleteObject(items.get(i)->getUUID()); } + count = categories.count(); for(S32 i = 0; i < count; ++i) { @@ -1378,7 +1375,6 @@ void LLInventoryModel::notifyObservers() iter != mObservers.end(); ) { LLInventoryObserver* observer = *iter; - observer->changed(mModifyMask); // safe way to increment since changed may delete entries! (@!##%@!@&*!) @@ -1564,7 +1560,7 @@ void LLInventoryModel::addCategory(LLViewerInventoryCategory* category) } // try to localize default names first. See EXT-8319, EXT-7051. - //category->localizeName(); + category->localizeName(); // Insert category uniquely into the map mCategoryMap[category->getUUID()] = category; // LLPointer will deref and delete the old one @@ -1644,7 +1640,7 @@ void LLInventoryModel::accountForUpdate(const LLCategoryUpdate& update) const cat->setVersion(++version); lldebugs << "accounted: '" << cat->getName() << "' " << version << " with " << descendents_actual - << " descendents." << llendl; + << " descendents." << llendl; } } if(!accounted) @@ -1891,7 +1887,7 @@ bool LLInventoryModel::loadSkeleton( LLViewerInventoryCategory* tcat = *cit; // we can safely ignore anything loaded from file, but - // not sent down in the skeleton. + // not sent down in the skeleton. Must have been removed from inventory. if (cit == not_cached) { continue; @@ -2352,73 +2348,6 @@ bool LLUUIDAndName::operator>(const LLUUIDAndName& rhs) const return (mID > rhs.mID); } -// Given the current state of the inventory items, figure out the -// clone information. *FIX: This is sub-optimal, since we can insert -// this information snurgically, but this makes sure the implementation -// works before we worry about optimization. -//void LLInventoryModel::recalculateCloneInformation() -//{ -// //dumpInventory(); -// -// // This implements a 'multi-map' like structure to keep track of -// // how many clones we find. -// typedef LLDynamicArray viewer_item_array_t; -// typedef std::map clone_map_t; -// clone_map_t clone_map; -// LLUUIDAndName id_and_name; -// viewer_item_array_t* clones = NULL; -// LLViewerInventoryItem* item = NULL; -// for(item = (LLViewerInventoryItem*)mItemMap.getFirstData(); -// item != NULL; -// item = (LLViewerInventoryItem*)mItemMap.getNextData()) -// { -// if(item->getType() == LLAssetType::AT_CALLINGCARD) -// { -// // if it's a calling card, we key off of the creator id, not -// // the asset id. -// id_and_name.mID = item->getCreatorUUID(); -// } -// else -// { -// // if it's not a calling card, we key clones from the -// // asset id. -// id_and_name.mID = item->getAssetUUID(); -// } -// if(id_and_name.mID == LLUUID::null) -// { -// continue; -// } -// id_and_name.mName = item->getName(); -// if(clone_map.checkData(id_and_name)) -// { -// clones = clone_map.getData(id_and_name); -// } -// else -// { -// clones = new viewer_item_array_t; -// clone_map.addData(id_and_name, clones); -// } -// clones->put(item); -// } -// -// S32 count = 0; -// for(clones = clone_map.getFirstData(); -// clones != NULL; -// clones = clone_map.getNextData()) -// { -// count = clones->count(); -// for(S32 i = 0; i < count; i++) -// { -// item = clones->get(i); -// item->setCloneCount(count - 1); -// //clones[i] = NULL; -// } -// delete clones; -// } -// clone_map.removeAllData(); -// //dumpInventory(); -//} - // static bool LLInventoryModel::loadFromFile(const std::string& filename, LLInventoryModel::cat_array_t& categories, @@ -2481,7 +2410,7 @@ bool LLInventoryModel::loadFromFile(const std::string& filename, { if (is_cache_obsolete) break; - + LLPointer inv_item = new LLViewerInventoryItem; if( inv_item->importFileLocal(file) ) { @@ -3003,7 +2932,7 @@ void LLInventoryModel::processBulkUpdateInventory(LLMessageSystem* msg, void**) // << titem->getParentUUID() << llendl; U32 callback_id; msg->getU32Fast(_PREHASH_ItemData, _PREHASH_CallbackID, callback_id); - if(titem->getUUID().notNull()) + if(titem->getUUID().notNull() ) // && callback_id.notNull() ) { items.push_back(titem); cblist.push_back(InventoryCallbackInfo(callback_id, titem->getUUID())); @@ -3117,6 +3046,7 @@ void LLInventoryModel::processInventoryDescendents(LLMessageSystem* msg,void**) msg->getS32("AgentData", "Version", version); S32 descendents; msg->getS32("AgentData", "Descendents", descendents); + S32 i; S32 count = msg->getNumberOfBlocksFast(_PREHASH_FolderData); LLPointer tcategory = new LLViewerInventoryCategory(owner_id); @@ -3422,7 +3352,8 @@ void LLInventoryModel::updateItemsOrder(LLInventoryModel::item_array_t& items, c } //* @param[in] items vector of items in order to be saved. -/*void LLInventoryModel::saveItemsOrder(const LLInventoryModel::item_array_t& items) +/* +void LLInventoryModel::saveItemsOrder(const LLInventoryModel::item_array_t& items) { int sortField = 0; @@ -3442,8 +3373,8 @@ void LLInventoryModel::updateItemsOrder(LLInventoryModel::item_array_t& items, c } notifyObservers(); -}*/ - +} +*/ // See also LLInventorySort where landmarks in the Favorites folder are sorted. /*class LLViewerInventoryItemSort { @@ -3467,7 +3398,8 @@ public: // * @param source_item_id - LLUUID of the source item to be moved into new position // * @param target_item_id - LLUUID of the target item before which source item should be placed. -/*void LLInventoryModel::rearrangeFavoriteLandmarks(const LLUUID& source_item_id, const LLUUID& target_item_id) +/* +void LLInventoryModel::rearrangeFavoriteLandmarks(const LLUUID& source_item_id, const LLUUID& target_item_id) { LLInventoryModel::cat_array_t cats; LLInventoryModel::item_array_t items; @@ -3482,7 +3414,10 @@ public: updateItemsOrder(items, source_item_id, target_item_id); saveItemsOrder(items); -}*/ +} +*/ +//---------------------------------------------------------------------------- + // *NOTE: DEBUG functionality void LLInventoryModel::dumpInventory() const { @@ -3494,8 +3429,8 @@ void LLInventoryModel::dumpInventory() const if(cat) { llinfos << " " << cat->getUUID() << " '" << cat->getName() << "' " - << cat->getVersion() << " " << cat->getDescendentCount() << " parent: " << cat->getParentUUID() - << LL_ENDL; + << cat->getVersion() << " " << cat->getDescendentCount() << " parent: " << cat->getParentUUID() + << llendl; } else { diff --git a/indra/newview/llinventorymodelbackgroundfetch.cpp b/indra/newview/llinventorymodelbackgroundfetch.cpp index 6b88ab5c5..272a0aad8 100644 --- a/indra/newview/llinventorymodelbackgroundfetch.cpp +++ b/indra/newview/llinventorymodelbackgroundfetch.cpp @@ -37,6 +37,7 @@ #include "llviewermessage.h" #include "llviewerregion.h" #include "llviewerwindow.h" +#include "hippogridmanager.h" class AIHTTPTimeoutPolicy; extern AIHTTPTimeoutPolicy inventoryModelFetchDescendentsResponder_timeout; @@ -115,7 +116,6 @@ void LLInventoryModelBackgroundFetch::start(const LLUUID& id, BOOL recursive) { // it's a folder, do a bulk fetch LL_DEBUGS("InventoryFetch") << "Start fetching category: " << id << ", recursive: " << recursive << LL_ENDL; - mBackgroundFetchActive = TRUE; mFolderFetchActive = true; if (id.isNull()) { @@ -124,12 +124,14 @@ void LLInventoryModelBackgroundFetch::start(const LLUUID& id, BOOL recursive) mRecursiveInventoryFetchStarted |= recursive; mFetchQueue.push_back(FetchQueueInfo(gInventory.getRootFolderID(), recursive)); gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL); + mBackgroundFetchActive = TRUE; } if (!mRecursiveLibraryFetchStarted) { mRecursiveLibraryFetchStarted |= recursive; mFetchQueue.push_back(FetchQueueInfo(gInventory.getLibraryRootFolderID(), recursive)); gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL); + mBackgroundFetchActive = TRUE; } } else @@ -139,6 +141,7 @@ void LLInventoryModelBackgroundFetch::start(const LLUUID& id, BOOL recursive) { mFetchQueue.push_front(FetchQueueInfo(id, recursive)); gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL); + mBackgroundFetchActive = TRUE; } if (id == gInventory.getLibraryRootFolderID()) { @@ -178,6 +181,11 @@ void LLInventoryModelBackgroundFetch::setAllFoldersFetched() mAllFoldersFetched = TRUE; } mFolderFetchActive = false; + if (mBackgroundFetchActive) + { + gIdleCallbacks.deleteFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL); + mBackgroundFetchActive = FALSE; + } } void LLInventoryModelBackgroundFetch::backgroundFetchCB(void *) @@ -190,14 +198,27 @@ void LLInventoryModelBackgroundFetch::backgroundFetch() LLViewerRegion* region = gAgent.getRegion(); if (mBackgroundFetchActive && region && region->capabilitiesReceived()) { - // If we'll be using the capability, we'll be sending batches and the background thing isn't as important. - std::string url = region->getCapability("FetchInventory2"); - if (gSavedSettings.getBOOL("UseHTTPInventory") && !url.empty()) + if (gSavedSettings.getBOOL("UseHTTPInventory")) { - bulkFetch(); - return; - } - + // If we'll be using the capability, we'll be sending batches and the background thing isn't as important. + std::string url = region->getCapability("FetchInventory2"); + if (!url.empty()) + { + if (!mPerServicePtr) + { + // One time initialization needed for bulkFetch(). + std::string servicename = AIPerService::extract_canonical_servicename(url); + if (!servicename.empty()) + { + llinfos << "Initialized service name for bulk inventory fetching with \"" << servicename << "\"." << llendl; + mPerServicePtr = AIPerService::instance(servicename); + } + } + bulkFetch(); + return; + } + } + #if 1 //-------------------------------------------------------------------------------- // DEPRECATED OLD CODE @@ -207,10 +228,7 @@ void LLInventoryModelBackgroundFetch::backgroundFetch() if (mFetchQueue.empty()) { llinfos << "Inventory fetch completed" << llendl; - setAllFoldersFetched(); - mBackgroundFetchActive = false; - mFolderFetchActive = false; return; } @@ -395,7 +413,6 @@ class LLInventoryModelFetchDescendentsResponder : public LLHTTPClient::Responder mRequestSD(request_sd), mRecursiveCatUUIDs(recursive_cats) {}; - //LLInventoryModelFetchDescendentsResponder() {}; /*virtual*/ void result(const LLSD& content); /*virtual*/ void error(U32 status, const std::string& reason); /*virtual*/ AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return inventoryModelFetchDescendentsResponder_timeout; } @@ -575,28 +592,20 @@ BOOL LLInventoryModelFetchDescendentsResponder::getIsRecursive(const LLUUID& cat } // Bundle up a bunch of requests to send all at once. -// static void LLInventoryModelBackgroundFetch::bulkFetch() { //Background fetch is called from gIdleCallbacks in a loop until background fetch is stopped. //If there are items in mFetchQueue, we want to check the time since the last bulkFetch was //sent. If it exceeds our retry time, go ahead and fire off another batch. LLViewerRegion* region = gAgent.getRegion(); - if (!region) return; + if (gDisconnected || !region) return; - S16 max_concurrent_fetches=8; - F32 new_min_time = 0.5f; //HACK! Clean this up when old code goes away entirely. - if (mMinTimeBetweenFetches < new_min_time) + static LLCachedControl const throttle_bandwidth("HTTPThrottleBandwidth", 2000); + bool const no_bandwidth_throttling = gHippoGridManager->getConnectedGrid()->isAvination(); + if (!AIPerService::wantsMoreHTTPRequestsFor(mPerServicePtr, throttle_bandwidth, no_bandwidth_throttling)) { - mMinTimeBetweenFetches=new_min_time; //HACK! See above. + return; // Wait. } - - if (gDisconnected || - (mFetchCount > max_concurrent_fetches) || - (mFetchTimer.getElapsedTimeF32() < mMinTimeBetweenFetches)) - { - return; // just bail if we are disconnected - } U32 item_count=0; U32 folder_count=0; @@ -708,6 +717,7 @@ void LLInventoryModelBackgroundFetch::bulkFetch() { mFetchCount++; url = region->getCapability("FetchInventory2"); + llassert(!url.empty()); if (!url.empty()) { LLSD body; @@ -716,18 +726,6 @@ void LLInventoryModelBackgroundFetch::bulkFetch() LLHTTPClient::post(url, body, new LLInventoryModelFetchItemResponder(body)); } - //else - //{ - // LLMessageSystem* msg = gMessageSystem; - // msg->newMessage("FetchInventory"); - // msg->nextBlock("AgentData"); - // msg->addUUID("AgentID", gAgent.getID()); - // msg->addUUID("SessionID", gAgent.getSessionID()); - // msg->nextBlock("InventoryData"); - // msg->addUUID("OwnerID", mPermissions.getOwner()); - // msg->addUUID("ItemID", mUUID); - // gAgent.sendReliableMessage(); - //} } if (item_request_body_lib.size()) @@ -735,6 +733,7 @@ void LLInventoryModelBackgroundFetch::bulkFetch() mFetchCount++; url = region->getCapability("FetchLib2"); + llassert(!url.empty()); if (!url.empty()) { LLSD body; @@ -750,6 +749,7 @@ void LLInventoryModelBackgroundFetch::bulkFetch() else if (isBulkFetchProcessingComplete()) { + llinfos << "Inventory fetch completed" << llendl; setAllFoldersFetched(); } } diff --git a/indra/newview/llinventorymodelbackgroundfetch.h b/indra/newview/llinventorymodelbackgroundfetch.h index bc40cc5cb..4056bdfbd 100644 --- a/indra/newview/llinventorymodelbackgroundfetch.h +++ b/indra/newview/llinventorymodelbackgroundfetch.h @@ -29,6 +29,7 @@ #include "llsingleton.h" #include "lluuid.h" +#include "aicurlperservice.h" //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Class LLInventoryModelBackgroundFetch @@ -75,12 +76,14 @@ private: BOOL mRecursiveLibraryFetchStarted; BOOL mAllFoldersFetched; - BOOL mBackgroundFetchActive; + BOOL mBackgroundFetchActive; // TRUE if LLInventoryModelBackgroundFetch::backgroundFetchCB is being called from idle(). bool mFolderFetchActive; S16 mFetchCount; BOOL mTimelyFetchPending; S32 mNumFetchRetries; + AIPerServicePtr mPerServicePtr; // Pointer to the AIPerService corresponding to the FetchInventory2 capability. + LLFrameTimer mFetchTimer; F32 mMinTimeBetweenFetches; F32 mMaxTimeBetweenFetches; diff --git a/indra/newview/llinventoryobserver.cpp b/indra/newview/llinventoryobserver.cpp index 887f0a474..9db175ec2 100644 --- a/indra/newview/llinventoryobserver.cpp +++ b/indra/newview/llinventoryobserver.cpp @@ -102,12 +102,12 @@ void LLInventoryCompletionObserver::changed(U32 mask) { // scan through the incomplete items and move or erase them as // appropriate. - if(!mIncomplete.empty()) + if (!mIncomplete.empty()) { - for(uuid_vec_t::iterator it = mIncomplete.begin(); it < mIncomplete.end(); ) + for (uuid_vec_t::iterator it = mIncomplete.begin(); it < mIncomplete.end(); ) { - LLViewerInventoryItem* item = gInventory.getItem(*it); - if(!item) + const LLViewerInventoryItem* item = gInventory.getItem(*it); + if (!item) { it = mIncomplete.erase(it); continue; @@ -120,7 +120,7 @@ void LLInventoryCompletionObserver::changed(U32 mask) } ++it; } - if(mIncomplete.empty()) + if (mIncomplete.empty()) { done(); } @@ -129,7 +129,7 @@ void LLInventoryCompletionObserver::changed(U32 mask) void LLInventoryCompletionObserver::watchItem(const LLUUID& id) { - if(id.notNull()) + if (id.notNull()) { mIncomplete.push_back(id); } @@ -158,6 +158,7 @@ void LLInventoryFetchItemsObserver::changed(U32 mask) // appropriate. if (!mIncomplete.empty()) { + // Have we exceeded max wait time? bool timeout_expired = mFetchingPeriod.hasExpired(); @@ -201,6 +202,7 @@ void LLInventoryFetchItemsObserver::changed(U32 mask) void fetch_items_from_llsd(const LLSD& items_llsd) { if (!items_llsd.size() || gDisconnected) return; + LLSD body; body[0]["cap_name"] = "FetchInventory2"; body[1]["cap_name"] = "FetchLib2"; @@ -244,7 +246,7 @@ void fetch_items_from_llsd(const LLSD& items_llsd) for (S32 j=0; jnewMessageFast(_PREHASH_FetchInventory); @@ -255,13 +257,13 @@ void fetch_items_from_llsd(const LLSD& items_llsd) msg->nextBlockFast(_PREHASH_InventoryData); msg->addUUIDFast(_PREHASH_OwnerID, item_entry["owner_id"].asUUID()); msg->addUUIDFast(_PREHASH_ItemID, item_entry["item_id"].asUUID()); - if(msg->isSendFull(NULL)) + if (msg->isSendFull(NULL)) { start_new_message = TRUE; gAgent.sendReliableMessage(); } } - if(!start_new_message) + if (!start_new_message) { gAgent.sendReliableMessage(); } @@ -335,8 +337,8 @@ void LLInventoryFetchDescendentsObserver::changed(U32 mask) { for (uuid_vec_t::iterator it = mIncomplete.begin(); it < mIncomplete.end();) { - LLViewerInventoryCategory* cat = gInventory.getCategory(*it); - if(!cat) + const LLViewerInventoryCategory* cat = gInventory.getCategory(*it); + if (!cat) { it = mIncomplete.erase(it); continue; @@ -465,7 +467,7 @@ void LLInventoryFetchComboObserver::startFetch() void LLInventoryExistenceObserver::watchItem(const LLUUID& id) { - if(id.notNull()) + if (id.notNull()) { mMIA.push_back(id); } @@ -475,12 +477,12 @@ void LLInventoryExistenceObserver::changed(U32 mask) { // scan through the incomplete items and move or erase them as // appropriate. - if(!mMIA.empty()) + if (!mMIA.empty()) { - for(uuid_vec_t::iterator it = mMIA.begin(); it < mMIA.end(); ) + for (uuid_vec_t::iterator it = mMIA.begin(); it < mMIA.end(); ) { LLViewerInventoryItem* item = gInventory.getItem(*it); - if(!item) + if (!item) { ++it; continue; @@ -488,7 +490,7 @@ void LLInventoryExistenceObserver::changed(U32 mask) mExist.push_back(*it); it = mMIA.erase(it); } - if(mMIA.empty()) + if (mMIA.empty()) { done(); } @@ -589,7 +591,7 @@ void LLInventoryAddedObserver::changed(U32 mask) LLPointer titem = new LLViewerInventoryItem; S32 num_blocks = msg->getNumberOfBlocksFast(_PREHASH_InventoryData); - for(S32 i = 0; i < num_blocks; ++i) + for (S32 i = 0; i < num_blocks; ++i) { titem->unpackMessage(msg, _PREHASH_InventoryData, i); if (!(titem->getUUID().isNull())) @@ -639,18 +641,18 @@ LLInventoryTransactionObserver::LLInventoryTransactionObserver(const LLTransacti void LLInventoryTransactionObserver::changed(U32 mask) { - if(mask & LLInventoryObserver::ADD) + if (mask & LLInventoryObserver::ADD) { // This could be it - see if we are processing a bulk update LLMessageSystem* msg = gMessageSystem; - if(msg->getMessageName() + if (msg->getMessageName() && (0 == strcmp(msg->getMessageName(), "BulkUpdateInventory"))) { // we have a match for the message - now check the // transaction id. LLUUID id; msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_TransactionID, id); - if(id == mTransactionID) + if (id == mTransactionID) { // woo hoo, we found it uuid_vec_t folders; @@ -658,19 +660,19 @@ void LLInventoryTransactionObserver::changed(U32 mask) S32 count; count = msg->getNumberOfBlocksFast(_PREHASH_FolderData); S32 i; - for(i = 0; i < count; ++i) + for (i = 0; i < count; ++i) { msg->getUUIDFast(_PREHASH_FolderData, _PREHASH_FolderID, id, i); - if(id.notNull()) + if (id.notNull()) { folders.push_back(id); } } count = msg->getNumberOfBlocksFast(_PREHASH_ItemData); - for(i = 0; i < count; ++i) + for (i = 0; i < count; ++i) { msg->getUUIDFast(_PREHASH_ItemData, _PREHASH_ItemID, id, i); - if(id.notNull()) + if (id.notNull()) { items.push_back(id); } diff --git a/indra/newview/llmarketplacefunctions.cpp b/indra/newview/llmarketplacefunctions.cpp index 7db143bc2..ed7c774c8 100644 --- a/indra/newview/llmarketplacefunctions.cpp +++ b/indra/newview/llmarketplacefunctions.cpp @@ -166,20 +166,25 @@ namespace LLMarketplaceImport llinfos << " SLM POST status: " << status << llendl; llinfos << " SLM POST reason: " << reason << llendl; llinfos << " SLM POST content: " << content.asString() << llendl; - llinfos << " SLM POST timer: " << slmPostTimer.getElapsedTimeF32() << llendl; } - if ((status == MarketplaceErrorCodes::IMPORT_REDIRECT) || - (status == MarketplaceErrorCodes::IMPORT_AUTHENTICATION_ERROR) || - (status == MarketplaceErrorCodes::IMPORT_JOB_LOW_SPEED) || - (status == MarketplaceErrorCodes::IMPORT_JOB_TIMEOUT)) + // MAINT-2301 : we determined we can safely ignore that error in that context + if (status == MarketplaceErrorCodes::IMPORT_JOB_TIMEOUT) { if (gSavedSettings.getBOOL("InventoryOutboxLogging")) { - llinfos << " SLM POST clearing marketplace cookie due to authentication failure or timeout" << llendl; + llinfos << " SLM POST : Ignoring time out status and treating it as success" << llendl; } + status = MarketplaceErrorCodes::IMPORT_DONE; + } + if (status >= MarketplaceErrorCodes::IMPORT_BAD_REQUEST) + { + if (gSavedSettings.getBOOL("InventoryOutboxLogging")) + { + llinfos << " SLM POST clearing marketplace cookie due to client or server error" << llendl; + } sMarketplaceCookie.clear(); } @@ -224,21 +229,23 @@ namespace LLMarketplaceImport llinfos << " SLM GET status: " << status << llendl; llinfos << " SLM GET reason: " << reason << llendl; llinfos << " SLM GET content: " << content.asString() << llendl; - llinfos << " SLM GET timer: " << slmGetTimer.getElapsedTimeF32() << llendl; } - if ((status == MarketplaceErrorCodes::IMPORT_AUTHENTICATION_ERROR) || - (status == MarketplaceErrorCodes::IMPORT_JOB_LOW_SPEED) || - (status == MarketplaceErrorCodes::IMPORT_JOB_TIMEOUT)) + // MAINT-2452 : Do not clear the cookie on IMPORT_DONE_WITH_ERRORS + if ((status >= MarketplaceErrorCodes::IMPORT_BAD_REQUEST) && + (status != MarketplaceErrorCodes::IMPORT_DONE_WITH_ERRORS)) { if (gSavedSettings.getBOOL("InventoryOutboxLogging")) { - llinfos << " SLM GET clearing marketplace cookie due to authentication failure or timeout (" << status << " / " << reason << ")." << llendl; + llinfos << " SLM GET clearing marketplace cookie due to client or server error (" << status << " / " << reason << ")." << llendl; } - sMarketplaceCookie.clear(); } + else if (gSavedSettings.getBOOL("InventoryOutboxLogging") && (status == MarketplaceErrorCodes::IMPORT_DONE_WITH_ERRORS)) + { + llinfos << " SLM GET : Got IMPORT_DONE_WITH_ERRORS, marketplace cookie not cleared." << llendl; + } sImportInProgress = (status == MarketplaceErrorCodes::IMPORT_PROCESSING); sImportGetPending = false; @@ -334,7 +341,9 @@ namespace LLMarketplaceImport if (gSavedSettings.getBOOL("InventoryOutboxLogging")) { - llinfos << " SLM GET: " << url << llendl; + llinfos << " SLM GET: pollStatus, LLHTTPClient::get, url = " << url << llendl; + llinfos << " SLM GET: headers " << llendl; + llinfos << headers << llendl; } slmGetTimer.start(); @@ -368,7 +377,9 @@ namespace LLMarketplaceImport if (gSavedSettings.getBOOL("InventoryOutboxLogging")) { - llinfos << " SLM POST: " << url << llendl; + llinfos << " SLM POST: triggerImport, LLHTTPClient::post, url = " << url << llendl; + llinfos << " SLM POST: headers " << llendl; + llinfos << headers << llendl; } slmPostTimer.start(); @@ -404,6 +415,7 @@ LLMarketplaceInventoryImporter::LLMarketplaceInventoryImporter() : mAutoTriggerImport(false) , mImportInProgress(false) , mInitialized(false) + , mMarketPlaceStatus(MarketplaceStatusCodes::MARKET_PLACE_NOT_INITIALIZED) , mErrorInitSignal(NULL) , mStatusChangedSignal(NULL) , mStatusReportSignal(NULL) @@ -446,16 +458,20 @@ void LLMarketplaceInventoryImporter::initialize() if (!LLMarketplaceImport::hasSessionCookie()) { + mMarketPlaceStatus = MarketplaceStatusCodes::MARKET_PLACE_INITIALIZING; LLMarketplaceImport::establishMarketplaceSessionCookie(); } + else + { + mMarketPlaceStatus = MarketplaceStatusCodes::MARKET_PLACE_MERCHANT; + } } void LLMarketplaceInventoryImporter::reinitializeAndTriggerImport() { mInitialized = false; - + mMarketPlaceStatus = MarketplaceStatusCodes::MARKET_PLACE_NOT_INITIALIZED; initialize(); - mAutoTriggerImport = true; } @@ -507,17 +523,30 @@ void LLMarketplaceInventoryImporter::updateImport() if (mInitialized) { + mMarketPlaceStatus = MarketplaceStatusCodes::MARKET_PLACE_MERCHANT; // Follow up with auto trigger of import if (mAutoTriggerImport) { mAutoTriggerImport = false; - mImportInProgress = triggerImport(); } } - else if (mErrorInitSignal) + else { - (*mErrorInitSignal)(LLMarketplaceImport::getResultStatus(), LLMarketplaceImport::getResults()); + U32 status = LLMarketplaceImport::getResultStatus(); + if ((status == MarketplaceErrorCodes::IMPORT_FORBIDDEN) || + (status == MarketplaceErrorCodes::IMPORT_AUTHENTICATION_ERROR)) + { + mMarketPlaceStatus = MarketplaceStatusCodes::MARKET_PLACE_NOT_MERCHANT; + } + else + { + mMarketPlaceStatus = MarketplaceStatusCodes::MARKET_PLACE_CONNECTION_FAILURE; + } + if (mErrorInitSignal && (mMarketPlaceStatus == MarketplaceStatusCodes::MARKET_PLACE_CONNECTION_FAILURE)) + { + (*mErrorInitSignal)(LLMarketplaceImport::getResultStatus(), LLMarketplaceImport::getResults()); + } } } } diff --git a/indra/newview/llmarketplacefunctions.h b/indra/newview/llmarketplacefunctions.h index af7c864c0..4e9e6ee81 100644 --- a/indra/newview/llmarketplacefunctions.h +++ b/indra/newview/llmarketplacefunctions.h @@ -48,11 +48,28 @@ namespace MarketplaceErrorCodes IMPORT_DONE = HTTP_OK, IMPORT_PROCESSING = HTTP_ACCEPTED, IMPORT_REDIRECT = HTTP_FOUND, + IMPORT_BAD_REQUEST = HTTP_BAD_REQUEST, IMPORT_AUTHENTICATION_ERROR = HTTP_UNAUTHORIZED, + IMPORT_FORBIDDEN = HTTP_FORBIDDEN, + IMPORT_NOT_FOUND = HTTP_NOT_FOUND, IMPORT_DONE_WITH_ERRORS = HTTP_CONFLICT, IMPORT_JOB_FAILED = HTTP_GONE, IMPORT_JOB_LOW_SPEED = HTTP_INTERNAL_ERROR_LOW_SPEED, - IMPORT_JOB_TIMEOUT = HTTP_INTERNAL_ERROR_CURL_TIMEOUT + IMPORT_JOB_TIMEOUT = HTTP_INTERNAL_ERROR_CURL_TIMEOUT, + IMPORT_SERVER_SITE_DOWN = HTTP_INTERNAL_SERVER_ERROR, + IMPORT_SERVER_API_DISABLED = HTTP_SERVICE_UNAVAILABLE, + }; +} + +namespace MarketplaceStatusCodes +{ + enum sCode + { + MARKET_PLACE_NOT_INITIALIZED = 0, + MARKET_PLACE_INITIALIZING = 1, + MARKET_PLACE_CONNECTION_FAILURE = 2, + MARKET_PLACE_MERCHANT = 3, + MARKET_PLACE_NOT_MERCHANT = 4, }; } @@ -75,6 +92,7 @@ public: void initialize(); bool triggerImport(); bool isImportInProgress() const { return mImportInProgress; } + U32 getMarketPlaceStatus() const { return mMarketPlaceStatus; } protected: void reinitializeAndTriggerImport(); @@ -84,6 +102,7 @@ private: bool mAutoTriggerImport; bool mImportInProgress; bool mInitialized; + U32 mMarketPlaceStatus; status_report_signal_t * mErrorInitSignal; status_changed_signal_t * mStatusChangedSignal; diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp index 88f6c8e38..1c70e6fae 100644 --- a/indra/newview/llmeshrepository.cpp +++ b/indra/newview/llmeshrepository.cpp @@ -1329,9 +1329,10 @@ void LLMeshUploadThread::preStart() } AIMeshUpload::AIMeshUpload(LLMeshUploadThread::instance_list& data, LLVector3& scale, bool upload_textures, bool upload_skin, bool upload_joints, std::string const& upload_url, bool do_upload, - LLHandle const& fee_observer, LLHandle const& upload_observer) : mWholeModelUploadURL(upload_url) + LLHandle const& fee_observer, LLHandle const& upload_observer) : + mMeshUpload(new AIStateMachineThread), mWholeModelUploadURL(upload_url) { - mMeshUpload->init(data, scale, upload_textures, upload_skin, upload_joints, do_upload, fee_observer, upload_observer); + mMeshUpload->thread_impl().init(data, scale, upload_textures, upload_skin, upload_joints, do_upload, fee_observer, upload_observer); } char const* AIMeshUpload::state_str_impl(state_type run_state) const @@ -1347,7 +1348,7 @@ char const* AIMeshUpload::state_str_impl(state_type run_state) const void AIMeshUpload::initialize_impl() { - mMeshUpload->preStart(); + mMeshUpload->thread_impl().preStart(); set_state(AIMeshUpload_start); } @@ -1356,11 +1357,11 @@ void AIMeshUpload::multiplex_impl(state_type run_state) switch (run_state) { case AIMeshUpload_start: - mMeshUpload.run(this, AIMeshUpload_threadFinished); + mMeshUpload->run(this, AIMeshUpload_threadFinished); idle(); // Wait till the thread finished. break; case AIMeshUpload_threadFinished: - mMeshUpload->postRequest(mWholeModelUploadURL, this); + mMeshUpload->thread_impl().postRequest(mWholeModelUploadURL, this); idle(); // Wait till the responder finished. break; case AIMeshUpload_responderFinished: diff --git a/indra/newview/llmeshrepository.h b/indra/newview/llmeshrepository.h index d26316a85..ce79f9506 100644 --- a/indra/newview/llmeshrepository.h +++ b/indra/newview/llmeshrepository.h @@ -433,7 +433,7 @@ enum AIMeshUpload_state_type { class AIMeshUpload : public AIStateMachine { private: - AIStateMachineThread mMeshUpload; + LLPointer > mMeshUpload; std::string mWholeModelUploadURL; public: diff --git a/indra/newview/llpanellogin.cpp b/indra/newview/llpanellogin.cpp index c8b674fac..f2523b505 100644 --- a/indra/newview/llpanellogin.cpp +++ b/indra/newview/llpanellogin.cpp @@ -113,10 +113,10 @@ static bool nameSplit(const std::string& full, std::string& first, std::string& first = fragments[0]; if (fragments.size() == 1) { - if (gHippoGridManager->getConnectedGrid()->isSecondLife()) - last = "Resident"; - else + if (gHippoGridManager->getConnectedGrid()->isAurora()) last = ""; + else + last = "Resident"; } else last = fragments[1]; diff --git a/indra/newview/llpanelmsgs.cpp b/indra/newview/llpanelmsgs.cpp index e1afe8a1f..95bb24e0a 100644 --- a/indra/newview/llpanelmsgs.cpp +++ b/indra/newview/llpanelmsgs.cpp @@ -3,10 +3,9 @@ * @brief Message popup preferences panel * * $LicenseInfo:firstyear=2003&license=viewergpl$ - * + * Second Life Viewer Source Code * 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 @@ -34,36 +33,30 @@ #include "llpanelmsgs.h" -#include "llnotificationsutil.h" #include "llscrolllistctrl.h" -#include "llviewerwindow.h" -#include "llviewercontrol.h" #include "lluictrlfactory.h" #include "llfirstuse.h" #include "llnotificationtemplate.h" -//----------------------------------------------------------------------------- -LLPanelMsgs::LLPanelMsgs() : - LLPanel("Messages Panel") +LLPanelMsgs::LLPanelMsgs() { LLUICtrlFactory::getInstance()->buildPanel(this, "panel_preferences_popups.xml"); } LLPanelMsgs::~LLPanelMsgs() -{ } +{ +} -//----------------------------------------------------------------------------- -// postBuild() -//----------------------------------------------------------------------------- BOOL LLPanelMsgs::postBuild() { - childSetAction("enable_popup", onClickEnablePopup, this); - childSetAction("reset_dialogs_btn", onClickResetDialogs, this); - childSetAction("skip_dialogs_btn", onClickSkipDialogs, this); - childSetAction("skip_frst_btn", onClickSkipFirstTime, this); + getChild("enable_popup")->setCommitCallback(boost::bind(&LLPanelMsgs::onClickEnablePopup, this)); + getChild("disable_popup")->setCommitCallback(boost::bind(&LLPanelMsgs::onClickDisablePopup, this)); + getChild("reset_dialogs_btn")->setCommitCallback(boost::bind(&LLPanelMsgs::onClickResetDialogs, this)); + getChild("skip_dialogs_btn")->setCommitCallback(boost::bind(&LLPanelMsgs::onClickSkipDialogs, this)); + getChild("skip_frst_btn")->setCommitCallback(boost::bind(&LLPanelMsgs::onClickSkipFirstTime, this)); - buildLists(); + buildPopupLists(); childSetValue("accept_new_inventory", gSavedSettings.getBOOL("AutoAcceptNewInventory")); childSetValue("show_new_inventory", gSavedSettings.getBOOL("ShowNewInventory")); @@ -72,8 +65,18 @@ BOOL LLPanelMsgs::postBuild() return TRUE; } +void LLPanelMsgs::draw() +{ + BOOL has_first_selected = (getChildRef("disabled_popups").getFirstSelected()!=NULL); + childSetEnabled("enable_popup", has_first_selected); -void LLPanelMsgs::buildLists() //void LLFloaterPreference::buildPopupLists() in v3 + has_first_selected = (getChildRef("enabled_popups").getFirstSelected()!=NULL); + childSetEnabled("disable_popup", has_first_selected); + + LLPanel::draw(); +} + +void LLPanelMsgs::buildPopupLists() //void LLFloaterPreference::buildPopupLists() in v3 { LLScrollListCtrl& disabled_popups = getChildRef("disabled_popups"); @@ -103,7 +106,7 @@ void LLPanelMsgs::buildLists() //void LLFloaterPreference::buildPopupLists() in LLStringUtil::format(ignore_msg,notification->getSubstitutions()); row["columns"][0]["value"] = ignore_msg; row["columns"][0]["font"] = "SANSSERIF_SMALL"; - row["columns"][0]["width"] = 300; + row["columns"][0]["width"] = 500; LLScrollListItem* item = NULL; @@ -129,13 +132,11 @@ void LLPanelMsgs::buildLists() //void LLFloaterPreference::buildPopupLists() in row["columns"][1]["font"] = "SANSSERIF_SMALL"; row["columns"][1]["width"] = 160; } - item = disabled_popups.addElement(row, - ADD_SORTED); + item = disabled_popups.addElement(row, ADD_SORTED); } else { - item = enabled_popups.addElement(row, - ADD_SORTED); + item = enabled_popups.addElement(row, ADD_SORTED); } if (item) @@ -145,22 +146,6 @@ void LLPanelMsgs::buildLists() //void LLFloaterPreference::buildPopupLists() in } } -void LLPanelMsgs::draw() -{ - LLScrollListCtrl& disabled_popups = getChildRef("disabled_popups"); - - if (disabled_popups.getFirstSelected()) - { - childEnable("enable_popup"); - } - else - { - childDisable("enable_popup"); - } - - LLPanel::draw(); -} - void LLPanelMsgs::apply() { @@ -173,6 +158,36 @@ void LLPanelMsgs::cancel() { } +void LLPanelMsgs::onClickEnablePopup() +{ + LLScrollListCtrl& disabled_popups = getChildRef("disabled_popups"); + + std::vector items = disabled_popups.getAllSelected(); + std::vector::iterator itor; + for (itor = items.begin(); itor != items.end(); ++itor) + { + LLNotificationTemplatePtr templatep = LLNotificationTemplates::instance().getTemplate(*(std::string*)((*itor)->getUserdata())); + gSavedSettings.setWarning(templatep->mName, TRUE); + } + + buildPopupLists(); +} + +void LLPanelMsgs::onClickDisablePopup() +{ + LLScrollListCtrl& enabled_popups = getChildRef("enabled_popups"); + + std::vector items = enabled_popups.getAllSelected(); + std::vector::iterator itor; + for (itor = items.begin(); itor != items.end(); ++itor) + { + LLNotificationTemplatePtr templatep = LLNotificationTemplates::instance().getTemplate(*(std::string*)((*itor)->getUserdata())); + gSavedSettings.setWarning(templatep->mName, false); + } + + buildPopupLists(); +} + void LLPanelMsgs::resetAllIgnored() { for (LLNotificationTemplates::TemplateMap::const_iterator iter = LLNotificationTemplates::instance().templatesBegin(); @@ -199,70 +214,22 @@ void LLPanelMsgs::setAllIgnored() } } -//static -void LLPanelMsgs::onClickEnablePopup(void* user_data) +void LLPanelMsgs::onClickResetDialogs() { - LLPanelMsgs* panelp = (LLPanelMsgs*)user_data; - - LLScrollListCtrl& disabled_popups = panelp->getChildRef("disabled_popups"); - - std::vector items = disabled_popups.getAllSelected(); - std::vector::iterator itor; - for (itor = items.begin(); itor != items.end(); ++itor) - { - LLNotificationTemplatePtr templatep = LLNotificationTemplates::instance().getTemplate(*(std::string*)((*itor)->getUserdata())); - gSavedSettings.setWarning(templatep->mName, TRUE); - } - - panelp->buildLists(); + resetAllIgnored(); + LLFirstUse::resetFirstUse(); + buildPopupLists(); } -bool callback_reset_dialogs(const LLSD& notification, const LLSD& response, LLPanelMsgs* panelp) +void LLPanelMsgs::onClickSkipDialogs() { - S32 option = LLNotification::getSelectedOption(notification, response); - if (0 == option) - { - if ( panelp ) - { - panelp->resetAllIgnored(); - LLFirstUse::resetFirstUse(); - panelp->buildLists(); - } - } - return false; + setAllIgnored(); + LLFirstUse::disableFirstUse(); + buildPopupLists(); } -// static -void LLPanelMsgs::onClickResetDialogs(void* user_data) -{ - LLNotificationsUtil::add("ResetShowNextTimeDialogs", LLSD(), LLSD(), boost::bind(&callback_reset_dialogs, _1, _2, (LLPanelMsgs*)user_data)); -} - -bool callback_skip_dialogs(const LLSD& notification, const LLSD& response, LLPanelMsgs* panelp) -{ - S32 option = LLNotification::getSelectedOption(notification, response); - if (0 == option) - { - if ( panelp ) - { - panelp->setAllIgnored(); - LLFirstUse::disableFirstUse(); - panelp->buildLists(); - } - } - return false; -} - -// static -void LLPanelMsgs::onClickSkipDialogs(void* user_data) -{ - LLNotificationsUtil::add("SkipShowNextTimeDialogs", LLSD(), LLSD(), boost::bind(&callback_skip_dialogs, _1, _2, (LLPanelMsgs*)user_data)); -} - -// static -void LLPanelMsgs::onClickSkipFirstTime(void* user_data) +void LLPanelMsgs::onClickSkipFirstTime() { LLFirstUse::disableFirstUse(); - LLPanelMsgs* panelp = (LLPanelMsgs*)user_data; - if(panelp) panelp->buildLists(); + buildPopupLists(); } diff --git a/indra/newview/llpanelmsgs.h b/indra/newview/llpanelmsgs.h index 1ab642809..0ff3243ec 100644 --- a/indra/newview/llpanelmsgs.h +++ b/indra/newview/llpanelmsgs.h @@ -3,10 +3,9 @@ * @brief Message popup preferences panel * * $LicenseInfo:firstyear=2003&license=viewergpl$ - * + * Second Life Viewer Source Code * 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 @@ -35,29 +34,26 @@ #include "llpanel.h" -class LLScrollListCtrl; - class LLPanelMsgs : public LLPanel { public: LLPanelMsgs(); /*virtual*/ ~LLPanelMsgs(); - /*virtual*/ BOOL postBuild(); - /*virtual*/ void draw(); - void apply(); void cancel(); + /*virtual*/ void draw(); + /*virtual*/ BOOL postBuild(); - static void onClickEnablePopup(void* user_data); - static void onClickResetDialogs(void* user_data); - static void onClickSkipDialogs(void* user_data); - static void onClickSkipFirstTime(void* user_data); - - void buildLists(); - + void onClickEnablePopup(); + void onClickDisablePopup(); void resetAllIgnored(); void setAllIgnored(); + void onClickResetDialogs(); + void onClickSkipDialogs(); + void onClickSkipFirstTime(); + + void buildPopupLists(); }; #endif // LL_PANEL_MSGS diff --git a/indra/newview/llpanelnetwork.cpp b/indra/newview/llpanelnetwork.cpp index 86e6bced5..95b91731b 100644 --- a/indra/newview/llpanelnetwork.cpp +++ b/indra/newview/llpanelnetwork.cpp @@ -44,6 +44,7 @@ #include "llnotificationsutil.h" #include "llviewercontrol.h" #include "llviewerwindow.h" +#include "hippogridmanager.h" #include "llproxy.h" @@ -74,6 +75,14 @@ BOOL LLPanelNetwork::postBuild() childSetValue("connection_port_enabled", gSavedSettings.getBOOL("ConnectionPortEnabled")); childSetValue("connection_port", (F32)gSavedSettings.getU32("ConnectionPort")); + // If in Avination, hide the texture bandwidth slider, Avination throttles server-side + if (gHippoGridManager->getConnectedGrid()->isAvination()) + { + childSetVisible("text_box4", FALSE); + childSetVisible("tex_bandwidth", FALSE); + childSetVisible("text_box3", FALSE); + } + // Socks 5 proxy settings, commit callbacks childSetCommitCallback("socks5_proxy_enabled", onCommitSocks5ProxyEnabled, this); childSetCommitCallback("socks5_auth", onSocksAuthChanged, this); diff --git a/indra/newview/llpanelobject.cpp b/indra/newview/llpanelobject.cpp index 821ebd4a0..90714d99f 100644 --- a/indra/newview/llpanelobject.cpp +++ b/indra/newview/llpanelobject.cpp @@ -2490,6 +2490,18 @@ void LLPanelObject::onCopyRot(void* user_data) gViewerWindow->mWindow->copyTextToClipboard(utf8str_to_wstring(stringVec)); } +namespace +{ + bool texturePermsCheck(const LLUUID& id) + { + return (id.notNull() && !gInventory.isObjectDescendentOf(id, gInventory.getLibraryRootFolderID()) + && id != LLUUID(gSavedSettings.getString("UIImgWhiteUUID")) + && id != LLUUID(gSavedSettings.getString("UIImgInvisibleUUID")) + && id != LLUUID(std::string("8dcd4a48-2d37-4909-9f78-f7a9eb4ef903")) // alpha + && LLPanelObject::findItemID(id).isNull()); + } +} + void LLPanelObject::onCopyParams(void* user_data) { LLPanelObject* self = (LLPanelObject*) user_data; @@ -2500,36 +2512,19 @@ void LLPanelObject::onCopyParams(void* user_data) LLViewerObject* objp = self->mObject; - mClipboardFlexiParams = (LLFlexibleObjectData*)objp->getParameterEntry(LLNetworkData::PARAMS_FLEXIBLE); - mClipboardLightParams = (LLLightParams*)objp->getParameterEntry(LLNetworkData::PARAMS_LIGHT); - mClipboardSculptParams = (LLSculptParams*)objp->getParameterEntry(LLNetworkData::PARAMS_SCULPT); + mClipboardFlexiParams = objp->getParameterEntryInUse(LLNetworkData::PARAMS_FLEXIBLE) ? static_cast(objp->getParameterEntry(LLNetworkData::PARAMS_FLEXIBLE)) : NULL; + mClipboardLightParams = objp->getParameterEntryInUse(LLNetworkData::PARAMS_LIGHT) ? static_cast(objp->getParameterEntry(LLNetworkData::PARAMS_LIGHT)) : NULL; + mClipboardSculptParams = objp->getParameterEntryInUse(LLNetworkData::PARAMS_SCULPT) ? static_cast(objp->getParameterEntry(LLNetworkData::PARAMS_SCULPT)) : NULL; if (mClipboardSculptParams) { - LLUUID id = mClipboardSculptParams->getSculptTexture(); - - // Texture perms check - if (!(id.isNull() || gInventory.isObjectDescendentOf(id, gInventory.getLibraryRootFolderID()) - || id == LLUUID(gSavedSettings.getString("UIImgWhiteUUID")) - || id == LLUUID(gSavedSettings.getString("UIImgInvisibleUUID")) - || id == LLUUID(std::string("8dcd4a48-2d37-4909-9f78-f7a9eb4ef903"))) // alpha - && findItemID(id).isNull()) - { - mClipboardSculptParams->setSculptTexture(LLUUID(SCULPT_DEFAULT_TEXTURE)); - } + const LLUUID id = mClipboardSculptParams->getSculptTexture(); + if (id != LLUUID(SCULPT_DEFAULT_TEXTURE) && !texturePermsCheck(id)) + mClipboardSculptParams = NULL; } - mClipboardLightImageParams = (LLLightImageParams*)objp->getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE); - if (mClipboardLightImageParams) + mClipboardLightImageParams = objp->getParameterEntryInUse(LLNetworkData::PARAMS_LIGHT_IMAGE) ? static_cast(objp->getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE)) : NULL; + if (mClipboardLightImageParams && texturePermsCheck(mClipboardLightImageParams->getLightTexture())) { - LLUUID id = mClipboardLightImageParams->getLightTexture(); - - // Texture perms check - if (!(id.isNull() || gInventory.isObjectDescendentOf(id, gInventory.getLibraryRootFolderID()) - || id == LLUUID(gSavedSettings.getString("UIImgWhiteUUID")) - || id == LLUUID(gSavedSettings.getString("UIImgInvisibleUUID")) - || id == LLUUID("8dcd4a48-2d37-4909-9f78-f7a9eb4ef903"))) // alpha - { - mClipboardLightImageParams->setLightTexture(findItemID(id)); - } + mClipboardLightImageParams = NULL; } } @@ -2542,16 +2537,27 @@ void LLPanelObject::onPasteParams(void* user_data) LLViewerObject* objp = self->mObject; - objp->updateVolume(mClipboardVolumeParams); - if (mClipboardFlexiParams) objp->setParameterEntry(LLNetworkData::PARAMS_FLEXIBLE, *mClipboardFlexiParams, true); + else + objp->setParameterEntryInUse(LLNetworkData::PARAMS_FLEXIBLE, false, true); + if (mClipboardLightParams) objp->setParameterEntry(LLNetworkData::PARAMS_LIGHT, *mClipboardLightParams, true); + else + objp->setParameterEntryInUse(LLNetworkData::PARAMS_LIGHT, false, true); + if (mClipboardSculptParams) objp->setParameterEntry(LLNetworkData::PARAMS_SCULPT, *mClipboardSculptParams, true); + else + objp->setParameterEntryInUse(LLNetworkData::PARAMS_SCULPT, false, true); + if (mClipboardLightImageParams) objp->setParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE, *mClipboardLightImageParams, true); + else + objp->setParameterEntryInUse(LLNetworkData::PARAMS_LIGHT_IMAGE, false, true); + + objp->updateVolume(mClipboardVolumeParams); } void LLPanelObject::onLinkObj(void* user_data) diff --git a/indra/newview/llpanelpermissions.cpp b/indra/newview/llpanelpermissions.cpp index 9fc9d2af7..c81ae35e9 100644 --- a/indra/newview/llpanelpermissions.cpp +++ b/indra/newview/llpanelpermissions.cpp @@ -67,7 +67,9 @@ #include "lluictrlfactory.h" #include "roles_constants.h" #include "lltrans.h" +#include "llinventoryfunctions.h" +#include "lfsimfeaturehandler.h" #include "hippogridmanager.h" @@ -76,6 +78,32 @@ #include "rlvhandler.h" // [/RLVa:KB] +// base and own must have EXPORT, next owner must be UNRESTRICTED +bool can_set_export(const U32& base, const U32& own, const U32& next) +{ + return base & PERM_EXPORT && own & PERM_EXPORT && (next & PERM_ITEM_UNRESTRICTED) == PERM_ITEM_UNRESTRICTED; +} + +bool perms_allow_export(const LLPermissions& perms) +{ + return perms.getMaskBase() & PERM_EXPORT && perms.getMaskEveryone() & PERM_EXPORT; +} + +bool is_asset_exportable(const LLUUID& asset_id) +{ + if (asset_id.isNull()) return true; // Don't permission-check null textures + LLViewerInventoryCategory::cat_array_t cats; + LLViewerInventoryItem::item_array_t items; + LLAssetIDMatches asset_id_matches(asset_id); + gInventory.collectDescendentsIf(LLUUID::null, cats, items, true, asset_id_matches, false); + + for (int i = 0; i < items.count(); ++i) + { + if (perms_allow_export(items[i]->getPermissions())) return true; + } + return false; +} + ///---------------------------------------------------------------------------- /// Class llpanelpermissions ///---------------------------------------------------------------------------- @@ -112,6 +140,8 @@ BOOL LLPanelPermissions::postBuild() childSetCommitCallback("checkbox allow everyone copy",LLPanelPermissions::onCommitEveryoneCopy,this); + getChild("checkbox allow export")->setCommitCallback(boost::bind(&LLPanelPermissions::onCommitExport, this, _2)); + childSetCommitCallback("checkbox for sale",LLPanelPermissions::onCommitSaleInfo,this); childSetCommitCallback("Edit Cost",LLPanelPermissions::onCommitSaleInfo,this); @@ -127,6 +157,9 @@ BOOL LLPanelPermissions::postBuild() mLabelGroupName = getChild("Group Name Proxy"); + if (!gHippoGridManager->getCurrentGrid()->isSecondLife()) + LFSimFeatureHandler::instance().setSupportsExportCallback(boost::bind(&LLPanelPermissions::refresh, this)); + return TRUE; } @@ -136,6 +169,13 @@ LLPanelPermissions::~LLPanelPermissions() // base class will take care of everything } +// virtual +void LLPanelPermissions::handleVisibilityChange(BOOL new_visibility) +{ + if (new_visibility) + refresh(); + LLPanel::handleVisibilityChange(new_visibility); +} void LLPanelPermissions::disableAll() { @@ -181,11 +221,14 @@ void LLPanelPermissions::disableAll() getChildView("checkbox share with group")->setEnabled(FALSE); getChildView("button deed")->setEnabled(FALSE); + getChildView("text anyone can")->setEnabled(FALSE); getChild("checkbox allow everyone move")->setValue(FALSE); getChildView("checkbox allow everyone move")->setEnabled(FALSE); getChild("checkbox allow everyone copy")->setValue(FALSE); getChildView("checkbox allow everyone copy")->setEnabled(FALSE); - + getChild("checkbox allow export")->setValue(FALSE); + getChildView("checkbox allow export")->setEnabled(FALSE); + //Next owner can: getChildView("Next owner can:")->setEnabled(FALSE); getChild("checkbox next owner can modify")->setValue(FALSE); @@ -230,6 +273,7 @@ void LLPanelPermissions::disableAll() getChildView("N:")->setVisible( FALSE); getChildView("F:")->setVisible( FALSE); } + void LLPanelPermissions::refresh() { @@ -272,6 +316,7 @@ void LLPanelPermissions::refresh() return; } + // figure out a few variables BOOL is_one_object = (object_count == 1); @@ -598,6 +643,7 @@ void LLPanelPermissions::refresh() &next_owner_mask_on, &next_owner_mask_off); + bool supports_export = LFSimFeatureHandler::instance().simSupportsExport(); if( gSavedSettings.getBOOL("DebugPermissions") ) { @@ -605,6 +651,8 @@ void LLPanelPermissions::refresh() if (valid_base_perms) { std::string perm_string = mask_to_string(base_mask_on); + if (!supports_export && base_mask_on & PERM_EXPORT) // Hide Export when not available + perm_string.erase(perm_string.find_last_of("E")); if (U32 diff_mask = base_mask_on ^ owner_mask_on) // When different, show the user's potential permissions lowercase. { if (diff_mask & PERM_MOVE) @@ -615,17 +663,25 @@ void LLPanelPermissions::refresh() LLStringUtil::replaceChar(perm_string, 'C', 'c'); if (diff_mask & PERM_TRANSFER) LLStringUtil::replaceChar(perm_string, 'T', 't'); + if (diff_mask & PERM_EXPORT) + LLStringUtil::replaceChar(perm_string, 'E', 'e'); } getChild("B:")->setValue("B: " + perm_string); getChildView("B:")->setVisible( TRUE); - getChild("O:")->setValue("O: " + mask_to_string(owner_mask_on)); + perm_string = mask_to_string(owner_mask_on); + if (!supports_export && owner_mask_on & PERM_EXPORT) // Hide Export when not available + perm_string.erase(perm_string.find_last_of("E")); + getChild("O:")->setValue("O: " + perm_string); getChildView("O:")->setVisible( TRUE); getChild("G:")->setValue("G: " + mask_to_string(group_mask_on)); getChildView("G:")->setVisible( TRUE); - getChild("E:")->setValue("E: " + mask_to_string(everyone_mask_on)); + perm_string = mask_to_string(owner_mask_on); + if (!supports_export && everyone_mask_on & PERM_EXPORT) // Hide Export when not available + perm_string.erase(perm_string.find_last_of("E")); + getChild("E:")->setValue("E: " + perm_string); getChildView("E:")->setVisible( TRUE); getChild("N:")->setValue("N: " + mask_to_string(next_owner_mask_on)); @@ -675,16 +731,41 @@ void LLPanelPermissions::refresh() if (has_change_perm_ability) { getChildView("checkbox share with group")->setEnabled(TRUE); + getChildView("text anyone can")->setEnabled(true); getChildView("checkbox allow everyone move")->setEnabled(owner_mask_on & PERM_MOVE); getChildView("checkbox allow everyone copy")->setEnabled(owner_mask_on & PERM_COPY && owner_mask_on & PERM_TRANSFER); } else { getChildView("checkbox share with group")->setEnabled(FALSE); + getChildView("text anyone can")->setEnabled(false); getChildView("checkbox allow everyone move")->setEnabled(FALSE); getChildView("checkbox allow everyone copy")->setEnabled(FALSE); } + // Is this user allowed to toggle export on this object? + if (supports_export && self_owned && mCreatorID == mOwnerID && can_set_export(base_mask_on, owner_mask_on, next_owner_mask_on)) + { + bool can_export = true; + LLInventoryObject::object_list_t objects; + objectp->getInventoryContents(objects); + for (LLInventoryObject::object_list_t::iterator i = objects.begin(); can_export && i != objects.end() ; ++i) //The object's inventory must have EXPORT. + { + LLViewerInventoryItem* item = static_cast(i->get()); //getInventoryContents() filters out categories, static_cast. + can_export = perms_allow_export(item->getPermissions()); + } + for (U8 i = 0; can_export && i < objectp->getNumTEs(); ++i) // Can the textures be exported? + if (LLTextureEntry* texture = objectp->getTE(i)) + can_export = is_asset_exportable(texture->getID()); + getChildView("checkbox allow export")->setEnabled(can_export); + } + else + { + getChildView("checkbox allow export")->setEnabled(false); + if (!gHippoGridManager->getCurrentGrid()->isSecondLife()) + getChildView("checkbox allow everyone copy")->setVisible(true); + } + if (has_change_sale_ability && (owner_mask_on & PERM_TRANSFER)) { getChildView("checkbox for sale")->setEnabled(can_transfer || (!can_transfer && num_for_sale)); @@ -693,10 +774,12 @@ void LLPanelPermissions::refresh() getChild("checkbox for sale")->setTentative( is_for_sale_mixed); getChildView("sale type")->setEnabled(num_for_sale && can_transfer && !is_sale_price_mixed); - getChildView("Next owner can:")->setEnabled(TRUE); - getChildView("checkbox next owner can modify")->setEnabled(base_mask_on & PERM_MODIFY); - getChildView("checkbox next owner can copy")->setEnabled(base_mask_on & PERM_COPY); - getChildView("checkbox next owner can transfer")->setEnabled(next_owner_mask_on & PERM_COPY); + + bool no_export = everyone_mask_off & PERM_EXPORT; // Next owner perms can't be changed if set + getChildView("Next owner can:")->setEnabled(no_export); + getChildView("checkbox next owner can modify")->setEnabled(no_export && base_mask_on & PERM_MODIFY); + getChildView("checkbox next owner can copy")->setEnabled(no_export && base_mask_on & PERM_COPY); + getChildView("checkbox next owner can transfer")->setEnabled(no_export && next_owner_mask_on & PERM_COPY); } else { @@ -766,6 +849,31 @@ void LLPanelPermissions::refresh() getChild("checkbox allow everyone copy")->setValue(TRUE); getChild("checkbox allow everyone copy")->setTentative( TRUE); } + + // Export + if (supports_export) + { + if(everyone_mask_on & PERM_EXPORT) + { + getChild("checkbox allow export")->setValue(TRUE); + getChild("checkbox allow export")->setTentative( FALSE); + } + else if(everyone_mask_off & PERM_EXPORT) + { + getChild("checkbox allow export")->setValue(FALSE); + getChild("checkbox allow export")->setTentative( FALSE); + } + else + { + getChild("checkbox allow export")->setValue(TRUE); + getChild("checkbox allow export")->setValue( TRUE); + } + } + else + { + childSetValue("checkbox allow export", false); + childSetTentative("checkbox allow export", false); + } } if (valid_next_perms) @@ -1057,6 +1165,11 @@ void LLPanelPermissions::onCommitEveryoneCopy(LLUICtrl *ctrl, void *data) onCommitPerm(ctrl, data, PERM_EVERYONE, PERM_COPY); } +void LLPanelPermissions::onCommitExport(const LLSD& param) +{ + LLSelectMgr::getInstance()->selectionSetObjectPermissions(PERM_EVERYONE, param, PERM_EXPORT); +} + // static void LLPanelPermissions::onCommitNextOwnerModify(LLUICtrl* ctrl, void* data) { diff --git a/indra/newview/llpanelpermissions.h b/indra/newview/llpanelpermissions.h index 90d75d8e3..8ac27d9be 100644 --- a/indra/newview/llpanelpermissions.h +++ b/indra/newview/llpanelpermissions.h @@ -57,6 +57,7 @@ public: virtual ~LLPanelPermissions(); virtual BOOL postBuild(); + virtual void handleVisibilityChange(BOOL new_visibility); // MANIPULATORS void refresh(); // refresh all labels as needed @@ -86,6 +87,7 @@ protected: static void onCommitEveryoneMove(LLUICtrl *ctrl, void *data); static void onCommitEveryoneCopy(LLUICtrl *ctrl, void *data); //static void onCommitEveryoneModify(LLUICtrl *ctrl, void *data); + void onCommitExport(const LLSD& param); static void onCommitNextOwnerModify(LLUICtrl* ctrl, void* data); static void onCommitNextOwnerCopy(LLUICtrl* ctrl, void* data); diff --git a/indra/newview/llprefsim.cpp b/indra/newview/llprefsim.cpp index fd0dc783b..8aed046ca 100644 --- a/indra/newview/llprefsim.cpp +++ b/indra/newview/llprefsim.cpp @@ -233,8 +233,11 @@ void LLPrefsIMImpl::apply() else { const std::string log_path = childGetText("log_path_string"); - gSavedPerAccountSettings.setString("InstantMessageLogPathAnyAccount", log_path); - gDirUtilp->setChatLogsDir(log_path); + if (!log_path.empty()) + { + gSavedSettings.setString("InstantMessageLogPathAnyAccount", log_path); + gDirUtilp->setChatLogsDir(log_path); + } } } diff --git a/indra/newview/llregioninfomodel.cpp b/indra/newview/llregioninfomodel.cpp index 590e24648..3892c8795 100644 --- a/indra/newview/llregioninfomodel.cpp +++ b/indra/newview/llregioninfomodel.cpp @@ -35,6 +35,7 @@ // viewer #include "llagent.h" #include "llviewerregion.h" +#include "llestateinfomodel.h" // For supporting legacy environment void LLRegionInfoModel::reset() { @@ -107,6 +108,17 @@ void LLRegionInfoModel::sendRegionTerrain(const LLUUID& invoice) const strings.push_back(buffer); buffer = llformat("%f", mSunHour); strings.push_back(buffer); + if (mUseEstateSun) + { + // Grab estate info, the user decided to set the region back to estate time. JC + LLEstateInfoModel& estate_info = LLEstateInfoModel::instance(); + estate_global_time = estate_info.getGlobalTime(); + if (!estate_global_time) + { + estate_fixed_sun = estate_info.getUseFixedSun(); + estate_sun_hour = estate_info.getSunHour(); + } + } buffer = llformat("%s", (estate_global_time ? "Y" : "N") ); strings.push_back(buffer); buffer = llformat("%s", (estate_fixed_sun ? "Y" : "N") ); diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 63390a0eb..f0919f372 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -213,6 +213,7 @@ #include "llinventorybridge.h" #include "llappearancemgr.h" #include "jcfloaterareasearch.h" +#include "generichandlers.h" // #include "llpanellogin.h" @@ -844,6 +845,8 @@ bool idle_startup() // *NOTE: This is where gMuteList used to get allocated before becoming LLMuteList::getInstance(). + gGenericHandlers = new GenericHandlers(); + // Initialize UI if (!gNoRender) { @@ -1000,6 +1003,7 @@ bool idle_startup() if(!gHippoGridManager->getConnectedGrid()->isSecondLife()) { LLTrans::setDefaultArg("[CURRENCY]",gHippoGridManager->getConnectedGrid()->getCurrencySymbol()); //replace [CURRENCY] with OS$, not L$ for instance. + LLTrans::setDefaultArg("[CURRENCY_TEXT]",gHippoGridManager->getConnectedGrid()->getCurrencyText()); //replace [CURRENCYTEXT] with OS DOllars, not Linden Dollars for instance. LLTrans::setDefaultArg("[SECOND_LIFE]", gHippoGridManager->getConnectedGrid()->getGridName()); LLTrans::setDefaultArg("[SECOND_LIFE_GRID]", gHippoGridManager->getConnectedGrid()->getGridName() + " Grid"); LLTrans::setDefaultArg("[GRID_OWNER]", gHippoGridManager->getConnectedGrid()->getGridOwner()); @@ -4376,6 +4380,8 @@ bool process_login_success_response(std::string& password) if (!tmp.empty()) gHippoGridManager->getConnectedGrid()->setSearchUrl(tmp); tmp = response["currency"].asString(); if (!tmp.empty()) gHippoGridManager->getConnectedGrid()->setCurrencySymbol(tmp); + tmp = response["currency_text"].asString(); + if (!tmp.empty()) gHippoGridManager->getConnectedGrid()->setCurrencyText(tmp); tmp = response["real_currency"].asString(); if (!tmp.empty()) gHippoGridManager->getConnectedGrid()->setRealCurrencySymbol(tmp); tmp = response["directory_fee"].asString(); @@ -4386,6 +4392,8 @@ bool process_login_success_response(std::string& password) if (!tmp.empty()) gHippoGridManager->getConnectedGrid()->setMaxAgentGroups(atoi(tmp.c_str())); tmp = response["VoiceConnector"].asString(); if (!tmp.empty()) gHippoGridManager->getConnectedGrid()->setVoiceConnector(tmp); + tmp = response["upc_supported"].asString(); + if (!tmp.empty()) gHippoGridManager->getConnectedGrid()->setUPCSupported(true); gHippoGridManager->saveFile(); gHippoLimits->setLimits(); diff --git a/indra/newview/llstatusbar.cpp b/indra/newview/llstatusbar.cpp index 631527d24..0563a150c 100644 --- a/indra/newview/llstatusbar.cpp +++ b/indra/newview/llstatusbar.cpp @@ -68,6 +68,7 @@ #include "llworld.h" #include "llstatgraph.h" #include "llviewercontrol.h" +#include "llviewergenericmessage.h" #include "llviewermenu.h" // for gMenuBarView #include "llviewerparcelmgr.h" #include "llviewerthrottle.h" @@ -137,9 +138,27 @@ std::vector LLStatusBar::sDays; std::vector LLStatusBar::sMonths; const U32 LLStatusBar::MAX_DATE_STRING_LENGTH = 2000; +class LLDispatchUPCBalance : public LLDispatchHandler +{ +public: + virtual bool operator()( + const LLDispatcher* dispatcher, + const std::string& key, + const LLUUID& invoice, + const sparam_t& strings) + { + S32 upc = atoi(strings[0].c_str()); + gStatusBar->setUPC(upc); + return true; + } +}; + +static LLDispatchUPCBalance sDispatchUPCBalance; + LLStatusBar::LLStatusBar(const std::string& name, const LLRect& rect) : LLPanel(name, LLRect(), FALSE), // not mouse opaque mBalance(0), +mUPC(0), mHealth(100), mSquareMetersCredit(0), mSquareMetersCommitted(0), @@ -147,6 +166,11 @@ mRegionCrossingSlot(), mNavMeshSlot(), mIsNavMeshDirty(false) { + mUPCSupported = gHippoGridManager->getConnectedGrid()->getUPCSupported(); + + if (mUPCSupported) + gGenericDispatcher.addHandler("upcbalance", &sDispatchUPCBalance); + // status bar can possible overlay menus? setMouseOpaque(FALSE); setIsChrome(TRUE); @@ -168,10 +192,14 @@ mIsNavMeshDirty(false) mTextParcelName = getChild("ParcelNameText" ); mTextBalance = getChild("BalanceText" ); + mTextUPC = getChild("UPCText" ); mTextHealth = getChild("HealthText" ); mTextTime = getChild("TimeText" ); + if (!mUPCSupported) + mTextUPC->setVisible(false); + childSetAction("scriptout", onClickScriptDebug, this); childSetAction("health", onClickHealth, this); childSetAction("no_fly", onClickFly, this); @@ -595,6 +623,14 @@ void LLStatusBar::refresh() } // Set rects of money, buy money, time + if (mUPCSupported) + { + childGetRect("UPCText", r); + r.translate( new_right - r.mRight, 0); + childSetRect("UPCText", r); + new_right -= r.getWidth() - 18; + } + childGetRect("BalanceText", r); r.translate( new_right - r.mRight, 0); childSetRect("BalanceText", r); @@ -631,6 +667,8 @@ void LLStatusBar::refresh() void LLStatusBar::setVisibleForMouselook(bool visible) { mTextBalance->setVisible(visible); + if (mUPCSupported) + mTextUPC->setVisible(visible); mTextTime->setVisible(visible); childSetVisible("buycurrency", visible); childSetVisible("search_editor", visible); @@ -653,7 +691,7 @@ void LLStatusBar::creditBalance(S32 credit) void LLStatusBar::setBalance(S32 balance) { mTextBalance->setText(gHippoGridManager->getConnectedGrid()->getCurrencySymbol().c_str() + - LLResMgr::getInstance()->getMonetaryString(balance)); + LLResMgr::getInstance()->getMonetaryString(balance - mUPC)); if (mBalance && (fabs((F32)(mBalance - balance)) > gSavedSettings.getF32("UISndMoneyChangeThreshold"))) { @@ -670,6 +708,14 @@ void LLStatusBar::setBalance(S32 balance) } } +void LLStatusBar::setUPC(S32 upc) +{ + mTextUPC->setText("UPC " + LLResMgr::getInstance()->getMonetaryString(upc)); + + mUPC = upc; + + setBalance(mBalance); +} // static void LLStatusBar::sendMoneyBalanceRequest() diff --git a/indra/newview/llstatusbar.h b/indra/newview/llstatusbar.h index 144047166..b24913ef3 100644 --- a/indra/newview/llstatusbar.h +++ b/indra/newview/llstatusbar.h @@ -61,6 +61,7 @@ public: // MANIPULATORS void setBalance(S32 balance); + void setUPC(S32 balance); void debitBalance(S32 debit); void creditBalance(S32 credit); @@ -99,6 +100,7 @@ private: private: LLTextBox *mTextBalance; + LLTextBox *mTextUPC; LLTextBox *mTextHealth; LLTextBox *mTextTime; @@ -110,6 +112,7 @@ private: LLButton *mBtnBuyCurrency; S32 mBalance; + S32 mUPC; S32 mHealth; S32 mSquareMetersCredit; S32 mSquareMetersCommitted; @@ -118,6 +121,7 @@ private: boost::signals2::connection mRegionCrossingSlot; LLPathfindingNavMesh::navmesh_slot_t mNavMeshSlot; bool mIsNavMeshDirty; + bool mUPCSupported; static std::vector sDays; static std::vector sMonths; diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp index 1d3634573..f80bd9539 100644 --- a/indra/newview/lltexturefetch.cpp +++ b/indra/newview/lltexturefetch.cpp @@ -36,7 +36,7 @@ #include "lltexturefetch.h" -#include "llcurl.h" +#include "aicurl.h" #include "lldir.h" #include "llhttpclient.h" #include "llhttpstatuscodes.h" @@ -60,6 +60,7 @@ #include "llstartup.h" #include "llsdserialize.h" #include "llbuffer.h" +#include "hippogridmanager.h" class AIHTTPTimeoutPolicy; extern AIHTTPTimeoutPolicy HTTPGetResponder_timeout; @@ -253,6 +254,7 @@ private: LLUUID mID; LLHost mHost; std::string mUrl; + AIPerServicePtr mPerServicePtr; // Pointer to the AIPerService corresponding to the host of mUrl. U8 mType; F32 mImagePriority; U32 mWorkPriority; @@ -495,30 +497,6 @@ public: SGHostBlackList::blacklist_t SGHostBlackList::blacklist; -#if 0 -//call every time a connection is opened -//return true if connecting allowed -static bool sgConnectionThrottle() { - const U32 THROTTLE_TIMESTEPS_PER_SECOND = 10; - static const LLCachedControl max_connections_per_second("HTTPRequestRate", 30); - U32 max_connections = max_connections_per_second/THROTTLE_TIMESTEPS_PER_SECOND; - const U32 timestep = USEC_PER_SEC/THROTTLE_TIMESTEPS_PER_SECOND; - U64 now = LLTimer::getTotalTime(); - std::deque timestamps; - while(!timestamps.empty() && (timestamps[0]<=now-timestep)) { - timestamps.pop_front(); - } - if(timestamps.size() < max_connections) { - //llinfos << "throttle pass" << llendl; - timestamps.push_back(now); - return true; - } else { - //llinfos << "throttle fail" << llendl; - return false; - } -} -#endif - ////////////////////////////////////////////////////////////////////////////// // Cross-thread messaging for asset metrics. @@ -819,6 +797,17 @@ LLTextureFetchWorker::LLTextureFetchWorker(LLTextureFetch* fetcher, { mCanUseNET = mUrl.empty() ; + if (!mCanUseNET) + { + // Probably a file://, but well; in that case servicename will be empty. + std::string servicename = AIPerService::extract_canonical_servicename(mUrl); + if (!servicename.empty()) + { + // Make sure mPerServicePtr is up to date with mUrl. + mPerServicePtr = AIPerService::instance(servicename); + } + } + calcWorkPriority(); mType = host.isOk() ? LLImageBase::TYPE_AVATAR_BAKE : LLImageBase::TYPE_NORMAL; //llinfos << "Create: " << mID << " mHost:" << host << " Discard=" << discard << " URL:"<< mUrl << llendl; @@ -972,8 +961,6 @@ void LLTextureFetchWorker::startWork(S32 param) // Called from LLWorkerThread::processRequest() bool LLTextureFetchWorker::doWork(S32 param) { - static const F32 FETCHING_TIMEOUT = 15.f;//seconds - LLMutexLock lock(&mWorkMutex); if ((mFetcher->isQuitting() || getFlags(LLWorkerClass::WCF_DELETE_REQUESTED))) @@ -1176,6 +1163,7 @@ bool LLTextureFetchWorker::doWork(S32 param) { mUrl = http_url + "/?texture_id=" + mID.asString().c_str(); mWriteToCacheState = CAN_WRITE ; //because this texture has a fixed texture id. + mPerServicePtr = AIPerService::instance(AIPerService::extract_canonical_servicename(http_url)); } else { @@ -1184,7 +1172,7 @@ bool LLTextureFetchWorker::doWork(S32 param) } else { - // This will happen if not logged in or if a region deoes not have HTTP Texture enabled + // This will happen if not logged in or if a region does not have HTTP Texture enabled //llwarns << "Region not found for host: " << mHost << llendl; mCanUseHTTP = false; } @@ -1261,29 +1249,14 @@ bool LLTextureFetchWorker::doWork(S32 param) { if(mCanUseHTTP) { - //NOTE: - //control the number of the http requests issued for: - //1, not opening too many file descriptors at the same time; - //2, control the traffic of http so udp gets bandwidth. - // - static const LLCachedControl max_http_requests("HTTPMaxRequests", 8); - static const LLCachedControl min_http_requests("HTTPMinRequests", 2); - static const LLCachedControl throttle_bandwidth("HTTPThrottleBandwidth", 2000); - if(((U32)mFetcher->getNumHTTPRequests() >= max_http_requests) || - ((mFetcher->getTextureBandwidth() > throttle_bandwidth) && - ((U32)mFetcher->getNumHTTPRequests() > min_http_requests))) - { - return false ; //wait. - } - - mFetcher->removeFromNetworkQueue(this, false); - S32 cur_size = 0; if (mFormattedImage.notNull()) { cur_size = mFormattedImage->getDataSize(); // amount of data we already have if (mFormattedImage->getDiscardLevel() == 0) { + // Already have all data. + mFetcher->removeFromNetworkQueue(this, false); // Note sure this is necessary, but it's what the old did --Aleric if(cur_size > 0) { // We already have all the data, just decode it @@ -1297,22 +1270,29 @@ bool LLTextureFetchWorker::doWork(S32 param) } } } + + // Let AICurl decide if we can process more HTTP requests at the moment or not. + static const LLCachedControl throttle_bandwidth("HTTPThrottleBandwidth", 2000); + bool const no_bandwidth_throttling = gHippoGridManager->getConnectedGrid()->isAvination(); + if (!AIPerService::wantsMoreHTTPRequestsFor(mPerServicePtr, throttle_bandwidth, no_bandwidth_throttling)) + { + return false ; //wait. + } + + mFetcher->removeFromNetworkQueue(this, false); + mRequestedSize = mDesiredSize - cur_size; mRequestedDiscard = mDesiredDiscard; mRequestedOffset = cur_size; - + bool res = false; if (!mUrl.empty()) { - mRequestedTimer.reset(); - mLoaded = FALSE; mGetStatus = 0; mGetReason.clear(); - static const LLCachedControl throttle_bandwidth("HTTPThrottleBandwidth", 2000); LL_DEBUGS("Texture") << "HTTP GET: " << mID << " Offset: " << mRequestedOffset << " Bytes: " << mRequestedSize - << " Bandwidth(kbps): " << mFetcher->getTextureBandwidth() << "/" << throttle_bandwidth << LL_ENDL; setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); mState = WAIT_HTTP_REQ; @@ -1334,17 +1314,17 @@ bool LLTextureFetchWorker::doWork(S32 param) mRequestedOffset--; } - // Will call callbackHttpGet when curl request completes - AIHTTPHeaders headers("Accept", "image/x-j2c"); - // Call LLHTTPClient::request directly instead of LLHTTPClient::getByteRange, because we want to pass a NULL AIEngine. - if (mRequestedOffset > 0 || mRequestedSize > 0) - { - headers.addHeader("Range", llformat("bytes=%d-%d", mRequestedOffset, mRequestedOffset + mRequestedSize - 1)); - } - LLHTTPClient::request(mUrl, LLHTTPClient::HTTP_GET, NULL, - new HTTPGetResponder(mFetcher, mID, LLTimer::getTotalTime(), mRequestedSize, mRequestedOffset, true), - headers/*,*/ DEBUG_CURLIO_PARAM(false), keep_alive, no_does_authentication, allow_compressed_reply, NULL, 0, NULL); - res = true; + // Will call callbackHttpGet when curl request completes + AIHTTPHeaders headers("Accept", "image/x-j2c"); + // Call LLHTTPClient::request directly instead of LLHTTPClient::getByteRange, because we want to pass a NULL AIEngine. + if (mRequestedOffset > 0 || mRequestedSize > 0) + { + headers.addHeader("Range", llformat("bytes=%d-%d", mRequestedOffset, mRequestedOffset + mRequestedSize - 1)); + } + LLHTTPClient::request(mUrl, LLHTTPClient::HTTP_GET, NULL, + new HTTPGetResponder(mFetcher, mID, LLTimer::getTotalTime(), mRequestedSize, mRequestedOffset, true), + headers/*,*/ DEBUG_CURLIO_PARAM(debug_off), keep_alive, no_does_authentication, allow_compressed_reply, NULL, 0, NULL); + res = true; } if (!res) { @@ -1533,13 +1513,6 @@ bool LLTextureFetchWorker::doWork(S32 param) } else { - if(FETCHING_TIMEOUT < mRequestedTimer.getElapsedTimeF32()) - { - //timeout, abort. - mState = DONE; - return true; - } - setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); return false; } @@ -2061,8 +2034,6 @@ LLTextureFetch::LLTextureFetch(LLTextureCache* cache, LLImageDecodeThread* image mBadPacketCount(0), mTextureCache(cache), mImageDecodeThread(imagedecodethread), - mTextureBandwidth(0), - mHTTPTextureBits(0), mTotalHTTPRequests(0), mQAMode(qa_mode), mTotalCacheReadCount(0U), @@ -2214,7 +2185,6 @@ void LLTextureFetch::removeFromHTTPQueue(const LLUUID& id, S32 received_size) { LLMutexLock lock(&mNetworkQueueMutex); mHTTPTextureQueue.erase(id); - mHTTPTextureBits += received_size * 8; // Approximate - does not include header bits } void LLTextureFetch::deleteRequest(const LLUUID& id, bool cancel) @@ -2272,15 +2242,6 @@ S32 LLTextureFetch::getNumRequests() return size ; } -S32 LLTextureFetch::getNumHTTPRequests() -{ - mNetworkQueueMutex.lock() ; - S32 size = (S32)mHTTPTextureQueue.size(); - mNetworkQueueMutex.unlock() ; - - return size ; -} - U32 LLTextureFetch::getTotalNumHTTPRequests() { mNetworkQueueMutex.lock() ; @@ -2436,15 +2397,6 @@ void LLTextureFetch::commonUpdate() //virtual S32 LLTextureFetch::update(F32 max_time_ms) { - { - mNetworkQueueMutex.lock() ; - - gTextureList.sTextureBits += mHTTPTextureBits ; - mHTTPTextureBits = 0 ; - - mNetworkQueueMutex.unlock() ; - } - S32 res = LLWorkerThread::update(max_time_ms); if (!mDebugPause) diff --git a/indra/newview/lltexturefetch.h b/indra/newview/lltexturefetch.h index f23961083..4062c310a 100644 --- a/indra/newview/lltexturefetch.h +++ b/indra/newview/lltexturefetch.h @@ -79,16 +79,12 @@ public: bool receiveImageHeader(const LLHost& host, const LLUUID& id, U8 codec, U16 packets, U32 totalbytes, U16 data_size, U8* data); bool receiveImagePacket(const LLHost& host, const LLUUID& id, U16 packet_num, U16 data_size, U8* data); - void setTextureBandwidth(F32 bandwidth) { mTextureBandwidth = bandwidth; } - F32 getTextureBandwidth() { return mTextureBandwidth; } - // Debug BOOL isFromLocalCache(const LLUUID& id); S32 getFetchState(const LLUUID& id, F32& decode_progress_p, F32& requested_priority_p, U32& fetch_priority_p, F32& fetch_dtime_p, F32& request_dtime_p, bool& can_use_http); void dump(); S32 getNumRequests() ; - S32 getNumHTTPRequests() ; U32 getTotalNumHTTPRequests() ; // Public for access by callbacks @@ -165,11 +161,8 @@ private: queue_t mHTTPTextureQueue; typedef std::map > cancel_queue_t; cancel_queue_t mCancelQueue; - F32 mTextureBandwidth; LLTextureInfo mTextureInfo; - U32 mHTTPTextureBits; - //debug use U32 mTotalHTTPRequests ; diff --git a/indra/newview/lltextureview.cpp b/indra/newview/lltextureview.cpp index e57fbc3a2..944870e32 100644 --- a/indra/newview/lltextureview.cpp +++ b/indra/newview/lltextureview.cpp @@ -64,6 +64,15 @@ LLTextureSizeView *gTextureCategoryView = NULL; //static std::set LLTextureView::sDebugImages; +// Forward declaration. +namespace AICurlInterface { + U32 getNumHTTPCommands(void); + U32 getNumHTTPQueued(void); + U32 getNumHTTPAdded(void); + U32 getNumHTTPRunning(void); + size_t getHTTPBandwidth(void); +} // namespace AICurlInterface + //////////////////////////////////////////////////////////////////////////// static std::string title_string1a("Tex UUID Area DDis(Req) DecodePri(Fetch) [download] pk/max"); @@ -593,7 +602,7 @@ void LLGLTexMemBar::draw() #endif //---------------------------------------------------------------------------- - text = llformat("Textures: %d Fetch: %d(%d) Pkts:%d(%d) Cache R/W: %d/%d LFS:%d IW:%d RAW:%d(%d) HTP:%d DEC:%d CRE:%d ", + text = llformat("Textures: %d Fetch: %d(%d) Pkts:%d(%d) Cache R/W: %d/%d LFS:%d IW:%d RAW:%d(%d) HTTP:%d/%d/%d/%d DEC:%d CRE:%d ", gTextureList.getNumImages(), LLAppViewer::getTextureFetch()->getNumRequests(), LLAppViewer::getTextureFetch()->getNumDeletes(), LLAppViewer::getTextureFetch()->mPacketCount, LLAppViewer::getTextureFetch()->mBadPacketCount, @@ -601,7 +610,10 @@ void LLGLTexMemBar::draw() LLLFSThread::sLocal->getPending(), LLAppViewer::getImageDecodeThread()->getPending(), LLImageRaw::sRawImageCount, LLImageRaw::sRawImageCachedCount, - LLAppViewer::getTextureFetch()->getNumHTTPRequests(), + AICurlInterface::getNumHTTPCommands(), + AICurlInterface::getNumHTTPQueued(), + AICurlInterface::getNumHTTPAdded(), + AICurlInterface::getNumHTTPRunning(), LLAppViewer::getImageDecodeThread()->getPending(), gTextureList.mCreateTextureList.size()); @@ -609,11 +621,15 @@ void LLGLTexMemBar::draw() text_color, LLFontGL::LEFT, LLFontGL::TOP); left += LLFontGL::getFontMonospace()->getWidth(text); - F32 bandwidth = LLAppViewer::getTextureFetch()->getTextureBandwidth(); - F32 max_bandwidth = gSavedSettings.getF32("HTTPThrottleBandwidth"); + // This bandwidth is averaged over 1 seconds (in kbps). + F32 bandwidth = AICurlInterface::getHTTPBandwidth() / 125.f; // Convert from bytes/s to kbps. + // This is the maximum bandwidth allowed for curl transactions (of any type and averaged per second), + // that is actually used to limit the number of HTTP texture requests (and only those). + // Comparing that with 'bandwidth' is a bit like comparing apples and oranges, but again... who really cares. + static const LLCachedControl max_bandwidth("HTTPThrottleBandwidth", 2000); color = bandwidth > max_bandwidth ? LLColor4::red : bandwidth > max_bandwidth*.75f ? LLColor4::yellow : text_color; color[VALPHA] = text_color[VALPHA]; - text = llformat("BW:%.0f/%.0f",bandwidth, max_bandwidth); + text = llformat("BW:%.0f/%.0f", bandwidth, max_bandwidth.get()); LLFontGL::getFontMonospace()->renderUTF8(text, 0, left, v_offset + line_height*2, color, LLFontGL::LEFT, LLFontGL::TOP); diff --git a/indra/newview/lltoolpie.cpp b/indra/newview/lltoolpie.cpp index 0dc00f826..f3a1831db 100644 --- a/indra/newview/lltoolpie.cpp +++ b/indra/newview/lltoolpie.cpp @@ -3,10 +3,9 @@ * @brief LLToolPie class implementation * * $LicenseInfo:firstyear=2001&license=viewergpl$ - * + * Second Life Viewer Source Code * 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 @@ -42,7 +41,6 @@ #include "llagentcamera.h" #include "llfocusmgr.h" #include "llfirstuse.h" -#include "llfloateravatarinfo.h" #include "llfloaterland.h" #include "llfloaterscriptdebug.h" #include "llhoverview.h" @@ -64,81 +62,86 @@ #include "llviewerobject.h" #include "llviewerparcelmgr.h" #include "llviewerwindow.h" -#include "llwindow.h" #include "llviewermedia.h" #include "llvoavatarself.h" #include "llviewermediafocus.h" #include "llworld.h" #include "llui.h" #include "llweb.h" - -// [RLVa:KB] +// [RLVa:KB] - Checked: 2010-03-06 (RLVa-1.2.0c) #include "rlvhandler.h" // [/RLVa:KB] -extern void handle_buy(); - extern BOOL gDebugClicks; -static bool handle_media_click(const LLPickInfo& info); -static bool handle_media_hover(const LLPickInfo& info); static void handle_click_action_play(); static void handle_click_action_open_media(LLPointer objectp); static ECursorType cursor_from_parcel_media(U8 click_action); - LLToolPie::LLToolPie() : LLTool(std::string("Pie")), - mPieMouseButtonDown( FALSE ), - mGrabMouseButtonDown( FALSE ), - mMouseOutsideSlop( FALSE ), - mClickAction(0) -{ } + mMouseButtonDown( false ), + mMouseOutsideSlop( false ), + mMouseSteerX(-1), + mMouseSteerY(-1), + mBlockClickToWalk(false), + mClickAction(0), + mClickActionBuyEnabled("ClickActionBuyEnabled"), + mClickActionPayEnabled("ClickActionPayEnabled") +{ +} BOOL LLToolPie::handleMouseDown(S32 x, S32 y, MASK mask) { + mMouseOutsideSlop = FALSE; + mMouseDownX = x; + mMouseDownY = y; + //left mouse down always picks transparent - gViewerWindow->pickAsync(x, y, mask, leftMouseCallback, TRUE, TRUE); - mGrabMouseButtonDown = TRUE; + mPick = gViewerWindow->pickImmediate(x, y, TRUE); + mPick.mKeyMask = mask; + + mMouseButtonDown = true; + + handleLeftClickPick(); + return TRUE; } -// static -void LLToolPie::leftMouseCallback(const LLPickInfo& pick_info) -{ - LLToolPie::getInstance()->mPick = pick_info; - LLToolPie::getInstance()->pickAndShowMenu(FALSE); -} - +// Spawn context menus on right mouse down so you can drag over and select +// an item. BOOL LLToolPie::handleRightMouseDown(S32 x, S32 y, MASK mask) { // don't pick transparent so users can't "pay" transparent objects - gViewerWindow->pickAsync(x, y, mask, rightMouseCallback, FALSE, TRUE); - mPieMouseButtonDown = TRUE; - // don't steal focus from UI + mPick = gViewerWindow->pickImmediate(x, y, FALSE); + mPick.mKeyMask = mask; + + // claim not handled so UI focus stays same + + handleRightClickPick(); + return FALSE; } +BOOL LLToolPie::handleRightMouseUp(S32 x, S32 y, MASK mask) +{ + LLToolMgr::getInstance()->clearTransientTool(); + return LLTool::handleRightMouseUp(x, y, mask); +} + BOOL LLToolPie::handleScrollWheel(S32 x, S32 y, S32 clicks) { return LLViewerMediaFocus::getInstance()->handleScrollWheel(x, y, clicks); } -// static -void LLToolPie::rightMouseCallback(const LLPickInfo& pick_info) -{ - LLToolPie::getInstance()->mPick = pick_info; - LLToolPie::getInstance()->pickAndShowMenu(TRUE); -} - // True if you selected an object. -BOOL LLToolPie::pickAndShowMenu(BOOL always_show) +BOOL LLToolPie::handleLeftClickPick() { S32 x = mPick.mMousePt.mX; S32 y = mPick.mMousePt.mY; MASK mask = mPick.mKeyMask; - if (!always_show && mPick.mPickType == LLPickInfo::PICK_PARCEL_WALL) + if (mPick.mPickType == LLPickInfo::PICK_PARCEL_WALL) { LLParcel* parcel = LLViewerParcelMgr::getInstance()->getCollisionParcel(); if (parcel) @@ -176,13 +179,15 @@ BOOL LLToolPie::pickAndShowMenu(BOOL always_show) parent = object->getRootEdit(); } - BOOL touchable = (object && object->flagHandleTouch()) - || (parent && parent->flagHandleTouch()); + if (handleMediaClick(mPick)) + { + return TRUE; + } // If it's a left-click, and we have a special action, do it. - if (useClickAction(always_show, mask, object, parent)) + if (useClickAction(mask, object, parent)) { -// [RLVa:KB] - Checked: 2010-01-02 (RLVa-1.1.0l) | Modified: RLVa-1.1.0l +// [RLVa:KB] - Checked: 2010-03-11 (RLVa-1.2.0e) | Modified: RLVa-1.1.0l // Block left-click special actions when fartouch restricted if ( (rlv_handler_t::isEnabled()) && (gRlvHandler.hasBehaviour(RLV_BHVR_FARTOUCH)) && (!gRlvHandler.canTouch(object, mPick.mObjectOffset)) ) @@ -207,22 +212,47 @@ BOOL LLToolPie::pickAndShowMenu(BOOL always_show) // touch behavior down below... break; case CLICK_ACTION_SIT: - if ((isAgentAvatarValid()) && (!gAgentAvatarp->isSitting()) - && (!gSavedSettings.getBOOL("DisableClickSit"))) // agent not already sitting { - handle_sit_or_stand(); - // put focus in world when sitting on an object - gFocusMgr.setKeyboardFocus(NULL); - return TRUE; - } // else nothing (fall through to touch) - + if (isAgentAvatarValid() && !gAgentAvatarp->isSitting()) // agent not already sitting + { + bool disable_click_sit = gSavedSettings.getBOOL("DisableClickSit"); + if (!disable_click_sit) + { + if (gSavedSettings.getBOOL("DisableClickSitOtherOwner")) + { + disable_click_sit = !object->permYouOwner(); + } + } + if (disable_click_sit) return true; + handle_object_sit_or_stand(); + // put focus in world when sitting on an object + gFocusMgr.setKeyboardFocus(NULL); + return TRUE; + } // else nothing (fall through to touch) + } case CLICK_ACTION_PAY: - if ((object && object->flagTakesMoney()) - || (parent && parent->flagTakesMoney())) + if ( mClickActionPayEnabled ) { - // pay event goes to object actually clicked on - mClickActionObject = object; - mLeftClickSelection = LLToolSelect::handleObjectSelection(mPick, FALSE, TRUE); + if ((object && object->flagTakesMoney()) + || (parent && parent->flagTakesMoney())) + { + // pay event goes to object actually clicked on + mClickActionObject = object; + mLeftClickSelection = LLToolSelect::handleObjectSelection(mPick, FALSE, TRUE); + if (LLSelectMgr::getInstance()->selectGetAllValid()) + { + // call this right away, since we have all the info we need to continue the action + selectionPropertiesReceived(); + } + return TRUE; + } + } + break; + case CLICK_ACTION_BUY: + if ( mClickActionBuyEnabled ) + { + mClickActionObject = parent; + mLeftClickSelection = LLToolSelect::handleObjectSelection(mPick, FALSE, TRUE, TRUE); if (LLSelectMgr::getInstance()->selectGetAllValid()) { // call this right away, since we have all the info we need to continue the action @@ -231,15 +261,6 @@ BOOL LLToolPie::pickAndShowMenu(BOOL always_show) return TRUE; } break; - case CLICK_ACTION_BUY: - mClickActionObject = parent; - mLeftClickSelection = LLToolSelect::handleObjectSelection(mPick, FALSE, TRUE, TRUE); - if (LLSelectMgr::getInstance()->selectGetAllValid()) - { - // call this right away, since we have all the info we need to continue the action - selectionPropertiesReceived(); - } - return TRUE; case CLICK_ACTION_OPEN: if (parent && parent->allowOpen()) { @@ -259,27 +280,53 @@ BOOL LLToolPie::pickAndShowMenu(BOOL always_show) // mClickActionObject = object; handle_click_action_open_media(object); return TRUE; + case CLICK_ACTION_ZOOM: + { + const F32 PADDING_FACTOR = 2.f; + LLViewerObject* object = gObjectList.findObject(mPick.mObjectID); + + if (object) + { + gAgentCamera.setFocusOnAvatar(FALSE, ANIMATE); + + LLBBox bbox = object->getBoundingBoxAgent() ; + F32 angle_of_view = llmax(0.1f, LLViewerCamera::getInstance()->getAspect() > 1.f ? LLViewerCamera::getInstance()->getView() * LLViewerCamera::getInstance()->getAspect() : LLViewerCamera::getInstance()->getView()); + F32 distance = bbox.getExtentLocal().magVec() * PADDING_FACTOR / atan(angle_of_view); + + LLVector3 obj_to_cam = LLViewerCamera::getInstance()->getOrigin() - bbox.getCenterAgent(); + obj_to_cam.normVec(); + + LLVector3d object_center_global = gAgent.getPosGlobalFromAgent(bbox.getCenterAgent()); + gAgentCamera.setCameraPosAndFocusGlobal(object_center_global + LLVector3d(obj_to_cam * distance), + object_center_global, + mPick.mObjectID ); + } + } + return TRUE; default: // nothing break; } } - if (!always_show && handle_media_click(mPick)) + // put focus back "in world" + if (gFocusMgr.getKeyboardFocus()) { - return FALSE; + // don't click to walk on attempt to give focus to world + mBlockClickToWalk = true; + gFocusMgr.setKeyboardFocus(NULL); } - // put focus back "in world" - gFocusMgr.setKeyboardFocus(NULL); + BOOL touchable = (object && object->flagHandleTouch()) + || (parent && parent->flagHandleTouch()); // Switch to grab tool if physical or triggerable if (object && !object->isAvatar() && - ((object->flagUsePhysics() || (parent && !parent->isAvatar() && parent->flagUsePhysics())) || touchable) && - !always_show) + ((object->flagUsePhysics() || (parent && !parent->isAvatar() && parent->flagUsePhysics())) || touchable) + ) { -// [RLVa:KB] - Checked: 2010-01-02 (RLVa-1.1.0l) | Modified: RLVa-1.1.0l +// [RLVa:KB] - Checked: 2010-03-11 (RLVa-1.2.0e) | Modified: RLVa-1.1.0l // Triggered by left-clicking on a touchable object if ( (rlv_handler_t::isEnabled()) && (!gRlvHandler.canTouch(object, mPick.mObjectOffset)) ) { @@ -288,6 +335,7 @@ BOOL LLToolPie::pickAndShowMenu(BOOL always_show) // [/RLVa:KB] gGrabTransientTool = this; + mMouseButtonDown = false; LLToolMgr::getInstance()->getCurrentToolset()->selectTool( LLToolGrab::getInstance() ); return LLToolGrab::getInstance()->handleObjectHit( mPick ); } @@ -300,13 +348,12 @@ BOOL LLToolPie::pickAndShowMenu(BOOL always_show) // If left-click never selects or spawns a menu // Eat the event. - if (!gSavedSettings.getBOOL("LeftClickShowMenu") - && !always_show) + if (!gSavedSettings.getBOOL("LeftClickShowMenu")) { // mouse already released - if (!mGrabMouseButtonDown) + if (!mMouseButtonDown) { - return TRUE; + return true; } while( object && object->isAttachment() && !object->flagHandleTouch()) @@ -318,9 +365,10 @@ BOOL LLToolPie::pickAndShowMenu(BOOL always_show) } object = (LLViewerObject*)object->getParent(); } - if (object && object == gAgentAvatarp) + if (object && object == gAgentAvatarp && !gSavedSettings.getBOOL("ClickToWalk")) { // we left clicked on avatar, switch to focus mode + mMouseButtonDown = false; LLToolMgr::getInstance()->setTransientTool(LLToolCamera::getInstance()); gViewerWindow->hideCursor(); LLToolCamera::getInstance()->setMouseCapture(TRUE); @@ -339,7 +387,7 @@ BOOL LLToolPie::pickAndShowMenu(BOOL always_show) return LLTool::handleMouseDown(x, y, mask); } - if (!always_show && gAgent.leftButtonGrabbed()) + if (gAgent.leftButtonGrabbed()) { // if the left button is grabbed, don't put up the pie menu return LLTool::handleMouseDown(x, y, mask); @@ -349,175 +397,15 @@ BOOL LLToolPie::pickAndShowMenu(BOOL always_show) LLToolSelect::handleObjectSelection(mPick, FALSE, TRUE); // Spawn pie menu - if (mPick.mPickType == LLPickInfo::PICK_LAND) - { - LLParcelSelectionHandle selection = LLViewerParcelMgr::getInstance()->selectParcelAt( mPick.mPosGlobal ); - gMenuHolder->setParcelSelection(selection); - gPieLand->show(x, y, mPieMouseButtonDown); - - // - if(!gSavedSettings.getBOOL("DisablePointAtAndBeam")) - { - // - // VEFFECT: ShowPie - LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_SPHERE, TRUE); - effectp->setPositionGlobal(mPick.mPosGlobal); - effectp->setColor(LLColor4U(gAgent.getEffectColor())); - effectp->setDuration(0.25f); - // - } - // - } - else if (mPick.mObjectID == gAgent.getID() ) - { - if(!gPieSelf) - { - //either at very early startup stage or at late quitting stage, - //this event is ignored. - return TRUE ; - } - - gPieSelf->show(x, y, mPieMouseButtonDown); - } - else if (object) - { - gMenuHolder->setObjectSelection(LLSelectMgr::getInstance()->getSelection()); - - if (object->isAvatar() - || (object->isAttachment() && !object->isHUDAttachment() && !object->permYouOwner())) - { - // Find the attachment's avatar - while( object && object->isAttachment()) - { - object = (LLViewerObject*)object->getParent(); - } - - if (!object) - { - return TRUE; // unexpected, but escape - } - - // Object is an avatar, so check for mute by id. - LLVOAvatar* avatar = (LLVOAvatar*)object; - std::string name = avatar->getFullname(); - if (LLMuteList::getInstance()->isMuted(avatar->getID(), name)) - { - gMenuHolder->childSetText("Avatar Mute", LLTrans::getString("UnmuteAvatar")); - //gMutePieMenu->setLabel("Unmute"); - } - else - { - gMenuHolder->childSetText("Avatar Mute", LLTrans::getString("MuteAvatar")); - //gMutePieMenu->setLabel("Mute"); - } - - //gPieAvatar->show(x, y, mPieMouseButtonDown); -// [RLVa:KB] - Checked: 2010-01-02 (RLVa-1.1.0l) | Modified: RLVa-1.1.0l - // Don't show the pie menu on empty selection when fartouch/interaction restricted [see LLToolSelect::handleObjectSelection()] - if ( (!rlv_handler_t::isEnabled()) || (!LLSelectMgr::getInstance()->getSelection()->isEmpty()) || - (!gRlvHandler.hasBehaviour(RLV_BHVR_FARTOUCH)) ) - { - gPieAvatar->show(x, y, mPieMouseButtonDown); - } - else - { - make_ui_sound("UISndInvalidOp"); - } -// [/RLVa:KB] - } - else if (object->isAttachment()) - { - //gPieAttachment->show(x, y, mPieMouseButtonDown); -// [RLVa:KB] - Checked: 2010-01-02 (RLVa-1.1.0l) | Modified: RLVa-1.1.0l - // Don't show the pie menu on empty selection when fartouch/interaction restricted [see LLToolSelect::handleObjectSelection()] - if ( (!rlv_handler_t::isEnabled()) || (!LLSelectMgr::getInstance()->getSelection()->isEmpty()) || - (!gRlvHandler.hasBehaviour(RLV_BHVR_FARTOUCH)) ) - { - gPieAttachment->show(x, y, mPieMouseButtonDown); - } - else - { - make_ui_sound("UISndInvalidOp"); - } -// [/RLVa:KB] - } - else - { - // BUG: What about chatting child objects? - std::string name; - LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstRootNode(); - if (node) - { - name = node->mName; - } - if (LLMuteList::getInstance()->isMuted(object->getID(), name)) - { - gMenuHolder->childSetText("Object Mute", LLTrans::getString("UnmuteObject")); - //gMuteObjectPieMenu->setLabel("Unmute"); - } - else - { - gMenuHolder->childSetText("Object Mute", LLTrans::getString("MuteObject2")); - //gMuteObjectPieMenu->setLabel("Mute"); - } - -// [RLVa:KB] - Checked: 2010-01-02 (RLVa-1.1.0l) | Modified: RLVa-1.1.0l - // Don't show the pie menu on empty selection when fartouch/interaction restricted - // (not entirely accurate in case of Tools / Select Only XXX [see LLToolSelect::handleObjectSelection()] - if ( (!rlv_handler_t::isEnabled()) || (!LLSelectMgr::getInstance()->getSelection()->isEmpty()) || - (!gRlvHandler.hasBehaviour(RLV_BHVR_FARTOUCH)) ) - { -// [/RLVa:KB] - gPieObject->show(x, y, mPieMouseButtonDown); - - // - if(!gSavedSettings.getBOOL("DisablePointAtAndBeam")) - { - // - // VEFFECT: ShowPie object - // Don't show when you click on someone else, it freaks them - // out. - LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)LLHUDManager::getInstance()->createViewerEffect( - LLHUDObject::LL_HUD_EFFECT_SPHERE, TRUE); - effectp->setPositionGlobal(mPick.mPosGlobal); - effectp->setColor(LLColor4U(gAgent.getEffectColor())); - effectp->setDuration(0.25f); - // - } - // -// [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) | Added: RLVa-0.2.0f - } - else - { - make_ui_sound("UISndInvalidOp"); - } -// [/RLVa:KB] - } - } - - if (always_show) - { - // ignore return value - LLTool::handleRightMouseDown(x, y, mask); - } - else - { - // ignore return value - LLTool::handleMouseDown(x, y, mask); - } - - // We handled the event. + LLTool::handleRightMouseDown(x, y, mask); return TRUE; } - -BOOL LLToolPie::useClickAction(BOOL always_show, - MASK mask, +BOOL LLToolPie::useClickAction(MASK mask, LLViewerObject* object, LLViewerObject* parent) { - return !always_show - && mask == MASK_NONE + return mask == MASK_NONE && object && !object->isAttachment() && LLPrimitive::isPrimitive(object->getPCode()) @@ -548,7 +436,7 @@ U8 final_click_action(LLViewerObject* obj) return click_action; } -ECursorType cursor_from_object(LLViewerObject* object) +ECursorType LLToolPie::cursorFromObject(LLViewerObject* object) { LLViewerObject* parent = NULL; if (object) @@ -560,17 +448,22 @@ ECursorType cursor_from_object(LLViewerObject* object) switch(click_action) { case CLICK_ACTION_SIT: -// if ((gAgentAvatarp != NULL) && (!gAgentAvatarp->isSitting())) // not already sitting? -// [RLVa:KB] - Checked: 2009-12-22 (RLVa-1.1.0k) | Added: RLVa-1.1.0j - if ( ((isAgentAvatarValid()) && (!gAgentAvatarp->isSitting())) && // not already sitting? - ((!rlv_handler_t::isEnabled()) || (gRlvHandler.canSit(object, gViewerWindow->getHoverPick().mObjectOffset))) ) -// [/RLVa:KB] { - cursor = UI_CURSOR_TOOLSIT; +// if (isAgentAvatarValid() && !gAgentAvatarp->isSitting()) // not already sitting? +// [RLVa:KB] - Checked: 2010-03-06 (RLVa-1.2.0c) | Modified: RLVa-1.2.0g + if ( (isAgentAvatarValid() && !gAgentAvatarp->isSitting()) && + ((!rlv_handler_t::isEnabled()) || (gRlvHandler.canSit(object, LLToolPie::getInstance()->getHoverPick().mObjectOffset))) ) +// [/RLVa:KB] + { + cursor = UI_CURSOR_TOOLSIT; + } } break; case CLICK_ACTION_BUY: - cursor = UI_CURSOR_TOOLBUY; + if ( mClickActionBuyEnabled ) + { + cursor = UI_CURSOR_TOOLBUY; + } break; case CLICK_ACTION_OPEN: // Open always opens the parent. @@ -580,12 +473,18 @@ ECursorType cursor_from_object(LLViewerObject* object) } break; case CLICK_ACTION_PAY: - if ((object && object->flagTakesMoney()) - || (parent && parent->flagTakesMoney())) + if ( mClickActionPayEnabled ) { - cursor = UI_CURSOR_TOOLPAY; + if ((object && object->flagTakesMoney()) + || (parent && parent->flagTakesMoney())) + { + cursor = UI_CURSOR_TOOLPAY; + } } break; + case CLICK_ACTION_ZOOM: + cursor = UI_CURSOR_TOOLZOOMIN; + break; case CLICK_ACTION_PLAY: case CLICK_ACTION_OPEN_MEDIA: cursor = cursor_from_parcel_media(click_action); @@ -603,6 +502,20 @@ void LLToolPie::resetSelection() mClickAction = 0; } +void LLToolPie::walkToClickedLocation() +{ + /* Singu TODO: llhudeffectblob + if(mAutoPilotDestination) { mAutoPilotDestination->markDead(); } + mAutoPilotDestination = (LLHUDEffectBlob *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_BLOB, FALSE); + mAutoPilotDestination->setPositionGlobal(mPick.mPosGlobal); + mAutoPilotDestination->setPixelSize(5); + mAutoPilotDestination->setColor(LLColor4U(170, 210, 190)); + mAutoPilotDestination->setDuration(3.f); + */ + + handle_go_to(); +} + // When we get object properties after left-clicking on an object // with left-click = buy, if it's the same object, do the buy. @@ -628,10 +541,16 @@ void LLToolPie::selectionPropertiesReceived() switch (click_action) { case CLICK_ACTION_BUY: - handle_buy(); + if ( LLToolPie::getInstance()->mClickActionBuyEnabled ) + { + handle_buy(); + } break; case CLICK_ACTION_PAY: - handle_give_money_dialog(); + if ( LLToolPie::getInstance()->mClickActionPayEnabled ) + { + handle_give_money_dialog(); + } break; case CLICK_ACTION_OPEN: handle_object_open(); @@ -646,40 +565,18 @@ void LLToolPie::selectionPropertiesReceived() BOOL LLToolPie::handleHover(S32 x, S32 y, MASK mask) { - /* - // If auto-rotate occurs, tag mouse-outside-slop to make sure the drag - // gets started. - const S32 ROTATE_H_MARGIN = (S32) (0.1f * gViewerWindow->getWindowWidth() ); - const F32 ROTATE_ANGLE_PER_SECOND = 30.f * DEG_TO_RAD; - const F32 rotate_angle = ROTATE_ANGLE_PER_SECOND / gFPSClamped; - // ...normal modes can only yaw - if (x < ROTATE_H_MARGIN) - { - gAgent.yaw(rotate_angle); - mMouseOutsideSlop = TRUE; - } - else if (x > gViewerWindow->getWindowWidth() - ROTATE_H_MARGIN) - { - gAgent.yaw(-rotate_angle); - mMouseOutsideSlop = TRUE; - } - */ - - - LLViewerObject *object = NULL; + mHoverPick = gViewerWindow->pickImmediate(x, y, FALSE); LLViewerObject *parent = NULL; -// object = gViewerWindow->getHoverPick().getObject(); -// [RLVa:KB] - Alternate: Snowglobe-1.2.4 | Checked: 2010-01-02 (RLVa-1.1.0l) | Modified: RLVa-1.1.0l + LLViewerObject *object = mHoverPick.getObject(); +// [RLVa:KB] - Checked: 2010-03-11 (RLVa-1.2.0e) | Modified: RLVa-1.1.0l // Block all special click action cursors when: // - @fartouch=n restricted and the object is out of range // - @interact=n restricted and the object isn't a HUD attachment - const LLPickInfo& pick = gViewerWindow->getHoverPick(); - object = pick.getObject(); if ( (object) && (rlv_handler_t::isEnabled()) && - ( (((gRlvHandler.hasBehaviour(RLV_BHVR_FARTOUCH))) && (!gRlvHandler.canTouch(object, pick.mObjectOffset))) || + ( ((gRlvHandler.hasBehaviour(RLV_BHVR_FARTOUCH))) && (!gRlvHandler.canTouch(object, mHoverPick.mObjectOffset)) || ((gRlvHandler.hasBehaviour(RLV_BHVR_INTERACT)) && (!object->isHUDAttachment())) ) ) { - gViewerWindow->getWindow()->setCursor(UI_CURSOR_ARROW); + gViewerWindow->setCursor(UI_CURSOR_ARROW); return TRUE; } // [/RLVa:KB] @@ -687,49 +584,78 @@ BOOL LLToolPie::handleHover(S32 x, S32 y, MASK mask) if (object) { parent = object->getRootEdit(); + } - if (object && useClickAction(FALSE, mask, object, parent)) + if (handleMediaHover(mHoverPick)) + { + // cursor set by media object + } + else if (!mMouseOutsideSlop + && mMouseButtonDown + && gSavedSettings.getBOOL("ClickToWalk")) + { + S32 delta_x = x - mMouseDownX; + S32 delta_y = y - mMouseDownY; + S32 threshold = gSavedSettings.getS32("DragAndDropDistanceThreshold"); + if (delta_x * delta_x + delta_y * delta_y > threshold * threshold) { - ECursorType cursor = cursor_from_object(object); - gViewerWindow->getWindow()->setCursor(cursor); + startCameraSteering(); + steerCameraWithMouse(x, y); + gViewerWindow->setCursor(UI_CURSOR_TOOLGRAB); } - else if (handle_media_hover(gViewerWindow->getHoverPick())) + else { - // cursor set by media object + gViewerWindow->setCursor(UI_CURSOR_ARROW); } -// [RLVa:KB] - Checked: 2010-01-02 (RLVa-1.1.0l) | Added: RLVa-1.1.0l - else if ( (rlv_handler_t::isEnabled()) && (!gRlvHandler.canTouch(object)) ) + } + else if (inCameraSteerMode()) + { + steerCameraWithMouse(x, y); + gViewerWindow->setCursor(UI_CURSOR_TOOLGRAB); + } + else + { + // perform a separate pick that detects transparent objects since they respond to 1-click actions + LLPickInfo click_action_pick = gViewerWindow->pickImmediate(x, y, TRUE); + + LLViewerObject* click_action_object = click_action_pick.getObject(); + + if (click_action_object && useClickAction(mask, click_action_object, click_action_object->getRootEdit())) + { + ECursorType cursor = cursorFromObject(click_action_object); + gViewerWindow->setCursor(cursor); + } +// [RLVa:KB] - Checked: 2010-03-11 (RLVa-1.2.0e) | Added: RLVa-1.1.0l + else if ( (object) && (rlv_handler_t::isEnabled()) && (!gRlvHandler.canTouch(object)) ) { // Block showing the "grab" or "touch" cursor if we can't touch the object (@fartouch=n is handled above) - gViewerWindow->getWindow()->setCursor(UI_CURSOR_ARROW); + gViewerWindow->setCursor(UI_CURSOR_ARROW); } // [/RLVa:KB] else if ((object && !object->isAvatar() && object->flagUsePhysics()) || (parent && !parent->isAvatar() && parent->flagUsePhysics())) { - gViewerWindow->getWindow()->setCursor(UI_CURSOR_TOOLGRAB); + gViewerWindow->setCursor(UI_CURSOR_TOOLGRAB); } else if ( (object && object->flagHandleTouch()) || (parent && parent->flagHandleTouch())) { - gViewerWindow->getWindow()->setCursor(UI_CURSOR_HAND); + gViewerWindow->setCursor(UI_CURSOR_HAND); } - - else + else { - gViewerWindow->getWindow()->setCursor(UI_CURSOR_ARROW); + gViewerWindow->setCursor(UI_CURSOR_ARROW); } - } - else + + if(!object) { - gViewerWindow->getWindow()->setCursor(UI_CURSOR_ARROW); + gViewerWindow->setCursor(UI_CURSOR_ARROW); // We need to clear media hover flag if (LLViewerMediaFocus::getInstance()->getMouseOverFlag()) { LLViewerMediaFocus::getInstance()->setMouseOverFlag(false); } - } return TRUE; @@ -739,7 +665,46 @@ BOOL LLToolPie::handleMouseUp(S32 x, S32 y, MASK mask) { LLViewerObject* obj = mPick.getObject(); U8 click_action = final_click_action(obj); - if (click_action != CLICK_ACTION_NONE) + + // let media have first pass at click + if (handleMediaMouseUp() || LLViewerMediaFocus::getInstance()->getFocus()) + { + mBlockClickToWalk = true; + } + stopCameraSteering(); + mMouseButtonDown = false; + + if (click_action == CLICK_ACTION_NONE // not doing 1-click action + && gSavedSettings.getBOOL("ClickToWalk") // click to walk enabled + && !gAgent.getFlying() // don't auto-navigate while flying until that works + && gAgentAvatarp + && !gAgentAvatarp->isSitting() + && !mBlockClickToWalk // another behavior hasn't cancelled click to walk + && !mPick.mPosGlobal.isExactlyZero() // valid coordinates for pick + && (mPick.mPickType == LLPickInfo::PICK_LAND // we clicked on land + || mPick.mObjectID.notNull())) // or on an object + { + // handle special cases of steering picks + LLViewerObject* avatar_object = mPick.getObject(); + + // get pointer to avatar + while (avatar_object && !avatar_object->isAvatar()) + { + avatar_object = (LLViewerObject*)avatar_object->getParent(); + } + + if (avatar_object && ((LLVOAvatar*)avatar_object)->isSelf()) + { + const F64 SELF_CLICK_WALK_DISTANCE = 3.0; + // pretend we picked some point a bit in front of avatar + mPick.mPosGlobal = gAgent.getPositionGlobal() + LLVector3d(LLViewerCamera::instance().getAtAxis()) * SELF_CLICK_WALK_DISTANCE; + } + gAgentCamera.setFocusOnAvatar(TRUE, TRUE); + walkToClickedLocation(); + + return TRUE; + } + else { switch(click_action) { @@ -751,7 +716,7 @@ BOOL LLToolPie::handleMouseUp(S32 x, S32 y, MASK mask) // the world. Keep the cursor an arrow, assuming that // after the user moves off the UI, they won't be on the // same object anymore. - gViewerWindow->getWindow()->setCursor(UI_CURSOR_ARROW); + gViewerWindow->setCursor(UI_CURSOR_ARROW); // Make sure the hover-picked object is ignored. gHoverView->resetLastHoverObject(); break; @@ -759,20 +724,30 @@ BOOL LLToolPie::handleMouseUp(S32 x, S32 y, MASK mask) break; } } - mGrabMouseButtonDown = FALSE; + if (hasMouseCapture()) + { + setMouseCapture(FALSE); + } + LLToolMgr::getInstance()->clearTransientTool(); gAgentCamera.setLookAt(LOOKAT_TARGET_CONVERSATION, obj); // maybe look at object/person clicked on + + mBlockClickToWalk = false; return LLTool::handleMouseUp(x, y, mask); } -BOOL LLToolPie::handleRightMouseUp(S32 x, S32 y, MASK mask) +void LLToolPie::stopClickToWalk() { - mPieMouseButtonDown = FALSE; - LLToolMgr::getInstance()->clearTransientTool(); - return LLTool::handleRightMouseUp(x, y, mask); + mPick.mPosGlobal = gAgent.getPositionGlobal(); + handle_go_to(); + /* Singu TODO: llhudeffectblob + if(mAutoPilotDestination) + { + mAutoPilotDestination->markDead(); + } + */ } - BOOL LLToolPie::handleDoubleClick(S32 x, S32 y, MASK mask) { if (gDebugClicks) @@ -785,7 +760,7 @@ BOOL LLToolPie::handleDoubleClick(S32 x, S32 y, MASK mask) if ((mPick.mPickType == LLPickInfo::PICK_LAND && !mPick.mPosGlobal.isExactlyZero()) || (mPick.mObjectID.notNull() && !mPick.mPosGlobal.isExactlyZero())) { - handle_go_to(); + walkToClickedLocation(); return TRUE; } } @@ -812,6 +787,11 @@ BOOL LLToolPie::handleDoubleClick(S32 x, S32 y, MASK mask) return FALSE; } +void LLToolPie::handleSelect() +{ + // tool is reselected when app gets focus, etc. + mBlockClickToWalk = true; +} void LLToolPie::handleDeselect() { @@ -820,20 +800,23 @@ void LLToolPie::handleDeselect() setMouseCapture( FALSE ); // Calls onMouseCaptureLost() indirectly } // remove temporary selection for pie menu + LLSelectMgr::getInstance()->setHoverObject(NULL); LLSelectMgr::getInstance()->validateSelection(); } LLTool* LLToolPie::getOverrideTool(MASK mask) { - if (mask == MASK_CONTROL) + if (gSavedSettings.getBOOL("EnableGrab")) { - return LLToolGrab::getInstance(); + if (mask == MASK_CONTROL) + { + return LLToolGrab::getInstance(); + } + else if (mask == (MASK_CONTROL | MASK_SHIFT)) + { + return LLToolGrab::getInstance(); + } } - else if (mask == (MASK_CONTROL | MASK_SHIFT)) - { - return LLToolGrab::getInstance(); - } - return LLTool::getOverrideTool(mask); } @@ -847,9 +830,20 @@ void LLToolPie::stopEditing() void LLToolPie::onMouseCaptureLost() { - mMouseOutsideSlop = FALSE; + stopCameraSteering(); + mMouseButtonDown = false; + handleMediaMouseUp(); } +void LLToolPie::stopCameraSteering() +{ + mMouseOutsideSlop = false; +} + +bool LLToolPie::inCameraSteerMode() +{ + return mMouseButtonDown && mMouseOutsideSlop && gSavedSettings.getBOOL("ClickToWalk"); +} // true if x,y outside small box around start_x,start_y BOOL LLToolPie::outsideSlop(S32 x, S32 y, S32 start_x, S32 start_y) @@ -888,7 +882,7 @@ static void handle_click_action_play() } } -static bool handle_media_click(const LLPickInfo& pick) +bool LLToolPie::handleMediaClick(const LLPickInfo& pick) { //FIXME: how do we handle object in different parcel than us? LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); @@ -906,23 +900,22 @@ static bool handle_media_click(const LLPickInfo& pick) return false; } - + // Does this face have media? + const LLTextureEntry* tep = objectp->getTE(pick.mObjectFace); + if(!tep) + return false; // HACK: This is directly referencing an impl name. BAD! // This can be removed when we have a truly generic media browser that only // builds an impl based on the type of url it is passed. - - // is media playing on this face? - const LLTextureEntry* tep = objectp->getTE(pick.mObjectFace); - viewer_media_t media_impl = LLViewerMedia::getMediaImplFromTextureID(tep->getID()); - if (tep - && media_impl.notNull() - && media_impl->hasMedia() - && gSavedSettings.getBOOL("MediaOnAPrimUI")) + if (media_impl.isNull() || !media_impl->hasMedia()) + return false; + + if (gSavedSettings.getBOOL("MediaOnAPrimUI")) { LLObjectSelectionHandle selection = LLViewerMediaFocus::getInstance()->getSelection(); - if (! selection->contains(pick.getObject(), pick.mObjectFace)) + if (!selection->contains(pick.getObject(), pick.mObjectFace)) { LLViewerMediaFocus::getInstance()->setFocusFace(TRUE, pick.getObject(), pick.mObjectFace, media_impl); } @@ -941,7 +934,7 @@ static bool handle_media_click(const LLPickInfo& pick) return false; } -static bool handle_media_hover(const LLPickInfo& pick) +bool LLToolPie::handleMediaHover(const LLPickInfo& pick) { //FIXME: how do we handle object in different parcel than us? LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); @@ -959,7 +952,6 @@ static bool handle_media_hover(const LLPickInfo& pick) return false; } - // HACK: This is directly referencing an impl name. BAD! // This can be removed when we have a truly generic media browser that only // builds an impl based on the type of url it is passed. @@ -992,6 +984,26 @@ static bool handle_media_hover(const LLPickInfo& pick) return false; } +bool LLToolPie::handleMediaMouseUp() +{ + bool result = false; + if(mMediaMouseCaptureID.notNull()) + { + // Face media needs to know the mouse went up. + viewer_media_t media_impl = LLViewerMedia::getMediaImplFromTextureID(mMediaMouseCaptureID); + if(media_impl) + { + // This will send a mouseUp event to the plugin using the last known mouse coordinate (from a mouseDown or mouseMove), which is what we want. + media_impl->onMouseCaptureLost(); + } + + mMediaMouseCaptureID.setNull(); + + result = true; + } + + return result; +} static void handle_click_action_open_media(LLPointer objectp) { @@ -1017,14 +1029,6 @@ static void handle_click_action_open_media(LLPointer objectp) std::string media_type = std::string ( parcel->getMediaType() ); LLStringUtil::trim(media_url); - // Get the scheme, see if that is handled as well. - LLURI uri(media_url); - std::string media_scheme = uri.scheme() != "" ? uri.scheme() : "http"; - - // HACK: This is directly referencing an impl name. BAD! - // This can be removed when we have a truly generic media browser that only - // builds an impl based on the type of url it is passed. - LLWeb::loadURL(media_url); } @@ -1054,3 +1058,328 @@ static ECursorType cursor_from_parcel_media(U8 click_action) return UI_CURSOR_TOOLPLAY; } } + + +// True if we handled the event. +BOOL LLToolPie::handleRightClickPick() +{ + S32 x = mPick.mMousePt.mX; + S32 y = mPick.mMousePt.mY; + MASK mask = mPick.mKeyMask; + + if (mPick.mPickType != LLPickInfo::PICK_LAND) + { + LLViewerParcelMgr::getInstance()->deselectLand(); + } + + // didn't click in any UI object, so must have clicked in the world + LLViewerObject *object = mPick.getObject(); + LLViewerObject *parent = NULL; + if(object) + parent = object->getRootEdit(); + + // Can't ignore children here. + LLToolSelect::handleObjectSelection(mPick, FALSE, TRUE); + + // Spawn pie menu + if (mPick.mPickType == LLPickInfo::PICK_LAND) + { + LLParcelSelectionHandle selection = LLViewerParcelMgr::getInstance()->selectParcelAt( mPick.mPosGlobal ); + gMenuHolder->setParcelSelection(selection); + gPieLand->show(x, y, true); + + showVisualContextMenuEffect(); + + } + else if (mPick.mObjectID == gAgent.getID() ) + { + if(!gPieSelf) + { + //either at very early startup stage or at late quitting stage, + //this event is ignored. + return TRUE ; + } + + gPieSelf->show(x, y, true); + } + else if (object) + { + gMenuHolder->setObjectSelection(LLSelectMgr::getInstance()->getSelection()); + + bool is_other_attachment = (object->isAttachment() && !object->isHUDAttachment() && !object->permYouOwner()); + if (object->isAvatar() + || is_other_attachment) + { + // Find the attachment's avatar + while( object && object->isAttachment()) + { + object = (LLViewerObject*)object->getParent(); + llassert(object); + } + + if (!object) + { + return TRUE; // unexpected, but escape + } + + // Object is an avatar, so check for mute by id. + LLVOAvatar* avatar = (LLVOAvatar*)object; + std::string name = avatar->getFullname(); + std::string mute_msg; + if (LLMuteList::getInstance()->isMuted(avatar->getID(), name)) + { + mute_msg = LLTrans::getString("UnmuteAvatar"); + } + else + { + mute_msg = LLTrans::getString("MuteAvatar"); + } + gMenuHolder->childSetText("Avatar Mute", mute_msg); + +// [RLVa:KB] - Checked: 2010-04-11 (RLVa-1.2.0e) | Modified: RLVa-1.1.0l + // Don't show the pie menu on empty selection when fartouch restricted [see LLToolSelect::handleObjectSelection()] + if ( (!rlv_handler_t::isEnabled()) || (!LLSelectMgr::getInstance()->getSelection()->isEmpty()) || + (!gRlvHandler.hasBehaviour(RLV_BHVR_FARTOUCH)) ) + { +// [/RLVa:KB] + /*if (is_other_attachment) + { + gPieAttachmentOther->show(x, y, true); + } + else*/ + { + gPieAvatar->show(x, y, true); + } +// [RLVa:KB] - Checked: 2010-04-11 (RLVa-1.2.0e) | Modified: RLVa-1.1.0l + } + else + { + make_ui_sound("UISndInvalidOp"); + } +// [/RLVa:KB] + } + else if (object->isAttachment()) + { + gPieAttachment->show(x, y, true); + } + else + { + // BUG: What about chatting child objects? + std::string name; + LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstRootNode(); + if (node) + { + name = node->mName; + } + std::string mute_msg; + if (LLMuteList::getInstance()->isMuted(object->getID(), name)) + { + mute_msg = LLTrans::getString("UnmuteObject"); + } + else + { + mute_msg = LLTrans::getString("MuteObject2"); + } + +// [RLVa:KB] - Checked: 2010-04-11 (RLVa-1.2.el) | Modified: RLVa-1.1.0l + // Don't show the pie menu on empty selection when fartouch/interaction restricted + // (not entirely accurate in case of Tools / Select Only XXX [see LLToolSelect::handleObjectSelection()] + if ( (!rlv_handler_t::isEnabled()) || (!LLSelectMgr::getInstance()->getSelection()->isEmpty()) || + (!gRlvHandler.hasBehaviour(RLV_BHVR_FARTOUCH)) ) + { +// [/RLVa:KB] + gMenuHolder->childSetText("Object Mute", mute_msg); + gPieObject->show(x, y, true); + + showVisualContextMenuEffect(); +// [RLVa:KB] - Checked: 2010-04-11 (RLVa-1.2.el) | Modified: RLVa-1.1.0l + } + else + { + make_ui_sound("UISndInvalidOp"); + } +// [/RLVa:KB] + } + } + + LLTool::handleRightMouseDown(x, y, mask); + // We handled the event. + return TRUE; +} + +void LLToolPie::showVisualContextMenuEffect() +{ + // + if (gSavedSettings.getBOOL("DisablePointAtAndBeam")) return; + // + // VEFFECT: ShowPie + LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_SPHERE, TRUE); + effectp->setPositionGlobal(mPick.mPosGlobal); + effectp->setColor(LLColor4U(gAgent.getEffectColor())); + effectp->setDuration(0.25f); +} + +typedef enum e_near_far +{ + NEAR_INTERSECTION, + FAR_INTERSECTION +} ENearFar; + +bool intersect_ray_with_sphere( const LLVector3& ray_pt, const LLVector3& ray_dir, const LLVector3& sphere_center, F32 sphere_radius, e_near_far near_far, LLVector3& intersection_pt) +{ + // do ray/sphere intersection by solving quadratic equation + LLVector3 sphere_to_ray_start_vec = ray_pt - sphere_center; + F32 B = 2.f * ray_dir * sphere_to_ray_start_vec; + F32 C = sphere_to_ray_start_vec.lengthSquared() - (sphere_radius * sphere_radius); + + F32 discriminant = B*B - 4.f*C; + if (discriminant >= 0.f) + { // intersection detected, now find closest one + F32 t0 = (-B - sqrtf(discriminant)) / 2.f; + + if (t0 > 0.f && near_far == NEAR_INTERSECTION) + { + intersection_pt = ray_pt + ray_dir * t0; + } + else + { + F32 t1 = (-B + sqrtf(discriminant)) / 2.f; + intersection_pt = ray_pt + ray_dir * t1; + } + return true; + } + else + { // no intersection + return false; + } +} + +void LLToolPie::startCameraSteering() +{ + mMouseOutsideSlop = true; + mBlockClickToWalk = true; + + if (gAgentCamera.getFocusOnAvatar()) + { + mSteerPick = mPick; + + // handle special cases of steering picks + LLViewerObject* avatar_object = mSteerPick.getObject(); + + // get pointer to avatar + while (avatar_object && !avatar_object->isAvatar()) + { + avatar_object = (LLViewerObject*)avatar_object->getParent(); + } + + // if clicking on own avatar... + if (avatar_object && ((LLVOAvatar*)avatar_object)->isSelf()) + { + // ...project pick point a few meters in front of avatar + mSteerPick.mPosGlobal = gAgent.getPositionGlobal() + LLVector3d(LLViewerCamera::instance().getAtAxis()) * 3.0; + } + + if (!mSteerPick.isValid()) + { + mSteerPick.mPosGlobal = gAgent.getPosGlobalFromAgent( + LLViewerCamera::instance().getOrigin() + gViewerWindow->mouseDirectionGlobal(mSteerPick.mMousePt.mX, mSteerPick.mMousePt.mY) * 100.f); + } + + setMouseCapture(TRUE); + + mMouseSteerX = mMouseDownX; + mMouseSteerY = mMouseDownY; + const LLVector3 camera_to_rotation_center = gAgent.getFrameAgent().getOrigin() - LLViewerCamera::instance().getOrigin(); + const LLVector3 rotation_center_to_pick = gAgent.getPosAgentFromGlobal(mSteerPick.mPosGlobal) - gAgent.getFrameAgent().getOrigin(); + + mClockwise = camera_to_rotation_center * rotation_center_to_pick < 0.f; + /* Singu TODO: llhudeffectblob + if (mMouseSteerGrabPoint) { mMouseSteerGrabPoint->markDead(); } + mMouseSteerGrabPoint = (LLHUDEffectBlob *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_BLOB, FALSE); + mMouseSteerGrabPoint->setPositionGlobal(mSteerPick.mPosGlobal); + mMouseSteerGrabPoint->setColor(LLColor4U(170, 210, 190)); + mMouseSteerGrabPoint->setPixelSize(5); + mMouseSteerGrabPoint->setDuration(2.f); + */ + } +} + +void LLToolPie::steerCameraWithMouse(S32 x, S32 y) +{ + const LLViewerCamera& camera = LLViewerCamera::instance(); + const LLCoordFrame& rotation_frame = gAgent.getFrameAgent(); + const LLVector3 pick_pos = gAgent.getPosAgentFromGlobal(mSteerPick.mPosGlobal); + const LLVector3 pick_rotation_center = rotation_frame.getOrigin() + parallel_component(pick_pos - rotation_frame.getOrigin(), rotation_frame.getUpAxis()); + const F32 MIN_ROTATION_RADIUS_FRACTION = 0.2f; + const F32 min_rotation_radius = MIN_ROTATION_RADIUS_FRACTION * dist_vec(pick_rotation_center, camera.getOrigin());; + const F32 pick_distance_from_rotation_center = llclamp(dist_vec(pick_pos, pick_rotation_center), min_rotation_radius, F32_MAX); + const LLVector3 camera_to_rotation_center = pick_rotation_center - camera.getOrigin(); + const LLVector3 adjusted_camera_pos = LLViewerCamera::instance().getOrigin() + projected_vec(camera_to_rotation_center, rotation_frame.getUpAxis()); + const F32 camera_distance_from_rotation_center = dist_vec(adjusted_camera_pos, pick_rotation_center); + + LLVector3 mouse_ray = orthogonal_component(gViewerWindow->mouseDirectionGlobal(x, y), rotation_frame.getUpAxis()); + mouse_ray.normalize(); + + LLVector3 old_mouse_ray = orthogonal_component(gViewerWindow->mouseDirectionGlobal(mMouseSteerX, mMouseSteerY), rotation_frame.getUpAxis()); + old_mouse_ray.normalize(); + + F32 yaw_angle; + F32 old_yaw_angle; + LLVector3 mouse_on_sphere; + LLVector3 old_mouse_on_sphere; + + if (intersect_ray_with_sphere( + adjusted_camera_pos, + mouse_ray, + pick_rotation_center, + pick_distance_from_rotation_center, + FAR_INTERSECTION, + mouse_on_sphere)) + { + LLVector3 mouse_sphere_offset = mouse_on_sphere - pick_rotation_center; + yaw_angle = atan2f(mouse_sphere_offset * rotation_frame.getLeftAxis(), mouse_sphere_offset * rotation_frame.getAtAxis()); + } + else + { + yaw_angle = F_PI_BY_TWO + asinf(pick_distance_from_rotation_center / camera_distance_from_rotation_center); + if (mouse_ray * rotation_frame.getLeftAxis() < 0.f) + { + yaw_angle *= -1.f; + } + } + + if (intersect_ray_with_sphere( + adjusted_camera_pos, + old_mouse_ray, + pick_rotation_center, + pick_distance_from_rotation_center, + FAR_INTERSECTION, + old_mouse_on_sphere)) + { + LLVector3 mouse_sphere_offset = old_mouse_on_sphere - pick_rotation_center; + old_yaw_angle = atan2f(mouse_sphere_offset * rotation_frame.getLeftAxis(), mouse_sphere_offset * rotation_frame.getAtAxis()); + } + else + { + old_yaw_angle = F_PI_BY_TWO + asinf(pick_distance_from_rotation_center / camera_distance_from_rotation_center); + + if (mouse_ray * rotation_frame.getLeftAxis() < 0.f) + { + old_yaw_angle *= -1.f; + } + } + + const F32 delta_angle = yaw_angle - old_yaw_angle; + + if (mClockwise) + { + gAgent.yaw(delta_angle); + } + else + { + gAgent.yaw(-delta_angle); + } + + mMouseSteerX = x; + mMouseSteerY = y; +} diff --git a/indra/newview/lltoolpie.h b/indra/newview/lltoolpie.h index a8fe44ab3..f811c53c2 100644 --- a/indra/newview/lltoolpie.h +++ b/indra/newview/lltoolpie.h @@ -3,10 +3,9 @@ * @brief LLToolPie class header file * * $LicenseInfo:firstyear=2001&license=viewergpl$ - * + * Second Life Viewer Source Code * 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 @@ -42,9 +41,11 @@ class LLObjectSelection; class LLToolPie : public LLTool, public LLSingleton { + LOG_CLASS(LLToolPie); public: LLToolPie( ); + // Virtual functions inherited from LLMouseHandler virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask); virtual BOOL handleRightMouseDown(S32 x, S32 y, MASK mask); virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask); @@ -58,36 +59,61 @@ public: virtual void stopEditing(); virtual void onMouseCaptureLost(); + virtual void handleSelect(); virtual void handleDeselect(); virtual LLTool* getOverrideTool(MASK mask); LLPickInfo& getPick() { return mPick; } +// [RLVa:KB] - Checked: 2010-03-06 (RLVa-1.2.0c) | Added: RLVa-1.2.0a + LLPickInfo& getHoverPick() { return mHoverPick; } +// [/RLVa:KB] U8 getClickAction() { return mClickAction; } LLViewerObject* getClickActionObject() { return mClickActionObject; } LLObjectSelection* getLeftClickSelection() { return (LLObjectSelection*)mLeftClickSelection; } void resetSelection(); + void walkToClickedLocation(); + void blockClickToWalk() { mBlockClickToWalk = true; } + void stopClickToWalk(); - static void leftMouseCallback(const LLPickInfo& pick_info); - static void rightMouseCallback(const LLPickInfo& pick_info); - static void selectionPropertiesReceived(); private: - BOOL outsideSlop(S32 x, S32 y, S32 start_x, S32 start_y); - BOOL pickAndShowMenu(BOOL edit_menu); - BOOL useClickAction(BOOL always_show, MASK mask, LLViewerObject* object, - LLViewerObject* parent); + BOOL outsideSlop (S32 x, S32 y, S32 start_x, S32 start_y); + BOOL handleLeftClickPick(); + BOOL handleRightClickPick(); + BOOL useClickAction (MASK mask, LLViewerObject* object,LLViewerObject* parent); + + void showVisualContextMenuEffect(); + ECursorType cursorFromObject(LLViewerObject* object); + + bool handleMediaClick(const LLPickInfo& info); + bool handleMediaHover(const LLPickInfo& info); + bool handleMediaMouseUp(); + + void steerCameraWithMouse(S32 x, S32 y); + void startCameraSteering(); + void stopCameraSteering(); + bool inCameraSteerMode(); private: - BOOL mPieMouseButtonDown; - BOOL mGrabMouseButtonDown; - BOOL mMouseOutsideSlop; // for this drag, has mouse moved outside slop region + bool mMouseButtonDown; + bool mMouseOutsideSlop; // for this drag, has mouse moved outside slop region + S32 mMouseDownX; + S32 mMouseDownY; + S32 mMouseSteerX; + S32 mMouseSteerY; + bool mClockwise; + bool mBlockClickToWalk; + LLUUID mMediaMouseCaptureID; LLPickInfo mPick; + LLPickInfo mHoverPick; + LLPickInfo mSteerPick; LLPointer mClickActionObject; U8 mClickAction; LLSafeHandle mLeftClickSelection; + const LLCachedControl mClickActionBuyEnabled; + const LLCachedControl mClickActionPayEnabled; }; - #endif diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp index 9e30efa3c..1fa7a4eca 100644 --- a/indra/newview/llviewercontrol.cpp +++ b/indra/newview/llviewercontrol.cpp @@ -792,7 +792,7 @@ void settings_setup_listeners() gSavedSettings.getControl("AscentAvatarZModifier")->getSignal()->connect(boost::bind(&handleAscentAvatarModifier, _2)); gSavedSettings.getControl("CurlMaxTotalConcurrentConnections")->getSignal()->connect(boost::bind(&AICurlInterface::handleCurlMaxTotalConcurrentConnections, _2)); - gSavedSettings.getControl("CurlConcurrentConnectionsPerHost")->getSignal()->connect(boost::bind(&AICurlInterface::handleCurlConcurrentConnectionsPerHost, _2)); + gSavedSettings.getControl("CurlConcurrentConnectionsPerService")->getSignal()->connect(boost::bind(&AICurlInterface::handleCurlConcurrentConnectionsPerService, _2)); gSavedSettings.getControl("NoVerifySSLCert")->getSignal()->connect(boost::bind(&AICurlInterface::handleNoVerifySSLCert, _2)); gSavedSettings.getControl("CurlTimeoutDNSLookup")->getValidateSignal()->connect(boost::bind(&validateCurlTimeoutDNSLookup, _2)); diff --git a/indra/newview/llviewergenericmessage.cpp b/indra/newview/llviewergenericmessage.cpp index 312fae50a..c4675e7bb 100644 --- a/indra/newview/llviewergenericmessage.cpp +++ b/indra/newview/llviewergenericmessage.cpp @@ -105,7 +105,7 @@ void process_generic_message(LLMessageSystem* msg, void**) } else if (agent_id != gAgent.getID()) { - llwarns << "GenericMessage for wrong agent" << llendl; + llwarns << "GenericMessage for wrong agent " << agent_id << llendl; return; } else diff --git a/indra/newview/llviewergesture.h b/indra/newview/llviewergesture.h index f5c4e578d..de7288ca0 100644 --- a/indra/newview/llviewergesture.h +++ b/indra/newview/llviewergesture.h @@ -33,7 +33,6 @@ #ifndef LL_LLVIEWERGESTURE_H #define LL_LLVIEWERGESTURE_H -#include "llanimationstates.h" #include "lluuid.h" #include "llstring.h" #include "lldarray.h" diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index 0063c9073..97ea6d71a 100644 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -63,11 +63,140 @@ #include "llfloatercustomize.h" // #include "llappviewer.h" // System Folders +// // Two do-nothing ops for use in callbacks. void no_op_inventory_func(const LLUUID&) {} void no_op() {} -// + +///---------------------------------------------------------------------------- +/// Helper class to store special inventory item names and their localized values. +///---------------------------------------------------------------------------- +class LLLocalizedInventoryItemsDictionary : public LLSingleton +{ +public: + std::map mInventoryItemsDict; + + LLLocalizedInventoryItemsDictionary() + { + mInventoryItemsDict["New Shape"] = LLTrans::getString("New Shape"); + mInventoryItemsDict["New Skin"] = LLTrans::getString("New Skin"); + mInventoryItemsDict["New Hair"] = LLTrans::getString("New Hair"); + mInventoryItemsDict["New Eyes"] = LLTrans::getString("New Eyes"); + mInventoryItemsDict["New Shirt"] = LLTrans::getString("New Shirt"); + mInventoryItemsDict["New Pants"] = LLTrans::getString("New Pants"); + mInventoryItemsDict["New Shoes"] = LLTrans::getString("New Shoes"); + mInventoryItemsDict["New Socks"] = LLTrans::getString("New Socks"); + mInventoryItemsDict["New Jacket"] = LLTrans::getString("New Jacket"); + mInventoryItemsDict["New Gloves"] = LLTrans::getString("New Gloves"); + mInventoryItemsDict["New Undershirt"] = LLTrans::getString("New Undershirt"); + mInventoryItemsDict["New Underpants"] = LLTrans::getString("New Underpants"); + mInventoryItemsDict["New Skirt"] = LLTrans::getString("New Skirt"); + mInventoryItemsDict["New Alpha"] = LLTrans::getString("New Alpha"); + mInventoryItemsDict["New Tattoo"] = LLTrans::getString("New Tattoo"); + mInventoryItemsDict["New Physics"] = LLTrans::getString("New Physics"); + mInventoryItemsDict["Invalid Wearable"] = LLTrans::getString("Invalid Wearable"); + + mInventoryItemsDict["New Gesture"] = LLTrans::getString("New Gesture"); + mInventoryItemsDict["New Script"] = LLTrans::getString("New Script"); + mInventoryItemsDict["New Folder"] = LLTrans::getString("New Folder"); + mInventoryItemsDict["New Note"] = LLTrans::getString("New Note"); + mInventoryItemsDict["Contents"] = LLTrans::getString("Contents"); + + mInventoryItemsDict["Gesture"] = LLTrans::getString("Gesture"); + mInventoryItemsDict["Male Gestures"] = LLTrans::getString("Male Gestures"); + mInventoryItemsDict["Female Gestures"] = LLTrans::getString("Female Gestures"); + mInventoryItemsDict["Other Gestures"] = LLTrans::getString("Other Gestures"); + mInventoryItemsDict["Speech Gestures"] = LLTrans::getString("Speech Gestures"); + mInventoryItemsDict["Common Gestures"] = LLTrans::getString("Common Gestures"); + + //predefined gestures + + //male + mInventoryItemsDict["Male - Excuse me"] = LLTrans::getString("Male - Excuse me"); + mInventoryItemsDict["Male - Get lost"] = LLTrans::getString("Male - Get lost"); // double space after Male. EXT-8319 + mInventoryItemsDict["Male - Blow kiss"] = LLTrans::getString("Male - Blow kiss"); + mInventoryItemsDict["Male - Boo"] = LLTrans::getString("Male - Boo"); + mInventoryItemsDict["Male - Bored"] = LLTrans::getString("Male - Bored"); + mInventoryItemsDict["Male - Hey"] = LLTrans::getString("Male - Hey"); + mInventoryItemsDict["Male - Laugh"] = LLTrans::getString("Male - Laugh"); + mInventoryItemsDict["Male - Repulsed"] = LLTrans::getString("Male - Repulsed"); + mInventoryItemsDict["Male - Shrug"] = LLTrans::getString("Male - Shrug"); + mInventoryItemsDict["Male - Stick tougue out"] = LLTrans::getString("Male - Stick tougue out"); + mInventoryItemsDict["Male - Wow"] = LLTrans::getString("Male - Wow"); + + //female + mInventoryItemsDict["Female - Chuckle"] = LLTrans::getString("Female - Chuckle"); + mInventoryItemsDict["Female - Cry"] = LLTrans::getString("Female - Cry"); + mInventoryItemsDict["Female - Embarrassed"] = LLTrans::getString("Female - Embarrassed"); + mInventoryItemsDict["Female - Excuse me"] = LLTrans::getString("Female - Excuse me"); + mInventoryItemsDict["Female - Get lost"] = LLTrans::getString("Female - Get lost"); // double space after Female. EXT-8319 + mInventoryItemsDict["Female - Blow kiss"] = LLTrans::getString("Female - Blow kiss"); + mInventoryItemsDict["Female - Boo"] = LLTrans::getString("Female - Boo"); + mInventoryItemsDict["Female - Bored"] = LLTrans::getString("Female - Bored"); + mInventoryItemsDict["Female - Hey"] = LLTrans::getString("Female - Hey"); + mInventoryItemsDict["Female - Hey baby"] = LLTrans::getString("Female - Hey baby"); + mInventoryItemsDict["Female - Laugh"] = LLTrans::getString("Female - Laugh"); + mInventoryItemsDict["Female - Looking good"] = LLTrans::getString("Female - Looking good"); + mInventoryItemsDict["Female - Over here"] = LLTrans::getString("Female - Over here"); + mInventoryItemsDict["Female - Please"] = LLTrans::getString("Female - Please"); + mInventoryItemsDict["Female - Repulsed"] = LLTrans::getString("Female - Repulsed"); + mInventoryItemsDict["Female - Shrug"] = LLTrans::getString("Female - Shrug"); + mInventoryItemsDict["Female - Stick tougue out"]= LLTrans::getString("Female - Stick tougue out"); + mInventoryItemsDict["Female - Wow"] = LLTrans::getString("Female - Wow"); + + //common + mInventoryItemsDict["/bow"] = LLTrans::getString("/bow"); + mInventoryItemsDict["/clap"] = LLTrans::getString("/clap"); + mInventoryItemsDict["/count"] = LLTrans::getString("/count"); + mInventoryItemsDict["/extinguish"] = LLTrans::getString("/extinguish"); + mInventoryItemsDict["/kmb"] = LLTrans::getString("/kmb"); + mInventoryItemsDict["/muscle"] = LLTrans::getString("/muscle"); + mInventoryItemsDict["/no"] = LLTrans::getString("/no"); + mInventoryItemsDict["/no!"] = LLTrans::getString("/no!"); + mInventoryItemsDict["/paper"] = LLTrans::getString("/paper"); + mInventoryItemsDict["/pointme"] = LLTrans::getString("/pointme"); + mInventoryItemsDict["/pointyou"] = LLTrans::getString("/pointyou"); + mInventoryItemsDict["/rock"] = LLTrans::getString("/rock"); + mInventoryItemsDict["/scissor"] = LLTrans::getString("/scissor"); + mInventoryItemsDict["/smoke"] = LLTrans::getString("/smoke"); + mInventoryItemsDict["/stretch"] = LLTrans::getString("/stretch"); + mInventoryItemsDict["/whistle"] = LLTrans::getString("/whistle"); + mInventoryItemsDict["/yes"] = LLTrans::getString("/yes"); + mInventoryItemsDict["/yes!"] = LLTrans::getString("/yes!"); + mInventoryItemsDict["afk"] = LLTrans::getString("afk"); + mInventoryItemsDict["dance1"] = LLTrans::getString("dance1"); + mInventoryItemsDict["dance2"] = LLTrans::getString("dance2"); + mInventoryItemsDict["dance3"] = LLTrans::getString("dance3"); + mInventoryItemsDict["dance4"] = LLTrans::getString("dance4"); + mInventoryItemsDict["dance5"] = LLTrans::getString("dance5"); + mInventoryItemsDict["dance6"] = LLTrans::getString("dance6"); + mInventoryItemsDict["dance7"] = LLTrans::getString("dance7"); + mInventoryItemsDict["dance8"] = LLTrans::getString("dance8"); + } + + /** + * Finds passed name in dictionary and replaces it with found localized value. + * + * @param object_name - string to be localized. + * @return true if passed name was found and localized, false otherwise. + */ + bool localizeInventoryObjectName(std::string& object_name) + { + LL_DEBUGS("InventoryLocalize") << "Searching for localization: " << object_name << LL_ENDL; + + std::map::const_iterator dictionary_iter = mInventoryItemsDict.find(object_name); + + bool found = dictionary_iter != mInventoryItemsDict.end(); + if(found) + { + object_name = dictionary_iter->second; + LL_DEBUGS("InventoryLocalize") << "Found, new name is: " << object_name << LL_ENDL; + } + return found; + } +}; + ///---------------------------------------------------------------------------- /// Local function declarations, constants, enums, and typedefs @@ -165,13 +294,10 @@ void LLViewerInventoryItem::cloneViewerItem(LLPointer& ne void LLViewerInventoryItem::removeFromServer() { // this check is ghetto - if((mParentUUID == gSystemFolderRoot) || (gInventory.isObjectDescendentOf(mUUID, gSystemFolderRoot))) - { - return; - } + if((mParentUUID == gSystemFolderRoot) || (gInventory.isObjectDescendentOf(mUUID, gSystemFolderRoot))) return; // - llinfos << "Removing inventory item " << mUUID << " from server." - << llendl; + lldebugs << "Removing inventory item " << mUUID << " from server." + << llendl; LLInventoryModel::LLCategoryUpdate up(mParentUUID, -1); gInventory.accountForUpdate(up); @@ -189,22 +315,14 @@ void LLViewerInventoryItem::removeFromServer() void LLViewerInventoryItem::updateServer(BOOL is_new) const { // - //if(gAgent.getID() != mPermissions.getOwner()) - //{ - // // *FIX: deal with this better. - // llwarns << "LLViewerInventoryItem::updateServer() - for unowned item" - // << llendl; - if((mParentUUID == gSystemFolderRoot) || (gInventory.isObjectDescendentOf(mUUID, gSystemFolderRoot))) - { + if((mParentUUID == gSystemFolderRoot) || (gInventory.isObjectDescendentOf(mUUID, gSystemFolderRoot))) return; // - return; - } if(!mIsComplete) { // *FIX: deal with this better. llwarns << "LLViewerInventoryItem::updateServer() - for incomplete item" << llendl; - LLNotificationsUtil::add("IncompleteInventoryItem"); + LLNotificationsUtil::add("IncompleteInventoryItem"); return; } if(gAgent.getID() != mPermissions.getOwner()) @@ -235,22 +353,25 @@ void LLViewerInventoryItem::fetchFromServer(void) const { std::string url; - LLViewerRegion* region = gAgent.getRegion(); - // we have to check region. It can be null after region was destroyed. See EXT-245 - if (region) + if (gSavedSettings.getBOOL("UseHTTPInventory")) { - if(gAgent.getID() != mPermissions.getOwner()) - { - url = region->getCapability("FetchLib2"); - } - else - { - url = region->getCapability("FetchInventory2"); - } - } - else - { - llwarns << "Agent Region is absent" << llendl; + LLViewerRegion* region = gAgent.getRegion(); + // we have to check region. It can be null after region was destroyed. See EXT-245 + if (region) + { + if(gAgent.getID() != mPermissions.getOwner()) + { + url = region->getCapability("FetchLib2"); + } + else + { + url = region->getCapability("FetchInventory2"); + } + } + else + { + llwarns << "Agent Region is absent" << llendl; + } } if (!url.empty()) @@ -286,6 +407,9 @@ void LLViewerInventoryItem::fetchFromServer(void) const BOOL LLViewerInventoryItem::unpackMessage(LLSD item) { BOOL rv = LLInventoryItem::fromLLSD(item); + + LLLocalizedInventoryItemsDictionary::getInstance()->localizeInventoryObjectName(mName); + mIsComplete = TRUE; return rv; } @@ -294,6 +418,9 @@ BOOL LLViewerInventoryItem::unpackMessage(LLSD item) BOOL LLViewerInventoryItem::unpackMessage(LLMessageSystem* msg, const char* block, S32 block_num) { BOOL rv = LLInventoryItem::unpackMessage(msg, block, block_num); + + LLLocalizedInventoryItemsDictionary::getInstance()->localizeInventoryObjectName(mName); + mIsComplete = TRUE; return rv; } @@ -429,7 +556,7 @@ void LLViewerInventoryCategory::copyViewerCategory(const LLViewerInventoryCatego { copyCategory(other); mOwnerID = other->mOwnerID; - mVersion = other->mVersion; + setVersion(other->getVersion()); mDescendentCount = other->mDescendentCount; mDescendentsRequested = other->mDescendentsRequested; } @@ -505,7 +632,7 @@ bool LLViewerInventoryCategory::fetch() // if((mUUID == gSystemFolderRoot) || (gInventory.isObjectDescendentOf(mUUID, gSystemFolderRoot))) return false; // - if((VERSION_UNKNOWN == mVersion) && + if((VERSION_UNKNOWN == getVersion()) && (!mDescendentsRequested.getStarted() || mDescendentsRequested.hasExpired())) //Expired check prevents multiple downloads. { @@ -720,6 +847,12 @@ void LLViewerInventoryCategory::changeType(LLFolderType::EType new_folder_type) setPreferredType(new_folder_type); gInventory.addChangedMask(LLInventoryObserver::LABEL, folder_id); } + +void LLViewerInventoryCategory::localizeName() +{ + LLLocalizedInventoryItemsDictionary::getInstance()->localizeInventoryObjectName(mName); +} + ///---------------------------------------------------------------------------- /// Local function definitions ///---------------------------------------------------------------------------- @@ -858,6 +991,25 @@ void create_inventory_item(const LLUUID& agent_id, const LLUUID& session_id, U32 next_owner_perm, LLPointer cb) { + //check if name is equal to one of special inventory items names + //EXT-5839 + std::string server_name = name; + + { + std::map::const_iterator dictionary_iter; + + for (dictionary_iter = LLLocalizedInventoryItemsDictionary::getInstance()->mInventoryItemsDict.begin(); + dictionary_iter != LLLocalizedInventoryItemsDictionary::getInstance()->mInventoryItemsDict.end(); + dictionary_iter++) + { + const std::string& localized_name = dictionary_iter->second; + if(localized_name == name) + { + server_name = dictionary_iter->first; + } + } + } + LLMessageSystem* msg = gMessageSystem; msg->newMessageFast(_PREHASH_CreateInventoryItem); msg->nextBlock(_PREHASH_AgentData); @@ -871,7 +1023,7 @@ void create_inventory_item(const LLUUID& agent_id, const LLUUID& session_id, msg->addS8Fast(_PREHASH_Type, (S8)asset_type); msg->addS8Fast(_PREHASH_InvType, (S8)inv_type); msg->addU8Fast(_PREHASH_WearableType, (U8)wtype); - msg->addStringFast(_PREHASH_Name, name); + msg->addStringFast(_PREHASH_Name, server_name); msg->addStringFast(_PREHASH_Description, desc); gAgent.sendReliableMessage(); diff --git a/indra/newview/llviewerinventory.h b/indra/newview/llviewerinventory.h index 7c9e0652f..18c57f2a3 100644 --- a/indra/newview/llviewerinventory.h +++ b/indra/newview/llviewerinventory.h @@ -3,10 +3,9 @@ * @brief Declaration of the inventory bits that only used on the viewer. * * $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 @@ -211,7 +210,7 @@ public: // Returns true if a fetch was issued. bool fetch(); - // used to help make cacheing more robust - for example, if + // used to help make caching more robust - for example, if // someone is getting 4 packets but logs out after 3. the viewer // may never know the cache is wrong. enum { DESCENDENT_COUNT_UNKNOWN = -1 }; @@ -219,7 +218,7 @@ public: void setDescendentCount(S32 descendents) { mDescendentCount = descendents; } // file handling on the viewer. These are not meant for anything - // other than cacheing. + // other than caching. bool exportFileLocal(LLFILE* fp) const; bool importFileLocal(LLFILE* fp); void determineFolderType(); @@ -227,6 +226,7 @@ public: private: friend class LLInventoryModel; + void localizeName(); // intended to be called from the LLInventoryModel protected: LLUUID mOwnerID; @@ -327,6 +327,7 @@ extern LLInventoryCallbackManager gInventoryCallbacks; #define NOT_WEARABLE (LLWearableType::EType)0 +// *TODO: Find a home for these void create_inventory_item(const LLUUID& agent_id, const LLUUID& session_id, const LLUUID& parent, const LLTransactionID& transaction_id, const std::string& name, diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 63fce86b9..ee3c77fcf 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -3,10 +3,9 @@ * @brief Builds menus out of items. * * $LicenseInfo:firstyear=2002&license=viewergpl$ - * - * Copyright (c) 2002-2009, Linden Research, Inc. - * * Second Life Viewer Source Code + * Copyright (c) 2002-2009, Linden Research, Inc. + * * 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 @@ -34,43 +33,19 @@ #include "llviewermenu.h" -// system library includes -#include -#include -#include - // linden library includes -#include "llaudioengine.h" -#include "indra_constants.h" -#include "llassetstorage.h" - +#include "llanimationstates.h" // For ANIM_AGENT_AWAY +#include "llavatarnamecache.h" // IDEVO +#include "llinventorypanel.h" #include "llnotifications.h" #include "llnotificationsutil.h" -#include "llchat.h" #include "llfeaturemanager.h" -#include "llfocusmgr.h" -#include "llfontgl.h" -#include "llinstantmessage.h" -#include "llpermissionsflags.h" -#include "llrect.h" #include "llsecondlifeurls.h" -#include "lltransactiontypes.h" -#include "llui.h" -#include "llview.h" -#include "llxfermanager.h" -#include "message.h" -#include "raytrace.h" -#include "llsdserialize.h" -#include "llsdutil.h" // -#include "lllocalinventory.h" #include "llfloaterexploreanimations.h" #include "llfloaterexploresounds.h" #include "llfloaterblacklist.h" // -#include "lltimer.h" -#include "llvfile.h" -#include "llvolumemgr.h" #include "statemachine/aifilepicker.h" // newview includes @@ -81,27 +56,14 @@ #include "jcfloaterareasearch.h" #include "llagentpilot.h" -#include "llbox.h" -#include "llcallingcard.h" -#include "llclipboard.h" #include "llcompilequeue.h" #include "llconsole.h" -#include "llcontrol.h" -#include "llviewercontrol.h" #include "lldebugview.h" -#include "lldir.h" -#include "lldrawable.h" -#include "lldrawpoolalpha.h" -#include "lldrawpooltree.h" #include "llenvmanager.h" -#include "llface.h" #include "llfirstuse.h" -#include "llfloater.h" - #include "llfloaterabout.h" -#include "llfloaterbuycurrency.h" #include "llfloateractivespeakers.h" -#include "llfloateranimpreview.h" +#include "llfloaterbvhpreview.h" #include "llfloateravatarinfo.h" #include "llfloateravatarlist.h" #include "llfloateravatartextures.h" @@ -112,7 +74,6 @@ #include "llfloaterbuycontents.h" #include "llfloaterbuycurrency.h" #include "llfloaterbuyland.h" -#include "llfloatercamera.h" #include "llfloaterchat.h" #include "llfloatercustomize.h" #include "llfloaterdaycycle.h" @@ -123,13 +84,10 @@ #include "llfloaterfonttest.h" #include "llfloatergesture.h" #include "llfloatergodtools.h" -#include "llfloatergroupinfo.h" #include "llfloatergroupinvite.h" #include "llfloatergroups.h" - #include "llfloaterhtmlcurrency.h" #include "llfloatermediabrowser.h" // gViewerHtmlHelp -#include "llfloaterhtmlsimple.h" #include "llfloaterhud.h" #include "llfloaterinspect.h" #include "llfloaterinventory.h" @@ -137,13 +95,11 @@ #include "llfloaterland.h" #include "llfloaterlandholdings.h" #include "llfloatermap.h" - #include "llfloatermute.h" #include "llfloateropenobject.h" #include "llfloateroutbox.h" #include "llfloaterpathfindingcharacters.h" #include "llfloaterpathfindinglinksets.h" -#include "llfloaterpermissionsmgr.h" #include "llfloaterperms.h" #include "llfloaterpostprocess.h" #include "llfloaterpreference.h" @@ -156,7 +112,6 @@ #include "llfloaterenvsettings.h" #include "llfloaterstats.h" -#include "llfloaterteleport.h" #include "llfloaterteleporthistory.h" #include "llfloatertest.h" #include "llfloatertools.h" @@ -165,92 +120,55 @@ #include "llfloaterworldmap.h" #include "llfloatermemleak.h" #include "llframestats.h" -#include "llframestatview.h" -#include "llfasttimerview.h" #include "llgivemoney.h" #include "llgroupmgr.h" #include "llhoverview.h" #include "llhudeffecttrail.h" #include "llhudmanager.h" -#include "llimage.h" -#include "llimagebmp.h" -#include "llimagej2c.h" -#include "llimagetga.h" +#include "llimview.h" +#include "llinventorybridge.h" #include "llinventorydefines.h" #include "llinventoryfunctions.h" -#include "llinventorypanel.h" -#include "llinventorybridge.h" -#include "llkeyboard.h" #include "llmakeoutfitdialog.h" -#include "llmenucommands.h" -#include "llmenugl.h" #include "llmimetypes.h" -#include "llmorphview.h" +#include "llmenucommands.h" #include "llmenuoptionpathfindingrebakenavmesh.h" #include "llmoveview.h" #include "llmutelist.h" #include "llnotify.h" #include "llpanellogin.h" -#include "llpanelobject.h" - #include "llparcel.h" - -#include "llpolymesh.h" -#include "llprimitive.h" -#include "llresmgr.h" #include "llselectmgr.h" -#include "llsky.h" #include "llstatusbar.h" -#include "llstatview.h" -#include "llstring.h" -#include "llsurfacepatch.h" -#include "llimview.h" #include "lltextureview.h" -#include "lltool.h" #include "lltoolbar.h" #include "lltoolcomp.h" -#include "lltoolfocus.h" -#include "lltoolgrab.h" #include "lltoolmgr.h" #include "lltoolpie.h" -#include "lltoolplacer.h" #include "lltoolselectland.h" #include "lluictrlfactory.h" -#include "lluploaddialog.h" #include "lluserauth.h" -#include "lluuid.h" #include "llvelocitybar.h" #include "llviewercamera.h" #include "llviewergenericmessage.h" -#include "llviewergesture.h" #include "llviewertexturelist.h" // gTextureList -#include "llviewerinventory.h" #include "llviewermenufile.h" // init_menu_file() #include "llviewermessage.h" #include "llviewernetwork.h" #include "llviewerobjectlist.h" #include "llviewerparcelmgr.h" -#include "llviewerparceloverlay.h" -#include "llviewerregion.h" #include "llviewerstats.h" -#include "llviewerwindow.h" #include "llvoavatarself.h" -#include "llvolume.h" -#include "llweb.h" #include "llworld.h" #include "llworldmap.h" -#include "object_flags.h" #include "pipeline.h" -#include "llappviewer.h" -#include "roles_constants.h" #include "llviewerjoystick.h" +#include "llwaterparammanager.h" #include "llwlanimator.h" #include "llwlparammanager.h" -#include "llwaterparammanager.h" +#include "llfloatercamera.h" #include "llfloaternotificationsconsole.h" -#include "lltexlayer.h" - // #include "llfloatermessagelog.h" #include "shfloatermediaticker.h" @@ -259,16 +177,16 @@ #include "scriptcounter.h" #include "llfloaterdisplayname.h" -#include "llavatarnamecache.h" #include "floaterao.h" #include "slfloatermediafilter.h" #include "llviewerobjectbackup.h" #include "llagentui.h" +#include "lltoolgrab.h" #include "llpathfindingmanager.h" +#include #include "lltexturecache.h" #include "llvovolume.h" -#include #include "hippogridmanager.h" @@ -303,13 +221,13 @@ void handle_test_load_url(void*); // // Evil hackish imported globals -// + //extern BOOL gHideSelectedObjects; //extern BOOL gAllowSelectAvatar; +//extern BOOL gDebugAvatarRotation; extern BOOL gDebugClicks; extern BOOL gDebugWindowProc; extern BOOL gDebugTextEditorTips; -extern BOOL gDebugAvatarRotation; extern BOOL gShowOverlayTitle; extern BOOL gOcclusionCull; // @@ -347,7 +265,6 @@ LLPieMenu* gDetachPieMenu = NULL; LLPieMenu* gDetachScreenPieMenu = NULL; LLPieMenu* gDetachBodyPartPieMenus[8]; -LLMenuItemCallGL* gFakeAway = NULL; LLMenuItemCallGL* gAFKMenu = NULL; LLMenuItemCallGL* gBusyMenu = NULL; @@ -355,7 +272,6 @@ typedef LLMemberListener view_listener_t; // // Local prototypes -// // File Menu void handle_compress_image(void*); @@ -373,8 +289,6 @@ void handle_region_dump_settings(void*); void handle_region_dump_temp_asset_data(void*); void handle_region_clear_temp_asset_data(void*); - - // Object pie menu BOOL sitting_on_selection(); @@ -390,8 +304,6 @@ bool confirm_take(const LLSD& notification, const LLSD& response, LLObjectSelect void handle_buy_object(LLSaleInfo sale_info); void handle_buy_contents(LLSaleInfo sale_info); -bool for_sale_selection(LLSelectNode* nodep); - // Land pie menu void near_sit_down_point(BOOL success, void *); @@ -404,8 +316,7 @@ void handle_talk_to(void *userdata); void handle_agent_stop_moving(void*); void print_packets_lost(void*); void drop_packet(void*); -void velocity_interpolate( void* data ); -void toggle_wind_audio(void); +void velocity_interpolate( void* ); void handle_rebake_textures(void*); BOOL check_admin_override(void*); void handle_admin_override_toggle(void*); @@ -418,6 +329,7 @@ void toggle_show_xui_names(void *); BOOL check_show_xui_names(void *); // Debug UI + void handle_web_search_demo(void*); void handle_web_browser_test(void*); void handle_buy_currency_test(void*); @@ -446,7 +358,6 @@ void handle_singleton_toggle(void *) // void handle_fake_away_status(void*); -void handle_area_search(void*); // for pose stand LLUUID current_pose = LLUUID::null; @@ -492,26 +403,15 @@ BOOL handle_check_pose(void* userdata) { } -void handle_force_ground_sit(void*); -void handle_phantom_avatar(void*); void handle_hide_typing_notification(void*); -void handle_close_all_notifications(void*); void handle_open_message_log(void*); -void handle_edit_ao(void*); -void handle_sounds_explorer(void*); -void handle_blacklist(void*); // -BOOL is_inventory_visible( void* user_data ); void handle_reset_view(); -void disabled_duplicate(void*); void handle_duplicate_in_place(void*); -void handle_repeat_duplicate(void*); -void handle_export(void*); -// void handle_deed_object_to_group(void*); -// BOOL enable_deed_object_to_group(void*); + void handle_object_owner_self(void*); void handle_object_owner_permissive(void*); void handle_object_lock(void*); @@ -526,7 +426,6 @@ void handle_force_parcel_owner_to_me(void*); void handle_force_parcel_to_content(void*); void handle_claim_public_land(void*); -void handle_god_request_havok(void *); void handle_god_request_avatar_geometry(void *); // Hack for easy testing of new avatar geometry void reload_personal_settings_overrides(void *); void reload_vertex_shader(void *); @@ -540,13 +439,6 @@ void force_error_infinite_loop(void *); void force_error_software_exception(void *); void force_error_driver_crash(void *); -void handle_stopall(void*); -//void handle_hinge(void*); -//void handle_ptop(void*); -//void handle_lptop(void*); -//void handle_wheel(void*); -//void handle_dehinge(void*); -BOOL enable_dehinge(void*); void handle_force_delete(void*); void print_object_info(void*); void print_agent_nvpairs(void*); @@ -585,7 +477,6 @@ void handle_test_male(void *); void handle_test_female(void *); void handle_toggle_pg(void*); void handle_dump_attachments(void *); -void handle_show_overlay_title(void*); void handle_dump_avatar_local_textures(void*); void handle_meshes_and_morphs(void*); void handle_mesh_save_llm(void* data); @@ -607,11 +498,9 @@ BOOL enable_selection_you_own_all(void*); BOOL enable_selection_you_own_one(void*); BOOL enable_save_into_inventory(void*); BOOL enable_save_into_task_inventory(void*); -BOOL enable_not_thirdperson(void*); -// BOOL enable_export_selected(void *); -BOOL enable_have_card(void*); -BOOL enable_detach(void*); -BOOL enable_region_owner(void*); + +BOOL enable_detach(const LLSD& = LLSD()); +BOOL is_god_customer_service(void*); void menu_toggle_attached_lights(void* user_data); void menu_toggle_attached_particles(void* user_data); @@ -622,6 +511,12 @@ void region_change(); void parse_simulator_features(); void custom_selected(void* user_data); +void reset_vertex_buffers(void *user_data) +{ + gPipeline.clearRebuildGroups(); + gPipeline.resetVertexBuffers(); +} + class LLMenuParcelObserver : public LLParcelObserver { public: @@ -667,6 +562,7 @@ void pre_init_menus() LLMenuItemGL::sHighlightForeground = gColors.getColor( "MenuItemHighlightFgColor" ); } + void initialize_menus(); //----------------------------------------------------------------------------- @@ -685,13 +581,13 @@ void set_underclothes_menu_options() { if (gMenuHolder && gAgent.isTeen()) { - gMenuHolder->getChild("Self Underpants", TRUE)->setVisible(FALSE); - gMenuHolder->getChild("Self Undershirt", TRUE)->setVisible(FALSE); + gMenuHolder->getChild("Self Underpants")->setVisible(FALSE); + gMenuHolder->getChild("Self Undershirt")->setVisible(FALSE); } if (gMenuBarView && gAgent.isTeen()) { - gMenuBarView->getChild("Menu Underpants", TRUE)->setVisible(FALSE); - gMenuBarView->getChild("Menu Undershirt", TRUE)->setVisible(FALSE); + gMenuBarView->getChild("Menu Underpants")->setVisible(FALSE); + gMenuBarView->getChild("Menu Undershirt")->setVisible(FALSE); } } @@ -804,34 +700,6 @@ void init_menus() // TomY TODO convert these two LLMenuGL*menu; - menu = new LLMenuGL("Singularity"); - menu->setCanTearOff(TRUE); - menu->addChild(new LLMenuItemCallGL( "Close All Dialogs", - &handle_close_all_notifications, NULL, NULL, 'D', MASK_CONTROL | MASK_ALT | MASK_SHIFT)); - menu->addSeparator(); - menu->addChild(new LLMenuItemCallGL( "Fake Away Status", &handle_fake_away_status, NULL)); - menu->addChild(new LLMenuItemCallGL( "Force Ground Sit", &handle_force_ground_sit, NULL)); - menu->addChild(new LLMenuItemCallGL( "Phantom Avatar", &handle_phantom_avatar, NULL, NULL, 'P', MASK_CONTROL | MASK_ALT)); - menu->addSeparator(); - menu->addChild(new LLMenuItemCallGL( "Animation Override...", - &handle_edit_ao, NULL)); - menu->addChild(new LLMenuItemCheckGL( "Nimble", - &menu_toggle_control, - NULL, - &menu_check_control, - (void*)"Nimble")); - menu->addSeparator(); - menu->addChild(new LLMenuItemCallGL( "Object Area Search", &handle_area_search, NULL)); - - menu->addChild(new LLMenuItemCallGL( "Sound Explorer", - &handle_sounds_explorer, NULL)); - menu->addChild(new LLMenuItemCallGL( "Asset Blacklist", - &handle_blacklist, NULL)); - menu->addChild(new LLMenuItemCheckGL( "Streaming Audio Display", - &handle_ticker_toggle, &handle_ticker_enabled, &handle_singleton_check, NULL )); - - - // // Add in the pose stand ------------------------------------------- /*LLMenuGL* sub = new LLMenuGL("Pose Stand..."); @@ -845,12 +713,6 @@ void init_menus() sub->addChild(new LLMenuItemCallGL( "Legs Half Arms Out", &handle_pose_stand_lhao, NULL)); sub->addChild(new LLMenuItemCallGL( "Stop Pose Stand", &handle_pose_stand_stop, NULL)); // ------------------------------------------------------*/ - - menu->addChild(new LLMenuItemCheckGL("Pose Stand",&handle_toggle_pose, NULL, &handle_check_pose, NULL)); - - //these should always be last in a sub menu - menu->createJumpKeys(); - gMenuBarView->addChild( menu ); menu = new LLMenuGL(CLIENT_MENU_NAME); menu->setCanTearOff(TRUE); @@ -874,7 +736,7 @@ void init_menus() show_debug_menus(); gLoginMenuBarView = (LLMenuBarGL*)LLUICtrlFactory::getInstance()->buildMenu("menu_login.xml", gMenuHolder); - + menu = new LLMenuGL(CLIENT_MENU_NAME); menu->setCanTearOff(FALSE); menu->addChild(new LLMenuItemCallGL("Debug Settings...", handle_singleton_toggle, NULL, NULL)); @@ -889,7 +751,6 @@ void init_menus() /*gLoginMenuBarView->setRect(LLRect(menuBarRect.mLeft, menuBarRect.mTop, gViewerWindow->getRootView()->getRect().getWidth() - menuBarRect.mLeft, menuBarRect.mBottom));*/ - gLoginMenuBarView->setBackgroundColor( color ); gMenuHolder->addChild(gLoginMenuBarView); @@ -900,8 +761,10 @@ void init_menus() ins->setVisible(false); ins = gMenuBarView->getChildView("insert_tools", true, false); ins->setVisible(false); - /* Singu Note: When the advanced menu is made xml, this should be uncommented. + /* Singu Note: When the advanced and/or admin menu is made xml, this should be uncommented. ins = gMenuBarView->getChildView("insert_advanced", true, false); + ins->setVisible(false); + ins = gMenuBarView->getChildView("insert_admin", true, false); ins->setVisible(false);*/ LLEnvManagerNew::instance().setRegionChangeCallback(®ion_change); @@ -1343,7 +1206,6 @@ void init_debug_xui_menu(LLMenuGL* menu) // menu->addChild(new LLMenuItemCheckGL("Show XUI Names", toggle_show_xui_names, NULL, check_show_xui_names, NULL)); - //menu->addChild(new LLMenuItemCallGL("Buy Currency...", handle_buy_currency)); menu->createJumpKeys(); } @@ -1537,7 +1399,7 @@ void init_debug_rendering_menu(LLMenuGL* menu) (void*)LLPipeline::RENDER_DEBUG_WIND_VECTORS)); sub_menu->addChild(new LLMenuItemCheckGL("Complexity", &LLPipeline::toggleRenderDebug, NULL, &LLPipeline::toggleRenderDebugControl, - (void*)LLPipeline::RENDER_DEBUG_RENDER_COMPLEXITY)); ; + (void*)LLPipeline::RENDER_DEBUG_RENDER_COMPLEXITY)); sub_menu = new LLMenuGL("Render Tests"); sub_menu->setCanTearOff(TRUE); @@ -1591,6 +1453,8 @@ void init_debug_rendering_menu(LLMenuGL* menu) item = new LLMenuItemCheckGL("Aggressive Alpha Masking", menu_toggle_control, NULL, menu_check_control, (void*)"SHUseRMSEAutoMask"); menu->addChild(item); + menu->addChild(new LLMenuItemCallGL("Rebuild Vertex Buffers", reset_vertex_buffers, NULL, NULL, 'V', MASK_CONTROL | MASK_SHIFT)); + item = new LLMenuItemCheckGL("Animate Textures", menu_toggle_control, NULL, menu_check_control, (void*)"AnimateTextures"); menu->addChild(item); @@ -1640,7 +1504,7 @@ void init_debug_avatar_menu(LLMenuGL* menu) // HACK for easy testing of avatar geometry sub_menu->addChild(new LLMenuItemCallGL( "Toggle Character Geometry", - &handle_god_request_avatar_geometry, &enable_god_customer_service, NULL)); + &handle_god_request_avatar_geometry, &is_god_customer_service, NULL)); sub_menu->addChild(new LLMenuItemCallGL("Test Male", handle_test_male)); @@ -1686,15 +1550,11 @@ void init_debug_avatar_menu(LLMenuGL* menu) (void*)LLPipeline::RENDER_DEBUG_ATTACHMENT_BYTES)); menu->addChild(new LLMenuItemToggleGL( "Debug Rotation", &LLVOAvatar::sDebugAvatarRotation)); menu->addChild(new LLMenuItemCallGL("Dump Attachments", handle_dump_attachments)); - menu->addChild(new LLMenuItemCallGL("Rebake Textures", handle_rebake_textures, NULL, NULL, 'R', MASK_ALT | MASK_CONTROL )); -// -//#ifndef LL_RELEASE_FOR_DOWNLOAD -// + menu->addChild(new LLMenuItemCallGL("Rebake Textures", handle_rebake_textures)); +#ifndef LL_RELEASE_FOR_DOWNLOAD menu->addChild(new LLMenuItemCallGL("Debug Avatar Textures", handle_debug_avatar_textures, NULL, NULL, 'A', MASK_SHIFT|MASK_CONTROL|MASK_ALT)); menu->addChild(new LLMenuItemCallGL("Dump Local Textures", handle_dump_avatar_local_textures, NULL, NULL, 'M', MASK_SHIFT|MASK_ALT )); -// -//#endif -// +#endif gMeshesAndMorphsMenu = new LLMenuGL("Meshes and Morphs"); menu->addChild(gMeshesAndMorphsMenu); @@ -1761,7 +1621,7 @@ void init_server_menu(LLMenuGL* menu) menu->addChild(sub); sub->addChild(new LLMenuItemCallGL( "Take Copy", - &force_take_copy, &enable_god_customer_service, NULL, + &force_take_copy, &is_god_customer_service, NULL, 'O', MASK_SHIFT | MASK_ALT | MASK_CONTROL)); #ifdef _CORY_TESTING sub->addChild(new LLMenuItemCallGL( "Export Copy", @@ -1774,17 +1634,17 @@ void init_server_menu(LLMenuGL* menu) //sub->addChild(new LLMenuItemCallGL( "Force Ownership/Permissive", // &handle_object_owner_self_and_permissive, NULL, NULL, 'K', MASK_SHIFT | MASK_ALT | MASK_CONTROL)); sub->addChild(new LLMenuItemCallGL( "Force Owner To Me", - &handle_object_owner_self, &enable_god_customer_service)); + &handle_object_owner_self, &is_god_customer_service)); sub->addChild(new LLMenuItemCallGL( "Force Owner Permissive", - &handle_object_owner_permissive, &enable_god_customer_service)); + &handle_object_owner_permissive, &is_god_customer_service)); //sub->addChild(new LLMenuItemCallGL( "Force Totally Permissive", // &handle_object_permissive)); sub->addChild(new LLMenuItemCallGL( "Delete", - &handle_force_delete, &enable_god_customer_service, NULL, KEY_DELETE, MASK_SHIFT | MASK_ALT | MASK_CONTROL)); + &handle_force_delete, &is_god_customer_service, NULL, KEY_DELETE, MASK_SHIFT | MASK_ALT | MASK_CONTROL)); sub->addChild(new LLMenuItemCallGL( "Lock", - &handle_object_lock, &enable_god_customer_service, NULL, 'L', MASK_SHIFT | MASK_ALT | MASK_CONTROL)); + &handle_object_lock, &is_god_customer_service, NULL, 'L', MASK_SHIFT | MASK_ALT | MASK_CONTROL)); sub->addChild(new LLMenuItemCallGL( "Get Asset IDs", - &handle_object_asset_ids, &enable_god_customer_service, NULL, 'I', MASK_SHIFT | MASK_ALT | MASK_CONTROL)); + &handle_object_asset_ids, &is_god_customer_service, NULL, 'I', MASK_SHIFT | MASK_ALT | MASK_CONTROL)); sub->createJumpKeys(); } { @@ -1793,14 +1653,14 @@ void init_server_menu(LLMenuGL* menu) sub->addChild(new LLMenuItemCallGL("Owner To Me", &handle_force_parcel_owner_to_me, - &enable_god_customer_service, NULL)); + &is_god_customer_service, NULL)); sub->addChild(new LLMenuItemCallGL("Set to Linden Content", &handle_force_parcel_to_content, - &enable_god_customer_service, NULL, + &is_god_customer_service, NULL, 'C', MASK_SHIFT | MASK_ALT | MASK_CONTROL)); sub->addSeparator(); sub->addChild(new LLMenuItemCallGL("Claim Public Land", - &handle_claim_public_land, &enable_god_customer_service)); + &handle_claim_public_land, &is_god_customer_service)); sub->createJumpKeys(); } @@ -1809,23 +1669,23 @@ void init_server_menu(LLMenuGL* menu) menu->addChild(sub); sub->addChild(new LLMenuItemCallGL("Dump Temp Asset Data", &handle_region_dump_temp_asset_data, - &enable_god_customer_service, NULL)); + &is_god_customer_service, NULL)); sub->createJumpKeys(); } menu->addChild(new LLMenuItemCallGL( "God Tools...", &LLFloaterGodTools::show, &enable_god_basic, NULL)); + { + LLMenuItemCallGL* item = new LLMenuItemCallGL("insert_admin", NULL); + item->setVisible(false); + menu->addChild(item); + } + menu->addSeparator(); menu->addChild(new LLMenuItemCallGL("Save Region State", - &LLPanelRegionTools::onSaveState, &enable_god_customer_service, NULL)); + &LLPanelRegionTools::onSaveState, &is_god_customer_service, NULL)); -// menu->addChild(new LLMenuItemCallGL("Force Join Group", handle_force_join_group)); -// -// menu->addSeparator(); -// -// menu->addChild(new LLMenuItemCallGL( "OverlayTitle", -// &handle_show_overlay_title, &enable_god_customer_service, NULL)); menu->createJumpKeys(); } @@ -1896,97 +1756,76 @@ class LLObjectTouch : public view_listener_t { bool handleEvent(LLPointer event, const LLSD& userdata) { - LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); - if (!object) return true; - - LLPickInfo pick = LLToolPie::getInstance()->getPick(); - -// [RLVa:KB] - Checked: 2010-04-11 (RLVa-1.2.0e) | Modified: RLVa-1.1.0l | OK - // NOTE: fallback code since we really shouldn't be getting an active selection if we can't touch this - if ( (rlv_handler_t::isEnabled()) && (!gRlvHandler.canTouch(object, pick.mObjectOffset)) ) - { - RLV_ASSERT(false); - return true; - } -// [/RLVa:KB] - - LLMessageSystem *msg = gMessageSystem; - - msg->newMessageFast(_PREHASH_ObjectGrab); - msg->nextBlockFast( _PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->nextBlockFast( _PREHASH_ObjectData); - msg->addU32Fast( _PREHASH_LocalID, object->mLocalID); - msg->addVector3Fast(_PREHASH_GrabOffset, LLVector3::zero ); - msg->nextBlock("SurfaceInfo"); - msg->addVector3("UVCoord", LLVector3(pick.mUVCoords)); - msg->addVector3("STCoord", LLVector3(pick.mSTCoords)); - msg->addS32Fast(_PREHASH_FaceIndex, pick.mObjectFace); - msg->addVector3("Position", pick.mIntersection); - msg->addVector3("Normal", pick.mNormal); - msg->addVector3("Binormal", pick.mBinormal); - msg->sendMessage( object->getRegion()->getHost()); - - // *NOTE: Hope the packets arrive safely and in order or else - // there will be some problems. - // *TODO: Just fix this bad assumption. - msg->newMessageFast(_PREHASH_ObjectDeGrab); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->nextBlockFast(_PREHASH_ObjectData); - msg->addU32Fast(_PREHASH_LocalID, object->mLocalID); - msg->nextBlock("SurfaceInfo"); - msg->addVector3("UVCoord", LLVector3(pick.mUVCoords)); - msg->addVector3("STCoord", LLVector3(pick.mSTCoords)); - msg->addS32Fast(_PREHASH_FaceIndex, pick.mObjectFace); - msg->addVector3("Position", pick.mIntersection); - msg->addVector3("Normal", pick.mNormal); - msg->addVector3("Binormal", pick.mBinormal); - msg->sendMessage(object->getRegion()->getHost()); - + handle_object_touch(); return true; } }; +void handle_object_touch() +{ + LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); + if (!object) return; + + LLPickInfo pick = LLToolPie::getInstance()->getPick(); + +// [RLVa:KB] - Checked: 2010-04-11 (RLVa-1.2.0e) | Modified: RLVa-1.1.0l + // NOTE: fallback code since we really shouldn't be getting an active selection if we can't touch this + if ( (rlv_handler_t::isEnabled()) && (!gRlvHandler.canTouch(object, pick.mObjectOffset)) ) + { + RLV_ASSERT(false); + return; + } +// [/RLVa:KB] + + // *NOTE: Hope the packets arrive safely and in order or else + // there will be some problems. + // *TODO: Just fix this bad assumption. + send_ObjectGrab_message(object, pick, LLVector3::zero); + send_ObjectDeGrab_message(object, pick); +} + + +bool enable_object_touch(const LLSD& userdata) +{ + LLViewerObject* obj = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); + + bool new_value = obj && obj->flagHandleTouch(); +// [RLVa:KB] - Checked: 2010-11-12 (RLVa-1.2.1g) | Added: RLVa-1.2.1g + if ( (rlv_handler_t::isEnabled()) && (new_value) ) + { + // RELEASE-RLVa: [RLVa-1.2.1] Make sure this stays in sync with handle_object_touch() + new_value = gRlvHandler.canTouch(obj, LLToolPie::getInstance()->getPick().mObjectOffset); + } +// [/RLVa:KB] + + std::string touch_text; + + // Update label based on the node touch name if available. + LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstRootNode(); + if (node && node->mValid && !node->mTouchName.empty()) + { + touch_text = node->mTouchName; + } + else + { + touch_text = userdata["data"].asString(); + } + + gMenuHolder->childSetText("Object Touch", touch_text); + gMenuHolder->childSetText("Attachment Object Touch", touch_text); + return new_value; +}; // One object must have touch sensor class LLObjectEnableTouch : public view_listener_t { bool handleEvent(LLPointer event, const LLSD& userdata) { - LLViewerObject* obj = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); - bool new_value = obj && obj->flagHandleTouch(); -// [RLVa:KB] - Version: 1.23.4 | Checked: 2010-01-01 (RLVa-1.1.0l) | Modified: RLVa-1.1.0l - if ( (new_value) && (rlv_handler_t::isEnabled()) && (!gRlvHandler.canTouch(obj, LLToolPie::getInstance()->getPick().mObjectOffset)) ) - { - new_value = false; - } -// [/RLVa:KB] - gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); - - // Update label based on the node touch name if available. - LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstRootNode(); - - std::string touch_text; - if (node && node->mValid && !node->mTouchName.empty()) - { - touch_text = node->mTouchName; - } - else - { - touch_text = userdata["data"].asString(); - } - - gMenuHolder->childSetText("Object Touch", touch_text); - gMenuHolder->childSetText("Attachment Object Touch", touch_text); - + gMenuHolder->findControl(userdata["control"].asString())->setValue(enable_object_touch(userdata)); return true; } }; - //void label_touch(std::string& label, void*) //{ // LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstRootNode(); @@ -2000,56 +1839,47 @@ class LLObjectEnableTouch : public view_listener_t // } //} -bool handle_object_open() +void handle_object_open() { - LLViewerObject* obj = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); - if(!obj) return true; - - LLFloaterOpenObject::show(); - return true; +// [RLVa:KB] - Checked: 2010-04-11 (RLVa-1.2.0e) | Added: RLVa-1.2.0e + if (enable_object_open()) + LLFloaterOpenObject::show(); +// [/RLVa:KB] +// LLFloaterOpenObject::show(); } class LLObjectOpen : public view_listener_t { bool handleEvent(LLPointer event, const LLSD& userdata) { -// [RLVa:KB] - Checked: 2011-09-16 (RLVa-1.1.4b) | Modified: RLVa-1.1.4b - // TODO-RLVa: shouldn't we be checking for fartouch here as well? - const LLViewerObject* pObj = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); - if ( (rlv_handler_t::isEnabled()) && (!gRlvHandler.canEdit(pObj)) ) - { - return true; - } -// [/RLVa:KB] - - return handle_object_open(); + handle_object_open(); + return true; } }; +bool enable_object_open() +{ + // Look for contents in root object, which is all the LLFloaterOpenObject + // understands. + LLViewerObject* obj = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); + if (!obj) return false; + + LLViewerObject* root = obj->getRootEdit(); + if (!root) return false; + + return root->allowOpen(); +} + class LLObjectEnableOpen : public view_listener_t { bool handleEvent(LLPointer event, const LLSD& userdata) { - // Look for contents in root object, which is all the LLFloaterOpenObject - // understands. - LLViewerObject* obj = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); - bool new_value = (obj != NULL); - if (new_value) - { - LLViewerObject* root = obj->getRootEdit(); - if (!root) new_value = false; - else new_value = root->allowOpen(); - } - gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); + gMenuHolder->findControl(userdata["control"].asString())->setValue(enable_object_open()); return true; } }; - - - - class LLViewJoystickFlycam : public view_listener_t { bool handleEvent(LLPointer event, const LLSD& userdata) @@ -2063,8 +1893,8 @@ class LLViewCheckJoystickFlycam : public view_listener_t { bool handleEvent(LLPointer event, const LLSD& userdata) { - bool new_val = LLViewerJoystick::getInstance()->getOverrideCamera(); - gMenuHolder->findControl(userdata["control"].asString())->setValue(new_val); + bool new_value = LLViewerJoystick::getInstance()->getOverrideCamera(); + gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); return true; } }; @@ -2120,73 +1950,99 @@ class LLObjectBuild : public view_listener_t } }; + +void handle_object_edit() +{ + LLViewerParcelMgr::getInstance()->deselectLand(); + +// Singu TODO: Find out if this RLVa patch is still needed, it has been removed from upstream. +// [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) | Modified: RLVa-0.2.0f + if (rlv_handler_t::isEnabled()) + { + bool fRlvCanEdit = (!gRlvHandler.hasBehaviour(RLV_BHVR_EDIT)) && (!gRlvHandler.hasBehaviour(RLV_BHVR_EDITOBJ)); + if (!fRlvCanEdit) + { + LLObjectSelectionHandle hSel = LLSelectMgr::getInstance()->getSelection(); + RlvSelectIsEditable f; + if ((hSel.notNull()) && ((hSel->getFirstRootNode(&f, TRUE)) != NULL)) + return; // Can't edit any object under @edit=n + } + else if ( (gRlvHandler.hasBehaviour(RLV_BHVR_FARTOUCH)) && + (SELECT_TYPE_WORLD == LLSelectMgr::getInstance()->getSelection()->getSelectType()) && + (dist_vec_squared(gAgent.getPositionAgent(), LLToolPie::getInstance()->getPick().mIntersection) > 1.5f * 1.5f) ) + { + // TODO-RLVa: this code is rather redundant since we'll never get an active selection to show a pie menu for + return; // Can't edit in-world objects farther than 1.5m away under @fartouch=n + } + } +// [/RLVa:KB] + + if (gAgentCamera.getFocusOnAvatar() && !LLToolMgr::getInstance()->inEdit()) + { + LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); + + if (selection->getSelectType() == SELECT_TYPE_HUD || !gSavedSettings.getBOOL("EditCameraMovement")) + { + // always freeze camera in space, even if camera doesn't move + // so, for example, follow cam scripts can't affect you when in build mode + gAgentCamera.setFocusGlobal(gAgentCamera.calcFocusPositionTargetGlobal(), LLUUID::null); + gAgentCamera.setFocusOnAvatar(FALSE, ANIMATE); + } + else + { + gAgentCamera.setFocusOnAvatar(FALSE, ANIMATE); + LLViewerObject* selected_objectp = selection->getFirstRootObject(); + if (selected_objectp) + { + // zoom in on object center instead of where we clicked, as we need to see the manipulator handles + gAgentCamera.setFocusGlobal(selected_objectp->getPositionGlobal(), selected_objectp->getID()); + gAgentCamera.cameraZoomIn(0.666f); + gAgentCamera.cameraOrbitOver( 30.f * DEG_TO_RAD ); + gViewerWindow->moveCursorToCenter(); + } + } + } + + gFloaterTools->open(); + + LLToolMgr::getInstance()->setCurrentToolset(gBasicToolset); + gFloaterTools->setEditTool( LLToolCompTranslate::getInstance() ); + + LLViewerJoystick::getInstance()->moveObjects(true); + LLViewerJoystick::getInstance()->setNeedsReset(true); + + // Could be first use + LLFirstUse::useBuild(); + return; +} + class LLObjectEdit : public view_listener_t { bool handleEvent(LLPointer event, const LLSD& userdata) { - LLViewerParcelMgr::getInstance()->deselectLand(); - -// [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) | Modified: RLVa-0.2.0f - if (rlv_handler_t::isEnabled()) - { - bool fRlvCanEdit = (!gRlvHandler.hasBehaviour(RLV_BHVR_EDIT)) && (!gRlvHandler.hasBehaviour(RLV_BHVR_EDITOBJ)); - if (!fRlvCanEdit) - { - LLObjectSelectionHandle hSel = LLSelectMgr::getInstance()->getSelection(); - RlvSelectIsEditable f; - if ((hSel.notNull()) && ((hSel->getFirstRootNode(&f, TRUE)) != NULL)) - return true; // Can't edit any object under @edit=n - } - else if ( (gRlvHandler.hasBehaviour(RLV_BHVR_FARTOUCH)) && - (SELECT_TYPE_WORLD == LLSelectMgr::getInstance()->getSelection()->getSelectType()) && - (dist_vec_squared(gAgent.getPositionAgent(), LLToolPie::getInstance()->getPick().mIntersection) > 1.5f * 1.5f) ) - { - // TODO-RLVa: this code is rather redundant since we'll never get an active selection to show a pie menu for - return true; // Can't edit in-world objects farther than 1.5m away under @fartouch=n - } - } -// [/RLVa:KB] - - if (gAgentCamera.getFocusOnAvatar() && !LLToolMgr::getInstance()->inEdit()) - { - LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); - - if (selection->getSelectType() == SELECT_TYPE_HUD || !gSavedSettings.getBOOL("EditCameraMovement")) - { - // always freeze camera in space, even if camera doesn't move - // so, for example, follow cam scripts can't affect you when in build mode - gAgentCamera.setFocusGlobal(gAgentCamera.calcFocusPositionTargetGlobal(), LLUUID::null); - gAgentCamera.setFocusOnAvatar(FALSE, ANIMATE); - } - else - { - gAgentCamera.setFocusOnAvatar(FALSE, ANIMATE); - LLViewerObject* selected_objectp = selection->getFirstRootObject(); - if (selected_objectp) - { - // zoom in on object center instead of where we clicked, as we need to see the manipulator handles - gAgentCamera.setFocusGlobal(selected_objectp->getPositionGlobal(), selected_objectp->getID()); - gAgentCamera.cameraZoomIn(0.666f); - gAgentCamera.cameraOrbitOver( 30.f * DEG_TO_RAD ); - gViewerWindow->moveCursorToCenter(); - } - } - } - - gFloaterTools->open(); /* Flawfinder: ignore */ - - LLToolMgr::getInstance()->setCurrentToolset(gBasicToolset); - gFloaterTools->setEditTool( LLToolCompTranslate::getInstance() ); - - LLViewerJoystick::getInstance()->moveObjects(true); - LLViewerJoystick::getInstance()->setNeedsReset(true); - - // Could be first use - LLFirstUse::useBuild(); + handle_object_edit(); return true; } }; +// [SL:KB] - Patch: Inventory-AttachmentEdit - Checked: 2010-08-25 (Catznip-2.2.0a) | Added: Catznip-2.1.2a +void handle_attachment_edit(const LLUUID& idItem) +{ + const LLInventoryItem* pItem = gInventory.getItem(idItem); + if ( (!isAgentAvatarValid()) || (!pItem) ) + return; + + LLViewerObject* pAttachObj = gAgentAvatarp->getWornAttachment(pItem->getLinkedUUID()); + if (!pAttachObj) + return; + + LLSelectMgr::getInstance()->deselectAll(); + LLSelectMgr::getInstance()->selectObjectAndFamily(pAttachObj); + + handle_object_edit(); +} +// [/SL:KB] + class LLObjectInspect : public view_listener_t { bool handleEvent(LLPointer event, const LLSD& userdata) @@ -2199,8 +2055,8 @@ class LLObjectInspect : public view_listener_t // Derenderizer. Originally by Phox. class LLObjectDerender : public view_listener_t { - bool handleEvent(LLPointer event, const LLSD& userdata) - { + bool handleEvent(LLPointer event, const LLSD& userdata) + { LLViewerObject* slct = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); if(!slct)return true; @@ -2208,18 +2064,17 @@ class LLObjectDerender : public view_listener_t LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); LLUUID root_key; //delivers null in linked parts if used as getFirstRootNode() - LLSelectNode* node = selection->getFirstRootNode(NULL,TRUE); - + LLSelectNode* node = selection->getFirstRootNode(NULL,TRUE); + /*this works for derendering entire object if child is selected - - LLSelectNode* node = selection->getFirstNode(); + + LLSelectNode* node = selection->getFirstNode(); //Delivers node even when linked parts, but only first node - + LLViewerObject* obj = node->getObject(); LLViewerObject* parent = (LLViewerObject*)obj->getParent();*/ - - - if(node) + + if(node) { root_key = node->getObject()->getID(); llinfos << "Derender node has key " << root_key << llendl; @@ -2228,21 +2083,23 @@ class LLObjectDerender : public view_listener_t { llinfos << "Derender node is null " << llendl; } - + LLViewerRegion* cur_region = gAgent.getRegion(); std::string entry_name; - if(slct->isAvatar()){ + if (slct->isAvatar()) + { LLNameValue* firstname = slct->getNVPair("FirstName"); LLNameValue* lastname = slct->getNVPair("LastName"); entry_name = llformat("Derendered: (AV) %s %s",firstname->getString(),lastname->getString()); } - else{ - if(root_key.isNull()) + else + { + if (root_key.isNull()) { return true; } id = root_key; - if(!node->mName.empty()) + if (!node->mName.empty()) { if(cur_region) entry_name = llformat("Derendered: %s in region %s",node->mName.c_str(),cur_region->getName().c_str()); @@ -2252,25 +2109,21 @@ class LLObjectDerender : public view_listener_t else { if(cur_region) - entry_name = llformat("Derendered: (unkown object) in region %s",cur_region->getName().c_str()); + entry_name = llformat("Derendered: (unknown object) in region %s",cur_region->getName().c_str()); else - entry_name = "Derendered: (unkown object)"; + entry_name = "Derendered: (unknown object)"; } } - - - - LLSD indata; - indata["entry_type"] = 6; //AT_TEXTURE - indata["entry_name"] = entry_name; - indata["entry_agent"] = gAgent.getID(); - - // ...don't kill the avatar - if (!(id == gAgentID)) + if (id != gAgentID) { + LLSD indata; + indata["entry_type"] = 6; //AT_TEXTURE + indata["entry_name"] = entry_name; + indata["entry_agent"] = gAgentID; + LLFloaterBlacklist::addEntry(id,indata); LLSelectMgr::getInstance()->deselectAll(); LLViewerObject *objectp = gObjectList.findObject(id); @@ -2348,7 +2201,7 @@ class LLAvatarReloadTextures : public view_listener_t } } } - else + else { texture_list.addTexture(avatar->getTEImage((ETextureIndex)i)); } @@ -2473,42 +2326,82 @@ BOOL enable_object_build(void*) return can_build; } +bool enable_object_edit() +{ + // *HACK: The new "prelude" Help Islands have a build sandbox area, + // so users need the Edit and Create pie menu options when they are + // there. Eventually this needs to be replaced with code that only + // lets you edit objects if you have permission to do so (edit perms, + // group edit, god). See also lltoolbar.cpp. JC + bool enable = false; + if (gAgent.inPrelude()) + { + enable = LLViewerParcelMgr::getInstance()->allowAgentBuild() + || LLSelectMgr::getInstance()->getSelection()->isAttachment(); + } + else if (LLSelectMgr::getInstance()->selectGetAllValidAndObjectsFound()) + { +// enable = true; +// [RLVa:KB] - Checked: 2010-11-29 (RLVa-1.3.0c) | Modified: RLVa-1.3.0c + bool fRlvCanEdit = (!gRlvHandler.hasBehaviour(RLV_BHVR_EDIT)) && (!gRlvHandler.hasBehaviour(RLV_BHVR_EDITOBJ)); + if (!fRlvCanEdit) + { + LLObjectSelectionHandle hSel = LLSelectMgr::getInstance()->getSelection(); + RlvSelectIsEditable f; + fRlvCanEdit = (hSel.notNull()) && ((hSel->getFirstRootNode(&f, TRUE)) == NULL); + } + enable = fRlvCanEdit; +// [/RLVa:KB] + } + + return enable; +} + class LLEnableEdit : public view_listener_t { bool handleEvent(LLPointer event, const LLSD& userdata) { - // *HACK: The new "prelude" Help Islands have a build sandbox area, - // so users need the Edit and Create pie menu options when they are - // there. Eventually this needs to be replaced with code that only - // lets you edit objects if you have permission to do so (edit perms, - // group edit, god). See also lltoolbar.cpp. JC - bool enable = true; - if (gAgent.inPrelude()) - { - enable = LLViewerParcelMgr::getInstance()->allowAgentBuild() - || LLSelectMgr::getInstance()->getSelection()->isAttachment(); - } -// [RLVa:KB] - Checked: 2009-07-05 (RLVa-1.0.0b) - // TODO-RLV: include fartouch here? - if ( (rlv_handler_t::isEnabled()) && (enable) ) - { - // We have no way of knowing whether we're being called for "Create" or for "Edit", but we can - // make an educated guess based on the currently active selection which puts us halfway there. - BOOL fActiveSelection = LLSelectMgr::getInstance()->getSelection()->getObjectCount(); - - if ( (gRlvHandler.hasBehaviour(RLV_BHVR_EDIT)) && (gRlvHandler.hasBehaviour(RLV_BHVR_REZ)) ) - enable = false; // Edit and rez restricted, disable them both - else if ( (gRlvHandler.hasBehaviour(RLV_BHVR_EDIT)) && (fActiveSelection) ) - enable = false; // Edit restricted and there's an active selection => disable Edit and Create - else if ( (gRlvHandler.hasBehaviour(RLV_BHVR_REZ)) && (!fActiveSelection) ) - enable = false; // Rez restricted and there's no active selection => disable Create - } -// [/RLVa:KB] - gMenuHolder->findControl(userdata["control"].asString())->setValue(enable); + gMenuHolder->findControl(userdata["control"].asString())->setValue(enable_object_edit()); return true; } }; + +bool enable_object_select_in_pathfinding_linksets() +{ + return LLPathfindingManager::getInstance()->isPathfindingEnabledForCurrentRegion() && LLSelectMgr::getInstance()->selectGetEditableLinksets(); +} + +class LLObjectEnablePFLinksetsSelected : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) + { + return enable_object_select_in_pathfinding_linksets(); + } +}; + +class LLObjectPFCharactersSelected : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) + { + LLFloaterPathfindingCharacters::openCharactersWithSelectedObjects(); + return true; + } +}; + +bool enable_object_select_in_pathfinding_characters() +{ + return LLPathfindingManager::getInstance()->isPathfindingEnabledForCurrentRegion() && LLSelectMgr::getInstance()->selectGetViewableCharacters(); +} + +class LLObjectEnablePFCharactersSelected : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) + { + return enable_object_select_in_pathfinding_characters(); + } +}; + class LLSelfRemoveAllAttachments : public view_listener_t { bool handleEvent(LLPointer event, const LLSD& userdata) @@ -2525,13 +2418,13 @@ class LLSelfEnableRemoveAllAttachments : public view_listener_t bool new_value = false; if (isAgentAvatarValid()) { - for (LLVOAvatar::attachment_map_t::iterator iter = gAgentAvatarp->mAttachmentPoints.begin(); + for (LLVOAvatar::attachment_map_t::iterator iter = gAgentAvatarp->mAttachmentPoints.begin(); iter != gAgentAvatarp->mAttachmentPoints.end(); ) { LLVOAvatar::attachment_map_t::iterator curiter = iter++; LLViewerJointAttachment* attachment = curiter->second; // if (attachment->getNumObjects() > 0) -// [RLVa:KB] - Checked: 2010-03-04 (RLVa-1.2.0a) | Added: RLVa-1.2.0a | OK +// [RLVa:KB] - Checked: 2010-03-04 (RLVa-1.2.0a) | Added: RLVa-1.2.0a if ( (attachment->getNumObjects() > 0) && ((!rlv_handler_t::isEnabled()) || (gRlvAttachmentLocks.canDetach(attachment))) ) // [/RLVa:KB] { @@ -2561,9 +2454,6 @@ BOOL enable_has_attachments(void*) return FALSE; } -//--------------------------------------------------------------------------- -// Avatar pie menu -//--------------------------------------------------------------------------- //--------------------------------------------------------------------------- // Avatar pie menu //--------------------------------------------------------------------------- @@ -2577,28 +2467,36 @@ BOOL enable_has_attachments(void*) // } //} +bool enable_object_mute() +{ + LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); + if (!object) return false; + + LLVOAvatar* avatar = find_avatar_from_object(object); + if (avatar) + { + // It's an avatar + bool is_linden = + LLMuteList::getInstance()->isLinden(avatar->getID()); + bool is_self = avatar->isSelf(); +// return !is_linden && !is_self; +// [RLVa:KB] - Checked: 2010-08-25 (RLVa-1.2.1b) | Added: RLVa-1.2.1b + return !is_linden && !is_self && !gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES); +// [/RLVa:KB] + } + else + { + // Just a regular object + return LLSelectMgr::getInstance()->getSelection()->contains( object, SELECT_ALL_TES ) && + !LLMuteList::getInstance()->isMuted(object->getID()); + } +} + class LLObjectEnableMute : public view_listener_t { bool handleEvent(LLPointer event, const LLSD& userdata) { - LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); - bool new_value = (object != NULL); - if (new_value) - { - LLVOAvatar* avatar = find_avatar_from_object(object); - if (avatar) - { - // It's an avatar - LLNameValue *lastname = avatar->getNVPair("LastName"); - BOOL is_linden = lastname && !LLStringUtil::compareStrings(lastname->getString(), "Linden"); - BOOL is_self = avatar->isSelf(); - new_value = !is_linden && !is_self; -// [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e) | OK - new_value &= (!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)); -// [/RLVa:KB] - } - } - gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); + gMenuHolder->findControl(userdata["control"].asString())->setValue(enable_object_mute()); return true; } }; @@ -2616,11 +2514,9 @@ class LLObjectMute : public view_listener_t LLVOAvatar* avatar = find_avatar_from_object(object); if (avatar) { -// [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e) | Added: RLVa-1.0.0e | OK +// [RLVa:KB] - Checked: 2010-08-25 (RLVa-1.2.1b) | Added: RLVa-1.0.0e if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) - { - return true; // Fallback code [see LLObjectEnableMute::handleEvent()] - } + return true; // [/RLVa:KB] id = avatar->getID(); @@ -2824,7 +2720,7 @@ class LLKillEmAll : public view_listener_t */ LLSelectMgr::getInstance()->selectionUpdateTemporary(1);//set temp to TRUE LLVector3 pos = objpos->getPosition();//get the x and the y - pos.mV[VZ] = 340282346638528859811704183484516925440.0f;//create the z + pos.mV[VZ] = FLT_MAX;//create the z objpos->setPositionParent(pos);//set the x y z LLSelectMgr::getInstance()->sendMultipleUpdate(UPD_POSITION);//send the data } @@ -2854,20 +2750,20 @@ class LLObjectMeasure : public view_listener_t startMeasurePoint = position; startpoint_set = true; - chat.mText = llformat("Start point set"); - LLFloaterChat::addChat(chat); + chat.mText = LLTrans::getString("StartPointSet"); } else { - chat.mText = llformat("End point set"); + chat.mText = LLTrans::getString("EndPointSet"); LLFloaterChat::addChat(chat); - F32 fdist = dist_vec(startMeasurePoint, position); + LLStringUtil::format_map_t args; + args["[DIST]"] = boost::lexical_cast(dist_vec(startMeasurePoint, position)); - chat.mText = llformat("Distance: %fm", fdist); - LLFloaterChat::addChat(chat); + chat.mText = LLTrans::getString("MeasuredDistance", args); startpoint_set = false; } + LLFloaterChat::addChat(chat); return true; } }; @@ -2881,41 +2777,6 @@ class LLObjectPFLinksetsSelected : public view_listener_t } }; -bool enable_object_select_in_pathfinding_linksets() -{ - return LLPathfindingManager::getInstance()->isPathfindingEnabledForCurrentRegion() && LLSelectMgr::getInstance()->selectGetEditableLinksets(); -} - -class LLObjectEnablePFLinksetsSelected : public view_listener_t -{ - bool handleEvent(LLPointer event, const LLSD& userdata) - { - return enable_object_select_in_pathfinding_linksets(); - } -}; - -class LLObjectPFCharactersSelected : public view_listener_t -{ - bool handleEvent(LLPointer event, const LLSD& userdata) - { - LLFloaterPathfindingCharacters::openCharactersWithSelectedObjects(); - return true; - } -}; - -bool enable_object_select_in_pathfinding_characters() -{ - return LLPathfindingManager::getInstance()->isPathfindingEnabledForCurrentRegion() && LLSelectMgr::getInstance()->selectGetViewableCharacters(); -} - -class LLObjectEnablePFCharactersSelected : public view_listener_t -{ - bool handleEvent(LLPointer event, const LLSD& userdata) - { - return enable_object_select_in_pathfinding_characters(); - } -}; - class LLAvatarAnims : public view_listener_t { bool handleEvent(LLPointer event, const LLSD& userdata) @@ -2933,15 +2794,6 @@ class LLAvatarAnims : public view_listener_t bool handle_go_to() { -// [RLVa:KB] - Checked: 2009-10-10 (RLVa-1.0.5a) | Modified: RLVa-1.0.5a -/* - if ( (rlv_handler_t::isEnabled()) && (gAgent.forwardGrabbed()) && (gRlvHandler.hasLockedAttachment(RLV_LOCK_REMOVE)) ) - { - return true; - } -*/ -// [/RLVa:KB] - // try simulator autopilot std::vector strings; std::string val; @@ -2979,6 +2831,19 @@ class LLGoToObject : public view_listener_t } }; +class LLAvatarReportAbuse : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) + { + LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() ); + if(avatar) + { + LLFloaterReporter::showFromObject(avatar->getID()); + } + return true; + } +}; + //--------------------------------------------------------------------------- // Object backup //--------------------------------------------------------------------------- @@ -2987,8 +2852,7 @@ class LLObjectEnableExport : public view_listener_t { bool handleEvent(LLPointer event, const LLSD& userdata) { - LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); - bool new_value = (object != NULL); + bool new_value = !!LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); if (new_value) { struct ff : public LLSelectedNodeFunctor @@ -3022,11 +2886,7 @@ class LLObjectExport : public view_listener_t { bool handleEvent(LLPointer event, const LLSD& userdata) { - LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); - if (object) - { - LLObjectBackup::getInstance()->exportObject(); - } + LLObjectBackup::getInstance()->exportObject(); return true; } }; @@ -3068,11 +2928,11 @@ bool callback_freeze(const LLSD& notification, const LLSD& response) if (0 == option || 1 == option) { - U32 flags = 0x0; + U32 flags = KICK_FLAGS_FREEZE; if (1 == option) { // unfreeze - flags |= 0x1; + flags |= KICK_FLAGS_UNFREEZE; } LLMessageSystem* msg = gMessageSystem; @@ -3093,6 +2953,58 @@ bool callback_freeze(const LLSD& notification, const LLSD& response) return false; } + +void handle_avatar_freeze(const LLSD& avatar_id) +{ + // Use avatar_id if available, otherwise default to right-click avatar + LLVOAvatar* avatar = NULL; + if (avatar_id.asUUID().notNull()) + { + avatar = find_avatar_from_object(avatar_id.asUUID()); + } + else + { + avatar = find_avatar_from_object( + LLSelectMgr::getInstance()->getSelection()->getPrimaryObject()); + } + + if( avatar ) + { + std::string fullname = avatar->getFullname(); + LLSD payload; + payload["avatar_id"] = avatar->getID(); + + if (!fullname.empty()) + { + LLSD args; +// args["AVATAR_NAME"] = fullname; +// [RLVa:KB] - Checked: 2010-09-28 (RLVa-1.2.1f) | Modified: RLVa-1.0.0e + args["AVATAR_NAME"] = (!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) ? fullname : RlvStrings::getAnonym(fullname); +// [/RLVa:KB] + LLNotificationsUtil::add("FreezeAvatarFullname", + args, + payload, + callback_freeze); + } + else + { + LLNotificationsUtil::add("FreezeAvatar", + LLSD(), + payload, + callback_freeze); + } + } +} + +class LLAvatarFreeze : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) + { + handle_avatar_freeze(LLUUID::null); + return true; + } +}; + class LLScriptCount : public view_listener_t { bool handleEvent(LLPointer event, const LLSD& userdata) @@ -3148,61 +3060,11 @@ class LLObjectEnableScriptDelete : public view_listener_t } }; -class LLAvatarFreeze : public view_listener_t -{ - bool handleEvent(LLPointer event, const LLSD& userdata) - { - LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() ); - if( avatar ) - { - std::string fullname = avatar->getFullname(); - LLSD payload; - payload["avatar_id"] = avatar->getID(); - - if (!fullname.empty()) - { - LLSD args; -// args["AVATAR_NAME"] = fullname; -// [RLVa:KB] - Checked: 2010-09-28 (RLVa-1.2.1f) | Modified: RLVa-1.0.0e | OK - args["AVATAR_NAME"] = (!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) ? fullname : RlvStrings::getAnonym(fullname); -// [/RLVa:KB] - LLNotificationsUtil::add("FreezeAvatarFullname", - args, - payload, - callback_freeze); - } - else - { - LLNotificationsUtil::add("FreezeAvatar", - LLSD(), - payload, - callback_freeze); - } - } - return true; - } -}; - class LLAvatarVisibleDebug : public view_listener_t { bool handleEvent(LLPointer event, const LLSD& userdata) { - //bool new_value = gAgent.isGodlike(); -// [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e) - // TODO-RLVa: can you actually use this to cheat anything? - bool new_value = gAgent.isGodlike() && (!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)); -// [/RLVa:KB] - gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); - return true; - } -}; - -class LLAvatarEnableDebug : public view_listener_t -{ - bool handleEvent(LLPointer event, const LLSD& userdata) - { - //bool new_value = gAgent.isGodlike(); - //gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); + gMenuHolder->findControl(userdata["control"].asString())->setValue(gAgent.isGodlike()); return true; } }; @@ -3211,19 +3073,9 @@ class LLAvatarDebug : public view_listener_t { bool handleEvent(LLPointer event, const LLSD& userdata) { - //LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() ); if (isAgentAvatarValid()) { gAgentAvatarp->dumpLocalTextures(); - // hell no don't tell them about that - /* - llinfos << "Dumping temporary asset data to simulator logs for avatar " << avatar->getID() << llendl; - std::vector strings; - strings.push_back(avatar->getID().asString()); - LLUUID invoice; - send_generic_message("dumptempassetdata", strings, invoice); - */ - // LLFloaterAvatarTextures::show( gAgentAvatarp->getID() ); } return true; @@ -3284,11 +3136,20 @@ bool callback_eject(const LLSD& notification, const LLSD& response) return false; } -class LLAvatarEject : public view_listener_t +void handle_avatar_eject(const LLSD& avatar_id) { - bool handleEvent(LLPointer event, const LLSD& userdata) - { - LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() ); + // Use avatar_id if available, otherwise default to right-click avatar + LLVOAvatar* avatar = NULL; + if (avatar_id.asUUID().notNull()) + { + avatar = find_avatar_from_object(avatar_id.asUUID()); + } + else + { + avatar = find_avatar_from_object( + LLSelectMgr::getInstance()->getSelection()->getPrimaryObject()); + } + if( avatar ) { LLSD payload; @@ -3305,7 +3166,7 @@ class LLAvatarEject : public view_listener_t { LLSD args; // args["AVATAR_NAME"] = fullname; -// [RLVa:KB] - Checked: 2010-09-28 (RLVa-1.2.1f) | Modified: RLVa-1.0.0e | OK +// [RLVa:KB] - Checked: 2010-09-28 (RLVa-1.2.1f) | Modified: RLVa-1.0.0e args["AVATAR_NAME"] = (!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) ? fullname : RlvStrings::getAnonym(fullname); // [/RLVa:KB] LLNotificationsUtil::add("EjectAvatarFullname", @@ -3328,7 +3189,7 @@ class LLAvatarEject : public view_listener_t { LLSD args; // args["AVATAR_NAME"] = fullname; -// [RLVa:KB] - Checked: 2010-09-28 (RLVa-1.2.1f) | Modified: RLVa-1.0.0e | OK +// [RLVa:KB] - Checked: 2010-09-28 (RLVa-1.2.1f) | Modified: RLVa-1.0.0e args["AVATAR_NAME"] = (!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) ? fullname : RlvStrings::getAnonym(fullname); // [/RLVa:KB] LLNotificationsUtil::add("EjectAvatarFullnameNoBan", @@ -3345,6 +3206,13 @@ class LLAvatarEject : public view_listener_t } } } +} + +class LLAvatarEject : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) + { + handle_avatar_eject(LLUUID::null); return true; } }; @@ -3377,32 +3245,45 @@ class LLAvatarClientUUID : public view_listener_t } }; +bool enable_freeze_eject(const LLSD& avatar_id) +{ + // Use avatar_id if available, otherwise default to right-click avatar + LLVOAvatar* avatar = NULL; + if (avatar_id.asUUID().notNull()) + { + avatar = find_avatar_from_object(avatar_id.asUUID()); + } + else + { + avatar = find_avatar_from_object( + LLSelectMgr::getInstance()->getSelection()->getPrimaryObject()); + } + if (!avatar) return false; + + // Gods can always freeze + if (gAgent.isGodlike()) return true; + + // Estate owners / managers can freeze + // Parcel owners can also freeze + const LLVector3& pos = avatar->getPositionRegion(); + const LLVector3d& pos_global = avatar->getPositionGlobal(); + LLParcel* parcel = LLViewerParcelMgr::getInstance()->selectParcelAt(pos_global)->getParcel(); + LLViewerRegion* region = avatar->getRegion(); + if (!region) return false; + + bool new_value = region->isOwnedSelf(pos); + if (!new_value || region->isOwnedGroup(pos)) + { + new_value = LLViewerParcelMgr::getInstance()->isParcelOwnedByAgent(parcel,GP_LAND_ADMIN); + } + return new_value; +} + class LLAvatarEnableFreezeEject : public view_listener_t { bool handleEvent(LLPointer event, const LLSD& userdata) { - LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() ); - bool new_value = (avatar != NULL); - - if (new_value) - { - const LLVector3& pos = avatar->getPositionRegion(); - const LLVector3d& pos_global = avatar->getPositionGlobal(); - LLParcel* parcel = LLViewerParcelMgr::getInstance()->selectParcelAt(pos_global)->getParcel(); - LLViewerRegion* region = avatar->getRegion(); - new_value = (region != NULL); - - if (new_value) - { - new_value = region->isOwnedSelf(pos); - if (!new_value || region->isOwnedGroup(pos)) - { - new_value = LLViewerParcelMgr::getInstance()->isParcelOwnedByAgent(parcel,GP_LAND_ADMIN); - } - } - } - - gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); + gMenuHolder->findControl(userdata["control"].asString())->setValue(enable_freeze_eject(LLUUID::null)); return true; } }; @@ -3460,7 +3341,6 @@ class LLAvatarGiveCard : public view_listener_t }; - void login_done(S32 which, void *user) { llinfos << "Login done " << which << llendl; @@ -3512,7 +3392,7 @@ void append_aggregate(std::string& string, const LLAggregatePermissions& ag_perm bool enable_buy_object() { // In order to buy, there must only be 1 purchaseable object in - // the selection manger. + // the selection manager. if(LLSelectMgr::getInstance()->getSelection()->getRootObjectCount() != 1) return false; LLViewerObject* obj = NULL; LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstRootNode(); @@ -3573,10 +3453,10 @@ void handle_buy_object(LLSaleInfo sale_info) } S32 price = sale_info.getSalePrice(); - + if (price > 0 && price > gStatusBar->getBalance()) { - LLFloaterBuyCurrency::buyCurrency("This object costs", price); + LLFloaterBuyCurrency::buyCurrency(LLTrans::getString("this_object_costs"), price); return; } @@ -3628,11 +3508,7 @@ void handle_show_notifications_console(void *) void handle_dump_group_info(void *) { - llinfos << "group " << gAgent.getGroupName() << llendl; - llinfos << "ID " << gAgent.getGroupID() << llendl; - llinfos << "powers " << gAgent.mGroupPowers << llendl; - llinfos << "title " << gAgent.getGroupTitle() << llendl; - //llinfos << "insig " << gAgent.mGroupInsigniaID << llendl; + gAgent.dumpGroupInfo(); } void handle_dump_capabilities_info(void *) @@ -3666,20 +3542,11 @@ class LLSelfSitOrStand : public view_listener_t { if (gAgentAvatarp && gAgentAvatarp->isSitting()) { -// [RLVa:KB] - Alternate: Snowglobe-1.3.X | Checked: 2009-12-29 (RLVa-1.1.0k) | Added: RLVa-1.1.0k | OK - if (gRlvHandler.hasBehaviour(RLV_BHVR_UNSIT)) - return true; -// [/RLVa:KB] - gAgent.setControlFlags(AGENT_CONTROL_STAND_UP); + gAgent.standUp(); } else { -// [RLVa:KB] - Alternate: Snowglobe-1.3.X | Checked: 2009-12-29 (RLVa-1.1.0k) | Added: RLVa-1.1.0k | OK - if (gRlvHandler.hasBehaviour(RLV_BHVR_SIT)) - return true; -// [/RLVa:KB] - - gAgent.setControlFlags(AGENT_CONTROL_SIT_ON_GROUND); + gAgent.sitDown(); // Might be first sit LLFirstUse::useSit(); @@ -3688,13 +3555,26 @@ class LLSelfSitOrStand : public view_listener_t } }; +bool enable_standup_self() +{ +// [RLVa:KB] - Checked: 2010-04-01 (RLVa-1.2.0c) | Modified: RLVa-1.0.0g + return isAgentAvatarValid() && gAgentAvatarp->isSitting() && !gRlvHandler.hasBehaviour(RLV_BHVR_UNSIT); +// [/RLVa:KB] +// return isAgentAvatarValid() && gAgentAvatarp->isSitting(); +} + +bool enable_sitdown_self() +{ +// [RLVa:KB] - Checked: 2010-08-28 (RLVa-1.2.1a) | Added: RLVa-1.2.1a + return isAgentAvatarValid() && !gAgentAvatarp->isSitting() /*&& !gAgent.getFlying()*/ && !gRlvHandler.hasBehaviour(RLV_BHVR_SIT); +// [/RLVa:KB] +// return isAgentAvatarValid() && !gAgentAvatarp->isSitting() && !gAgent.getFlying(); +} + class LLSelfEnableSitOrStand : public view_listener_t { bool handleEvent(LLPointer event, const LLSD& userdata) { - bool new_value = gAgentAvatarp && !gAgent.getFlying(); -// gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); - std::string label; std::string sit_text; std::string stand_text; @@ -3705,27 +3585,18 @@ class LLSelfEnableSitOrStand : public view_listener_t sit_text = param.substr(0, offset); stand_text = param.substr(offset+1); } - - if (gAgentAvatarp && gAgentAvatarp->isSitting()) - { -// [RLVa:KB] - Alternate: Snowglobe-1.3.X | Checked: 2009-12-29 (RLVa-1.1.0k) | Added: RLVa-1.1.0k | OK - new_value &= (!gRlvHandler.hasBehaviour(RLV_BHVR_UNSIT)); -// [/RLVa:KB] + + bool new_value = true; + if (enable_standup_self()) label = stand_text; - } - else - { -// [RLVa:KB] - Alternate: Snowglobe-1.3.X | Checked: 2009-12-29 (RLVa-1.1.0k) | Added: RLVa-1.1.0k | OK - new_value &= (!gRlvHandler.hasBehaviour(RLV_BHVR_SIT)); -// [/RLVa:KB] + else if (enable_sitdown_self()) label = sit_text; - } - -// [RLVa:KB] - Alternate: Snowglobe-1.3.X | Checked: 2009-12-29 (RLVa-1.1.0k) | Added: RLVa-1.1.0k | OK + else + new_value = false; + gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); -// [/RLVa:KB] - gMenuHolder->childSetText("Self Sit", label); - gMenuHolder->childSetText("Self Sit Attachment", label); + gMenuHolder->childSetText("Stand Up", label); + gMenuHolder->childSetText("Stand Up Self", label); return true; } @@ -3765,7 +3636,7 @@ void set_god_level(U8 god_level) LLFloaterDirectory::requestClassifieds(); // God mode changes region visibility - LLWorldMap::getInstance()->reset(); + LLWorldMap::getInstance()->reloadItems(true); // inventory in items may change in god mode gObjectList.dirtyAllObjectInventory(); @@ -3788,7 +3659,6 @@ void set_god_level(U8 god_level) LLNotificationsUtil::add("LeavingGodMode", args); } - // changing god-level can affect which menus we see show_debug_menus(); } @@ -3831,85 +3701,11 @@ void handle_open_message_log(void*) LLFloaterMessageLog::show(); } -void handle_edit_ao(void*) -{ - LLFloaterAO::show(NULL); -} - -void handle_sounds_explorer(void*) -{ - LLFloaterExploreSounds::toggle(); -} - -void handle_blacklist(void*) -{ - LLFloaterBlacklist::show(); -} - -void handle_close_all_notifications(void*) -{ - LLView::child_list_t child_list(*(gNotifyBoxView->getChildList())); - for(LLView::child_list_iter_t iter = child_list.begin(); - iter != child_list.end(); - iter++) - { - gNotifyBoxView->removeChild(*iter); - } -} - -void handle_area_search(void*) -{ - JCFloaterAreaSearch::toggleInstance(); -} - void handle_fake_away_status(void*) { - if (!gSavedSettings.controlExists("FakeAway")) gSavedSettings.declareBOOL("FakeAway", FALSE, "", NO_PERSIST); - - if (gSavedSettings.getBOOL("FakeAway") == TRUE) - { - gSavedSettings.declareBOOL("FakeAway", FALSE, "", NO_PERSIST); - gSavedSettings.setBOOL("FakeAway", FALSE); - gAgent.sendAnimationRequest(ANIM_AGENT_AWAY, ANIM_REQUEST_STOP); - } - else - { - gSavedSettings.declareBOOL("FakeAway", TRUE, "", NO_PERSIST); - gSavedSettings.setBOOL("FakeAway", TRUE); - gAgent.sendAnimationRequest(ANIM_AGENT_AWAY, ANIM_REQUEST_START); - } -} - -void handle_force_ground_sit(void*) -{ - if (gAgentAvatarp) - { - if(!gAgentAvatarp->isSitting()) - { - gAgent.setControlFlags(AGENT_CONTROL_SIT_ON_GROUND); - } - else - { - gAgent.setControlFlags(AGENT_CONTROL_STAND_UP); - } - } -} - -void handle_phantom_avatar(void*) -{ - BOOL ph = LLAgent::getPhantom(); - - if (ph) - gAgent.setControlFlags(AGENT_CONTROL_STAND_UP); - else - gAgent.setControlFlags(AGENT_CONTROL_SIT_ON_GROUND); - - LLAgent::togglePhantom(); - ph = LLAgent::getPhantom(); - LLChat chat; - chat.mSourceType = CHAT_SOURCE_SYSTEM; - chat.mText = llformat("%s%s","Phantom ",(ph ? "On" : "Off")); - LLFloaterChat::addChat(chat); + bool fake_away = gSavedSettings.getBOOL("FakeAway"); + gAgent.sendAnimationRequest(ANIM_AGENT_AWAY, fake_away ? ANIM_REQUEST_STOP : ANIM_REQUEST_START); + gSavedSettings.setBOOL("FakeAway", !fake_away); } // @@ -3956,31 +3752,14 @@ BOOL is_agent_friend(const LLUUID& agent_id) BOOL is_agent_mappable(const LLUUID& agent_id) { - return (is_agent_friend(agent_id) && - LLAvatarTracker::instance().getBuddyInfo(agent_id)->isOnline() && - LLAvatarTracker::instance().getBuddyInfo(agent_id)->isRightGrantedFrom(LLRelationship::GRANT_MAP_LOCATION) + const LLRelationship* buddy_info = LLAvatarTracker::instance().getBuddyInfo(agent_id); + + return (buddy_info && + buddy_info->isOnline() && + buddy_info->isRightGrantedFrom(LLRelationship::GRANT_MAP_LOCATION) ); } -// Enable a menu item when you have someone's card. -/* -BOOL enable_have_card(void *userdata) -{ - LLUUID* avatar_id = (LLUUID *)userdata; - if (gAgent.isGodlike()) - { - return TRUE; - } - else if(avatar_id) - { - return is_agent_friend(*avatar_id); - } - else - { - return FALSE; - } -} -*/ // Enable a menu item when you don't have someone's card. class LLAvatarEnableAddFriend : public view_listener_t @@ -3988,12 +3767,10 @@ class LLAvatarEnableAddFriend : public view_listener_t bool handleEvent(LLPointer event, const LLSD& userdata) { LLVOAvatar* avatar = find_avatar_from_object(LLSelectMgr::getInstance()->getSelection()->getPrimaryObject()); - bool new_value = avatar && !is_agent_friend(avatar->getID()); - -// [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e) | OK - new_value &= (!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)); +// bool new_value = avatar && !is_agent_friend(avatar->getID()); +// [RLVa:KB] - Checked: 2010-04-20 (RLVa-1.2.0f) | Modified: RLVa-1.2.0f + bool new_value = avatar && !is_agent_friend(avatar->getID()) && (!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)); // [/RLVa:KB] - gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); return true; } @@ -4004,16 +3781,17 @@ void request_friendship(const LLUUID& dest_id) LLViewerObject* dest = gObjectList.findObject(dest_id); if(dest && dest->isAvatar()) { - std::string fullname; + std::string full_name; LLNameValue* nvfirst = dest->getNVPair("FirstName"); LLNameValue* nvlast = dest->getNVPair("LastName"); if(nvfirst && nvlast) { - fullname = std::string(nvfirst->getString()) + " " + nvlast->getString(); + full_name = LLCacheName::buildFullName( + nvfirst->getString(), nvlast->getString()); } - if (!fullname.empty()) + if (!full_name.empty()) { - LLPanelFriends::requestFriendshipDialog(dest_id, fullname); + LLPanelFriends::requestFriendshipDialog(dest_id, full_name); } else { @@ -4046,49 +3824,67 @@ class LLEditEnableChangeDisplayname : public view_listener_t } }; -// only works on pie menu -bool handle_sit_or_stand() +bool is_object_sittable() { - LLPickInfo pick = LLToolPie::getInstance()->getPick(); - LLViewerObject *object = pick.getObject();; - // - //if (!object || pick.mPickType == LLPickInfo::PICK_FLORA) - if (!object) - // +// [RLVa:KB] - Checked: 2010-03-06 (RLVa-1.2.0c) | Added: RLVa-1.1.0j + // RELEASE-RLVa: [SL-2.2.0] Make sure we're examining the same object that handle_sit_or_stand() will request a sit for + if (rlv_handler_t::isEnabled()) { - return true; - } - -// [RLVa:KB] - Checked: 2009-12-22 (RLVa-1.1.0k) | Modified: RLVa-1.1.0j | OK - // Block if we can't sit on the selected object (also handles sitting and prevented from standing up) - if ( (rlv_handler_t::isEnabled()) && (!gRlvHandler.canSit(object, pick.mObjectOffset)) ) - { - return true; + const LLPickInfo& pick = LLToolPie::getInstance()->getPick(); + if ( (pick.mObjectID.notNull()) && (!gRlvHandler.canSit(pick.getObject(), pick.mObjectOffset)) ) + return false; } // [/RLVa:KB] + LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); + + if (object && object->getPCode() == LL_PCODE_VOLUME) + { + return true; + } + else + { + return false; + } +} + + +// only works on pie menu +void handle_object_sit_or_stand() +{ + LLPickInfo pick = LLToolPie::getInstance()->getPick(); + LLViewerObject *object = pick.getObject();; + if (!object || pick.mPickType == LLPickInfo::PICK_FLORA) + { + return; + } + if (sitting_on_selection()) { - gAgent.setControlFlags(AGENT_CONTROL_STAND_UP); - return true; + gAgent.standUp(); + return; } // get object selection offset - if (object && object->getPCode() == LL_PCODE_VOLUME) +// if (object && object->getPCode() == LL_PCODE_VOLUME) +// [RLVa:KB] - Checked: 2010-03-06 (RLVa-1.2.0c) | Modified: RLVa-1.2.0c + if ( (object && object->getPCode() == LL_PCODE_VOLUME) && + ((!rlv_handler_t::isEnabled()) || (gRlvHandler.canSit(object, pick.mObjectOffset))) ) +// [/RLVa:KB] { -// [RLVa:KB] - Checked: 2010-08-29 (RLVa-1.1.3b) | Added: RLVa-1.2.1c | OK - if ( (gRlvHandler.hasBehaviour(RLV_BHVR_STANDTP)) && (gAgentAvatarp) ) +// [RLVa:KB] - Checked: 2010-08-29 (RLVa-1.2.1c) | Added: RLVa-1.2.1c + if ( (gRlvHandler.hasBehaviour(RLV_BHVR_STANDTP)) && (isAgentAvatarValid()) ) { if (gAgentAvatarp->isSitting()) { - if (gRlvHandler.canStand()) - gAgent.setControlFlags(AGENT_CONTROL_STAND_UP); - return true; + gAgent.standUp(); + return; } gRlvHandler.setSitSource(gAgent.getPositionGlobal()); } // [/RLVa:KB] + gMessageSystem->newMessageFast(_PREHASH_AgentRequestSit); gMessageSystem->nextBlockFast(_PREHASH_AgentData); gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); @@ -4099,14 +3895,14 @@ bool handle_sit_or_stand() object->getRegion()->sendReliableMessage(); } - return true; } class LLObjectSitOrStand : public view_listener_t { bool handleEvent(LLPointer event, const LLSD& userdata) { - return handle_sit_or_stand(); + handle_object_sit_or_stand(); + return true; } }; @@ -4114,6 +3910,7 @@ void near_sit_down_point(BOOL success, void *) { if (success) { + if (!gSavedSettings.getBOOL("LiruContinueFlyingOnUnsit")) gAgent.setFlying(FALSE); gAgent.setControlFlags(AGENT_CONTROL_SIT_ON_GROUND); @@ -4126,20 +3923,18 @@ class LLLandSit : public view_listener_t { bool handleEvent(LLPointer event, const LLSD& userdata) { -// [RLVa:KB] - Checked: 2010-09-28 (RLVa-1.2.1f) | Modified: RLVa-1.2.1f | OK +// [RLVa:KB] - Checked: 2010-09-28 (RLVa-1.2.1f) | Modified: RLVa-1.2.1f if ( (rlv_handler_t::isEnabled()) && ((!gRlvHandler.canStand()) || (gRlvHandler.hasBehaviour(RLV_BHVR_SIT))) ) - { return true; - } // [/RLVa:KB] - gAgent.setControlFlags(AGENT_CONTROL_STAND_UP); + gAgent.standUp(); LLViewerParcelMgr::getInstance()->deselectLand(); LLVector3d posGlobal = LLToolPie::getInstance()->getPick().mPosGlobal; LLQuaternion target_rot; - if (gAgentAvatarp) + if (isAgentAvatarValid()) { target_rot = gAgentAvatarp->getRotation(); } @@ -4243,32 +4038,6 @@ void velocity_interpolate( void* data ) } } - -void toggle_wind_audio(void) -{ - if (gAudiop) - { - gAudiop->enableWind(!(gAudiop->isWindEnabled())); - } -} - - -// Callback for enablement -BOOL is_inventory_visible( void* user_data ) -{ - LLInventoryView* iv = reinterpret_cast(user_data); - if( iv ) - { - return iv->getVisible(); - } - return FALSE; -} - -void handle_show_newest_map(void*) -{ - LLFloaterWorldMap::show(NULL, FALSE); -} - //------------------------------------------------------------------- // Help menu functions //------------------------------------------------------------------- @@ -4276,7 +4045,7 @@ void handle_show_newest_map(void*) // // Major mode switching // -void reset_view_final( BOOL proceed); +void reset_view_final( BOOL proceed ); void handle_reset_view() { @@ -4301,7 +4070,7 @@ class LLViewResetView : public view_listener_t }; // Note: extra parameters allow this function to be called from dialog. -void reset_view_final( BOOL proceed) +void reset_view_final( BOOL proceed ) { if( !proceed ) { @@ -4399,15 +4168,6 @@ class LLEditEnableDuplicate : public view_listener_t } }; - -void disabled_duplicate(void*) -{ - if (LLSelectMgr::getInstance()->getSelection()->getPrimaryObject()) - { - LLNotificationsUtil::add("CopyFailed"); - } -} - void handle_duplicate_in_place(void*) { llinfos << "handle_duplicate_in_place" << llendl; @@ -4416,11 +4176,6 @@ void handle_duplicate_in_place(void*) LLSelectMgr::getInstance()->selectDuplicate(offset, TRUE); } -void handle_repeat_duplicate(void*) -{ - LLSelectMgr::getInstance()->repeatDuplicate(); -} - /* dead code 30-apr-2008 void handle_deed_object_to_group(void*) { @@ -4572,38 +4327,6 @@ void handle_claim_public_land(void*) gAgent.sendReliableMessage(); } -void handle_god_request_havok(void *) -{ - if (gAgent.isGodlike()) - { - LLSelectMgr::getInstance()->sendGodlikeRequest("havok", "infoverbose"); - } -} - -//void handle_god_request_foo(void *) -//{ -// if (gAgent.isGodlike()) -// { -// LLSelectMgr::getInstance()->sendGodlikeRequest(GOD_WANTS_FOO); -// } -//} - -//void handle_god_request_terrain_save(void *) -//{ -// if (gAgent.isGodlike()) -// { -// LLSelectMgr::getInstance()->sendGodlikeRequest("terrain", "save"); -// } -//} - -//void handle_god_request_terrain_load(void *) -//{ -// if (gAgent.isGodlike()) -// { -// LLSelectMgr::getInstance()->sendGodlikeRequest("terrain", "load"); -// } -//} - BOOL enable_dump_archetype_xm(void*) { return gSavedSettings.getBOOL("DebugAvatarAppearanceMessage"); @@ -4626,17 +4349,10 @@ void handle_god_request_avatar_geometry(void *) { if (gAgent.isGodlike()) { - LLSelectMgr::getInstance()->sendGodlikeRequest("avatar toggle", NULL); + LLSelectMgr::getInstance()->sendGodlikeRequest("avatar toggle", ""); } } - -void handle_show_overlay_title(void*) -{ - gShowOverlayTitle = !gShowOverlayTitle; - gSavedSettings.setBOOL("ShowOverlayTitle", gShowOverlayTitle); -} - static bool get_derezzable_objects( EDeRezDestination dest, std::string& error, @@ -4709,12 +4425,9 @@ static bool get_derezzable_objects( break; default: - // - //if((node->mPermissions->allowTransferTo(gAgent.getID()) - // && object->permCopy()) - // || gAgent.isGodlike()) - if(1) - // + if((node->mPermissions->allowTransferTo(gAgent.getID()) + && object->permCopy()) + || gAgent.isGodlike()) { can_derez_current = TRUE; } @@ -4819,12 +4532,12 @@ static void derez_objects( // if(!gSavedSettings.getBOOL("DisablePointAtAndBeam")) { - // + // // VEFFECT: DerezObject LLHUDEffectSpiral* effectp = (LLHUDEffectSpiral*)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_POINT, TRUE); effectp->setPositionGlobal(object->getPositionGlobal()); effectp->setColor(LLColor4U(gAgent.getEffectColor())); - // + // } // } @@ -4864,6 +4577,7 @@ class LLToolsTakeCopy : public view_listener_t void handle_take_copy() { if (LLSelectMgr::getInstance()->getSelection()->isEmpty()) return; + // [RLVa:KB] - Checked: 2010-03-07 (RLVa-1.2.0c) | Modified: RLVa-1.2.0a if ( (rlv_handler_t::isEnabled()) && (!gRlvHandler.canStand()) ) { @@ -4884,10 +4598,12 @@ class LLObjectReturn : public view_listener_t { public: LLObjectReturn() : mFirstRegion(NULL) {} + +private: bool handleEvent(LLPointer event, const LLSD& userdata) { if (LLSelectMgr::getInstance()->getSelection()->isEmpty()) return true; -// [RLVa:KB] - Checked: 2010-03-24 (RLVa-1.2.0e) | Modified: RLVa-1.0.0b | OK +// [RLVa:KB] - Checked: 2010-03-24 (RLVa-1.4.0a) | Modified: RLVa-1.0.0b if ( (rlv_handler_t::isEnabled()) && (!rlvCanDeleteOrReturn()) ) return true; // [/RLVa:KB] @@ -4973,13 +4689,13 @@ void handle_take() // we want to use the folder this was derezzed from if it's // available. Otherwise, derez to the normal place. // if(LLSelectMgr::getInstance()->getSelection()->isEmpty()) -// [RLVa:KB] - Checked: 2010-03-24 (RLVa-1.2.0e) | Modified: RLVa-1.0.0b | OK +// [RLVa:KB] - Checked: 2010-03-24 (RLVa-1.2.0e) | Modified: RLVa-1.0.0b if ( (LLSelectMgr::getInstance()->getSelection()->isEmpty()) || ((rlv_handler_t::isEnabled()) && (!rlvCanDeleteOrReturn())) ) // [/RLVa:KB] { return; } - + BOOL you_own_everything = TRUE; BOOL locked_but_takeable_object = FALSE; LLUUID category_id; @@ -5051,6 +4767,9 @@ void handle_take() LLNotification::Params params("ConfirmObjectTakeLock"); params.payload(payload) + // MAINT-290 + // Reason: Showing the confirmation dialog resets object selection, thus there is nothing to derez. + // Fix: pass selection to the confirm_take, so that selection doesn't "die" after confirmation dialog is opened .functor(boost::bind(&confirm_take, _1, _2, LLSelectMgr::instance().getSelection())); if(locked_but_takeable_object || @@ -5059,7 +4778,6 @@ void handle_take() if(locked_but_takeable_object && you_own_everything) { params.name("ConfirmObjectTakeLock"); - } else if(!locked_but_takeable_object && !you_own_everything) { @@ -5094,7 +4812,7 @@ bool confirm_take(const LLSD& notification, const LLSD& response, LLObjectSelect BOOL enable_take() { // if (sitting_on_selection()) -// [RLVa:KB] - Checked: 2010-03-24 (RLVa-1.2.0e) | Modified: RLVa-1.0.0b | OK +// [RLVa:KB] - Checked: 2010-03-24 (RLVa-1.2.0e) | Modified: RLVa-1.0.0b if ( (sitting_on_selection()) || ((rlv_handler_t::isEnabled()) && (!rlvCanDeleteOrReturn())) ) // [/RLVa:KB] { @@ -5134,33 +4852,38 @@ BOOL enable_take() return FALSE; } + +void handle_buy_or_take() +{ + if (LLSelectMgr::getInstance()->getSelection()->isEmpty()) + { + return; + } + + if (is_selection_buy_not_take()) + { + S32 total_price = selection_price(); + + if (total_price <= gStatusBar->getBalance() || total_price == 0) + { + handle_buy(); + } + else + { + LLFloaterBuyCurrency::buyCurrency( LLTrans::getString( "BuyingCosts" ), total_price ); + } + } + else + { + handle_take(); + } +} + class LLToolsBuyOrTake : public view_listener_t { bool handleEvent(LLPointer event, const LLSD& userdata) { - if (LLSelectMgr::getInstance()->getSelection()->isEmpty()) - { - return true; - } - - if (is_selection_buy_not_take()) - { - S32 total_price = selection_price(); - - if (total_price <= gStatusBar->getBalance() || total_price == 0) - { - handle_buy(); - } - else - { - LLFloaterBuyCurrency::buyCurrency( - "Buying this costs", total_price); - } - } - else - { - handle_take(); - } + handle_buy_or_take(); return true; } }; @@ -5288,11 +5011,6 @@ void show_buy_currency(const char* extra) LLNotificationsUtil::add("PromptGoToCurrencyPage", args, LLSD(), callback_show_buy_currency); } -void handle_buy_currency(void*) -{ -// LLFloaterBuyCurrency::buyCurrency(); -} - void handle_buy() { if (LLSelectMgr::getInstance()->getSelection()->isEmpty()) return; @@ -5364,10 +5082,7 @@ class LLToolsSaveToInventory : public view_listener_t { bool handleEvent(LLPointer event, const LLSD& userdata) { - // - //if(enable_save_into_inventory(NULL)) - if(1) - // + if(enable_save_into_inventory(NULL)) { derez_objects(DRD_SAVE_INTO_AGENT_INVENTORY, LLUUID::null); } @@ -5431,7 +5146,6 @@ class LLToolsEnablePathfindingRebakeRegion : public view_listener_t LLMenuOptionPathfindingRebakeNavmesh *rebakeInstance = LLMenuOptionPathfindingRebakeNavmesh::getInstance(); returnValue = (rebakeInstance->canRebakeRegion() && (rebakeInstance->getMode() == LLMenuOptionPathfindingRebakeNavmesh::kRebakeNavMesh_Available)); - } gMenuHolder->findControl(userdata["control"].asString())->setValue(returnValue); return returnValue; @@ -5641,7 +5355,6 @@ class LLToolsReleaseKeys : public view_listener_t // [/RLVa:KB] gAgent.forceReleaseControls(); - return true; } }; @@ -5650,46 +5363,15 @@ class LLToolsEnableReleaseKeys : public view_listener_t { bool handleEvent(LLPointer event, const LLSD& userdata) { -// [RLVa:KB] - Checked: 2010-04-19 (RLVa-1.2.0f) | Modified: RLVa-1.0.5a | OK - gMenuHolder->findControl(userdata["control"].asString())->setValue( - gAgent.anyControlGrabbed() && ((!rlv_handler_t::isEnabled()) || (!gRlvAttachmentLocks.hasLockedAttachmentPoint(RLV_LOCK_REMOVE))) ); +// [RLVa:KB] - Checked: 2010-04-19 (RLVa-1.2.0f) | Modified: RLVa-1.0.5a + gMenuHolder->findControl(userdata["control"].asString())->setValue(gAgent.anyControlGrabbed() && + ( (!rlv_handler_t::isEnabled()) || (!gRlvAttachmentLocks.hasLockedAttachmentPoint(RLV_LOCK_REMOVE)) )); // [/RLVa:KB] - //gMenuHolder->findControl(userdata["control"].asString())->setValue( gAgent.anyControlGrabbed() ); +// gMenuHolder->findControl(userdata["control"].asString())->setValue(gAgent.anyControlGrabbed()); return true; } }; -//void handle_hinge(void*) -//{ -// LLSelectMgr::getInstance()->sendHinge(1); -//} - -//void handle_ptop(void*) -//{ -// LLSelectMgr::getInstance()->sendHinge(2); -//} - -//void handle_lptop(void*) -//{ -// LLSelectMgr::getInstance()->sendHinge(3); -//} - -//void handle_wheel(void*) -//{ -// LLSelectMgr::getInstance()->sendHinge(4); -//} - -//void handle_dehinge(void*) -//{ -// LLSelectMgr::getInstance()->sendDehinge(); -//} - -//BOOL enable_dehinge(void*) -//{ -// LLViewerObject* obj = LLSelectMgr::getInstance()->getSelection()->getFirstEditableObject(); -// return obj && !obj->isAttachment(); -//} - class LLEditEnableCut : public view_listener_t { @@ -6082,7 +5764,7 @@ void show_debug_menus() if ( gMenuBarView ) { BOOL debug = gSavedSettings.getBOOL("UseDebugMenus"); - + if(debug) { LLFirstUse::useDebugMenus(); @@ -6100,7 +5782,7 @@ void show_debug_menus() //gMenuBarView->setItemVisible(std::string(AVI_TOOLS), visible); gMenuBarView->needsArrange(); // clean-up positioning - }; + } } void toggle_debug_menus(void*) @@ -6148,6 +5830,7 @@ void toggle_debug_menus(void*) // gExportDialog = LLUploadDialog::modalUploadDialog("Exporting selected objects..."); // } +// BOOL menu_check_build_tool( void* user_data ) { @@ -6244,18 +5927,7 @@ class LLWorldFakeAway : public view_listener_t { bool handleEvent(LLPointer event, const LLSD& userdata) { - if (!gSavedSettings.controlExists("FakeAway")) gSavedSettings.declareBOOL("FakeAway", FALSE, "", NO_PERSIST); - - if (gSavedSettings.getBOOL("FakeAway") == TRUE) - { - gSavedSettings.setBOOL("FakeAway", FALSE); - gAgent.sendAnimationRequest(ANIM_AGENT_AWAY, ANIM_REQUEST_STOP); - } - else - { - gSavedSettings.setBOOL("FakeAway", TRUE); - gAgent.sendAnimationRequest(ANIM_AGENT_AWAY, ANIM_REQUEST_START); - } + handle_fake_away_status(NULL); return true; } }; @@ -6303,16 +5975,13 @@ class LLWorldSetBusy : public view_listener_t } }; - class LLWorldCreateLandmark : public view_listener_t { bool handleEvent(LLPointer event, const LLSD& userdata) { -// [RLVa:KB] - Checked: 2010-09-28 (RLVa-1.2.1f) | Added: RLVa-1.0.0a | OK +// [RLVa:KB] - Checked: 2010-09-28 (RLVa-1.4.5) | Added: RLVa-1.0.0 if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC)) - { return true; - } // [/RLVa:KB] LLViewerRegion* agent_region = gAgent.getRegion(); @@ -6354,43 +6023,49 @@ class LLToolsLookAtSelection : public view_listener_t { bool handleEvent(LLPointer event, const LLSD& userdata) { - const F32 PADDING_FACTOR = 2.f; - BOOL zoom = (userdata.asString() == "zoom"); - if (!LLSelectMgr::getInstance()->getSelection()->isEmpty()) - { - gAgentCamera.setFocusOnAvatar(FALSE, ANIMATE); - - LLBBox selection_bbox = LLSelectMgr::getInstance()->getBBoxOfSelection(); - F32 angle_of_view = llmax(0.1f, LLViewerCamera::getInstance()->getAspect() > 1.f ? LLViewerCamera::getInstance()->getView() * LLViewerCamera::getInstance()->getAspect() : LLViewerCamera::getInstance()->getView()); - F32 distance = selection_bbox.getExtentLocal().magVec() * PADDING_FACTOR / atan(angle_of_view); - - LLVector3 obj_to_cam = LLViewerCamera::getInstance()->getOrigin() - selection_bbox.getCenterAgent(); - obj_to_cam.normVec(); - - LLUUID object_id; - if (LLSelectMgr::getInstance()->getSelection()->getPrimaryObject()) - { - object_id = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject()->mID; - } - if (zoom) - { - // Make sure we are not increasing the distance between the camera and object - LLVector3d orig_distance = gAgentCamera.getCameraPositionGlobal() - LLSelectMgr::getInstance()->getSelectionCenterGlobal(); - distance = llmin(distance, (F32) orig_distance.length()); - - gAgentCamera.setCameraPosAndFocusGlobal(LLSelectMgr::getInstance()->getSelectionCenterGlobal() + LLVector3d(obj_to_cam * distance), - LLSelectMgr::getInstance()->getSelectionCenterGlobal(), - object_id ); - } - else - { - gAgentCamera.setFocusGlobal( LLSelectMgr::getInstance()->getSelectionCenterGlobal(), object_id ); - } - } + handle_look_at_selection(userdata); return true; } }; +void handle_look_at_selection(const LLSD& param) +{ + const F32 PADDING_FACTOR = 2.f; + BOOL zoom = (param.asString() == "zoom"); + if (!LLSelectMgr::getInstance()->getSelection()->isEmpty()) + { + gAgentCamera.setFocusOnAvatar(FALSE, ANIMATE); + + LLBBox selection_bbox = LLSelectMgr::getInstance()->getBBoxOfSelection(); + F32 angle_of_view = llmax(0.1f, LLViewerCamera::getInstance()->getAspect() > 1.f ? LLViewerCamera::getInstance()->getView() * LLViewerCamera::getInstance()->getAspect() : LLViewerCamera::getInstance()->getView()); + F32 distance = selection_bbox.getExtentLocal().magVec() * PADDING_FACTOR / atan(angle_of_view); + + LLVector3 obj_to_cam = LLViewerCamera::getInstance()->getOrigin() - selection_bbox.getCenterAgent(); + obj_to_cam.normVec(); + + LLUUID object_id; + if (LLSelectMgr::getInstance()->getSelection()->getPrimaryObject()) + { + object_id = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject()->mID; + } + if (zoom) + { + // Make sure we are not increasing the distance between the camera and object + LLVector3d orig_distance = gAgentCamera.getCameraPositionGlobal() - LLSelectMgr::getInstance()->getSelectionCenterGlobal(); + distance = llmin(distance, (F32) orig_distance.length()); + + gAgentCamera.setCameraPosAndFocusGlobal(LLSelectMgr::getInstance()->getSelectionCenterGlobal() + LLVector3d(obj_to_cam * distance), + LLSelectMgr::getInstance()->getSelectionCenterGlobal(), + object_id ); + + } + else + { + gAgentCamera.setFocusGlobal( LLSelectMgr::getInstance()->getSelectionCenterGlobal(), object_id ); + } + } +} + void callback_invite_to_group(LLUUID group_id, void *user_data) { std::vector agent_ids; @@ -6419,15 +6094,11 @@ class LLAvatarInviteToGroup : public view_listener_t { bool handleEvent(LLPointer event, const LLSD& userdata) { -// [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e) | OK - if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) - { - return true; - } -// [/RLVa:KB] - LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() ); - if(avatar) +// if(avatar) +// [RLVa:KB] - Checked: 2010-06-04 (RLVa-1.2.0d) | Added: RLVa-1.2.0d + if ( (avatar) && (!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) ) +// [/RLVa:KB] { invite_to_group(avatar->getID()); } @@ -6439,15 +6110,11 @@ class LLAvatarAddFriend : public view_listener_t { bool handleEvent(LLPointer event, const LLSD& userdata) { -// [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e) | OK - if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) - { - return true; // Fallback code [see LLAvatarEnableAddFriend::handleEvent()] - } -// [/RLVa:KB] - LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() ); - if(avatar && !is_agent_friend(avatar->getID())) +// if(avatar && !is_agent_friend(avatar->getID())) +// [RLVa:KB] - Checked: 2010-04-20 (RLVa-1.2.0f) | Modified: RLVa-1.2.0f + if ( (avatar && !is_agent_friend(avatar->getID())) && (!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) ) +// [/RLVa:KB] { request_friendship(avatar->getID()); } @@ -6455,7 +6122,7 @@ class LLAvatarAddFriend : public view_listener_t } }; -bool complete_give_money(const LLSD& notification, const LLSD& response, LLObjectSelectionHandle handle) +bool complete_give_money(const LLSD& notification, const LLSD& response, LLObjectSelectionHandle selection) { S32 option = LLNotification::getSelectedOption(notification, response); if (option == 0) @@ -6463,7 +6130,7 @@ bool complete_give_money(const LLSD& notification, const LLSD& response, LLObjec gAgent.clearBusy(); } - LLViewerObject* objectp = handle->getPrimaryObject(); + LLViewerObject* objectp = selection->getPrimaryObject(); // Show avatar's name if paying attachment if (objectp && objectp->isAttachment()) @@ -6478,7 +6145,7 @@ bool complete_give_money(const LLSD& notification, const LLSD& response, LLObjec { if (objectp->isAvatar()) { - const BOOL is_group = FALSE; + const bool is_group = false; LLFloaterPay::payDirectly(&give_money, objectp->getID(), is_group); @@ -6491,7 +6158,7 @@ bool complete_give_money(const LLSD& notification, const LLSD& response, LLObjec return false; } -bool handle_give_money_dialog() +void handle_give_money_dialog() { LLNotification::Params params("BusyModePay"); params.functor(boost::bind(complete_give_money, _1, _2, LLSelectMgr::getInstance()->getSelection())); @@ -6505,63 +6172,93 @@ bool handle_give_money_dialog() { LLNotifications::instance().forceResponse(params, 1); } - return true; } class LLPayObject : public view_listener_t { bool handleEvent(LLPointer event, const LLSD& userdata) { - return handle_give_money_dialog(); - } -}; - -class LLEnablePayObject : public view_listener_t -{ - bool handleEvent(LLPointer event, const LLSD& userdata) - { - LLVOAvatar* avatar = find_avatar_from_object(LLSelectMgr::getInstance()->getSelection()->getPrimaryObject()); - bool new_value = (avatar != NULL); - if (!new_value) - { - LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); - if( object ) - { - LLViewerObject *parent = (LLViewerObject *)object->getParent(); - if((object->flagTakesMoney()) || (parent && parent->flagTakesMoney())) - { - new_value = true; - } - } - } - -// [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e) - // Don't enable "Pay..." on the avatar pie menu under @shownames=n - new_value &= (!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) || (avatar == NULL); -// [/RLVa:KB] - - gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); + handle_give_money_dialog(); return true; } }; +bool enable_pay_avatar() +{ + LLViewerObject* obj = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); + LLVOAvatar* avatar = find_avatar_from_object(obj); +// return (avatar != NULL); +// [RLVa:KB] - Checked: 2010-08-25 (RLVa-1.2.1b) | Added: RLVa-1.2.1b + return (avatar != NULL) && (!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)); +// [/RLVa:KB] +} + +bool enable_pay_object() +{ + LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); + if( object ) + { + LLViewerObject *parent = (LLViewerObject *)object->getParent(); + if((object->flagTakesMoney()) || (parent && parent->flagTakesMoney())) + { + return true; + } + } + return false; +} + +bool enable_object_stand_up() +{ + // 'Object Stand Up' menu item is enabled when agent is sitting on selection +// return sitting_on_selection(); +// [RLVa:KB] - Checked: 2010-07-24 (RLVa-1.2.0g) | Added: RLVa-1.2.0g + return sitting_on_selection() && ( (!rlv_handler_t::isEnabled()) || (gRlvHandler.canStand()) ); +// [/RLVa:KB] +} + +bool enable_object_sit(/*LLUICtrl* ctrl*/) +{ + // 'Object Sit' menu item is enabled when agent is not sitting on selection + bool sitting_on_sel = sitting_on_selection(); + /* + if (!sitting_on_sel) + { + std::string item_name = ctrl->getName(); + + // init default labels + init_default_item_label(item_name); + + // Update label + LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstRootNode(); + if (node && node->mValid && !node->mSitName.empty()) + { + gMenuHolder->childSetText(item_name, node->mSitName); + } + else + { + gMenuHolder->childSetText(item_name, get_default_item_label(item_name)); + } + } + */ + +// [RLVa:KB] - Checked: 2010-04-01 (RLVa-1.2.0c) | Modified: RLVa-1.2.0c + // RELEASE-RLVA: [SL-2.2.0] Make this match what happens in handle_object_sit_or_stand() + if (rlv_handler_t::isEnabled()) + { + const LLPickInfo& pick = LLToolPie::getInstance()->getPick(); + if (pick.mObjectID.notNull()) + sitting_on_sel = !gRlvHandler.canSit(pick.getObject(), pick.mObjectOffset); + } +// [/RLVa:KB] + + return !sitting_on_sel && is_object_sittable(); +} + class LLObjectEnableSitOrStand : public view_listener_t { bool handleEvent(LLPointer event, const LLSD& userdata) { - bool new_value = false; - LLViewerObject* dest_object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); - - if(dest_object) - { - if(dest_object->getPCode() == LL_PCODE_VOLUME) - { - new_value = true; - } - } -// [RLVa:KB] - Checked: 2009-12-22 (RLVa-1.1.0k) | Added: RLVa-1.1.0j -// gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); -// [/RLVa:KB] + bool new_value; // Update label std::string label; @@ -6574,12 +6271,11 @@ class LLObjectEnableSitOrStand : public view_listener_t sit_text = param.substr(0, offset); stand_text = param.substr(offset+1); } + if (sitting_on_selection()) { label = stand_text; -// [RLVa:KB] - Checked: 2009-12-22 (RLVa-1.1.0k) | Added: RLVa-1.1.0j - new_value &= !gRlvHandler.hasBehaviour(RLV_BHVR_UNSIT); -// [/RLVa:KB] + new_value = enable_object_stand_up(); } else { @@ -6592,27 +6288,24 @@ class LLObjectEnableSitOrStand : public view_listener_t { label = sit_text; } -// [RLVa:KB] - Checked: 2009-12-22 (RLVa-1.1.0k) | Added: RLVa-1.1.0j - if ( (rlv_handler_t::isEnabled()) && (new_value) ) - { - // RELEASE-RLVa: [2009-12-22] make sure we examine the same object that handle_sit_or_stand() will request a sit for - const LLPickInfo& pick = LLToolPie::getInstance()->getPick(); - if (pick.mObjectID.notNull()) - { - new_value = gRlvHandler.canSit(pick.getObject(), pick.mObjectOffset); - } - } -// [/RLVa:KB] + new_value = enable_object_sit(); } gMenuHolder->childSetText("Object Sit", label); -// [RLVa:KB] - Checked: 2009-12-22 (RLVa-1.1.0k) | Added: RLVa-1.1.0j gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); -// [/RLVa:KB] return true; } }; +class LLEnablePayObject : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) + { + gMenuHolder->findControl(userdata["control"].asString())->setValue(enable_pay_avatar() || enable_pay_object()); + return true; + } +}; + void edit_ui(void*) { LLFloater::setEditModeEnabled(!LLFloater::getEditModeEnabled()); @@ -6628,6 +6321,7 @@ void dump_inventory(void*) gInventory.dumpInventory(); } + void handle_dump_followcam(void*) { LLFollowCamMgr::dump(); @@ -6666,7 +6360,8 @@ struct MenuFloaterDict : public LLSingleton // Phoenix: Wolfspirit: Enabled Show Floater out of viewer menu registerFloater("toolbar", boost::bind(&LLToolBar::toggle,(void*)NULL), boost::bind(&LLToolBar::visible,(void*)NULL)); registerFloater("world map", boost::bind(&LLFloaterWorldMap::toggle,(void*)NULL)); - + registerFloater("asset_blacklist", boost::bind(&LLFloaterBlacklist::toggle), boost::bind(&LLFloaterBlacklist::visible)); + registerFloater ("about land"); registerFloater ("about region"); registerFloater ("active speakers"); @@ -6688,6 +6383,8 @@ struct MenuFloaterDict : public LLSingleton registerFloater ("teleport history"); registerFloater ("pathfinding_characters"); registerFloater ("pathfinding_linksets"); + registerFloater ("object_area_search"); + } void registerFloater(const std::string& name, boost::function show, boost::function visible = NULL) { @@ -6740,7 +6437,6 @@ class LLShowFloater : public view_listener_t { LLViewerParcelMgr::getInstance()->selectParcelAt(gAgent.getPositionGlobal()); } - LLViewerParcelMgr::getInstance()->startBuyLand(); } @@ -6803,6 +6499,7 @@ class LLFloaterVisible : public view_listener_t } }; + bool callback_show_url(const LLSD& notification, const LLSD& response) { S32 option = LLNotification::getSelectedOption(notification, response); @@ -6904,7 +6601,7 @@ class LLShowAgentProfile : public view_listener_t if ( (avatar) && ((!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) || (gAgent.getID() == agent_id)) ) // [/RLVa:KB] { - LLFloaterAvatarInfo::show( avatar->getID() ); + LLFloaterAvatarInfo::show(avatar->getID()); } return true; } @@ -6918,6 +6615,7 @@ class LLShowAgentGroups : public view_listener_t return true; } }; + class LLLandEdit : public view_listener_t { bool handleEvent(LLPointer event, const LLSD& userdata) @@ -6976,7 +6674,6 @@ BOOL enable_buy_land(void*) } - class LLObjectAttachToAvatar : public view_listener_t { public: @@ -6995,7 +6692,7 @@ private: if (index > 0) attachment_point = get_if_there(gAgentAvatarp->mAttachmentPoints, index, (LLViewerJointAttachment*)NULL); -// [RLVa:KB] - Checked: 2010-09-28 (RLVa-1.2.1f) | Modified: RLVa-1.2.1f | OK +// [RLVa:KB] - Checked: 2010-09-28 (RLVa-1.2.1f) | Modified: RLVa-1.2.1f // RELEASE-RLVa: [SL-2.2.0] If 'index != 0' then the object will be "add attached" [see LLSelectMgr::sendAttach()] if ( (rlv_handler_t::isEnabled()) && ( ((!index) && (gRlvAttachmentLocks.hasLockedAttachmentPoint(RLV_LOCK_ANY))) || // Can't wear on default @@ -7151,7 +6848,7 @@ class LLAttachmentDrop : public view_listener_t { bool handleEvent(LLPointer event, const LLSD& userdata) { -// [RLVa:KB] - Checked: 2010-03-15 (RLVa-1.2.0e) | Modified: RLVa-1.0.5 | OK +// [RLVa:KB] - Checked: 2010-03-15 (RLVa-1.2.0e) | Modified: RLVa-1.0.5 if (rlv_handler_t::isEnabled()) { if (gRlvAttachmentLocks.hasLockedAttachmentPoint(RLV_LOCK_REMOVE)) @@ -7192,7 +6889,7 @@ void handle_detach_from_avatar(void* user_data) { uuid_vec_t ids_to_remove; const LLViewerJointAttachment *attachment = (LLViewerJointAttachment*)user_data; - + // if (attachment->getNumObjects() > 0) // [RLVa:KB] - Checked: 2010-03-04 (RLVa-1.2.0a) | Added: RLVa-1.2.0a if ( (attachment->getNumObjects() > 0) && ((!rlv_handler_t::isEnabled()) || (gRlvAttachmentLocks.canDetach(attachment))) ) @@ -7264,7 +6961,6 @@ void detach_label(std::string& label, void* user_data) } } - class LLAttachmentDetach : public view_listener_t { bool handleEvent(LLPointer event, const LLSD& userdata) @@ -7301,7 +6997,7 @@ class LLAttachmentDetach : public view_listener_t return true; } -// [RLVa:KB] - Checked: 2010-03-15 (RLVa-1.2.0a) | Modified: RLVa-1.0.5 | OK +// [RLVa:KB] - Checked: 2010-03-15 (RLVa-1.2.0a) | Modified: RLVa-1.0.5 // NOTE: copy/paste of the code in enable_detach() if ( (rlv_handler_t::isEnabled()) && (gRlvAttachmentLocks.hasLockedAttachmentPoint(RLV_LOCK_REMOVE)) ) { @@ -7355,18 +7051,18 @@ class LLAttachmentEnableDrop : public view_listener_t // item is in your inventory LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); - LLViewerJointAttachment* attachment_pt = NULL; + LLViewerJointAttachment* attachment = NULL; LLInventoryItem* item = NULL; - if ( object ) + if (object) { S32 attachmentID = ATTACHMENT_ID_FROM_STATE(object->getState()); - attachment_pt = get_if_there(gAgentAvatarp->mAttachmentPoints, attachmentID, (LLViewerJointAttachment*)NULL); + attachment = get_if_there(gAgentAvatarp->mAttachmentPoints, attachmentID, (LLViewerJointAttachment*)NULL); - if ( attachment_pt ) + if (attachment) { - for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment_pt->mAttachedObjects.begin(); - attachment_iter != attachment_pt->mAttachedObjects.end(); + for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin(); + attachment_iter != attachment->mAttachedObjects.end(); ++attachment_iter) { // make sure item is in your inventory (it could be a delayed attach message being sent from the sim) @@ -7387,9 +7083,9 @@ class LLAttachmentEnableDrop : public view_listener_t } //now check to make sure that the item is actually in the inventory before we enable dropping it -// bool new_value = enable_detach(NULL) && can_build && item; -// [RLVa:KB] - Checked: 2009-07-05 (RLVa-1.0.0b) - bool new_value = enable_detach(NULL) && can_build && item && (!gRlvHandler.hasBehaviour(RLV_BHVR_REZ)); +// bool new_value = enable_detach() && can_build && item; +// [RLVa:KB] - Checked: 2010-03-24 (RLVa-1.0.0b) | Modified: RLVa-1.0.0b + bool new_value = enable_detach() && can_build && item && (!gRlvHandler.hasBehaviour(RLV_BHVR_REZ)); // [/RLVa:KB] gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); @@ -7397,11 +7093,14 @@ class LLAttachmentEnableDrop : public view_listener_t } }; -BOOL enable_detach(void*) +BOOL enable_detach(const LLSD&) { LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); - if (!object) return FALSE; - if (!object->isAttachment()) return FALSE; + if (!object || + !object->isAttachment()) + { + return FALSE; + } // Find the avatar who owns this attachment LLViewerObject* avatar = object; @@ -7410,7 +7109,7 @@ BOOL enable_detach(void*) // ...if it's you, good to detach if (avatar->getID() == gAgent.getID()) { -// [RLVa:KB] - Checked: 2010-03-15 (RLVa-1.2.0a) | Modified: RLVa-1.0.5 | OK +// [RLVa:KB] - Checked: 2010-03-15 (RLVa-1.2.0a) | Modified: RLVa-1.0.5 // NOTE: this code is reused as-is in LLAttachmentDetach::handleEvent() and LLAttachmentDrop::handleEvent() // so any changes here should be reflected there as well @@ -7437,7 +7136,7 @@ class LLAttachmentEnableDetach : public view_listener_t { bool handleEvent(LLPointer event, const LLSD& userdata) { - bool new_value = enable_detach(NULL); + bool new_value = enable_detach(); gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); return true; } @@ -7451,6 +7150,7 @@ BOOL object_selected_and_point_valid(void *user_data) { if (!isAgentAvatarValid()) return FALSE; + // RELEASE-RLVa: look at the caller graph for this function on every new release // -> 1.22.11 and 1.23.4 // - object_is_wearable() => dead code [user_data == NULL => default attach point => OK!] @@ -7467,7 +7167,6 @@ BOOL object_selected_and_point_valid(void *user_data) } // [/RLVa:KB] - //LLViewerJointAttachment *attachment = (LLViewerJointAttachment *)user_data; LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); for (LLObjectSelection::root_iterator iter = selection->root_begin(); iter != selection->root_end(); iter++) @@ -7495,6 +7194,8 @@ BOOL object_selected_and_point_valid(void *user_data) } +// [RLVa:KB] - Checked: 2010-03-16 (RLVa-1.2.0a) | Added: RLVa-1.2.0a +/* BOOL object_is_wearable() { if (!object_selected_and_point_valid(NULL)) @@ -7517,6 +7218,8 @@ BOOL object_is_wearable() } return FALSE; } +*/ +// [/RLVa:KB] // Also for seeing if object can be attached. See above. @@ -7602,7 +7305,7 @@ namespace }; } -void queue_actions(LLFloaterScriptQueue* q, const std::string& noscriptmsg, const std::string& nomodmsg) +void queue_actions(LLFloaterScriptQueue* q, const std::string& msg) { QueueObjects func(q); LLSelectMgr *mgr = LLSelectMgr::getInstance(); @@ -7612,10 +7315,12 @@ void queue_actions(LLFloaterScriptQueue* q, const std::string& noscriptmsg, cons { if ( !func.scripted ) { + std::string noscriptmsg = std::string("Cannot") + msg + "SelectObjectsNoScripts"; LLNotifications::instance().add(noscriptmsg); } else if ( !func.modifiable ) { + std::string nomodmsg = std::string("Cannot") + msg + "SelectObjectsNoPermission"; LLNotifications::instance().add(nomodmsg); } else @@ -7632,43 +7337,11 @@ void queue_actions(LLFloaterScriptQueue* q, const std::string& noscriptmsg, cons } } -void handle_compile_queue(std::string to_lang) -{ - LLFloaterCompileQueue* queue; - if (to_lang == "mono") - { - queue = LLFloaterCompileQueue::create(TRUE); - } - else - { - queue = LLFloaterCompileQueue::create(FALSE); - } - queue_actions(queue, "CannotRecompileSelectObjectsNoScripts", "CannotRecompileSelectObjectsNoPermission"); -} - -void handle_reset_selection(void) -{ - LLFloaterResetQueue* queue = LLFloaterResetQueue::create(); - queue_actions(queue, "CannotResetSelectObjectsNoScripts", "CannotResetSelectObjectsNoPermission"); -} - -void handle_set_run_selection(void) -{ - LLFloaterRunQueue* queue = LLFloaterRunQueue::create(); - queue_actions(queue, "CannotSetRunningSelectObjectsNoScripts", "CannotSerRunningSelectObjectsNoPermission"); -} - -void handle_set_not_run_selection(void) -{ - LLFloaterNotRunQueue* queue = LLFloaterNotRunQueue::create(); - queue_actions(queue, "CannotSetRunningNotSelectObjectsNoScripts", "CannotSerRunningNotSelectObjectsNoPermission"); -} - class LLToolsSelectedScriptAction : public view_listener_t { bool handleEvent(LLPointer event, const LLSD& userdata) { -// [RLVa:KB] - Checked: 2010-04-19 (RLVa-1.2.0f) | Modified: RLVa-1.0.5a | OK +// [RLVa:KB] - Checked: 2010-04-19 (RLVa-1.2.0f) | Modified: RLVa-1.0.5a // We'll allow resetting the scripts of objects on a non-attachable attach point since they wouldn't be able to circumvent anything if ( (rlv_handler_t::isEnabled()) && (gRlvAttachmentLocks.hasLockedAttachmentPoint(RLV_LOCK_REMOVE)) ) { @@ -7680,25 +7353,40 @@ class LLToolsSelectedScriptAction : public view_listener_t // [/RLVa:KB] std::string action = userdata.asString(); + LLFloaterScriptQueue* queue = NULL; + std::string msg; if (action == "compile mono") { - handle_compile_queue("mono"); + queue = LLFloaterCompileQueue::create(true); + msg = "Recompile"; } if (action == "compile lsl") { - handle_compile_queue("lsl"); + queue = LLFloaterCompileQueue::create(false); + msg = "Recompile"; } else if (action == "reset") { - handle_reset_selection(); + queue = LLFloaterResetQueue::create(); + msg = "Reset"; } else if (action == "start") { - handle_set_run_selection(); + queue = LLFloaterRunQueue::create(); + msg = "SetRunning"; } else if (action == "stop") { - handle_set_not_run_selection(); + queue = LLFloaterNotRunQueue::create(); + msg = "SetRunningNot"; + } + if (queue) + { + queue_actions(queue, msg); + } + else + { + llwarns << "Failed to generate LLFloaterScriptQueue with action: " << action << llendl; } return true; } @@ -7780,7 +7468,7 @@ void handle_dump_image_list(void*) void handle_test_male(void*) { -// [RLVa:KB] - Checked: 2010-03-19 (RLVa-1.2.0c) | Modified: RLVa-1.2.0a | OK +// [RLVa:KB] - Checked: 2010-03-19 (RLVa-1.2.0c) | Modified: RLVa-1.2.0a // TODO-RLVa: [RLVa-1.2.1] Is there any reason to still block this? if ( (rlv_handler_t::isEnabled()) && ((gRlvAttachmentLocks.hasLockedAttachmentPoint(RLV_LOCK_ANY)) || (gRlvWearableLocks.hasLockedWearableType(RLV_LOCK_ANY))) ) @@ -7795,7 +7483,7 @@ void handle_test_male(void*) void handle_test_female(void*) { -// [RLVa:KB] - Checked: 2010-03-19 (RLVa-1.2.0c) | Modified: RLVa-1.2.0a | OK +// [RLVa:KB] - Checked: 2010-03-19 (RLVa-1.2.0c) | Modified: RLVa-1.2.0a // TODO-RLVa: [RLVa-1.2.1] Is there any reason to still block this? if ( (rlv_handler_t::isEnabled()) && ((gRlvAttachmentLocks.hasLockedAttachmentPoint(RLV_LOCK_ANY)) || (gRlvWearableLocks.hasLockedWearableType(RLV_LOCK_ANY))) ) @@ -7814,20 +7502,15 @@ void handle_toggle_pg(void*) LLFloaterWorldMap::reloadIcons(NULL); - llinfos << "PG status set to " << (S32)gAgent.isTeen() << llendl; + llinfos << "PG status set to " << gAgent.isTeen() << llendl; } void handle_dump_attachments(void*) { - LLVOAvatar* avatar = gAgentAvatarp; - if( !avatar ) - { - llinfos << "NO AVATAR" << llendl; - return; - } + if(!isAgentAvatarValid()) return; - for (LLVOAvatar::attachment_map_t::iterator iter = avatar->mAttachmentPoints.begin(); - iter != avatar->mAttachmentPoints.end(); ) + for (LLVOAvatar::attachment_map_t::iterator iter = gAgentAvatarp->mAttachmentPoints.begin(); + iter != gAgentAvatarp->mAttachmentPoints.end(); ) { LLVOAvatar::attachment_map_t::iterator curiter = iter++; LLViewerJointAttachment* attachment = curiter->second; @@ -7886,7 +7569,7 @@ void menu_toggle_control( void* user_data ) } -// these are used in the gl menus to set control values. +// these are used in the gl menus to set control values, generically. class LLToggleControl : public view_listener_t { bool handleEvent(LLPointer event, const LLSD& userdata) @@ -7966,7 +7649,7 @@ BOOL enable_more_than_one_selected(void* ) static bool is_editable_selected() { -// [RLVa:KB] - Checked: 2010-09-28 (RLVa-1.2.1f) | Modified: RLVa-1.0.5a | OK +// [RLVa:KB] - Checked: 2010-09-28 (RLVa-1.2.1f) | Modified: RLVa-1.0.5a // RELEASE-RLVa: [SL-2.2.0] Check that this still isn't called by anything but script actions in the Build menu if ( (rlv_handler_t::isEnabled()) && (gRlvAttachmentLocks.hasLockedAttachmentPoint(RLV_LOCK_REMOVE)) ) { @@ -8201,28 +7884,6 @@ class LLToolsEnableSaveToObjectInventory : public view_listener_t } }; -BOOL enable_not_thirdperson(void*) -{ - return !gAgentCamera.cameraThirdPerson(); -} - - -// BOOL enable_export_selected(void *) -// { -// if (LLSelectMgr::getInstance()->getSelection()->isEmpty()) -// { -// return FALSE; -// } -// if (!gExporterRequestID.isNull()) -// { -// return FALSE; -// } -// if (!LLUploadDialog::modalUploadIsFinished()) -// { -// return FALSE; -// } -// return TRUE; -// } class LLViewEnableMouselook : public view_listener_t { @@ -8278,21 +7939,15 @@ class LLWorldEnableTeleportHome : public view_listener_t LLViewerRegion* regionp = gAgent.getRegion(); bool agent_on_prelude = (regionp && regionp->isPrelude()); bool enable_teleport_home = gAgent.isGodlike() || !agent_on_prelude; -// [RLVa:KB] - Checked: 2009-12-22 (RLVa-1.1.0k) | Added: RLVa-1.1.0j - enable_teleport_home &= !gRlvHandler.hasBehaviour(RLV_BHVR_TPLM); +// [RLVa:KB] - Checked: 2010-09-28 (RLVa-1.2.1f) | Modified: RLVa-1.2.1f + enable_teleport_home &= + (!rlv_handler_t::isEnabled()) || ((!gRlvHandler.hasBehaviour(RLV_BHVR_TPLM)) && (!gRlvHandler.hasBehaviour(RLV_BHVR_TPLOC))); // [/RLVa:KB] gMenuHolder->findControl(userdata["control"].asString())->setValue(enable_teleport_home); return true; } }; -BOOL enable_region_owner(void*) -{ - if(gAgent.getRegion() && gAgent.getRegion()->getOwner() == gAgent.getID()) - return TRUE; - return enable_god_customer_service(NULL); -} - BOOL enable_god_full(void*) { return gAgent.getGodLevel() >= GOD_FULL; @@ -8303,26 +7958,20 @@ BOOL enable_god_liaison(void*) return gAgent.getGodLevel() >= GOD_LIAISON; } -BOOL enable_god_customer_service(void*) +BOOL is_god_customer_service(void*) { return gAgent.getGodLevel() >= GOD_CUSTOMER_SERVICE; } BOOL enable_god_basic(void*) { -// [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0a) - // RELEASE-RLVa: check that this function isn't used for anything other than to enable/disable showing the "God Tools..." floater - return (gAgent.getGodLevel() > GOD_NOT) && (!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC)); -// [/RLVa:KB] - //return gAgent.getGodLevel() > GOD_NOT; + return gAgent.getGodLevel() > GOD_NOT; } + void toggle_show_xui_names(void *) { - BOOL showXUINames = gSavedSettings.getBOOL("ShowXUINames"); - - showXUINames = !showXUINames; - gSavedSettings.setBOOL("ShowXUINames", showXUINames); + gSavedSettings.setBOOL("ShowXUINames", !gSavedSettings.getBOOL("ShowXUINames")); } BOOL check_show_xui_names(void *) @@ -8445,10 +8094,23 @@ void slow_mo_animations(void*) void handle_dump_avatar_local_textures(void*) { - if( isAgentAvatarValid() ) + if (!isAgentAvatarValid()) return; + gAgentAvatarp->dumpLocalTextures(); +} + +void handle_debug_avatar_textures(void*) +{ + if (LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject()) { - gAgentAvatarp->dumpLocalTextures(); + LLFloaterAvatarTextures::show(objectp->getID()); } + // + else + { + // default to own avatar + LLFloaterAvatarTextures::show(gAgent.getID()); + } + // } void init_meshes_and_morphs_menu() @@ -8847,22 +8509,6 @@ static void handle_morph_load_obj_continued(void* data, AIFilePicker* filepicker morph_data->setMorphFromMesh(&mesh); } -void handle_debug_avatar_textures(void*) -{ - LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); - if (objectp) - { - LLFloaterAvatarTextures::show(objectp->getID()); - } - // -} - // Returns a pointer to the avatar give the UUID of the avatar OR of an attachment the avatar is wearing. // Returns NULL on failure. LLVOAvatar* find_avatar_from_object( LLViewerObject* object ) @@ -8877,8 +8523,7 @@ LLVOAvatar* find_avatar_from_object( LLViewerObject* object ) } while( object && !object->isAvatar() ); } - else - if( !object->isAvatar() ) + else if( !object->isAvatar() ) { object = NULL; } @@ -8898,7 +8543,7 @@ LLVOAvatar* find_avatar_from_object( const LLUUID& object_id ) void handle_disconnect_viewer(void *) { - LLAppViewer::instance()->forceDisconnect("Testing viewer disconnect"); + LLAppViewer::instance()->forceDisconnect(LLTrans::getString("TestingDisconnect")); } void force_error_breakpoint(void *) @@ -8966,20 +8611,29 @@ void handle_test_load_url(void*) // LLViewerMenuHolderGL // -LLViewerMenuHolderGL::LLViewerMenuHolderGL() : LLMenuHolderGL() -{ -} +LLViewerMenuHolderGL::LLViewerMenuHolderGL() +: LLMenuHolderGL() +{} BOOL LLViewerMenuHolderGL::hideMenus() { - BOOL handled = LLMenuHolderGL::hideMenus(); + BOOL handled = FALSE; + + if (LLMenuHolderGL::hideMenus()) + { + LLToolPie::instance().blockClickToWalk(); + handled = TRUE; + } // drop pie menu selection mParcelSelection = NULL; mObjectSelection = NULL; - gMenuBarView->clearHoverItem(); - gMenuBarView->resetMenuTrigger(); + if (gMenuBarView) + { + gMenuBarView->clearHoverItem(); + gMenuBarView->resetMenuTrigger(); + } return handled; } @@ -9065,25 +8719,7 @@ void handle_buy_currency_test(void*) LLStringUtil::format_map_t replace; replace["[AGENT_ID]"] = gAgent.getID().asString(); replace["[SESSION_ID]"] = gAgent.getSecureSessionID().asString(); - - // *TODO: Replace with call to LLUI::getLanguage() after windows-setup - // branch merges in. JC - std::string language = "en-us"; - language = gSavedSettings.getString("Language"); - if (language.empty() || language == "default") - { - language = gSavedSettings.getString("InstallLanguage"); - } - if (language.empty() || language == "default") - { - language = gSavedSettings.getString("SystemLanguage"); - } - if (language.empty() || language == "default") - { - language = "en-us"; - } - - replace["[LANGUAGE]"] = language; + replace["[LANGUAGE]"] = LLUI::getLanguage(); LLStringUtil::format(url, replace); llinfos << "buy currency url " << url << llendl; @@ -9196,7 +8832,7 @@ class LLViewShowHUDAttachments : public view_listener_t { bool handleEvent(LLPointer event, const LLSD& userdata) { -// [RLVa:KB] - Checked: 2010-04-19 (RLVa-1.2.1a) | Modified: RLVa-1.0.0c | OK +// [RLVa:KB] - Checked: 2010-04-19 (RLVa-1.2.1a) | Modified: RLVa-1.0.0c if ( (rlv_handler_t::isEnabled()) && (gRlvAttachmentLocks.hasLockedHUD()) && (LLPipeline::sShowHUDAttachments) ) return true; // [/RLVa:KB] @@ -9224,13 +8860,15 @@ class LLEditEnableTakeOff : public view_listener_t std::string control_name = userdata["control"].asString(); std::string clothing = userdata["data"].asString(); LLWearableType::EType type = LLWearableType::typeNameToType(clothing); - if (type >= LLWearableType::WT_SHAPE && type < LLWearableType::WT_COUNT) -// [RLVa:KB] - Checked: 2009-07-07 (RLVa-1.1.3b) | Modified: RLVa-1.1.3b | OK - if ( !(rlv_handler_t::isEnabled()) || (gRlvWearableLocks.canRemove(type)) ) +// if (type >= LLWearableType::WT_SHAPE && type < LLWearableType::WT_COUNT) +// [RLVa:KB] - Checked: 2010-03-20 (RLVa-1.2.0c) | Modified: RLVa-1.2.0a + // NOTE: see below - enable if there is at least one wearable on this type that can be removed + if ( (type >= LLWearableType::WT_SHAPE && type < LLWearableType::WT_COUNT) && + ((!rlv_handler_t::isEnabled()) || (gRlvWearableLocks.canRemove(type))) ) // [/RLVa:KB] - - new_value = LLAgentWearables::selfHasWearable(type); - + { + new_value = LLAgentWearables::selfHasWearable(type); + } gMenuHolder->findControl(control_name)->setValue(new_value); return false; } @@ -9267,6 +8905,7 @@ class LLEditTakeOff : public view_listener_t return true; // No wearable found that can be removed } // [/RLVa:KB] + LLUUID item_id = gAgentWearables.getWearableItemID(type,wearable_index); LLAppearanceMgr::instance().removeItemFromAvatar(item_id); } @@ -9318,7 +8957,7 @@ class LLWorldEnvSettings : public view_listener_t { bool handleEvent(LLPointer event, const LLSD& userdata) { -// [RLVa:KB] - Checked: 2010-03-18 (RLVa-1.2.0a) | Modified: RLVa-1.0.0g | OK +// [RLVa:KB] - Checked: 2010-03-18 (RLVa-1.2.0a) | Modified: RLVa-1.0.0g if (gRlvHandler.hasBehaviour(RLV_BHVR_SETENV)) return true; // [/RLVa:KB] @@ -9329,18 +8968,18 @@ class LLWorldEnvSettings : public view_listener_t { // if not there or is hidden, show it if( !LLFloaterEnvSettings::isOpen() || - !LLFloaterEnvSettings::instance()->getVisible()) { - LLFloaterEnvSettings::show(); - - // otherwise, close it button acts like a toggle - } - else + !LLFloaterEnvSettings::instance()->getVisible()) { + LLFloaterEnvSettings::show(); + } + else + { + // otherwise, close it button acts like a toggle LLFloaterEnvSettings::instance()->close(); } return true; } - + if (tod == "sunrise") { LLEnvManagerNew::instance().setUseSkyPreset("Sunrise", gSavedSettings.getBOOL("PhoenixInterpolateSky")); @@ -9368,7 +9007,7 @@ class LLWorldEnvSettings : public view_listener_t /// Water Menu callbacks class LLWorldWaterSettings : public view_listener_t -{ +{ bool handleEvent(LLPointer event, const LLSD& userdata) { // [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) @@ -9420,6 +9059,192 @@ class LLWorldDayCycle : public view_listener_t } }; + +class SinguCloseAllDialogs : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) + { + LLView::child_list_t child_list(*(gNotifyBoxView->getChildList())); + for(LLView::child_list_iter_t iter = child_list.begin(); + iter != child_list.end(); + iter++) + { + gNotifyBoxView->removeChild(*iter); + } + return true; + } +}; + +class SinguForceGroundSit : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) + { + if (isAgentAvatarValid()) + { + if (!gAgentAvatarp->isSitting()) + { + gAgent.setControlFlags(AGENT_CONTROL_SIT_ON_GROUND); + } + else + { + gAgent.setControlFlags(AGENT_CONTROL_STAND_UP); + } + } + return true; + } +}; + +class SinguAnimationOverride : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) + { + LLFloaterAO::show(NULL); + + return true; + } +}; + +class SinguNimble : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) + { + BOOL checked = gSavedSettings.getBOOL("Nimble"); + gSavedSettings.setBOOL("Nimble", !checked); + + return true; + } +}; + +class SinguCheckNimble : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) + { + BOOL checked = gSavedSettings.getBOOL("Nimble"); + gMenuHolder->findControl(userdata["control"].asString())->setValue(checked); + + return true; + } +}; + +class SinguObjectAreaSearch : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) + { + JCFloaterAreaSearch::toggleInstance(); + + return true; + } +}; + +class SinguSoundExplorer : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) + { + LLFloaterExploreSounds::toggle(); + + return true; + } +}; + +class SinguAssetBlacklist : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) + { + LLFloaterBlacklist::toggle(); + + return true; + } +}; + +class SinguStreamingAudioDisplay : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) + { + handle_ticker_toggle(NULL); + + return true; + } +}; + +class SinguCheckStreamingAudioDisplay : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) + { + bool checked = handle_singleton_check(NULL); + gMenuHolder->findControl(userdata["control"].asString())->setValue(checked); + + return true; + } +}; + +class SinguEnableStreamingAudioDisplay : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) + { + return handle_ticker_enabled(NULL); + } +}; + +class SinguPoseStand : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) + { + handle_toggle_pose(NULL); + + return true; + } +}; + +class SinguCheckPoseStand : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) + { + bool checked = handle_check_pose(NULL); + gMenuHolder->findControl(userdata["control"].asString())->setValue(checked); + return true; + } +}; + +class SinguRebake : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) + { + handle_rebake_textures(NULL); + return true; + } +}; + +class SinguDebugConsole : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) + { + handle_singleton_toggle(NULL); + return true; + } +}; + +class SinguCheckDebugConsole : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) + { + bool checked = handle_singleton_check(NULL); + gMenuHolder->findControl(userdata["control"].asString())->setValue(checked); + return true; + } +}; + +class SinguVisibleDebugConsole : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) + { + bool visible = !(gAgent.getRegion()->getCapability("SimConsoleAsync").empty()); + LLView* item = gMenuBarView->getChildView("Region Debug Console", true, false); + item->setVisible(visible); + + return true; + } +}; + void addMenu(view_listener_t *menu, const std::string& name) { sMenus.push_back(menu); @@ -9445,19 +9270,6 @@ void initialize_menus() F32 mVal; bool mMult; }; - - class LLAvatarReportAbuse : public view_listener_t - { - bool handleEvent(LLPointer event, const LLSD& userdata) - { - LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() ); - if(avatar) - { - LLFloaterReporter::showFromObject(avatar->getID()); - } - return true; - } - }; // File menu init_menu_file(); @@ -9565,7 +9377,6 @@ void initialize_menus() addMenu(new LLToolsTakeCopy(), "Tools.TakeCopy"); addMenu(new LLToolsTakeCopy(), "Tools.TakeCopy"); - addMenu(new LLScriptDelete(), "Tools.ScriptDelete"); // addMenu(new LLToolsEnableAdminDelete(), "Tools.EnableAdminDelete"); addMenu(new LLToolsAdminDelete(), "Tools.AdminDelete"); @@ -9609,7 +9420,6 @@ void initialize_menus() addMenu(new LLAvatarDebug(), "Avatar.Debug"); addMenu(new LLAvatarVisibleDebug(), "Avatar.VisibleDebug"); - addMenu(new LLAvatarEnableDebug(), "Avatar.EnableDebug"); addMenu(new LLAvatarInviteToGroup(), "Avatar.InviteToGroup"); addMenu(new LLAvatarGiveCard(), "Avatar.GiveCard"); addMenu(new LLAvatarEject(), "Avatar.Eject"); @@ -9710,6 +9520,26 @@ void initialize_menus() addMenu(new LLEditableSelected(), "EditableSelected"); addMenu(new LLEditableSelectedMono(), "EditableSelectedMono"); + // Singularity menu + addMenu(new SinguCloseAllDialogs(), "CloseAllDialogs"); + // ---- Fake away handled elsewhere + addMenu(new SinguForceGroundSit(), "ForceGroundSit"); + addMenu(new SinguAnimationOverride(), "AnimationOverride"); + addMenu(new SinguNimble(), "Nimble"); + addMenu(new SinguCheckNimble(), "CheckNimble"); + addMenu(new SinguObjectAreaSearch(), "ObjectAreaSearch"); + addMenu(new SinguSoundExplorer(), "SoundExplorer"); + addMenu(new SinguAssetBlacklist(), "AssetBlacklist"); + addMenu(new SinguStreamingAudioDisplay(), "StreamingAudioDisplay"); + addMenu(new SinguEnableStreamingAudioDisplay(), "EnableStreamingAudioDisplay"); + addMenu(new SinguCheckStreamingAudioDisplay(), "CheckStreamingAudioDisplay"); + addMenu(new SinguPoseStand(), "PoseStand"); + addMenu(new SinguCheckPoseStand(), "CheckPoseStand"); + addMenu(new SinguRebake(), "Rebake"); + addMenu(new SinguDebugConsole(), "RegionDebugConsole"); + addMenu(new SinguCheckDebugConsole(), "CheckRegionDebugConsole"); + addMenu(new SinguVisibleDebugConsole(), "VisibleRegionDebugConsole"); + // [RLVa:KB] - Checked: 2010-01-18 (RLVa-1.1.0m) | Added: RLVa-1.1.0m | OK if (rlv_handler_t::isEnabled()) { diff --git a/indra/newview/llviewermenu.h b/indra/newview/llviewermenu.h index 9d4d43629..265f77fd3 100644 --- a/indra/newview/llviewermenu.h +++ b/indra/newview/llviewermenu.h @@ -83,14 +83,13 @@ void confirm_replace_attachment(S32 option, void* user_data); void handle_detach_from_avatar(void* user_data); void attach_label(std::string& label, void* user_data); void detach_label(std::string& label, void* user_data); -BOOL object_selected_and_point_valid(void* user_data); -BOOL object_attached(void* user_data); void handle_detach(void*); +// [SL:KB] - Patch: Inventory-AttachmentEdit - Checked: 2010-08-25 (Catznip-2.2.0a) | Added: Catznip-2.1.2a +void handle_attachment_edit(const LLUUID& idItem); +// [/SL:KB] BOOL enable_god_full(void* user_data); BOOL enable_god_liaison(void* user_data); -BOOL enable_god_customer_service(void* user_data); BOOL enable_god_basic(void* user_data); -void handle_show_newest_map(void*); void set_underclothes_menu_options(); void exchange_callingcard(const LLUUID& dest_id); @@ -98,6 +97,9 @@ void exchange_callingcard(const LLUUID& dest_id); void handle_gestures(void*); void handle_sit_down(void*); void handle_object_build(void*); +void handle_object_touch(); +bool enable_object_open(); +void handle_object_open(); bool visible_take_object(); bool enable_object_take_copy(); @@ -108,9 +110,18 @@ bool enable_object_delete(); void handle_buy(); void handle_take(); void handle_take_copy(); +void handle_look_at_selection(const LLSD& param); void handle_object_return(); void handle_object_delete(); +// Takes avatar UUID, or if no UUID passed, uses last selected object +void handle_avatar_freeze(const LLSD& avatar_id); + +// Takes avatar UUID, or if no UUID passed, uses last selected object +void handle_avatar_eject(const LLSD& avatar_id); + +bool enable_freeze_eject(const LLSD& avatar_id); + // Can anyone take a free copy of the object? // *TODO: Move to separate file bool anyone_copy_selection(LLSelectNode* nodep); @@ -123,9 +134,9 @@ void handle_save_snapshot(void *); void handle_toggle_flycam(); void handle_fake_away_status(void*); -bool handle_sit_or_stand(); -bool handle_give_money_dialog(); -bool handle_object_open(); +void handle_object_sit_or_stand(); +void handle_give_money_dialog(); +bool enable_pay_object(); bool enable_buy_object(); bool handle_go_to(); @@ -158,19 +169,12 @@ extern LLViewerMenuHolderGL* gMenuHolder; extern LLMenuBarGL* gLoginMenuBarView; // Pie menus -extern LLPieMenu *gPieSelf; -extern LLPieMenu *gPieAvatar; -extern LLPieMenu *gPieObject; -extern LLPieMenu *gPieAttachment; -extern LLPieMenu *gPieLand; -extern LLPieMenu* gPieRate; - -// Pie menus -extern LLPieMenu *gPieSelfSimple; -extern LLPieMenu *gPieAvatarSimple; -extern LLPieMenu *gPieObjectSimple; -extern LLPieMenu *gPieAttachmentSimple; -extern LLPieMenu *gPieLandSimple; +extern LLPieMenu *gPieSelf; +extern LLPieMenu *gPieAvatar; +extern LLPieMenu *gPieObject; +extern LLPieMenu *gPieAttachment; +extern LLPieMenu *gPieLand; +extern LLPieMenu *gPieRate; // Needed to build menus when attachment site list available extern LLMenuGL* gAttachSubMenu; diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp index 7eb89b582..7492ea725 100644 --- a/indra/newview/llviewermenufile.cpp +++ b/indra/newview/llviewermenufile.cpp @@ -3,10 +3,9 @@ * @brief "File" menu in the main menu bar. * * $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,6 +38,7 @@ #include "llagentcamera.h" #include "statemachine/aifilepicker.h" #include "llfloateranimpreview.h" +#include "llfloaterbvhpreview.h" #include "llfloaterimagepreview.h" #include "llfloatermodelpreview.h" #include "llfloaternamedesc.h" @@ -63,11 +63,9 @@ #include "lltrans.h" #include "llfloaterbuycurrency.h" // -#include "llselectmgr.h" +#include "floaterlocalassetbrowse.h" #include "llassettype.h" #include "llinventorytype.h" -#include "llbvhloader.h" -#include "lllocalinventory.h" // // linden libraries @@ -89,12 +87,9 @@ #include #include "hippogridmanager.h" -#include "importtracker.h" using namespace LLOldEvents; -std::deque gUploadQueue; - typedef LLMemberListener view_listener_t; @@ -354,8 +349,17 @@ class LLFileUploadAnim : public view_listener_t, public AIFileUpload // Inherited from AIFileUpload. /*virtual*/ void handle_event(std::string const& filename) { - LLFloaterAnimPreview* floaterp = new LLFloaterAnimPreview(filename); - LLUICtrlFactory::getInstance()->buildFloater(floaterp, "floater_animation_preview.xml"); + int len = filename.size(); + if (len >= 5 && filename.substr(len - 5, 5) == ".anim") + { + LLFloaterAnimPreview* floaterp = new LLFloaterAnimPreview(filename); + LLUICtrlFactory::getInstance()->buildFloater(floaterp, "floater_animation_anim_preview.xml"); + floaterp->childSetLabelArg("ok_btn", "[AMOUNT]", llformat("%s%d", gHippoGridManager->getConnectedGrid()->getCurrencySymbol().c_str(), LLGlobalEconomy::Singleton::getInstance()->getPriceUpload())); + } + else + { + LLUICtrlFactory::getInstance()->buildFloater(new LLFloaterBvhPreview(filename), "floater_animation_bvh_preview.xml"); + } } }; @@ -502,6 +506,15 @@ class LLFileMinimizeAllWindows : public view_listener_t return true; } }; + +class LLFileLocalAssetBrowser : public view_listener_t +{ + bool handleEvent(LLPointer, const LLSD&) + { + FloaterLocalAssetBrowser::show(0); + return true; + } +}; // class LLFileSavePreview : public view_listener_t @@ -600,20 +613,6 @@ class LLFileTakeSnapshotToDisk : public view_listener_t } }; -class LLFileLogOut : public view_listener_t -{ - bool handleEvent(LLPointer event, const LLSD& userdata) - { - std::string command(gDirUtilp->getExecutableDir() + gDirUtilp->getDirDelimiter() + gDirUtilp->getExecutableFilename()); - gSavedSettings.setBOOL("ShowConsoleWindow", FALSE); - gViewerWindow->getWindow()->ShellEx(command); - gSavedSettings.setBOOL("ShowConsoleWindow", FALSE); - LLAppViewer::instance()->userQuit(); - gSavedSettings.setBOOL("ShowConsoleWindow", FALSE); - return true; - } -}; - class LLFileQuit : public view_listener_t { bool handleEvent(LLPointer event, const LLSD& userdata) @@ -696,7 +695,7 @@ void upload_new_resource(const std::string& src_filename, std::string name, "No file extension for the file: '%s'\nPlease make sure the file has a correct file extension", short_name.c_str()); args["FILE"] = short_name; - upload_error(error_message, "NofileExtension", filename, args); + upload_error(error_message, "NoFileExtension", filename, args); return; } else if (codec == IMG_CODEC_J2C) @@ -882,8 +881,8 @@ void upload_new_resource(const std::string& src_filename, std::string name, } else if (exten == "bvh") { - error_message = llformat("We do not currently support bulk upload of animation files\n"); - upload_error(error_message, "DoNotSupportBulkAnimationUpload", filename, args); + error_message = llformat("We do not currently support bulk upload of BVH animation files\n"); + upload_error(error_message, "DoNotSupportBulkBVHAnimationUpload", filename, args); return; } // @@ -992,16 +991,10 @@ void temp_upload_callback(const LLUUID& uuid, void* user_data, S32 result, LLExt perms->setMaskEveryone(PERM_ALL); perms->setMaskGroup(PERM_ALL); perms->setMaskNext(PERM_ALL); - - LLUUID destination = gInventory.findCategoryUUIDForType(LLFolderType::FT_TEXTURE); - BOOL bUseSystemInventory = (gSavedSettings.getBOOL("AscentUseSystemFolder") && gSavedSettings.getBOOL("AscentSystemTemporary")); - if (bUseSystemInventory) - { - destination = gSystemFolderAssets; - } + LLViewerInventoryItem* item = new LLViewerInventoryItem( item_id, - destination, + gInventory.findCategoryUUIDForType(LLFolderType::FT_TEXTURE), *perms, uuid, (LLAssetType::EType)data->mAssetInfo.mType, @@ -1011,16 +1004,10 @@ void temp_upload_callback(const LLUUID& uuid, void* user_data, S32 result, LLExt LLSaleInfo::DEFAULT, 0, time_corrected()); - if (bUseSystemInventory) - { - LLLocalInventory::addItem(item); - } - else - { - item->updateServer(TRUE); - gInventory.updateItem(item); - gInventory.notifyObservers(); - } + + item->updateServer(TRUE); + gInventory.updateItem(item); + gInventory.notifyObservers(); } else { @@ -1129,40 +1116,44 @@ void upload_done_callback(const LLUUID& uuid, void* user_data, S32 result, LLExt data = NULL; } -static LLAssetID upload_new_resource_prep(const LLTransactionID& tid, - LLAssetType::EType asset_type, - LLInventoryType::EType& inventory_type, - std::string& name, - const std::string& display_name, - std::string& description) +static LLAssetID upload_new_resource_prep( + const LLTransactionID& tid, + LLAssetType::EType asset_type, + LLInventoryType::EType& inventory_type, + std::string& name, + const std::string& display_name, + std::string& description) { LLAssetID uuid = generate_asset_id_for_new_upload(tid); increase_new_upload_stats(asset_type); - assign_defaults_and_show_upload_message(asset_type, - inventory_type, - name, - display_name, - description); + assign_defaults_and_show_upload_message( + asset_type, + inventory_type, + name, + display_name, + description); return uuid; } -LLSD generate_new_resource_upload_capability_body(LLAssetType::EType asset_type, - const std::string& name, - const std::string& desc, - LLFolderType::EType destination_folder_type, - LLInventoryType::EType inv_type, - U32 next_owner_perms, - U32 group_perms, - U32 everyone_perms) +LLSD generate_new_resource_upload_capability_body( + LLAssetType::EType asset_type, + const std::string& name, + const std::string& desc, + LLFolderType::EType destination_folder_type, + LLInventoryType::EType inv_type, + U32 next_owner_perms, + U32 group_perms, + U32 everyone_perms) { LLSD body; - body["folder_id"] = gInventory.findCategoryUUIDForType(destination_folder_type == LLFolderType::FT_NONE ? - LLFolderType::assetTypeToFolderType(asset_type) : - destination_folder_type); + body["folder_id"] = gInventory.findCategoryUUIDForType( + destination_folder_type == LLFolderType::FT_NONE ? + LLFolderType::assetTypeToFolderType(asset_type) : + destination_folder_type); body["asset_type"] = LLAssetType::lookup(asset_type); body["inventory_type"] = LLInventoryType::lookup(inv_type); @@ -1175,28 +1166,36 @@ LLSD generate_new_resource_upload_capability_body(LLAssetType::EType asset_type, return body; } -bool upload_new_resource(const LLTransactionID &tid, LLAssetType::EType asset_type, - std::string name, - std::string desc, S32 compression_info, - LLFolderType::EType destination_folder_type, - LLInventoryType::EType inv_type, - U32 next_owner_perms, - U32 group_perms, - U32 everyone_perms, - const std::string& display_name, - LLAssetStorage::LLStoreAssetCallback callback, - S32 expected_upload_cost, - void *userdata, - void (*callback2)(bool, void*)) +bool upload_new_resource( + const LLTransactionID &tid, + LLAssetType::EType asset_type, + std::string name, + std::string desc, + S32 compression_info, + LLFolderType::EType destination_folder_type, + LLInventoryType::EType inv_type, + U32 next_owner_perms, + U32 group_perms, + U32 everyone_perms, + const std::string& display_name, + LLAssetStorage::LLStoreAssetCallback callback, + S32 expected_upload_cost, + void *userdata, + void (*callback2)(bool, void*)) { if(gDisconnected) { return false; } - - LLAssetID uuid = upload_new_resource_prep(tid, asset_type, inv_type, - name, display_name, desc); + LLAssetID uuid = + upload_new_resource_prep( + tid, + asset_type, + inv_type, + name, + display_name, + desc); llinfos << "*** Uploading: " << "\nType: " << LLAssetType::lookup(asset_type) << "\nUUID: " << uuid @@ -1216,6 +1215,7 @@ bool upload_new_resource(const LLTransactionID &tid, LLAssetType::EType asset_ty // { llinfos << "New Agent Inventory via capability" << llendl; + LLSD body; body["folder_id"] = gInventory.findCategoryUUIDForType((destination_folder_type == LLFolderType::FT_NONE) ? LLFolderType::assetTypeToFolderType(asset_type) : destination_folder_type); body["asset_type"] = LLAssetType::lookup(asset_type); @@ -1227,8 +1227,15 @@ bool upload_new_resource(const LLTransactionID &tid, LLAssetType::EType asset_ty body["everyone_mask"] = LLSD::Integer(everyone_perms); body["expected_upload_cost"] = LLSD::Integer(expected_upload_cost); - LLHTTPClient::post(url, body, - new LLNewAgentInventoryResponder(body, uuid, asset_type, callback2, userdata)); + LLHTTPClient::post( + url, + body, + new LLNewAgentInventoryResponder( + body, + uuid, + asset_type, + callback2, + userdata)); } else { @@ -1274,12 +1281,14 @@ bool upload_new_resource(const LLTransactionID &tid, LLAssetType::EType asset_ty { asset_callback = callback; } - gAssetStorage->storeAssetData(data->mAssetInfo.mTransactionID, data->mAssetInfo.mType, - asset_callback, - (void*)data, - temporary, - TRUE, - temporary); + gAssetStorage->storeAssetData( + data->mAssetInfo.mTransactionID, + data->mAssetInfo.mType, + asset_callback, + (void*)data, + temporary, + TRUE, + temporary); } // Return true when a call to a callback function will follow. @@ -1330,6 +1339,7 @@ void assign_defaults_and_show_upload_message(LLAssetType::EType asset_type, } LLStringUtil::stripNonprintable(name); LLStringUtil::stripNonprintable(description); + if (name.empty()) { name = "(No Name)"; @@ -1345,6 +1355,7 @@ void assign_defaults_and_show_upload_message(LLAssetType::EType asset_type, LLUploadDialog::modalUploadDialog(upload_message); } + void init_menu_file() { (new LLFileUploadImage())->registerListener(gMenuHolder, "File.UploadImage"); @@ -1358,13 +1369,13 @@ void init_menu_file() (new LLFileEnableCloseAllWindows())->registerListener(gMenuHolder, "File.EnableCloseAllWindows"); // (new LLFileMinimizeAllWindows())->registerListener(gMenuHolder, "File.MinimizeAllWindows"); + (new LLFileLocalAssetBrowser())->registerListener(gMenuHolder, "File.LocalAssetBrowser"); // (new LLFileSavePreview())->registerListener(gMenuHolder, "File.SavePreview"); (new LLFileSavePreviewPNG())->registerListener(gMenuHolder, "File.SavePreviewPNG"); (new LLFileTakeSnapshot())->registerListener(gMenuHolder, "File.TakeSnapshot"); (new LLFileTakeSnapshotToDisk())->registerListener(gMenuHolder, "File.TakeSnapshotToDisk"); (new LLFileQuit())->registerListener(gMenuHolder, "File.Quit"); - (new LLFileLogOut())->registerListener(gMenuHolder, "File.LogOut"); (new LLFileEnableUpload())->registerListener(gMenuHolder, "File.EnableUpload"); (new LLFileEnableUploadModel())->registerListener(gMenuHolder, "File.EnableUploadModel"); diff --git a/indra/newview/llviewermenufile.h b/indra/newview/llviewermenufile.h index 426a5a4bf..65ff1a425 100644 --- a/indra/newview/llviewermenufile.h +++ b/indra/newview/llviewermenufile.h @@ -48,8 +48,6 @@ class NewResourceItemCallback : public LLInventoryCallback class LLTransactionID; -extern std::deque gUploadQueue; - void init_menu_file(); void upload_new_resource(const std::string& src_filename, diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index c151c691d..d930cec27 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -3,10 +3,9 @@ * @brief Dumping ground for viewer-side message system callbacks. * * $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 @@ -34,80 +33,53 @@ #include "llviewermessage.h" #include -#include - -#include "llimagejpeg.h" -#include "llagentui.h" #include "llanimationstates.h" #include "llaudioengine.h" #include "llavatarnamecache.h" -#include "indra_constants.h" #include "../lscript/lscript_byteformat.h" //Need LSCRIPTRunTimePermissionBits and SCRIPT_PERMISSION_* - -#include "llfloaterbump.h" -#include "llassetstorage.h" -#include "llcachename.h" -#include "llchat.h" -#include "lldbstrings.h" #include "lleconomy.h" #include "llfocusmgr.h" #include "llfollowcamparams.h" -#include "llinstantmessage.h" -#include "llquantize.h" -#include "llregionflags.h" +#include "llinventorydefines.h" #include "llregionhandle.h" #include "llsdserialize.h" -#include "llstring.h" #include "llteleportflags.h" -#include "lltracker.h" #include "lltransactionflags.h" #include "llvfile.h" #include "llvfs.h" #include "llxfermanager.h" #include "mean_collision_data.h" -#include "message.h" -#include "sound_ids.h" -#include "lleventtimer.h" -#include "llmd5.h" #include "llagent.h" #include "llagentcamera.h" #include "llcallingcard.h" -#include "llconsole.h" -#include "llvieweraudio.h" -#include "llviewercontrol.h" -#include "lldrawpool.h" #include "llfirstuse.h" -#include "llfloateranimpreview.h" +#include "llfloaterbvhpreview.h" +#include "llfloaterbump.h" #include "llfloaterbuycurrency.h" #include "llfloaterbuyland.h" #include "llfloaterchat.h" #include "llfloatergroupinfo.h" #include "llfloaterimagepreview.h" -#include "llfloaterinventory.h" #include "llfloaterland.h" #include "llfloaterregioninfo.h" #include "llfloaterlandholdings.h" -#include "llurldispatcher.h" #include "llfloatermute.h" #include "llfloaterpostcard.h" #include "llfloaterpreference.h" #include "llfloaterteleporthistory.h" -#include "llfollowcam.h" -#include "llgroupnotify.h" -#include "llhudeffect.h" #include "llhudeffecttrail.h" #include "llhudmanager.h" #include "llimpanel.h" -#include "llinventorydefines.h" +#include "llinventorybridge.h" #include "llinventorymodel.h" #include "llinventorypanel.h" -#include "llmenugl.h" #include "llmutelist.h" #include "llnotify.h" #include "llnotifications.h" #include "llnotificationsutil.h" #include "llpanelgrouplandmoney.h" +#include "llpanelmaininventory.h" #include "llselectmgr.h" #include "llstartup.h" #include "llsky.h" @@ -115,48 +87,33 @@ #include "llstatusbar.h" #include "llimview.h" #include "llfloateractivespeakers.h" -#include "lltexturestats.h" -#include "lltool.h" -#include "lltoolbar.h" -#include "lltoolmgr.h" #include "lltrans.h" -#include "llfoldertype.h" -#include "llui.h" // for make_ui_sound -#include "lluploaddialog.h" -#include "llviewercamera.h" -#include "llviewerdisplay.h" #include "llviewerfoldertype.h" #include "llviewergenericmessage.h" #include "llviewermenu.h" #include "llviewerinventory.h" #include "llviewerjoystick.h" -#include "llviewerobject.h" #include "llviewerobjectlist.h" #include "llviewerparcelmgr.h" -#include "llviewerpartsource.h" #include "llviewerstats.h" #include "llviewertexteditor.h" #include "llviewerthrottle.h" #include "llviewerwindow.h" #include "llvlmanager.h" #include "llvoavatar.h" -#include "llweb.h" #include "llworld.h" #include "pipeline.h" -#include "llappviewer.h" #include "llfloaterworldmap.h" #include "llviewerdisplay.h" #include "llkeythrottle.h" +#include "llagentui.h" #include "llviewerregion.h" -// -#include "llviewernetwork.h" -// -// [RLVa:KB] +// [RLVa:KB] - Checked: 2010-03-09 (RLVa-1.2.0a) +#include "llfloateravatarinfo.h" // Checked: 2009-07-08 (RLVa-1.0.0e) #include "rlvhandler.h" #include "rlvinventory.h" #include "rlvui.h" -#include "rlvcommon.h" // [/RLVa:KB] #if SHY_MOD //Command handler @@ -169,9 +126,6 @@ #include "sgversion.h" #include "m7wlinterface.h" -#include "llwlparammanager.h" -#include "llwaterparammanager.h" - #include "llgiveinventory.h" #include @@ -190,10 +144,6 @@ static const boost::regex NEWLINES("\\n{1}"); extern AIHTTPTimeoutPolicy authHandler_timeout; -// [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e) -#include "llfloateravatarinfo.h" -// [/RLVa:KB] - // // Constants // @@ -212,6 +162,7 @@ extern bool gShiftFrame; // function prototypes bool check_offer_throttle(const std::string& from_name, bool check_only); +bool check_asset_previewable(const LLAssetType::EType asset_type); void callbackCacheEstateOwnerName(const LLUUID& id, const LLAvatarName& av_name); static void process_money_balance_reply_extended(LLMessageSystem* msg); @@ -234,7 +185,8 @@ const std::string SCRIPT_QUESTIONS[SCRIPT_PERMISSION_EOF] = "ChangePermissions", "TrackYourCamera", "ControlYourCamera", - "TeleportYourAgent" + "TeleportYourAgent", + "OverrideAnimations" }; const BOOL SCRIPT_QUESTION_IS_CAUTION[SCRIPT_PERMISSION_EOF] = @@ -250,7 +202,8 @@ const BOOL SCRIPT_QUESTION_IS_CAUTION[SCRIPT_PERMISSION_EOF] = FALSE, // ChangePermissions FALSE, // TrackYourCamera, FALSE, // ControlYourCamera - FALSE // TeleportYourAgent + FALSE, // TeleportYourAgent + FALSE // OverrideAnimations }; bool friendship_offer_callback(const LLSD& notification, const LLSD& response) @@ -312,9 +265,6 @@ static LLNotificationFunctorRegistration friendship_offer_callback_reg_nm("Offer void give_money(const LLUUID& uuid, LLViewerRegion* region, S32 amount, BOOL is_group, S32 trx_type, const std::string& desc) { - // - //if(!region) return; - // if(0 == amount || !region) return; amount = abs(amount); LL_INFOS("Messaging") << "give_money(" << uuid << "," << amount << ")"<< LL_ENDL; @@ -1113,7 +1063,9 @@ public: // If we now try to remove the inventory item, it will cause a nested // notifyObservers() call, which won't work. // So defer moving the item to trash until viewer gets idle (in a moment). - LLAppViewer::instance()->addOnIdleCallback(boost::bind(&LLInventoryModel::removeItem, &gInventory, mObjectID)); + // Use removeObject() rather than removeItem() because at this level, + // the object could be either an item or a folder. + LLAppViewer::instance()->addOnIdleCallback(boost::bind(&LLInventoryModel::removeObject, &gInventory, mObjectID)); gInventory.removeObserver(this); delete this; } @@ -1196,46 +1148,78 @@ bool check_offer_throttle(const std::string& from_name, bool check_only) } } -void open_inventory_offer(const uuid_vec_t& items, const std::string& from_name) +// Return "true" if we have a preview method for that asset type, "false" otherwise +bool check_asset_previewable(const LLAssetType::EType asset_type) { - uuid_vec_t::const_iterator it = items.begin(); - uuid_vec_t::const_iterator end = items.end(); - LLInventoryItem* item; - for(; it != end; ++it) - { - item = gInventory.getItem(*it); - if(!item) - { - LL_WARNS("Messaging") << "Unable to show inventory item: " << *it << LL_ENDL; - continue; - } - if(!highlight_offered_object(item->getUUID())) - { - continue; - } - LLAssetType::EType asset_type = item->getType(); + return (asset_type == LLAssetType::AT_NOTECARD) || + (asset_type == LLAssetType::AT_LANDMARK) || + (asset_type == LLAssetType::AT_TEXTURE) || + (asset_type == LLAssetType::AT_ANIMATION) || + (asset_type == LLAssetType::AT_SCRIPT) || + (asset_type == LLAssetType::AT_SOUND); +} - //if we are throttled, don't display them - if (check_offer_throttle(from_name, false)) +void open_inventory_offer(const uuid_vec_t& objects, const std::string& from_name) +{ + for (uuid_vec_t::const_iterator obj_iter = objects.begin(); + obj_iter != objects.end(); + ++obj_iter) + { + const LLUUID& obj_id = (*obj_iter); + if(!highlight_offered_object(obj_id)) { - // I'm not sure this is a good idea - Definitely a bad idea. HB - //bool show_keep_discard = item->getPermissions().getCreator() != gAgent.getID(); - bool show_keep_discard = true; - switch(asset_type) + continue; + } + + const LLInventoryObject *obj = gInventory.getObject(obj_id); + if (!obj) + { + llwarns << "Cannot find object [ itemID:" << obj_id << " ] to open." << llendl; + continue; + } + + const LLAssetType::EType asset_type = obj->getActualType(); + + // Either an inventory item or a category. + const LLInventoryItem* item = dynamic_cast(obj); + if (item && check_asset_previewable(asset_type)) + { + //////////////////////////////////////////////////////////////////////////////// + // Special handling for various types. + if (check_offer_throttle(from_name, false)) // If we are throttled, don't display { - case LLAssetType::AT_NOTECARD: - open_notecard((LLViewerInventoryItem*)item, std::string("Note: ") + item->getName(), LLUUID::null, show_keep_discard, LLUUID::null, FALSE); - break; - case LLAssetType::AT_LANDMARK: - open_landmark((LLViewerInventoryItem*)item, std::string("Landmark: ") + item->getName(), show_keep_discard, LLUUID::null, FALSE); - break; - case LLAssetType::AT_TEXTURE: - open_texture(*it, std::string("Texture: ") + item->getName(), show_keep_discard, LLUUID::null, FALSE); - break; - default: - break; + // I'm not sure this is a good idea - Definitely a bad idea. HB + //bool show_keep_discard = item->getPermissions().getCreator() != gAgent.getID(); + bool show_keep_discard = true; + switch(asset_type) + { + case LLAssetType::AT_NOTECARD: + { + open_notecard((LLViewerInventoryItem*)item, std::string("Note: ") + item->getName(), LLUUID::null, show_keep_discard, LLUUID::null, FALSE); + break; + } + case LLAssetType::AT_LANDMARK: + { + open_landmark((LLViewerInventoryItem*)item, std::string("Landmark: ") + item->getName(), show_keep_discard, LLUUID::null, FALSE); + } + break; + case LLAssetType::AT_TEXTURE: + { + open_texture(obj_id, std::string("Texture: ") + item->getName(), show_keep_discard, LLUUID::null, FALSE); + break; + } + case LLAssetType::AT_ANIMATION: + case LLAssetType::AT_SCRIPT: + case LLAssetType::AT_SOUND: + LLInvFVBridgeAction::doAction(asset_type, obj_id, &gInventory); + break; + default: + LL_DEBUGS("Messaging") << "No preview method for previewable asset type : " << LLAssetType::lookupHumanReadable(asset_type) << LL_ENDL; + break; + } } } + //highlight item, if it's not in the trash or lost+found // Don't auto-open the inventory floater @@ -1245,40 +1229,29 @@ void open_inventory_offer(const uuid_vec_t& items, const std::string& from_name) return; } - if(gSavedSettings.getBOOL("ShowInInventory") && + //Trash Check + if ((gInventory.isObjectDescendentOf(obj_id, gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH))) + // don't select lost and found items if the user is active + || (gAwayTimer.getStarted() && gInventory.isObjectDescendentOf(obj_id, gInventory.findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND)))) + { + return; + } + + if (gSavedSettings.getBOOL("ShowInInventory") && + objects.size() == 1 && item != NULL && asset_type != LLAssetType::AT_CALLINGCARD && item->getInventoryType() != LLInventoryType::IT_ATTACHMENT && !from_name.empty()) { LLInventoryView::showAgentInventory(TRUE); } - //Trash Check - LLUUID trash_id; - trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH); - if(gInventory.isObjectDescendentOf(item->getUUID(), trash_id)) - { - return; - } - LLUUID lost_and_found_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND); - //BOOL inventory_has_focus = gFocusMgr.childHasKeyboardFocus(view); - BOOL user_is_away = gAwayTimer.getStarted(); - // don't select lost and found items if the user is active - if (gInventory.isObjectDescendentOf(item->getUUID(), lost_and_found_id) - && !user_is_away) - { - return; - } - - //Not sure about this check. Could make it easy to miss incoming items. - //don't dick with highlight while the user is working - //if(inventory_has_focus && !user_is_away) - // break; - LL_DEBUGS("Messaging") << "Highlighting" << item->getUUID() << LL_ENDL; - //highlight item + //////////////////////////////////////////////////////////////////////////////// + // Highlight item + LL_DEBUGS("Messaging") << "Highlighting" << obj_id << LL_ENDL; LLFocusableElement* focus_ctrl = gFocusMgr.getKeyboardFocus(); - view->getPanel()->setSelection(item->getUUID(), TAKE_FOCUS_NO); + view->getPanel()->setSelection(obj_id, TAKE_FOCUS_NO); gFocusMgr.setKeyboardFocus(focus_ctrl); } } @@ -1379,7 +1352,7 @@ LLSD LLOfferInfo::asLLSD() } bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD& response) - { +{ LLChat chat; std::string log_message; S32 button = LLNotificationsUtil::getSelectedOption(notification, response); @@ -1413,8 +1386,7 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD& msg->addUUIDFast(_PREHASH_RegionID, LLUUID::null); msg->addVector3Fast(_PREHASH_Position, gAgent.getPositionAgent()); LLInventoryObserver* opener = NULL; - LLViewerInventoryCategory* catp = NULL; - catp = (LLViewerInventoryCategory*)gInventory.getCategory(mObjectID); + LLViewerInventoryCategory* catp = gInventory.getCategory(mObjectID); LLViewerInventoryItem* itemp = NULL; if(!catp) { @@ -1919,6 +1891,36 @@ static std::string clean_name_from_im(const std::string& name, EInstantMessage t } } +static std::string clean_name_from_task_im(const std::string& msg, + BOOL from_group) +{ + boost::smatch match; + static const boost::regex returned_exp( + "(.*been returned to your inventory lost and found folder by )(.+)( (from|near).*)"); + if (boost::regex_match(msg, match, returned_exp)) + { + // match objects are 1-based for groups + std::string final = match[1].str(); + std::string name = match[2].str(); + // Don't try to clean up group names + if (!from_group) + { + if (LLAvatarNameCache::useDisplayNames()) + { + // ...just convert to username + final += LLCacheName::buildUsername(name); + } + else + { + // ...strip out legacy "Resident" name + final += LLCacheName::cleanFullName(name); + } + } + final += match[3].str(); + return final; + } + return msg; +} void notification_display_name_callback(const LLUUID& id, const LLAvatarName& av_name, @@ -1929,6 +1931,25 @@ void notification_display_name_callback(const LLUUID& id, substitutions["NAME"] = av_name.mDisplayName; LLNotificationsUtil::add(name, substitutions, payload); } + +// Callback for name resolution of a god/estate message +void god_message_name_cb(const LLAvatarName& av_name, LLChat chat, std::string message) +{ + std::string name; + LLAvatarNameCache::getPNSName(av_name, name); + LLSD args; + args["NAME"] = name; + args["MESSAGE"] = message; + LLNotificationsUtil::add("GodMessage", args); + + // Treat like a system message and put in chat history. + chat.mText = name + ": " + message; + + // Claim to be from a local agent so it doesn't go into console. + LLFloaterChat::addChat(chat, false, true); + +} + void process_improved_im(LLMessageSystem *msg, void **user_data) { if (gNoRender) @@ -2004,6 +2025,10 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) { name = LLTrans::getString("Unnamed"); } + + // Preserve the unaltered name for use in group notice mute checking. + std::string original_name = name; + // IDEVO convert new-style "Resident" names for display name = clean_name_from_im(name, dialog); @@ -2017,6 +2042,8 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) || dialog == IM_FROM_TASK && LLMuteList::getInstance()->isMuted(session_id); BOOL is_linden = LLMuteList::getInstance()->isLinden(name); BOOL is_owned_by_me = FALSE; + BOOL is_friend = (LLAvatarTracker::instance().getBuddyInfo(from_id) == NULL) ? false : true; + BOOL accept_im_from_only_friend = gSavedSettings.getBOOL("VoiceCallsFriendsOnly"); LLUUID computed_session_id = LLIMMgr::computeSessionID(dialog,from_id); @@ -2288,10 +2315,10 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) // do nothing -- don't distract newbies in // Prelude with global IMs } -// [RLVa:KB] - Checked: 2010-03-27 (RLVa-1.1.3a) | Modified: RLVa-1.2.0b - else if ( (rlv_handler_t::isEnabled()) && (offline == IM_ONLINE) && ("@version" == message) ) +// [RLVa:KB] - Checked: 2011-05-28 (RLVa-1.4.0a) | Modified: RLVa-1.4.0a + else if ( (rlv_handler_t::isEnabled()) && (offline == IM_ONLINE) && ("@version" == message) && + (!is_muted) && ((!accept_im_from_only_friend) || (is_friend)) ) { - // TODO-RLVa: [RLVa-1.2.1] Should we send our version string if the other party is muted? RlvUtil::sendBusyMessage(from_id, RlvStrings::getVersion(), session_id); // We won't receive a typing stop message, so do that manually (see comment at the end of LLFloaterIMPanel::sendMsg) LLPointer im_info = new LLIMInfo(gMessageSystem); @@ -2358,41 +2385,24 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) } else if (to_id.isNull()) { -// [RLVa:KB] - Version: 1.23.4 | Checked: 2009-07-08 (RLVa-1.0.0e) - // Filter region messages that weren't sent by a Linden - if ( (rlv_handler_t::isEnabled()) && (LLMuteList::getInstance()) && - (!LLMuteList::getInstance()->isLinden(name)) && (from_id != gAgent.getID()) ) - { - if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC)) - RlvUtil::filterLocation(message); - if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) - { - name = RlvStrings::getAnonym(name); - RlvUtil::filterNames(message); - } - } -// [/RLVa:KB] - - // Message to everyone from GOD - args["NAME"] = name; - args["MESSAGE"] = message; - LLNotificationsUtil::add("GodMessage", args); - - // Treat like a system message and put in chat history. - // Claim to be from a local agent so it doesn't go into - // console. - chat.mText = name + separator_string + message.substr(message_offset); - BOOL local_agent = TRUE; - LLFloaterChat::addChat(chat, FALSE, local_agent); + // Message to everyone from GOD, look up the fullname since + // server always slams name to legacy names + LLAvatarNameCache::get(from_id, boost::bind(god_message_name_cb, _2, chat, message)); } else { // standard message, not from system + bool mute_im = is_muted; + if(accept_im_from_only_friend&&!is_friend) + { + mute_im = true; + } + // [RLVa:KB] - Checked: 2010-11-30 (RLVa-1.3.0c) | Modified: RLVa-1.3.0c // Don't block offline IMs, or IMs from Lindens if ( (rlv_handler_t::isEnabled()) && (offline != IM_OFFLINE) && (!is_linden) && (!gRlvHandler.canReceiveIM(from_id)) ) { - if (!is_muted) + if (!mute_im) RlvUtil::sendBusyMessage(from_id, RlvStrings::getString(RLV_STRING_BLOCKED_RECVIM_REMOTE), session_id); message = message.substr(0, message_offset) + RlvStrings::getString(RLV_STRING_BLOCKED_RECVIM); } @@ -2405,11 +2415,25 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) args["[LONG_TIMESTAMP]"] = formatted_time(timestamp); saved = LLTrans::getString("Saved_message", args); } - buffer = separator_string + saved + message.substr(message_offset); + buffer = separator_string + saved + message.substr(message_offset); LL_INFOS("Messaging") << "process_improved_im: session_id( " << session_id << " ), from_id( " << from_id << " )" << LL_ENDL; - if (!is_muted || is_linden) +/* + bool mute_im = is_muted; + if (accept_im_from_only_friend && !is_friend) + { + if (!gIMMgr->isNonFriendSessionNotified(session_id)) + { + std::string message = LLTrans::getString("IM_unblock_only_groups_friends"); + gIMMgr->addMessage(session_id, from_id, name, message); + gIMMgr->addNotifiedNonFriendSessionID(session_id); + } + + mute_im = true; + } +*/ + if (!mute_im || is_linden) { gIMMgr->addMessage( session_id, @@ -2456,9 +2480,9 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) case IM_MESSAGEBOX: { // This is a block, modeless dialog. - // *TODO: Translate + //*TODO: Translate args["MESSAGE"] = message; - LLNotificationsUtil::add("SystemMessage", args); + LLNotificationsUtil::add("SystemMessageTip", args); } break; case IM_GROUP_NOTICE: @@ -2491,6 +2515,26 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) break; } + // The group notice packet does not have an AgentID. Obtain one from the name cache. + // If last name is "Resident" strip it out so the cache name lookup works. + U32 index = original_name.find(" Resident"); + if (index != std::string::npos) + { + original_name = original_name.substr(0, index); + } + std::string legacy_name = gCacheName->buildLegacyName(original_name); + LLUUID agent_id; + gCacheName->getUUID(legacy_name, agent_id); + + if (agent_id.isNull()) + { + LL_WARNS("Messaging") << "buildLegacyName returned null while processing " << original_name << LL_ENDL; + } + else if (LLMuteList::getInstance()->isMuted(agent_id)) + { + break; + } + notice_bin_bucket = (struct notice_bucket_full_t*) &binary_bucket[0]; U8 has_inventory = notice_bin_bucket->header.has_inventory; U8 asset_type = notice_bin_bucket->header.asset_type; @@ -2563,27 +2607,11 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) break; case IM_GROUP_INVITATION: { - // Read the binary bucket for more information. - struct invite_bucket_t - { - S32 membership_fee; - LLUUID role_id; - }* invite_bucket; - - // Make sure the binary bucket is the correct size. - if (binary_bucket_size != sizeof(invite_bucket_t)) - { - LL_WARNS("Messaging") << "Malformed group invite binary bucket" << LL_ENDL; - break; - } - - invite_bucket = (struct invite_bucket_t*) &binary_bucket[0]; - S32 membership_fee = ntohl(invite_bucket->membership_fee); - // NaCl - Antispam - if(antispam || gSavedSettings.getBOOL("AntiSpamGroupInvites") || (membership_fee > 0 && gSavedSettings.getBOOL("AntiSpamGroupFeeInvites"))) + if (antispam || gSavedSettings.getBOOL("AntiSpamGroupInvites")) return; // NaCl End + //if (!is_linden && (is_busy || is_muted)) if ((is_busy || is_muted)) { @@ -2593,6 +2621,26 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) else { LL_INFOS("Messaging") << "Received IM_GROUP_INVITATION message." << LL_ENDL; + // Read the binary bucket for more information. + struct invite_bucket_t + { + S32 membership_fee; + LLUUID role_id; + }* invite_bucket; + + // Make sure the binary bucket is the correct size. + if (binary_bucket_size != sizeof(invite_bucket_t)) + { + LL_WARNS("Messaging") << "Malformed group invite binary bucket" << LL_ENDL; + break; + } + + invite_bucket = (struct invite_bucket_t*) &binary_bucket[0]; + S32 membership_fee = ntohl(invite_bucket->membership_fee); + // NaCl - Antispam + if (membership_fee > 0 && gSavedSettings.getBOOL("AntiSpamGroupFeeInvites")) + return; + // NaCl End LLSD payload; payload["transaction_id"] = session_id; @@ -2694,23 +2742,23 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) case IM_INVENTORY_ACCEPTED: { +// args["NAME"] = name; // [RLVa:KB] - Version: 1.23.4 | Checked: 2009-07-08 (RLVa-1.0.0e) | Modified: RLVa-0.2.0b - bool fRlvObfuscate = (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) && - (RlvUtil::isNearbyAgent(from_id)) && (!LLFloaterAvatarInfo::getInstance(from_id)); - args["NAME"] = (!fRlvObfuscate) ? name : RlvStrings::getAnonym(name); + bool fRlvFilterName = (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) && (RlvUtil::isNearbyAgent(from_id)) && + (!LLFloaterAvatarInfo::getInstance(from_id)); + args["NAME"] = (!fRlvFilterName) ? name : RlvStrings::getAnonym(name); // [/RLVa:KB] - //args["NAME"] = name; LLNotificationsUtil::add("InventoryAccepted", args); break; } case IM_INVENTORY_DECLINED: { +// args["NAME"] = name; // [RLVa:KB] - Version: 1.23.4 | Checked: 2009-07-08 (RLVa-1.0.0e) | Modified: RLVa-0.2.0b - bool fRlvObfuscate = (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) && - (RlvUtil::isNearbyAgent(from_id)) && (!LLFloaterAvatarInfo::getInstance(from_id)); - args["NAME"] = (!fRlvObfuscate) ? name : RlvStrings::getAnonym(name); + bool fRlvFilterName = (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) && (RlvUtil::isNearbyAgent(from_id)) && + (!LLFloaterAvatarInfo::getInstance(from_id)); + args["NAME"] = (!fRlvFilterName) ? name : RlvStrings::getAnonym(name); // [/RLVa:KB] - //args["NAME"] = name; LLNotificationsUtil::add("InventoryDeclined", args); break; } @@ -2778,11 +2826,6 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) saved = llformat("(Saved %s) ", formatted_time(timestamp).c_str()); } buffer = separator_string + saved + message.substr(message_offset); - BOOL is_this_agent = FALSE; - if(from_id == gAgentID) - { - is_this_agent = TRUE; - } gIMMgr->addMessage( session_id, from_id, @@ -2807,7 +2850,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) prepend_msg = std::string("IM: "); } chat.mText = prepend_msg + name + separator_string + saved + message.substr(message_offset); - LLFloaterChat::addChat(chat, TRUE, is_this_agent); + LLFloaterChat::addChat(chat, TRUE, from_id == gAgentID); } break; @@ -2846,6 +2889,22 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) chat.mFromID = from_id ^ gAgent.getSessionID(); } + chat.mSourceType = CHAT_SOURCE_OBJECT; + + // To conclude that the source type of message is CHAT_SOURCE_SYSTEM it's not + // enough to check only from name (i.e. fromName = "Second Life"). For example + // source type of messages from objects called "Second Life" should not be CHAT_SOURCE_SYSTEM. + bool chat_from_system = (SYSTEM_FROM == name) && region_id.isNull() && position.isNull(); + if(chat_from_system) + { + // System's UUID is NULL (fixes EXT-4766) + chat.mFromID = LLUUID::null; + chat.mSourceType = CHAT_SOURCE_SYSTEM; + } + + // IDEVO Some messages have embedded resident names + message = clean_name_from_task_im(message, from_group); + std::ostringstream link; link << "secondlife:///app/objectim/" << session_id << LLURI::mapToQueryString(query_string); @@ -2855,7 +2914,6 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) // Note: lie to LLFloaterChat::addChat(), pretending that this is NOT an IM, because // IMs from objcts don't open IM sessions. - chat.mSourceType = CHAT_SOURCE_OBJECT; LLFloaterChat::addChat(chat, FALSE, FALSE); } break; @@ -3477,12 +3535,10 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data) // if (chat.mSourceType == CHAT_SOURCE_OBJECT // && chat.mChatType != CHAT_TYPE_DEBUG_MSG // && gSavedSettings.getBOOL("EffectScriptChatParticles") ) -// [RLVa:KB] - Alternate: Snowglobe-1.2.4 | Checked: 2009-07-10 (RLVa-1.0.0g) - // Don't show swirly things for llOwnerSay() chat here because we handle those further down - // RELEASE-RLVa: if this code changes, remember to change the code down below as well - if ( (chat.mSourceType == CHAT_SOURCE_OBJECT && chat.mChatType != CHAT_TYPE_DEBUG_MSG) && - (gSavedSettings.getBOOL("EffectScriptChatParticles")) && - (CHAT_TYPE_OWNER != chat.mChatType) ) +// [RLVa:KB] - Checked: 2010-03-09 (RLVa-1.2.0b) | Modified: RLVa-1.0.0g + if ( ((chat.mSourceType == CHAT_SOURCE_OBJECT) && (chat.mChatType != CHAT_TYPE_DEBUG_MSG)) && + (gSavedSettings.getBOOL("EffectScriptChatParticles")) && + ((!rlv_handler_t::isEnabled()) || (CHAT_TYPE_OWNER != chat.mChatType)) ) // [/RLVa:KB] { LLPointer psc = new LLViewerPartSourceChat(chatter->getPositionAgent()); @@ -3836,11 +3892,10 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data) if(SHCommandHandler::handleCommand(false,mesg,from_id,chatter)) return; #endif //shy_mod -// [RLVa:KB] - Alternate: Snowglobe-1.2.4 | Checked: 2009-07-10 (RLVa-1.0.0g) +// [RLVa:KB] - Checked: 2010-03-09 (RLVa-1.2.0b) | Modified: RLVa-1.0.0g // Copy/paste from above - if ( chatter && (chat.mSourceType == CHAT_SOURCE_OBJECT && chat.mChatType != CHAT_TYPE_DEBUG_MSG) && - (gSavedSettings.getBOOL("EffectScriptChatParticles")) && - (CHAT_TYPE_OWNER != chat.mChatType) ) + if ( (rlv_handler_t::isEnabled()) && (chatter) && (chat.mSourceType == CHAT_SOURCE_OBJECT) && + (gSavedSettings.getBOOL("EffectScriptChatParticles")) ) { LLPointer psc = new LLViewerPartSourceChat(chatter->getPositionAgent()); psc->setSourceObject(chatter); @@ -3852,8 +3907,8 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data) } // [/RLVa:KB] case CHAT_TYPE_DEBUG_MSG: - case CHAT_TYPE_DIRECT: // llRegionSayTo() case CHAT_TYPE_NORMAL: + case CHAT_TYPE_DIRECT: verb = ": "; break; case CHAT_TYPE_SHOUT: @@ -3904,8 +3959,8 @@ void process_teleport_start(LLMessageSystem *msg, void**) LL_DEBUGS("Messaging") << "Got TeleportStart with TeleportFlags=" << teleport_flags << ". gTeleportDisplay: " << gTeleportDisplay << ", gAgent.mTeleportState: " << gAgent.getTeleportState() << LL_ENDL; - //if (teleport_flags & TELEPORT_FLAGS_DISABLE_CANCEL) -// [RLVa:KB] - Checked: 2009-07-07 (RLVa-1.0.0d) | Added: RLVa-0.2.0b +// if (teleport_flags & TELEPORT_FLAGS_DISABLE_CANCEL) +// [RLVa:KB] - Checked: 2010-04-07 (RLVa-1.2.0d) | Added: RLVa-0.2.0b if ( (teleport_flags & TELEPORT_FLAGS_DISABLE_CANCEL) || (!gRlvHandler.getCanCancelTp()) ) // [/RLVa:KB] { @@ -3944,8 +3999,8 @@ void process_teleport_progress(LLMessageSystem* msg, void**) } U32 teleport_flags = 0x0; msg->getU32("Info", "TeleportFlags", teleport_flags); - //if (teleport_flags & TELEPORT_FLAGS_DISABLE_CANCEL) -// [RLVa:KB] - Checked: 2009-07-07 (RLVa-1.0.0d) | Added: RLVa-0.2.0b +// if (teleport_flags & TELEPORT_FLAGS_DISABLE_CANCEL) +// [RLVa:KB] - Checked: 2010-04-07 (RLVa-1.2.0d) | Added: RLVa-0.2.0b if ( (teleport_flags & TELEPORT_FLAGS_DISABLE_CANCEL) || (!gRlvHandler.getCanCancelTp()) ) // [/RLVa:KB] { @@ -4146,7 +4201,7 @@ void process_teleport_finish(LLMessageSystem* msg, void**) gAgent.setRegion(regionp); gObjectList.shiftObjects(shift_vector); - if (gAgentAvatarp) + if (isAgentAvatarValid()) { gAgentAvatarp->clearChatText(); gAgentCamera.slamLookAt(look_at); @@ -4462,8 +4517,6 @@ void send_agent_update(BOOL force_send, BOOL send_reliable) return; } - if(gAgent.getPhantom()) return; //Don't want to do this while phantom - // We have already requested to log out. Don't send agent updates. if(LLAppViewer::instance()->logoutRequestSent()) { @@ -4552,6 +4605,8 @@ void send_agent_update(BOOL force_send, BOOL send_reliable) head_rot_chg = dot(last_head_rot, head_rotation); + //static S32 msg_number = 0; // Used for diagnostic log messages + if (force_send || (cam_center_chg.magVec() > TRANSLATE_THRESHOLD) || (head_rot_chg < THRESHOLD_HEAD_ROT_QDOT) || @@ -4560,19 +4615,20 @@ void send_agent_update(BOOL force_send, BOOL send_reliable) control_flag_change != 0 || flag_change != 0) { - /* + /* Diagnotics to show why we send the AgentUpdate message. Also un-commment the msg_number code above and below this block + msg_number += 1; if (head_rot_chg < THRESHOLD_HEAD_ROT_QDOT) { //LL_INFOS("Messaging") << "head rot " << head_rotation << LL_ENDL; - LL_INFOS("Messaging") << "head_rot_chg = " << head_rot_chg << LL_ENDL; + LL_INFOS("Messaging") << "msg " << msg_number << ", frame " << LLFrameTimer::getFrameCount() << ", head_rot_chg " << head_rot_chg << LL_ENDL; } if (cam_rot_chg.magVec() > ROTATION_THRESHOLD) { - LL_INFOS("Messaging") << "cam rot " << cam_rot_chg.magVec() << LL_ENDL; + LL_INFOS("Messaging") << "msg " << msg_number << ", frame " << LLFrameTimer::getFrameCount() << ", cam rot " << cam_rot_chg.magVec() << LL_ENDL; } if (cam_center_chg.magVec() > TRANSLATE_THRESHOLD) { - LL_INFOS("Messaging") << "cam center " << cam_center_chg.magVec() << LL_ENDL; + LL_INFOS("Messaging") << "msg " << msg_number << ", frame " << LLFrameTimer::getFrameCount() << ", cam center " << cam_center_chg.magVec() << LL_ENDL; } // if (drag_delta_chg.magVec() > TRANSLATE_THRESHOLD) // { @@ -4580,9 +4636,9 @@ void send_agent_update(BOOL force_send, BOOL send_reliable) // } if (control_flag_change) { - LL_INFOS("Messaging") << "dcf = " << control_flag_change << LL_ENDL; + LL_INFOS("Messaging") << "msg " << msg_number << ", frame " << LLFrameTimer::getFrameCount() << ", dcf = " << control_flag_change << LL_ENDL; } - */ +*/ duplicate_count = 0; } @@ -4617,6 +4673,26 @@ void send_agent_update(BOOL force_send, BOOL send_reliable) if (duplicate_count < DUP_MSGS && !gDisconnected) { + /* More diagnostics to count AgentUpdate messages + static S32 update_sec = 0; + static S32 update_count = 0; + static S32 max_update_count = 0; + S32 cur_sec = lltrunc( LLTimer::getTotalSeconds() ); + update_count += 1; + if (cur_sec != update_sec) + { + if (update_sec != 0) + { + update_sec = cur_sec; + //msg_number = 0; + max_update_count = llmax(max_update_count, update_count); + llinfos << "Sent " << update_count << " AgentUpdate messages per second, max is " << max_update_count << llendl; + } + update_sec = cur_sec; + update_count = 0; + } + */ + LLFastTimer t(FTM_AGENT_UPDATE_SEND); // Build the message msg->newMessageFast(_PREHASH_AgentUpdate); @@ -4834,8 +4910,7 @@ void process_time_synch(LLMessageSystem *mesgsys, void **user_data) LLWorld::getInstance()->setSpaceTimeUSec(space_time_usec); - //LL_DEBUGS("Messaging") << "time_synch() - " << sun_direction << ", " << sun_ang_velocity - // << ", " << phase << LL_ENDL; + LL_DEBUGS("Windlight Sync") << "Sun phase: " << phase << " rad = " << fmodf(phase / F_TWO_PI + 0.25, 1.f) * 24.f << " h" << LL_ENDL; gSky.setSunPhase(phase); gSky.setSunTargetDirection(sun_direction, sun_ang_velocity); @@ -4914,7 +4989,7 @@ void process_sound_trigger(LLMessageSystem *msg, void **) if (object_id == owner_id && !gSavedSettings.getBOOL("EnableGestureSounds")) { // Don't mute own gestures, if they're not muted. - if(owner_id != gAgent.getID() || !gSavedSettings.getBOOL("EnableGestureSoundsSelf")) + if (owner_id != gAgentID || !gSavedSettings.getBOOL("EnableGestureSoundsSelf")) return; } @@ -5726,17 +5801,17 @@ void process_money_balance_reply( LLMessageSystem* msg, void** ) return; } - // Once the 'recent' container gets large enough, chop some - // off the beginning. - const U32 MAX_LOOKBACK = 30; - const S32 POP_FRONT_SIZE = 12; - if(recent.size() > MAX_LOOKBACK) - { - LL_DEBUGS("Messaging") << "Removing oldest transaction records" << LL_ENDL; - recent.erase(recent.begin(), recent.begin() + POP_FRONT_SIZE); - } - //LL_DEBUGS("Messaging") << "Pushing back transaction " << tid << LL_ENDL; - recent.push_back(tid); + // Once the 'recent' container gets large enough, chop some + // off the beginning. + const U32 MAX_LOOKBACK = 30; + const S32 POP_FRONT_SIZE = 12; + if(recent.size() > MAX_LOOKBACK) + { + LL_DEBUGS("Messaging") << "Removing oldest transaction records" << LL_ENDL; + recent.erase(recent.begin(), recent.begin() + POP_FRONT_SIZE); + } + //LL_DEBUGS("Messaging") << "Pushing back transaction " << tid << LL_ENDL; + recent.push_back(tid); if (msg->has("TransactionInfo")) { @@ -5959,14 +6034,14 @@ static void process_money_balance_reply_extended(LLMessageSystem* msg) bool handle_prompt_for_maturity_level_change_callback(const LLSD& notification, const LLSD& response) { S32 option = LLNotificationsUtil::getSelectedOption(notification, response); - + if (0 == option) { // set the preference to the maturity of the region we're calling U8 preferredMaturity = static_cast(notification["payload"]["_region_access"].asInteger()); gSavedSettings.setU32("PreferredMaturity", static_cast(preferredMaturity)); } - + return false; } @@ -6475,7 +6550,7 @@ void process_economy_data(LLMessageSystem *msg, void** /*user_data*/) LL_INFOS_ONCE("Messaging") << "EconomyData message arrived; upload cost is L$" << upload_cost << LL_ENDL; LLFloaterImagePreview::setUploadAmount(upload_cost); - LLFloaterAnimPreview::setUploadAmount(upload_cost); + LLFloaterBvhPreview::setUploadAmount(upload_cost); std::string fee = gHippoGridManager->getConnectedGrid()->getUploadFee(); gMenuHolder->childSetLabelArg("Upload Image", "[UPLOADFEE]", fee); diff --git a/indra/newview/llviewerobjectbackup.cpp b/indra/newview/llviewerobjectbackup.cpp index 0dde3582c..09783ed21 100644 --- a/indra/newview/llviewerobjectbackup.cpp +++ b/indra/newview/llviewerobjectbackup.cpp @@ -55,7 +55,7 @@ #include "llappviewer.h" #include "llassetuploadresponders.h" #include "statemachine/aifilepicker.h" -#include "llfloateranimpreview.h" +#include "llfloaterbvhpreview.h" #include "llfloaterbuycurrency.h" #include "llfloaterimagepreview.h" #include "llfloaternamedesc.h" diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index f000bc39c..6c09d31e4 100644 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -1638,15 +1638,10 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames) capabilityNames.append("EnvironmentSettings"); capabilityNames.append("EstateChangeInfo"); capabilityNames.append("EventQueueGet"); - - if (gSavedSettings.getBOOL("UseHTTPInventory")) //Caps suffixed with 2 by LL. Don't update until rest of fetch system is updated first. - { - capabilityNames.append("FetchLib2"); - capabilityNames.append("FetchLibDescendents2"); - capabilityNames.append("FetchInventory2"); - capabilityNames.append("FetchInventoryDescendents2"); - } - + capabilityNames.append("FetchLib2"); + capabilityNames.append("FetchLibDescendents2"); + capabilityNames.append("FetchInventory2"); + capabilityNames.append("FetchInventoryDescendents2"); capabilityNames.append("GamingData"); //Used by certain grids. capabilityNames.append("GetDisplayNames"); capabilityNames.append("GetMesh"); @@ -1701,6 +1696,7 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames) capabilityNames.append("ViewerMetrics"); capabilityNames.append("ViewerStartAuction"); capabilityNames.append("ViewerStats"); + capabilityNames.append("WearablesLoaded"); // Please add new capabilities alphabetically to reduce // merge conflicts. diff --git a/indra/newview/llviewerstats.cpp b/indra/newview/llviewerstats.cpp index 2d20f8de3..4728f0ffd 100644 --- a/indra/newview/llviewerstats.cpp +++ b/indra/newview/llviewerstats.cpp @@ -67,6 +67,10 @@ class AIHTTPTimeoutPolicy; extern AIHTTPTimeoutPolicy viewerStatsResponder_timeout; +namespace AICurlInterface { +size_t getHTTPBandwidth(void); +} + class StatAttributes { public: @@ -210,7 +214,8 @@ LLViewerStats::LLViewerStats() : mLayersKBitStat("layerskbitstat"), mObjectKBitStat("objectkbitstat"), mAssetKBitStat("assetkbitstat"), - mTextureKBitStat("texturekbitstat"), + mHTTPTextureKBitStat("httptexturekbitstat"), + mUDPTextureKBitStat("udptexturekbitstat"), mMallocStat("mallocstat"), mVFSPendingOperations("vfspendingoperations"), mObjectsDrawnStat("objectsdrawnstat"), @@ -300,7 +305,8 @@ void LLViewerStats::resetStats() stats.mKBitStat.reset(); stats.mLayersKBitStat.reset(); stats.mObjectKBitStat.reset(); - stats.mTextureKBitStat.reset(); + stats.mHTTPTextureKBitStat.reset(); + stats.mUDPTextureKBitStat.reset(); stats.mVFSPendingOperations.reset(); stats.mAssetKBitStat.reset(); stats.mPacketsInStat.reset(); @@ -673,13 +679,13 @@ void update_statistics() // Only update texture stats periodically so that they are less noisy { - static const F32 texture_stats_freq = 10.f; + static const F32 texture_stats_freq = 0.25f; static LLFrameTimer texture_stats_timer; if (texture_stats_timer.getElapsedTimeF32() >= texture_stats_freq) { - stats.mTextureKBitStat.addValue(LLViewerTextureList::sTextureBits/1024.f); + stats.mHTTPTextureKBitStat.addValue(AICurlInterface::getHTTPBandwidth()/125.f); + stats.mUDPTextureKBitStat.addValue(LLViewerTextureList::sTextureBits/1024.f); stats.mTexturePacketsStat.addValue(LLViewerTextureList::sTexturePackets); - LLAppViewer::getTextureFetch()->setTextureBandwidth(LLViewerTextureList::sTextureBits/1024.f/texture_stats_timer.getElapsedTimeF32()); gTotalTextureBytes += LLViewerTextureList::sTextureBits / 8; LLViewerTextureList::sTextureBits = 0; LLViewerTextureList::sTexturePackets = 0; diff --git a/indra/newview/llviewerstats.h b/indra/newview/llviewerstats.h index f7c7c0c1c..f6300d1e2 100644 --- a/indra/newview/llviewerstats.h +++ b/indra/newview/llviewerstats.h @@ -43,7 +43,8 @@ public: mLayersKBitStat, mObjectKBitStat, mAssetKBitStat, - mTextureKBitStat, + mHTTPTextureKBitStat, + mUDPTextureKBitStat, mVFSPendingOperations, mObjectsDrawnStat, mObjectsCulledStat, diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp index 7a7b70f9b..80efedbed 100644 --- a/indra/newview/llviewertexturelist.cpp +++ b/indra/newview/llviewertexturelist.cpp @@ -663,13 +663,15 @@ static LLFastTimer::DeclareTimer FTM_IMAGE_MEDIA("Media"); void LLViewerTextureList::updateImages(F32 max_time) { static BOOL cleared = FALSE; - static const LLCachedControl hide_tp_screen("AscentDisableTeleportScreens",false); + //Singu note: Don't clear vbos on local tp until some serious geom rebuild bugs are stomped out. + //Currently it causes prims to fail to rebuild when they should be popping back into visiblity. + //static const LLCachedControl hide_tp_screen("AscentDisableTeleportScreens",false); //Can't check gTeleportDisplay due to a process_teleport_local(), which sets it to true for local teleports... so: // Do this case if IS teleporting but NOT local teleporting, AND either the TP screen is set to appear OR we just entered the sim (TELEPORT_START_ARRIVAL) LLAgent::ETeleportState state = gAgent.getTeleportState(); if(state != LLAgent::TELEPORT_NONE && state != LLAgent::TELEPORT_LOCAL && state != LLAgent::TELEPORT_PENDING && - (!hide_tp_screen || state == LLAgent::TELEPORT_START_ARRIVAL || state == LLAgent::TELEPORT_ARRIVING)) + (/*!hide_tp_screen ||*/ state == LLAgent::TELEPORT_START_ARRIVAL || state == LLAgent::TELEPORT_ARRIVING)) { if(!cleared) { @@ -685,8 +687,6 @@ void LLViewerTextureList::updateImages(F32 max_time) } cleared = FALSE; - LLAppViewer::getTextureFetch()->setTextureBandwidth(LLViewerStats::getInstance()->mTextureKBitStat.getMeanPerSec()); - S32 global_raw_memory; { global_raw_memory = *AIAccess(LLImageRaw::sGlobalRawMemory); @@ -1340,6 +1340,7 @@ void LLViewerTextureList::receiveImageHeader(LLMessageSystem *msg, void **user_d { received_size = msg->getReceiveSize() ; } + // Only used for statistics and texture console. gTextureList.sTextureBits += received_size * 8; gTextureList.sTexturePackets++; diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 1f4ae3a69..8d583108f 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -48,12 +48,10 @@ #include "llviewquery.h" #include "llxmltree.h" -//#include "llviewercamera.h" #include "llrender.h" #include "llvoiceclient.h" // for push-to-talk button handling - // // TODO: Many of these includes are unnecessary. Remove them. // @@ -67,7 +65,6 @@ #include "llrect.h" #include "llsky.h" #include "llstring.h" -#include "lltrans.h" #include "llui.h" #include "lluuid.h" #include "llview.h" @@ -136,8 +133,8 @@ #include "llpreviewtexture.h" #include "llprogressview.h" #include "llresmgr.h" -#include "llrootview.h" #include "llselectmgr.h" +#include "llrootview.h" #include "llrendersphere.h" #include "llstartup.h" #include "llstatusbar.h" @@ -163,6 +160,7 @@ #include "lltoolplacer.h" #include "lltoolselectland.h" #include "lltoolview.h" +#include "lltrans.h" #include "lluictrlfactory.h" #include "llurldispatcher.h" // SLURL from other app instance #include "llvieweraudio.h" @@ -219,7 +217,6 @@ extern BOOL gDebugClicks; extern BOOL gDisplaySwapBuffers; extern BOOL gDepthDirty; extern BOOL gResizeScreenTexture; -extern S32 gJamesInt; LLViewerWindow *gViewerWindow = NULL; LLVelocityBar *gVelocityBar = NULL; @@ -291,14 +288,14 @@ private: line_list_t mLineList; LLColor4 mTextColor; -public: - LLDebugText(LLViewerWindow* window) : mWindow(window) {} - void addText(S32 x, S32 y, const std::string &text) { mLineList.push_back(Line(text, x, y)); } +public: + LLDebugText(LLViewerWindow* window) : mWindow(window) {} + void update() { std::string wind_vel_text; @@ -307,6 +304,14 @@ public: std::string rwind_vector_text; std::string audio_text; + static const std::string beacon_particle = LLTrans::getString("BeaconParticle"); + static const std::string beacon_physical = LLTrans::getString("BeaconPhysical"); + static const std::string beacon_scripted = LLTrans::getString("BeaconScripted"); + static const std::string beacon_scripted_touch = LLTrans::getString("BeaconScriptedTouch"); + static const std::string beacon_sound = LLTrans::getString("BeaconSound"); + static const std::string beacon_media = LLTrans::getString("BeaconMedia"); + static const std::string particle_hiding = LLTrans::getString("ParticleHiding"); + // Draw the statistics in a light gray // and in a thin font mTextColor = LLColor4( 0.86f, 0.86f, 0.86f, 1.f ); @@ -329,18 +334,15 @@ public: addText(xpos, ypos, llformat("Texture: %d:%02d:%02d", hours,mins,secs)); ypos += y_inc2; } - { F32 time = gFrameTimeSeconds; S32 hours = (S32)(time / (60*60)); S32 mins = (S32)((time - hours*(60*60)) / 60); S32 secs = (S32)((time - hours*(60*60) - mins*60)); addText(xpos, ypos, llformat("Time: %d:%02d:%02d", hours,mins,secs)); ypos += y_inc; } - } static const LLCachedControl analyze_target_texture("AnalyzeTargetTexture", false); if(analyze_target_texture) { - static LLViewerObject* lastObject = NULL; LLSelectNode* nodep = LLSelectMgr::instance().getPrimaryHoverNode(); LLObjectSelectionHandle handle = LLSelectMgr::instance().getHoverObjects(); if(nodep || handle.notNull()) @@ -371,7 +373,7 @@ public: static const LLCachedControl use_rmse_auto_mask("SHUseRMSEAutoMask",false); static const LLCachedControl auto_mask_max_rmse("SHAutoMaskMaxRMSE",.09f); addText(xpos, ypos, llformat("Mask: %s", imagep->getIsAlphaMask(use_rmse_auto_mask ? auto_mask_max_rmse : -1.f) ? "TRUE":"FALSE")); ypos += y_inc; - addText(xpos, ypos, llformat("ID: %s", imagep->getID().asString())); ypos += y_inc; + addText(xpos, ypos, llformat("ID: %s", imagep->getID().asString().c_str())); ypos += y_inc; } } } @@ -386,6 +388,7 @@ public: ypos += y_inc; } #endif + if (gDisplayCameraPos) { std::string camera_view_text; @@ -580,7 +583,7 @@ public: ypos += y_inc; addText(xpos, ypos, llformat("%d Render Calls", gPipeline.mBatchCount)); - ypos += y_inc; + ypos += y_inc; addText(xpos, ypos, llformat("%d Matrix Ops", gPipeline.mMatrixOpCount)); ypos += y_inc; @@ -600,7 +603,7 @@ public: gPipeline.mMaxBatchSize = 0; gPipeline.mBatchCount = 0; } - ypos += y_inc; + ypos += y_inc; addText(xpos,ypos, llformat("%d/%d Nodes visible", gPipeline.mNumVisibleNodes, LLSpatialGroup::sNodeCount)); @@ -691,7 +694,7 @@ public: } LLVertexBuffer::sBindCount = LLImageGL::sBindCount = - LLVertexBuffer::sSetCount = LLImageGL::sUniqueCount = + LLVertexBuffer::sSetCount = LLImageGL::sUniqueCount = gPipeline.mNumVisibleNodes = LLPipeline::sVisibleLightCount = 0; } static const LLCachedControl debug_show_render_matrices("DebugShowRenderMatrices"); @@ -748,39 +751,44 @@ public: addText(xpos, ypos, llformat("Total Allocated(KB): %d", LLPrivateMemoryPoolManager::getInstance()->mTotalAllocatedSize / 1024)); ypos += y_inc; } + // only display these messages if we are actually rendering beacons at this moment static const LLCachedControl beacons_visible("BeaconsVisible",false); if (LLPipeline::getRenderBeacons(NULL) && beacons_visible) { + if (LLPipeline::toggleRenderTypeControlNegated((void*)LLPipeline::RENDER_TYPE_PARTICLES)) + { + addText(xpos, ypos, particle_hiding); + ypos += y_inc; + } + if (LLPipeline::getRenderParticleBeacons(NULL)) { addText(xpos, ypos, "Viewing particle beacons (blue)"); ypos += y_inc; } - if (LLPipeline::toggleRenderTypeControlNegated((void*)LLPipeline::RENDER_TYPE_PARTICLES)) + + if (LLPipeline::getRenderSoundBeacons(NULL)) { - addText(xpos, ypos, "Hiding particles"); - ypos += y_inc; - } - if (LLPipeline::getRenderPhysicalBeacons(NULL)) - { - addText(xpos, ypos, "Viewing physical object beacons (green)"); + addText(xpos, ypos, "Viewing sound beacons (blue/cyan/green/yellow/red)"); ypos += y_inc; } + if (LLPipeline::getRenderScriptedBeacons(NULL)) { - addText(xpos, ypos, "Viewing scripted object beacons (red)"); + addText(xpos, ypos, beacon_scripted); ypos += y_inc; } else if (LLPipeline::getRenderScriptedTouchBeacons(NULL)) { - addText(xpos, ypos, "Viewing scripted object with touch function beacons (red)"); + addText(xpos, ypos, beacon_scripted_touch); ypos += y_inc; } - if (LLPipeline::getRenderSoundBeacons(NULL)) + + if (LLPipeline::getRenderPhysicalBeacons(NULL)) { - addText(xpos, ypos, "Viewing sound beacons (blue/cyan/green/yellow/red)"); + addText(xpos, ypos, "Viewing physical object beacons (green)"); ypos += y_inc; } } @@ -837,9 +845,13 @@ BOOL LLViewerWindow::handleAnyMouseClick(LLWindow *window, LLCoordGL pos, MASK y = llround((F32)y / mDisplayScale.mV[VY]); if (down) + { buttonstatestr = "down"; + } else + { buttonstatestr = "up"; + } switch (clicktype) { @@ -874,7 +886,7 @@ BOOL LLViewerWindow::handleAnyMouseClick(LLWindow *window, LLCoordGL pos, MASK llinfos << "ViewerWindow " << buttonname << " mouse " << buttonstatestr << " at " << x << "," << y << llendl; } - // Make sure we get a coresponding mouseup event, even if the mouse leaves the window + // Make sure we get a corresponding mouseup event, even if the mouse leaves the window if (down) { mWindow->captureMouse(); @@ -928,15 +940,15 @@ BOOL LLViewerWindow::handleAnyMouseClick(LLWindow *window, LLCoordGL pos, MASK if (down) { - if (top_ctrl->pointInView(local_x, local_y)) - { - return top_ctrl->handleAnyMouseClick(local_x, local_y, mask, clicktype, down) ; - } - else - { - gFocusMgr.setTopCtrl(NULL); - } - } + if (top_ctrl->pointInView(local_x, local_y)) + { + return top_ctrl->handleAnyMouseClick(local_x, local_y, mask, clicktype, down) ; + } + else + { + gFocusMgr.setTopCtrl(NULL); + } + } else handled = top_ctrl->pointInView(local_x, local_y) && top_ctrl->handleMouseUp(local_x, local_y, mask); } @@ -957,38 +969,38 @@ BOOL LLViewerWindow::handleAnyMouseClick(LLWindow *window, LLCoordGL pos, MASK if (down) { - // Do not allow tool manager to handle mouseclicks if we have disconnected - if (gDisconnected) - { - return FALSE; - } - - if(LLToolMgr::getInstance()->getCurrentTool()->handleAnyMouseClick( x, y, mask, clicktype, down ) ) - { - // This is necessary to force clicks in the world to cause edit - // boxes that might have keyboard focus to relinquish it, and hence - // cause a commit to update their value. JC - gFocusMgr.setKeyboardFocus(NULL); - return TRUE; - } + // Do not allow tool manager to handle mouseclicks if we have disconnected + if (gDisconnected) + { + return FALSE; + } + + if (LLToolMgr::getInstance()->getCurrentTool()->handleAnyMouseClick( x, y, mask, clicktype, down ) ) + { + // This is necessary to force clicks in the world to cause edit + // boxes that might have keyboard focus to relinquish it, and hence + // cause a commit to update their value. JC + gFocusMgr.setKeyboardFocus(NULL); + return TRUE; + } } else { - mWindow->releaseMouse(); + mWindow->releaseMouse(); - LLTool *tool = LLToolMgr::getInstance()->getCurrentTool(); + LLTool *tool = LLToolMgr::getInstance()->getCurrentTool(); if( !handled ) - { + { handled = mRootView->handleAnyMouseClick(x, y, mask, clicktype, down); - } + } if( !handled ) - { + { if (tool) - { + { handled = tool->handleAnyMouseClick(x, y, mask, clicktype, down); - } - } + } + } } return (!down); @@ -1005,7 +1017,7 @@ BOOL LLViewerWindow::handleDoubleClick(LLWindow *window, LLCoordGL pos, MASK ma // try handling as a double-click first, then a single-click if that // wasn't handled. BOOL down = TRUE; - return handleAnyMouseClick(window,pos,mask,LLMouseHandler::CLICK_DOUBLELEFT,down) || + return handleAnyMouseClick(window, pos, mask, LLMouseHandler::CLICK_DOUBLELEFT, down) || handleMouseDown(window, pos, mask); } @@ -1019,16 +1031,17 @@ BOOL LLViewerWindow::handleMouseUp(LLWindow *window, LLCoordGL pos, MASK mask) BOOL LLViewerWindow::handleRightMouseDown(LLWindow *window, LLCoordGL pos, MASK mask) { //From Phoenix - gSavedSettings.setBOOL("zmm_rightmousedown",1); - if(gAgentCamera.cameraMouselook()&&gSavedSettings.getBOOL("zmm_isinml")==0) + // Singu TODO: Change these from debug settings to externs? + gSavedSettings.setBOOL("zmm_rightmousedown", true); + if (gAgentCamera.cameraMouselook() && !gSavedSettings.getBOOL("zmm_isinml")) { llinfos << "zmmisinml set to true" << llendl; - gSavedSettings.setBOOL("zmm_isinml",1); - F32 deffov=LLViewerCamera::getInstance()->getDefaultFOV(); - gSavedSettings.setF32("zmm_deffov",deffov); - LLViewerCamera::getInstance()->setDefaultFOV(gSavedSettings.getF32("zmm_deffov")/gSavedSettings.getF32("zmm_mlfov")); + gSavedSettings.setBOOL("zmm_isinml", true); + F32 deffov = LLViewerCamera::getInstance()->getDefaultFOV(); + gSavedSettings.setF32("zmm_deffov", deffov); + LLViewerCamera::getInstance()->setDefaultFOV(deffov/gSavedSettings.getF32("zmm_mlfov")); } - + S32 x = pos.mX; S32 y = pos.mY; x = llround((F32)x / mDisplayScale.mV[VX]); @@ -1041,7 +1054,6 @@ BOOL LLViewerWindow::handleRightMouseDown(LLWindow *window, LLCoordGL pos, MASK if (handle) return handle; - // *HACK: this should be rolled into the composite tool logic, not // hardcoded at the top level. if (CAMERA_MODE_CUSTOMIZE_AVATAR != gAgentCamera.getCameraMode() && LLToolMgr::getInstance()->getCurrentTool() != LLToolPie::getInstance()) @@ -1058,14 +1070,14 @@ BOOL LLViewerWindow::handleRightMouseDown(LLWindow *window, LLCoordGL pos, MASK BOOL LLViewerWindow::handleRightMouseUp(LLWindow *window, LLCoordGL pos, MASK mask) { - gSavedSettings.setBOOL("zmm_rightmousedown",0); + gSavedSettings.setBOOL("zmm_rightmousedown", false); if(gSavedSettings.getBOOL("zmm_isinml")==1) { llinfos << "zmmisinml set to false" << llendl; gSavedSettings.setBOOL("zmm_isinml",0); LLViewerCamera::getInstance()->setDefaultFOV(gSavedSettings.getF32("zmm_deffov")); - } - + } + BOOL down = FALSE; return handleAnyMouseClick(window,pos,mask,LLMouseHandler::CLICK_RIGHT,down); } @@ -1110,12 +1122,11 @@ void LLViewerWindow::handleMouseMove(LLWindow *window, LLCoordGL pos, MASK mask { gMouseIdleTimer.reset(); } + saveLastMouse(mouse_point); BOOL mouse_actually_moved = !gFocusMgr.getMouseCapture() && // mouse is not currenty captured ((prev_saved_mouse_point.mX != mCurrentMousePoint.mX) || (prev_saved_mouse_point.mY != mCurrentMousePoint.mY)); // mouse moved from last recorded position - - mWindow->showCursorFromMouseMove(); if (gAwayTimer.getElapsedTimeF32() > MIN_AFK_TIME @@ -1268,7 +1279,7 @@ BOOL LLViewerWindow::handleActivate(LLWindow *window, BOOL activated) { if (activated) { - mActive = TRUE; + mActive = true; send_agent_resume(); gAgent.clearAFK(); if (mWindow->getFullscreen() && !mIgnoreActivate) @@ -1298,7 +1309,8 @@ BOOL LLViewerWindow::handleActivate(LLWindow *window, BOOL activated) } else { - mActive = FALSE; + mActive = false; + if (gSavedSettings.getBOOL("AllowIdleAFK")) { gAgent.setAFK(); @@ -1484,9 +1496,8 @@ LLViewerWindow::LLViewerWindow( S32 x, S32 y, S32 width, S32 height, BOOL fullscreen, BOOL ignore_pixel_depth) - : - mWindow(NULL), - mActive(TRUE), +: mWindow(NULL), + mActive(true), mWantFullscreen(fullscreen), mShowFullscreenProgress(FALSE), mWindowRectRaw(0, height, width, 0), @@ -1552,7 +1563,7 @@ LLViewerWindow::LLViewerWindow( LL_WARNS("Window") << "Unable to create window, be sure screen is set at 32-bit color in Control Panels->Display->Settings" << LL_ENDL; #endif - LLAppViewer::instance()->fastQuit(1); + LLAppViewer::instance()->fastQuit(1); } if (!LLAppViewer::instance()->restoreErrorTrap()) @@ -1561,15 +1572,15 @@ LLViewerWindow::LLViewerWindow( } LLCoordScreen scr; - mWindow->getSize(&scr); + mWindow->getSize(&scr); - if(fullscreen && ( scr.mX!=width || scr.mY!=height)) - { + if(fullscreen && ( scr.mX!=width || scr.mY!=height)) + { llwarns << "Fullscreen has forced us in to a different resolution now using "<setFollows(FOLLOWS_LEFT | FOLLOWS_RIGHT | FOLLOWS_BOTTOM); - mRootView->addChild(gConsole); + getRootView()->addChild(gConsole); // Debug view over the console gDebugView = new LLDebugView("gDebugView", full_window); @@ -1895,7 +1906,7 @@ void LLViewerWindow::adjustRectanglesForFirstUse(const LLRect& window) adjust_rect_top_left("FloaterGestureRect2", window); adjust_rect_top_right("FloaterMiniMapRect", window); - + adjust_rect_top_right("FloaterLagMeter", window); adjust_rect_top_left("FloaterBuildOptionsRect", window); @@ -1928,7 +1939,7 @@ void LLViewerWindow::adjustRectanglesForFirstUse(const LLRect& window) r.getHeight()); gSavedSettings.setRect("FloaterInventoryRect", r); } - + // adjust_rect_top_left("FloaterHUDRect2", window); // slightly off center to be left of the avatar. @@ -1971,7 +1982,7 @@ void LLViewerWindow::initWorldUI() gHoverView = new LLHoverView(std::string("gHoverView"), full_window); gHoverView->setVisible(TRUE); mRootView->addChild(gHoverView); - + gIMMgr = LLIMMgr::getInstance(); // @@ -1984,7 +1995,7 @@ void LLViewerWindow::initWorldUI() gFloaterTools = new LLFloaterTools(); gFloaterTools->setVisible(FALSE); } - + if ( gHUDView == NULL ) { LLRect hud_rect = full_window; @@ -2000,7 +2011,7 @@ void LLViewerWindow::initWorldUI() LLPanel* panel_ssf_container = getRootView()->getChild("state_management_buttons_container"); panel_ssf_container->setVisible(TRUE); - + LLMenuOptionPathfindingRebakeNavmesh::getInstance()->initialize(); } @@ -2072,10 +2083,12 @@ void LLViewerWindow::shutdownViews() { gMorphView->setVisible(FALSE); } + llinfos << "Global views cleaned." << llendl ; // DEV-40930: Clear sModalStack. Otherwise, any LLModalDialog left open // will crump with LL_ERRS. LLModalDialog::shutdownModals(); + llinfos << "LLModalDialog shut down." << llendl; // Delete all child views. delete mRootView; @@ -2137,8 +2150,6 @@ void LLViewerWindow::shutdownGL() llinfos << "Cleaning up select manager" << llendl; LLSelectMgr::getInstance()->cleanup(); - - llinfos << "Stopping GL during shutdown" << llendl; if (!gNoRender) { @@ -2298,10 +2309,10 @@ void LLViewerWindow::reshape(S32 width, S32 height) // Hide normal UI when a logon fails void LLViewerWindow::setNormalControlsVisible( BOOL visible ) { - if ( gBottomPanel ) + if (gBottomPanel) { - gBottomPanel->setVisible( visible ); - gBottomPanel->setEnabled( visible ); + gBottomPanel->setVisible(visible); + gBottomPanel->setEnabled(visible); } if ( gMenuBarView ) @@ -2313,7 +2324,7 @@ void LLViewerWindow::setNormalControlsVisible( BOOL visible ) setMenuBackgroundColor(gAgent.getGodLevel() > GOD_NOT, LLViewerLogin::getInstance()->isInProductionGrid()); } - + if ( gStatusBar ) { gStatusBar->setVisible( visible ); @@ -2323,35 +2334,35 @@ void LLViewerWindow::setNormalControlsVisible( BOOL visible ) void LLViewerWindow::setMenuBackgroundColor(bool god_mode, bool dev_grid) { - LLSD args; - LLColor4 new_bg_color; + LLSD args; + LLColor4 new_bg_color; - if(god_mode && LLViewerLogin::getInstance()->isInProductionGrid()) - { - new_bg_color = gColors.getColor( "MenuBarGodBgColor" ); - } - else if(god_mode && !LLViewerLogin::getInstance()->isInProductionGrid()) - { - new_bg_color = gColors.getColor( "MenuNonProductionGodBgColor" ); - } - else if(!god_mode && !LLViewerLogin::getInstance()->isInProductionGrid()) - { - new_bg_color = gColors.getColor( "MenuNonProductionBgColor" ); - } - else - { - new_bg_color = gColors.getColor( "MenuBarBgColor" ); - } + if(god_mode && LLViewerLogin::getInstance()->isInProductionGrid()) + { + new_bg_color = gColors.getColor( "MenuBarGodBgColor" ); + } + else if(god_mode && !LLViewerLogin::getInstance()->isInProductionGrid()) + { + new_bg_color = gColors.getColor( "MenuNonProductionGodBgColor" ); + } + else if(!god_mode && !LLViewerLogin::getInstance()->isInProductionGrid()) + { + new_bg_color = gColors.getColor( "MenuNonProductionBgColor" ); + } + else + { + new_bg_color = gColors.getColor( "MenuBarBgColor" ); + } - if(gMenuBarView) - { - gMenuBarView->setBackgroundColor( new_bg_color ); - } + if(gMenuBarView) + { + gMenuBarView->setBackgroundColor( new_bg_color ); + } - if(gStatusBar) - { - gStatusBar->setBackgroundColor( new_bg_color ); - } + if(gStatusBar) + { + gStatusBar->setBackgroundColor( new_bg_color ); + } } void LLViewerWindow::drawDebugText() @@ -2422,6 +2433,7 @@ void LLViewerWindow::draw() { gUIProgram.bind(); } + gGL.pushMatrix(); { @@ -2469,7 +2481,7 @@ void LLViewerWindow::draw() gGL.matrixMode(LLRender::MM_MODELVIEW); LLUI::pushMatrix(); - LLUI::translate( (F32) screen_x, (F32) screen_y, 0.f); + LLUI::translate( (F32) screen_x, (F32) screen_y); if(gDebugGL)check_blend_funcs(); top_ctrl->draw(); if(gDebugGL)check_blend_funcs(); @@ -2545,7 +2557,6 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask) && !gFocusMgr.getKeystrokesOnly()) { // We have keyboard focus, and it's not an accelerator - if (key < 0x80) { // Not a special key, so likely (we hope) to generate a character. Let it fall through to character handler first. @@ -2587,9 +2598,9 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask) // Debugging view for unified notifications: CTRL-SHIFT-5 // *FIXME: Having this special-cased right here (just so this can be invoked from the login screen) sucks. if ((MASK_SHIFT & mask) - && (!(MASK_ALT & mask)) - && (MASK_CONTROL & mask) - && ('5' == key)) + && (!(MASK_ALT & mask)) + && (MASK_CONTROL & mask) + && ('5' == key)) { LLFloaterNotificationConsole::showInstance(); return TRUE; @@ -2633,35 +2644,36 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask) // arrow keys move avatar while chatting hack if (gChatBar && gChatBar->inputEditorHasFocus()) { - if (gChatBar->getCurrentChat().empty() || gSavedSettings.getBOOL("ArrowKeysMoveAvatar")) + // If text field is empty, there's no point in trying to move + // cursor with arrow keys, so allow movement + if (gChatBar->getCurrentChat().empty() + || gSavedSettings.getBOOL("ArrowKeysMoveAvatar")) { - switch(key) + // Singu Note: We do this differently from LL to preserve the Ctrl- behavior in the chatbar + // let Control-Up and Control-Down through for chat line history, + //if (!(key == KEY_UP && mask == MASK_CONTROL) + // && !(key == KEY_DOWN && mask == MASK_CONTROL)) { - case KEY_LEFT: - case KEY_RIGHT: - case KEY_UP: - // let CTRL UP through for chat line history - if( MASK_CONTROL == mask ) + switch(key) { + case KEY_LEFT: + case KEY_RIGHT: + case KEY_UP: + case KEY_DOWN: + if (mask == MASK_CONTROL) + break; + case KEY_PAGE_UP: + case KEY_PAGE_DOWN: + case KEY_HOME: + // when chatbar is empty or ArrowKeysMoveAvatar set, + //pass arrow keys on to avatar... + return FALSE; + default: break; } - case KEY_DOWN: - // let CTRL DOWN through for chat line history - if( MASK_CONTROL == mask ) - { - break; - } - case KEY_PAGE_UP: - case KEY_PAGE_DOWN: - case KEY_HOME: - // when chatbar is empty or ArrowKeysMoveAvatar set, pass arrow keys on to avatar... - return FALSE; - default: - break; } } } - if (keyboard_focus->handleKey(key, mask, FALSE)) { return TRUE; @@ -2723,13 +2735,8 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask) } // give menus a chance to handle keys - if (gMenuBarView && gMenuBarView->handleAcceleratorKey(key, mask)) - { - return TRUE; - } - - // give menus a chance to handle keys - if (gLoginMenuBarView && gLoginMenuBarView->handleAcceleratorKey(key, mask)) + if ((gMenuBarView && gMenuBarView->handleAcceleratorKey(key, mask)) + ||(gLoginMenuBarView && gLoginMenuBarView->handleAcceleratorKey(key, mask))) { return TRUE; } @@ -2993,7 +3000,7 @@ void LLViewerWindow::updateUI() if( !handled ) { - lldebugst(LLERR_USER_INPUT) << "hover not handled by top view or root" << llendl; + lldebugst(LLERR_USER_INPUT) << "hover not handled by top view or root" << llendl; } } @@ -3027,7 +3034,7 @@ void LLViewerWindow::updateUI() } - // Show a new tool tip (or update one that is alrady shown) + // Show a new tool tip (or update one that is already shown) BOOL tool_tip_handled = FALSE; std::string tool_tip_msg; static const LLCachedControl tool_tip_delay("ToolTipDelay",.7f); @@ -3040,8 +3047,8 @@ void LLViewerWindow::updateUI() tooltip_delay = drag_and_drop_tool_tip_delay; } if( handled && - gMouseIdleTimer.getElapsedTimeF32() > tooltip_delay && - !mWindow->isCursorHidden() ) + gMouseIdleTimer.getElapsedTimeF32() > tooltip_delay && + !mWindow->isCursorHidden() ) { LLRect screen_sticky_rect; LLMouseHandler *mh; @@ -3066,7 +3073,7 @@ void LLViewerWindow::updateUI() if (shouldShowToolTipFor(mh)) { tool_tip_handled = mh->handleToolTip(local_x, local_y, tool_tip_msg, &screen_sticky_rect ); - + if( tool_tip_handled && !tool_tip_msg.empty() ) { mToolTipStickyRect = screen_sticky_rect; @@ -3083,8 +3090,8 @@ void LLViewerWindow::updateUI() { mToolTip->setVisible( tooltip_vis ); } - } - + } + static const LLCachedControl freeze_time("FreezeTime",0); if (tool && tool != gToolNull && tool != LLToolCompInspect::getInstance() && tool != LLToolDragAndDrop::getInstance() && !freeze_time) { @@ -3092,8 +3099,8 @@ void LLViewerWindow::updateUI() // With the null, inspect, or drag and drop tool, don't muck // with visibility. - if (gFloaterTools->isMinimized() || - (tool != LLToolPie::getInstance() // not default tool + if (gFloaterTools->isMinimized() + || (tool != LLToolPie::getInstance() // not default tool && tool != LLToolCompGun::getInstance() // not coming out of mouselook && !mSuppressToolbox // not override in third person && LLToolMgr::getInstance()->getCurrentToolset() != gFaceEditToolset // not special mode @@ -3247,8 +3254,6 @@ void LLViewerWindow::updateUI() LLSelectMgr::getInstance()->deselectUnused(); } - - // per frame picking - for tooltips and changing cursor over interactive objects static S32 previous_x = -1; static S32 previous_y = -1; @@ -3272,17 +3277,15 @@ void LLViewerWindow::updateUI() previous_x = x; previous_y = y; - + return; } - /* static */ void LLViewerWindow::hoverPickCallback(const LLPickInfo& pick_info) { gViewerWindow->mHoverPick = pick_info; } - void LLViewerWindow::updateMouseDelta() { @@ -3324,7 +3327,7 @@ void LLViewerWindow::updateMouseDelta() mCurrentMouseDelta.set(dx, dy); mouse_vel.setVec((F32) dx, (F32) dy); } - + mMouseVelocityStat.addValue(mouse_vel.magVec()); } @@ -3592,7 +3595,7 @@ void LLViewerWindow::pickAsync(S32 x, S32 y_from_bot, MASK mask, void (*callback { return; } - + // push back pick info object BOOL in_build_mode = gFloaterTools && gFloaterTools->getVisible(); if (in_build_mode || LLDrawPoolAlpha::sShowDebugAlpha) @@ -3769,7 +3772,6 @@ LLViewerObject* LLViewerWindow::cursorIntersect(S32 mouse_x, S32 mouse_y, F32 de found = this_object; } } - else // is a world object { if (this_object->lineSegmentIntersect(mouse_world_start, mouse_world_end, this_face, pick_transparent, @@ -3779,7 +3781,6 @@ LLViewerObject* LLViewerWindow::cursorIntersect(S32 mouse_x, S32 mouse_y, F32 de } } } - else // check ALL objects { found = gPipeline.lineSegmentIntersectInHUD(mouse_hud_start, mouse_hud_end, pick_transparent, @@ -4060,7 +4061,7 @@ void LLViewerWindow::saveImageNumbered(LLPointer image, int in pick_type = FFSAVE_ALL; // ??? // Get a base file location if needed. - if ( ! isSnapshotLocSet()) + if (!isSnapshotLocSet()) { std::string proposed_name( sSnapshotBaseName ); @@ -4211,7 +4212,7 @@ void LLViewerWindow::playSnapshotAnimAndSound() BOOL LLViewerWindow::thumbnailSnapshot(LLImageRaw *raw, S32 preview_width, S32 preview_height, BOOL show_ui, BOOL do_rebuild, ESnapshotType type) { return rawSnapshot(raw, preview_width, preview_height, (F32)gViewerWindow->getWindowWidthRaw() / gViewerWindow->getWindowHeightRaw(), show_ui, do_rebuild, type); - + // *TODO below code was broken in deferred pipeline /* if ((!raw) || preview_width < 10 || preview_height < 10) @@ -4243,14 +4244,14 @@ BOOL LLViewerWindow::thumbnailSnapshot(LLImageRaw *raw, S32 preview_width, S32 p S32 render_name = gSavedSettings.getS32("RenderName"); gSavedSettings.setS32("RenderName", 0); LLVOAvatar::updateFreezeCounter(1) ; //pause avatar updating for one frame - + S32 w = preview_width ; S32 h = preview_height ; LLVector2 display_scale = mDisplayScale ; mDisplayScale.setVec((F32)w / mWindowRectRaw.getWidth(), (F32)h / mWindowRectRaw.getHeight()) ; LLRect window_rect = mWindowRect; mWindowRectRaw.set(0, h, w, 0); - + gDisplaySwapBuffers = FALSE; gDepthDirty = TRUE; glClearColor(0.f, 0.f, 0.f, 0.f); @@ -4274,7 +4275,7 @@ BOOL LLViewerWindow::thumbnailSnapshot(LLImageRaw *raw, S32 preview_width, S32 p if(SNAPSHOT_TYPE_DEPTH == type) { glpixel_length = 4 ; - glformat = GL_DEPTH_COMPONENT ; + glformat = GL_DEPTH_COMPONENT ; gltype = GL_FLOAT ; } else @@ -4299,9 +4300,9 @@ BOOL LLViewerWindow::thumbnailSnapshot(LLImageRaw *raw, S32 preview_width, S32 p for(S32 x = 0 ; x < w ; x++) { S32 i = (w * y + x) << 2 ; - + F32 depth_float_i = *(F32*)(raw->getData() + i); - + F32 linear_depth_float = 1.f / (depth_conversion_factor_1 - (depth_float_i * depth_conversion_factor_2)); U8 depth_byte = F32_to_U8(linear_depth_float, camerap->getNear(), camerap->getFar()); *(raw->getData() + i + 0) = depth_byte; @@ -4309,13 +4310,13 @@ BOOL LLViewerWindow::thumbnailSnapshot(LLImageRaw *raw, S32 preview_width, S32 p *(raw->getData() + i + 2) = depth_byte; *(raw->getData() + i + 3) = 255; } - } + } } LLFontGL::setFontDisplay(TRUE) ; LLHUDText::setDisplayText(TRUE) ; mDisplayScale.setVec(display_scale) ; - mWindowRect = window_rect; + mWindowRect = window_rect; setup3DRender(); setupViewport(); gDisplaySwapBuffers = FALSE; @@ -4343,9 +4344,9 @@ BOOL LLViewerWindow::thumbnailSnapshot(LLImageRaw *raw, S32 preview_width, S32 p // objects on them. gPipeline.resetDrawOrders(); } - - gSavedSettings.setS32("RenderName", render_name); - + + gSavedSettings.setS32("RenderName", render_name); + return TRUE;*/ } @@ -4424,7 +4425,7 @@ bool LLViewerWindow::rawRawSnapshot(LLImageRaw *raw, LLPipeline::toggleRenderDebugFeature((void*)LLPipeline::RENDER_DEBUG_FEATURE_UI); } } - + S32 buffer_x_offset = 0; S32 buffer_y_offset = 0; F32 scale_factor = 1.0f; @@ -4464,7 +4465,6 @@ bool LLViewerWindow::rawRawSnapshot(LLImageRaw *raw, } } - // ratio is the ratio snapshot/image', where image' is a rectangle with aspect snapshot_aspect that precisely contains image. // Thus image_width' / image_height' == aspect ==> snapshot_width / image_width' == snapshot_height / image_height'. // Since image' precisely contains image, one of them is equal (ie, image_height' = image_height) and the other is larger @@ -4504,7 +4504,6 @@ bool LLViewerWindow::rawRawSnapshot(LLImageRaw *raw, // Done. break; } - // Center the buffer. buffer_x_offset = llfloor(((window_width - unscaled_image_buffer_x) * scale_factor) / 2.f); @@ -4669,7 +4668,7 @@ bool LLViewerWindow::rawRawSnapshot(LLImageRaw *raw, // objects on them. gPipeline.resetDrawOrders(); } - + if (reset_deferred) { mWindowRectRaw = window_rect; @@ -4769,7 +4768,7 @@ void LLViewerWindow::drawMouselookInstructions() gGL.color4f( 0.9f, 0.9f, 0.9f, alpha ); gl_rect_2d( instructions_rect ); } - + font->renderUTF8( instructions, 0, instructions_rect.mLeft + INSTRUCTIONS_PAD, @@ -4846,7 +4845,6 @@ void LLViewerWindow::setup3DViewport(S32 x_offset, S32 y_offset) } - void LLViewerWindow::setShowProgress(const BOOL show) { if (mProgressView) @@ -4855,15 +4853,12 @@ void LLViewerWindow::setShowProgress(const BOOL show) } } - - - void LLViewerWindow::moveProgressViewToFront() { - if( mProgressView && mRootView ) + if (mProgressView && mRootView) { - mRootView->removeChild( mProgressView ); - mRootView->addChild( mProgressView ); + mRootView->removeChild(mProgressView); + mRootView->addChild(mProgressView); } } @@ -5035,6 +5030,7 @@ void LLViewerWindow::initFonts(F32 zoom_factor) return; LLFontGL::destroyAllGL(); // Initialize with possibly different zoom factor + LLFontGL::initClass( gSavedSettings.getF32("FontScreenDPI"), mDisplayScale.mV[VX] * zoom_factor, mDisplayScale.mV[VY] * zoom_factor, @@ -5055,7 +5051,7 @@ void LLViewerWindow::toggleFullscreen(BOOL show_progress) void LLViewerWindow::getTargetWindow(BOOL& fullscreen, S32& width, S32& height) const { fullscreen = mWantFullscreen; - + if (mWindow && mWindow->getFullscreen() == mWantFullscreen) { @@ -5104,7 +5100,7 @@ BOOL LLViewerWindow::checkSettings() { getWindow()->setNativeAspectRatio(gSavedSettings.getF32("FullScreenAspectRatio")); } - + reshape(getWindowWidthRaw(), getWindowHeightRaw()); // force aspect ratio @@ -5115,7 +5111,7 @@ BOOL LLViewerWindow::checkSettings() mResDirty = false; } - + BOOL is_fullscreen = mWindow->getFullscreen(); if(mWantFullscreen) { @@ -5124,14 +5120,14 @@ BOOL LLViewerWindow::checkSettings() gSavedSettings.getS32("FullScreenHeight")); getWindow()->getSize(&screen_size); if(!is_fullscreen || - screen_size.mX != desired_screen_size.mX + screen_size.mX != desired_screen_size.mX || screen_size.mY != desired_screen_size.mY) { if (!LLStartUp::canGoFullscreen()) { return FALSE; } - + LLGLState::checkStates(); LLGLState::checkTextureChannels(); changeDisplaySettings(TRUE, @@ -5242,7 +5238,7 @@ BOOL LLViewerWindow::changeDisplaySettings(BOOL fullscreen, LLCoordScreen size, new_pos.mX = gSavedSettings.getS32("WindowX"); new_pos.mY = gSavedSettings.getS32("WindowY"); } - + mWindow->setFSAASamples(fsaa); result_first_try = mWindow->switchContext(fullscreen, size, disable_vsync, &new_pos); @@ -5282,6 +5278,7 @@ BOOL LLViewerWindow::changeDisplaySettings(BOOL fullscreen, LLCoordScreen size, } BOOL success = result_first_try || result_second_try; + if (success) { #if LL_WINDOWS @@ -5323,7 +5320,7 @@ F32 LLViewerWindow::getDisplayAspectRatio() const { if (gSavedSettings.getBOOL("FullScreenAutoDetectAspectRatio")) { - return mWindow->getNativeAspectRatio(); + return mWindow->getNativeAspectRatio(); } else { @@ -5362,7 +5359,7 @@ void LLViewerWindow::calcDisplayScale() display_scale.mV[0] = llround(display_scale.mV[0], 2.0f/(F32) mWindowRectRaw.getWidth()); display_scale.mV[1] = llround(display_scale.mV[1], 2.0f/(F32) mWindowRectRaw.getHeight()); } - + if (display_scale != mDisplayScale) { llinfos << "Setting display scale to " << display_scale << llendl; @@ -5376,7 +5373,8 @@ void LLViewerWindow::calcDisplayScale() S32 LLViewerWindow::getChatConsoleBottomPad() { S32 offset = 0; - if( gToolBar && gToolBar->getVisible() ) + + if(gToolBar && gToolBar->getVisible()) offset += TOOL_BAR_HEIGHT; return offset; @@ -5396,8 +5394,9 @@ LLRect LLViewerWindow::getChatConsoleRect() console_rect.mLeft += CONSOLE_PADDING_LEFT; - static const LLCachedControl chat_full_width("ChatFullWidth",true); - if (chat_full_width) + static const LLCachedControl CHAT_FULL_WIDTH("ChatFullWidth",true); + + if (CHAT_FULL_WIDTH) { console_rect.mRight -= CONSOLE_PADDING_RIGHT; } @@ -5449,7 +5448,7 @@ LLBottomPanel::LLBottomPanel(const LLRect &rect) : mFactoryMap["toolbar"] = LLCallbackMap(createToolBar, NULL); mFactoryMap["overlay"] = LLCallbackMap(createOverlayBar, NULL); LLUICtrlFactory::getInstance()->buildPanel(this, "panel_bars.xml", &getFactoryMap()); - + setOrigin(rect.mLeft, rect.mBottom); reshape(rect.getWidth(), rect.getHeight()); } @@ -5484,6 +5483,7 @@ void* LLBottomPanel::createToolBar(void* data) return gToolBar; } +//////////////////////////////////////////////////////////////////////////// // // LLPickInfo // @@ -5634,7 +5634,7 @@ void LLPickInfo::getSurfaceInfo() mObjectFace = -1; mUVCoords = LLVector2(-1, -1); mSTCoords = LLVector2(-1, -1); - mXYCoords = LLCoordScreen(-1, -1); + mXYCoords = LLCoordScreen(-1, -1); mIntersection = LLVector3(0,0,0); mNormal = LLVector3(0,0,0); mBinormal = LLVector3(0,0,0); diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 0ff0697d2..c955ef202 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -931,8 +931,6 @@ F32 LLVOAvatar::sLODFactor = 1.f; F32 LLVOAvatar::sPhysicsLODFactor = 1.f; BOOL LLVOAvatar::sUseImpostors = FALSE; BOOL LLVOAvatar::sJointDebug = FALSE; - - F32 LLVOAvatar::sUnbakedTime = 0.f; F32 LLVOAvatar::sUnbakedUpdateTime = 0.f; F32 LLVOAvatar::sGreyTime = 0.f; @@ -2471,7 +2469,7 @@ void LLVOAvatar::idleUpdateVoiceVisualizer(bool voice_enabled) { LLVector3 tagPos = mRoot->getWorldPosition(); tagPos[VZ] -= mPelvisToFoot; - tagPos[VZ] += ( mBodySize[VZ] + mAvatarOffset[VZ] + 0.125f ); + tagPos[VZ] += ( mBodySize[VZ] + 0.125f ); mVoiceVisualizer->setVoiceSourceWorldPosition( tagPos ); } }//if ( voiceEnabled ) @@ -2489,13 +2487,6 @@ void LLVOAvatar::idleUpdateMisc(bool detailed_update) LLJoint::sNumUpdates = 0; LLJoint::sNumTouches = 0; - /*// *NOTE: this is necessary for the floating name text above your head. - // NOTE NOTE: This doesn't seem to be needed any more? - if (mDrawable && mDrawable.notNull()) - { - gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_SHADOW, TRUE); - }*/ - BOOL visible = isVisible() || mNeedsAnimUpdate; // update attachments positions @@ -2852,14 +2843,17 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last) static const LLCachedControl NAME_SHOW_TIME("RenderNameShowTime",10); // seconds static const LLCachedControl FADE_DURATION("RenderNameFadeDuration",1); // seconds static const LLCachedControl use_chat_bubbles("UseChatBubbles",false); + static const LLCachedControl use_typing_bubbles("UseTypingBubbles"); static const LLCachedControl render_name_hide_self("RenderNameHideSelf",false); static const LLCachedControl allow_nameplate_override ("CCSAllowNameplateOverride", true); -// [RLVa:KB] - Checked: 2009-07-08 (RLVa-1.0.0e) | Added: RLVa-0.2.0b +// [RLVa:KB] - Checked: 2010-04-04 (RLVa-1.2.2a) | Added: RLVa-0.2.0b bool fRlvShowNames = gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES); // [/RLVa:KB] BOOL visible_avatar = isVisible() || mNeedsAnimUpdate; BOOL visible_chat = use_chat_bubbles && (mChats.size() || mTyping); + bool visible_typing = use_typing_bubbles && mTyping; BOOL render_name = visible_chat || + visible_typing || (visible_avatar && // [RLVa:KB] - Checked: 2010-04-04 (RLVa-1.2.2a) | Added: RLVa-1.0.0h ( (!fRlvShowNames) || (RlvSettings::getShowNameTags()) ) && @@ -2893,6 +2887,11 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last) mVisibleChat = visible_chat; new_name = TRUE; } + if (visible_typing != mVisibleTyping) + { + mVisibleTyping = visible_typing; + new_name = true; + } // [RLVa:KB] - Checked: 2010-04-04 (RLVa-1.2.2a) | Added: RLVa-0.2.0b if (fRlvShowNames) @@ -2917,7 +2916,7 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last) if (mAppAngle > 5.f) { const F32 START_FADE_TIME = NAME_SHOW_TIME - FADE_DURATION; - if (!visible_chat && sRenderName == RENDER_NAME_FADE && time_visible > START_FADE_TIME) + if (!visible_chat && !visible_typing && sRenderName == RENDER_NAME_FADE && time_visible > START_FADE_TIME) { alpha = 1.f - (time_visible - START_FADE_TIME) / FADE_DURATION; } @@ -2943,7 +2942,7 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last) } return; } - + if (!mNameText) { mNameText = static_cast( LLHUDObject::addHUDObject( @@ -3299,7 +3298,7 @@ void LLVOAvatar::idleUpdateNameTagText(BOOL new_name) new_name = TRUE; } - if (mVisibleChat) + if (mVisibleChat || mVisibleTyping) { mNameText->setFont(LLFontGL::getFontSansSerif()); mNameText->setTextAlignment(LLHUDNameTag::ALIGN_TEXT_LEFT); @@ -3309,6 +3308,8 @@ void LLVOAvatar::idleUpdateNameTagText(BOOL new_name) mNameText->clearString(); LLColor4 new_chat = gColors.getColor( "AvatarNameColor" ); + if (mVisibleChat) + { LLColor4 normal_chat = lerp(new_chat, LLColor4(0.8f, 0.8f, 0.8f, 1.f), 0.7f); LLColor4 old_chat = lerp(normal_chat, LLColor4(0.6f, 0.6f, 0.6f, 1.f), 0.7f); if (mTyping && mChats.size() >= MAX_BUBBLE_CHAT_UTTERANCES) @@ -3348,6 +3349,7 @@ void LLVOAvatar::idleUpdateNameTagText(BOOL new_name) mNameText->addLine(chat_iter->mText, old_chat, style); } } + } mNameText->setVisibleOffScreen(TRUE); if (mTyping) @@ -3379,7 +3381,7 @@ void LLVOAvatar::idleUpdateNameTagText(BOOL new_name) void LLVOAvatar::addNameTagLine(const std::string& line, const LLColor4& color, S32 style, const LLFontGL* font) { llassert(mNameText); - if (mVisibleChat) + if (mVisibleChat || mVisibleTyping) { mNameText->addLabel(line); } @@ -3777,7 +3779,7 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent) } root_pos = gAgent.getPosGlobalFromAgent(getRenderPosition()); - root_pos.mdV[VZ] += getVisualParamWeight(11001); + root_pos.mdV[VZ] += getVisualParamWeight(AVATAR_HOVER); resolveHeightGlobal(root_pos, ground_under_pelvis, normal); @@ -4958,31 +4960,6 @@ void LLVOAvatar::updateTextures() } } - /* - // JAMESDEBUG - if (isSelf()) - { - S32 null_count = 0; - S32 default_count = 0; - for (U32 i = 0; i < getNumTEs(); i++) - { - const LLTextureEntry* te = getTE(i); - if (te) - { - if (te->getID() == LLUUID::null) - { - null_count++; - } - else if (te->getID() == IMG_DEFAULT_AVATAR) - { - default_count++; - } - } - } - llinfos << "JAMESDEBUG my avatar TE null " << null_count << " default " << default_count << llendl; - } - */ - mMaxPixelArea = 0.f; mMinPixelArea = 99999999.f; mHasGrey = FALSE; // debug @@ -5015,7 +4992,7 @@ void LLVOAvatar::updateTextures() const EBakedTextureIndex baked_index = texture_dict->mBakedTextureIndex; if (texture_dict->mIsLocalTexture) { - addLocalTextureStats((ETextureIndex)texture_index, imagep, texel_area_ratio, render_avatar, layer_baked[baked_index]); + addLocalTextureStats((ETextureIndex)texture_index, imagep, texel_area_ratio, render_avatar, mBakedTextureDatas[baked_index].mIsUsed); } } } @@ -5048,7 +5025,7 @@ void LLVOAvatar::updateTextures() void LLVOAvatar::addLocalTextureStats( ETextureIndex idx, LLViewerFetchedTexture* imagep, - F32 texel_area_ratio, BOOL render_avatar, BOOL covered_by_baked, U32 index ) + F32 texel_area_ratio, BOOL render_avatar, BOOL covered_by_baked) { // No local texture stats for non-self avatars return; @@ -5259,10 +5236,7 @@ const LLUUID& LLVOAvatar::getStepSound() const //----------------------------------------------------------------------------- void LLVOAvatar::processAnimationStateChanges() { - if ((gNoRender)||(gAgent.isTPosed())) //isTPosed is meant to stop animation updates while force-TPosed. - { - return; - } + if (gNoRender) return; if ( isAnyAnimationSignaled(AGENT_WALK_ANIMS, NUM_AGENT_WALK_ANIMS) ) { @@ -6210,32 +6184,6 @@ const LLViewerJointAttachment *LLVOAvatar::attachObject(LLViewerObject *viewer_o { LLViewerJointAttachment* attachment = getTargetAttachmentPoint(viewer_object); - // testzone attachpt - if(!attachment) - { - llwarns << "Failed to find attachment." << llendl; - S32 attachmentID = ATTACHMENT_ID_FROM_STATE(viewer_object->getState()); - LLUUID item_id; - LLNameValue* item_id_nv = viewer_object->getNVPair("AttachItemID"); - if( item_id_nv ) - { - const char* s = item_id_nv->getString(); - if(s) - item_id.set(s); - } - if(!item_id.isNull()) - { - mUnsupportedAttachmentPoints[attachmentID] = std::pair(item_id,viewer_object->getID()); - if (viewer_object->isSelected()) - { - LLSelectMgr::getInstance()->updateSelectionCenter(); - LLSelectMgr::getInstance()->updatePointAt(); - } - } - else - llwarns << "No item ID" << llendl; - } - // if (!attachment || !attachment->addObject(viewer_object)) { return 0; @@ -6421,57 +6369,6 @@ BOOL LLVOAvatar::detachObject(LLViewerObject *viewer_object) mPendingAttachment.erase(iter); return TRUE; } - - - // testzone attachpt - LLUUID item_id; - LLNameValue* item_id_nv = viewer_object->getNVPair("AttachItemID"); - if( item_id_nv ) - { - const char* s = item_id_nv->getString(); - if(s) - item_id.set(s); - } - if(!item_id.isNull()) - { - std::map >::iterator iter = mUnsupportedAttachmentPoints.begin(); - std::map >::iterator end = mUnsupportedAttachmentPoints.end(); - for( ; iter != end; ++iter) - { - if((*iter).second.first == item_id) - { - mUnsupportedAttachmentPoints.erase((*iter).first); - if (isSelf()) - { - // the simulator should automatically handle - // permission revocation - - stopMotionFromSource(viewer_object->getID()); - LLFollowCamMgr::setCameraActive(viewer_object->getID(), FALSE); - - LLViewerObject::const_child_list_t& child_list = viewer_object->getChildren(); - for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin(); - iter != child_list.end(); iter++) - { - LLViewerObject* child_objectp = *iter; - // the simulator should automatically handle - // permissions revocation - - stopMotionFromSource(child_objectp->getID()); - LLFollowCamMgr::setCameraActive(child_objectp->getID(), FALSE); - } - // Then make sure the inventory is in sync with the avatar. - gInventory.addChangedMask(LLInventoryObserver::LABEL, item_id); - gInventory.notifyObservers(); - } - return TRUE; - } - } - llwarns << "Not found" << llendl; - } - else - llwarns << "No item ID" << llendl; - // return FALSE; } @@ -6715,19 +6612,6 @@ BOOL LLVOAvatar::isWearingAttachment( const LLUUID& inv_item_id ) return FALSE; } -// testzone attachpt -BOOL LLVOAvatar::isWearingUnsupportedAttachment( const LLUUID& inv_item_id ) -{ - std::map >::iterator end = mUnsupportedAttachmentPoints.end(); - for(std::map >::iterator iter = mUnsupportedAttachmentPoints.begin(); iter != end; ++iter) - { - if((*iter).second.first == inv_item_id) - { - return TRUE; - } - } - return FALSE; -} //----------------------------------------------------------------------------- // getWornAttachment() //----------------------------------------------------------------------------- @@ -6764,6 +6648,7 @@ const std::string LLVOAvatar::getAttachedPointName(const LLUUID& inv_item_id) return LLStringUtil::null; } +// virtual void LLVOAvatar::invalidateComposite( LLTexLayerSet* layerset, BOOL upload_result ) { } @@ -7615,10 +7500,6 @@ LLBBox LLVOAvatar::getHUDBBox() const return bbox; } -void LLVOAvatar::rebuildHUD() -{ -} - //----------------------------------------------------------------------------- // onFirstTEMessageReceived() //----------------------------------------------------------------------------- @@ -8145,6 +8026,7 @@ void LLVOAvatar::getAnimNames( LLDynamicArray* names ) names->put( "enter_away_from_keyboard_state" ); } +// static void LLVOAvatar::onBakedTextureMasksLoaded( BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata ) { if (!userdata) return; @@ -8238,7 +8120,7 @@ void LLVOAvatar::onInitialBakedTextureLoaded( BOOL success, LLViewerFetchedTextu { LLUUID *avatar_idp = (LLUUID *)userdata; LLVOAvatar *selfp = gObjectList.findAvatar(*avatar_idp); - + if (selfp) { LL_DEBUGS("Avatar") << selfp->avString() << "discard_level " << discard_level << " success " << success << " final " << final << LL_ENDL; @@ -8259,7 +8141,7 @@ void LLVOAvatar::onBakedTextureLoaded(BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata) { - // llinfos << "onBakedTextureLoaded: " << src_vi->getID() << llendl; + LL_DEBUGS("Avatar") << "onBakedTextureLoaded: " << src_vi->getID() << LL_ENDL; LLUUID id = src_vi->getID(); LLUUID *avatar_idp = (LLUUID *)userdata; @@ -8289,7 +8171,6 @@ void LLVOAvatar::onBakedTextureLoaded(BOOL success, // Called when baked texture is loaded and also when we start up with a baked texture void LLVOAvatar::useBakedTexture( const LLUUID& id ) { - for (U32 i = 0; i < mBakedTextureDatas.size(); i++) { LLViewerTexture* image_baked = getImage( mBakedTextureDatas[i].mTextureIndex, 0 ); diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index 9362f5f7c..0299cf070 100644 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -336,7 +336,6 @@ public: S32 mLastRezzedStatus; - void startPhase(const std::string& phase_name); void stopPhase(const std::string& phase_name, bool err_check = true); void clearPhases(); @@ -371,6 +370,7 @@ protected: /** State ** ** *******************************************************************************/ + /******************************************************************************** ** ** ** SKELETON @@ -578,7 +578,7 @@ protected: //-------------------------------------------------------------------- protected: virtual void setLocalTexture(LLAvatarAppearanceDefines::ETextureIndex type, LLViewerTexture* tex, BOOL baked_version_exits, U32 index = 0); - virtual void addLocalTextureStats(LLAvatarAppearanceDefines::ETextureIndex type, LLViewerFetchedTexture* imagep, F32 texel_area_ratio, BOOL rendered, BOOL covered_by_baked, U32 index = 0); + virtual void addLocalTextureStats(LLAvatarAppearanceDefines::ETextureIndex type, LLViewerFetchedTexture* imagep, F32 texel_area_ratio, BOOL rendered, BOOL covered_by_baked); // MULTI-WEARABLE: make self-only? virtual void setBakedReady(LLAvatarAppearanceDefines::ETextureIndex type, BOOL baked_version_exists, U32 index = 0); @@ -757,7 +757,6 @@ public: public: BOOL hasHUDAttachment() const; LLBBox getHUDBBox() const; - void rebuildHUD(); void resetHUDAttachments(); BOOL canAttachMoreObjects() const; BOOL canAttachMoreObjects(U32 n) const; @@ -769,17 +768,10 @@ protected: //-------------------------------------------------------------------- public: BOOL isWearingAttachment( const LLUUID& inv_item_id ); - // testzone attachpt - BOOL isWearingUnsupportedAttachment( const LLUUID& inv_item_id ); - // LLViewerObject* getWornAttachment( const LLUUID& inv_item_id ); const std::string getAttachedPointName(const LLUUID& inv_item_id); - // - std::map > mUnsupportedAttachmentPoints; - // - /** Wearables ** ** *******************************************************************************/ @@ -824,6 +816,7 @@ public: void stopTyping() { mTyping = FALSE; mIdleTimer.reset();} private: BOOL mVisibleChat; + bool mVisibleTyping; //-------------------------------------------------------------------- // Lip synch morphs diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp index b5344c16c..49e9eba37 100644 --- a/indra/newview/llvoavatarself.cpp +++ b/indra/newview/llvoavatarself.cpp @@ -77,6 +77,9 @@ LLPointer gAgentAvatarp = NULL; +BOOL object_attached(void *user_data); +BOOL object_selected_and_point_valid(void *user_data); + BOOL isAgentAvatarValid() { return (gAgentAvatarp.notNull() && gAgentAvatarp->isValid() && @@ -2618,38 +2621,45 @@ BOOL LLVOAvatarSelf::canGrabBakedTexture(EBakedTextureIndex baked_index) const } void LLVOAvatarSelf::addLocalTextureStats( ETextureIndex type, LLViewerFetchedTexture* imagep, - F32 texel_area_ratio, BOOL render_avatar, BOOL covered_by_baked, U32 index ) + F32 texel_area_ratio, BOOL render_avatar, BOOL covered_by_baked) { if (!isIndexLocalTexture(type)) return; - if (getLocalTextureID(type, index) != IMG_DEFAULT_AVATAR) + // Sunshine - ignoring covered_by_baked will force local textures + // to always load. Fix for SH-4001 and many related issues. Do + // not restore this without some more targetted fix for the local + // textures failing to load issue. + //if (!covered_by_baked) { - imagep->setNoDelete(); - if (imagep->getDiscardLevel() != 0) + if (imagep->getID() != IMG_DEFAULT_AVATAR) { - F32 desired_pixels; - desired_pixels = llmin(mPixelArea, (F32)getTexImageArea()); - - // DRANO what priority should wearable-based textures have? - if (isUsingLocalAppearance()) + imagep->setNoDelete(); + if (imagep->getDiscardLevel() != 0) { - imagep->setBoostLevel(getAvatarBoostLevel()); - imagep->setAdditionalDecodePriority(SELF_ADDITIONAL_PRI) ; - } - imagep->resetTextureStats(); - imagep->setMaxVirtualSizeResetInterval(MAX_TEXTURE_VIRTURE_SIZE_RESET_INTERVAL); - imagep->addTextureStats( desired_pixels / texel_area_ratio ); - imagep->forceUpdateBindStats() ; - if (imagep->getDiscardLevel() < 0) - { - mHasGrey = TRUE; // for statistics gathering + F32 desired_pixels; + desired_pixels = llmin(mPixelArea, (F32)getTexImageArea()); + + // DRANO what priority should wearable-based textures have? + if (isUsingLocalAppearance()) + { + imagep->setBoostLevel(getAvatarBoostLevel()); + imagep->setAdditionalDecodePriority(SELF_ADDITIONAL_PRI) ; + } + imagep->resetTextureStats(); + imagep->setMaxVirtualSizeResetInterval(MAX_TEXTURE_VIRTURE_SIZE_RESET_INTERVAL); + imagep->addTextureStats( desired_pixels / texel_area_ratio ); + imagep->forceUpdateBindStats() ; + if (imagep->getDiscardLevel() < 0) + { + mHasGrey = TRUE; // for statistics gathering + } } } - } - else - { - // texture asset is missing - mHasGrey = TRUE; // for statistics gathering + else + { + // texture asset is missing + mHasGrey = TRUE; // for statistics gathering + } } } @@ -3014,9 +3024,9 @@ void LLVOAvatarSelf::onCustomizeStart(bool disable_camera_switch) gAgentAvatarp->idleUpdateAppearanceAnimation(); #endif - gAgentAvatarp->updateTextures(); // call updateTextureStats gAgentAvatarp->invalidateAll(); // mark all bakes as dirty, request updates gAgentAvatarp->updateMeshTextures(); // make sure correct textures are applied to the avatar mesh. + gAgentAvatarp->updateTextures(); // call updateTextureStats } } diff --git a/indra/newview/llvoavatarself.h b/indra/newview/llvoavatarself.h index 62108b416..99e45bcff 100644 --- a/indra/newview/llvoavatarself.h +++ b/indra/newview/llvoavatarself.h @@ -217,7 +217,7 @@ protected: /*virtual*/ void setBakedReady(LLAvatarAppearanceDefines::ETextureIndex type, BOOL baked_version_exists, U32 index); void localTextureLoaded(BOOL succcess, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata); void getLocalTextureByteCount(S32* gl_byte_count) const; - /*virtual*/ void addLocalTextureStats(LLAvatarAppearanceDefines::ETextureIndex i, LLViewerFetchedTexture* imagep, F32 texel_area_ratio, BOOL rendered, BOOL covered_by_baked, U32 index); + /*virtual*/ void addLocalTextureStats(LLAvatarAppearanceDefines::ETextureIndex i, LLViewerFetchedTexture* imagep, F32 texel_area_ratio, BOOL rendered, BOOL covered_by_baked); LLLocalTextureObject* getLocalTextureObject(LLAvatarAppearanceDefines::ETextureIndex i, U32 index) const; private: diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index cd242f0a5..bcdd9b9b1 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -2403,6 +2403,17 @@ BOOL LLPipeline::updateDrawableGeom(LLDrawable* drawablep, BOOL priority) BOOL update_complete = drawablep->updateGeometry(priority); if (update_complete && assertInitialized()) { + //Workaround for 'missing prims' until it's fixed upstream by LL. + //Sometimes clearing CLEAR_INVISIBLE and FORCE_INVISIBLE in LLPipeline::stateSort was too late. Do it here instead, before + //the rebuild state is picked up on and LLVolumeGeometryManager::rebuildGeom is called. + //If the FORCE_INVISIBLE isn't cleared before the rebuildGeom call, the geometry will NOT BE REBUILT! + if(drawablep->isState(LLDrawable::CLEAR_INVISIBLE)) + { + // clear invisible flag here to avoid single frame glitch + drawablep->clearState(LLDrawable::FORCE_INVISIBLE|LLDrawable::CLEAR_INVISIBLE); + return false; //Defer to next mBuildQ1 iteration + } + drawablep->setState(LLDrawable::BUILT); //Workaround for 'missing prims' until it's fixed upstream by LL. //Sometimes clearing CLEAR_INVISIBLE and FORCE_INVISIBLE in LLPipeline::stateSort was too late. Do it here instead, before @@ -4729,11 +4740,6 @@ void LLPipeline::rebuildPools() } max_count--; } - - if (isAgentAvatarValid()) - { - gAgentAvatarp->rebuildHUD(); - } } void LLPipeline::addToQuickLookup( LLDrawPool* new_poolp ) diff --git a/indra/newview/sgmemstat.cpp b/indra/newview/sgmemstat.cpp index d8c4a3f5a..ca4ce0593 100644 --- a/indra/newview/sgmemstat.cpp +++ b/indra/newview/sgmemstat.cpp @@ -18,7 +18,7 @@ #include "llviewerprecompiledheaders.h" #include "sgmemstat.h" -#if (!(LL_LINUX || LL_USE_TCMALLOC)) +#if (!LL_LINUX && !LL_USE_TCMALLOC) bool SGMemStat::haveStat() { return false; } diff --git a/indra/newview/skins/apollo/keywords.ini b/indra/newview/skins/apollo/keywords.ini index 5a85f42a1..d6b7595f4 100644 --- a/indra/newview/skins/apollo/keywords.ini +++ b/indra/newview/skins/apollo/keywords.ini @@ -52,7 +52,7 @@ changed changed( integer change ):Triggered various event change the task:(tes remote_data remote_data(integer event_type, key channel, key message_id, string sender,integer idata, string sdata):Triggered by various XML-RPC calls (event_type will be one of REMOTE_DATA_CHANNEL, REMOTE_DATA_REQUEST, REMOTE_DATA_REPLY) http_response http_response(key request_id, integer status, list metadata, string body):Triggered when task receives a response to one of its llHTTPRequests http_request http_request(key id, string method, string body):Triggered when task receives an http request against a public URL -transaction_result transaction_result(key id, integer success, string data):Triggered when task receives asynchronous data. +transaction_result transaction_result(key id, integer success, string data): Triggered when currency is given to task path_update path_update(integer type, list reserved):Triggered when the state of a pathfinder character changes. Note; "list reserved" is not currently used # integer constants @@ -99,6 +99,7 @@ PERMISSION_CHANGE_LINKS Passed to llRequestPermissions library function to req PERMISSION_TRACK_CAMERA Passed to llRequestPermissions library function to request permission to track agent's camera PERMISSION_CONTROL_CAMERA Passed to llRequestPermissions library function to request permission to change agent's camera PERMISSION_TELEPORT Passed to llRequestPermissions library function to request permission to teleport agent +PERMISSION_OVERRIDE_ANIMATIONS Passed to llRequestPermissions library function to request permission to override agent's animations DEBUG_CHANNEL Chat channel reserved for debug and error messages from scripts PUBLIC_CHANNEL Chat channel that broadcasts to all nearby users diff --git a/indra/newview/skins/default/textures/inv_reset.tga b/indra/newview/skins/default/textures/inv_reset.tga new file mode 100644 index 000000000..8c911e709 Binary files /dev/null and b/indra/newview/skins/default/textures/inv_reset.tga differ diff --git a/indra/newview/skins/default/xui/en-us/floater_animation_anim_preview.xml b/indra/newview/skins/default/xui/en-us/floater_animation_anim_preview.xml new file mode 100644 index 000000000..785a80334 --- /dev/null +++ b/indra/newview/skins/default/xui/en-us/floater_animation_anim_preview.xml @@ -0,0 +1,77 @@ + + + + Name: + + + + Description: + + +