Conflicts:
	indra/newview/llnetmap.cpp
This commit is contained in:
Shyotl
2014-08-05 18:17:13 -05:00
446 changed files with 25784 additions and 9117 deletions

6
.gitignore vendored
View File

@@ -29,3 +29,9 @@ qtcreator-build/
/indra/newview/res/viewerRes.rc
/indra/newview/res/viewerRes_bc.rc
/indra/newview/English.lproj/InfoPlist.strings
/indra/newview/linux_tools/handle_secondlifeprotocol.sh
/indra/newview/linux_tools/install.sh
/indra/newview/linux_tools/refresh_desktop_app_entry.sh
/indra/newview/linux_tools/wrapper.sh

View File

@@ -54,6 +54,11 @@ if (WINDOWS)
# Remove default /Zm1000 flag that cmake inserts
string (REPLACE "/Zm1000" " " CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
if (MSVC11)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /Zm140")
endif (MSVC11)
# Don't build DLLs.
set(BUILD_SHARED_LIBS OFF)
@@ -246,30 +251,28 @@ endif (LINUX)
if (DARWIN)
add_definitions(-DLL_DARWIN=1 -D_XOPEN_SOURCE)
set(CMAKE_CXX_LINK_FLAGS "-Wl,-headerpad_max_install_names,-search_paths_first")
add_definitions(-DLL_DARWIN=1)
set(CMAKE_CXX_LINK_FLAGS "-Wl,-no_compact_unwind -Wl,-headerpad_max_install_names,-search_paths_first")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_CXX_LINK_FLAGS}")
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mlong-branch")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mlong-branch")
# NOTE: it's critical that the optimization flag is put in front.
# NOTE: it's critical to have both CXX_FLAGS and C_FLAGS covered.
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O3 -msse3 -mtune=generic -mfpmath=sse ${GCC_EXTRA_OPTIMIZATIONS}")
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -O3 -msse3 -mtune=generic -mfpmath=sse ${GCC_EXTRA_OPTIMIZATIONS}")
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -O3 -msse3 -mtune=generic -mfpmath=sse ${GCC_EXTRA_OPTIMIZATIONS}")
set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} -O3 -msse3 -mtune=generic -mfpmath=sse ${GCC_EXTRA_OPTIMIZATIONS}")
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
# NOTE: it's critical that the optimization flag is put in front.
# NOTE: it's critical to have both CXX_FLAGS and C_FLAGS covered.
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O3 -msse3")
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -O3 -msse3")
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -O3 -msse3")
set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} -O3 -msse3")
endif()
set(DARWIN_extra_cstar_flags "-g")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${DARWIN_extra_cstar_flags} -ftemplate-depth=256")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${DARWIN_extra_cstar_flags}")
# NOTE: it's critical that the optimization flag is put in front.
# NOTE: it's critical to have both CXX_FLAGS and C_FLAGS covered.
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O0 ${CMAKE_CXX_FLAGS_RELWITHDEBINFO}")
set(CMAKE_C_FLAGS_RELWITHDEBINFO "-O0 ${CMAKE_C_FLAGS_RELWITHDEBINFO}")
set(CMAKE_XCODE_ATTRIBUTE_CLANG_X86_VECTOR_INSTRUCTIONS SSE3)
set(CMAKE_XCODE_ATTRIBUTE_GCC_OPTIMIZATION_LEVEL -O3)
set(CMAKE_CXX_FLAGS_RELEASE "-O3 -msse3 ${CMAKE_CXX_FLAGS_RELEASE}")
set(CMAKE_C_FLAGS_RELEASE "-O3 -msse3 ${CMAKE_C_FLAGS_RELEASE}")
if (XCODE_VERSION GREATER 4.2)
set(ENABLE_SIGNING TRUE)
set(SIGNING_IDENTITY "Developer ID Application: Linden Research, Inc.")
endif (XCODE_VERSION GREATER 4.2)
endif (DARWIN)
if (LINUX OR DARWIN)
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
add_definitions(-DLL_GNUC=1)
@@ -277,13 +280,11 @@ if (LINUX OR DARWIN)
set(UNIX_CXX_WARNINGS "${UNIX_WARNINGS} -Wno-reorder -Wno-non-virtual-dtor -Woverloaded-virtual")
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
add_definitions(-DLL_CLANG=1)
set(UNIX_WARNINGS "-Wall -Wno-sign-compare -Wno-trigraphs -Wno-tautological-compare -Wno-char-subscripts -Wno-gnu -Wno-logical-op-parentheses -Wno-non-virtual-dtor")
set(UNIX_WARNINGS "${UNIX_WARNINGS} -Woverloaded-virtual -Wno-parentheses-equality -Wno-reorder -Wno-unused-function -Wno-unused-value -Wno-unused-variable")
set(UNIX_WARNINGS "-Wall -Wno-sign-compare -Wno-trigraphs -Wno-tautological-compare -Wno-char-subscripts -Wno-gnu -Wno-logical-op-parentheses -Wno-logical-not-parentheses -Wno-non-virtual-dtor -Wno-deprecated")
set(UNIX_WARNINGS "${UNIX_WARNINGS} -Woverloaded-virtual -Wno-parentheses-equality -Wno-reorder -Wno-unused-function -Wno-unused-value -Wno-unused-variable -Wno-unused-private-field -Wno-parentheses")
set(UNIX_CXX_WARNINGS "${UNIX_WARNINGS}")
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel")
add_definitions(-DLL_ICC=1)
set(UNIX_WARNINGS "-wd327 -wd597 -wd858")
set(UNIX_CXX_WARNINGS "${UNIX_WARNINGS}")
endif ()
if (NOT DISABLE_FATAL_WARNINGS)

View File

@@ -52,6 +52,29 @@ if (DARWIN)
)
endif (DARWIN)
if (LINUX)
configure_file(
${CMAKE_SOURCE_DIR}/newview/linux_tools/wrapper.sh.in
${CMAKE_SOURCE_DIR}/newview/linux_tools/wrapper.sh
@ONLY
)
configure_file(
${CMAKE_SOURCE_DIR}/newview/linux_tools/handle_secondlifeprotocol.sh.in
${CMAKE_SOURCE_DIR}/newview/linux_tools/handle_secondlifeprotocol.sh
@ONLY
)
configure_file(
${CMAKE_SOURCE_DIR}/newview/linux_tools/install.sh.in
${CMAKE_SOURCE_DIR}/newview/linux_tools/install.sh
@ONLY
)
configure_file(
${CMAKE_SOURCE_DIR}/newview/linux_tools/refresh_desktop_app_entry.sh.in
${CMAKE_SOURCE_DIR}/newview/linux_tools/refresh_desktop_app_entry.sh
@ONLY
)
endif (LINUX)
# Compose the version.
set(viewer_VERSION "${vMAJOR}.${vMINOR}.${vPATCH}.${vBUILD}")
if (viewer_VERSION MATCHES "^[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+$")

View File

@@ -97,24 +97,54 @@ endif (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
set(DARWIN 1)
if(${CMAKE_GENERATOR} MATCHES "Xcode")
#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)
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")
execute_process(
COMMAND sh -c "xcodebuild -version | grep Xcode | cut -d ' ' -f2 | cut -d'.' -f1-2"
OUTPUT_VARIABLE XCODE_VERSION )
string(REGEX REPLACE "(\r?\n)+$" "" XCODE_VERSION "${XCODE_VERSION}")
# # To support a different SDK update these Xcode settings:
# if (XCODE_VERSION GREATER 4.9) # (Which would be 5.0+)
# set(CMAKE_OSX_DEPLOYMENT_TARGET 10.8)
# set(CMAKE_OSX_SYSROOT macosx10.9)
# else (XCODE_VERION GREATER 4.9)
# if (XCODE_VERSION GREATER 4.5)
# set(CMAKE_OSX_DEPLOYMENT_TARGET 10.7)
# set(CMAKE_OSX_SYSROOT macosx10.8)
# else (XCODE_VERSION GREATER 4.5)
# if (XCODE_VERSION GREATER 4.2)
# set(CMAKE_OSX_DEPLOYMENT_TARGET 10.6)
# set(CMAKE_OSX_SYSROOT macosx10.7)
# else (XCODE_VERSION GREATER 4.2)
# set(CMAKE_OSX_DEPLOYMENT_TARGET 10.6)
# set(CMAKE_OSX_SYSROOT macosx10.7)
# endif (XCODE_VERSION GREATER 4.2)
# endif (XCODE_VERSION GREATER 4.5)
# endif (XCODE_VERSION GREATER 4.9)
set(CMAKE_XCODE_ATTRIBUTE_GCC_VERSION "com.apple.compilers.llvmgcc42")
# Hardcode SDK we build against until we can test and allow newer ones
# as autodetected in the code above
set(CMAKE_OSX_DEPLOYMENT_TARGET 10.6)
set(CMAKE_OSX_SYSROOT macosx10.6)
# Support for Unix Makefiles generator
if (CMAKE_GENERATOR STREQUAL "Unix Makefiles")
execute_process(COMMAND xcodebuild -version -sdk "${CMAKE_OSX_SYSROOT}" Path | head -n 1 OUTPUT_VARIABLE CMAKE_OSX_SYSROOT)
string(REGEX REPLACE "(\r?\n)+$" "" CMAKE_OSX_SYSROOT "${CMAKE_OSX_SYSROOT}")
endif (CMAKE_GENERATOR STREQUAL "Unix Makefiles")
# LLVM-GCC has been removed in Xcode5
if (XCODE_VERSION GREATER 4.9)
set(CMAKE_XCODE_ATTRIBUTE_GCC_VERSION "com.apple.compilers.llvm.clang.1_0")
else (XCODE_VERSION GREATER 4.9)
set(CMAKE_XCODE_ATTRIBUTE_GCC_VERSION "com.apple.compilers.llvmgcc42")
endif (XCODE_VERSION GREATER 4.9)
set(CMAKE_XCODE_ATTRIBUTE_DEBUG_INFORMATION_FORMAT dwarf-with-dsym)
message(STATUS "Xcode version: ${XCODE_VERSION}")
message(STATUS "OSX sysroot: ${CMAKE_OSX_SYSROOT}")
message(STATUS "OSX deployment target: ${CMAKE_OSX_DEPLOYMENT_TARGET}")
# Build only for i386 by default, system default on MacOSX 10.6 is x86_64
set(CMAKE_OSX_ARCHITECTURES i386)
set(ARCH i386)

View File

@@ -392,6 +392,40 @@ void InstanceTracker<T>::dump(void)
} // namespace debug
template<class T>
class AIDebugInstanceCounter
{
public:
static int sInstanceCount;
protected:
static void print_count(char const* name, int count, bool destruction);
AIDebugInstanceCounter()
{
print_count(typeid(T).name(), ++sInstanceCount, false);
}
AIDebugInstanceCounter(AIDebugInstanceCounter const&)
{
print_count(typeid(T).name(), ++sInstanceCount, false);
}
~AIDebugInstanceCounter()
{
print_count(typeid(T).name(), --sInstanceCount, true);
}
};
//static
template<class T>
int AIDebugInstanceCounter<T>::sInstanceCount;
//static
template<class T>
void AIDebugInstanceCounter<T>::print_count(char const* name, int count, bool destruction)
{
Dout(dc::notice, (destruction ? "Destructed " : "Constructing ") << name << ", now " << count << " instance" << ((count == 1) ? "." : "s."));
}
//! Debugging macro.
//
// Print "Entering " << \a data to channel \a cntrl and increment

View File

@@ -694,6 +694,8 @@ class CygwinSetup(WindowsSetup):
project_name=self.project_name,
word_size=self.word_size,
)
if self.word_size == 64:
args["generator"] += r' Win64'
#if simple:
# return 'cmake %(opts)s "%(dir)s"' % args
return ('cmake -G "%(generator)s" '

View File

@@ -7,7 +7,7 @@ include(00-Common)
include_directories(${LIBS_OPEN_DIR}/libhacd)
set (libndhacd_SOURCE_FILES
LLConvexDecomposition.cpp
llconvexdecomposition.cpp
nd_hacdConvexDecomposition.cpp
nd_hacdStructs.cpp
nd_hacdUtils.cpp
@@ -16,12 +16,12 @@ set (libndhacd_SOURCE_FILES
)
set (libndhacd_HEADER_FILES
LLConvexDecomposition.h
llconvexdecomposition.h
ndConvexDecomposition.h
nd_hacdConvexDecomposition.h
nd_hacdStructs.h
nd_StructTracer.h
LLConvexDecompositionStubImpl.h
llconvexdecompositionstubimpl.h
nd_EnterExitTracer.h
nd_hacdDefines.h
nd_hacdUtils.h

View File

@@ -1,5 +1,5 @@
/**
* @file LLConvexDecomposition.cpp
* @file llconvexdecomposition.cpp
* @author falcon@lindenlab.com
* @brief A stub implementation of LLConvexDecomposition interface
*
@@ -35,7 +35,7 @@
#include "nd_hacdConvexDecomposition.h"
#include "LLConvexDecomposition.h"
#include "llconvexdecomposition.h"
/*static */bool LLConvexDecomposition::s_isInitialized = false;

View File

@@ -1,5 +1,5 @@
/**
* @file LLConvexDecomposition.cpp
* @file llconvexdecomposition.cpp
* @brief LLConvexDecomposition interface definition
*
* $LicenseInfo:firstyear=2011&license=viewerlgpl$

View File

@@ -1,5 +1,5 @@
/**
* @file LLConvexDecompositionStubImpl.cpp
* @file llconvexdecompositionstubimpl.cpp
* @author falcon@lindenlab.com
* @brief A stub implementation of LLConvexDecomposition
*
@@ -28,7 +28,7 @@
#include <string.h>
#include <memory>
#include "LLConvexDecompositionStubImpl.h"
#include "llconvexdecompositionstubimpl.h"
LLConvexDecomposition* LLConvexDecompositionImpl::getInstance()
{

View File

@@ -1,5 +1,5 @@
/**
* @file LLConvexDecompositionStubImpl.h
* @file llconvexdecompositionstubimpl.h
* @author falcon@lindenlab.com
* @brief A stub implementation of LLConvexDecomposition
*
@@ -29,7 +29,7 @@
#ifndef LL_CONVEX_DECOMP_UTIL_H
#define LL_CONVEX_DECOMP_UTIL_H
#include "LLConvexDecomposition.h"
#include "llconvexdecomposition.h"
class LLConvexDecompositionImpl : public LLConvexDecomposition
{

View File

@@ -21,7 +21,7 @@
#include "ndConvexDecomposition.h"
#include "LLConvexDecomposition.h"
#include "llconvexdecomposition.h"
#include "nd_hacdStructs.h"
namespace ndStructTracer

View File

@@ -19,7 +19,7 @@
#ifndef ND_HACD_CONVEXDECOMP_H
#define ND_HACD_CONVEXDECOMP_H
#include "LLConvexDecomposition.h"
#include "llconvexdecomposition.h"
#include <map>
#include <vector>

View File

@@ -17,7 +17,6 @@
*/
#include "nd_hacdStructs.h"
#include "LLConvexDecomposition.h"
void DecompHull::clear()
{

View File

@@ -21,7 +21,7 @@
#include "nd_hacdDefines.h"
#include "hacdHACD.h"
#include "LLConvexDecomposition.h"
#include "llconvexdecomposition.h"
#include <vector>
struct LLCDHull;

View File

@@ -20,7 +20,6 @@
#define ND_HACD_UTILS_H
#include "nd_hacdStructs.h"
#include "LLConvexDecomposition.h"
tHACD* init( int nConcavity, int nClusters, int nMaxVerticesPerHull, double dMaxConnectDist, HACDDecoder *aData );
DecompData decompose( tHACD *aHACD );

View File

@@ -29,7 +29,6 @@ set(llcharacter_SOURCE_FILES
lljointsolverrp3.cpp
llkeyframefallmotion.cpp
llkeyframemotion.cpp
llkeyframemotionparam.cpp
llkeyframestandmotion.cpp
llkeyframewalkmotion.cpp
llmotion.cpp
@@ -57,7 +56,6 @@ set(llcharacter_HEADER_FILES
lljointstate.h
llkeyframefallmotion.h
llkeyframemotion.h
llkeyframemotionparam.h
llkeyframestandmotion.h
llkeyframewalkmotion.h
llmotion.h

View File

@@ -126,7 +126,6 @@ LLMotion* LLCharacter::findMotion( const LLUUID &id )
//-----------------------------------------------------------------------------
// createMotion()
// NOTE: Always assign the result to a LLPointer!
//-----------------------------------------------------------------------------
LLMotion* LLCharacter::createMotion( const LLUUID &id )
{
@@ -185,11 +184,26 @@ void LLCharacter::updateMotions(e_update_t update_type)
{
if (update_type == HIDDEN_UPDATE)
{
//<singu>
// Keep updating avatars that have at least one motion that is synchronized with a still running motion.
// This call tells the other controllers that we are in principle hidden.
// It returns false if we need to keep updating anyway.
if (!mMotionController.hidden(true))
{
mMotionController.updateMotions(LLCharacter::NORMAL_UPDATE);
return;
}
//</singu>
LLFastTimer t(FTM_UPDATE_HIDDEN_ANIMATION);
mMotionController.updateMotionsMinimal();
}
else
{
//<singu>
// This call tells the other controllers that we are visible and that they need
// to keep updating if they are synchronized with us, even if they are hidden.
mMotionController.hidden(false);
//</singu>
LLFastTimer t(FTM_UPDATE_ANIMATION);
// unpause if the number of outstanding pause requests has dropped to the initial one
if (mMotionController.isPaused() && mPauseRequest->getNumRefs() == 1)
@@ -519,3 +533,17 @@ LLAnimPauseRequest LLCharacter::requestPause()
return mPauseRequest;
}
void LLCharacter::requestPause(std::vector<LLAnimPauseRequest>& avatar_pause_handles)
{
mMotionController.pauseAllMotions();
avatar_pause_handles.push_back(mPauseRequest);
}
void LLCharacter::pauseAllSyncedCharacters(std::vector<LLAnimPauseRequest>& avatar_pause_handles)
{
// Pause this avatar.
requestPause(avatar_pause_handles);
// Also pause all avatars with synchronized motions.
mMotionController.pauseAllSyncedCharacters(avatar_pause_handles);
}

View File

@@ -146,6 +146,7 @@ public:
// is this motion active?
BOOL isMotionActive( const LLUUID& id );
bool isMotionActive(U32 bit) const { return mMotionController.isactive(bit); }
// Event handler for motion deactivation.
// Called when a motion has completely stopped and has been deactivated.
@@ -158,6 +159,8 @@ public:
void updateMotions(e_update_t update_type);
LLAnimPauseRequest requestPause();
void requestPause(std::vector<LLAnimPauseRequest>& avatar_pause_handles);
void pauseAllSyncedCharacters(std::vector<LLAnimPauseRequest>& avatar_pause_handles);
BOOL areAnimationsPaused() const { return mMotionController.isPaused(); }
void setAnimTimeFactor(F32 factor) { mMotionController.setTimeFactor(factor); }
void setTimeStep(F32 time_step) { mMotionController.setTimeStep(time_step); }

View File

@@ -49,7 +49,7 @@ S32 LLEditingMotion::sHandPosePriority = 3;
// LLEditingMotion()
// Class Constructor
//-----------------------------------------------------------------------------
LLEditingMotion::LLEditingMotion( const LLUUID &id) : LLMotion(id)
LLEditingMotion::LLEditingMotion(LLUUID const& id, LLMotionController* controller) : AIMaskedMotion(id, controller, ANIM_AGENT_EDITING)
{
mCharacter = NULL;
@@ -155,7 +155,7 @@ BOOL LLEditingMotion::onActivate()
mShoulderJoint.setRotation( mShoulderState->getJoint()->getRotation() );
mElbowJoint.setRotation( mElbowState->getJoint()->getRotation() );
return TRUE;
return AIMaskedMotion::onActivate();
}
//-----------------------------------------------------------------------------
@@ -256,12 +256,4 @@ BOOL LLEditingMotion::onUpdate(F32 time, U8* joint_mask)
return result;
}
//-----------------------------------------------------------------------------
// LLEditingMotion::onDeactivate()
//-----------------------------------------------------------------------------
void LLEditingMotion::onDeactivate()
{
}
// End

View File

@@ -49,11 +49,11 @@
// class LLEditingMotion
//-----------------------------------------------------------------------------
class LLEditingMotion :
public LLMotion
public AIMaskedMotion
{
public:
// Constructor
LLEditingMotion(const LLUUID &id);
LLEditingMotion(LLUUID const& id, LLMotionController* controller);
// Destructor
virtual ~LLEditingMotion();
@@ -65,7 +65,7 @@ public:
// static constructor
// all subclasses must implement such a function and register it
static LLMotion *create(const LLUUID &id) { return new LLEditingMotion(id); }
static LLMotion* create(LLUUID const& id, LLMotionController* controller) { return new LLEditingMotion(id, controller); }
public:
//-------------------------------------------------------------------------
@@ -107,9 +107,6 @@ public:
// must return FALSE when the motion is completed.
virtual BOOL onUpdate(F32 time, U8* joint_mask);
// called when a motion is deactivated
virtual void onDeactivate();
public:
//-------------------------------------------------------------------------
// joint states to be animated

View File

@@ -61,7 +61,7 @@ const F32 HAND_MORPH_BLEND_TIME = 0.2f;
// LLHandMotion()
// Class Constructor
//-----------------------------------------------------------------------------
LLHandMotion::LLHandMotion(const LLUUID &id) : LLMotion(id)
LLHandMotion::LLHandMotion(LLUUID const& id, LLMotionController* controller) : AIMaskedMotion(id, controller, ANIM_AGENT_HAND_MOTION)
{
mCharacter = NULL;
mLastTime = 0.f;
@@ -112,7 +112,7 @@ BOOL LLHandMotion::onActivate()
mCharacter->setVisualParamWeight(gHandPoseNames[mCurrentPose], 1.f);
mCharacter->updateVisualParams();
}
return TRUE;
return AIMaskedMotion::onActivate();
}
@@ -235,14 +235,6 @@ BOOL LLHandMotion::onUpdate(F32 time, U8* joint_mask)
return TRUE;
}
//-----------------------------------------------------------------------------
// LLHandMotion::onDeactivate()
//-----------------------------------------------------------------------------
void LLHandMotion::onDeactivate()
{
}
//-----------------------------------------------------------------------------
// LLHandMotion::getHandPoseName()
//-----------------------------------------------------------------------------

View File

@@ -45,7 +45,7 @@
// class LLHandMotion
//-----------------------------------------------------------------------------
class LLHandMotion :
public LLMotion
public AIMaskedMotion
{
public:
typedef enum e_hand_pose
@@ -68,7 +68,7 @@ public:
} eHandPose;
// Constructor
LLHandMotion(const LLUUID &id);
LLHandMotion(LLUUID const& id, LLMotionController* controller);
// Destructor
virtual ~LLHandMotion();
@@ -80,7 +80,7 @@ public:
// static constructor
// all subclasses must implement such a function and register it
static LLMotion *create(const LLUUID &id) { return new LLHandMotion(id); }
static LLMotion* create(LLUUID const& id, LLMotionController* controller) { return new LLHandMotion(id, controller); }
public:
//-------------------------------------------------------------------------
@@ -122,9 +122,6 @@ public:
// must return FALSE when the motion is completed.
virtual BOOL onUpdate(F32 time, U8* joint_mask);
// called when a motion is deactivated
virtual void onDeactivate();
virtual BOOL canDeprecate() { return FALSE; }
static std::string getHandPoseName(eHandPose pose);

View File

@@ -76,8 +76,8 @@ const F32 EYE_BLINK_TIME_DELTA = 0.005f; // time between one eye starting a blin
// LLHeadRotMotion()
// Class Constructor
//-----------------------------------------------------------------------------
LLHeadRotMotion::LLHeadRotMotion(const LLUUID &id) :
LLMotion(id),
LLHeadRotMotion::LLHeadRotMotion(LLUUID const& id, LLMotionController* controller) :
AIMaskedMotion(id, controller, ANIM_AGENT_HEAD_ROT),
mCharacter(NULL),
mTorsoJoint(NULL),
mHeadJoint(NULL)
@@ -104,7 +104,10 @@ LLHeadRotMotion::~LLHeadRotMotion()
LLMotion::LLMotionInitStatus LLHeadRotMotion::onInitialize(LLCharacter *character)
{
if (!character)
{
llwarns << "character is NULL." << llendl;
return STATUS_FAILURE;
}
mCharacter = character;
mPelvisJoint = character->getJoint("mPelvis");
@@ -169,16 +172,6 @@ LLMotion::LLMotionInitStatus LLHeadRotMotion::onInitialize(LLCharacter *characte
return STATUS_SUCCESS;
}
//-----------------------------------------------------------------------------
// LLHeadRotMotion::onActivate()
//-----------------------------------------------------------------------------
BOOL LLHeadRotMotion::onActivate()
{
return TRUE;
}
//-----------------------------------------------------------------------------
// LLHeadRotMotion::onUpdate()
//-----------------------------------------------------------------------------
@@ -263,19 +256,11 @@ BOOL LLHeadRotMotion::onUpdate(F32 time, U8* joint_mask)
}
//-----------------------------------------------------------------------------
// LLHeadRotMotion::onDeactivate()
//-----------------------------------------------------------------------------
void LLHeadRotMotion::onDeactivate()
{
}
//-----------------------------------------------------------------------------
// LLEyeMotion()
// Class Constructor
//-----------------------------------------------------------------------------
LLEyeMotion::LLEyeMotion(const LLUUID &id) : LLMotion(id)
LLEyeMotion::LLEyeMotion(LLUUID const& id, LLMotionController* controller) : AIMaskedMotion(id, controller, ANIM_AGENT_EYE)
{
mCharacter = NULL;
mEyeJitterTime = 0.f;
@@ -343,16 +328,6 @@ LLMotion::LLMotionInitStatus LLEyeMotion::onInitialize(LLCharacter *character)
return STATUS_SUCCESS;
}
//-----------------------------------------------------------------------------
// LLEyeMotion::onActivate()
//-----------------------------------------------------------------------------
BOOL LLEyeMotion::onActivate()
{
return TRUE;
}
//-----------------------------------------------------------------------------
// LLEyeMotion::onUpdate()
//-----------------------------------------------------------------------------
@@ -533,6 +508,8 @@ void LLEyeMotion::onDeactivate()
{
joint->setRotation(LLQuaternion::DEFAULT);
}
AIMaskedMotion::onDeactivate();
}
// End

View File

@@ -46,11 +46,11 @@
// class LLHeadRotMotion
//-----------------------------------------------------------------------------
class LLHeadRotMotion :
public LLMotion
public AIMaskedMotion
{
public:
// Constructor
LLHeadRotMotion(const LLUUID &id);
LLHeadRotMotion(LLUUID const& id, LLMotionController* controller);
// Destructor
virtual ~LLHeadRotMotion();
@@ -62,7 +62,7 @@ public:
// static constructor
// all subclasses must implement such a function and register it
static LLMotion *create(const LLUUID &id) { return new LLHeadRotMotion(id); }
static LLMotion* create(LLUUID const& id, LLMotionController* controller) { return new LLHeadRotMotion(id, controller); }
public:
//-------------------------------------------------------------------------
@@ -94,19 +94,11 @@ public:
// must return true to indicate success and be available for activation
virtual LLMotionInitStatus onInitialize(LLCharacter *character);
// called when a motion is activated
// must return TRUE to indicate success, or else
// it will be deactivated
virtual BOOL onActivate();
// called per time step
// must return TRUE while it is active, and
// must return FALSE when the motion is completed.
virtual BOOL onUpdate(F32 time, U8* joint_mask);
// called when a motion is deactivated
virtual void onDeactivate();
public:
//-------------------------------------------------------------------------
// joint states to be animated
@@ -129,11 +121,11 @@ public:
// class LLEyeMotion
//-----------------------------------------------------------------------------
class LLEyeMotion :
public LLMotion
public AIMaskedMotion
{
public:
// Constructor
LLEyeMotion(const LLUUID &id);
LLEyeMotion(LLUUID const& id, LLMotionController* controller);
// Destructor
virtual ~LLEyeMotion();
@@ -145,7 +137,7 @@ public:
// static constructor
// all subclasses must implement such a function and register it
static LLMotion *create( const LLUUID &id) { return new LLEyeMotion(id); }
static LLMotion* create(LLUUID const& id, LLMotionController* controller) { return new LLEyeMotion(id, controller); }
public:
//-------------------------------------------------------------------------
@@ -177,11 +169,6 @@ public:
// must return true to indicate success and be available for activation
virtual LLMotionInitStatus onInitialize(LLCharacter *character);
// called when a motion is activated
// must return TRUE to indicate success, or else
// it will be deactivated
virtual BOOL onActivate();
// called per time step
// must return TRUE while it is active, and
// must return FALSE when the motion is completed.

View File

@@ -41,7 +41,7 @@
#include "lldarray.h"
const S32 LL_CHARACTER_MAX_JOINTS_PER_MESH = 15;
const U32 LL_CHARACTER_MAX_JOINTS = 32; // must be divisible by 4!
const U32 LL_CHARACTER_MAX_JOINTS = 32; // must be divisible by 16!
const U32 LL_HAND_JOINT_NUM = 31;
const U32 LL_FACE_JOINT_NUM = 30;
const S32 LL_CHARACTER_MAX_PRIORITY = 7;

View File

@@ -49,7 +49,7 @@
// LLKeyframeFallMotion()
// Class Constructor
//-----------------------------------------------------------------------------
LLKeyframeFallMotion::LLKeyframeFallMotion(const LLUUID &id) : LLKeyframeMotion(id)
LLKeyframeFallMotion::LLKeyframeFallMotion(LLUUID const& id, LLMotionController* controller) : LLKeyframeMotion(id, controller)
{
mVelocityZ = 0.f;
mCharacter = NULL;

View File

@@ -47,7 +47,7 @@ class LLKeyframeFallMotion :
{
public:
// Constructor
LLKeyframeFallMotion(const LLUUID &id);
LLKeyframeFallMotion(LLUUID const& id, LLMotionController* controller);
// Destructor
virtual ~LLKeyframeFallMotion();
@@ -59,7 +59,7 @@ public:
// static constructor
// all subclasses must implement such a function and register it
static LLMotion *create(const LLUUID &id) { return new LLKeyframeFallMotion(id); }
static LLMotion* create(LLUUID const& id, LLMotionController* controller) { return new LLKeyframeFallMotion(id, controller); }
public:
//-------------------------------------------------------------------------

View File

@@ -84,38 +84,55 @@ LLKeyframeMotion::JointMotionList::~JointMotionList()
for_each(mJointMotionArray.begin(), mJointMotionArray.end(), DeletePointer());
}
U32 LLKeyframeMotion::JointMotionList::dumpDiagInfo()
//Singu: add parameter 'silent'.
U32 LLKeyframeMotion::JointMotionList::dumpDiagInfo(bool silent) const
{
S32 total_size = sizeof(JointMotionList);
for (U32 i = 0; i < getNumJointMotions(); i++)
{
LLKeyframeMotion::JointMotion* joint_motion_p = mJointMotionArray[i];
LLKeyframeMotion::JointMotion const* joint_motion_p = mJointMotionArray[i];
llinfos << "\tJoint " << joint_motion_p->mJointName << llendl;
if (!silent)
{
llinfos << "\tJoint " << joint_motion_p->mJointName << llendl;
}
if (joint_motion_p->mUsage & LLJointState::SCALE)
{
llinfos << "\t" << joint_motion_p->mScaleCurve.mNumKeys << " scale keys at "
<< joint_motion_p->mScaleCurve.mNumKeys * sizeof(ScaleKey) << " bytes" << llendl;
if (!silent)
{
llinfos << "\t" << joint_motion_p->mScaleCurve.mNumKeys << " scale keys at "
<< joint_motion_p->mScaleCurve.mNumKeys * sizeof(ScaleKey) << " bytes" << llendl;
}
total_size += joint_motion_p->mScaleCurve.mNumKeys * sizeof(ScaleKey);
}
if (joint_motion_p->mUsage & LLJointState::ROT)
{
llinfos << "\t" << joint_motion_p->mRotationCurve.mNumKeys << " rotation keys at "
<< joint_motion_p->mRotationCurve.mNumKeys * sizeof(RotationKey) << " bytes" << llendl;
if (!silent)
{
llinfos << "\t" << joint_motion_p->mRotationCurve.mNumKeys << " rotation keys at "
<< joint_motion_p->mRotationCurve.mNumKeys * sizeof(RotationKey) << " bytes" << llendl;
}
total_size += joint_motion_p->mRotationCurve.mNumKeys * sizeof(RotationKey);
}
if (joint_motion_p->mUsage & LLJointState::POS)
{
llinfos << "\t" << joint_motion_p->mPositionCurve.mNumKeys << " position keys at "
<< joint_motion_p->mPositionCurve.mNumKeys * sizeof(PositionKey) << " bytes" << llendl;
if (!silent)
{
llinfos << "\t" << joint_motion_p->mPositionCurve.mNumKeys << " position keys at "
<< joint_motion_p->mPositionCurve.mNumKeys * sizeof(PositionKey) << " bytes" << llendl;
}
total_size += joint_motion_p->mPositionCurve.mNumKeys * sizeof(PositionKey);
}
}
llinfos << "Size: " << total_size << " bytes" << llendl;
//Singu: Also add memory used by the constraints.
S32 constraints_size = mConstraints.size() * sizeof(constraint_list_t::value_type);
total_size += constraints_size;
if (!silent)
{
llinfos << "\t" << mConstraints.size() << " constraints at " << constraints_size << " bytes" << llendl;
llinfos << "Size: " << total_size << " bytes" << llendl;
}
return total_size;
}
@@ -427,9 +444,8 @@ void LLKeyframeMotion::JointMotion::update(LLJointState* joint_state, F32 time,
// LLKeyframeMotion()
// Class Constructor
//-----------------------------------------------------------------------------
LLKeyframeMotion::LLKeyframeMotion(const LLUUID &id)
: LLMotion(id),
mJointMotionList(NULL),
LLKeyframeMotion::LLKeyframeMotion(const LLUUID &id, LLMotionController* controller)
: LLMotion(id, controller),
mPelvisp(NULL),
mLastSkeletonSerialNum(0),
mLastUpdateTime(0.f),
@@ -452,9 +468,9 @@ LLKeyframeMotion::~LLKeyframeMotion()
//-----------------------------------------------------------------------------
// create()
//-----------------------------------------------------------------------------
LLMotion *LLKeyframeMotion::create(const LLUUID &id)
LLMotion* LLKeyframeMotion::create(LLUUID const& id, LLMotionController* controller)
{
return new LLKeyframeMotion(id);
return new LLKeyframeMotion(id, controller);
}
//-----------------------------------------------------------------------------
@@ -517,6 +533,7 @@ LLMotion::LLMotionInitStatus LLKeyframeMotion::onInitialize(LLCharacter *charact
case ASSET_FETCHED:
return STATUS_HOLD;
case ASSET_FETCH_FAILED:
llwarns << "Trying to initialize a motion that failed to be fetched." << llendl;
return STATUS_FAILURE;
case ASSET_LOADED:
return STATUS_SUCCESS;
@@ -526,7 +543,7 @@ LLMotion::LLMotionInitStatus LLKeyframeMotion::onInitialize(LLCharacter *charact
break;
}
LLKeyframeMotion::JointMotionList* joint_motion_list = LLKeyframeDataCache::getKeyframeData(getID());
LLKeyframeMotion::JointMotionListPtr joint_motion_list = LLKeyframeDataCache::getKeyframeData(getID());
if(joint_motion_list)
{
@@ -801,7 +818,44 @@ void LLKeyframeMotion::onDeactivate()
//-----------------------------------------------------------------------------
// setStopTime()
//-----------------------------------------------------------------------------
// time is in seconds since character creation
//
// Consider a looping animation of 20 frames, where the loop in point is at 3 frames
// and the loop out point at 16 frames:
//
// The first 3 frames of the animation would be the "loop in" animation.
// The last 4 frames of the animation would be the "loop out" animation.
// Frames 4 through 15 would be the looping animation frames.
//
// If the animation would not be looping, all frames would just be played once sequentially:
//
// mActivationTimestamp -.
// v
// 0 3 15 16 20
// | | \| |
// ---------------------
// <--> <-- mLoopInPoint (relative to mActivationTimestamp)
// <--------------> <-- mLoopOutPoint (relative to mActivationTimestamp)
// <----mDuration------>
//
// When looping the animation would repeat frames 3 to 16 (loop) a few times, for example:
//
// 0 3 15 3 15 3 15 3 15 16 20
// | | loop 1 \| loop 2 \| loop 3 \| loop 4 \| |
// ------------------------------------------------------------
//LOOP^ ^ LOOP
// IN | <----->| OUT
// start_loop_time loop_fraction_time-' time
//
// The time at which the animation is started corresponds to frame 0 and is stored
// in mActivationTimestamp (in seconds since character creation).
//
// If setStopTime() is called with a time somewhere inside loop 4,
// then 'loop_fraction_time' is the time from the beginning of
// loop 4 till 'time'. Thus 'time - loop_fraction_time' is the first
// frame of loop 4, and '(time - loop_fraction_time) +
// (mJointMotionList->mDuration - mJointMotionList->mLoopInPoint)'
// would correspond to frame 20.
//
void LLKeyframeMotion::setStopTime(F32 time)
{
LLMotion::setStopTime(time);
@@ -819,6 +873,8 @@ void LLKeyframeMotion::setStopTime(F32 time)
loop_fraction_time = fmod(time - start_loop_time,
mJointMotionList->mLoopOutPoint - mJointMotionList->mLoopInPoint);
}
// This sets mStopTimestamp to the time that corresponds to the end of the animation (ie, frame 20 in the above example)
// minus the ease out duration, so that the animation eases out during the loop out and finishes exactly at the end.
mStopTimestamp = llmax(time,
(time - loop_fraction_time) + (mJointMotionList->mDuration - mJointMotionList->mLoopInPoint) - getEaseOutDuration());
}
@@ -1227,13 +1283,42 @@ void LLKeyframeMotion::applyConstraint(JointConstraint* constraint, F32 time, U8
}
}
// Helper class.
template<typename T>
struct AIAutoDestruct
{
T* mPtr;
AIAutoDestruct() : mPtr(NULL) { }
~AIAutoDestruct() { delete mPtr; }
void add(T* ptr) { mPtr = ptr; }
};
//-----------------------------------------------------------------------------
// deserialize()
//-----------------------------------------------------------------------------
BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp)
{
BOOL old_version = FALSE;
mJointMotionList = new LLKeyframeMotion::JointMotionList;
//<singu>
// First add a new LLKeyframeMotion::JointMotionList to the cache, then assign a pointer
// to that to mJointMotionList. In LLs code the cache is never deleted again. Now it is
// is deleted when the last mJointMotionList pointer is destructed.
//
// It is possible that we get here for an already added animation, because animations can
// be requested multiple times (we get here from LLKeyframeMotion::onLoadComplete) when
// the animation was still downloading from a previous request for another LLMotionController
// object (avatar). In that case we just overwrite the old data while decoding it again.
mJointMotionList = LLKeyframeDataCache::getKeyframeData(getID());
bool singu_new_joint_motion_list = !mJointMotionList;
if (singu_new_joint_motion_list)
{
// Create a new JointMotionList.
mJointMotionList = LLKeyframeDataCache::createKeyframeData(getID());
}
//</singu>
//-------------------------------------------------------------------------
// get base priority
@@ -1396,8 +1481,10 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp)
return FALSE;
}
mJointMotionList->mJointMotionArray.clear();
mJointMotionList->mJointMotionArray.reserve(num_motions);
if (singu_new_joint_motion_list)
{
mJointMotionList->mJointMotionArray.reserve(num_motions);
}
mJointStates.clear();
mJointStates.reserve(num_motions);
@@ -1407,8 +1494,19 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp)
for(U32 i=0; i<num_motions; ++i)
{
AIAutoDestruct<JointMotion> watcher;
JointMotion* joint_motion = new JointMotion;
mJointMotionList->mJointMotionArray.push_back(joint_motion);
if (singu_new_joint_motion_list)
{
// Pass ownership to mJointMotionList.
mJointMotionList->mJointMotionArray.push_back(joint_motion);
}
else
{
// Just delete this at the end.
watcher.add(joint_motion);
}
std::string joint_name;
if (!dp.unpackString(joint_name, "joint_name"))
@@ -1836,7 +1934,15 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp)
return FALSE;
}
mJointMotionList->mConstraints.push_front(constraintp);
AIAutoDestruct<JointConstraintSharedData> watcher;
if (singu_new_joint_motion_list)
{
mJointMotionList->mConstraints.push_front(constraintp);
}
else
{
watcher.add(constraintp);
}
constraintp->mJointStateIndices = new S32[constraintp->mChainLength + 1]; // note: mChainLength is size-limited - comes from a byte
@@ -1876,15 +1982,12 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp)
if (constraintp->mJointStateIndices[i] < 0 )
{
llwarns << "No joint index for constraint " << i << llendl;
delete constraintp;
return FALSE;
}
}
}
}
// *FIX: support cleanup of old keyframe data
LLKeyframeDataCache::addKeyframeData(getID(), mJointMotionList);
mAssetStatus = ASSET_LOADED;
setupPose();
@@ -2226,16 +2329,24 @@ void LLKeyframeMotion::onLoadComplete(LLVFS *vfs,
//--------------------------------------------------------------------
// LLKeyframeDataCache::dumpDiagInfo()
//--------------------------------------------------------------------
void LLKeyframeDataCache::dumpDiagInfo()
// <singu>
// quiet = 0 : print everything in detail.
// 1 : print the UUIDs of all animations in the cache and the total memory usage.
// 2 : only print the total memory usage.
// </singu>
void LLKeyframeDataCache::dumpDiagInfo(int quiet)
{
// keep track of totals
U32 total_size = 0;
char buf[1024]; /* Flawfinder: ignore */
llinfos << "-----------------------------------------------------" << llendl;
llinfos << " Global Motion Table (DEBUG only)" << llendl;
llinfos << "-----------------------------------------------------" << llendl;
if (quiet < 2)
{
llinfos << "-----------------------------------------------------" << llendl;
llinfos << " Global Motion Table" << llendl;
llinfos << "-----------------------------------------------------" << llendl;
}
// print each loaded mesh, and it's memory usage
for (keyframe_data_map_t::iterator map_it = sKeyframeDataMap.begin();
@@ -2243,30 +2354,46 @@ void LLKeyframeDataCache::dumpDiagInfo()
{
U32 joint_motion_kb;
LLKeyframeMotion::JointMotionList *motion_list_p = map_it->second;
LLKeyframeMotion::JointMotionList const* motion_list_p = map_it->get();
llinfos << "Motion: " << map_it->first << llendl;
if (quiet < 2)
{
llinfos << "Motion: " << map_it->key() << llendl;
}
joint_motion_kb = motion_list_p->dumpDiagInfo();
total_size += joint_motion_kb;
if (motion_list_p)
{
joint_motion_kb = motion_list_p->dumpDiagInfo(quiet);
total_size += joint_motion_kb;
}
}
llinfos << "-----------------------------------------------------" << llendl;
if (quiet < 2)
{
llinfos << "-----------------------------------------------------" << llendl;
}
llinfos << "Motions\tTotal Size" << llendl;
snprintf(buf, sizeof(buf), "%d\t\t%d bytes", (S32)sKeyframeDataMap.size(), total_size ); /* Flawfinder: ignore */
llinfos << buf << llendl;
llinfos << "-----------------------------------------------------" << llendl;
if (quiet < 2)
{
llinfos << "-----------------------------------------------------" << llendl;
}
}
//--------------------------------------------------------------------
// LLKeyframeDataCache::addKeyframeData()
// LLKeyframeDataCache::createKeyframeData()
//--------------------------------------------------------------------
void LLKeyframeDataCache::addKeyframeData(const LLUUID& id, LLKeyframeMotion::JointMotionList* joint_motion_listp)
//<singu> This function replaces LLKeyframeDataCache::addKeyframeData and was rewritten to fix a memory leak (aka, the usage of AICachedPointer).
LLKeyframeMotion::JointMotionListPtr LLKeyframeDataCache::createKeyframeData(LLUUID const& id)
{
sKeyframeDataMap[id] = joint_motion_listp;
std::pair<keyframe_data_map_t::iterator, bool> result =
sKeyframeDataMap.insert(AICachedPointer<LLUUID, LLKeyframeMotion::JointMotionList>(id, new LLKeyframeMotion::JointMotionList, &sKeyframeDataMap));
llassert(result.second); // id may not already exist in the cache.
return &*result.first; // Construct and return a JointMotionListPt from a pointer to the actually inserted AICachedPointer.
}
//</singu>
//--------------------------------------------------------------------
// LLKeyframeDataCache::removeKeyframeData()
@@ -2276,7 +2403,6 @@ void LLKeyframeDataCache::removeKeyframeData(const LLUUID& id)
keyframe_data_map_t::iterator found_data = sKeyframeDataMap.find(id);
if (found_data != sKeyframeDataMap.end())
{
delete found_data->second;
sKeyframeDataMap.erase(found_data);
}
}
@@ -2284,14 +2410,14 @@ void LLKeyframeDataCache::removeKeyframeData(const LLUUID& id)
//--------------------------------------------------------------------
// LLKeyframeDataCache::getKeyframeData()
//--------------------------------------------------------------------
LLKeyframeMotion::JointMotionList* LLKeyframeDataCache::getKeyframeData(const LLUUID& id)
LLKeyframeMotion::JointMotionListPtr LLKeyframeDataCache::getKeyframeData(const LLUUID& id)
{
keyframe_data_map_t::iterator found_data = sKeyframeDataMap.find(id);
if (found_data == sKeyframeDataMap.end())
{
return NULL;
}
return found_data->second;
return &*found_data; // Construct and return a JointMotionListPt from a pointer to the found AICachedPointer.
}
//--------------------------------------------------------------------
@@ -2307,7 +2433,6 @@ LLKeyframeDataCache::~LLKeyframeDataCache()
//-----------------------------------------------------------------------------
void LLKeyframeDataCache::clear()
{
for_each(sKeyframeDataMap.begin(), sKeyframeDataMap.end(), DeletePairedPointer());
sKeyframeDataMap.clear();
}

View File

@@ -5,6 +5,7 @@
* $LicenseInfo:firstyear=2001&license=viewergpl$
*
* Copyright (c) 2001-2009, Linden Research, Inc.
* AICachedPointer and AICachedPointPtr copyright (c) 2013, Aleric Inglewood.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
@@ -48,10 +49,12 @@
#include "v3dmath.h"
#include "v3math.h"
#include "llbvhconsts.h"
#include <boost/intrusive_ptr.hpp>
class LLKeyframeDataCache;
class LLVFS;
class LLDataPacker;
class LLMotionController;
#define MIN_REQUIRED_PIXEL_AREA_KEYFRAME (40.f)
#define MAX_CHAIN_LENGTH (4)
@@ -59,6 +62,112 @@ class LLDataPacker;
const S32 KEYFRAME_MOTION_VERSION = 1;
const S32 KEYFRAME_MOTION_SUBVERSION = 0;
//-----------------------------------------------------------------------------
// <singu>
template<typename KEY, typename T>
class AICachedPointer;
template<typename KEY, typename T>
void intrusive_ptr_add_ref(AICachedPointer<KEY, T> const* p);
template<typename KEY, typename T>
void intrusive_ptr_release(AICachedPointer<KEY, T> const* p);
template<typename KEY, typename T>
class AICachedPointer
{
public:
typedef std::set<AICachedPointer<KEY, T> > container_type;
private:
KEY mKey; // The unique key.
LLPointer<T> mData; // The actual data pointer.
container_type* mCache; // Pointer to the underlaying cache.
mutable int mRefCount; // Number of AICachedPointerPtr's pointing to this object.
public:
// Construct a NULL pointer. This is needed when adding a new entry to a std::set, it is always first default constructed.
AICachedPointer(void) : mCache(NULL) { }
// Copy constructor. This is needed to replace the std::set inserted instance with its actual value.
AICachedPointer(AICachedPointer const& cptr) : mKey(cptr.mKey), mData(cptr.mData), mCache(cptr.mCache), mRefCount(0) { }
// Construct a AICachedPointer that points to 'ptr' with key 'key'.
AICachedPointer(KEY const& key, T* ptr, container_type* cache) : mKey(key), mData(ptr), mCache(cache), mRefCount(-1) { }
// Construct a temporary NULL pointer that can be used in a search for a key.
AICachedPointer(KEY const& key) : mKey(key), mCache(NULL) { }
// Accessors for key and data.
KEY const& key(void) const { return mKey; }
T const* get(void) const { return mData.get(); }
T* get(void) { return mData.get(); }
// Order only by key.
friend bool operator<(AICachedPointer const& cp1, AICachedPointer const& cp2) { return cp1.mKey < cp2.mKey; }
private:
friend void intrusive_ptr_add_ref<>(AICachedPointer<KEY, T> const* p);
friend void intrusive_ptr_release<>(AICachedPointer<KEY, T> const* p);
private:
AICachedPointer& operator=(AICachedPointer const&);
};
template<typename KEY, typename T>
void intrusive_ptr_add_ref(AICachedPointer<KEY, T> const* p)
{
llassert(p->mCache);
if (p->mCache)
{
p->mRefCount++;
}
}
template<typename KEY, typename T>
void intrusive_ptr_release(AICachedPointer<KEY, T> const* p)
{
llassert(p->mCache);
if (p->mCache)
{
if (--p->mRefCount == 0)
{
p->mCache->erase(p->mKey);
}
}
}
template<typename KEY, typename T>
class AICachedPointerPtr
{
private:
boost::intrusive_ptr<AICachedPointer<KEY, T> const> mPtr;
static int sCnt;
public:
AICachedPointerPtr(void) { ++sCnt; }
AICachedPointerPtr(AICachedPointerPtr const& cpp) : mPtr(cpp.mPtr) { ++sCnt; }
AICachedPointerPtr(AICachedPointer<KEY, T> const* cp) : mPtr(cp) { ++sCnt; }
~AICachedPointerPtr() { --sCnt; }
typedef boost::intrusive_ptr<AICachedPointer<KEY, T> const> const AICachedPointerPtr<KEY, T>::* const bool_type;
operator bool_type() const { return mPtr ? &AICachedPointerPtr<KEY, T>::mPtr : NULL; }
T const* operator->() const { return mPtr->get(); }
T* operator->() { return const_cast<AICachedPointer<KEY, T>&>(*mPtr).get(); }
T const& operator*() const { return *mPtr->get(); }
T& operator*() { return *const_cast<AICachedPointer<KEY, T>&>(*mPtr).get(); }
AICachedPointerPtr& operator=(AICachedPointerPtr const& cpp) { mPtr = cpp.mPtr; return *this; }
};
template<typename KEY, typename T>
int AICachedPointerPtr<KEY, T>::sCnt;
// </singu>
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// class LLKeyframeMotion
//-----------------------------------------------------------------------------
@@ -68,7 +177,7 @@ class LLKeyframeMotion :
friend class LLKeyframeDataCache;
public:
// Constructor
LLKeyframeMotion(const LLUUID &id);
LLKeyframeMotion(const LLUUID &id, LLMotionController* controller);
// Destructor
virtual ~LLKeyframeMotion();
@@ -85,7 +194,7 @@ public:
// static constructor
// all subclasses must implement such a function and register it
static LLMotion *create(const LLUUID& id);
static LLMotion* create(LLUUID const& id, LLMotionController* controller);
public:
//-------------------------------------------------------------------------
@@ -158,7 +267,7 @@ public:
U32 getFileSize();
BOOL serialize(LLDataPacker& dp) const;
BOOL deserialize(LLDataPacker& dp);
BOOL isLoaded() { return mJointMotionList != NULL; }
BOOL isLoaded() { return !!mJointMotionList; }
// setters for modifying a keyframe animation
@@ -393,7 +502,7 @@ public:
//-------------------------------------------------------------------------
// JointMotionList
//-------------------------------------------------------------------------
class JointMotionList
class JointMotionList : public LLRefCount
{
public:
std::vector<JointMotion*> mJointMotionArray;
@@ -416,19 +525,22 @@ public:
public:
JointMotionList();
~JointMotionList();
U32 dumpDiagInfo();
U32 dumpDiagInfo(bool silent = false) const;
JointMotion* getJointMotion(U32 index) const { llassert(index < mJointMotionArray.size()); return mJointMotionArray[index]; }
U32 getNumJointMotions() const { return mJointMotionArray.size(); }
};
// Singu: Type of a pointer to the cached pointer (in LLKeyframeDataCache::sKeyframeDataMap) to a JointMotionList object.
typedef AICachedPointerPtr<LLUUID, JointMotionList> JointMotionListPtr;
protected:
static LLVFS* sVFS;
//-------------------------------------------------------------------------
// Member Data
//-------------------------------------------------------------------------
JointMotionList* mJointMotionList;
JointMotionListPtr mJointMotionList; // singu: automatically clean up cache entry when destructed.
std::vector<LLPointer<LLJointState> > mJointStates;
LLJoint* mPelvisp;
LLCharacter* mCharacter;
@@ -442,21 +554,24 @@ protected:
class LLKeyframeDataCache
{
public:
// *FIX: implement this as an actual singleton member of LLKeyframeMotion
private:
friend class LLKeyframeMotion;
LLKeyframeDataCache(){};
~LLKeyframeDataCache();
typedef std::map<LLUUID, class LLKeyframeMotion::JointMotionList*> keyframe_data_map_t;
public:
typedef AICachedPointer<LLUUID, LLKeyframeMotion::JointMotionList>::container_type keyframe_data_map_t; // singu: add automatic cache cleanup.
static keyframe_data_map_t sKeyframeDataMap;
static void addKeyframeData(const LLUUID& id, LLKeyframeMotion::JointMotionList*);
static LLKeyframeMotion::JointMotionList* getKeyframeData(const LLUUID& id);
//<singu>
static LLKeyframeMotion::JointMotionListPtr createKeyframeData(LLUUID const& id); // id may not exist.
static LLKeyframeMotion::JointMotionListPtr getKeyframeData(LLUUID const& id); // id may or may not exists. Returns a NULL pointer when it doesn't exist.
//</singu>
static void removeKeyframeData(const LLUUID& id);
//print out diagnostic info
static void dumpDiagInfo();
static void dumpDiagInfo(int quiet = 0); // singu: added param 'quiet'.
static void clear();
};

View File

@@ -1,456 +0,0 @@
/**
* @file llkeyframemotionparam.cpp
* @brief Implementation of LLKeyframeMotion class.
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
//-----------------------------------------------------------------------------
// Header Files
//-----------------------------------------------------------------------------
#include "linden_common.h"
#include "llkeyframemotionparam.h"
#include "llcharacter.h"
#include "llmath.h"
#include "m3math.h"
#include "lldir.h"
#include "llanimationstates.h"
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// LLKeyframeMotionParam class
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// LLKeyframeMotionParam()
// Class Constructor
//-----------------------------------------------------------------------------
LLKeyframeMotionParam::LLKeyframeMotionParam( const LLUUID &id) : LLMotion(id)
{
mDefaultKeyframeMotion = NULL;
mCharacter = NULL;
mEaseInDuration = 0.f;
mEaseOutDuration = 0.f;
mDuration = 0.f;
mPriority = LLJoint::LOW_PRIORITY;
}
//-----------------------------------------------------------------------------
// ~LLKeyframeMotionParam()
// Class Destructor
//-----------------------------------------------------------------------------
LLKeyframeMotionParam::~LLKeyframeMotionParam()
{
for (motion_map_t::iterator iter = mParameterizedMotions.begin();
iter != mParameterizedMotions.end(); ++iter)
{
motion_list_t& motionList = iter->second;
for (motion_list_t::iterator iter2 = motionList.begin(); iter2 != motionList.end(); ++iter2)
{
const ParameterizedMotion& paramMotion = *iter2;
delete paramMotion.mMotion;
}
motionList.clear();
}
mParameterizedMotions.clear();
}
//-----------------------------------------------------------------------------
// LLKeyframeMotionParam::onInitialize(LLCharacter *character)
//-----------------------------------------------------------------------------
LLMotion::LLMotionInitStatus LLKeyframeMotionParam::onInitialize(LLCharacter *character)
{
mCharacter = character;
if (!loadMotions())
{
return STATUS_FAILURE;
}
for (motion_map_t::iterator iter = mParameterizedMotions.begin();
iter != mParameterizedMotions.end(); ++iter)
{
motion_list_t& motionList = iter->second;
for (motion_list_t::iterator iter2 = motionList.begin(); iter2 != motionList.end(); ++iter2)
{
const ParameterizedMotion& paramMotion = *iter2;
LLMotion* motion = paramMotion.mMotion;
motion->onInitialize(character);
if (motion->getDuration() > mEaseInDuration)
{
mEaseInDuration = motion->getEaseInDuration();
}
if (motion->getEaseOutDuration() > mEaseOutDuration)
{
mEaseOutDuration = motion->getEaseOutDuration();
}
if (motion->getDuration() > mDuration)
{
mDuration = motion->getDuration();
}
if (motion->getPriority() > mPriority)
{
mPriority = motion->getPriority();
}
LLPose *pose = motion->getPose();
mPoseBlender.addMotion(motion);
for (LLJointState *jsp = pose->getFirstJointState(); jsp; jsp = pose->getNextJointState())
{
LLPose *blendedPose = mPoseBlender.getBlendedPose();
blendedPose->addJointState(jsp);
}
}
}
return STATUS_SUCCESS;
}
//-----------------------------------------------------------------------------
// LLKeyframeMotionParam::onActivate()
//-----------------------------------------------------------------------------
BOOL LLKeyframeMotionParam::onActivate()
{
for (motion_map_t::iterator iter = mParameterizedMotions.begin();
iter != mParameterizedMotions.end(); ++iter)
{
motion_list_t& motionList = iter->second;
for (motion_list_t::iterator iter2 = motionList.begin(); iter2 != motionList.end(); ++iter2)
{
const ParameterizedMotion& paramMotion = *iter2;
paramMotion.mMotion->activate(mActivationTimestamp);
}
}
return TRUE;
}
//-----------------------------------------------------------------------------
// LLKeyframeMotionParam::onUpdate()
//-----------------------------------------------------------------------------
BOOL LLKeyframeMotionParam::onUpdate(F32 time, U8* joint_mask)
{
F32 weightFactor = 1.f / (F32)mParameterizedMotions.size();
// zero out all pose weights
for (motion_map_t::iterator iter = mParameterizedMotions.begin();
iter != mParameterizedMotions.end(); ++iter)
{
motion_list_t& motionList = iter->second;
for (motion_list_t::iterator iter2 = motionList.begin(); iter2 != motionList.end(); ++iter2)
{
const ParameterizedMotion& paramMotion = *iter2;
// llinfos << "Weight for pose " << paramMotion.mMotion->getName() << " is " << paramMotion.mMotion->getPose()->getWeight() << llendl;
paramMotion.mMotion->getPose()->setWeight(0.f);
}
}
for (motion_map_t::iterator iter = mParameterizedMotions.begin();
iter != mParameterizedMotions.end(); ++iter)
{
const std::string& paramName = iter->first;
F32* paramValue = (F32 *)mCharacter->getAnimationData(paramName);
if (NULL == paramValue) // unexpected, but...
{
llwarns << "paramValue == NULL" << llendl;
continue;
}
// DANGER! Do not modify mParameterizedMotions while using these pointers!
const ParameterizedMotion* firstMotion = NULL;
const ParameterizedMotion* secondMotion = NULL;
motion_list_t& motionList = iter->second;
for (motion_list_t::iterator iter2 = motionList.begin(); iter2 != motionList.end(); ++iter2)
{
const ParameterizedMotion& paramMotion = *iter2;
paramMotion.mMotion->onUpdate(time, joint_mask);
F32 distToParam = paramMotion.mParam - *paramValue;
if ( distToParam <= 0.f)
{
// keep track of the motion closest to the parameter value
firstMotion = &paramMotion;
}
else
{
// we've passed the parameter value
// so store the first motion we find as the second one we want to blend...
if (firstMotion && !secondMotion )
{
secondMotion = &paramMotion;
}
//...or, if we've seen no other motion so far, make sure we blend to this only
else if (!firstMotion)
{
firstMotion = &paramMotion;
secondMotion = &paramMotion;
}
}
}
LLPose *firstPose;
LLPose *secondPose;
if (firstMotion)
firstPose = firstMotion->mMotion->getPose();
else
firstPose = NULL;
if (secondMotion)
secondPose = secondMotion->mMotion->getPose();
else
secondPose = NULL;
// now modify weight of the subanim (only if we are blending between two motions)
if (firstMotion && secondMotion)
{
if (firstMotion == secondMotion)
{
firstPose->setWeight(weightFactor);
}
else if (firstMotion->mParam == secondMotion->mParam)
{
firstPose->setWeight(0.5f * weightFactor);
secondPose->setWeight(0.5f * weightFactor);
}
else
{
F32 first_weight = 1.f -
((llclamp(*paramValue - firstMotion->mParam, 0.f, (secondMotion->mParam - firstMotion->mParam))) /
(secondMotion->mParam - firstMotion->mParam));
first_weight = llclamp(first_weight, 0.f, 1.f);
F32 second_weight = 1.f - first_weight;
firstPose->setWeight(first_weight * weightFactor);
secondPose->setWeight(second_weight * weightFactor);
// llinfos << "Parameter " << *paramName << ": " << *paramValue << llendl;
// llinfos << "Weights " << firstPose->getWeight() << " " << secondPose->getWeight() << llendl;
}
}
else if (firstMotion && !secondMotion)
{
firstPose->setWeight(weightFactor);
}
}
// blend poses
mPoseBlender.blendAndApply();
llinfos << "Param Motion weight " << mPoseBlender.getBlendedPose()->getWeight() << llendl;
return TRUE;
}
//-----------------------------------------------------------------------------
// LLKeyframeMotionParam::onDeactivate()
//-----------------------------------------------------------------------------
void LLKeyframeMotionParam::onDeactivate()
{
for (motion_map_t::iterator iter = mParameterizedMotions.begin();
iter != mParameterizedMotions.end(); ++iter)
{
motion_list_t& motionList = iter->second;
for (motion_list_t::iterator iter2 = motionList.begin(); iter2 != motionList.end(); ++iter2)
{
const ParameterizedMotion& paramMotion = *iter2;
paramMotion.mMotion->onDeactivate();
}
}
}
//-----------------------------------------------------------------------------
// LLKeyframeMotionParam::addKeyframeMotion()
//-----------------------------------------------------------------------------
BOOL LLKeyframeMotionParam::addKeyframeMotion(char *name, const LLUUID &id, char *param, F32 value)
{
LLMotion *newMotion = mCharacter->createMotion( id );
if (!newMotion)
{
return FALSE;
}
newMotion->setName(name);
// now add motion to this list
mParameterizedMotions[param].insert(ParameterizedMotion(newMotion, value));
return TRUE;
}
//-----------------------------------------------------------------------------
// LLKeyframeMotionParam::setDefaultKeyframeMotion()
//-----------------------------------------------------------------------------
void LLKeyframeMotionParam::setDefaultKeyframeMotion(char *name)
{
for (motion_map_t::iterator iter = mParameterizedMotions.begin();
iter != mParameterizedMotions.end(); ++iter)
{
motion_list_t& motionList = iter->second;
for (motion_list_t::iterator iter2 = motionList.begin(); iter2 != motionList.end(); ++iter2)
{
const ParameterizedMotion& paramMotion = *iter2;
if (paramMotion.mMotion->getName() == name)
{
mDefaultKeyframeMotion = paramMotion.mMotion;
}
}
}
}
//-----------------------------------------------------------------------------
// loadMotions()
//-----------------------------------------------------------------------------
BOOL LLKeyframeMotionParam::loadMotions()
{
//-------------------------------------------------------------------------
// Load named file by concatenating the character prefix with the motion name.
// Load data into a buffer to be parsed.
//-------------------------------------------------------------------------
//std::string path = gDirUtilp->getExpandedFilename(LL_PATH_MOTIONS,mCharacter->getAnimationPrefix())
// + "_" + getName() + ".llp";
//RN: deprecated unused reference to "motion" directory
std::string path;
//-------------------------------------------------------------------------
// open the file
//-------------------------------------------------------------------------
S32 fileSize = 0;
LLAPRFile infile(path, LL_APR_R, &fileSize);
apr_file_t* fp = infile.getFileHandle() ;
if (!fp || fileSize == 0)
{
llinfos << "ERROR: can't open: " << path << llendl;
return FALSE;
}
// allocate a text buffer
try
{
std::vector<char> text(fileSize+1);
//-------------------------------------------------------------------------
// load data from file into buffer
//-------------------------------------------------------------------------
bool error = false;
char *p = &text[0];
while ( 1 )
{
if (apr_file_eof(fp) == APR_EOF)
{
break;
}
if (apr_file_gets(p, 1024, fp) != APR_SUCCESS)
{
error = true;
break;
}
while ( *(++p) )
;
}
//-------------------------------------------------------------------------
// close the file
//-------------------------------------------------------------------------
infile.close();
//-------------------------------------------------------------------------
// check for error
//-------------------------------------------------------------------------
llassert( p <= (&text[0] + fileSize) );
if ( error )
{
llinfos << "ERROR: error while reading from " << path << llendl;
return FALSE;
}
llinfos << "Loading parametric keyframe data for: " << getName() << llendl;
//-------------------------------------------------------------------------
// parse the text and build keyframe data structures
//-------------------------------------------------------------------------
p = &text[0];
S32 num;
char strA[80]; /* Flawfinder: ignore */
char strB[80]; /* Flawfinder: ignore */
F32 floatA = 0.0f;
//-------------------------------------------------------------------------
// get priority
//-------------------------------------------------------------------------
BOOL isFirstMotion = TRUE;
num = sscanf(p, "%79s %79s %f", strA, strB, &floatA); /* Flawfinder: ignore */
while(1)
{
if (num == 0 || num == EOF) break;
if ((num != 3))
{
llinfos << "WARNING: can't read parametric motion" << llendl;
return FALSE;
}
addKeyframeMotion(strA, gAnimLibrary.stringToAnimState(std::string(strA)), strB, floatA);
if (isFirstMotion)
{
isFirstMotion = FALSE;
setDefaultKeyframeMotion(strA);
}
p = strstr(p, "\n");
if (!p)
{
break;
}
p++;
num = sscanf(p, "%79s %79s %f", strA, strB, &floatA); /* Flawfinder: ignore */
}
return TRUE;
}
catch(std::bad_alloc)
{
llinfos << "ERROR: Unable to allocate keyframe text buffer." << llendl;
return FALSE;
}
}
// End

View File

@@ -1,176 +0,0 @@
/**
* @file llkeyframemotionparam.h
* @brief Implementation of LLKeframeMotionParam class.
*
* $LicenseInfo:firstyear=2002&license=viewergpl$
*
* Copyright (c) 2002-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#ifndef LL_LLKEYFRAMEMOTIONPARAM_H
#define LL_LLKEYFRAMEMOTIONPARAM_H
//-----------------------------------------------------------------------------
// Header files
//-----------------------------------------------------------------------------
#include <string>
#include "llmotion.h"
#include "lljointstate.h"
#include "v3math.h"
#include "llquaternion.h"
#include "linked_lists.h"
#include "llkeyframemotion.h"
//-----------------------------------------------------------------------------
// class LLKeyframeMotionParam
//-----------------------------------------------------------------------------
class LLKeyframeMotionParam :
public LLMotion
{
public:
// Constructor
LLKeyframeMotionParam(const LLUUID &id);
// Destructor
virtual ~LLKeyframeMotionParam();
public:
//-------------------------------------------------------------------------
// functions to support MotionController and MotionRegistry
//-------------------------------------------------------------------------
// static constructor
// all subclasses must implement such a function and register it
static LLMotion *create(const LLUUID &id) { return new LLKeyframeMotionParam(id); }
public:
//-------------------------------------------------------------------------
// animation callbacks to be implemented by subclasses
//-------------------------------------------------------------------------
// motions must specify whether or not they loop
virtual BOOL getLoop() {
return TRUE;
}
// motions must report their total duration
virtual F32 getDuration() {
return mDuration;
}
// motions must report their "ease in" duration
virtual F32 getEaseInDuration() {
return mEaseInDuration;
}
// motions must report their "ease out" duration.
virtual F32 getEaseOutDuration() {
return mEaseOutDuration;
}
// motions must report their priority
virtual LLJoint::JointPriority getPriority() {
return mPriority;
}
virtual LLMotionBlendType getBlendType() { return NORMAL_BLEND; }
// called to determine when a motion should be activated/deactivated based on avatar pixel coverage
virtual F32 getMinPixelArea() { return MIN_REQUIRED_PIXEL_AREA_KEYFRAME; }
// run-time (post constructor) initialization,
// called after parameters have been set
// must return true to indicate success and be available for activation
virtual LLMotionInitStatus onInitialize(LLCharacter *character);
// called when a motion is activated
// must return TRUE to indicate success, or else
// it will be deactivated
virtual BOOL onActivate();
// called per time step
// must return TRUE while it is active, and
// must return FALSE when the motion is completed.
virtual BOOL onUpdate(F32 time, U8* joint_mask);
// called when a motion is deactivated
virtual void onDeactivate();
virtual LLPose* getPose() { return mPoseBlender.getBlendedPose();}
protected:
//-------------------------------------------------------------------------
// new functions defined by this subclass
//-------------------------------------------------------------------------
struct ParameterizedMotion
{
ParameterizedMotion(LLMotion* motion, F32 param) : mMotion(motion), mParam(param) {}
LLMotion* mMotion;
F32 mParam;
};
// add a motion and associated parameter triplet
BOOL addKeyframeMotion(char *name, const LLUUID &id, char *param, F32 value);
// set default motion for LOD and retrieving blend constants
void setDefaultKeyframeMotion(char *);
BOOL loadMotions();
protected:
//-------------------------------------------------------------------------
// Member Data
//-------------------------------------------------------------------------
struct compare_motions
{
bool operator() (const ParameterizedMotion& a, const ParameterizedMotion& b) const
{
if (a.mParam != b.mParam)
return (a.mParam < b.mParam);
else
return a.mMotion < b.mMotion;
}
};
typedef std::set < ParameterizedMotion, compare_motions > motion_list_t;
typedef std::map <std::string, motion_list_t > motion_map_t;
motion_map_t mParameterizedMotions;
LLMotion* mDefaultKeyframeMotion;
LLCharacter* mCharacter;
LLPoseBlender mPoseBlender;
F32 mEaseInDuration;
F32 mEaseOutDuration;
F32 mDuration;
LLJoint::JointPriority mPriority;
LLUUID mTransactionID;
};
#endif // LL_LLKEYFRAMEMOTIONPARAM_H

View File

@@ -50,7 +50,7 @@ const F32 POSITION_THRESHOLD = 0.1f;
// LLKeyframeStandMotion()
// Class Constructor
//-----------------------------------------------------------------------------
LLKeyframeStandMotion::LLKeyframeStandMotion(const LLUUID &id) : LLKeyframeMotion(id)
LLKeyframeStandMotion::LLKeyframeStandMotion(LLUUID const& id, LLMotionController* controller) : LLKeyframeMotion(id, controller)
{
mFlipFeet = FALSE;
mCharacter = NULL;

View File

@@ -48,7 +48,7 @@ class LLKeyframeStandMotion :
{
public:
// Constructor
LLKeyframeStandMotion(const LLUUID &id);
LLKeyframeStandMotion(LLUUID const& id, LLMotionController* controller);
// Destructor
virtual ~LLKeyframeStandMotion();
@@ -60,7 +60,7 @@ public:
// static constructor
// all subclasses must implement such a function and register it
static LLMotion *create(const LLUUID &id) { return new LLKeyframeStandMotion(id); }
static LLMotion* create(LLUUID const& id, LLMotionController* controller) { return new LLKeyframeStandMotion(id, controller); }
public:
//-------------------------------------------------------------------------

View File

@@ -55,8 +55,8 @@ const F32 SPEED_ADJUST_TIME_CONSTANT = 0.1f; // time constant for speed adjustm
// LLKeyframeWalkMotion()
// Class Constructor
//-----------------------------------------------------------------------------
LLKeyframeWalkMotion::LLKeyframeWalkMotion(const LLUUID &id)
: LLKeyframeMotion(id),
LLKeyframeWalkMotion::LLKeyframeWalkMotion(LLUUID const& id, LLMotionController* controller)
: LLKeyframeMotion(id, controller),
mCharacter(NULL),
mCyclePhase(0.0f),
mRealTimeLast(0.0f),
@@ -138,8 +138,8 @@ BOOL LLKeyframeWalkMotion::onUpdate(F32 time, U8* joint_mask)
// LLWalkAdjustMotion()
// Class Constructor
//-----------------------------------------------------------------------------
LLWalkAdjustMotion::LLWalkAdjustMotion(const LLUUID &id) :
LLMotion(id),
LLWalkAdjustMotion::LLWalkAdjustMotion(LLUUID const& id, LLMotionController* controller) :
AIMaskedMotion(id, controller, ANIM_AGENT_WALK_ADJUST),
mLastTime(0.f),
mAnimSpeed(0.f),
mAdjustedSpeed(0.f),
@@ -193,7 +193,7 @@ BOOL LLWalkAdjustMotion::onActivate()
F32 rightAnkleOffset = (mRightAnkleJoint->getWorldPosition() - mCharacter->getCharacterPosition()).magVec();
mAnkleOffset = llmax(leftAnkleOffset, rightAnkleOffset);
return TRUE;
return AIMaskedMotion::onActivate();
}
//-----------------------------------------------------------------------------
@@ -325,13 +325,14 @@ BOOL LLWalkAdjustMotion::onUpdate(F32 time, U8* joint_mask)
void LLWalkAdjustMotion::onDeactivate()
{
mCharacter->removeAnimationData("Walk Speed");
AIMaskedMotion::onDeactivate();
}
//-----------------------------------------------------------------------------
// LLFlyAdjustMotion::LLFlyAdjustMotion()
//-----------------------------------------------------------------------------
LLFlyAdjustMotion::LLFlyAdjustMotion(const LLUUID &id)
: LLMotion(id),
LLFlyAdjustMotion::LLFlyAdjustMotion(LLUUID const& id, LLMotionController* controller)
: AIMaskedMotion(id, controller, ANIM_AGENT_FLY_ADJUST),
mRoll(0.f)
{
mName = "fly_adjust";
@@ -368,7 +369,7 @@ BOOL LLFlyAdjustMotion::onActivate()
mPelvisState->setPosition(LLVector3::zero);
mPelvisState->setRotation(LLQuaternion::DEFAULT);
mRoll = 0.f;
return TRUE;
return AIMaskedMotion::onActivate();
}
//-----------------------------------------------------------------------------

View File

@@ -52,7 +52,7 @@ class LLKeyframeWalkMotion :
friend class LLWalkAdjustMotion;
public:
// Constructor
LLKeyframeWalkMotion(const LLUUID &id);
LLKeyframeWalkMotion(LLUUID const& id, LLMotionController* controller);
// Destructor
virtual ~LLKeyframeWalkMotion();
@@ -64,7 +64,7 @@ public:
// static constructor
// all subclasses must implement such a function and register it
static LLMotion *create(const LLUUID &id) { return new LLKeyframeWalkMotion(id); }
static LLMotion* create(LLUUID const& id, LLMotionController* controller) { return new LLKeyframeWalkMotion(id, controller); }
public:
//-------------------------------------------------------------------------
@@ -86,11 +86,11 @@ public:
S32 mDownFoot;
};
class LLWalkAdjustMotion : public LLMotion
class LLWalkAdjustMotion : public AIMaskedMotion
{
public:
// Constructor
LLWalkAdjustMotion(const LLUUID &id);
LLWalkAdjustMotion(LLUUID const& id, LLMotionController* controller);
public:
//-------------------------------------------------------------------------
@@ -99,7 +99,7 @@ public:
// static constructor
// all subclasses must implement such a function and register it
static LLMotion *create(const LLUUID &id) { return new LLWalkAdjustMotion(id); }
static LLMotion* create(LLUUID const& id, LLMotionController* controller) { return new LLWalkAdjustMotion(id, controller); }
public:
//-------------------------------------------------------------------------
@@ -136,11 +136,11 @@ public:
F32 mAnkleOffset;
};
class LLFlyAdjustMotion : public LLMotion
class LLFlyAdjustMotion : public AIMaskedMotion
{
public:
// Constructor
LLFlyAdjustMotion(const LLUUID &id);
LLFlyAdjustMotion(LLUUID const& id, LLMotionController* controller);
public:
//-------------------------------------------------------------------------
@@ -149,7 +149,7 @@ public:
// static constructor
// all subclasses must implement such a function and register it
static LLMotion *create(const LLUUID &id) { return new LLFlyAdjustMotion(id); }
static LLMotion* create(LLUUID const& id, LLMotionController* controller) { return new LLFlyAdjustMotion(id, controller); }
public:
//-------------------------------------------------------------------------
@@ -157,7 +157,6 @@ public:
//-------------------------------------------------------------------------
virtual LLMotionInitStatus onInitialize(LLCharacter *character);
virtual BOOL onActivate();
virtual void onDeactivate() {};
virtual BOOL onUpdate(F32 time, U8* joint_mask);
virtual LLJoint::JointPriority getPriority(){return LLJoint::HIGHER_PRIORITY;}
virtual BOOL getLoop() { return TRUE; }

View File

@@ -37,6 +37,125 @@
#include "llmotion.h"
#include "llcriticaldamp.h"
#include "llmotioncontroller.h"
//<singu>
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// AISyncClientMotion class
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
AISyncKey* AISyncClientMotion::createSyncKey(AISyncKey const* from_key) const
{
// The const cast is needed because getDuration() is non-const while it should have been.
AISyncClientMotion* self = const_cast<AISyncClientMotion*>(this);
// Only synchronize motions with the same duration and loop value.
return new AISyncKeyMotion(from_key, self->getDuration(), self->getLoop());
}
void AISyncClientMotion::aisync_loading(void)
{
// Register the motion for (possible) synchronization: this marks the time at which is should have started.
unregister_client(); // In case it is already registered. Getting here means we are being (re)started now, we need to synchronize with other motions that start now.
register_client();
}
void AISyncClientMotion::aisync_loaded(void)
{
AISyncServer* server = this->server();
if (!server)
{
// Already expired without being synchronized (no other motion was started at the same time).
return;
}
AISyncKey const& key = server->key(); // The allocation of this is owned by server.
// There is no need to resync if there was not another motion started at the same time and the key already expired.
bool need_resync = !(server->never_synced() && key.expired());
AISyncKey* new_key = NULL;
if (need_resync)
{
// Create a new key using the old start time.
new_key = createSyncKey(&key);
}
server->remove(this); // This resets mServer and might even delete server.
if (need_resync)
{
// Add the client to another server (based on the new key). This takes ownership of the key allocation.
AISyncServerMap::instance().register_client(this, new_key);
}
}
F32 LLMotion::getRuntime(void) const
{
llassert(mActive);
return mController->getAnimTime() - mActivationTimestamp;
}
F32 LLMotion::getAnimTime(void) const
{
return mController->getAnimTime();
}
F32 LLMotion::syncActivationTime(F32 time)
{
AISyncServer* server = this->server();
if (!server)
{
register_client();
server = this->server();
}
AISyncServer::client_list_t const& clients = server->getClients();
if (clients.size() > 1)
{
// Look for the client with the smallest runtime.
AISyncClientMotion* motion_with_smallest_runtime = NULL;
F32 runtime = 1e10;
// Run over all motions in this to be synchronized group.
for (AISyncServer::client_list_t::const_iterator client = clients.begin(); client != clients.end(); ++client)
{
if ((client->mReadyEvents & 2)) // Is this motion active? Motions that aren't loaded yet are not active.
{
// Currently, if event 2 is set then this is an LLMotion.
llassert(dynamic_cast<AISyncClientMotion*>(client->mClientPtr));
AISyncClientMotion* motion = static_cast<AISyncClientMotion*>(client->mClientPtr);
// Deactivated motions should have been deregistered, certainly not have event 2 set.
llassert(static_cast<LLMotion*>(motion)->isActive());
if (motion->getRuntime() < runtime)
{
// This is a bit fuzzy since theoretically the runtime of all active motions in the list should be the same.
// Just use the smallest value to get rid of some randomness. We might even synchronizing with ourselves
// in which case 'time' would be set to a value such that mActivationTimestamp won't change.
// In practise however, this list will contain only two clients: this, being inactive, and our partner.
runtime = motion->getRuntime();
motion_with_smallest_runtime = motion;
}
}
}
//-----------------------------------------------------------------------------------------
// Here is where the actual synchronization takes place.
// Current we only synchronize looped motions.
if (getLoop())
{
if (motion_with_smallest_runtime)
{
// Pretend the motion was started in the past at the same time as the other motion(s).
time = getAnimTime() - runtime;
}
}
//-----------------------------------------------------------------------------------------
}
return time;
}
void AISyncClientMotion::deregistered(void)
{
#ifdef SHOW_ASSERT
mReadyEvents = 0;
#endif
}
//</singu>
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
@@ -48,10 +167,11 @@
// LLMotion()
// Class Constructor
//-----------------------------------------------------------------------------
LLMotion::LLMotion( const LLUUID &id ) :
LLMotion::LLMotion(LLUUID const& id, LLMotionController* controller) :
mStopped(TRUE),
mActive(FALSE),
mID(id),
mController(controller),
mActivationTimestamp(0.f),
mStopTimestamp(0.f),
mSendStopTimestamp(F32_MAX),
@@ -147,6 +267,19 @@ void LLMotion::activate(F32 time)
{
mActivationTimestamp = time;
mStopped = FALSE;
//<singu>
if (mController && !mController->syncing_disabled()) // Avoid being registered when syncing is disabled for this motion.
{
if (mActive)
{
// If the motion is already active then we are being restarted.
// Unregister it first (if it is registered) so that the call to ready will cause it to be registered
// and be synchronized with other motions that are started at this moment.
unregister_client();
}
ready(6, 2 | (mController->isHidden() ? 0 : 4)); // Signal that mActivationTimestamp is set/valid (2), and that this server has a visible motion (4) (or not).
}
//</singu>
mActive = TRUE;
onActivate();
}
@@ -159,6 +292,14 @@ void LLMotion::deactivate()
mActive = FALSE;
mPose.setWeight(0.f);
//<singu>
if (server()) // Only when this motion is already registered.
{
ready(6, 0); // Signal that mActivationTimestamp is no longer valid.
unregister_client(); // No longer running, so no longer a part of this sync group.
}
//</singu>
if (mDeactivateCallback)
{
(*mDeactivateCallback)(mDeactivateCallbackUserData);
@@ -174,4 +315,19 @@ BOOL LLMotion::canDeprecate()
return TRUE;
}
//-----------------------------------------------------------------------------
// AIMaskedMotion
//-----------------------------------------------------------------------------
BOOL AIMaskedMotion::onActivate()
{
mController->activated(mMaskBit);
return TRUE;
}
void AIMaskedMotion::onDeactivate()
{
mController->deactivated(mMaskBit);
}
// End

View File

@@ -38,16 +38,85 @@
//-----------------------------------------------------------------------------
#include <string>
#include "aisyncclient.h"
#include "llerror.h"
#include "llpose.h"
#include "lluuid.h"
class LLCharacter;
class LLMotionController;
//-----------------------------------------------------------------------------
// class AISync* stuff
//-----------------------------------------------------------------------------
class AISyncKeyMotion : public AISyncKey
{
private:
F32 mDuration;
bool mLoop;
public:
AISyncKeyMotion(AISyncKey const* from_key, F32 duration, bool loop) : AISyncKey(from_key), mDuration(duration), mLoop(loop) { }
// Virtual functions of AISyncKey.
public:
/*virtual*/ synckeytype_t getkeytype(void) const
{
// Return a unique identifier for this class, where the low 8 bits represent the syncgroup.
return synckeytype_motion;
}
/*virtual*/ bool equals(AISyncKey const& key) const
{
switch (key.getkeytype())
{
case synckeytype_motion:
{
// The other key is of the same type.
AISyncKeyMotion const& motion_key = static_cast<AISyncKeyMotion const&>(key);
return mLoop == motion_key.mLoop && is_approx_equal(mDuration, motion_key.mDuration);
}
default:
// The keys must be in the same syncgroup.
break;
}
return false;
}
};
class AISyncClientMotion : public AISyncClient
{
protected:
// Make sure that clients that are destroyed are first unregistered.
// This is needed, for example, when loading fails or when excess motions are being purged.
/*virtual*/ ~AISyncClientMotion() { unregister_client(); }
// AISyncClient events.
/*virtual*/ AISyncKey* createSyncKey(AISyncKey const* from_key = NULL) const;
/*virtual*/ void event1_ready(void) { }
/*virtual*/ void event1_not_ready(void) { }
/*virtual*/ void deregistered(void);
protected:
// This is called when the server sent us a message that it wants us to play this animation, but we can't because it isn't fully downloaded yet.
void aisync_loading(void);
// This is called when that motion is successfully loaded and it has to be re-registered because now the duration etc is known.
void aisync_loaded(void);
public:
// Virtual functions of AISyncClientMotion.
// These are defined by classes derived from LLMotion (which is derived from this class).
virtual BOOL getLoop() = 0;
virtual F32 getDuration() = 0;
virtual F32 getAnimTime(void) const = 0;
virtual F32 getRuntime(void) const = 0;
};
//-----------------------------------------------------------------------------
// class LLMotion
//-----------------------------------------------------------------------------
class LLMotion
class LLMotion : public AISyncClientMotion
{
friend class LLMotionController;
@@ -66,7 +135,7 @@ public:
};
// Constructor
LLMotion(const LLUUID &id);
LLMotion(LLUUID const& id, LLMotionController* controller);
// Destructor
virtual ~LLMotion();
@@ -114,7 +183,22 @@ protected:
BOOL isActive() { return mActive; }
public:
void activate(F32 time);
//<singu>
// Returns the time that this motion has been running.
virtual F32 getRuntime(void) const;
// Return the current time (in seconds since creation of the controller).
virtual F32 getAnimTime(void) const;
// This is called when a motion is to be activated, but might need synchronization.
// It adjusts the start time to match that of other motions in the same synchronization group that were already started.
F32 syncActivationTime(F32 time);
// Accessor.
LLMotionController* getController(void) const { return mController; }
//</singu>
public:
//-------------------------------------------------------------------------
// animation callbacks to be implemented by subclasses
@@ -181,6 +265,9 @@ protected:
//-------------------------------------------------------------------------
std::string mName; // instance name assigned by motion controller
LLUUID mID;
//<singu>
LLMotionController* mController;
//</singu>
F32 mActivationTimestamp; // time when motion was activated
F32 mStopTimestamp; // time when motion was told to stop
@@ -199,9 +286,9 @@ protected:
class LLTestMotion : public LLMotion
{
public:
LLTestMotion(const LLUUID &id) : LLMotion(id){}
LLTestMotion(LLUUID const& id, LLMotionController* controller) : LLMotion(id, controller){}
~LLTestMotion() {}
static LLMotion *create(const LLUUID& id) { return new LLTestMotion(id); }
static LLMotion* create(LLUUID const& id, LLMotionController* controller) { return new LLTestMotion(id, controller); }
BOOL getLoop() { return FALSE; }
F32 getDuration() { return 0.0f; }
F32 getEaseInDuration() { return 0.0f; }
@@ -223,9 +310,9 @@ public:
class LLNullMotion : public LLMotion
{
public:
LLNullMotion(const LLUUID &id) : LLMotion(id) {}
LLNullMotion(LLUUID const& id, LLMotionController* controller) : LLMotion(id, controller) {}
~LLNullMotion() {}
static LLMotion *create(const LLUUID &id) { return new LLNullMotion(id); }
static LLMotion* create(LLUUID const& id, LLMotionController* controller) { return new LLNullMotion(id, controller); }
// motions must specify whether or not they loop
/*virtual*/ BOOL getLoop() { return TRUE; }
@@ -266,5 +353,41 @@ public:
// called when a motion is deactivated
/*virtual*/ void onDeactivate() {}
};
//-----------------------------------------------------------------------------
// AIMaskedMotion
//-----------------------------------------------------------------------------
// These motions have a bit assigned in LLMotionController::mActiveMask
// that is set and uset upon activation/deactivation.
// This must be in the same order as ANIM_AGENT_BODY_NOISE_ID through ANIM_AGENT_WALK_ADJUST_ID in llvoavatar.cpp.
U32 const ANIM_AGENT_BODY_NOISE = 0x001;
U32 const ANIM_AGENT_BREATHE_ROT = 0x002;
U32 const ANIM_AGENT_PHYSICS_MOTION = 0x004;
U32 const ANIM_AGENT_EDITING = 0x008;
U32 const ANIM_AGENT_EYE = 0x010;
U32 const ANIM_AGENT_FLY_ADJUST = 0x020;
U32 const ANIM_AGENT_HAND_MOTION = 0x040;
U32 const ANIM_AGENT_HEAD_ROT = 0x080;
U32 const ANIM_AGENT_PELVIS_FIX = 0x100;
U32 const ANIM_AGENT_TARGET = 0x200;
U32 const ANIM_AGENT_WALK_ADJUST = 0x400;
class AIMaskedMotion : public LLMotion
{
private:
U32 mMaskBit;
public:
AIMaskedMotion(LLUUID const& id, LLMotionController* controller, U32 mask_bit) : LLMotion(id, controller), mMaskBit(mask_bit) { }
/*virtual*/ BOOL onActivate();
/*virtual*/ void onDeactivate();
U32 getMaskBit(void) const { return mMaskBit; }
};
#endif // LL_LLMOTION_H

View File

@@ -97,7 +97,7 @@ void LLMotionRegistry::markBad( const LLUUID& id )
//-----------------------------------------------------------------------------
// createMotion()
//-----------------------------------------------------------------------------
LLMotion *LLMotionRegistry::createMotion( const LLUUID &id )
LLMotion* LLMotionRegistry::createMotion(LLUUID const& id, LLMotionController* controller)
{
LLMotionConstructor constructor = get_if_there(mMotionTable, id, LLMotionConstructor(NULL));
LLMotion* motion = NULL;
@@ -105,11 +105,11 @@ LLMotion *LLMotionRegistry::createMotion( const LLUUID &id )
if ( constructor == NULL )
{
// *FIX: need to replace with a better default scheme. RN
motion = LLKeyframeMotion::create(id);
motion = LLKeyframeMotion::create(id, controller);
}
else
{
motion = constructor(id);
motion = constructor(id, controller);
}
return motion;
@@ -126,18 +126,22 @@ LLMotion *LLMotionRegistry::createMotion( const LLUUID &id )
// Class Constructor
//-----------------------------------------------------------------------------
LLMotionController::LLMotionController()
: mTimeFactor(sCurrentTimeFactor),
: mIsSelf(FALSE),
mTimeFactor(sCurrentTimeFactor),
mCharacter(NULL),
mAnimTime(0.f),
mActiveMask(0),
mDisableSyncing(0),
mHidden(false),
mHaveVisibleSyncedMotions(false),
mPrevTimerElapsed(0.f),
mAnimTime(0.f),
mLastTime(0.0f),
mHasRunOnce(FALSE),
mPaused(FALSE),
mPauseTime(0.f),
mTimeStep(0.f),
mTimeStepCount(0),
mLastInterp(0.f),
mIsSelf(FALSE)
mLastInterp(0.f)
{
}
@@ -168,7 +172,15 @@ void LLMotionController::deleteAllMotions()
mLoadingMotions.clear();
mLoadedMotions.clear();
mActiveMotions.clear();
//<singu>
mActiveMask = 0;
for_each(mDeprecatedMotions.begin(), mDeprecatedMotions.end(), DeletePointer());
mDeprecatedMotions.clear();
for (motion_map_t::iterator iter = mAllMotions.begin(); iter != mAllMotions.end(); ++iter)
{
iter->second->unregister_client();
}
//</singu>
for_each(mAllMotions.begin(), mAllMotions.end(), DeletePairedPointer());
mAllMotions.clear();
}
@@ -178,26 +190,19 @@ void LLMotionController::deleteAllMotions()
//-----------------------------------------------------------------------------
void LLMotionController::purgeExcessMotions()
{
if (mLoadedMotions.size() > MAX_MOTION_INSTANCES)
//<singu>
// The old code attempted to remove non-active motions from mDeprecatedMotions,
// but that is nonsense: there are no motions in mDeprecatedMotions that are not active.
if (mLoadedMotions.size() <= MAX_MOTION_INSTANCES)
{
// clean up deprecated motions
for (motion_set_t::iterator deprecated_motion_it = mDeprecatedMotions.begin();
deprecated_motion_it != mDeprecatedMotions.end(); )
{
motion_set_t::iterator cur_iter = deprecated_motion_it++;
LLMotion* cur_motionp = *cur_iter;
if (!isMotionActive(cur_motionp))
{
// Motion is deprecated so we know it's not cannonical,
// we can safely remove the instance
removeMotionInstance(cur_motionp); // modifies mDeprecatedMotions
mDeprecatedMotions.erase(cur_iter);
}
}
// Speed up, no need to create motions_to_kill.
return;
}
//</singu>
std::set<LLUUID> motions_to_kill;
if (mLoadedMotions.size() > MAX_MOTION_INSTANCES)
if (1) // Singu: leave indentation alone...
{
// too many motions active this frame, kill all blenders
mPoseBlender.clearBlenders();
@@ -308,24 +313,44 @@ BOOL LLMotionController::registerMotion( const LLUUID& id, LLMotionConstructor c
void LLMotionController::removeMotion( const LLUUID& id)
{
LLMotion* motionp = findMotion(id);
mAllMotions.erase(id);
removeMotionInstance(motionp);
//<singu>
// If a motion is erased from mAllMotions, it must be deleted.
if (motionp)
{
mAllMotions.erase(id);
removeMotionInstance(motionp);
delete motionp;
}
//</singu>
}
// removes instance of a motion from all runtime structures, but does
// not erase entry by ID, as this could be a duplicate instance
// use removeMotion(id) to remove all references to a given motion by id.
// use removeMotion(id) to remove a reference to a given motion by id
// (that will not remove (active) deprecated motions).
void LLMotionController::removeMotionInstance(LLMotion* motionp)
{
if (motionp)
{
llassert(findMotion(motionp->getID()) != motionp);
if (motionp->isActive())
motionp->deactivate();
mLoadingMotions.erase(motionp);
mLoadedMotions.erase(motionp);
mActiveMotions.remove(motionp);
delete motionp;
//<singu>
// Deactivation moved here. Only delete motionp when it is being removed from mDeprecatedMotions.
if (motionp->isActive())
{
motionp->deactivate();
// If a motion is deactivated, it must be removed from mDeprecatedMotions if there.
motion_set_t::iterator found_it = mDeprecatedMotions.find(motionp);
if (found_it != mDeprecatedMotions.end())
{
mDeprecatedMotions.erase(found_it);
// If a motion is erased from mDeprecatedMotions, it must be deleted.
delete motionp;
}
}
//</singu>
}
}
@@ -341,7 +366,7 @@ LLMotion* LLMotionController::createMotion( const LLUUID &id )
if (!motion)
{
// look up constructor and create it
motion = sRegistry.createMotion(id);
motion = sRegistry.createMotion(id, this);
if (!motion)
{
return NULL;
@@ -393,6 +418,7 @@ BOOL LLMotionController::startMotion(const LLUUID &id, F32 start_offset)
if (motion
&& !mPaused
&& motion->canDeprecate()
&& motion->isActive() // singu: do not deprecate motions that are not active.
&& motion->getFadeWeight() > 0.01f // not LOD-ed out
&& (motion->isBlending() || motion->getStopTime() != 0.f))
{
@@ -418,7 +444,19 @@ BOOL LLMotionController::startMotion(const LLUUID &id, F32 start_offset)
}
// llinfos << "Starting motion " << name << llendl;
return activateMotionInstance(motion, mAnimTime - start_offset);
//<singu>
F32 start_time = mAnimTime - start_offset;
if (!mDisableSyncing)
{
start_time = motion->syncActivationTime(start_time);
}
++mDisableSyncing;
//</singu>
BOOL res = activateMotionInstance(motion, start_time);
//<singu>
--mDisableSyncing;
//</singu>
return res;
}
@@ -774,7 +812,19 @@ void LLMotionController::updateLoadingMotions()
// this motion should be playing
if (!motionp->isStopped())
{
activateMotionInstance(motionp, mAnimTime);
//<singu>
F32 start_time = mAnimTime;
if (!mDisableSyncing)
{
motionp->aisync_loaded();
start_time = motionp->syncActivationTime(start_time);
}
++mDisableSyncing;
//</singu>
activateMotionInstance(motionp, start_time);
//<singu>
--mDisableSyncing;
//</singu>
}
}
else if (status == LLMotion::STATUS_FAILURE)
@@ -782,12 +832,15 @@ void LLMotionController::updateLoadingMotions()
llinfos << "Motion " << motionp->getID() << " init failed." << llendl;
sRegistry.markBad(motionp->getID());
mLoadingMotions.erase(curiter);
motion_set_t::iterator found_it = mDeprecatedMotions.find(motionp);
if (found_it != mDeprecatedMotions.end())
{
mDeprecatedMotions.erase(found_it);
}
// Singu note: a motion in mLoadingMotions will not be in mActiveMotions
// and therefore not be in mDeprecatedMotions. So, we don't have to
// check for it's existence there.
llassert(mDeprecatedMotions.find(motionp) == mDeprecatedMotions.end());
mAllMotions.erase(motionp->getID());
//<singu>
// Make sure we're not registered anymore.
motionp->unregister_client();
//</singu>
delete motionp;
}
}
@@ -821,8 +874,15 @@ void LLMotionController::updateMotions(bool force_update)
{
F32 time_interval = fmodf(update_time, mTimeStep);
// always animate *ahead* of actual time
S32 quantum_count = llmax(0, llfloor((update_time - time_interval) / mTimeStep)) + 1;
//<singu>
// This old code is nonsense.
//S32 quantum_count = llmax(0, llround((update_time - time_interval) / mTimeStep)) + 1;
// (update_time - time_interval) / mTimeStep is an integer! We need llround to get rid of floating point errors, not llfloor.
// Moreover, just rounding off to the nearest integer with llround(update_time / mTimeStep) makes a lot more sense:
// it is the best we can do to get as close to what we should draw as possible.
// However, mAnimTime may only be incremented; therefore make sure of that with the llmax.
S32 quantum_count = llmax(llround(update_time / mTimeStep), llceil(mAnimTime / mTimeStep));
//</singu>
if (quantum_count == mTimeStepCount)
{
// we're still in same time quantum as before, so just interpolate and exit
@@ -848,7 +908,8 @@ void LLMotionController::updateMotions(bool force_update)
}
else
{
mAnimTime = update_time;
// Singu note: mAnimTime may never be set back in time.
mAnimTime = llmax(mAnimTime, update_time);
}
}
@@ -915,6 +976,12 @@ BOOL LLMotionController::activateMotionInstance(LLMotion *motion, F32 time)
if (mLoadingMotions.find(motion) != mLoadingMotions.end())
{
//<singu>
if (!syncing_disabled())
{
motion->aisync_loading();
}
//</singu>
// we want to start this motion, but we can't yet, so flag it as started
motion->setStopped(FALSE);
// report pending animations as activated
@@ -970,18 +1037,16 @@ BOOL LLMotionController::activateMotionInstance(LLMotion *motion, F32 time)
//-----------------------------------------------------------------------------
BOOL LLMotionController::deactivateMotionInstance(LLMotion *motion)
{
motion->deactivate();
motion_set_t::iterator found_it = mDeprecatedMotions.find(motion);
if (found_it != mDeprecatedMotions.end())
{
// deprecated motions need to be completely excised
removeMotionInstance(motion);
mDeprecatedMotions.erase(found_it);
removeMotionInstance(motion); // singu note: this deactivates motion and removes it from mDeprecatedMotions.
}
else
{
// for motions that we are keeping, simply remove from active queue
motion->deactivate(); // singu note: moved here from the top of the function.
mActiveMotions.remove(motion);
}
@@ -1049,11 +1114,26 @@ void LLMotionController::dumpMotions()
state_string += std::string("L");
if (std::find(mActiveMotions.begin(), mActiveMotions.end(), motion)!=mActiveMotions.end())
state_string += std::string("A");
if (mDeprecatedMotions.find(motion) != mDeprecatedMotions.end())
state_string += std::string("D");
llassert(mDeprecatedMotions.find(motion) == mDeprecatedMotions.end()); // singu: it's impossible that a motion is in mAllMotions and mDeprecatedMotions at the same time.
llinfos << gAnimLibrary.animationName(id) << " " << state_string << llendl;
}
//<singu>
// Also dump the deprecated motions.
for (motion_set_t::iterator iter = mDeprecatedMotions.begin();
iter != mDeprecatedMotions.end(); ++iter)
{
std::string state_string;
LLMotion* motion = *iter;
LLUUID id = motion->getID();
llassert(mLoadingMotions.find(motion) == mLoadingMotions.end());
if (mLoadedMotions.find(motion) != mLoadedMotions.end())
state_string += std::string("L");
if (std::find(mActiveMotions.begin(), mActiveMotions.end(), motion)!=mActiveMotions.end())
state_string += std::string("A");
state_string += "D";
llinfos << gAnimLibrary.animationName(id) << " " << state_string << llendl;
}
//</singu>
}
//-----------------------------------------------------------------------------
@@ -1061,11 +1141,11 @@ void LLMotionController::dumpMotions()
//-----------------------------------------------------------------------------
void LLMotionController::deactivateAllMotions()
{
for (motion_map_t::iterator iter = mAllMotions.begin();
iter != mAllMotions.end(); iter++)
// Singu note: this must run over mActiveMotions: other motions are not active,
// and running over mAllMotions will miss the ones in mDeprecatedMotions.
for (motion_list_t::iterator iter = mActiveMotions.begin(); iter != mActiveMotions.end();)
{
LLMotion* motionp = iter->second;
deactivateMotionInstance(motionp);
deactivateMotionInstance(*iter++); // This might invalidate iter by erasing it from mActiveMotions.
}
}
@@ -1086,8 +1166,7 @@ void LLMotionController::flushAllMotions()
active_motions.push_back(std::make_pair(motionp->getID(),dtime));
motionp->deactivate(); // don't call deactivateMotionInstance() because we are going to reactivate it
}
mActiveMotions.clear();
// delete all motion instances
deleteAllMotions();
@@ -1096,13 +1175,136 @@ void LLMotionController::flushAllMotions()
mCharacter->removeAnimationData("Hand Pose");
// restart motions
//<singu>
// Because we called motionp->deactivate() above, instead of deactivateMotionInstance(),
// prevent calling AISyncClientMotion::activateInstance in startMotion below.
disable_syncing();
//</singu>
for (std::vector<std::pair<LLUUID,F32> >::iterator iter = active_motions.begin();
iter != active_motions.end(); ++iter)
{
startMotion(iter->first, iter->second);
}
//<singu>
enable_syncing();
//</singu>
}
//<singu>
//-----------------------------------------------------------------------------
// toggle_hidden()
//-----------------------------------------------------------------------------
void LLMotionController::toggle_hidden(void)
{
mHaveVisibleSyncedMotions = mHidden; // Default is false if we just became invisible (otherwise this value isn't used).
mHidden = !mHidden;
synceventset_t const visible = mHidden ? 0 : 4;
// Run over all motions.
for (motion_list_t::iterator iter = mActiveMotions.begin(); iter != mActiveMotions.end(); ++iter)
{
LLMotion* motionp = *iter;
AISyncServer* server = motionp->server();
if (server && !server->never_synced() && motionp->isActive()) // Skip motions that aren't synchronized at all or that are not active.
{
bool visible_before = server->events_with_at_least_one_client_ready() & 4;
server->ready(4, visible, motionp); // Mark that now we are visible or no longer visible.
bool visible_after = server->events_with_at_least_one_client_ready() & 4;
if (visible_after) // Are there any synchronized motions (left) that ARE visible?
{
mHaveVisibleSyncedMotions = true;
}
if (visible_before != visible_after)
{
// The group as a whole now might need to change whether or not it is animated.
AISyncServer::client_list_t const& clients = server->getClients();
for (AISyncServer::client_list_t::const_iterator client = clients.begin(); client != clients.end(); ++client)
{
LLMotion* motion = dynamic_cast<LLMotion*>(client->mClientPtr);
if (!motion)
{
continue;
}
LLMotionController* controller = motion->getController();
if (controller == this)
{
continue;
}
if (visible_after)
{
// Us becoming visible means that all synchronized avatars need to be animated again too.
controller->setHaveVisibleSyncedMotions();
}
else
{
// Us becoming hidden means that all synchronized avatars might stop animating.
controller->refresh_hidden(); // It is extremely unlikely, but harmless, to call this twice on the same controller.
}
}
}
}
}
}
void LLMotionController::refresh_hidden(void)
{
mHaveVisibleSyncedMotions = !mHidden;
// Run over all motions.
for (motion_list_t::iterator iter = mActiveMotions.begin(); iter != mActiveMotions.end(); ++iter)
{
LLMotion* motionp = *iter;
AISyncServer* server = motionp->server();
if (server && !server->never_synced() && motionp->isActive()) // Skip motions that aren't synchronized at all or that are not active.
{
bool visible_after = server->events_with_at_least_one_client_ready() & 4;
if (visible_after) // Are there any synchronized motions (left) that ARE visible?
{
mHaveVisibleSyncedMotions = true;
}
}
}
}
void LLMotionController::pauseAllSyncedCharacters(std::vector<LLAnimPauseRequest>& avatar_pause_handles)
{
// Run over all motions.
for (motion_list_t::iterator iter = mActiveMotions.begin(); iter != mActiveMotions.end(); ++iter)
{
LLMotion* motionp = *iter;
AISyncServer* server = motionp->server();
if (server && !server->never_synced() && motionp->isActive()) // Skip motions that aren't synchronized at all or that are not active.
{
// Run over all clients of the found servers.
AISyncServer::client_list_t const& clients = server->getClients();
for (AISyncServer::client_list_t::const_iterator client = clients.begin(); client != clients.end(); ++client)
{
LLMotion* motion = dynamic_cast<LLMotion*>(client->mClientPtr);
if (!motion)
{
continue;
}
LLMotionController* controller = motion->getController();
if (controller == this)
{
continue;
}
controller->requestPause(avatar_pause_handles);
}
}
}
}
void LLMotionController::requestPause(std::vector<LLAnimPauseRequest>& avatar_pause_handles)
{
if (mCharacter)
{
mCharacter->requestPause(avatar_pause_handles);
}
}
//</singu>
//-----------------------------------------------------------------------------
// pause()
//-----------------------------------------------------------------------------

View File

@@ -51,11 +51,14 @@
// This is necessary because llcharacter.h includes this file.
//-----------------------------------------------------------------------------
class LLCharacter;
class LLMotionController;
class LLPauseRequestHandle;
typedef LLPointer<LLPauseRequestHandle> LLAnimPauseRequest;
//-----------------------------------------------------------------------------
// LLMotionRegistry
//-----------------------------------------------------------------------------
typedef LLMotion*(*LLMotionConstructor)(const LLUUID &id);
typedef LLMotion* (*LLMotionConstructor)(LLUUID const& id, LLMotionController*);
class LLMotionRegistry
{
@@ -72,7 +75,7 @@ public:
// creates a new instance of a named motion
// returns NULL motion is not registered
LLMotion *createMotion( const LLUUID &id );
LLMotion* createMotion(LLUUID const& id, LLMotionController* controller);
// initialization of motion failed, don't try to create this motion again
void markBad( const LLUUID& id );
@@ -115,7 +118,6 @@ public:
// unregisters a motion with the controller
// (actually just forwards call to motion registry)
// returns true if successfull
void removeMotion( const LLUUID& id );
// start motion
@@ -150,10 +152,20 @@ public:
//Flush is a liar.
void deactivateAllMotions();
//<singu>
void activated(U32 bit) { mActiveMask |= bit; }
void deactivated(U32 bit) { mActiveMask &= ~bit; }
bool isactive(U32 bit) const { return (mActiveMask & bit) != 0; }
//</singu>
// pause and continue all motions
void pauseAllMotions();
void unpauseAllMotions();
BOOL isPaused() const { return mPaused; }
//<singu>
void requestPause(std::vector<LLAnimPauseRequest>& avatar_pause_handles);
void pauseAllSyncedCharacters(std::vector<LLAnimPauseRequest>& avatar_pause_handles);
//</singu>
void setTimeStep(F32 step);
@@ -180,7 +192,10 @@ protected:
// internal operations act on motion instances directly
// as there can be duplicate motions per id during blending overlap
void deleteAllMotions();
// singu: LLMotion needs access to activateMotionInstance.
public:
BOOL activateMotionInstance(LLMotion *motion, F32 time);
protected:
BOOL deactivateMotionInstance(LLMotion *motion);
void deprecateMotionInstance(LLMotion* motion);
BOOL stopMotionInstance(LLMotion *motion, BOOL stop_imemdiate);
@@ -205,10 +220,13 @@ protected:
// Life cycle of an animation:
//
// Animations are instantiated and immediately put in the mAllMotions map for their entire lifetime.
// Singu note: that is not true, they are moved to mDeprecatedMotions (often) for the last part of their lifetime.
// If the animations depend on any asset data, the appropriate data is fetched from the data server,
// and the animation is put on the mLoadingMotions list.
// Once an animations is loaded, it will be initialized and put on the mLoadedMotions list.
// Any animation that is currently playing also sits in the mActiveMotions list.
// Singu note: animations are only put in mDeprecatedMotions if and while they are playing,
// therefore animations in mDeprecatedMotions will be (must be) active and in mActiveMotions.
typedef std::map<LLUUID, LLMotion*> motion_map_t;
motion_map_t mAllMotions;
@@ -217,7 +235,13 @@ protected:
motion_set_t mLoadedMotions;
motion_list_t mActiveMotions;
motion_set_t mDeprecatedMotions;
//<singu>
U32 mActiveMask;
int mDisableSyncing; // Set while LLMotion::onActivate (and onDeactivate) are called for this controller.
bool mHidden; // The value of the last call to hidden().
bool mHaveVisibleSyncedMotions; // Set when we are synchronized with one or more motions of a controller that is not hidden.
//</singu>
LLFrameTimer mTimer;
F32 mPrevTimerElapsed;
F32 mAnimTime;
@@ -230,6 +254,26 @@ protected:
F32 mLastInterp;
U8 mJointSignature[2][LL_CHARACTER_MAX_JOINTS];
//<singu>
public:
// Internal administration for AISync.
void disable_syncing(void) { mDisableSyncing += 100; }
void enable_syncing(void) { mDisableSyncing -= 100; }
bool syncing_disabled(void) const { return mDisableSyncing >= 100; }
// Accessors needed for synchronization.
F32 getAnimTime(void) const { return mAnimTime; }
bool isHidden(void) const { return mHidden; }
// Called often. Should return false if we still need to keep updating our motions even if we're not visible.
bool hidden(bool not_visible) { if (mHidden != not_visible) toggle_hidden(); return !mHaveVisibleSyncedMotions; }
private:
void toggle_hidden(void);
void refresh_hidden(void);
void setHaveVisibleSyncedMotions(void) { mHaveVisibleSyncedMotions = true; }
//</singu>
};
//-----------------------------------------------------------------------------

View File

@@ -52,7 +52,7 @@ const F32 TORSO_ROT_FRACTION = 0.5f;
// LLTargetingMotion()
// Class Constructor
//-----------------------------------------------------------------------------
LLTargetingMotion::LLTargetingMotion(const LLUUID &id) : LLMotion(id)
LLTargetingMotion::LLTargetingMotion(LLUUID const& id, LLMotionController* controller) : AIMaskedMotion(id, controller, ANIM_AGENT_TARGET)
{
mCharacter = NULL;
mName = "targeting";
@@ -99,14 +99,6 @@ LLMotion::LLMotionInitStatus LLTargetingMotion::onInitialize(LLCharacter *charac
return STATUS_SUCCESS;
}
//-----------------------------------------------------------------------------
// LLTargetingMotion::onActivate()
//-----------------------------------------------------------------------------
BOOL LLTargetingMotion::onActivate()
{
return TRUE;
}
//-----------------------------------------------------------------------------
// LLTargetingMotion::onUpdate()
//-----------------------------------------------------------------------------
@@ -166,12 +158,4 @@ BOOL LLTargetingMotion::onUpdate(F32 time, U8* joint_mask)
return result;
}
//-----------------------------------------------------------------------------
// LLTargetingMotion::onDeactivate()
//-----------------------------------------------------------------------------
void LLTargetingMotion::onDeactivate()
{
}
// End

View File

@@ -48,11 +48,11 @@
// class LLTargetingMotion
//-----------------------------------------------------------------------------
class LLTargetingMotion :
public LLMotion
public AIMaskedMotion
{
public:
// Constructor
LLTargetingMotion(const LLUUID &id);
LLTargetingMotion(LLUUID const& id, LLMotionController* controller);
// Destructor
virtual ~LLTargetingMotion();
@@ -64,7 +64,7 @@ public:
// static constructor
// all subclasses must implement such a function and register it
static LLMotion *create(const LLUUID &id) { return new LLTargetingMotion(id); }
static LLMotion* create(LLUUID const& id, LLMotionController* controller) { return new LLTargetingMotion(id, controller); }
public:
//-------------------------------------------------------------------------
@@ -96,19 +96,11 @@ public:
// must return true to indicate success and be available for activation
virtual LLMotionInitStatus onInitialize(LLCharacter *character);
// called when a motion is activated
// must return TRUE to indicate success, or else
// it will be deactivated
virtual BOOL onActivate();
// called per time step
// must return TRUE while it is active, and
// must return FALSE when the motion is completed.
virtual BOOL onUpdate(F32 time, U8* joint_mask);
// called when a motion is deactivated
virtual void onDeactivate();
public:
LLCharacter *mCharacter;

View File

@@ -20,6 +20,7 @@ set(llcommon_SOURCE_FILES
aialert.cpp
aifile.cpp
aiframetimer.cpp
aisyncclient.cpp
aithreadid.cpp
imageids.cpp
indra_constants.cpp
@@ -59,7 +60,6 @@ set(llcommon_SOURCE_FILES
llformat.cpp
llframetimer.cpp
llheartbeat.cpp
llindraconfigfile.cpp
llinitparam.cpp
llinstancetracker.cpp
llliveappconfig.cpp
@@ -112,6 +112,7 @@ set(llcommon_HEADER_FILES
aifile.h
aiframetimer.h
airecursive.h
aisyncclient.h
aithreadid.h
aithreadsafe.h
bitpack.h
@@ -184,7 +185,6 @@ set(llcommon_HEADER_FILES
llheartbeat.h
llhttpstatuscodes.h
llindexedqueue.h
llindraconfigfile.h
llinitparam.h
llinstancetracker.h
llkeythrottle.h

View File

@@ -0,0 +1,698 @@
/**
* @file aisyncclient.cpp
*
* 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 <http://www.gnu.org/licenses/>.
*
* 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.
*
* 13/12/2013
* - Initial version, written by Aleric Inglewood @ SL
*/
/*
* AISyncClient : the base class of a client object (LLMotion) that needs to be informed
* of the state of other such objects and/or to poll a server object about the state of
* other such objects, in order to be and stay synchronized with those other objects.
* In the case of an LLMotion (animation), all clients would be started and stopped at
* the same time, as long as they are part of the same synchronization group (AISyncServer).
*
* AISyncKey: object that determines what synchronization group a client belongs to.
* When a new client is created, a new AISyncKey is created too, using information from
* the client, the current frame number and the current frame time. If two AISyncKey
* compare equal, using operator==(AISyncKey const& key1, AISyncKey const& key2),
* then the clients that created them need to be synchronized.
*
* AISyncServer: object that represents a group of clients that need to be synchronized:
* it's a wrapper around a std::list<AISyncClientData> with pointers to all the clients
* that need to be synchronized. It also stores the AISyncKey of the first (oldest) client
* that was added. Clients with keys that compare equal to that will be added.
* If a client is added with a synckeytype_t that is larger then it always replaces
* the existing key however.
*
* AISyncServerMap: A wrapper around std::list<boost::intrusive_ptr<AISyncServer> >
* that stores pointers to all currently existing AISyncServer objects. New entries
* are added at the end, so the oldest key is at the front.
*
* AISyncServerMap list + - - - - - - + - - - - - - + ... The AISyncServerMap is
* | | | a list with refcounted
* V V V pointers to AISyncServers.
* AISyncClient +--> AISyncServer
* | <--- list key ---> AISyncKey Each AISyncServer is a
* DerivedClient . list of normal pointers
* . AISyncClients and one
* <--- . pointer to a AISyncKey.
* Each AISyncClient is the
* base class of a DerivedClient
* and pointers back to the
* server with a refcounted
* pointer.
*
* A new client is passed to the AISyncServerMap to be stored in a new or existing AISyncServer
* object, using the key that the client produces. A boost::intrusive_ptr<AISyncServer> member
* of the client is set to point to this server.
*
* The lifetime of the server objects is determined by the intrusive_ptr objects that
* point to it: all the clients (which have an externally determined lifetime) and one
* pointer in the AISyncServerMap. However, regularly a check is done on all servers in
* the list to find expired servers: objects with keys older than two frames and older
* than 0.1 seconds; if such a server is found and it has zero or one client, then the
* client is unregistered and the pointer (and thus the server) removed from the
* AISyncServerMap. If it has two or more clients then the entry is kept until both
* clients are removed, which therefore can only be detected in intrusive_ptr_release
* which only has access to the server object. The server then is removed from the list
* by searching through it for the pointer to the server.
*/
#include "sys.h"
#include "aisyncclient.h"
#include <cmath>
#include <algorithm>
#include "debug.h"
bool operator==(AISyncKey const& key1, AISyncKey const& key2)
{
// Test if these keys match based on time.
if (std::abs((S32)(key1.mStartFrameCount - key2.mStartFrameCount)) > 1 &&
std::abs(key1.mFrameTimer.getStartTime() - key2.mFrameTimer.getStartTime()) >= sSyncKeyExpirationTime)
{
return false;
}
// Time matches, let the derived classes determine if they also match otherwise.
return key1.equals(key2);
}
#ifdef CWDEBUG
struct SyncEventSet {
synceventset_t mBits;
SyncEventSet(synceventset_t bits) : mBits(bits) { }
};
std::ostream& operator<<(std::ostream& os, SyncEventSet const& ses)
{
for (int b = sizeof(ses.mBits) * 8 - 1; b >= 0; --b)
{
int m = 1 << b;
os << ((ses.mBits & m) ? '1' : '0');
}
return os;
}
void print_clients(AISyncServer const* server, AISyncServer::client_list_t const& client_list)
{
Dout(dc::notice, "Clients of server " << server << ": ");
for (AISyncServer::client_list_t::const_iterator iter = client_list.begin(); iter != client_list.end(); ++ iter)
{
llassert(iter->mClientPtr->mReadyEvents == iter->mReadyEvents);
Dout(dc::notice, "-> " << iter->mClientPtr << " : " << SyncEventSet(iter->mReadyEvents));
}
}
#endif
void AISyncServerMap::register_client(AISyncClient* client, AISyncKey* new_key)
{
// client must always be a new client that has to be stored somewhere.
llassert(client->server() == NULL);
// Obviously the client can't be ready for anything when it isn't registered yet.
llassert(!client->mReadyEvents);
// Find if a server with this key already exists.
AISyncServer* server = NULL;
for (server_list_t::iterator iter = mServers.begin(); iter != mServers.end();)
{
boost::intrusive_ptr<AISyncServer>& server_ptr = *iter++; // Immediately increment iter because the call to unregister_last_client will erase it.
AISyncKey const& server_key(server_ptr->key());
if (server_key.is_older_than(*new_key)) // This means that the server key is expired: a new key will never match.
{
if (server_ptr->never_synced()) // This means that it contains one or zero clients and will never contain more.
{
// Get rid of this server.
server_ptr->unregister_last_client(); // This will cause the server to be deleted, and erased from mServers.
}
continue;
}
if (*new_key == server_key)
{
server = server_ptr.get();
// mServers stores new servers in strict order of the creation time of the keys,
// so once we find a server with a key that is equal, none of the remaining servers
// will have expired if they were never synced and we're done with the loop.
// Servers that synced might have been added later, but we don't unregister
// clients from those anyway because their sync partner might still show up.
break;
}
}
if (server)
{
// A server already exists.
// Keep the oldest key, unless this new key has a synckeytype_t that is larger!
if (new_key->getkeytype() > server->key().getkeytype())
{
server->swapkey(new_key);
}
delete new_key;
}
else
{
// Create a new server for this client. Transfers the ownership of the key allocation to the server.
server = new AISyncServer(new_key);
// Add it to mServers, before the last server that is younger then the new key.
server_list_t::iterator where = mServers.end(); // Insert the new server before 'where',
server_list_t::iterator new_where = where;
while (where != mServers.begin()) // unless there exists a server before that
{
--new_where;
if (new_key->getCreationTime() > (*new_where)->key().getCreationTime()) // and the new key is not younger then that,
{
break;
}
where = new_where; // then insert it before that element (etc).
}
// This method causes a single call to intrusive_ptr_add_ref and none to intrusive_ptr_release.
server_ptr_t server_ptr = server;
mServers.insert(where, server_ptr_t())->swap(server_ptr);
}
// Add the client to the server.
server->add(client);
}
#ifdef SYNC_TESTSUITE
void AISyncServer::sanity_check(void) const
{
synceventset_t ready_events = (synceventset_t)-1; // All clients are ready.
client_list_t::const_iterator client_iter = mClients.begin();
while (client_iter != mClients.end())
{
ready_events &= client_iter->mReadyEvents;
++client_iter;
}
synceventset_t pending_events = 0; // At least one client is ready.
client_iter = mClients.begin();
while (client_iter != mClients.end())
{
pending_events |= client_iter->mReadyEvents;
++client_iter;
}
llassert(ready_events == mReadyEvents);
llassert(pending_events == mPendingEvents);
}
#endif
void AISyncServer::add(AISyncClient* client)
{
#ifdef SYNC_TESTSUITE
sanity_check();
#endif
// The client can't already be ready when it isn't even added to a server yet.
llassert(!client->mReadyEvents);
synceventset_t old_ready_events = mReadyEvents;
// A new client is not ready for anything.
mReadyEvents = 0;
// Set mSynchronized if after adding client we'll have more than 1 client (that prevents the
// server from being deleted unless all clients are actually destructed or explicitly unregistered).
if (!mSynchronized && mClients.size() > 0)
{
mSynchronized = true;
}
// Trigger the existing clients to be not-ready anymore (if we were before).
trigger(old_ready_events);
// Only then add the new client (so that it didn't get not-ready trigger).
mClients.push_back(client);
client->mServer = this;
#ifdef SYNC_TESTSUITE
sanity_check();
#endif
}
void AISyncServer::remove(AISyncClient* client)
{
#ifdef SYNC_TESTSUITE
sanity_check();
#endif
client_list_t::iterator client_iter = mClients.begin();
synceventset_t remaining_ready_events = (synceventset_t)-1; // All clients are ready.
synceventset_t remaining_pending_events = 0; // At least one client is ready (waiting for the other clients thus).
client_list_t::iterator found_client = mClients.end();
while (client_iter != mClients.end())
{
if (client_iter->mClientPtr == client)
{
found_client = client_iter;
}
else
{
remaining_ready_events &= client_iter->mReadyEvents;
remaining_pending_events |= client_iter->mReadyEvents;
}
++client_iter;
}
llassert(found_client != mClients.end());
// This must be the same as client->mReadyEvents.
llassert(found_client->mReadyEvents == client->mReadyEvents);
mClients.erase(found_client);
synceventset_t old_ready_events = mReadyEvents;
mReadyEvents = remaining_ready_events;
mPendingEvents = remaining_pending_events;
trigger(old_ready_events);
client->mServer.reset();
client->deregistered();
#ifdef SYNC_TESTSUITE
sanity_check();
#endif
}
void AISyncServer::unregister_last_client(void)
{
#ifdef SYNC_TESTSUITE
sanity_check();
#endif
// This function may only be called for servers with exactly one client that was never (potentially) synchronized.
llassert(!mSynchronized && mClients.size() == 1);
AISyncClient* client = mClients.begin()->mClientPtr;
mClients.clear();
client->mServer.reset();
llassert(mReadyEvents == client->mReadyEvents);
llassert(mPendingEvents == mReadyEvents);
// No need to update mReadyEvents/mPendingEvents because the server is going to be deleted,
// but inform the client that is no longer has a server.
client->deregistered();
#ifdef SYNC_TESTSUITE
sanity_check();
#endif
}
void AISyncServer::trigger(synceventset_t old_ready_events)
{
// If event 1 changed, informat all clients about it.
if (((old_ready_events ^ mReadyEvents) & 1))
{
for (client_list_t::iterator client_iter = mClients.begin(); client_iter != mClients.end(); ++client_iter)
{
if ((mReadyEvents & 1))
{
client_iter->mClientPtr->event1_ready();
}
else
{
client_iter->mClientPtr->event1_not_ready();
}
}
}
}
void AISyncServer::ready(synceventset_t events, synceventset_t yesno, AISyncClient* client)
{
#ifdef SYNC_TESTSUITE
sanity_check();
#endif
synceventset_t added_events = events & yesno;
synceventset_t removed_events = events & ~yesno;
// Run over all clients to find the client and calculate the current state.
synceventset_t remaining_ready_events = (synceventset_t)-1; // All clients are ready.
synceventset_t remaining_pending_events = 0; // At least one client is ready (waiting for the other clients thus).
client_list_t::iterator found_client = mClients.end();
for (client_list_t::iterator client_iter = mClients.begin(); client_iter != mClients.end(); ++client_iter)
{
if (client_iter->mClientPtr == client)
{
found_client = client_iter;
}
else
{
remaining_ready_events &= client_iter->mReadyEvents;
remaining_pending_events |= client_iter->mReadyEvents;
}
}
llassert(mReadyEvents == (remaining_ready_events & found_client->mReadyEvents));
llassert(mPendingEvents == (remaining_pending_events | found_client->mReadyEvents));
found_client->mReadyEvents &= ~removed_events;
found_client->mReadyEvents |= added_events;
#ifdef SHOW_ASSERT
client->mReadyEvents = found_client->mReadyEvents;
#endif
synceventset_t old_ready_events = mReadyEvents;
mReadyEvents = remaining_ready_events & found_client->mReadyEvents;
mPendingEvents = remaining_pending_events | found_client->mReadyEvents;
trigger(old_ready_events);
#ifdef SYNC_TESTSUITE
sanity_check();
#endif
}
void intrusive_ptr_add_ref(AISyncServer* server)
{
server->mRefCount++;
}
void intrusive_ptr_release(AISyncServer* server)
{
llassert(server->mRefCount > 0);
server->mRefCount--;
if (server->mRefCount == 0)
{
delete server;
}
else if (server->mRefCount == 1)
{
// If the the last pointer to this server is in the the AISyncServerMap, then delete that too.
AISyncServerMap::instance().remove_server(server);
}
}
void AISyncServerMap::remove_server(AISyncServer* server)
{
for (server_list_t::iterator iter = mServers.begin(); iter != mServers.end(); ++iter)
{
if (server == iter->get())
{
mServers.erase(iter); // This causes server to be deleted too.
return;
}
}
// The server must be found: this function is only called from intrusive_ptr_release for servers
// with just a single server_ptr_t left, which must be the one in mServers (otherwise it wasn't
// even registered properly!)
llassert(false);
}
//=============================================================================
// SYNC_TESTSUITE
//=============================================================================
#ifdef SYNC_TESTSUITE
#include <iostream>
#include <iomanip>
#include <cstdlib>
#include <boost/io/ios_state.hpp>
//static
U32 LLFrameTimer::sFrameCount;
double innerloop_count = 0;
double LLFrameTimer::getCurrentTime()
{
return innerloop_count * 0.001;
}
template<synckeytype_t synckeytype>
class TestsuiteKey : public AISyncKey
{
private:
int mIndex;
public:
TestsuiteKey(int index) : mIndex(index) { }
int getIndex(void) const { return mIndex; }
// Virtual functions of AISyncKey.
public:
/*virtual*/ synckeytype_t getkeytype(void) const
{
// Return a unique identifier for this class, where the low 8 bits represent the syncgroup.
return synckeytype;
}
/*virtual*/ bool equals(AISyncKey const& key) const
{
synckeytype_t const theotherkey = (synckeytype_t)(synckeytype ^ 0x100);
switch (key.getkeytype())
{
case synckeytype:
{
// The other key is of the same type.
TestsuiteKey<synckeytype> const& test_key = static_cast<TestsuiteKey<synckeytype> const&>(key);
return (mIndex & 1) == (test_key.mIndex & 1);
}
case theotherkey:
{
TestsuiteKey<theotherkey> const& test_key = static_cast<TestsuiteKey<theotherkey> const&>(key);
return (mIndex & 2) == (test_key.getIndex() & 2);
}
default:
// The keys must be in the same syncgroup.
break;
}
return false;
}
};
template<synckeytype_t synckeytype>
class TestsuiteClient : public AISyncClient
{
// AISyncClient events.
protected:
/*virtual*/ AISyncKey* createSyncKey(void) const
{
return new TestsuiteKey<synckeytype>(mIndex);
}
private:
int mIndex;
bool mRequestedRegistered;
synceventset_t mRequestedReady;
bool mActualReady1;
public:
TestsuiteClient() : mIndex(-1), mRequestedRegistered(false), mRequestedReady(0), mActualReady1(false) { }
~TestsuiteClient() { if (is_registered()) this->ready(mRequestedReady, (synceventset_t)0); }
void setIndex(int index) { mIndex = index; }
protected:
/*virtual*/ void event1_ready(void)
{
#ifdef DEBUG_SYNCOUTPUT
Dout(dc::notice, "Calling TestsuiteClient<" << synckeytype << ">::event1_ready() (mIndex = " << mIndex << ") of client " << this);
#endif
llassert(!mActualReady1);
mActualReady1 = true;
}
/*virtual*/ void event1_not_ready(void)
{
#ifdef DEBUG_SYNCOUTPUT
Dout(dc::notice, "Calling TestsuiteClient<" << synckeytype << ">::event1_not_ready() (mIndex = " << mIndex << ") of client " << this);
#endif
llassert(mActualReady1);
mActualReady1 = false;
}
// This is called when the server expired and we're the only client on it.
/*virtual*/ void deregistered(void)
{
#ifdef DEBUG_SYNCOUTPUT
DoutEntering(dc::notice, "TestsuiteClient<" << synckeytype << ">::deregistered(), with this = " << this);
#endif
mRequestedRegistered = false;
mRequestedReady = 0;
mActualReady1 = false;
this->mReadyEvents = 0;
}
private:
bool is_registered(void) const { return this->server(); }
public:
void change_state(unsigned long r);
bool getRequestedRegistered(void) const { return mRequestedRegistered; }
synceventset_t getRequestedReady(void) const { return mRequestedReady; }
};
TestsuiteClient<synckeytype_test1a>* client1ap;
TestsuiteClient<synckeytype_test1b>* client1bp;
TestsuiteClient<synckeytype_test2a>* client2ap;
TestsuiteClient<synckeytype_test2b>* client2bp;
int const number_of_clients_per_syncgroup = 8;
template<synckeytype_t synckeytype>
void TestsuiteClient<synckeytype>::change_state(unsigned long r)
{
bool change_registered = r & 1;
r >>= 1;
synceventset_t toggle_events = r & 15;
r >>= 4;
if (change_registered)
{
if (mRequestedRegistered && !mRequestedReady)
{
mRequestedRegistered = false;
this->unregister_client();
}
}
else if (toggle_events)
{
mRequestedReady ^= toggle_events;
mRequestedRegistered = true;
this->ready(toggle_events, mRequestedReady & toggle_events);
}
llassert(mRequestedRegistered == is_registered());
AISyncServer* server = this->server();
if (mRequestedRegistered)
{
synceventset_t all_ready = synceventset_t(-1);
synceventset_t any_ready = 0;
int nr = 0;
for (int cl = 0; cl < number_of_clients_per_syncgroup; ++cl)
{
switch ((synckeytype & 0xff))
{
case syncgroup_test1:
{
if (client1ap[cl].server() == server)
{
if (client1ap[cl].getRequestedRegistered())
{
++nr;
all_ready &= client1ap[cl].getRequestedReady();
any_ready |= client1ap[cl].getRequestedReady();
}
}
if (client1bp[cl].server() == server)
{
if (client1bp[cl].getRequestedRegistered())
{
++nr;
all_ready &= client1bp[cl].getRequestedReady();
any_ready |= client1bp[cl].getRequestedReady();
}
}
break;
}
case syncgroup_test2:
{
if (client2ap[cl].server() == server)
{
if (client2ap[cl].getRequestedRegistered())
{
++nr;
all_ready &= client2ap[cl].getRequestedReady();
any_ready |= client2ap[cl].getRequestedReady();
}
}
if (client2bp[cl].server() == server)
{
if (client2bp[cl].getRequestedRegistered())
{
++nr;
all_ready &= client2bp[cl].getRequestedReady();
any_ready |= client2bp[cl].getRequestedReady();
}
}
break;
}
}
}
llassert(nr == server->getClients().size());
llassert(!!(all_ready & 1) == mActualReady1);
llassert(this->server()->events_with_all_clients_ready() == all_ready);
llassert(this->server()->events_with_at_least_one_client_ready() == any_ready);
llassert(nr == 0 || (any_ready & all_ready) == all_ready);
}
llassert(mRequestedReady == this->mReadyEvents);
}
int main()
{
Debug(libcw_do.on());
Debug(dc::notice.on());
Debug(libcw_do.set_ostream(&std::cout));
Debug(list_channels_on(libcw_do));
unsigned short seed16v[3] = { 0x1234, 0xfedc, 0x7091 };
for (int k = 0;; ++k)
{
std::cout << "Loop: " << k << "; SEED: " << std::hex << seed16v[0] << ", " << seed16v[1] << ", " << seed16v[2] << std::dec << std::endl;
++LLFrameTimer::sFrameCount;
seed48(seed16v);
seed16v[0] = lrand48() & 0xffff;
seed16v[1] = lrand48() & 0xffff;
seed16v[2] = lrand48() & 0xffff;
TestsuiteClient<synckeytype_test1a> client1a[number_of_clients_per_syncgroup];
TestsuiteClient<synckeytype_test1b> client1b[number_of_clients_per_syncgroup];
TestsuiteClient<synckeytype_test2a> client2a[number_of_clients_per_syncgroup];
TestsuiteClient<synckeytype_test2b> client2b[number_of_clients_per_syncgroup];
client1ap = client1a;
client1bp = client1b;
client2ap = client2a;
client2bp = client2b;
for (int i = 0; i < number_of_clients_per_syncgroup; ++i)
{
client1a[i].setIndex(i);
client1b[i].setIndex(i);
client2a[i].setIndex(i);
client2b[i].setIndex(i);
}
for (int j = 0; j < 1000000; ++j)
{
innerloop_count += 1;
#ifdef DEBUG_SYNCOUTPUT
Dout(dc::notice, "Innerloop: " << j);
#endif
unsigned long r = lrand48();
synckeytype_t keytype = (r & 1) ? ((r & 2) ? synckeytype_test1a : synckeytype_test1b) : ((r & 2) ? synckeytype_test2a : synckeytype_test2b);
r >>= 2;
int cl = (r & 255) % number_of_clients_per_syncgroup;
r >>= 8;
switch (keytype)
{
case synckeytype_test1a:
client1a[cl].change_state(r);
break;
case synckeytype_test1b:
client1b[cl].change_state(r);
break;
case synckeytype_test2a:
client2a[cl].change_state(r);
break;
case synckeytype_test2b:
client2b[cl].change_state(r);
break;
}
}
}
}
#endif

View File

@@ -0,0 +1,304 @@
/**
* @file aisyncclient.h
* @brief Declaration of AISyncClient.
*
* 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 <http://www.gnu.org/licenses/>.
*
* 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.
*
* 12/12/2013
* Initial version, written by Aleric Inglewood @ SL
*/
#ifndef AI_SYNC_CLIENT_H
#define AI_SYNC_CLIENT_H
#ifdef SYNC_TESTSUITE
/*
* To compile the testsuite, run:
*
* cd indra/llcommon
* g++ -O3 -DCWDEBUG -DSYNC_TESTSUITE -I. -I../cwdebug aisyncclient.cpp -lcwd
*/
#include <stdint.h>
#include <cassert>
typedef uint32_t U32;
typedef int32_t S32;
typedef uint64_t U64;
typedef float F32;
typedef double F64;
#define LL_COMMON_API
#define SHOW_ASSERT
#define ASSERT_ONLY_COMMA(...) , __VA_ARGS__
#define llassert assert
struct LLFrameTimer
{
double mStartTime;
double mExpiry;
static double getCurrentTime(void);
static U32 sFrameCount;
static U32 getFrameCount() { return sFrameCount; }
F64 getStartTime() const { return mStartTime; }
void reset(double expiration) { mStartTime = getCurrentTime(); mExpiry = mStartTime + expiration; }
bool hasExpired(void) const { return getCurrentTime() > mExpiry; }
};
template<typename T>
struct LLSingleton
{
static T sInstance;
static T& instance(void) { return sInstance; }
};
template<typename T>
T LLSingleton<T>::sInstance;
#else // !SYNC_TESTSUITE
#include "llsingleton.h"
#include "llframetimer.h"
#endif
#include <list>
#include <boost/intrusive_ptr.hpp>
//---------------------------------------------------------------------------------------------------------------------
// Keys with a different syncgroup are never equal (so they are never synchronized).
enum syncgroups
{
#ifdef SYNC_TESTSUITE
syncgroup_test1,
syncgroup_test2,
#else
syncgroup_motions, // Syncgroup used for animations.
#endif
syncgroup_size
};
// Each key type must return a unique identifier that exists of its syncgroup (the least significant 8 bit) plus a few bit to make it unique (bit 9 and higher).
enum synckeytype_t
{
#ifdef SYNC_TESTSUITE
synckeytype_test1a = 0x000 + syncgroup_test1,
synckeytype_test1b = 0x100 + syncgroup_test1,
synckeytype_test2a = 0x000 + syncgroup_test2,
synckeytype_test2b = 0x100 + syncgroup_test2,
#else
synckeytype_motion = syncgroup_motions // There is currently only one key type in the syncgroup_motions group: AISyncKeyMotion.
#endif
};
typedef U32 synceventset_t; // A mask where each bit represents a ready state.
static F32 const sSyncKeyExpirationTime = 0.25; // In seconds.
class LL_COMMON_API AISyncKey
{
private:
LLFrameTimer mFrameTimer; // This timer is started at the moment the sync key is created.
U32 mStartFrameCount; // The frame count at which the timer was started.
public:
// Constructor.
AISyncKey(AISyncKey const* from_key) : mStartFrameCount(from_key ? from_key->mStartFrameCount : LLFrameTimer::getFrameCount())
{
if (from_key)
{
mFrameTimer.copy(from_key->mFrameTimer);
}
else
{
mFrameTimer.reset(sSyncKeyExpirationTime);
}
}
// Destructor.
virtual ~AISyncKey() { }
// Return true if this key expired.
bool expired(void) const
{
// The key has expired when sSyncKeyExpirationTime seconds have elapsed AND at least two frames have passed.
return mFrameTimer.getFrameCount() > mStartFrameCount + 1 && mFrameTimer.hasExpired();
}
// Returns true if this object and key would not compare equal based on time because this object is too old.
bool is_older_than(AISyncKey const& key) const
{
return key.mStartFrameCount > mStartFrameCount + 1 && key.mFrameTimer.getStartTime() > mFrameTimer.getStartTime() + sSyncKeyExpirationTime;
}
// Return the creation time of this key (in number of seconds since application start).
F64 getCreationTime(void) const { return mFrameTimer.getStartTime(); }
// Returns true if the two keys match, meaning that they should be synchronized.
friend bool operator==(AISyncKey const& key1, AISyncKey const& key2);
// Returns an ID that uniquely identifies the derived type.
// Currently the only derived type is AISyncKeyMotion with ID synckeytype_motion.
virtual synckeytype_t getkeytype(void) const = 0;
// Returns true if the data in the derived objects match, meaning that they should be synchronized.
virtual bool equals(AISyncKey const& key) const = 0;
};
// Forward declaration.
class AISyncClient;
class AISyncServer;
LL_COMMON_API extern void intrusive_ptr_add_ref(AISyncServer* server);
LL_COMMON_API extern void intrusive_ptr_release(AISyncServer* server);
struct LL_COMMON_API AISyncClientData
{
AISyncClient* mClientPtr;
synceventset_t mReadyEvents;
AISyncClientData(AISyncClient* client) : mClientPtr(client), mReadyEvents(0) { }
};
class LL_COMMON_API AISyncServer
{
public:
typedef std::list<AISyncClientData> client_list_t;
private:
int mRefCount; // Number of boost::intrusive_ptr objects pointing to this object.
AISyncKey* mKey; // The key of the first client that was added.
client_list_t mClients; // A list with pointers to all registered clients.
bool mSynchronized; // Set when a server gets more than one client, and not reset anymore after that.
synceventset_t mReadyEvents; // 0xFFFFFFFF bitwise-AND-ed with all clients.
synceventset_t mPendingEvents; // The bitwise-OR of all clients.
public:
AISyncServer(AISyncKey* key) : mRefCount(0), mKey(key), mSynchronized(false), mReadyEvents((synceventset_t)-1), mPendingEvents(0) { }
~AISyncServer() { delete mKey; }
// Add a new client to this server.
void add(AISyncClient* client);
// Remove a client from this server.
void remove(AISyncClient* client);
// Return the key associated to this server (which is the key produced by the first client of the largest synckeytype_t that was added).
AISyncKey const& key(void) const { return *mKey; }
// Replace they key with another key (of larger synckeytype_t).
void swapkey(AISyncKey*& key_ptr) { AISyncKey* tmp = key_ptr; key_ptr = mKey; mKey = tmp; }
// Returns true if this server never had more than one client.
bool never_synced(void) const { return !mSynchronized; }
// Set readiness of all events at once.
void ready(synceventset_t events, synceventset_t yesno, AISyncClient* client);
// Unregister the (only) client because it's own its own and will never need synchronization.
void unregister_last_client(void);
// Return the events that all clients for.
synceventset_t events_with_all_clients_ready(void) const { return mReadyEvents; }
// Return events that at least one client is ready for.
synceventset_t events_with_at_least_one_client_ready(void) const { return mPendingEvents; }
// Return a list of all registered clients.
client_list_t const& getClients(void) const { return mClients; }
private:
// Call event1_ready() or event1_not_ready() on all clients if the least significant bit of mReadyEvents changed.
void trigger(synceventset_t old_ready_events);
#ifdef SYNC_TESTSUITE
void sanity_check(void) const;
#endif
private:
friend LL_COMMON_API void intrusive_ptr_add_ref(AISyncServer* server);
friend LL_COMMON_API void intrusive_ptr_release(AISyncServer* server);
};
class LL_COMMON_API AISyncServerMap : public LLSingleton<AISyncServerMap>
{
public:
typedef boost::intrusive_ptr<AISyncServer> server_ptr_t; // The type of a (stored) pointer to the server objects.
typedef std::list<server_ptr_t> server_list_t; // The type of the list with pointers to the server objects.
private:
server_list_t mServers; // A list with pointers to all server objects.
public:
// Find or create a server object that the client belongs to and store the client in it.
// If a new server is created, it is stored in mServers.
void register_client(AISyncClient* client, AISyncKey* new_key);
private:
friend LL_COMMON_API void intrusive_ptr_release(AISyncServer* server);
// Remove a server from the map, only called by intrusive_ptr_release when there is one pointer left;
// therefore, the server should not have any clients.
void remove_server(AISyncServer* server);
};
class LL_COMMON_API AISyncClient
{
private:
friend class AISyncServer;
boost::intrusive_ptr<AISyncServer> mServer; // The server this client was registered with, or NULL when unregistered.
public:
#ifdef SHOW_ASSERT
synceventset_t mReadyEvents;
AISyncClient(void) : mReadyEvents(0) { }
#endif
virtual ~AISyncClient() { llassert(!mServer); /* If this fails then you need to add unregister_client() to the top of the destructor of the derived class that implements deregistered(). */ }
virtual AISyncKey* createSyncKey(AISyncKey const* from_key = NULL) const = 0;
virtual void event1_ready(void) = 0;
virtual void event1_not_ready(void) = 0;
// Only client. Client was forcefully deregistered from expired server because it was the only client.
virtual void deregistered(void)
{
#ifdef SHOW_ASSERT
mReadyEvents = 0;
#endif
}
AISyncServer* server(void) const { return mServer.get(); }
// Add this client to a server with matching sync key. Optionally the server is first created.
void register_client(void) { AISyncServerMap::instance().register_client(this, createSyncKey()); }
// Remove this client from its server, if any.
void unregister_client(void) { if (mServer) mServer->remove(this); }
// Call 'ready' when you are ready (or not) to get a call to start().
// Returns true if that call was made (immediately), otherwise it may happen later.
// Set readiness of all events at once.
void ready(synceventset_t events, synceventset_t yesno)
{
if (!mServer)
{
register_client();
}
mServer->ready(events, yesno, this);
}
};
#endif

View File

@@ -47,6 +47,10 @@ public:
// Create an LLFrameTimer and start it. After creation it is running and in the state expired (hasExpired will return true).
LLFrameTimer(void) : mExpiry(0), mRunning(true), mPaused(false) { if (!sGlobalMutex) global_initialization(); setAge(0.0); }
//<singu>
void copy(LLFrameTimer const& timer) { mStartTime = timer.mStartTime; mExpiry = timer.mExpiry; mRunning = timer.mRunning; mPaused = timer.mPaused; }
//</singu>
// Atomic reads of static variables.
// Return the number of seconds since the start of the application.
@@ -142,6 +146,9 @@ public:
bool hasExpired() const { return getElapsedSeconds() >= mExpiry; }
F32 getElapsedTimeF32() const { llassert(mRunning); return mPaused ? (F32)mStartTime : (F32)(getElapsedSeconds() - mStartTime); }
bool getStarted() const { return mRunning; }
//<singu>
F64 getStartTime() const { llassert(!mPaused); return mStartTime; }
//</singu>
// return the seconds since epoch when this timer will expire.
F64 expiresAt() const;

View File

@@ -1,119 +0,0 @@
/**
* @file llindraconfigfile.cpp
*
*
* This class is an LLLiveFile that has config info for indra
* Currently only whether it's blacklisted
*
* $LicenseInfo:firstyear=2007&license=viewergpl$
*
* 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
* ("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 "llindraconfigfile.h"
#include "llfile.h"
#include "llsd.h"
#include "llsdserialize.h"
#include "llframetimer.h"
static std::string sConfigDir = "";
static const char indraConfigFileName[] = "indra.xml";
LLIndraConfigFile::LLIndraConfigFile()
: LLLiveFile(filename()),
mConfig(LLSD())
{
}
//static
void LLIndraConfigFile::initClass(const std::string& config_dir)
{
sConfigDir = config_dir;
llinfos << "LLIndraConfigFile::initClass config dir "
<< config_dir << "/" << indraConfigFileName << llendl;
}
LLSD LLIndraConfigFile::getConfig(const std::string& config_name)
{
if (sConfigDir.empty())
{
llerrs << "LLIndraConfigFile::initClass() not called" << llendl;
}
LLFrameTimer::updateFrameTime();
static LLIndraConfigFile the_file;
the_file.checkAndReload();
return the_file.mConfig[config_name];
}
std::string LLIndraConfigFile::filename()
{
std::ostringstream ostr;
ostr << sConfigDir
<< "/" << indraConfigFileName;
return ostr.str();
}
/* virtual */
bool LLIndraConfigFile::loadFile()
{
llinfos << "LLIndraConfigFile::loadFile: reading from "
<< filename() << llendl;
LLSD config;
{
llifstream file(filename());
if (file.is_open())
{
LLSDSerialize::fromXML(config, file);
}
if (config.isUndefined())
{
llinfos << "LLIndraConfigFile::loadFile: file missing, ill-formed,"
" or simply undefined; not changing the blacklist" << llendl;
return false;
}
}
if (config.isMap())
{
mConfig = config;
return true;
}
else
{
llwarns << "LLIndraConfigFile: " << indraConfigFileName << " expects a map; wrong format" << llendl;
return false;
}
}

View File

@@ -1,61 +0,0 @@
/**
* @file llindraconfigfile.h
* @brief manages configuration file for indra.xml
*
* $LicenseInfo:firstyear=2007&license=viewergpl$
*
* 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
* ("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_LLINDRACONFIGFILE_H
#define LL_LLINDRACONFIGFILE_H
#include "linden_common.h"
#include <string>
#include "lllivefile.h"
#include "llsd.h"
// To use, call LLIndraConfigFile::initClass(config_dir);
// Then whenever getConfig is called, it will check and reload automatically
class LLIndraConfigFile : public LLLiveFile
{
public:
LLIndraConfigFile();
static void initClass(const std::string& config_dir);
static LLSD getConfig(const std::string& config_name);
private:
static std::string filename();
protected:
/* virtual */ bool loadFile();
LLSD mConfig;
};
#endif //LL_LLINDRACONFIGFILE_H

View File

@@ -2,31 +2,25 @@
* @file camera.h
* @brief Legacy wrapper header.
*
* $LicenseInfo:firstyear=2000&license=viewergpl$
*
* Copyright (c) 2000-2009, Linden Research, Inc.
*
* $LicenseInfo:firstyear=2000&license=viewerlgpl$
* 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
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* 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
* 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.
*
* 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.
* 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
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/

View File

@@ -2,31 +2,25 @@
* @file coordframe.h
* @brief Legacy wrapper header.
*
* $LicenseInfo:firstyear=2000&license=viewergpl$
*
* Copyright (c) 2000-2009, Linden Research, Inc.
*
* $LicenseInfo:firstyear=2000&license=viewerlgpl$
* 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
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* 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
* 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.
*
* 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.
* 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
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/

View File

@@ -2,36 +2,28 @@
* @file llbbox.cpp
* @brief General purpose bounding box class (Not axis aligned)
*
* $LicenseInfo:firstyear=2001&license=viewergpl$
*
* Copyright (c) 2001-2010, Linden Research, Inc.
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* 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://secondlife.com/developers/opensource/gplv2
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* 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://secondlife.com/developers/opensource/flossexception
* 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.
*
* 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.
* 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
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*
*/
#include "linden_common.h"
// self include

View File

@@ -2,36 +2,28 @@
* @file llbbox.h
* @brief General purpose bounding box class
*
* $LicenseInfo:firstyear=2001&license=viewergpl$
*
* Copyright (c) 2001-2010, Linden Research, Inc.
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* 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://secondlife.com/developers/opensource/gplv2
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* 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://secondlife.com/developers/opensource/flossexception
* 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.
*
* 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.
* 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
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*
*/
#ifndef LL_BBOX_H
#define LL_BBOX_H

View File

@@ -2,31 +2,25 @@
* @file llbboxlocal.cpp
* @brief General purpose bounding box class (Not axis aligned).
*
* $LicenseInfo:firstyear=2001&license=viewergpl$
*
* Copyright (c) 2001-2009, Linden Research, Inc.
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* 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
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* 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
* 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.
*
* 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.
* 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
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/

View File

@@ -2,31 +2,25 @@
* @file llbboxlocal.h
* @brief General purpose bounding box class.
*
* $LicenseInfo:firstyear=2001&license=viewergpl$
*
* Copyright (c) 2001-2009, Linden Research, Inc.
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* 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
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* 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
* 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.
*
* 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.
* 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
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/

View File

@@ -2,31 +2,25 @@
* @file llcamera.cpp
* @brief Implementation of the LLCamera class.
*
* $LicenseInfo:firstyear=2000&license=viewergpl$
*
* Copyright (c) 2000-2009, Linden Research, Inc.
*
* $LicenseInfo:firstyear=2000&license=viewerlgpl$
* 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
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* 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
* 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.
*
* 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.
* 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
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -189,8 +183,30 @@ static const LLVector4a sFrustumScaler[] =
LLVector4a( 1, 1, 1) // 8 entries
};
S32 LLCamera::AABBInFrustum(const LLVector4a &center, const LLVector4a& radius)
bool LLCamera::isChanged()
{
bool changed = false;
for (U32 i = 0; i < mPlaneCount; i++)
{
U8 mask = mPlaneMask[i];
if (mask != 0xff && !changed)
{
changed = !mAgentPlanes[i].equal(mLastAgentPlanes[i]);
}
mLastAgentPlanes[i].set(mAgentPlanes[i]);
}
return changed;
}
S32 LLCamera::AABBInFrustum(const LLVector4a &center, const LLVector4a& radius, const LLPlane* planes)
{
if(!planes)
{
//use agent space
planes = mAgentPlanes;
}
U8 mask = 0;
bool result = false;
LLVector4a rscale, maxp, minp;
@@ -201,7 +217,7 @@ S32 LLCamera::AABBInFrustum(const LLVector4a &center, const LLVector4a& radius)
mask = mPlaneMask[i];
if (mask < PLANE_MASK_NUM)
{
const LLPlane& p(mAgentPlanes[i]);
const LLPlane& p(planes[i]);
p.getAt<3>(d);
rscale.setMul(radius, sFrustumScaler[mask]);
minp.setSub(center, rscale);
@@ -222,9 +238,21 @@ S32 LLCamera::AABBInFrustum(const LLVector4a &center, const LLVector4a& radius)
return result?1:2;
}
S32 LLCamera::AABBInFrustumNoFarClip(const LLVector4a& center, const LLVector4a& radius)
//exactly same as the function AABBInFrustum(...)
//except uses mRegionPlanes instead of mAgentPlanes.
S32 LLCamera::AABBInRegionFrustum(const LLVector4a& center, const LLVector4a& radius)
{
return AABBInFrustum(center, radius, mRegionPlanes);
}
S32 LLCamera::AABBInFrustumNoFarClip(const LLVector4a& center, const LLVector4a& radius, const LLPlane* planes)
{
if(!planes)
{
//use agent space
planes = mAgentPlanes;
}
U8 mask = 0;
bool result = false;
LLVector4a rscale, maxp, minp;
@@ -235,7 +263,7 @@ S32 LLCamera::AABBInFrustumNoFarClip(const LLVector4a& center, const LLVector4a&
mask = mPlaneMask[i];
if ((i != 5) && (mask < PLANE_MASK_NUM))
{
const LLPlane& p(mAgentPlanes[i]);
const LLPlane& p(planes[i]);
p.getAt<3>(d);
rscale.setMul(radius, sFrustumScaler[mask]);
minp.setSub(center, rscale);
@@ -256,6 +284,13 @@ S32 LLCamera::AABBInFrustumNoFarClip(const LLVector4a& center, const LLVector4a&
return result?1:2;
}
//exactly same as the function AABBInFrustumNoFarClip(...)
//except uses mRegionPlanes instead of mAgentPlanes.
S32 LLCamera::AABBInRegionFrustumNoFarClip(const LLVector4a& center, const LLVector4a& radius)
{
return AABBInFrustumNoFarClip(center, radius, mRegionPlanes);
}
int LLCamera::sphereInFrustumQuick(const LLVector3 &sphere_center, const F32 radius)
{
LLVector3 dist = sphere_center-mFrustCenter;
@@ -592,6 +627,47 @@ void LLCamera::calcAgentFrustumPlanes(LLVector3* frust)
}
}
//calculate regional planes from mAgentPlanes.
//vector "shift" is the vector of the region origin in the agent space.
void LLCamera::calcRegionFrustumPlanes(const LLVector3& shift, F32 far_clip_distance)
{
F32 far_w;
{
LLVector3 p = getOrigin();
LLVector3 n(mAgentPlanes[5][0], mAgentPlanes[5][1], mAgentPlanes[5][2]);
F32 dd = n * p;
if(dd + mAgentPlanes[5][3] < 0) //signed distance
{
far_w = -far_clip_distance - dd;
}
else
{
far_w = far_clip_distance - dd;
}
far_w += n * shift;
}
F32 d;
LLVector3 n;
for(S32 i = 0 ; i < 7; i++)
{
if (mPlaneMask[i] != 0xff)
{
n.setVec(mAgentPlanes[i][0], mAgentPlanes[i][1], mAgentPlanes[i][2]);
if(i != 5)
{
d = mAgentPlanes[i][3] + n * shift;
}
else
{
d = far_w;
}
mRegionPlanes[i].setVec(n, d);
}
}
}
void LLCamera::calculateFrustumPlanes(F32 left, F32 right, F32 top, F32 bottom)
{
LLVector3 a, b, c;

View File

@@ -2,31 +2,25 @@
* @file llcamera.h
* @brief Header file for the LLCamera class.
*
* $LicenseInfo:firstyear=2000&license=viewergpl$
*
* Copyright (c) 2000-2009, Linden Research, Inc.
*
* $LicenseInfo:firstyear=2000&license=viewerlgpl$
* 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
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* 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
* 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.
*
* 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.
* 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
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -55,7 +49,7 @@ const F32 MIN_FAR_PLANE = 0.2f;
// Min/Max FOV values for square views. Call getMin/MaxView to get extremes based on current aspect ratio.
static const F32 MIN_FIELD_OF_VIEW = 5.0f * DEG_TO_RAD;
static const F32 MAX_FIELD_OF_VIEW = 175.f * DEG_TO_RAD;
static const F32 MAX_FIELD_OF_VIEW = 320.f * DEG_TO_RAD;
// An LLCamera is an LLCoorFrame with a view frustum.
// This means that it has several methods for moving it around
@@ -128,6 +122,8 @@ public:
private:
LL_ALIGN_16(LLPlane mAgentPlanes[AGENT_PLANE_USER_CLIP_NUM]); //frustum planes in agent space a la gluUnproject (I'm a bastard, I know) - DaveP
LL_ALIGN_16(LLPlane mRegionPlanes[AGENT_PLANE_USER_CLIP_NUM]); //frustum planes in a local region space, derived from mAgentPlanes
LL_ALIGN_16(LLPlane mLastAgentPlanes[AGENT_PLANE_USER_CLIP_NUM]);
U8 mPlaneMask[PLANE_MASK_NUM]; // 8 for alignment
F32 mView; // angle between top and bottom frustum planes in radians.
@@ -156,6 +152,7 @@ public:
LLCamera(F32 vertical_fov_rads, F32 aspect_ratio, S32 view_height_in_pixels, F32 near_plane, F32 far_plane);
virtual ~LLCamera();
bool isChanged(); //check if mAgentPlanes changed since last frame.
void setUserClipPlane(const LLPlane& plane);
void disableUserClipPlane();
@@ -197,6 +194,7 @@ public:
// Return number of bytes copied.
size_t readFrustumFromBuffer(const char *buffer);
void calcAgentFrustumPlanes(LLVector3* frust);
void calcRegionFrustumPlanes(const LLVector3& shift, F32 far_clip_distance); //calculate regional planes from mAgentPlanes.
void ignoreAgentFrustumPlane(S32 idx);
// Returns 1 if partly in, 2 if fully in.
@@ -205,8 +203,10 @@ public:
S32 sphereInFrustum(const LLVector3 &center, const F32 radius) const;
S32 pointInFrustum(const LLVector3 &point) const { return sphereInFrustum(point, 0.0f); }
S32 sphereInFrustumFull(const LLVector3 &center, const F32 radius) const { return sphereInFrustum(center, radius); }
S32 AABBInFrustum(const LLVector4a& center, const LLVector4a& radius);
S32 AABBInFrustumNoFarClip(const LLVector4a& center, const LLVector4a& radius);
S32 AABBInFrustum(const LLVector4a& center, const LLVector4a& radius, const LLPlane* planes = NULL);
S32 AABBInRegionFrustum(const LLVector4a& center, const LLVector4a& radius);
S32 AABBInFrustumNoFarClip(const LLVector4a& center, const LLVector4a& radius, const LLPlane* planes = NULL);
S32 AABBInRegionFrustumNoFarClip(const LLVector4a& center, const LLVector4a& radius);
//does a quick 'n dirty sphere-sphere check
S32 sphereInFrustumQuick(const LLVector3 &sphere_center, const F32 radius);

View File

@@ -1,31 +1,25 @@
/**
* @file llplane.h
*
* $LicenseInfo:firstyear=2001&license=viewergpl$
*
* Copyright (c) 2001-2009, Linden Research, Inc.
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* 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
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* 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
* 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.
*
* 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.
* 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
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -100,6 +94,12 @@ public:
return mV.greaterEqual(LLVector4a::getZero()).getGatheredBits() & LLVector4Logical::MASK_XYZ;
}
//check if two planes are nearly same
bool equal(const LLPlane& p) const
{
return mV.equals4(p.mV);
}
private:
LL_ALIGN_16(LLVector4a mV);
} LL_ALIGN_POSTFIX(16);

View File

@@ -3,31 +3,25 @@
* @brief useful routines for quantizing floats to various length ints
* and back out again
*
* $LicenseInfo:firstyear=2001&license=viewergpl$
*
* Copyright (c) 2001-2009, Linden Research, Inc.
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* 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
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* 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
* 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.
*
* 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.
* 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
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/

View File

@@ -2,31 +2,25 @@
* @file llquaternion.cpp
* @brief LLQuaternion class implementation.
*
* $LicenseInfo:firstyear=2000&license=viewergpl$
*
* Copyright (c) 2000-2009, Linden Research, Inc.
*
* $LicenseInfo:firstyear=2000&license=viewerlgpl$
* 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
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* 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
* 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.
*
* 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.
* 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
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/

View File

@@ -2,31 +2,25 @@
* @file llquaternion.h
* @brief LLQuaternion class header file.
*
* $LicenseInfo:firstyear=2000&license=viewergpl$
*
* Copyright (c) 2000-2009, Linden Research, Inc.
*
* $LicenseInfo:firstyear=2000&license=viewerlgpl$
* 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
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* 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
* 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.
*
* 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.
* 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
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/

View File

@@ -1,31 +1,26 @@
/**
* @file llrect.cpp
* @brief LLRect class implementation
*
* $LicenseInfo:firstyear=2001&license=viewergpl$
*
* Copyright (c) 2001-2009, Linden Research, Inc.
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* 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
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* 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
* 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.
*
* 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.
* 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
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/

View File

@@ -4,31 +4,25 @@
* @date 2006-05-24
* @brief Implementation of classes, functions, etc, for using structured data.
*
* $LicenseInfo:firstyear=2006&license=viewergpl$
*
* Copyright (c) 2006-2009, Linden Research, Inc.
*
* $LicenseInfo:firstyear=2006&license=viewerlgpl$
* 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
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* 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
* 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.
*
* 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.
* 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
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/

View File

@@ -4,36 +4,28 @@
* @date 2009-05-19
* @brief Utility classes, functions, etc, for using structured data with math classes.
*
* $LicenseInfo:firstyear=2009&license=viewergpl$
*
* Copyright (c) 2009-2010, Linden Research, Inc.
*
* $LicenseInfo:firstyear=2009&license=viewerlgpl$
* 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://secondlife.com/developers/opensource/gplv2
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* 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://secondlife.com/developers/opensource/flossexception
* 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.
*
* 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.
* 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
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*
*/
#ifndef LL_LLSDUTIL_MATH_H
#define LL_LLSDUTIL_MATH_H

View File

@@ -3,31 +3,25 @@
* @author Andrew Meadows
* @brief Simple line class that can compute nearest approach between two lines
*
* $LicenseInfo:firstyear=2007&license=viewergpl$
*
* Copyright (c) 2007-2009, Linden Research, Inc.
*
* $LicenseInfo:firstyear=2007&license=viewerlgpl$
* 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
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* 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
* 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.
*
* 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.
* 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
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/

View File

@@ -4,31 +4,25 @@
* @author Andrew Meadows
* @brief Simple sphere implementation for basic geometric operations
*
* $LicenseInfo:firstyear=2007&license=viewergpl$
*
* Copyright (c) 2007-2009, Linden Research, Inc.
*
* $LicenseInfo:firstyear=2007&license=viewerlgpl$
* 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
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* 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
* 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.
*
* 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.
* 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
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/

View File

@@ -1,31 +1,25 @@
/**
* @file lltreenode.h
*
* $LicenseInfo:firstyear=2005&license=viewergpl$
*
* Copyright (c) 2005-2009, Linden Research, Inc.
*
* $LicenseInfo:firstyear=2005&license=viewerlgpl$
* 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
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* 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
* 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.
*
* 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.
* 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
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -36,6 +30,7 @@
#include "xform.h"
#include "llpointer.h"
#include "llrefcount.h"
#include <vector>
template <class T> class LLTreeNode;
@@ -62,7 +57,14 @@ public:
virtual bool remove(T* data);
virtual void notifyRemoval(T* data);
virtual U32 getListenerCount() { return mListeners.size(); }
virtual LLTreeListener<T>* getListener(U32 index) const { return mListeners[index]; }
virtual LLTreeListener<T>* getListener(U32 index) const
{
if(index < mListeners.size())
{
return mListeners[index];
}
return NULL;
}
virtual void addListener(LLTreeListener<T>* listener) { mListeners.push_back(listener); }
protected:

View File

@@ -85,6 +85,7 @@ public:
}
// Copy words 16-byte blocks from src to dst. Source and destination must not overlap.
// Source and dest must be 16-byte aligned and size must be multiple of 16.
static void memcpyNonAliased16(F32* __restrict dst, const F32* __restrict src, size_t bytes);
////////////////////////////////////

View File

@@ -1093,8 +1093,6 @@ BOOL LLProfile::generate(const LLProfileParams& params, BOOL path_open,F32 detai
}
}
//genNormals(params);
return TRUE;
}
@@ -2373,7 +2371,7 @@ bool LLVolume::unpackVolumeFaces(std::istream& is, S32 size)
LLSD mdl;
if (!unzip_llsd(mdl, is, size))
{
LL_DEBUGS("MeshStreaming") << "Failed to unzip LLSD blob for LoD, will probably fetch from sim again." << llendl;
LL_DEBUGS("MeshStreaming") << "Failed to unzip LLSD blob for LoD, will probably fetch from sim again." << LL_ENDL;
return false;
}
@@ -5614,7 +5612,6 @@ BOOL LLVolumeFace::createCap(LLVolume* volume, BOOL partial_build)
else
{
resizeVertices(num_vertices);
if (!partial_build)
{
resizeIndices(num_indices);
@@ -5719,6 +5716,7 @@ BOOL LLVolumeFace::createCap(LLVolume* volume, BOOL partial_build)
cuv = (min_uv + max_uv)*0.5f;
VertexData vd;
vd.setPosition(*mCenter);
vd.mTexCoord = cuv;
@@ -6767,7 +6765,7 @@ BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build)
return TRUE;
}
//adapted from Lengyel, Eric. <EFBFBD>Computing Tangent Space Basis Vectors for an Arbitrary Mesh<EFBFBD>. Terathon Software 3D Graphics Library, 2001. http://www.terathon.com/code/tangent.html
//adapted from Lengyel, Eric. "Computing Tangent Space Basis Vectors for an Arbitrary Mesh". Terathon Software 3D Graphics Library, 2001. http://www.terathon.com/code/tangent.html
void CalculateTangentArray(U32 vertexCount, const LLVector4a *vertex, const LLVector4a *normal,
const LLVector2 *texcoord, U32 triangleCount, const U16* index_array, LLVector4a *tangent)
{

View File

@@ -934,6 +934,7 @@ P(fetchScriptLimitsRegionDetailsResponder);
P(fetchScriptLimitsRegionInfoResponder);
P(fetchScriptLimitsRegionSummaryResponder);
P(fnPtrResponder);
P(floaterPermsResponder);
P2(gamingDataReceived, transfer_22s_connect_10s);
P2(groupMemberDataResponder, transfer_300s);
P2(groupProposalBallotResponder, transfer_300s);
@@ -965,7 +966,6 @@ P(newAgentInventoryVariablePriceResponder);
P(objectCostResponder);
P(objectLinksetsResponder);
P(physicsFlagsResponder);
P(placeAvatarTeleportResponder);
P(productInfoRequestResponder);
P(regionResponder);
P(remoteParcelRequestResponder);

View File

@@ -237,13 +237,23 @@ void LLHTTPClient::request(
req->run(parent, new_parent_state, parent != NULL, true, default_engine);
}
void LLHTTPClient::getByteRange(std::string const& url, S32 offset, S32 bytes, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug))
bool LLHTTPClient::getByteRange(std::string const& url, AIHTTPHeaders& headers, S32 offset, S32 bytes, ResponderPtr responder/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug))
{
if(offset > 0 || bytes > 0)
try
{
headers.addHeader("Range", llformat("bytes=%d-%d", offset, offset + bytes - 1));
if (offset > 0 || bytes > 0)
{
int const range_end = offset + bytes - 1;
char const* const range_format = (range_end >= HTTP_REQUESTS_RANGE_END_MAX) ? "bytes=%d-" : "bytes=%d-%d";
headers.addHeader("Range", llformat(range_format, offset, range_end));
}
request(url, HTTP_GET, NULL, responder, headers, NULL/*,*/ DEBUG_CURLIO_PARAM(debug));
}
request(url, HTTP_GET, NULL, responder, headers, NULL/*,*/ DEBUG_CURLIO_PARAM(debug));
catch(AICurlNoEasyHandle const&)
{
return false;
}
return true;
}
void LLHTTPClient::head(std::string const& url, ResponderHeadersOnly* responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug))

View File

@@ -55,6 +55,17 @@ typedef struct _xmlrpc_request* XMLRPC_REQUEST;
typedef struct _xmlrpc_value* XMLRPC_VALUE;
extern AIEngine gMainThreadEngine;
// In Viewer 3 this definition is in indra/newview/lltexturefetch.cpp,
// but we need it in two .cpp files, so it's moved here.
//
// BUG-3323/SH-4375
// *NOTE: This is a heuristic value. Texture fetches have a habit of using a
// value of 32MB to indicate 'get the rest of the image'. Certain ISPs and
// network equipment get confused when they see this in a Range: header. So,
// if the request end is beyond this value, we issue an open-ended Range:
// request (e.g. 'Range: <start>-') which seems to fix the problem.
static const S32 HTTP_REQUESTS_RANGE_END_MAX = 20000000;
// Output parameter of AICurlPrivate::CurlEasyRequest::getResult.
// Used in XMLRPCResponder.
struct AITransferInfo {
@@ -133,6 +144,14 @@ public:
public:
typedef boost::shared_ptr<LLBufferArray> buffer_ptr_t;
/**
* @brief return true if the status code indicates success.
*/
static bool isGoodStatus(U32 status)
{
return((200 <= status) && (status < 300));
}
protected:
ResponderBase(void);
virtual ~ResponderBase();
@@ -452,9 +471,9 @@ public:
static void head(std::string const& url, ResponderHeadersOnly* responder/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off))
{ AIHTTPHeaders headers; head(url, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug)); }
static void getByteRange(std::string const& url, S32 offset, S32 bytes, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off));
static void getByteRange(std::string const& url, S32 offset, S32 bytes, ResponderPtr responder/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off))
{ AIHTTPHeaders headers; getByteRange(url, offset, bytes, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug)); }
static bool getByteRange(std::string const& url, AIHTTPHeaders& headers, S32 offset, S32 bytes, ResponderPtr responder/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off));
static bool getByteRange(std::string const& url, S32 offset, S32 bytes, ResponderPtr responder/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off))
{ AIHTTPHeaders headers; return getByteRange(url, headers, offset, bytes, responder/*,*/ DEBUG_CURLIO_PARAM(debug)); }
static void get(std::string const& url, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off));
static void get(std::string const& url, ResponderPtr responder/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off))

View File

@@ -28,7 +28,7 @@
#include "llmodel.h"
#include "llmemory.h"
#include "LLConvexDecomposition.h"
#include "llconvexdecomposition.h"
#include "llsdserialize.h"
#include "llvector4a.h"
#include "llmatrix4a.h"
@@ -169,6 +169,7 @@ LLModel::EModelStatus load_face_from_dom_triangles(std::vector<LLVolumeFace>& fa
if ( !get_dom_sources(inputs, pos_offset, tc_offset, norm_offset, idx_stride, pos_source, tc_source, norm_source) || !pos_source )
{
llwarns << "Could not find dom sources for basic geo data; invalid model." << llendl;
return LLModel::BAD_ELEMENT;
}
@@ -189,27 +190,78 @@ LLModel::EModelStatus load_face_from_dom_triangles(std::vector<LLVolumeFace>& fa
LLVolumeFace::VertexMapData::PointMap point_map;
for (U32 i = 0; i < idx.getCount(); i += idx_stride)
U32 index_count = idx.getCount();
U32 vertex_count = pos_source ? v.getCount() : 0;
U32 tc_count = tc_source ? tc.getCount() : 0;
U32 norm_count = norm_source ? n.getCount() : 0;
for (U32 i = 0; i < index_count; i += idx_stride)
{
LLVolumeFace::VertexData cv;
if (pos_source)
{
// guard against model data specifiying out of range indices or verts
//
if (((i + pos_offset) > index_count)
|| ((idx[i+pos_offset]*3+2) > vertex_count))
{
llwarns << "Out of range index data; invalid model." << llendl;
return LLModel::BAD_ELEMENT;
}
cv.setPosition(LLVector4a(v[idx[i+pos_offset]*3+0],
v[idx[i+pos_offset]*3+1],
v[idx[i+pos_offset]*3+2]));
if (!cv.getPosition().isFinite3())
{
llwarns << "Nan positional data, invalid model." << llendl;
return LLModel::BAD_ELEMENT;
}
}
if (tc_source)
{
// guard against model data specifiying out of range indices or tcs
//
if (((i + tc_offset) > index_count)
|| ((idx[i+tc_offset]*2+1) > tc_count))
{
llwarns << "Out of range TC indices." << llendl;
return LLModel::BAD_ELEMENT;
}
cv.mTexCoord.setVec(tc[idx[i+tc_offset]*2+0],
tc[idx[i+tc_offset]*2+1]);
if (!cv.mTexCoord.isFinite())
{
llwarns << "Found NaN while loading tex coords from DAE-Model, invalid model." << llendl;
return LLModel::BAD_ELEMENT;
}
}
if (norm_source)
{
// guard against model data specifiying out of range indices or norms
//
if (((i + norm_offset) > index_count)
|| ((idx[i+norm_offset]*3+2) > norm_count))
{
llwarns << "Found out of range norm indices, invalid model." << llendl;
return LLModel::BAD_ELEMENT;
}
cv.setNormal(LLVector4a(n[idx[i+norm_offset]*3+0],
n[idx[i+norm_offset]*3+1],
n[idx[i+norm_offset]*3+2]));
if (!cv.getNormal().isFinite3())
{
llwarns << "Found NaN while loading normals from DAE-Model, invalid model." << llendl;
return LLModel::BAD_ELEMENT;
}
}
BOOL found = FALSE;
@@ -264,7 +316,7 @@ LLModel::EModelStatus load_face_from_dom_triangles(std::vector<LLVolumeFace>& fa
LLVolumeFace& new_face = *face_list.rbegin();
if (!norm_source)
{
//l_aligned_free_16(new_face.mNormals);
//ll_aligned_free_16(new_face.mNormals);
new_face.mNormals = NULL;
}
@@ -336,6 +388,7 @@ LLModel::EModelStatus load_face_from_dom_polylist(std::vector<LLVolumeFace>& fac
if (!get_dom_sources(inputs, pos_offset, tc_offset, norm_offset, idx_stride, pos_source, tc_source, norm_source))
{
llwarns << "Could not get DOM sources for basic geo data, invalid model." << llendl;
return LLModel::BAD_ELEMENT;
}
@@ -367,6 +420,11 @@ LLModel::EModelStatus load_face_from_dom_polylist(std::vector<LLVolumeFace>& fac
LLVolumeFace::VertexMapData::PointMap point_map;
U32 index_count = idx.getCount();
U32 vertex_count = pos_source ? v.getCount() : 0;
U32 tc_count = tc_source ? tc.getCount() : 0;
U32 norm_count = norm_source ? n.getCount() : 0;
U32 cur_idx = 0;
for (U32 i = 0; i < vcount.getCount(); ++i)
{ //for each polygon
@@ -379,22 +437,68 @@ LLModel::EModelStatus load_face_from_dom_polylist(std::vector<LLVolumeFace>& fac
if (pos_source)
{
// guard against model data specifiying out of range indices or verts
//
if (((cur_idx + pos_offset) > index_count)
|| ((idx[cur_idx+pos_offset]*3+2) > vertex_count))
{
llwarns << "Out of range position indices, invalid model." << llendl;
return LLModel::BAD_ELEMENT;
}
cv.getPosition().set(v[idx[cur_idx+pos_offset]*3+0],
v[idx[cur_idx+pos_offset]*3+1],
v[idx[cur_idx+pos_offset]*3+2]);
if (!cv.getPosition().isFinite3())
{
llwarns << "Found NaN while loading positions from DAE-Model, invalid model." << llendl;
return LLModel::BAD_ELEMENT;
}
}
if (tc_source)
{
// guard against model data specifiying out of range indices or tcs
//
if (((cur_idx + tc_offset) > index_count)
|| ((idx[cur_idx+tc_offset]*2+1) > tc_count))
{
llwarns << "Out of range TC indices, invalid model." << llendl;
return LLModel::BAD_ELEMENT;
}
cv.mTexCoord.setVec(tc[idx[cur_idx+tc_offset]*2+0],
tc[idx[cur_idx+tc_offset]*2+1]);
if (!cv.mTexCoord.isFinite())
{
llwarns << "Found NaN while loading tex coords from DAE-Model, invalid model." << llendl;
return LLModel::BAD_ELEMENT;
}
}
if (norm_source)
{
// guard against model data specifiying out of range indices or norms
//
if (((cur_idx + norm_offset) > index_count)
|| ((idx[cur_idx+norm_offset]*3+2) > norm_count))
{
llwarns << "Out of range norm indices, invalid model." << llendl;
return LLModel::BAD_ELEMENT;
}
cv.getNormal().set(n[idx[cur_idx+norm_offset]*3+0],
n[idx[cur_idx+norm_offset]*3+1],
n[idx[cur_idx+norm_offset]*3+2]);
if (!cv.getNormal().isFinite3())
{
llwarns << "Found NaN while loading normals from DAE-Model, invalid model." << llendl;
return LLModel::BAD_ELEMENT;
}
}
cur_idx += idx_stride;
@@ -561,6 +665,7 @@ LLModel::EModelStatus load_face_from_dom_polygons(std::vector<LLVolumeFace>& fac
domVertices* vertices = (domVertices*) elem.cast();
if (!vertices)
{
llwarns << "Could not find vertex source, invalid model." << llendl;
return LLModel::BAD_ELEMENT;
}
domInputLocal_Array& v_inp = vertices->getInput_array();
@@ -574,6 +679,7 @@ LLModel::EModelStatus load_face_from_dom_polygons(std::vector<LLVolumeFace>& fac
domSource* src = (domSource*) elem.cast();
if (!src)
{
llwarns << "Could not find DOM source, invalid model." << llendl;
return LLModel::BAD_ELEMENT;
}
v = &(src->getFloat_array()->getValue());
@@ -589,6 +695,7 @@ LLModel::EModelStatus load_face_from_dom_polygons(std::vector<LLVolumeFace>& fac
domSource* src = (domSource*) elem.cast();
if (!src)
{
llwarns << "Could not find DOM source, invalid model." << llendl;
return LLModel::BAD_ELEMENT;
}
n = &(src->getFloat_array()->getValue());
@@ -601,6 +708,7 @@ LLModel::EModelStatus load_face_from_dom_polygons(std::vector<LLVolumeFace>& fac
domSource* src = (domSource*) elem.cast();
if (!src)
{
llwarns << "Could not find DOM source, invalid model." << llendl;
return LLModel::BAD_ELEMENT;
}
t = &(src->getFloat_array()->getValue());
@@ -635,6 +743,12 @@ LLModel::EModelStatus load_face_from_dom_polygons(std::vector<LLVolumeFace>& fac
vert.getPosition().set(v->get(v_idx),
v->get(v_idx+1),
v->get(v_idx+2));
if (!vert.getPosition().isFinite3())
{
llwarns << "Found NaN while loading position data from DAE-Model, invalid model." << llendl;
return LLModel::BAD_ELEMENT;
}
}
//bounds check n and t lookups because some FBX to DAE converters
@@ -647,6 +761,12 @@ LLModel::EModelStatus load_face_from_dom_polygons(std::vector<LLVolumeFace>& fac
vert.getNormal().set(n->get(n_idx),
n->get(n_idx+1),
n->get(n_idx+2));
if (!vert.getNormal().isFinite3())
{
llwarns << "Found NaN while loading normals from DAE-Model, invalid model." << llendl;
return LLModel::BAD_ELEMENT;
}
}
else
{
@@ -660,6 +780,12 @@ LLModel::EModelStatus load_face_from_dom_polygons(std::vector<LLVolumeFace>& fac
t_idx = llclamp(t_idx, (U32) 0, (U32) t->getCount());
vert.mTexCoord.setVec(t->get(t_idx),
t->get(t_idx+1));
if (!vert.mTexCoord.isFinite())
{
llwarns << "Found NaN while loading tex coords from DAE-Model, invalid model." << llendl;
return LLModel::BAD_ELEMENT;
}
}
else
{
@@ -1592,6 +1718,7 @@ LLSD LLModel::writeModel(
mdl[model_names[idx]][i]["TexCoord0Domain"]["Max"] = max_tc.getValue();
mdl[model_names[idx]][i]["TexCoord0"] = tc;
}
mdl[model_names[idx]][i]["TriangleList"] = indices;
if (skinning)

View File

@@ -272,7 +272,7 @@ void LLButton::onCommit()
LLUICtrl::onCommit();
}
/*boost::signals2::connection LLButton::setClickedCallback(const CommitCallbackParam& cb)
boost::signals2::connection LLButton::setClickedCallback(const CommitCallbackParam& cb)
{
return setClickedCallback(initCommitCallback(cb));
}
@@ -287,7 +287,7 @@ boost::signals2::connection LLButton::setMouseUpCallback(const CommitCallbackPar
boost::signals2::connection LLButton::setHeldDownCallback(const CommitCallbackParam& cb)
{
return setHeldDownCallback(initCommitCallback(cb));
}*/
}
boost::signals2::connection LLButton::setClickedCallback( const commit_signal_t::slot_type& cb )

View File

@@ -116,10 +116,10 @@ public:
void setSelectedLabelColor( const LLColor4& c ) { mSelectedLabelColor = c; }
/*boost::signals2::connection setClickedCallback(const CommitCallbackParam& cb);
boost::signals2::connection setClickedCallback(const CommitCallbackParam& cb);
boost::signals2::connection setMouseDownCallback(const CommitCallbackParam& cb);
boost::signals2::connection setMouseUpCallback(const CommitCallbackParam& cb);
boost::signals2::connection setHeldDownCallback(const CommitCallbackParam& cb);*/
boost::signals2::connection setHeldDownCallback(const CommitCallbackParam& cb);
boost::signals2::connection setClickedCallback( const commit_signal_t::slot_type& cb ); // mouse down and up within button
boost::signals2::connection setMouseDownCallback( const commit_signal_t::slot_type& cb );

View File

@@ -921,6 +921,23 @@ void LLLineEditor::addChar(const llwchar uni_char)
mText.insert(getCursor(), w_buf);
setCursor(getCursor() + 1);
if (!mReadOnly && mAutoreplaceCallback != NULL)
{
// autoreplace the text, if necessary
S32 replacement_start;
S32 replacement_length;
LLWString replacement_string;
S32 new_cursor_pos = getCursor();
mAutoreplaceCallback(replacement_start, replacement_length, replacement_string, new_cursor_pos, mText);
if (replacement_length > 0 || !replacement_string.empty())
{
mText.erase(replacement_start, replacement_length);
mText.insert(replacement_start, replacement_string);
setCursor(new_cursor_pos);
}
}
}
else
{

View File

@@ -167,6 +167,10 @@ public:
virtual BOOL isSpellDirty() const { return mText.getString() != mPrevSpelledText; } // Returns TRUE if user changed value at all
virtual void resetSpellDirty() { mPrevSpelledText = mText.getString(); } // Clear dirty state
typedef boost::function<void(S32&, S32&, LLWString&, S32&, const LLWString&)> autoreplace_callback_t;
autoreplace_callback_t mAutoreplaceCallback;
void setAutoreplaceCallback(autoreplace_callback_t cb) { mAutoreplaceCallback = cb; }
// assumes UTF8 text
virtual void setValue(const LLSD& value ) { setText(value.asString()); }
virtual LLSD getValue() const { return LLSD(getText()); }

File diff suppressed because it is too large Load Diff

View File

@@ -79,16 +79,6 @@ typedef void (*label_callback)(std::string&,void*);
class LLMenuItemGL : public LLUICtrl
{
public:
// static functions to control the global color scheme.
/*static void setEnabledColor( const LLColor4& color ) { sEnabledColor = color; }
static const LLColor4& getEnabledColor() { return sEnabledColor; }
static void setDisabledColor( const LLColor4& color ) { sDisabledColor = color; }
static const LLColor4& getDisabledColor() { return sDisabledColor; }
static void setHighlightBGColor( const LLColor4& color ) { sHighlightBackground = color; }
static const LLColor4& getHighlightBGColor() { return sHighlightBackground; }
static void setHighlightFGColor( const LLColor4& color ) { sHighlightForeground = color; }
static const LLColor4& getHighlightFGColor() { return sHighlightForeground; }*/
LLMenuItemGL( const std::string& name, const std::string& label, KEY key = KEY_NONE, MASK = MASK_NONE );
virtual ~LLMenuItemGL();
@@ -148,7 +138,7 @@ public:
// lead to visual errors if the state of the object changes
// without the knowledge of the menu item. For example, if a
// boolean being watched is changed outside of the menu item's
// doIt() function, the draw buffer will not be updated and will
// onCommit() function, the draw buffer will not be updated and will
// reflect the wrong value. If this ever becomes an issue, there
// are ways to fix this.
// Returns the enabled state of the item.
@@ -157,8 +147,7 @@ public:
// for branching menu items, bring sub menus up to root level of menu hierarchy
virtual void updateBranchParent( LLView* parentp ){};
// doIt() - do the primary funcationality of the menu item.
virtual void doIt( void );
virtual void onCommit( void );
virtual void setHighlight( BOOL highlight );
virtual BOOL getHighlight() const { return mHighlight; }
@@ -190,6 +179,7 @@ protected:
// the current accelerator key and mask to the provided string.
void appendAcceleratorString( std::string& st ) const;
protected:
KEY mAcceleratorKey;
MASK mAcceleratorMask;
// mLabel contains the actual label specified by the user.
@@ -245,15 +235,14 @@ public:
virtual std::string getType() const { return "separator"; }
// doIt() - do the primary funcationality of the menu item.
virtual void doIt( void ) {}
virtual void onCommit( void ) {}
virtual void draw( void );
virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask);
virtual BOOL handleHover(S32 x, S32 y, MASK mask);
/*virtual*/ void draw( void );
/*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask);
/*virtual*/ BOOL handleMouseUp(S32 x, S32 y, MASK mask);
/*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask);
virtual U32 getNominalHeight( void ) const;
/*virtual*/ U32 getNominalHeight( void ) const;
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -323,8 +312,7 @@ public:
// called to rebuild the draw label
virtual void buildDrawLabel( void );
// doIt() - do the primary funcationality of the menu item.
virtual void doIt( void );
virtual void onCommit( void );
virtual BOOL handleAcceleratorKey(KEY key, MASK mask);
virtual BOOL handleKeyHere(KEY key, MASK mask);
@@ -419,8 +407,8 @@ public:
// called to rebuild the draw label
virtual void buildDrawLabel( void );
// doIt() - do the primary funcationality of the menu item.
virtual void doIt( void );
// onCommit() - do the primary funcationality of the menu item.
virtual void onCommit( void );
// LLView Functionality
//virtual void draw( void );
@@ -429,7 +417,6 @@ private:
BOOL* mToggle;
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Class LLMenuGL
//
@@ -453,6 +440,15 @@ public:
static const std::string ARROW_UP;
static const std::string ARROW_DOWN;
// for scrollable menus
typedef enum e_scrolling_direction
{
SD_UP = 0,
SD_DOWN = 1,
SD_BEGIN = 2,
SD_END = 3
} EScrollingDirection;
protected:
// let branching menu items use my protected traversal methods
friend class LLMenuItemBranchGL;
@@ -470,14 +466,12 @@ public:
/*virtual*/ BOOL handleHover( S32 x, S32 y, MASK mask );
/*virtual*/ BOOL handleScrollWheel( S32 x, S32 y, S32 clicks );
/*virtual*/ void draw( void );
virtual void drawBackground(LLMenuItemGL* itemp, LLColor4& color);
/*virtual*/ void drawBackground(LLMenuItemGL* itemp, LLColor4& color);
/*virtual*/ void setVisible(BOOL visible);
/*virtual*/ bool addChild(LLView* view, S32 tab_group = 0);
/*virtual*/ void removeChild( LLView* ctrl);
/*virtual*/ BOOL postBuild();
bool addChild(LLView* view, LLView* insert_before, S32 tab_group = 0);
virtual BOOL handleAcceleratorKey(KEY key, MASK mask);
LLMenuGL* getChildMenuByName(const std::string& name, BOOL recurse) const;
@@ -531,6 +525,16 @@ public:
// remove all items on the menu
void empty( void );
// erase group of items from menu
void erase(S32 begin, S32 end, bool arrange = true);
// add new item at position
void insert(S32 begin, LLView* ctrl, bool arrange = true);
void insert(std::list<LLMenuItemGL*>::iterator position_iter, LLMenuItemGL* item, bool arrange = true);
// find an item's position
std::list<LLMenuItemGL*>::iterator find(LLMenuItemGL* item) { return std::find(mItems.begin(), mItems.end(), item); }
void setItemLastSelected(LLMenuItemGL* item); // must be in menu
U32 getItemCount(); // number of menu items
LLMenuItemGL* getItem(S32 number); // 0 = first item
@@ -545,7 +549,7 @@ public:
// Show popup in global screen space based on last mouse location.
static void showPopup(LLMenuGL* menu);
// Show popup at a specific location.
// Show popup at a specific location, in the spawn_view's coordinate frame
static void showPopup(LLView* spawning_view, LLMenuGL* menu, S32 x, S32 y);
// Whether to drop shadow menu bar
@@ -566,27 +570,29 @@ public:
static BOOL getKeyboardMode() { return sKeyboardMode; }
S32 getShortcutPad() { return mShortcutPad; }
BOOL isScrollable() const { return FALSE; }
bool scrollItems(EScrollingDirection direction);
BOOL isScrollable() const { return mScrollable; }
void setScrollable(bool b);
static class LLMenuHolderGL* sMenuContainer;
bool isScrollPositionOnShowReset() { return false; }
void resetScrollPositionOnShow(bool reset_scroll_pos) { mResetScrollPositionOnShow = reset_scroll_pos; }
bool isScrollPositionOnShowReset() { return mResetScrollPositionOnShow; }
protected:
void createSpilloverBranch();
void cleanupSpilloverBranch();
// Add the menu item to this menu.
virtual BOOL append( LLMenuItemGL* item );
BOOL append(LLMenuItemGL* item, LLView* insert_before);
// add a menu - this will create a cascading menu
virtual BOOL appendMenu( LLMenuGL* menu );
BOOL appendMenu(LLMenuGL* menu, LLView* insert_before);
// TODO: create accessor methods for these?
typedef std::list< LLMenuItemGL* > item_list_t;
item_list_t mItems;
LLMenuItemGL*mFirstVisibleItem;
LLMenuItemGL *mArrowUpItem, *mArrowDownItem;
typedef std::map<KEY, LLMenuItemGL*> navigation_key_map_t;
navigation_key_map_t mJumpKeys;
@@ -594,11 +600,15 @@ protected:
S32 mLastMouseY;
S32 mMouseVelX;
S32 mMouseVelY;
U32 mMaxScrollableItems;
BOOL mHorizontalLayout;
BOOL mScrollable;
BOOL mKeepFixedSize;
BOOL mNeedsArrange;
private:
static LLColor4 sDefaultBackgroundColor;
static BOOL sKeyboardMode;
@@ -609,12 +619,15 @@ private:
BOOL mDropShadowed; // Whether to drop shadow
bool mHasSelection;
LLFrameTimer mFadeTimer;
LLTimer mScrollItemsTimer;
BOOL mTornOff;
class LLMenuItemTearOffGL* mTearOffItem;
class LLMenuItemBranchGL* mSpilloverBranch;
LLMenuGL* mSpilloverMenu;
KEY mJumpKey;
BOOL mCreateJumpKeys;
S32 mShortcutPad;
bool mResetScrollPositionOnShow;
}; // end class LLMenuGL
@@ -648,8 +661,7 @@ public:
// called to rebuild the draw label
virtual void buildDrawLabel( void );
// doIt() - do the primary funcationality of the menu item.
virtual void doIt( void );
virtual void onCommit( void );
virtual BOOL handleKey(KEY key, MASK mask, BOOL called_from_parent);
virtual BOOL handleUnicodeChar(llwchar uni_char, BOOL called_from_parent);
@@ -684,11 +696,11 @@ private:
}; // end class LLMenuItemBranchGL
//-----------------------------------------------------------------------------
// class LLContextMenu
// A context menu
//-----------------------------------------------------------------------------
class LLContextMenu
: public LLMenuGL
{
@@ -792,8 +804,8 @@ public:
return TRUE;
}
// doIt() - do the primary funcationality of the menu item.
virtual void doIt( void );
// onCommit() - do the primary funcationality of the menu item.
virtual void onCommit( void );
LLContextMenu* getBranch() { return mBranch; }
void setHighlight( BOOL highlight );
@@ -904,7 +916,8 @@ class LLTearOffMenu : public LLFloater
{
public:
static LLTearOffMenu* create(LLMenuGL* menup);
virtual ~LLTearOffMenu() {}
virtual ~LLTearOffMenu();
virtual void onClose(bool app_quitting);
virtual void draw(void);
virtual void onFocusReceived();
@@ -935,7 +948,7 @@ public:
virtual LLXMLNodePtr getXML(bool save_children = true) const;
virtual std::string getType() const { return "tearoff_menu"; }
virtual void doIt(void);
virtual void onCommit(void);
virtual void draw(void);
virtual U32 getNominalHeight() const;

View File

@@ -3214,6 +3214,11 @@ void LLScrollListCtrl::setFocus(BOOL b)
selectFirstItem();
//onCommit(); // SJB: selectFirstItem() will call onCommit() if appropriate
}
// Singu Note: Edit menu handler, y'know for Ctrl-A and such!
if (b) gEditMenuHandler = this;
else if (gEditMenuHandler == this) gEditMenuHandler = NULL;
LLUICtrl::setFocus(b);
}

View File

@@ -395,8 +395,14 @@ void LLTextBox::initFromXML(LLXMLNodePtr node, LLView* parent)
LLFontGL* font = LLView::selectFont(node);
if(font)
mFontGL = font;
setText(node->getTextContents());
if (node->hasAttribute("value"))
{
std::string text;
node->getAttributeString("value", text);
setText(text);
}
else setText(node->getTextContents());
LLFontGL::HAlign halign = LLView::selectFontHAlign(node);
setHAlign(halign);

View File

@@ -301,19 +301,19 @@ void LLDir::setDumpDir( const std::string& path )
const std::string &LLDir::getDumpDir() const
{
if (sDumpDir.empty() )
{
if (sDumpDir.empty() )
{
/* Singu Note: don't generate a different dump dir each time
LLUUID uid;
uid.generate();
sDumpDir = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "")
+ "dump-" + uid.asString();
LLUUID uid;
uid.generate();
sDumpDir = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "")
+ "dump-" + uid.asString();
*/
sDumpDir = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "") + "singularity-debug";
dir_exists_or_crash(sDumpDir);
}
sDumpDir = getExpandedFilename(LL_PATH_LOGS, "") + "singularity-debug";
dir_exists_or_crash(sDumpDir);
}
return LLDir::sDumpDir;
}
@@ -710,6 +710,33 @@ void LLDir::setLindenUserDir(const std::string &grid, const std::string &first,
dumpCurrentDirectories();
}
void LLDir::makePortable()
{
std::string dir = mExecutableDir;
dir.erase(dir.rfind(mDirDelimiter)); // Go one level up
dir += mDirDelimiter + "portable_viewer";
if (LLFile::mkdir(dir) == -1)
{
if (errno != EEXIST)
{
llwarns << "Couldn't create portable_viewer directory." << llendl;
return; // Failed, don't mess anything up.
}
}
mOSUserDir = dir + mDirDelimiter + "settings";
mOSCacheDir = dir + mDirDelimiter + "cache";
if (LLFile::mkdir(mOSUserDir) == -1 || LLFile::mkdir(mOSCacheDir) == -1)
{
if (errno != EEXIST)
{
llwarns << "Couldn't create portable_viewer cache and settings directories." << llendl;
return; // Failed, don't mess up the existing initialization.
}
}
mDefaultCacheDir = buildSLOSCacheDir();
initAppDirs(mAppName); // This is kinda lazy, but it's probably the quickest, most uniform way.
}
void LLDir::setChatLogsDir(const std::string &path)
{
if (!path.empty() )

View File

@@ -133,6 +133,7 @@ class LLDir
static std::string getForbiddenFileChars();
void setDumpDir( const std::string& path );
void makePortable();
virtual void setChatLogsDir(const std::string &path); // Set the chat logs dir to this user's dir
virtual void setPerAccountChatLogsDir(const std::string &grid, const std::string &first, const std::string &last); // Set the per user chat log directory.
virtual void setLindenUserDir(const std::string& grid, const std::string& first, const std::string& last); // Set the linden user dir to this user's dir

View File

@@ -156,8 +156,6 @@ LLDir_Win32::LLDir_Win32()
mAppRODataDir = mWorkingDir;
// if (mExecutableDir.find("indra") == std::string::npos)
// *NOTE:Mani - It is a mistake to put viewer specific code in
// the LLDir implementation. The references to 'skins' and
// 'llplugin' need to go somewhere else.
@@ -172,7 +170,18 @@ LLDir_Win32::LLDir_Win32()
llinfos << "mAppRODataDir = " << mAppRODataDir << llendl;
mSkinBaseDir = mAppRODataDir + mDirDelimiter + "skins";
std::string::size_type build_dir_pos = mExecutableDir.rfind("indra" + mDirDelimiter);
if (build_dir_pos != std::string::npos)
{
// ...we're in a dev checkout
mSkinBaseDir = mExecutableDir.substr(0, build_dir_pos) + "indra" + mDirDelimiter + "newview" + mDirDelimiter + "skins";
llinfos << "Running in dev checkout with mSkinBaseDir " << mSkinBaseDir << llendl;
}
else
{
// ...normal installation running
mSkinBaseDir = mAppRODataDir + mDirDelimiter + "skins";
}
// Build the default cache directory
mDefaultCacheDir = buildSLOSCacheDir();

View File

@@ -57,6 +57,7 @@ LLKeyboard::LLKeyboard() : mCallbacks(NULL), mNumpadDistinct(ND_NUMLOCK_OFF)
mKeyUp[i] = FALSE;
mKeyDown[i] = FALSE;
mKeyRepeated[i] = FALSE;
mControllerKeys[i] = FALSE;
}
mInsertMode = LL_KIM_INSERT;

View File

@@ -113,6 +113,12 @@ public:
F32 getKeyElapsedTime( KEY key ); // Returns time in seconds since key was pressed.
S32 getKeyElapsedFrameCount( KEY key ); // Returns time in frames since key was pressed.
void setControllerKey(KEY key, bool level)
{
mControllerKeys[key] = mKeyLevel[key] = level;
(level ? mKeyDown[key] : mKeyUp[key]) = true;
}
protected:
void addKeyName(KEY key, const std::string& name);
@@ -127,6 +133,7 @@ protected:
BOOL mKeyRepeated[KEY_COUNT]; // Key was repeated
BOOL mKeyUp[KEY_COUNT]; // Up edge
BOOL mKeyDown[KEY_COUNT]; // Down edge
BOOL mControllerKeys[KEY_COUNT]; // Keys held in controller
KEY mCurTranslatedKey;
KEY mCurScanKey; // Used during the scanKeyboard()

View File

@@ -267,7 +267,7 @@ void LLKeyboardWin32::scanKeyboard()
// ...translate back to windows key
U16 virtual_key = inverseTranslateExtendedKey(key);
// keydown in highest bit
if (!pending_key_events && !(GetAsyncKeyState(virtual_key) & 0x8000))
if (!mControllerKeys[key] && !pending_key_events && !(GetAsyncKeyState(virtual_key) & 0x8000))
{
//llinfos << "Key up event missed, resetting" << llendl;
mKeyLevel[key] = FALSE;

View File

@@ -3277,7 +3277,7 @@ void LLWindowMacOSX::spawnWebBrowser(const std::string& escaped_url, bool async)
llinfos << "Opening URL " << escaped_url << llendl;
CFStringRef stringRef = CFStringCreateWithCString(NULL, escaped_url.c_str(), kCFStringEncodingUTF8);
CFStringRef stringRef = CFStringCreateWithBytes(NULL, (UInt8 *)escaped_url.c_str(), strlen(escaped_url.c_str()), kCFStringEncodingUTF8, false);
if (stringRef)
{
// This will succeed if the string is a full URL, including the http://
@@ -3315,6 +3315,21 @@ void LLWindowMacOSX::setTitle(const std::string &title)
SetWindowTitleWithCFString(mWindow, title_str);
}
// virtual
void LLWindowMacOSX::ShellEx(const std::string& command)
{
char * path = NULL;
asprintf(&path, "%s %s", (char*)"file://", command.c_str());
CFURLRef url = CFURLCreateAbsoluteURLWithBytes(NULL, (UInt8 *)path, strlen(path),
kCFURLPOSIXPathStyle, NULL, true);
if (url != NULL)
{
LSOpenCFURLRef(url, NULL);
CFRelease(url);
}
free(path);
}
LLSD LLWindowMacOSX::getNativeKeyData()
{
LLSD result = LLSD::emptyMap();

View File

@@ -116,6 +116,7 @@ public:
/*virtual*/ void spawnWebBrowser(const std::string& escaped_url, bool async);
/*virtual*/ void setTitle(const std::string &title);
/*virtual*/ void ShellEx(const std::string& command);
static std::vector<std::string> getDynamicFallbackFontList();

View File

@@ -3329,9 +3329,9 @@ S32 OSMessageBoxWin32(const std::string& text, const std::string& caption, U32 t
return retval;
}
void LLWindowWin32::ShellEx(const std::string& command )
void LLWindowWin32::ShellEx(const std::string& command)
{
LLWString url_wstring = utf8str_to_wstring( command );
LLWString url_wstring = utf8str_to_wstring( "\"" + command + "\"" );
llutf16string url_utf16 = wstring_to_utf16str( url_wstring );
SHELLEXECUTEINFO sei = { sizeof( sei ) };

View File

@@ -126,6 +126,7 @@ set(viewer_SOURCE_FILES
llassetuploadresponders.cpp
llattachmentsmgr.cpp
llaudiosourcevo.cpp
llautoreplace.cpp
llavataractions.cpp
llavatarpropertiesprocessor.cpp
llbox.cpp
@@ -181,6 +182,7 @@ set(viewer_SOURCE_FILES
llfloaterabout.cpp
llfloateractivespeakers.cpp
llfloaterauction.cpp
llfloaterautoreplacesettings.cpp
llfloateravatarinfo.cpp
llfloateravatarlist.cpp
llfloateravatarpicker.cpp
@@ -238,13 +240,13 @@ set(viewer_SOURCE_FILES
llfloaternamedesc.cpp
llfloaternotificationsconsole.cpp
llfloaterobjectiminfo.cpp
llfloaterobjectweights.cpp
llfloateropenobject.cpp
llfloateroutbox.cpp
llfloaterparcel.cpp
llfloaterpathfindingcharacters.cpp
llfloaterpathfindinglinksets.cpp
llfloaterpathfindingobjects.cpp
llfloaterpermissionsmgr.cpp
llfloaterperms.cpp
llfloaterpostcard.cpp
llfloaterpostprocess.cpp
@@ -252,6 +254,7 @@ set(viewer_SOURCE_FILES
llfloaterproperties.cpp
llfloaterregiondebugconsole.cpp
llfloaterregioninfo.cpp
llfloaterregionrestarting.cpp
llfloaterreporter.cpp
llfloaterscriptdebug.cpp
llfloaterscriptlimits.cpp
@@ -646,6 +649,7 @@ set(viewer_HEADER_FILES
llassetuploadresponders.h
llattachmentsmgr.h
llaudiosourcevo.h
llautoreplace.h
llavataractions.h
llavatarpropertiesprocessor.h
llbox.h
@@ -701,6 +705,7 @@ set(viewer_HEADER_FILES
llfloaterabout.h
llfloateractivespeakers.h
llfloaterauction.h
llfloaterautoreplacesettings.h
llfloateravatarinfo.h
llfloateravatarlist.h
llfloateravatarpicker.h
@@ -758,13 +763,13 @@ set(viewer_HEADER_FILES
llfloaternamedesc.h
llfloaternotificationsconsole.h
llfloaterobjectiminfo.h
llfloaterobjectweights.h
llfloateropenobject.h
llfloateroutbox.h
llfloaterparcel.h
llfloaterpathfindingcharacters.h
llfloaterpathfindinglinksets.h
llfloaterpathfindingobjects.h
llfloaterpermissionsmgr.h
llfloaterperms.h
llfloaterpostcard.h
llfloaterpostprocess.h
@@ -772,6 +777,7 @@ set(viewer_HEADER_FILES
llfloaterproperties.h
llfloaterregiondebugconsole.h
llfloaterregioninfo.h
llfloaterregionrestarting.h
llfloaterreporter.h
llfloaterscriptdebug.h
llfloaterscriptlimits.h
@@ -1140,7 +1146,7 @@ if (DARWIN)
# Add resource files to the project.
set(viewer_RESOURCE_FILES
${VIEWER_BRANDING_ID}.icns
${VIEWER_BRANDING_ID}_icon.icns
macview.r
gpu_table.txt
SecondLife.nib/
@@ -1702,7 +1708,7 @@ if (DARWIN)
PROPERTIES
OUTPUT_NAME "${product}"
MACOSX_BUNDLE_INFO_STRING "A stable third-party Second Life viewer."
MACOSX_BUNDLE_ICON_FILE "${VIEWER_BRANDING_ID}.icns"
MACOSX_BUNDLE_ICON_FILE "${VIEWER_BRANDING_ID}_icon.icns"
MACOSX_BUNDLE_GUI_IDENTIFIER "${VIEWER_BRANDING_NAME}"
MACOSX_BUNDLE_LONG_VERSION_STRING "${viewer_VERSION}"
MACOSX_BUNDLE_BUNDLE_NAME "${VIEWER_BRANDING_NAME}"
@@ -1794,7 +1800,7 @@ if (PACKAGE)
if (LINUX)
list(APPEND SYMBOL_SEARCH_DIRS "${CMAKE_CURRENT_BINARY_DIR}/packaged")
set(VIEWER_SYMBOL_FILE "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/secondlife-symbols-linux.tar.bz2")
set(VIEWER_EXE_GLOBS "singularity-do-not-run-directly SLPlugin")
set(VIEWER_EXE_GLOBS "${VIEWER_BRANDING_ID}-do-not-run-directly SLPlugin")
set(VIEWER_LIB_GLOB "*${CMAKE_SHARED_MODULE_SUFFIX}*")
set(VIEWER_COPY_MANIFEST copy_l_viewer_manifest)
endif (LINUX)

File diff suppressed because it is too large Load Diff

View File

@@ -253,6 +253,12 @@
<string>UserConnectionPort</string>
</map>
<key>portable</key>
<map>
<key>count</key>
<integer>0</integer>
</map>
<key>purge</key>
<map>
<key>desc</key>

View File

@@ -0,0 +1,362 @@
# keys.ini
#
# keyboard binding initialization
#
# comments must have # in the first column
# blank lines OK
#
# Format:
# mode key mask function
#
# mode must be one of FIRST_PERSON, THIRD_PERSON, EDIT, EDIT_AVATAR, or CONVERSATION
# key must be upper case, or SPACE, HOME, END, PGUP, PGDN, LEFT, RIGHT, UP, DOWN,
# or one of ,.;'[]
# mask must be NONE, SHIFT, ALT, ALT_SHIFT.
# Control is reserved for user commands.
# function must be a function named in llkeyboard.cpp
FIRST_PERSON Q NONE slide_left
FIRST_PERSON D NONE slide_right
FIRST_PERSON Z NONE push_forward
FIRST_PERSON S NONE push_backward
FIRST_PERSON E NONE jump
FIRST_PERSON C NONE push_down
FIRST_PERSON F NONE toggle_fly
FIRST_PERSON LEFT NONE slide_left
FIRST_PERSON RIGHT NONE slide_right
FIRST_PERSON UP NONE push_forward
FIRST_PERSON DOWN NONE push_backward
FIRST_PERSON PGUP NONE jump
FIRST_PERSON PGDN NONE push_down
FIRST_PERSON HOME NONE toggle_fly
FIRST_PERSON PAD_LEFT NONE slide_left
FIRST_PERSON PAD_RIGHT NONE slide_right
FIRST_PERSON PAD_UP NONE push_forward
FIRST_PERSON PAD_DOWN NONE push_backward
FIRST_PERSON PAD_PGUP NONE jump
FIRST_PERSON PAD_PGDN NONE push_down
FIRST_PERSON PAD_HOME NONE toggle_fly
FIRST_PERSON PAD_CENTER NONE stop_moving
FIRST_PERSON PAD_ENTER NONE start_chat
FIRST_PERSON PAD_DIVIDE NONE start_gesture
FIRST_PERSON Q SHIFT slide_left
FIRST_PERSON D SHIFT slide_right
FIRST_PERSON Z SHIFT push_forward
FIRST_PERSON S SHIFT push_backward
FIRST_PERSON E SHIFT jump
FIRST_PERSON C SHIFT toggle_down
FIRST_PERSON F SHIFT toggle_fly
FIRST_PERSON SPACE NONE stop_moving
FIRST_PERSON ENTER NONE start_chat
FIRST_PERSON DIVIDE NONE start_gesture
FIRST_PERSON / NONE start_gesture
FIRST_PERSON LEFT SHIFT slide_left
FIRST_PERSON RIGHT SHIFT slide_right
FIRST_PERSON UP SHIFT push_forward
FIRST_PERSON DOWN SHIFT push_backward
FIRST_PERSON PGUP SHIFT jump
FIRST_PERSON PGDN SHIFT toggle_down
FIRST_PERSON PAD_LEFT SHIFT slide_left
FIRST_PERSON PAD_RIGHT SHIFT slide_right
FIRST_PERSON PAD_UP SHIFT push_forward
FIRST_PERSON PAD_DOWN SHIFT push_backward
FIRST_PERSON PAD_PGUP SHIFT jump
FIRST_PERSON PAD_PGDN SHIFT toggle_down
FIRST_PERSON PAD_HOME SHIFT toggle_fly
FIRST_PERSON PAD_ENTER SHIFT start_chat
FIRST_PERSON PAD_DIVIDE SHIFT start_gesture
THIRD_PERSON Q NONE turn_left
THIRD_PERSON D NONE turn_right
THIRD_PERSON Q SHIFT slide_left
THIRD_PERSON D SHIFT slide_right
THIRD_PERSON Z NONE push_forward
THIRD_PERSON S NONE push_backward
THIRD_PERSON Z SHIFT push_forward
THIRD_PERSON S SHIFT push_backward
THIRD_PERSON E NONE jump
THIRD_PERSON C NONE push_down
THIRD_PERSON E SHIFT jump
THIRD_PERSON C SHIFT toggle_down
THIRD_PERSON F NONE toggle_fly
THIRD_PERSON F SHIFT toggle_fly
THIRD_PERSON SPACE NONE stop_moving
THIRD_PERSON ENTER NONE start_chat
THIRD_PERSON DIVIDE NONE start_gesture
THIRD_PERSON / NONE start_gesture
THIRD_PERSON LEFT NONE turn_left
THIRD_PERSON LEFT SHIFT slide_left
THIRD_PERSON RIGHT NONE turn_right
THIRD_PERSON RIGHT SHIFT slide_right
THIRD_PERSON UP NONE push_forward
THIRD_PERSON DOWN NONE push_backward
THIRD_PERSON UP SHIFT push_forward
THIRD_PERSON DOWN SHIFT push_backward
THIRD_PERSON PGUP NONE jump
THIRD_PERSON PGDN NONE push_down
THIRD_PERSON PGUP SHIFT jump
THIRD_PERSON PGDN SHIFT toggle_down
THIRD_PERSON HOME SHIFT toggle_fly
THIRD_PERSON HOME NONE toggle_fly
THIRD_PERSON PAD_LEFT NONE turn_left
THIRD_PERSON PAD_LEFT SHIFT slide_left
THIRD_PERSON PAD_RIGHT NONE turn_right
THIRD_PERSON PAD_RIGHT SHIFT slide_right
THIRD_PERSON PAD_UP NONE push_forward
THIRD_PERSON PAD_DOWN NONE push_backward
THIRD_PERSON PAD_UP SHIFT push_forward
THIRD_PERSON PAD_DOWN SHIFT push_backward
THIRD_PERSON PAD_PGUP NONE jump
THIRD_PERSON PAD_PGDN NONE push_down
THIRD_PERSON PAD_PGUP SHIFT jump
THIRD_PERSON PAD_PGDN SHIFT toggle_down
THIRD_PERSON PAD_HOME NONE toggle_fly
THIRD_PERSON PAD_HOME SHIFT toggle_fly
THIRD_PERSON PAD_CENTER NONE stop_moving
THIRD_PERSON PAD_CENTER SHIFT stop_moving
THIRD_PERSON PAD_ENTER NONE start_chat
THIRD_PERSON PAD_ENTER SHIFT start_chat
THIRD_PERSON PAD_DIVIDE NONE start_gesture
THIRD_PERSON PAD_DIVIDE SHIFT start_gesture
# Camera controls in third person on Alt
THIRD_PERSON LEFT ALT spin_around_cw
THIRD_PERSON RIGHT ALT spin_around_ccw
THIRD_PERSON UP ALT move_forward
THIRD_PERSON DOWN ALT move_backward
THIRD_PERSON PGUP ALT spin_over
THIRD_PERSON PGDN ALT spin_under
THIRD_PERSON Q ALT spin_around_cw
THIRD_PERSON D ALT spin_around_ccw
THIRD_PERSON Z ALT move_forward
THIRD_PERSON S ALT move_backward
THIRD_PERSON E ALT spin_over
THIRD_PERSON C ALT spin_under
THIRD_PERSON PAD_LEFT ALT spin_around_cw
THIRD_PERSON PAD_RIGHT ALT spin_around_ccw
THIRD_PERSON PAD_UP ALT move_forward
THIRD_PERSON PAD_DOWN ALT move_backward
THIRD_PERSON PAD_PGUP ALT spin_over
THIRD_PERSON PAD_PGDN ALT spin_under
THIRD_PERSON PAD_ENTER ALT start_chat
THIRD_PERSON PAD_DIVIDE ALT start_gesture
# mimic alt zoom behavior with keyboard only
THIRD_PERSON Q CTL_ALT spin_around_cw
THIRD_PERSON D CTL_ALT spin_around_ccw
THIRD_PERSON Z CTL_ALT spin_over
THIRD_PERSON S CTL_ALT spin_under
THIRD_PERSON E CTL_ALT spin_over
THIRD_PERSON C CTL_ALT spin_under
THIRD_PERSON LEFT CTL_ALT spin_around_cw
THIRD_PERSON RIGHT CTL_ALT spin_around_ccw
THIRD_PERSON UP CTL_ALT spin_over
THIRD_PERSON DOWN CTL_ALT spin_under
THIRD_PERSON PGUP CTL_ALT spin_over
THIRD_PERSON PGDN CTL_ALT spin_under
THIRD_PERSON PAD_LEFT CTL_ALT spin_around_cw
THIRD_PERSON PAD_RIGHT CTL_ALT spin_around_ccw
THIRD_PERSON PAD_UP CTL_ALT spin_over
THIRD_PERSON PAD_DOWN CTL_ALT spin_under
THIRD_PERSON PAD_PGUP CTL_ALT spin_over
THIRD_PERSON PAD_PGDN CTL_ALT spin_under
THIRD_PERSON PAD_ENTER CTL_ALT start_chat
THIRD_PERSON PAD_DIVIDE CTL_ALT start_gesture
# Therefore pan on Alt-Shift
THIRD_PERSON Q CTL_ALT_SHIFT pan_left
THIRD_PERSON D CTL_ALT_SHIFT pan_right
THIRD_PERSON Z CTL_ALT_SHIFT pan_up
THIRD_PERSON S CTL_ALT_SHIFT pan_down
THIRD_PERSON LEFT CTL_ALT_SHIFT pan_left
THIRD_PERSON RIGHT CTL_ALT_SHIFT pan_right
THIRD_PERSON UP CTL_ALT_SHIFT pan_up
THIRD_PERSON DOWN CTL_ALT_SHIFT pan_down
THIRD_PERSON PAD_LEFT CTL_ALT_SHIFT pan_left
THIRD_PERSON PAD_RIGHT CTL_ALT_SHIFT pan_right
THIRD_PERSON PAD_UP CTL_ALT_SHIFT pan_up
THIRD_PERSON PAD_DOWN CTL_ALT_SHIFT pan_down
THIRD_PERSON PAD_ENTER CTL_ALT_SHIFT start_chat
THIRD_PERSON PAD_DIVIDE CTL_ALT_SHIFT start_gesture
# Basic editing camera control
EDIT Q NONE spin_around_cw
EDIT D NONE spin_around_ccw
EDIT Z NONE move_forward
EDIT S NONE move_backward
EDIT E NONE spin_over
EDIT C NONE spin_under
EDIT ENTER NONE start_chat
EDIT DIVIDE NONE start_gesture
EDIT / NONE start_gesture
EDIT PAD_ENTER NONE start_chat
EDIT PAD_DIVIDE NONE start_gesture
EDIT LEFT NONE spin_around_cw
EDIT RIGHT NONE spin_around_ccw
EDIT UP NONE move_forward
EDIT DOWN NONE move_backward
EDIT PGUP NONE spin_over
EDIT PGDN NONE spin_under
EDIT Q SHIFT pan_left
EDIT D SHIFT pan_right
EDIT Z SHIFT pan_up
EDIT S SHIFT pan_down
EDIT LEFT SHIFT pan_left
EDIT RIGHT SHIFT pan_right
EDIT UP SHIFT pan_up
EDIT DOWN SHIFT pan_down
# Walking works with ALT held down.
EDIT Q ALT slide_left
EDIT D ALT slide_right
EDIT Z ALT push_forward
EDIT S ALT push_backward
EDIT E ALT jump
EDIT C ALT push_down
EDIT LEFT ALT slide_left
EDIT RIGHT ALT slide_right
EDIT UP ALT push_forward
EDIT DOWN ALT push_backward
EDIT PGUP ALT jump
EDIT PGDN ALT push_down
EDIT HOME ALT toggle_fly
EDIT PAD_LEFT ALT slide_left
EDIT PAD_RIGHT ALT slide_right
EDIT PAD_UP ALT push_forward
EDIT PAD_DOWN ALT push_backward
EDIT PAD_PGUP ALT jump
EDIT PAD_PGDN ALT push_down
EDIT PAD_ENTER ALT start_chat
EDIT PAD_DIVIDE ALT start_gesture
SITTING Q ALT spin_around_cw
SITTING D ALT spin_around_ccw
SITTING Z ALT move_forward
SITTING S ALT move_backward
SITTING E ALT spin_over_sitting
SITTING C ALT spin_under_sitting
SITTING LEFT ALT spin_around_cw
SITTING RIGHT ALT spin_around_ccw
SITTING UP ALT move_forward
SITTING DOWN ALT move_backward
SITTING PGUP ALT spin_over
SITTING PGDN ALT spin_under
SITTING Q CTL_ALT spin_around_cw
SITTING D CTL_ALT spin_around_ccw
SITTING Z CTL_ALT spin_over
SITTING S CTL_ALT spin_under
SITTING E CTL_ALT spin_over
SITTING C CTL_ALT spin_under
SITTING LEFT CTL_ALT spin_around_cw
SITTING RIGHT CTL_ALT spin_around_ccw
SITTING UP CTL_ALT spin_over
SITTING DOWN CTL_ALT spin_under
SITTING PGUP CTL_ALT spin_over
SITTING PGDN CTL_ALT spin_under
SITTING Q NONE spin_around_cw_sitting
SITTING D NONE spin_around_ccw_sitting
SITTING Z NONE move_forward_sitting
SITTING S NONE move_backward_sitting
SITTING E NONE spin_over_sitting
SITTING C NONE spin_under_sitting
SITTING LEFT NONE spin_around_cw_sitting
SITTING RIGHT NONE spin_around_ccw_sitting
SITTING UP NONE move_forward_sitting
SITTING DOWN NONE move_backward_sitting
SITTING PGUP NONE spin_over_sitting
SITTING PGDN NONE spin_under_sitting
SITTING PAD_LEFT NONE spin_around_cw_sitting
SITTING PAD_RIGHT NONE spin_around_ccw_sitting
SITTING PAD_UP NONE move_forward_sitting
SITTING PAD_DOWN NONE move_backward_sitting
SITTING PAD_PGUP NONE spin_over_sitting
SITTING PAD_PGDN NONE spin_under_sitting
SITTING PAD_CENTER NONE stop_moving
SITTING PAD_ENTER NONE start_chat
SITTING PAD_DIVIDE NONE start_gesture
# these are for passing controls when sitting on vehicles
SITTING Q SHIFT slide_left
SITTING D SHIFT slide_right
SITTING LEFT SHIFT slide_left
SITTING RIGHT SHIFT slide_right
SITTING PAD_LEFT SHIFT slide_left
SITTING PAD_RIGHT SHIFT slide_right
SITTING PAD_ENTER SHIFT start_chat
SITTING PAD_DIVIDE SHIFT start_gesture
# pan on Alt-Shift
SITTING Q CTL_ALT_SHIFT pan_left
SITTING D CTL_ALT_SHIFT pan_right
SITTING Z CTL_ALT_SHIFT pan_up
SITTING S CTL_ALT_SHIFT pan_down
SITTING LEFT CTL_ALT_SHIFT pan_left
SITTING RIGHT CTL_ALT_SHIFT pan_right
SITTING UP CTL_ALT_SHIFT pan_up
SITTING DOWN CTL_ALT_SHIFT pan_down
SITTING PAD_LEFT CTL_ALT_SHIFT pan_left
SITTING PAD_RIGHT CTL_ALT_SHIFT pan_right
SITTING PAD_UP CTL_ALT_SHIFT pan_up
SITTING PAD_DOWN CTL_ALT_SHIFT pan_down
SITTING PAD_ENTER CTL_ALT_SHIFT start_chat
SITTING PAD_DIVIDE CTL_ALT_SHIFT start_gesture
SITTING ENTER NONE start_chat
SITTING DIVIDE NONE start_gesture
SITTING / NONE start_gesture
# Avatar editing camera controls
EDIT_AVATAR Q NONE edit_avatar_spin_cw
EDIT_AVATAR D NONE edit_avatar_spin_ccw
EDIT_AVATAR Z NONE edit_avatar_move_forward
EDIT_AVATAR S NONE edit_avatar_move_backward
EDIT_AVATAR E NONE edit_avatar_spin_over
EDIT_AVATAR C NONE edit_avatar_spin_under
EDIT_AVATAR LEFT NONE edit_avatar_spin_cw
EDIT_AVATAR RIGHT NONE edit_avatar_spin_ccw
EDIT_AVATAR UP NONE edit_avatar_move_forward
EDIT_AVATAR DOWN NONE edit_avatar_move_backward
EDIT_AVATAR PGUP NONE edit_avatar_spin_over
EDIT_AVATAR PGDN NONE edit_avatar_spin_under
EDIT_AVATAR ENTER NONE start_chat
EDIT_AVATAR DIVIDE NONE start_gesture
EDIT_AVATAR / NONE start_gesture
EDIT_AVATAR PAD_LEFT NONE edit_avatar_spin_cw
EDIT_AVATAR PAD_RIGHT NONE edit_avatar_spin_ccw
EDIT_AVATAR PAD_UP NONE edit_avatar_move_forward
EDIT_AVATAR PAD_DOWN NONE edit_avatar_move_backward
EDIT_AVATAR PAD_PGUP NONE edit_avatar_spin_over
EDIT_AVATAR PAD_PGDN NONE edit_avatar_spin_under
EDIT_AVATAR PAD_ENTER NONE start_chat
EDIT_AVATAR PAD_DIVIDE NONE start_gesture

View File

@@ -651,6 +651,17 @@
<key>Value</key>
<integer>0</integer>
</map>
<key>LiruBlockConferences</key>
<map>
<key>Comment</key>
<string>When true, new incoming conference chats will not be opened.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>LiruContinueFlyingOnUnsit</key>
<map>
<key>Comment</key>
@@ -678,6 +689,19 @@
<real>1.0</real>
</array>
</map>
<key>LiruCustomizeAnim</key>
<map>
<key>Comment</key>
<string>Whether or not to animate when going into appearance mode.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<boolean>1</boolean>
<key>IsCOA</key>
<integer>1</integer>
</map>
<key>LiruGridInTitle</key>
<map>
<key>Comment</key>
@@ -724,6 +748,17 @@
<key>Value</key>
<integer>0</integer>
</map>
<key>LiruLegacyDisplayMuteds</key>
<map>
<key>Comment</key>
<string>When off, muted people will go unrendered...</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>1</integer>
</map>
<key>LiruLegacyLandmarks</key>
<map>
<key>Comment</key>
@@ -738,7 +773,7 @@
<key>LiruLegacyLogLaunch</key>
<map>
<key>Comment</key>
<string>When opening a chat log, open in an external text editor instead of a browser floater(Windows Only).</string>
<string>When opening a chat log, open in an external text editor instead of a browser floater(Windows and Mac Only).</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
@@ -768,6 +803,17 @@
<key>Value</key>
<integer>1</integer>
</map>
<key>LiruLegacyScrollToEnd</key>
<map>
<key>Comment</key>
<string>Automatically scroll to the end of a chat's history when the chat regains focus.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>LiruLocalTime</key>
<map>
<key>Comment</key>
@@ -834,6 +880,28 @@
<key>Value</key>
<boolean>0</boolean>
</map>
<key>LiruMouselookHidesToolbar</key>
<map>
<key>Comment</key>
<string>Whether or not the toolbar will be hidden in mouselook</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<boolean>1</boolean>
</map>
<key>LiruMouselookInstantZoom</key>
<map>
<key>Comment</key>
<string>Whether or not the right click zoom in mouselook will be instant or smoothly transition between zooms</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<boolean>0</boolean>
</map>
<key>LiruMouselookMenu</key>
<map>
<key>Comment</key>
@@ -882,6 +950,19 @@
<key>IsCOA</key>
<integer>1</integer>
</map>
<key>LiruNewMessageSoundIMsOn</key>
<map>
<key>Comment</key>
<string>Whether or not ding defaults to being on for new IMs.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<boolean>0</boolean>
<key>IsCOA</key>
<integer>1</integer>
</map>
<key>LiruNoTransactionClutter</key>
<map>
<key>Comment</key>
@@ -893,6 +974,19 @@
<key>Value</key>
<integer>0</integer>
</map>
<key>LiruRegionRestartMinimized</key>
<map>
<key>Comment</key>
<string>Whether or not to spawn the region restart notice minimized (Useful for sim owners and people who need to pack up before leaving)</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
<key>IsCOA</key>
<integer>1</integer>
</map>
<key>LiruScriptErrorsStealFocus</key>
<map>
<key>Comment</key>
@@ -927,6 +1021,17 @@ Found in Advanced->Rendering->Info Displays</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>LiruUseAdvancedMenuShortcut</key>
<map>
<key>Comment</key>
<string>Use ctrl-alt(-shift)-d to toggle the advanced menu.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<boolean>1</boolean>
</map>
<key>LiruUseContextMenus</key>
<map>
<key>Comment</key>
@@ -938,6 +1043,28 @@ Found in Advanced->Rendering->Info Displays</string>
<key>Value</key>
<boolean>0</boolean>
</map>
<key>LiruUseZQSDKeys</key>
<map>
<key>Comment</key>
<string>Use ZQSD layout instead of WASD.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<boolean>0</boolean>
</map>
<key>SFMapShowRegionPositions</key>
<map>
<key>Comment</key>
<string>Shows the X and Y coordinates above the sim name in the world map.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<boolean>0</boolean>
</map>
<key>SLBShowFPS</key>
<map>
<key>Comment</key>
@@ -960,6 +1087,17 @@ Found in Advanced->Rendering->Info Displays</string>
<key>Value</key>
<integer>1</integer>
</map>
<key>UseRealisticMouselook</key>
<map>
<key>Comment</key>
<string>Use a realistic first person view, this prevents your camera from being the center of everything and your avatar always beeing locked below you, it allows your Avatar to move around freely in mouselook while your camera will follow it around. Prepare your seatbelts for an awesome shaky View! May break with certain super unrealistic animations.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>LogShowHistoryLines</key>
<map>
<key>Comment</key>
@@ -1198,6 +1336,17 @@ This should be as low as possible, but too low may break functionality</string>
<key>Value</key>
<boolean>0</boolean>
</map>
<key>RightClickTurnsAvatar</key>
<map>
<key>Comment</key>
<string>When false, right clicking on objects that are certain angles from the direction your avatar is facing will not turn your avatar to face them.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<boolean>1</boolean>
</map>
<key>ShowDisplayNameChanges</key>
<map>
<key>Comment</key>
@@ -1313,6 +1462,17 @@ This should be as low as possible, but too low may break functionality</string>
<key>Value</key>
<integer>1</integer>
</map>
<key>AnnounceBumps</key>
<map>
<key>Comment</key>
<string>Announce if someone bumps into you.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<boolean>0</boolean>
</map>
<key>AnnounceSnapshots</key>
<map>
<key>Comment</key>
@@ -2222,6 +2382,17 @@ This should be as low as possible, but too low may break functionality</string>
<key>IsCOA</key>
<integer>1</integer>
</map>
<key>UISndRestart</key>
<map>
<key>Comment</key>
<string>Sound file for region restarting (uuid for sound asset)</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>String</string>
<key>Value</key>
<string>1e506d0c-4811-bdf3-5ec7-d624284c9040</string>
</map>
<key>UISndSnapshot</key>
<map>
<key>Comment</key>
@@ -2396,6 +2567,17 @@ This should be as low as possible, but too low may break functionality</string>
<key>Value</key>
<integer>1</integer>
</map>
<key>AllowSelectAvatar</key>
<map>
<key>Comment</key>
<string>Allow selecting an avatar that you have modify rights on (via tag) while in edit mode to reposition them</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>AllowTapTapHoldRun</key>
<map>
<key>Comment</key>
@@ -2693,6 +2875,17 @@ This should be as low as possible, but too low may break functionality</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>AutoReplace</key>
<map>
<key>Comment</key>
<string>Replaces keywords with a configured word or phrase</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>AutoAcceptAllNewInventory</key>
<map>
<key>Comment</key>
@@ -2979,6 +3172,17 @@ This should be as low as possible, but too low may break functionality</string>
<key>Value</key>
<integer>2</integer>
</map>
<key>AvatarRotateThresholdMouselook</key>
<map>
<key>Comment</key>
<string>Angle between avatar facing and camera facing at which avatar turns to face same direction as camera, when in mouselook (degrees)</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>F32</string>
<key>Value</key>
<real>120</real>
</map>
<key>AvatarBakedTextureUploadTimeout</key>
<map>
<key>Comment</key>
@@ -4032,6 +4236,28 @@ This should be as low as possible, but too low may break functionality</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>ChatLoadGroupMaxMembers</key>
<map>
<key>Comment</key>
<string>Max number of active members we'll show up for an unresponsive group</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>S32</string>
<key>Value</key>
<real>100</real>
</map>
<key>ChatLoadGroupTimeout</key>
<map>
<key>Comment</key>
<string>Time we give the server to send group participants before we hit the server for group info (seconds)</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>F32</string>
<key>Value</key>
<real>10.0</real>
</map>
<key>ChatOnlineNotification</key>
<map>
<key>Comment</key>
@@ -6349,17 +6575,6 @@ This should be as low as possible, but too low may break functionality</string>
<key>Value</key>
<integer>175</integer>
</map>
<key>EveryoneCopy</key>
<map>
<key>Comment</key>
<string>Everyone can copy the newly created objects</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>FPSLogFrequency</key>
<map>
<key>Comment</key>
@@ -7277,6 +7492,17 @@ This should be as low as possible, but too low may break functionality</string>
<key>Value</key>
<integer>24</integer>
</map>
<key>RadarColumnVoiceWidth</key>
<map>
<key>Comment</key>
<string>Width for radar's voice status column</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>S32</string>
<key>Value</key>
<integer>24</integer>
</map>
<key>RadarColumnAgeWidth</key>
<map>
<key>Comment</key>
@@ -7354,6 +7580,17 @@ This should be as low as possible, but too low may break functionality</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>RadarColumnVoiceHidden</key>
<map>
<key>Comment</key>
<string>Hide radar's voice status column</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<boolean>0</boolean>
</map>
<key>RadarColumnAgeHidden</key>
<map>
<key>Comment</key>
@@ -8320,6 +8557,17 @@ This should be as low as possible, but too low may break functionality</string>
<key>Value</key>
<real>1.0</real>
</map>
<key>FlycamBuildModeScale</key>
<map>
<key>Comment</key>
<string>Scale factor to apply to flycam movements when in build mode.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>F32</string>
<key>Value</key>
<real>0.3333333</real>
</map>
<key>FlycamFeathering</key>
<map>
<key>Comment</key>
@@ -10624,39 +10872,6 @@ This should be as low as possible, but too low may break functionality</string>
<key>Value</key>
<integer>20</integer>
</map>
<key>NextOwnerCopy</key>
<map>
<key>Comment</key>
<string>Newly created objects can be copied by next owner</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>NextOwnerModify</key>
<map>
<key>Comment</key>
<string>Newly created objects can be modified by next owner</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>NextOwnerTransfer</key>
<map>
<key>Comment</key>
<string>Newly created objects can be resold or given away by next owner</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>1</integer>
</map>
<key>NewCacheLocation</key>
<map>
<key>Comment</key>
@@ -11123,22 +11338,6 @@ This should be as low as possible, but too low may break functionality</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>PermissionsManagerRect</key>
<map>
<key>Comment</key>
<string>Rectangle for permissions manager window</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Rect</string>
<key>Value</key>
<array>
<integer>0</integer>
<integer>85</integer>
<integer>300</integer>
<integer>0</integer>
</array>
</map>
<key>PickerContextOpacity</key>
<map>
<key>Comment</key>
@@ -14490,17 +14689,6 @@ This should be as low as possible, but too low may break functionality</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>ShareWithGroup</key>
<map>
<key>Comment</key>
<string>Newly created objects are shared with the currently active group</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>ShowActiveSpeakers</key>
<map>
<key>Comment</key>
@@ -14559,9 +14747,9 @@ This should be as low as possible, but too low may break functionality</string>
<key>ShowChatHistory</key>
<map>
<key>Comment</key>
<string/>
<string>Open local chat window on login</string>
<key>Persist</key>
<integer>0</integer>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
@@ -14570,14 +14758,25 @@ This should be as low as possible, but too low may break functionality</string>
<key>ShowCommunicate</key>
<map>
<key>Comment</key>
<string/>
<string>Open communicate window on login</string>
<key>Persist</key>
<integer>0</integer>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>ShowContacts</key>
<map>
<key>Comment</key>
<string>Open contacts window on login</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<boolean>0</boolean>
</map>
<key>ShowConsoleWindow</key>
<map>
<key>Comment</key>
@@ -17726,6 +17925,336 @@ This should be as low as possible, but too low may break functionality</string>
<integer>0</integer>
</array>
</map>
<key>ObjectsNextOwnerCopy</key>
<map>
<key>Comment</key>
<string>Newly created objects can be copied by next owner</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>ObjectsNextOwnerModify</key>
<map>
<key>Comment</key>
<string>Newly created objects can be modified by next owner</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>ObjectsNextOwnerTransfer</key>
<map>
<key>Comment</key>
<string>Newly created objects can be resold or given away by next owner</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>1</integer>
</map>
<key>ObjectsEveryoneCopy</key>
<map>
<key>Comment</key>
<string>Everyone can copy the newly created object</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>ObjectsShareWithGroup</key>
<map>
<key>Comment</key>
<string>Newly created objects are shared with the currently active group</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>UploadsNextOwnerCopy</key>
<map>
<key>Comment</key>
<string>Newly uploaded items can be copied by next owner</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>UploadsNextOwnerModify</key>
<map>
<key>Comment</key>
<string>Newly uploaded items can be modified by next owner</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>UploadsNextOwnerTransfer</key>
<map>
<key>Comment</key>
<string>Newly uploaded items can be resold or given away by next owner</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>1</integer>
</map>
<key>UploadsEveryoneCopy</key>
<map>
<key>Comment</key>
<string>Everyone can copy the newly uploaded item</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>UploadsShareWithGroup</key>
<map>
<key>Comment</key>
<string>Newly uploaded items are shared with the currently active group</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>ScriptsNextOwnerCopy</key>
<map>
<key>Comment</key>
<string>Newly created scripts can be copied by next owner</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>ScriptsNextOwnerModify</key>
<map>
<key>Comment</key>
<string>Newly created scripts can be modified by next owner</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>ScriptsNextOwnerTransfer</key>
<map>
<key>Comment</key>
<string>Newly created scripts can be resold or given away by next owner</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>1</integer>
</map>
<key>ScriptsEveryoneCopy</key>
<map>
<key>Comment</key>
<string>Everyone can copy the newly created script</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>ScriptsShareWithGroup</key>
<map>
<key>Comment</key>
<string>Newly created scripts are shared with the currently active group</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>NotecardsNextOwnerCopy</key>
<map>
<key>Comment</key>
<string>Newly created notecards can be copied by next owner</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>1</integer>
</map>
<key>NotecardsNextOwnerModify</key>
<map>
<key>Comment</key>
<string>Newly created notecards can be modified by next owner</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>1</integer>
</map>
<key>NotecardsNextOwnerTransfer</key>
<map>
<key>Comment</key>
<string>Newly created notecards can be resold or given away by next owner</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>1</integer>
</map>
<key>NotecardsEveryoneCopy</key>
<map>
<key>Comment</key>
<string>Everyone can copy the newly created notecard</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>NotecardsShareWithGroup</key>
<map>
<key>Comment</key>
<string>Newly created scripts are shared with the currently active group</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>GesturesNextOwnerCopy</key>
<map>
<key>Comment</key>
<string>Newly created gestures can be copied by next owner</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>1</integer>
</map>
<key>GesturesNextOwnerModify</key>
<map>
<key>Comment</key>
<string>Newly created gestures can be modified by next owner</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>1</integer>
</map>
<key>GesturesNextOwnerTransfer</key>
<map>
<key>Comment</key>
<string>Newly created gestures can be resold or given away by next owner</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>1</integer>
</map>
<key>GesturesEveryoneCopy</key>
<map>
<key>Comment</key>
<string>Everyone can copy the newly created gesture</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>GesturesShareWithGroup</key>
<map>
<key>Comment</key>
<string>Newly created gestures are shared with the currently active group</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>WearablesNextOwnerCopy</key>
<map>
<key>Comment</key>
<string>Newly created clothing or body part can be copied by next owner</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>WearablesNextOwnerModify</key>
<map>
<key>Comment</key>
<string>Newly created clothing or body part can be modified by next owner</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>WearablesNextOwnerTransfer</key>
<map>
<key>Comment</key>
<string>Newly created clothing or body part can be resold or given away by next owner</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>1</integer>
</map>
<key>WearablesEveryoneCopy</key>
<map>
<key>Comment</key>
<string>Everyone can copy the newly created clothing or body part</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>WearablesShareWithGroup</key>
<map>
<key>Comment</key>
<string>Newly created clothing or body part is shared with the currently active group</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>SimulateFBOFailure</key>
<map>
<key>Comment</key>
@@ -17998,6 +18527,62 @@ This should be as low as possible, but too low may break functionality</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>EveryoneCopy</key>
<map>
<key>Comment</key>
<string>(obsolete) Everyone can copy the newly created objects</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>NextOwnerCopy</key>
<map>
<key>Comment</key>
<string>(obsolete) Newly created objects can be copied by next owner</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>NextOwnerModify</key>
<map>
<key>Comment</key>
<string>(obsolete) Newly created objects can be modified by next owner</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>NextOwnerTransfer</key>
<map>
<key>Comment</key>
<string>(obsolete) Newly created objects can be resold or given away by next owner</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>1</integer>
</map>
<key>ShareWithGroup</key>
<map>
<key>Comment</key>
<string>(obsolete) Newly created objects are shared with the currently active group</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
</map>
</llsd>

File diff suppressed because it is too large Load Diff

View File

@@ -406,6 +406,17 @@
<key>Value</key>
<string>This is an autoresponse!</string>
</map>
<key>AutoresponseOnlyIfAway</key>
<map>
<key>Comment</key>
<string>When true, enabled autoresponses (not busy responses) will only be sent while in away (or Fake Away) mode. Does not apply to autoresponses to muted persons, they don't need to know you're away.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>BusyModeResponse</key>
<map>
<key>Comment</key>
@@ -452,7 +463,40 @@
</map>
<key>DefaultUploadPermissionsConverted</key>
<map>
<key>Comment</key>
<string>Default upload permissions have been converted to default creation permissions</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>EveryoneExport</key>
<map>
<key>Comment</key>
<string>(obsolete) Whether content you upload has exportability permission by default</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>ObjectsEveryoneExport</key>
<map>
<key>Comment</key>
<string>Whether objects you create have exportability permission by default</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>UploadsEveryoneExport</key>
<map>
<key>Comment</key>
<string>Whether content you upload has exportability permission by default</string>
@@ -463,6 +507,50 @@
<key>Value</key>
<integer>0</integer>
</map>
<key>ScriptsEveryoneExport</key>
<map>
<key>Comment</key>
<string>Whether scripts you make have exportability permission by default</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>NotecardsEveryoneExport</key>
<map>
<key>Comment</key>
<string>Whether notecards you make have exportability permission by default</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>GesturesEveryoneExport</key>
<map>
<key>Comment</key>
<string>Whether gestures you make have exportability permission by default</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>WearablesEveryoneExport</key>
<map>
<key>Comment</key>
<string>Whether wearables you make have exportability permission by default</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>RLVaLoginLastLocation</key>
<map>
<key>Comment</key>
@@ -723,6 +811,27 @@
<key>Value</key>
<string></string>
</map>
<key>EmergencyTeleportLandmark</key>
<map>
<key>Comment</key>
<string>UUID of the landmark to teleport to in the last twenty seconds before a region will restart, empty is none.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>String</string>
<key>Value</key>
<string/>
</map>
<key>EmergencyTeleportLandmarkBackup</key>
<map>
<key>Comment</key>
<string>UUID of the landmark to teleport to in the last twenty seconds before a region will restart if you're already in the region of EmergencyTeleportLandmark or if EmergencyTeleportLandmark is set but canot be found, empty is none.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>String</string>
<key>Value</key>
<string/>
</map>
</map>
</llsd>

View File

@@ -37,6 +37,7 @@
#include "llagent.h"
#include "llcolorswatch.h"
#include "llcombobox.h"
#include "llfloaterautoreplacesettings.h"
#include "llradiogroup.h"
#include "lluictrlfactory.h"
#include "llviewercontrol.h"
@@ -88,10 +89,8 @@ LLPrefsAscentChat::LLPrefsAscentChat()
childSetEnabled("reset_antispam", started);
getChild<LLUICtrl>("reset_antispam")->setCommitCallback(boost::bind(NACLAntiSpamRegistry::purgeAllQueues));
getChild<LLUICtrl>("enable_as")->setCommitCallback(boost::bind(&LLPrefsAscentChat::onCommitEnableAS, this, _2));
getChild<LLUICtrl>("antispam_checkbox")->setCommitCallback(boost::bind(&LLPrefsAscentChat::onCommitDialogBlock, this, _1, _2));
getChild<LLUICtrl>("Group Invites")->setCommitCallback(boost::bind(&LLPrefsAscentChat::onCommitDialogBlock, this, _1, _2));
getChild<LLUICtrl>("autoreplace")->setCommitCallback(boost::bind(LLFloaterAutoReplaceSettings::showInstance, LLSD()));
getChild<LLUICtrl>("KeywordsOn")->setCommitCallback(boost::bind(&LLPrefsAscentChat::onCommitKeywords, this, _1));
getChild<LLUICtrl>("KeywordsList")->setCommitCallback(boost::bind(&LLPrefsAscentChat::onCommitKeywords, this, _1));
getChild<LLUICtrl>("KeywordsSound")->setCommitCallback(boost::bind(&LLPrefsAscentChat::onCommitKeywords, this, _1));
@@ -184,39 +183,6 @@ void LLPrefsAscentChat::onCommitTimeDate(LLUICtrl* ctrl)
gSavedSettings.setString("TimestampFormat", timestamp);
}
void LLPrefsAscentChat::onCommitEnableAS(const LLSD& value)
{
bool enabled = value.asBoolean();
childSetEnabled("spammsg_checkbox", enabled);
childSetEnabled("antispamtime", enabled);
childSetEnabled("antispamamount", enabled);
childSetEnabled("antispamsoundmulti", enabled);
childSetEnabled("antispamsoundpreloadmulti", enabled);
childSetEnabled("antispamnewlines", enabled);
childSetEnabled("Notify On Spam", enabled);
}
void LLPrefsAscentChat::onCommitDialogBlock(LLUICtrl* ctrl, const LLSD& value)
{
childSetEnabled("Group Fee Invites", !childGetValue("antispam_checkbox").asBoolean() && !childGetValue("Group Invites").asBoolean());
bool enabled = value.asBoolean();
if (ctrl->getName() == "antispam_checkbox")
{
childSetEnabled("Block All Dialogs From", !enabled);
childSetEnabled("Alerts", !enabled);
childSetEnabled("Friendship Offers", !enabled);
childSetEnabled("Group Invites", !enabled);
childSetEnabled("Group Notices", !enabled);
childSetEnabled("Item Offers", !enabled);
childSetEnabled("Scripts", !enabled);
childSetEnabled("Teleport Offers", !enabled);
childSetEnabled("Teleport Requests", !enabled);
childSetEnabled("Except those from:", !enabled);
childSetEnabled("My objects", !enabled);
childSetEnabled("My friends", !enabled);
}
}
void LLPrefsAscentChat::onCommitKeywords(LLUICtrl* ctrl)
{
if (ctrl->getName() == "KeywordsOn")
@@ -296,6 +262,7 @@ void LLPrefsAscentChat::refreshValues()
mOneLineGroupButt = gSavedSettings.getBOOL("UseConciseGroupChatButtons");
mOneLineConfButt = gSavedSettings.getBOOL("UseConciseConferenceButtons");
mOnlyComm = gSavedSettings.getBOOL("CommunicateSpecificShortcut");
mLegacyEndScroll = gSavedSettings.getBOOL("LiruLegacyScrollToEnd");
mItalicizeActions = gSavedSettings.getBOOL("LiruItalicizeActions");
mLegacyLogLaunch = gSavedSettings.getBOOL("LiruLegacyLogLaunch");
mFriendNames = gSavedSettings.getS32("FriendNameSystem");
@@ -392,26 +359,6 @@ void LLPrefsAscentChat::refresh()
if (combo = getChild<LLComboBox>("speaker_namesystem_combobox"))
combo->setCurrentByIndex(mSpeakerNames);
//Antispam ------------------------------------------------------------------------
// sensitivity tuners
childSetEnabled("spammsg_checkbox", mEnableAS);
childSetEnabled("antispamtime", mEnableAS);
childSetEnabled("antispamamount", mEnableAS);
childSetEnabled("antispamsoundmulti", mEnableAS);
childSetEnabled("antispamsoundpreloadmulti", mEnableAS);
childSetEnabled("antispamnewlines", mEnableAS);
childSetEnabled("Notify On Spam", mEnableAS);
// dialog blocking tuners
childSetEnabled("Block All Dialogs From", !mBlockDialogSpam);
childSetEnabled("Alerts", !mBlockDialogSpam);
childSetEnabled("Friendship Offers", !mBlockDialogSpam);
childSetEnabled("Group Invites", !mBlockDialogSpam);
childSetEnabled("Group Fee Invites", !mBlockDialogSpam && !mBlockGroupInviteSpam);
childSetEnabled("Group Notices", !mBlockDialogSpam);
childSetEnabled("Item Offers", !mBlockDialogSpam);
childSetEnabled("Scripts", !mBlockDialogSpam);
childSetEnabled("Teleport Offers", !mBlockDialogSpam);
//Text Options ------------------------------------------------------------------------
combo = getChild<LLComboBox>("SpellBase");
@@ -551,6 +498,7 @@ void LLPrefsAscentChat::cancel()
gSavedSettings.setBOOL("UseConciseGroupChatButtons", mOneLineGroupButt);
gSavedSettings.setBOOL("UseConciseConferenceButtons", mOneLineConfButt);
gSavedSettings.setBOOL("CommunicateSpecificShortcut", mOnlyComm);
gSavedSettings.setBOOL("LiruLegacyScrollToEnd", mLegacyEndScroll);
gSavedSettings.setBOOL("LiruItalicizeActions", mItalicizeActions);
gSavedSettings.setBOOL("LiruLegacyLogLaunch", mLegacyLogLaunch);
gSavedSettings.setS32("FriendNameSystem", mFriendNames);

View File

@@ -52,8 +52,6 @@ protected:
void onSpellEditCustom();
void onSpellBaseComboBoxCommit(const LLSD& value);
void onCommitTimeDate(LLUICtrl* ctrl);
void onCommitEnableAS(const LLSD& value);
void onCommitDialogBlock(LLUICtrl* ctrl, const LLSD& value);
void onCommitKeywords(LLUICtrl* ctrl);
private:
@@ -86,6 +84,7 @@ private:
bool mOneLineGroupButt;
bool mOneLineConfButt;
bool mOnlyComm;
bool mLegacyEndScroll;
bool mItalicizeActions;
bool mLegacyLogLaunch;
S32 mFriendNames;

View File

@@ -51,37 +51,35 @@ LLPrefsAscentSys::LLPrefsAscentSys()
LLUICtrlFactory::getInstance()->buildPanel(this, "panel_preferences_ascent_system.xml");
//General -----------------------------------------------------------------------------
getChild<LLUICtrl>("speed_rez_check")->setCommitCallback(boost::bind(&LLPrefsAscentSys::onCommitCheckBox, this, _1, _2));
getChild<LLUICtrl>("double_click_teleport_check")->setCommitCallback(boost::bind(&LLPrefsAscentSys::onCommitCheckBox, this, _1, _2));
getChild<LLUICtrl>("show_look_at_check")->setCommitCallback(boost::bind(&LLPrefsAscentSys::onCommitCheckBox, this, _1, _2));
getChild<LLUICtrl>("enable_clouds")->setCommitCallback(boost::bind(&LLPrefsAscentSys::onCommitCheckBox, this, _1, _2));
getChild<LLUICtrl>("power_user_check")->setCommitCallback(boost::bind(&LLPrefsAscentSys::onCommitCheckBox, this, _1, _2));
getChild<LLUICtrl>("power_user_confirm_check")->setCommitCallback(boost::bind(&LLPrefsAscentSys::onCommitCheckBox, this, _1, _2));
//Command Line ------------------------------------------------------------------------
getChild<LLUICtrl>("chat_cmd_toggle")->setCommitCallback(boost::bind(&LLPrefsAscentSys::onCommitCmdLine, this, _1, _2));
getChild<LLUICtrl>("AscentCmdLinePos")->setCommitCallback(boost::bind(&LLPrefsAscentSys::onCommitCmdLine, this, _1, _2));
getChild<LLUICtrl>("AscentCmdLineGround")->setCommitCallback(boost::bind(&LLPrefsAscentSys::onCommitCmdLine, this, _1, _2));
getChild<LLUICtrl>("AscentCmdLineHeight")->setCommitCallback(boost::bind(&LLPrefsAscentSys::onCommitCmdLine, this, _1, _2));
getChild<LLUICtrl>("AscentCmdLineTeleportHome")->setCommitCallback(boost::bind(&LLPrefsAscentSys::onCommitCmdLine, this, _1, _2));
getChild<LLUICtrl>("AscentCmdLineRezPlatform")->setCommitCallback(boost::bind(&LLPrefsAscentSys::onCommitCmdLine, this, _1, _2));
getChild<LLUICtrl>("AscentCmdLineCalc")->setCommitCallback(boost::bind(&LLPrefsAscentSys::onCommitCmdLine, this, _1, _2));
getChild<LLUICtrl>("AscentCmdLineClearChat")->setCommitCallback(boost::bind(&LLPrefsAscentSys::onCommitCmdLine, this, _1, _2));
getChild<LLUICtrl>("AscentCmdLineDrawDistance")->setCommitCallback(boost::bind(&LLPrefsAscentSys::onCommitCmdLine, this, _1, _2));
getChild<LLUICtrl>("AscentCmdTeleportToCam")->setCommitCallback(boost::bind(&LLPrefsAscentSys::onCommitCmdLine, this, _1, _2));
getChild<LLUICtrl>("AscentCmdLineKeyToName")->setCommitCallback(boost::bind(&LLPrefsAscentSys::onCommitCmdLine, this, _1, _2));
getChild<LLUICtrl>("AscentCmdLineOfferTp")->setCommitCallback(boost::bind(&LLPrefsAscentSys::onCommitCmdLine, this, _1, _2));
getChild<LLUICtrl>("AscentCmdLineMapTo")->setCommitCallback(boost::bind(&LLPrefsAscentSys::onCommitCmdLine, this, _1, _2));
getChild<LLUICtrl>("AscentCmdLineTP2")->setCommitCallback(boost::bind(&LLPrefsAscentSys::onCommitCmdLine, this, _1, _2));
getChild<LLUICtrl>("SinguCmdLineAway")->setCommitCallback(boost::bind(&LLPrefsAscentSys::onCommitCmdLine, this, _1, _2));
getChild<LLUICtrl>("SinguCmdLineURL")->setCommitCallback(boost::bind(&LLPrefsAscentSys::onCommitCmdLine, this, _1, _2));
commit_callback_t lineEditorControl(boost::bind(&LLControlGroup::setString, boost::ref(gSavedSettings), boost::bind(&LLUICtrl::getName, _1), _2));
getChild<LLUICtrl>("AscentCmdLinePos")->setCommitCallback(lineEditorControl);
getChild<LLUICtrl>("AscentCmdLineGround")->setCommitCallback(lineEditorControl);
getChild<LLUICtrl>("AscentCmdLineHeight")->setCommitCallback(lineEditorControl);
getChild<LLUICtrl>("AscentCmdLineTeleportHome")->setCommitCallback(lineEditorControl);
getChild<LLUICtrl>("AscentCmdLineRezPlatform")->setCommitCallback(lineEditorControl);
getChild<LLUICtrl>("AscentCmdLineCalc")->setCommitCallback(lineEditorControl);
getChild<LLUICtrl>("AscentCmdLineClearChat")->setCommitCallback(lineEditorControl);
getChild<LLUICtrl>("AscentCmdLineDrawDistance")->setCommitCallback(lineEditorControl);
getChild<LLUICtrl>("AscentCmdTeleportToCam")->setCommitCallback(lineEditorControl);
getChild<LLUICtrl>("AscentCmdLineKeyToName")->setCommitCallback(lineEditorControl);
getChild<LLUICtrl>("AscentCmdLineOfferTp")->setCommitCallback(lineEditorControl);
getChild<LLUICtrl>("AscentCmdLineMapTo")->setCommitCallback(lineEditorControl);
getChild<LLUICtrl>("AscentCmdLineTP2")->setCommitCallback(lineEditorControl);
getChild<LLUICtrl>("SinguCmdLineAway")->setCommitCallback(lineEditorControl);
getChild<LLUICtrl>("SinguCmdLineRegionSay")->setCommitCallback(lineEditorControl);
getChild<LLUICtrl>("SinguCmdLineURL")->setCommitCallback(lineEditorControl);
//Security ----------------------------------------------------------------------------
getChild<LLUICtrl>("disable_click_sit_check")->setCommitCallback(boost::bind(&LLPrefsAscentSys::onCommitCheckBox, this, _1, _2));
getChild<LLUICtrl>("UISndRestart")->setCommitCallback(lineEditorControl);
//Build -------------------------------------------------------------------------------
getChild<LLUICtrl>("next_owner_copy")->setCommitCallback(boost::bind(&LLPrefsAscentSys::onCommitCheckBox, this, _1, _2));
childSetEnabled("next_owner_transfer", gSavedSettings.getBOOL("NextOwnerCopy"));
getChild<LLUICtrl>("script_next_owner_copy")->setCommitCallback(boost::bind(&LLPrefsAscentSys::onCommitCheckBox, this, _1, _2));
getChild<LLUICtrl>("material")->setCommitCallback(boost::bind(&LLPrefsAscentSys::onCommitComboBox, this, _1, _2));
getChild<LLUICtrl>("combobox shininess")->setCommitCallback(boost::bind(&LLPrefsAscentSys::onCommitComboBox, this, _1, _2));
getChild<LLTextureCtrl>("texture control")->setDefaultImageAssetID(LLUUID(gSavedSettings.getString("EmeraldBuildPrefs_Texture")));
@@ -101,21 +99,7 @@ void LLPrefsAscentSys::onCommitCheckBox(LLUICtrl* ctrl, const LLSD& value)
const std::string name = ctrl->getName();
bool enabled = value.asBoolean();
if (name == "speed_rez_check")
{
childSetEnabled("speed_rez_interval", enabled);
childSetEnabled("speed_rez_seconds", enabled);
}
else if (name == "double_click_teleport_check")
{
childSetEnabled("center_after_teleport_check", enabled);
childSetEnabled("offset_teleport_check", enabled);
}
else if (name == "enable_clouds")
{
childSetEnabled("enable_classic_clouds", enabled);
}
else if (name == "power_user_check")
if (name == "power_user_check")
{
childSetEnabled("power_user_confirm_check", enabled);
childSetValue("power_user_confirm_check", false);
@@ -135,57 +119,13 @@ void LLPrefsAscentSys::onCommitCheckBox(LLUICtrl* ctrl, const LLSD& value)
LLFloaterChat::addChat(chat);
}
}
else if (name == "disable_click_sit_check")
{
childSetEnabled("disable_click_sit_own_check", !enabled);
}
else if (name == "next_owner_copy")
{
if (!enabled) gSavedSettings.setBOOL("NextOwnerTransfer", true);
childSetEnabled("next_owner_transfer", enabled);
if (!enabled) gSavedSettings.setBOOL("ObjectsNextOwnerTransfer", true);
}
}
void LLPrefsAscentSys::onCommitCmdLine(LLUICtrl* ctrl, const LLSD& value)
{
const std::string& name = ctrl->getName();
if (name == "chat_cmd_toggle")
{
bool enabled = value.asBoolean();
childSetEnabled("cmd_line_text_2", enabled);
childSetEnabled("cmd_line_text_3", enabled);
childSetEnabled("cmd_line_text_4", enabled);
childSetEnabled("cmd_line_text_5", enabled);
childSetEnabled("cmd_line_text_6", enabled);
childSetEnabled("cmd_line_text_7", enabled);
childSetEnabled("cmd_line_text_8", enabled);
childSetEnabled("cmd_line_text_9", enabled);
childSetEnabled("cmd_line_text_10", enabled);
childSetEnabled("cmd_line_text_11", enabled);
childSetEnabled("cmd_line_text_12", enabled);
childSetEnabled("cmd_line_text_13", enabled);
childSetEnabled("cmd_line_text_15", enabled);
childSetEnabled("AscentCmdLinePos", enabled);
childSetEnabled("AscentCmdLineGround", enabled);
childSetEnabled("AscentCmdLineHeight", enabled);
childSetEnabled("AscentCmdLineTeleportHome", enabled);
childSetEnabled("AscentCmdLineRezPlatform", enabled);
childSetEnabled("AscentPlatformSize", enabled);
childSetEnabled("AscentCmdLineCalc", enabled);
childSetEnabled("AscentCmdLineClearChat", enabled);
childSetEnabled("AscentCmdLineDrawDistance", enabled);
childSetEnabled("AscentCmdTeleportToCam", enabled);
childSetEnabled("AscentCmdLineKeyToName", enabled);
childSetEnabled("AscentCmdLineOfferTp", enabled);
childSetEnabled("AscentCmdLineMapTo", enabled);
childSetEnabled("map_to_keep_pos", enabled);
childSetEnabled("AscentCmdLineTP2", enabled);
childSetEnabled("SinguCmdLineAway", enabled);
childSetEnabled("SinguCmdLineURL", enabled);
}
else
else if (name == "script_next_owner_copy")
{
gSavedSettings.setString(name, value); // Singu Note: Keep commandline settings using the same name as their settings
if (!enabled) gSavedSettings.setBOOL("ScriptsNextOwnerTransfer", true);
}
}
@@ -244,6 +184,7 @@ void LLPrefsAscentSys::refreshValues()
mCmdMapToKeepPos = gSavedSettings.getBOOL("AscentMapToKeepPos");
mCmdLineTP2 = gSavedSettings.getString("AscentCmdLineTP2");
mCmdLineAway = gSavedSettings.getString("SinguCmdLineAway");
mCmdLineRegionSay = gSavedSettings.getString("SinguCmdLineRegionSay");
mCmdLineURL = gSavedSettings.getString("SinguCmdLineURL");
//Security ----------------------------------------------------------------------------
@@ -251,13 +192,20 @@ void LLPrefsAscentSys::refreshValues()
mDisablePointAtAndBeam = gSavedSettings.getBOOL("DisablePointAtAndBeam");
mPrivateLookAt = gSavedSettings.getBOOL("PrivateLookAt");
mShowLookAt = gSavedSettings.getBOOL("AscentShowLookAt");
mLookAtNames = gSavedSettings.getS32("LookAtNameSystem");
mLookAtLines = gSavedSettings.getBOOL("AlchemyLookAtLines");
mQuietSnapshotsToDisk = gSavedSettings.getBOOL("QuietSnapshotsToDisk");
mAnnounceBumps = gSavedSettings.getBOOL("AnnounceBumps");
mDetachBridge = gSavedSettings.getBOOL("SGDetachBridge");
mRevokePermsOnStandUp = gSavedSettings.getBOOL("RevokePermsOnStandUp");
mDisableClickSit = gSavedSettings.getBOOL("DisableClickSit");
mDisableClickSitOtherOwner = gSavedSettings.getBOOL("DisableClickSitOtherOwner");
mDisplayScriptJumps = gSavedSettings.getBOOL("AscentDisplayTotalScriptJumps");
mNumScriptDiff = gSavedSettings.getF32("Ascentnumscriptdiff");
mRestartMinimized = gSavedSettings.getBOOL("LiruRegionRestartMinimized");
mRestartSound = gSavedSettings.getString("UISndRestart");
mLandmark = gSavedPerAccountSettings.getString("EmergencyTeleportLandmark");
mLandmarkBackup = gSavedPerAccountSettings.getString("EmergencyTeleportLandmarkBackup");
//Build -------------------------------------------------------------------------------
mAlpha = gSavedSettings.getF32("EmeraldBuildPrefs_Alpha");
@@ -266,9 +214,12 @@ void LLPrefsAscentSys::refreshValues()
mGlow = gSavedSettings.getF32("EmeraldBuildPrefs_Glow");
mItem = gSavedPerAccountSettings.getString("EmeraldBuildPrefs_Item");
mMaterial = gSavedSettings.getString("BuildPrefs_Material");
mNextCopy = gSavedSettings.getBOOL("NextOwnerCopy");
mNextMod = gSavedSettings.getBOOL("NextOwnerModify");
mNextTrans = gSavedSettings.getBOOL("NextOwnerTransfer");
mNextCopy = gSavedSettings.getBOOL("ObjectsNextOwnerCopy");
mNextMod = gSavedSettings.getBOOL("ObjectsNextOwnerModify");
mNextTrans = gSavedSettings.getBOOL("ObjectsNextOwnerTransfer");
mScriptNextCopy = gSavedSettings.getBOOL("ScriptsNextOwnerCopy");
mScriptNextMod = gSavedSettings.getBOOL("ScriptsNextOwnerModify");
mScriptNextTrans = gSavedSettings.getBOOL("ScriptsNextOwnerTransfer");
mShiny = gSavedSettings.getString("EmeraldBuildPrefs_Shiny");
mTemporary = gSavedSettings.getBOOL("EmeraldBuildPrefs_Temporary");
mTexture = gSavedSettings.getString("EmeraldBuildPrefs_Texture");
@@ -282,46 +233,14 @@ void LLPrefsAscentSys::refreshValues()
void LLPrefsAscentSys::refresh()
{
//General -----------------------------------------------------------------------------
childSetEnabled("center_after_teleport_check", mDoubleClickTeleport);
childSetEnabled("offset_teleport_check", mDoubleClickTeleport);
childSetValue("power_user_check", mPowerUser);
childSetValue("power_user_confirm_check", mPowerUser);
childSetEnabled("speed_rez_interval", mSpeedRez);
childSetEnabled("speed_rez_seconds", mSpeedRez);
if (LLUICtrl* ctrl = getChild<LLUICtrl>("power_user_confirm_check"))
{
ctrl->setEnabled(mPowerUser);
ctrl->setValue(mPowerUser);
}
//Command Line ------------------------------------------------------------------------
childSetEnabled("cmd_line_text_2", mCmdLine);
childSetEnabled("cmd_line_text_3", mCmdLine);
childSetEnabled("cmd_line_text_4", mCmdLine);
childSetEnabled("cmd_line_text_5", mCmdLine);
childSetEnabled("cmd_line_text_6", mCmdLine);
childSetEnabled("cmd_line_text_7", mCmdLine);
childSetEnabled("cmd_line_text_8", mCmdLine);
childSetEnabled("cmd_line_text_9", mCmdLine);
childSetEnabled("cmd_line_text_10", mCmdLine);
childSetEnabled("cmd_line_text_11", mCmdLine);
childSetEnabled("cmd_line_text_12", mCmdLine);
childSetEnabled("cmd_line_text_13", mCmdLine);
childSetEnabled("cmd_line_text_15", mCmdLine);
childSetEnabled("AscentCmdLinePos", mCmdLine);
childSetEnabled("AscentCmdLineGround", mCmdLine);
childSetEnabled("AscentCmdLineHeight", mCmdLine);
childSetEnabled("AscentCmdLineTeleportHome", mCmdLine);
childSetEnabled("AscentCmdLineRezPlatform", mCmdLine);
childSetEnabled("AscentPlatformSize", mCmdLine);
childSetEnabled("AscentCmdLineCalc", mCmdLine);
childSetEnabled("AscentCmdLineClearChat", mCmdLine);
childSetEnabled("AscentCmdLineDrawDistance", mCmdLine);
childSetEnabled("AscentCmdTeleportToCam", mCmdLine);
childSetEnabled("AscentCmdLineKeyToName", mCmdLine);
childSetEnabled("AscentCmdLineOfferTp", mCmdLine);
childSetEnabled("AscentCmdLineMapTo", mCmdLine);
childSetEnabled("map_to_keep_pos", mCmdLine);
childSetEnabled("AscentCmdLineTP2", mCmdLine);
childSetEnabled("SinguCmdLineAway", mCmdLine);
childSetEnabled("SinguCmdLineURL", mCmdLine);
//Security ----------------------------------------------------------------------------
//Command Line ----------------------------------------------------------------------------
childSetValue("AscentCmdLinePos", mCmdLinePos);
childSetValue("AscentCmdLineGround", mCmdLineGround);
childSetValue("AscentCmdLineHeight", mCmdLineHeight);
@@ -336,8 +255,15 @@ void LLPrefsAscentSys::refresh()
childSetValue("AscentCmdLineMapTo", mCmdLineMapTo);
childSetValue("AscentCmdLineTP2", mCmdLineTP2);
childSetValue("SinguCmdLineAway", mCmdLineAway);
childSetValue("SinguCmdLineRegionSay", mCmdLineRegionSay);
childSetValue("SinguCmdLineURL", mCmdLineURL);
//Security ----------------------------------------------------------------------------
getChildView("UISndRestart")->setValue(mRestartSound);
if (LLComboBox* combo = getChild<LLComboBox>("lookat_namesystem_combobox"))
combo->setValue(mLookAtNames);
//Build -------------------------------------------------------------------------------
childSetValue("alpha", mAlpha);
getChild<LLColorSwatchCtrl>("colorswatch")->setOriginal(mColor);
@@ -400,6 +326,7 @@ void LLPrefsAscentSys::cancel()
gSavedSettings.setBOOL("AscentMapToKeepPos", mCmdMapToKeepPos);
gSavedSettings.setString("AscentCmdLineTP2", mCmdLineTP2);
gSavedSettings.setString("SinguCmdLineAway", mCmdLineAway);
gSavedSettings.setString("SinguCmdLineRegionSay", mCmdLineRegionSay);
gSavedSettings.setString("SinguCmdLineURL", mCmdLineURL);
//Security ----------------------------------------------------------------------------
@@ -407,13 +334,20 @@ void LLPrefsAscentSys::cancel()
gSavedSettings.setBOOL("DisablePointAtAndBeam", mDisablePointAtAndBeam);
gSavedSettings.setBOOL("PrivateLookAt", mPrivateLookAt);
gSavedSettings.setBOOL("AscentShowLookAt", mShowLookAt);
gSavedSettings.setS32("LookAtNameSystem", mLookAtNames);
gSavedSettings.setBOOL("AlchemyLookAtLines", mLookAtLines);
gSavedSettings.setBOOL("QuietSnapshotsToDisk", mQuietSnapshotsToDisk);
gSavedSettings.setBOOL("AnnounceBumps", mAnnounceBumps);
gSavedSettings.setBOOL("SGDetachBridge", mDetachBridge);
gSavedSettings.setBOOL("RevokePermsOnStandUp", mRevokePermsOnStandUp);
gSavedSettings.setBOOL("DisableClickSit", mDisableClickSit);
gSavedSettings.setBOOL("DisableClickSitOtherOwner", mDisableClickSitOtherOwner);
gSavedSettings.setBOOL("AscentDisplayTotalScriptJumps", mDisplayScriptJumps);
gSavedSettings.setF32("Ascentnumscriptdiff", mNumScriptDiff);
gSavedSettings.setBOOL("LiruRegionRestartMinimized", mRestartMinimized);
gSavedSettings.setString("UISndRestart", mRestartSound);
gSavedPerAccountSettings.setString("EmergencyTeleportLandmark", mLandmark);
gSavedPerAccountSettings.setString("EmergencyTeleportLandmarkBackup", mLandmarkBackup);
//Build -------------------------------------------------------------------------------
gSavedSettings.setF32("EmeraldBuildPrefs_Alpha", mAlpha);
@@ -422,9 +356,12 @@ void LLPrefsAscentSys::cancel()
gSavedSettings.setF32("EmeraldBuildPrefs_Glow", mGlow);
gSavedPerAccountSettings.setString("EmeraldBuildPrefs_Item", mItem);
gSavedSettings.setString("BuildPrefs_Material", mMaterial);
gSavedSettings.setBOOL("NextOwnerCopy", mNextCopy);
gSavedSettings.setBOOL("NextOwnerModify", mNextMod);
gSavedSettings.setBOOL("NextOwnerTransfer", mNextTrans);
gSavedSettings.setBOOL("ObjectsNextOwnerCopy", mNextCopy);
gSavedSettings.setBOOL("ObjectsNextOwnerModify", mNextMod);
gSavedSettings.setBOOL("ObjectsNextOwnerTransfer", mNextTrans);
gSavedSettings.setBOOL("ScriptsNextOwnerCopy", mScriptNextCopy);
gSavedSettings.setBOOL("ScriptsNextOwnerModify", mScriptNextMod);
gSavedSettings.setBOOL("ScriptsNextOwnerTransfer", mScriptNextTrans);
gSavedSettings.setBOOL("EmeraldBuildPrefs_Phantom", mPhantom);
gSavedSettings.setBOOL("EmeraldBuildPrefs_Physical", mPhysical);
gSavedSettings.setString("EmeraldBuildPrefs_Shiny", mShiny);

View File

@@ -48,7 +48,6 @@ public:
protected:
void onCommitCheckBox(LLUICtrl* ctrl, const LLSD& value);
void onCommitCmdLine(LLUICtrl* ctrl, const LLSD& value);
void onCommitComboBox(LLUICtrl* ctrl, const LLSD& value);
void onCommitTexturePicker(LLUICtrl* ctrl);
@@ -95,6 +94,7 @@ private:
bool mCmdMapToKeepPos;
std::string mCmdLineTP2;
std::string mCmdLineAway;
std::string mCmdLineRegionSay;
std::string mCmdLineURL;
//Security ----------------------------------------------------------------------------
@@ -102,13 +102,20 @@ private:
bool mDisablePointAtAndBeam;
bool mPrivateLookAt;
bool mShowLookAt;
S32 mLookAtNames;
bool mLookAtLines;
bool mQuietSnapshotsToDisk;
bool mAnnounceBumps;
bool mDetachBridge;
bool mRevokePermsOnStandUp;
bool mDisableClickSit;
bool mDisableClickSitOtherOwner;
bool mDisplayScriptJumps;
bool mRestartMinimized;
F32 mNumScriptDiff;
std::string mRestartSound;
std::string mLandmark;
std::string mLandmarkBackup;
//Build -------------------------------------------------------------------------------
F32 mAlpha;
@@ -120,6 +127,9 @@ private:
bool mNextCopy;
bool mNextMod;
bool mNextTrans;
bool mScriptNextCopy;
bool mScriptNextMod;
bool mScriptNextTrans;
std::string mShiny;
bool mTemporary;
std::string mTexture;

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