diff options
Diffstat (limited to 'indra')
242 files changed, 10889 insertions, 4248 deletions
diff --git a/indra/CMakeLists.txt b/indra/CMakeLists.txt index 422927704a..3be8ebafa8 100644 --- a/indra/CMakeLists.txt +++ b/indra/CMakeLists.txt @@ -82,17 +82,17 @@ if (ENABLE_MEDIA_PLUGINS) add_subdirectory(${LIBS_OPEN_PREFIX}media_plugins) endif (ENABLE_MEDIA_PLUGINS) -if (LINUX) - if (INSTALL_PROPRIETARY) - include(LLAppearanceUtility) - add_subdirectory(${LLAPPEARANCEUTILITY_SRC_DIR} ${LLAPPEARANCEUTILITY_BIN_DIR}) - endif (INSTALL_PROPRIETARY) -elseif (WINDOWS) - # cmake EXISTS requires an absolute path, see indra/cmake/Variables.cmake - if (EXISTS ${VIEWER_DIR}win_setup) - add_subdirectory(${VIEWER_DIR}win_setup) - endif (EXISTS ${VIEWER_DIR}win_setup) -endif (LINUX) +# if (LINUX) +# if (INSTALL_PROPRIETARY) +# include(LLAppearanceUtility) +# add_subdirectory(${LLAPPEARANCEUTILITY_SRC_DIR} ${LLAPPEARANCEUTILITY_BIN_DIR}) +# endif (INSTALL_PROPRIETARY) +# elseif (WINDOWS) +# # cmake EXISTS requires an absolute path, see indra/cmake/Variables.cmake +# if (EXISTS ${VIEWER_DIR}win_setup) +# add_subdirectory(${VIEWER_DIR}win_setup) +# endif (EXISTS ${VIEWER_DIR}win_setup) +# endif (LINUX) if (WINDOWS) # cmake EXISTS requires an absolute path, see indra/cmake/Variables.cmake diff --git a/indra/cmake/00-COMPILE-LINK-RUN.txt b/indra/cmake/00-COMPILE-LINK-RUN.txt index 1933072a6d..6cff0c0f28 100644 --- a/indra/cmake/00-COMPILE-LINK-RUN.txt +++ b/indra/cmake/00-COMPILE-LINK-RUN.txt @@ -162,7 +162,7 @@ Linking * Update the autobuild.xml of ALL consumers of the library. In the case of zlib, that meant updating freetype, libpng, openssl, - libxml2, fontconfig, curl, Boost, SDL, llqtwebkit, google-mock and + libxml2, fontconfig, curl, Boost, SDL2, llqtwebkit, google-mock and colladadom. * Confirm by test and observation that the consumers actually use diff --git a/indra/cmake/00-Common.cmake b/indra/cmake/00-Common.cmake index 5cb25368d2..fc18ffebb5 100644 --- a/indra/cmake/00-Common.cmake +++ b/indra/cmake/00-Common.cmake @@ -155,30 +155,11 @@ if (LINUX) -fvisibility=hidden ) - set(GCC_CLANG_COMPATIBLE_WARNINGS - -Wno-parentheses - -Wno-deprecated - -Wno-c++20-compat - -Wno-pessimizing-move - ) - - set(CLANG_WARNINGS - ${GCC_CLANG_COMPATIBLE_WARNINGS} - # Put clang specific warning configuration here - ) - - set(GCC_WARNINGS - ${GCC_CLANG_COMPATIBLE_WARNINGS} - ) - add_link_options( -Wl,--no-keep-memory -Wl,--build-id -Wl,--no-undefined ) - if (NOT GCC_DISABLE_FATAL_WARNINGS) - add_compile_options( -Werror ) - endif (NOT GCC_DISABLE_FATAL_WARNINGS) # this stops us requiring a really recent glibc at runtime add_compile_options(-fno-stack-protector) @@ -189,9 +170,6 @@ if (LINUX) -lstdc++ -lm ) - add_compile_options(${CLANG_WARNINGS}) - else() - add_compile_options(${GCC_WARNINGS}) endif() endif (LINUX) @@ -200,7 +178,7 @@ if (DARWIN) set(CLANG_DISABLE_FATAL_WARNINGS OFF) set(CMAKE_CXX_LINK_FLAGS "-Wl,-headerpad_max_install_names,-search_paths_first") set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_CXX_LINK_FLAGS}") - set(DARWIN_extra_cstar_flags "-Wno-unused-local-typedef -Wno-deprecated-declarations") + set(DARWIN_extra_cstar_flags "-Wno-deprecated-declarations") # Ensure that CMAKE_CXX_FLAGS has the correct -g debug information format -- # see Variables.cmake. string(REPLACE "-gdwarf-2" "-g${CMAKE_XCODE_ATTRIBUTE_DEBUG_INFORMATION_FORMAT}" @@ -209,22 +187,26 @@ if (DARWIN) 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. -## Really?? On developer machines too? -##set(ENABLE_SIGNING TRUE) -##set(SIGNING_IDENTITY "Developer ID Application: Linden Research, Inc.") + ## Really?? On developer machines too? + ##set(ENABLE_SIGNING TRUE) + ##set(SIGNING_IDENTITY "Developer ID Application: Linden Research, Inc.") # required for clang-15/xcode-15 since our boost package still uses deprecated std::unary_function/binary_function # see https://developer.apple.com/documentation/xcode-release-notes/xcode-15-release-notes#C++-Standard-Library add_compile_definitions(_LIBCPP_ENABLE_CXX17_REMOVED_UNARY_BINARY_FUNCTION) +endif(DARWIN) - set(GCC_WARNINGS -Wall -Wno-sign-compare -Wno-trigraphs) - - list(APPEND GCC_WARNINGS -Wno-reorder -Wno-non-virtual-dtor ) +if(LINUX OR DARWIN) + add_compile_options(-Wall -Wno-sign-compare -Wno-trigraphs -Wno-reorder -Wno-unused-but-set-variable -Wno-unused-variable -Wno-unused-local-typedef) - if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 13) - list(APPEND GCC_WARNINGS -Wno-unused-but-set-variable -Wno-unused-variable ) + if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + add_compile_options(-Wno-stringop-truncation -Wno-parentheses -Wno-c++20-compat) endif() + if (NOT GCC_DISABLE_FATAL_WARNINGS) + add_compile_options(-Werror) + endif () + add_compile_options(${GCC_WARNINGS}) add_compile_options(-m${ADDRESS_SIZE}) -endif () +endif (LINUX OR DARWIN) diff --git a/indra/cmake/CMakeLists.txt b/indra/cmake/CMakeLists.txt index 16da388e61..9017fc2fb4 100644 --- a/indra/cmake/CMakeLists.txt +++ b/indra/cmake/CMakeLists.txt @@ -52,6 +52,7 @@ set(cmake_SOURCE_FILES Prebuilt.cmake PulseAudio.cmake Python.cmake + SDL2.cmake TemplateCheck.cmake TinyEXR.cmake TinyGLTF.cmake diff --git a/indra/cmake/Copy3rdPartyLibs.cmake b/indra/cmake/Copy3rdPartyLibs.cmake index ced012426f..e98c77497b 100644 --- a/indra/cmake/Copy3rdPartyLibs.cmake +++ b/indra/cmake/Copy3rdPartyLibs.cmake @@ -54,6 +54,7 @@ if(WINDOWS) set(release_src_dir "${ARCH_PREBUILT_DIRS_RELEASE}") set(release_files openjp2.dll + SDL2.dll ) if(LLCOMMON_LINK_SHARED) @@ -106,7 +107,8 @@ if(WINDOWS) else(ADDRESS_SIZE EQUAL 32) set(redist_find_path "$ENV{VCTOOLSREDISTDIR}x64\\Microsoft.VC${MSVC_TOOLSET_VER}.CRT") endif(ADDRESS_SIZE EQUAL 32) - get_filename_component(redist_path "${redist_find_path}" ABSOLUTE) + get_filename_component(redist_path_component "${redist_find_path}" ABSOLUTE) + set(redist_path ${redist_path_component} CACHE INTERNAL "MSVC Redist Path" FORCE) MESSAGE(STATUS "VC Runtime redist path: ${redist_path}") endif (MSVC_TOOLSET_VER AND DEFINED ENV{VCTOOLSREDISTDIR}) @@ -132,12 +134,11 @@ if(WINDOWS) msvcp${MSVC_VER}_2.dll msvcp${MSVC_VER}_atomic_wait.dll msvcp${MSVC_VER}_codecvt_ids.dll - msvcr${MSVC_VER}.dll vcruntime${MSVC_VER}.dll vcruntime${MSVC_VER}_1.dll vcruntime${MSVC_VER}_threads.dll ) - if(redist_path AND EXISTS "${redist_path}/${release_msvc_file}") + if(DEFINED redist_path AND EXISTS "${redist_path}/${release_msvc_file}") MESSAGE(STATUS "Copying redist file from ${redist_path}/${release_msvc_file}") to_staging_dirs( ${redist_path} @@ -169,6 +170,8 @@ elseif(DARWIN) set(release_src_dir "${ARCH_PREBUILT_DIRS_RELEASE}") set(release_files libndofdev.dylib + libSDL2.dylib + libSDL2-2.0.dylib ) if(LLCOMMON_LINK_SHARED) @@ -197,6 +200,7 @@ elseif(LINUX) libortp.so libvivoxoal.so.1 libvivoxsdk.so + libSDL2.so ) set(slvoice_files SLVoice) diff --git a/indra/cmake/Havok.cmake b/indra/cmake/Havok.cmake index c544440adc..64e33f6c83 100644 --- a/indra/cmake/Havok.cmake +++ b/indra/cmake/Havok.cmake @@ -27,26 +27,26 @@ else (LL_DEBUG_HAVOK) endif (LL_DEBUG_HAVOK) set(HAVOK_LIBS - hkBase - hkCompat + hkgpConvexDecomposition hkGeometryUtilities - hkInternal hkSerialize hkSceneData hkpCollide hkpUtilities hkpConstraintSolver hkpDynamics - hkpInternal - hkaiInternal hkaiPathfinding hkaiAiPhysicsBridge - hkcdInternal hkcdCollide hkpVehicle hkVisualize hkaiVisualize - hkgpConvexDecomposition + hkaiInternal + hkcdInternal + hkpInternal + hkInternal + hkCompat + hkBase ) unset(HK_DEBUG_LIBRARIES) @@ -60,16 +60,22 @@ if (DEBUG_PREBUILT) # but making it pretty is a lot more work message(STATUS "${ARGN}") endfunction(DEBUG_MESSAGE) + function(DEBUG_EXEC_FUNC) + execute_process(COMMAND ${ARGN}) + endfunction(DEBUG_EXEC_FUNC) else (DEBUG_PREBUILT) # without DEBUG_PREBUILT, DEBUG_MESSAGE() is a no-op function(DEBUG_MESSAGE) endfunction(DEBUG_MESSAGE) + function(DEBUG_EXEC_FUNC) + execute_process(COMMAND ${ARGN} OUTPUT_QUIET) + endfunction(DEBUG_EXEC_FUNC) endif (DEBUG_PREBUILT) # DEBUG_EXEC() reports each execute_process() before invoking function(DEBUG_EXEC) DEBUG_MESSAGE(${ARGN}) - execute_process(COMMAND ${ARGN}) + DEBUG_EXEC_FUNC(${ARGN}) endfunction(DEBUG_EXEC) # *TODO: Figure out why we need to extract like this... @@ -79,9 +85,7 @@ foreach(HAVOK_LIB ${HAVOK_LIBS}) find_library(HAVOK_RELWITHDEBINFO_LIB_${HAVOK_LIB} ${HAVOK_LIB} PATHS ${HAVOK_RELWITHDEBINFO_LIBRARY_PATH}) if(LINUX) - set(debug_dir "${HAVOK_DEBUG_LIBRARY_PATH}/${HAVOK_LIB}") set(release_dir "${HAVOK_RELEASE_LIBRARY_PATH}/${HAVOK_LIB}") - set(relwithdebinfo_dir "${HAVOK_RELWITHDEBINFO_LIBRARY_PATH}/${HAVOK_LIB}") # Try to avoid extracting havok library each time we run cmake. if("${havok_${HAVOK_LIB}_extracted}" STREQUAL "" AND EXISTS "${PREBUILD_TRACKING_DIR}/havok_${HAVOK_LIB}_extracted") @@ -92,8 +96,8 @@ foreach(HAVOK_LIB ${HAVOK_LIBS}) if(${PREBUILD_TRACKING_DIR}/havok_source_installed IS_NEWER_THAN ${PREBUILD_TRACKING_DIR}/havok_${HAVOK_LIB}_extracted OR NOT ${havok_${HAVOK_LIB}_extracted} EQUAL 0) DEBUG_MESSAGE("Extracting ${HAVOK_LIB}...") - foreach(lib ${debug_dir} ${release_dir} ${relwithdebinfo_dir}) - DEBUG_EXEC("mkdir" ${lib}) + foreach(lib ${release_dir}) + DEBUG_EXEC("mkdir" "-p" ${lib}) DEBUG_EXEC("ar" "-xv" "../lib${HAVOK_LIB}.a" WORKING_DIRECTORY ${lib}) endforeach(lib) @@ -104,17 +108,12 @@ foreach(HAVOK_LIB ${HAVOK_LIBS}) endif() - file(GLOB extracted_debug "${debug_dir}/*.o") file(GLOB extracted_release "${release_dir}/*.o") - file(GLOB extracted_relwithdebinfo "${relwithdebinfo_dir}/*.o") - - DEBUG_MESSAGE("extracted_debug ${debug_dir}/*.o") DEBUG_MESSAGE("extracted_release ${release_dir}/*.o") - DEBUG_MESSAGE("extracted_relwithdebinfo ${relwithdebinfo_dir}/*.o") - list(APPEND HK_DEBUG_LIBRARIES ${extracted_debug}) + list(APPEND HK_DEBUG_LIBRARIES ${extracted_release}) list(APPEND HK_RELEASE_LIBRARIES ${extracted_release}) - list(APPEND HK_RELWITHDEBINFO_LIBRARIES ${extracted_relwithdebinfo}) + list(APPEND HK_RELWITHDEBINFO_LIBRARIES ${extracted_release}) else(LINUX) # Win32 list(APPEND HK_DEBUG_LIBRARIES ${HAVOK_DEBUG_LIB_${HAVOK_LIB}}) diff --git a/indra/cmake/LLWindow.cmake b/indra/cmake/LLWindow.cmake index 23f4115aeb..a5791f1bef 100644 --- a/indra/cmake/LLWindow.cmake +++ b/indra/cmake/LLWindow.cmake @@ -3,18 +3,11 @@ include(Variables) include(GLEXT) include(Prebuilt) +include(SDL2) include_guard() -add_library( ll::SDL INTERFACE IMPORTED ) - if (LINUX) - #Must come first as use_system_binary can exit this file early - target_compile_definitions( ll::SDL INTERFACE LL_SDL_VERSION=2 LL_SDL) - - #find_package(SDL2 REQUIRED) - #target_link_libraries( ll::SDL INTERFACE SDL2::SDL2 SDL2::SDL2main X11) - - use_prebuilt_binary(SDL2) - target_link_libraries( ll::SDL INTERFACE SDL2 X11) + # linux uses SDL2 for window and keyboard + target_compile_definitions( ll::SDL2 INTERFACE LL_USE_SDL_KEYBOARD=1 ) endif (LINUX) diff --git a/indra/cmake/OPENAL.cmake b/indra/cmake/OPENAL.cmake index 347dd02cd7..355907bcf5 100644 --- a/indra/cmake/OPENAL.cmake +++ b/indra/cmake/OPENAL.cmake @@ -4,11 +4,7 @@ include(Prebuilt) include_guard() -# ND: Turn this off by default, the openal code in the viewer isn't very well maintained, seems -# to have memory leaks, has no option to play music streams -# It probably makes sense to to completely remove it - -set(USE_OPENAL OFF CACHE BOOL "Enable OpenAL") +set(USE_OPENAL ON CACHE BOOL "Enable OpenAL") # ND: To streamline arguments passed, switch from OPENAL to USE_OPENAL # To not break all old build scripts convert old arguments but warn about it if(OPENAL) diff --git a/indra/cmake/Prebuilt.cmake b/indra/cmake/Prebuilt.cmake index a8c702bfef..c040090ea3 100644 --- a/indra/cmake/Prebuilt.cmake +++ b/indra/cmake/Prebuilt.cmake @@ -43,6 +43,8 @@ macro (use_prebuilt_binary _binary) message(STATUS "Installing ${_binary}...") execute_process(COMMAND "${AUTOBUILD_EXECUTABLE}" install + -A${ADDRESS_SIZE} + --skip-source-environment --install-dir=${AUTOBUILD_INSTALL_DIR} ${_binary} WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}" diff --git a/indra/cmake/SDL2.cmake b/indra/cmake/SDL2.cmake new file mode 100644 index 0000000000..87195ed108 --- /dev/null +++ b/indra/cmake/SDL2.cmake @@ -0,0 +1,22 @@ +# -*- cmake -*- +cmake_minimum_required( VERSION 3.13 FATAL_ERROR ) + +include(Linking) +include( Prebuilt ) +include_guard() + +add_library( ll::SDL2 INTERFACE IMPORTED ) + +use_system_binary( SDL2 ) +use_prebuilt_binary( SDL2 ) + +find_library( SDL2_LIBRARY + NAMES SDL2 + PATHS "${LIBS_PREBUILT_DIR}/lib/release") +if ( "${SDL2_LIBRARY}" STREQUAL "SDL2_LIBRARY-NOTFOUND" ) + message( FATAL_ERROR "unable to find SDL2_LIBRARY" ) +endif() + +target_link_libraries( ll::SDL2 INTERFACE "${SDL2_LIBRARY}" ) +target_include_directories( ll::SDL2 SYSTEM INTERFACE "${LIBS_PREBUILT_DIR}/include" ) + diff --git a/indra/cmake/UI.cmake b/indra/cmake/UI.cmake index 0df62808e7..ae039b4a47 100644 --- a/indra/cmake/UI.cmake +++ b/indra/cmake/UI.cmake @@ -21,9 +21,10 @@ if (LINUX) Xext Xft Xinerama + X11 ll::fontconfig ll::freetype - ll::SDL + ll::SDL2 ll::glib ll::gio ) diff --git a/indra/cmake/bugsplat.cmake b/indra/cmake/bugsplat.cmake index 509981d72c..0798d4f51f 100644 --- a/indra/cmake/bugsplat.cmake +++ b/indra/cmake/bugsplat.cmake @@ -1,13 +1,13 @@ -if (INSTALL_PROPRIETARY) +if (INSTALL_PROPRIETARY AND NOT LINUX) # Note that viewer_manifest.py makes decision based on BUGSPLAT_DB and not USE_BUGSPLAT if (BUGSPLAT_DB) set(USE_BUGSPLAT ON CACHE BOOL "Use the BugSplat crash reporting system") else (BUGSPLAT_DB) set(USE_BUGSPLAT OFF CACHE BOOL "Use the BugSplat crash reporting system") endif (BUGSPLAT_DB) -else (INSTALL_PROPRIETARY) +else (INSTALL_PROPRIETARY AND NOT LINUX) set(USE_BUGSPLAT OFF CACHE BOOL "Use the BugSplat crash reporting system") -endif (INSTALL_PROPRIETARY) +endif (INSTALL_PROPRIETARY AND NOT LINUX) include_guard() add_library( ll::bugsplat INTERFACE IMPORTED ) @@ -36,6 +36,6 @@ if (USE_BUGSPLAT) set_property( TARGET ll::bugsplat APPEND PROPERTY INTERFACE_COMPILE_DEFINITIONS LL_BUGSPLAT) else() - set(BUGSPLAT_DB "" CACHE STRING "BugSplat crash database name") + set(BUGSPLAT_DB "" CACHE STRING "BugSplat crash database name" FORCE) endif (USE_BUGSPLAT) diff --git a/indra/llappearance/CMakeLists.txt b/indra/llappearance/CMakeLists.txt index c3be8bc78e..c510d01e3a 100644 --- a/indra/llappearance/CMakeLists.txt +++ b/indra/llappearance/CMakeLists.txt @@ -27,7 +27,7 @@ set(llappearance_SOURCE_FILES llviewervisualparam.cpp llavatarappearancedefines.cpp ) - + set(llappearance_HEADER_FILES CMakeLists.txt diff --git a/indra/llaudio/llaudioengine_openal.cpp b/indra/llaudio/llaudioengine_openal.cpp index 18d682b554..755547bfaa 100644 --- a/indra/llaudio/llaudioengine_openal.cpp +++ b/indra/llaudio/llaudioengine_openal.cpp @@ -79,7 +79,7 @@ bool LLAudioEngine_OpenAL::init(void* userdata, const std::string &app_title) ALCdevice *device = alcGetContextsDevice(alcGetCurrentContext()); alcGetIntegerv(device, ALC_MAJOR_VERSION, 1, &major); - alcGetIntegerv(device, ALC_MAJOR_VERSION, 1, &minor); + alcGetIntegerv(device, ALC_MINOR_VERSION, 1, &minor); LL_INFOS() << "ALC version: " << major << "." << minor << LL_ENDL; LL_INFOS() << "ALC default device: " @@ -190,6 +190,8 @@ LLAudioChannelOpenAL::~LLAudioChannelOpenAL() void LLAudioChannelOpenAL::cleanup() { alSourceStop(mALSource); + alSourcei(mALSource, AL_BUFFER, AL_NONE); + mCurrentBufferp = NULL; } diff --git a/indra/llcommon/classic_callback.h b/indra/llcommon/classic_callback.h index 009c25d67c..8a6ac7f7ff 100644 --- a/indra/llcommon/classic_callback.h +++ b/indra/llcommon/classic_callback.h @@ -184,8 +184,8 @@ protected: template <typename SIGNATURE, typename USERDATA=void*, typename CALLABLE=void(*)()> auto makeClassicCallback(CALLABLE&& callable) { - return std::move(ClassicCallback<SIGNATURE, USERDATA, CALLABLE> - (std::forward<CALLABLE>(callable))); + return ClassicCallback<SIGNATURE, USERDATA, CALLABLE> + (std::forward<CALLABLE>(callable)); } /***************************************************************************** diff --git a/indra/llcommon/coro_scheduler.cpp b/indra/llcommon/coro_scheduler.cpp index 02b9f11333..2d8b6e1a97 100644 --- a/indra/llcommon/coro_scheduler.cpp +++ b/indra/llcommon/coro_scheduler.cpp @@ -87,7 +87,7 @@ boost::fibers::context* scheduler::pick_next() noexcept /*------------------------- logging stuff --------------------------*/ // Unless this log tag is enabled, don't even bother posting. - LL_DEBUGS("LLCoros.scheduler"); + LL_DEBUGS("LLCoros.scheduler") << " "; // This feature is inherently hard to verify. The logging in the // lambda below seems useful, but also seems like a lot of overhead // for a coroutine context switch. Try posting the logging lambda to a diff --git a/indra/llcommon/indra_constants.h b/indra/llcommon/indra_constants.h index d2de88ff0a..566ea2ea14 100644 --- a/indra/llcommon/indra_constants.h +++ b/indra/llcommon/indra_constants.h @@ -31,15 +31,15 @@ class LLUUID; -static const F32 REGION_WIDTH_METERS = 256.f; -static const S32 REGION_WIDTH_UNITS = 256; -static const U32 REGION_WIDTH_U32 = 256; +static constexpr F32 REGION_WIDTH_METERS = 256.f; +static constexpr S32 REGION_WIDTH_UNITS = 256; +static constexpr U32 REGION_WIDTH_U32 = 256; -const F32 REGION_HEIGHT_METERS = 4096.f; +constexpr F32 REGION_HEIGHT_METERS = 4096.f; -const F32 DEFAULT_AGENT_DEPTH = 0.45f; -const F32 DEFAULT_AGENT_WIDTH = 0.60f; -const F32 DEFAULT_AGENT_HEIGHT = 1.9f; +constexpr F32 DEFAULT_AGENT_DEPTH = 0.45f; +constexpr F32 DEFAULT_AGENT_WIDTH = 0.60f; +constexpr F32 DEFAULT_AGENT_HEIGHT = 1.9f; enum ETerrainBrushType { @@ -67,112 +67,112 @@ enum EMouseClickType{ // keys // Bit masks for various keyboard modifier keys. -const MASK MASK_NONE = 0x0000; -const MASK MASK_CONTROL = 0x0001; // Mapped to cmd on Macs -const MASK MASK_ALT = 0x0002; -const MASK MASK_SHIFT = 0x0004; -const MASK MASK_NORMALKEYS = 0x0007; // A real mask - only get the bits for normal modifier keys -const MASK MASK_MAC_CONTROL = 0x0008; // Un-mapped Ctrl key on Macs, not used on Windows -const MASK MASK_MODIFIERS = MASK_CONTROL|MASK_ALT|MASK_SHIFT|MASK_MAC_CONTROL; +constexpr MASK MASK_NONE = 0x0000; +constexpr MASK MASK_CONTROL = 0x0001; // Mapped to cmd on Macs +constexpr MASK MASK_ALT = 0x0002; +constexpr MASK MASK_SHIFT = 0x0004; +constexpr MASK MASK_NORMALKEYS = 0x0007; // A real mask - only get the bits for normal modifier keys +constexpr MASK MASK_MAC_CONTROL = 0x0008; // Un-mapped Ctrl key on Macs, not used on Windows +constexpr MASK MASK_MODIFIERS = MASK_CONTROL|MASK_ALT|MASK_SHIFT|MASK_MAC_CONTROL; // Special keys go into >128 -const KEY KEY_SPECIAL = 0x80; // special keys start here -const KEY KEY_RETURN = 0x81; -const KEY KEY_LEFT = 0x82; -const KEY KEY_RIGHT = 0x83; -const KEY KEY_UP = 0x84; -const KEY KEY_DOWN = 0x85; -const KEY KEY_ESCAPE = 0x86; -const KEY KEY_BACKSPACE =0x87; -const KEY KEY_DELETE = 0x88; -const KEY KEY_SHIFT = 0x89; -const KEY KEY_CONTROL = 0x8A; -const KEY KEY_ALT = 0x8B; -const KEY KEY_HOME = 0x8C; -const KEY KEY_END = 0x8D; -const KEY KEY_PAGE_UP = 0x8E; -const KEY KEY_PAGE_DOWN = 0x8F; -const KEY KEY_HYPHEN = 0x90; -const KEY KEY_EQUALS = 0x91; -const KEY KEY_INSERT = 0x92; -const KEY KEY_CAPSLOCK = 0x93; -const KEY KEY_TAB = 0x94; -const KEY KEY_ADD = 0x95; -const KEY KEY_SUBTRACT =0x96; -const KEY KEY_MULTIPLY =0x97; -const KEY KEY_DIVIDE = 0x98; -const KEY KEY_F1 = 0xA1; -const KEY KEY_F2 = 0xA2; -const KEY KEY_F3 = 0xA3; -const KEY KEY_F4 = 0xA4; -const KEY KEY_F5 = 0xA5; -const KEY KEY_F6 = 0xA6; -const KEY KEY_F7 = 0xA7; -const KEY KEY_F8 = 0xA8; -const KEY KEY_F9 = 0xA9; -const KEY KEY_F10 = 0xAA; -const KEY KEY_F11 = 0xAB; -const KEY KEY_F12 = 0xAC; - -const KEY KEY_PAD_UP = 0xC0; -const KEY KEY_PAD_DOWN = 0xC1; -const KEY KEY_PAD_LEFT = 0xC2; -const KEY KEY_PAD_RIGHT = 0xC3; -const KEY KEY_PAD_HOME = 0xC4; -const KEY KEY_PAD_END = 0xC5; -const KEY KEY_PAD_PGUP = 0xC6; -const KEY KEY_PAD_PGDN = 0xC7; -const KEY KEY_PAD_CENTER = 0xC8; // the 5 in the middle -const KEY KEY_PAD_INS = 0xC9; -const KEY KEY_PAD_DEL = 0xCA; -const KEY KEY_PAD_RETURN = 0xCB; -const KEY KEY_PAD_ADD = 0xCC; // not used -const KEY KEY_PAD_SUBTRACT = 0xCD; // not used -const KEY KEY_PAD_MULTIPLY = 0xCE; // not used -const KEY KEY_PAD_DIVIDE = 0xCF; // not used - -const KEY KEY_BUTTON0 = 0xD0; -const KEY KEY_BUTTON1 = 0xD1; -const KEY KEY_BUTTON2 = 0xD2; -const KEY KEY_BUTTON3 = 0xD3; -const KEY KEY_BUTTON4 = 0xD4; -const KEY KEY_BUTTON5 = 0xD5; -const KEY KEY_BUTTON6 = 0xD6; -const KEY KEY_BUTTON7 = 0xD7; -const KEY KEY_BUTTON8 = 0xD8; -const KEY KEY_BUTTON9 = 0xD9; -const KEY KEY_BUTTON10 = 0xDA; -const KEY KEY_BUTTON11 = 0xDB; -const KEY KEY_BUTTON12 = 0xDC; -const KEY KEY_BUTTON13 = 0xDD; -const KEY KEY_BUTTON14 = 0xDE; -const KEY KEY_BUTTON15 = 0xDF; - -const KEY KEY_NONE = 0xFF; // not sent from keyboard. For internal use only. - -const S32 KEY_COUNT = 256; - - -const F32 DEFAULT_WATER_HEIGHT = 20.0f; +constexpr KEY KEY_SPECIAL = 0x80; // special keys start here +constexpr KEY KEY_RETURN = 0x81; +constexpr KEY KEY_LEFT = 0x82; +constexpr KEY KEY_RIGHT = 0x83; +constexpr KEY KEY_UP = 0x84; +constexpr KEY KEY_DOWN = 0x85; +constexpr KEY KEY_ESCAPE = 0x86; +constexpr KEY KEY_BACKSPACE =0x87; +constexpr KEY KEY_DELETE = 0x88; +constexpr KEY KEY_SHIFT = 0x89; +constexpr KEY KEY_CONTROL = 0x8A; +constexpr KEY KEY_ALT = 0x8B; +constexpr KEY KEY_HOME = 0x8C; +constexpr KEY KEY_END = 0x8D; +constexpr KEY KEY_PAGE_UP = 0x8E; +constexpr KEY KEY_PAGE_DOWN = 0x8F; +constexpr KEY KEY_HYPHEN = 0x90; +constexpr KEY KEY_EQUALS = 0x91; +constexpr KEY KEY_INSERT = 0x92; +constexpr KEY KEY_CAPSLOCK = 0x93; +constexpr KEY KEY_TAB = 0x94; +constexpr KEY KEY_ADD = 0x95; +constexpr KEY KEY_SUBTRACT =0x96; +constexpr KEY KEY_MULTIPLY =0x97; +constexpr KEY KEY_DIVIDE = 0x98; +constexpr KEY KEY_F1 = 0xA1; +constexpr KEY KEY_F2 = 0xA2; +constexpr KEY KEY_F3 = 0xA3; +constexpr KEY KEY_F4 = 0xA4; +constexpr KEY KEY_F5 = 0xA5; +constexpr KEY KEY_F6 = 0xA6; +constexpr KEY KEY_F7 = 0xA7; +constexpr KEY KEY_F8 = 0xA8; +constexpr KEY KEY_F9 = 0xA9; +constexpr KEY KEY_F10 = 0xAA; +constexpr KEY KEY_F11 = 0xAB; +constexpr KEY KEY_F12 = 0xAC; + +constexpr KEY KEY_PAD_UP = 0xC0; +constexpr KEY KEY_PAD_DOWN = 0xC1; +constexpr KEY KEY_PAD_LEFT = 0xC2; +constexpr KEY KEY_PAD_RIGHT = 0xC3; +constexpr KEY KEY_PAD_HOME = 0xC4; +constexpr KEY KEY_PAD_END = 0xC5; +constexpr KEY KEY_PAD_PGUP = 0xC6; +constexpr KEY KEY_PAD_PGDN = 0xC7; +constexpr KEY KEY_PAD_CENTER = 0xC8; // the 5 in the middle +constexpr KEY KEY_PAD_INS = 0xC9; +constexpr KEY KEY_PAD_DEL = 0xCA; +constexpr KEY KEY_PAD_RETURN = 0xCB; +constexpr KEY KEY_PAD_ADD = 0xCC; // not used +constexpr KEY KEY_PAD_SUBTRACT = 0xCD; // not used +constexpr KEY KEY_PAD_MULTIPLY = 0xCE; // not used +constexpr KEY KEY_PAD_DIVIDE = 0xCF; // not used + +constexpr KEY KEY_BUTTON0 = 0xD0; +constexpr KEY KEY_BUTTON1 = 0xD1; +constexpr KEY KEY_BUTTON2 = 0xD2; +constexpr KEY KEY_BUTTON3 = 0xD3; +constexpr KEY KEY_BUTTON4 = 0xD4; +constexpr KEY KEY_BUTTON5 = 0xD5; +constexpr KEY KEY_BUTTON6 = 0xD6; +constexpr KEY KEY_BUTTON7 = 0xD7; +constexpr KEY KEY_BUTTON8 = 0xD8; +constexpr KEY KEY_BUTTON9 = 0xD9; +constexpr KEY KEY_BUTTON10 = 0xDA; +constexpr KEY KEY_BUTTON11 = 0xDB; +constexpr KEY KEY_BUTTON12 = 0xDC; +constexpr KEY KEY_BUTTON13 = 0xDD; +constexpr KEY KEY_BUTTON14 = 0xDE; +constexpr KEY KEY_BUTTON15 = 0xDF; + +constexpr KEY KEY_NONE = 0xFF; // not sent from keyboard. For internal use only. + +constexpr S32 KEY_COUNT = 256; + + +constexpr F32 DEFAULT_WATER_HEIGHT = 20.0f; // Maturity ratings for simulators -const U8 SIM_ACCESS_MIN = 0; // Treated as 'unknown', usually ends up being SIM_ACCESS_PG -const U8 SIM_ACCESS_PG = 13; -const U8 SIM_ACCESS_MATURE = 21; -const U8 SIM_ACCESS_ADULT = 42; // Seriously Adult Only -const U8 SIM_ACCESS_DOWN = 254; -const U8 SIM_ACCESS_MAX = SIM_ACCESS_ADULT; +constexpr U8 SIM_ACCESS_MIN = 0; // Treated as 'unknown', usually ends up being SIM_ACCESS_PG +constexpr U8 SIM_ACCESS_PG = 13; +constexpr U8 SIM_ACCESS_MATURE = 21; +constexpr U8 SIM_ACCESS_ADULT = 42; // Seriously Adult Only +constexpr U8 SIM_ACCESS_DOWN = 254; +constexpr U8 SIM_ACCESS_MAX = SIM_ACCESS_ADULT; // attachment constants -const U8 ATTACHMENT_ADD = 0x80; +constexpr U8 ATTACHMENT_ADD = 0x80; // god levels -const U8 GOD_MAINTENANCE = 250; -const U8 GOD_FULL = 200; -const U8 GOD_LIAISON = 150; -const U8 GOD_CUSTOMER_SERVICE = 100; -const U8 GOD_LIKE = 1; -const U8 GOD_NOT = 0; +constexpr U8 GOD_MAINTENANCE = 250; +constexpr U8 GOD_FULL = 200; +constexpr U8 GOD_LIAISON = 150; +constexpr U8 GOD_CUSTOMER_SERVICE = 100; +constexpr U8 GOD_LIKE = 1; +constexpr U8 GOD_NOT = 0; // "agent id" for things that should be done to ALL agents LL_COMMON_API extern const LLUUID LL_UUID_ALL_AGENTS; @@ -239,120 +239,120 @@ LL_COMMON_API extern const LLUUID BLANK_OBJECT_NORMAL; LL_COMMON_API extern const LLUUID BLANK_MATERIAL_ASSET_ID; // radius within which a chat message is fully audible -const F32 CHAT_NORMAL_RADIUS = 20.f; +constexpr F32 CHAT_NORMAL_RADIUS = 20.f; // media commands -const U32 PARCEL_MEDIA_COMMAND_STOP = 0; -const U32 PARCEL_MEDIA_COMMAND_PAUSE = 1; -const U32 PARCEL_MEDIA_COMMAND_PLAY = 2; -const U32 PARCEL_MEDIA_COMMAND_LOOP = 3; -const U32 PARCEL_MEDIA_COMMAND_TEXTURE = 4; -const U32 PARCEL_MEDIA_COMMAND_URL = 5; -const U32 PARCEL_MEDIA_COMMAND_TIME = 6; -const U32 PARCEL_MEDIA_COMMAND_AGENT = 7; -const U32 PARCEL_MEDIA_COMMAND_UNLOAD = 8; -const U32 PARCEL_MEDIA_COMMAND_AUTO_ALIGN = 9; -const U32 PARCEL_MEDIA_COMMAND_TYPE = 10; -const U32 PARCEL_MEDIA_COMMAND_SIZE = 11; -const U32 PARCEL_MEDIA_COMMAND_DESC = 12; -const U32 PARCEL_MEDIA_COMMAND_LOOP_SET = 13; +constexpr U32 PARCEL_MEDIA_COMMAND_STOP = 0; +constexpr U32 PARCEL_MEDIA_COMMAND_PAUSE = 1; +constexpr U32 PARCEL_MEDIA_COMMAND_PLAY = 2; +constexpr U32 PARCEL_MEDIA_COMMAND_LOOP = 3; +constexpr U32 PARCEL_MEDIA_COMMAND_TEXTURE = 4; +constexpr U32 PARCEL_MEDIA_COMMAND_URL = 5; +constexpr U32 PARCEL_MEDIA_COMMAND_TIME = 6; +constexpr U32 PARCEL_MEDIA_COMMAND_AGENT = 7; +constexpr U32 PARCEL_MEDIA_COMMAND_UNLOAD = 8; +constexpr U32 PARCEL_MEDIA_COMMAND_AUTO_ALIGN = 9; +constexpr U32 PARCEL_MEDIA_COMMAND_TYPE = 10; +constexpr U32 PARCEL_MEDIA_COMMAND_SIZE = 11; +constexpr U32 PARCEL_MEDIA_COMMAND_DESC = 12; +constexpr U32 PARCEL_MEDIA_COMMAND_LOOP_SET = 13; const S32 CHAT_CHANNEL_DEBUG = S32_MAX; // agent constants -const U32 CONTROL_AT_POS_INDEX = 0; -const U32 CONTROL_AT_NEG_INDEX = 1; -const U32 CONTROL_LEFT_POS_INDEX = 2; -const U32 CONTROL_LEFT_NEG_INDEX = 3; -const U32 CONTROL_UP_POS_INDEX = 4; -const U32 CONTROL_UP_NEG_INDEX = 5; -const U32 CONTROL_PITCH_POS_INDEX = 6; -const U32 CONTROL_PITCH_NEG_INDEX = 7; -const U32 CONTROL_YAW_POS_INDEX = 8; -const U32 CONTROL_YAW_NEG_INDEX = 9; -const U32 CONTROL_FAST_AT_INDEX = 10; -const U32 CONTROL_FAST_LEFT_INDEX = 11; -const U32 CONTROL_FAST_UP_INDEX = 12; -const U32 CONTROL_FLY_INDEX = 13; -const U32 CONTROL_STOP_INDEX = 14; -const U32 CONTROL_FINISH_ANIM_INDEX = 15; -const U32 CONTROL_STAND_UP_INDEX = 16; -const U32 CONTROL_SIT_ON_GROUND_INDEX = 17; -const U32 CONTROL_MOUSELOOK_INDEX = 18; -const U32 CONTROL_NUDGE_AT_POS_INDEX = 19; -const U32 CONTROL_NUDGE_AT_NEG_INDEX = 20; -const U32 CONTROL_NUDGE_LEFT_POS_INDEX = 21; -const U32 CONTROL_NUDGE_LEFT_NEG_INDEX = 22; -const U32 CONTROL_NUDGE_UP_POS_INDEX = 23; -const U32 CONTROL_NUDGE_UP_NEG_INDEX = 24; -const U32 CONTROL_TURN_LEFT_INDEX = 25; -const U32 CONTROL_TURN_RIGHT_INDEX = 26; -const U32 CONTROL_AWAY_INDEX = 27; -const U32 CONTROL_LBUTTON_DOWN_INDEX = 28; -const U32 CONTROL_LBUTTON_UP_INDEX = 29; -const U32 CONTROL_ML_LBUTTON_DOWN_INDEX = 30; -const U32 CONTROL_ML_LBUTTON_UP_INDEX = 31; -const U32 TOTAL_CONTROLS = 32; - -const U32 AGENT_CONTROL_AT_POS = 0x1 << CONTROL_AT_POS_INDEX; // 0x00000001 -const U32 AGENT_CONTROL_AT_NEG = 0x1 << CONTROL_AT_NEG_INDEX; // 0x00000002 -const U32 AGENT_CONTROL_LEFT_POS = 0x1 << CONTROL_LEFT_POS_INDEX; // 0x00000004 -const U32 AGENT_CONTROL_LEFT_NEG = 0x1 << CONTROL_LEFT_NEG_INDEX; // 0x00000008 -const U32 AGENT_CONTROL_UP_POS = 0x1 << CONTROL_UP_POS_INDEX; // 0x00000010 -const U32 AGENT_CONTROL_UP_NEG = 0x1 << CONTROL_UP_NEG_INDEX; // 0x00000020 -const U32 AGENT_CONTROL_PITCH_POS = 0x1 << CONTROL_PITCH_POS_INDEX; // 0x00000040 -const U32 AGENT_CONTROL_PITCH_NEG = 0x1 << CONTROL_PITCH_NEG_INDEX; // 0x00000080 -const U32 AGENT_CONTROL_YAW_POS = 0x1 << CONTROL_YAW_POS_INDEX; // 0x00000100 -const U32 AGENT_CONTROL_YAW_NEG = 0x1 << CONTROL_YAW_NEG_INDEX; // 0x00000200 - -const U32 AGENT_CONTROL_FAST_AT = 0x1 << CONTROL_FAST_AT_INDEX; // 0x00000400 -const U32 AGENT_CONTROL_FAST_LEFT = 0x1 << CONTROL_FAST_LEFT_INDEX; // 0x00000800 -const U32 AGENT_CONTROL_FAST_UP = 0x1 << CONTROL_FAST_UP_INDEX; // 0x00001000 - -const U32 AGENT_CONTROL_FLY = 0x1 << CONTROL_FLY_INDEX; // 0x00002000 -const U32 AGENT_CONTROL_STOP = 0x1 << CONTROL_STOP_INDEX; // 0x00004000 -const U32 AGENT_CONTROL_FINISH_ANIM = 0x1 << CONTROL_FINISH_ANIM_INDEX; // 0x00008000 -const U32 AGENT_CONTROL_STAND_UP = 0x1 << CONTROL_STAND_UP_INDEX; // 0x00010000 -const U32 AGENT_CONTROL_SIT_ON_GROUND = 0x1 << CONTROL_SIT_ON_GROUND_INDEX; // 0x00020000 -const U32 AGENT_CONTROL_MOUSELOOK = 0x1 << CONTROL_MOUSELOOK_INDEX; // 0x00040000 - -const U32 AGENT_CONTROL_NUDGE_AT_POS = 0x1 << CONTROL_NUDGE_AT_POS_INDEX; // 0x00080000 -const U32 AGENT_CONTROL_NUDGE_AT_NEG = 0x1 << CONTROL_NUDGE_AT_NEG_INDEX; // 0x00100000 -const U32 AGENT_CONTROL_NUDGE_LEFT_POS = 0x1 << CONTROL_NUDGE_LEFT_POS_INDEX; // 0x00200000 -const U32 AGENT_CONTROL_NUDGE_LEFT_NEG = 0x1 << CONTROL_NUDGE_LEFT_NEG_INDEX; // 0x00400000 -const U32 AGENT_CONTROL_NUDGE_UP_POS = 0x1 << CONTROL_NUDGE_UP_POS_INDEX; // 0x00800000 -const U32 AGENT_CONTROL_NUDGE_UP_NEG = 0x1 << CONTROL_NUDGE_UP_NEG_INDEX; // 0x01000000 -const U32 AGENT_CONTROL_TURN_LEFT = 0x1 << CONTROL_TURN_LEFT_INDEX; // 0x02000000 -const U32 AGENT_CONTROL_TURN_RIGHT = 0x1 << CONTROL_TURN_RIGHT_INDEX; // 0x04000000 - -const U32 AGENT_CONTROL_AWAY = 0x1 << CONTROL_AWAY_INDEX; // 0x08000000 - -const U32 AGENT_CONTROL_LBUTTON_DOWN = 0x1 << CONTROL_LBUTTON_DOWN_INDEX; // 0x10000000 -const U32 AGENT_CONTROL_LBUTTON_UP = 0x1 << CONTROL_LBUTTON_UP_INDEX; // 0x20000000 -const U32 AGENT_CONTROL_ML_LBUTTON_DOWN = 0x1 << CONTROL_ML_LBUTTON_DOWN_INDEX; // 0x40000000 -const U32 AGENT_CONTROL_ML_LBUTTON_UP = ((U32)0x1) << CONTROL_ML_LBUTTON_UP_INDEX; // 0x80000000 +constexpr U32 CONTROL_AT_POS_INDEX = 0; +constexpr U32 CONTROL_AT_NEG_INDEX = 1; +constexpr U32 CONTROL_LEFT_POS_INDEX = 2; +constexpr U32 CONTROL_LEFT_NEG_INDEX = 3; +constexpr U32 CONTROL_UP_POS_INDEX = 4; +constexpr U32 CONTROL_UP_NEG_INDEX = 5; +constexpr U32 CONTROL_PITCH_POS_INDEX = 6; +constexpr U32 CONTROL_PITCH_NEG_INDEX = 7; +constexpr U32 CONTROL_YAW_POS_INDEX = 8; +constexpr U32 CONTROL_YAW_NEG_INDEX = 9; +constexpr U32 CONTROL_FAST_AT_INDEX = 10; +constexpr U32 CONTROL_FAST_LEFT_INDEX = 11; +constexpr U32 CONTROL_FAST_UP_INDEX = 12; +constexpr U32 CONTROL_FLY_INDEX = 13; +constexpr U32 CONTROL_STOP_INDEX = 14; +constexpr U32 CONTROL_FINISH_ANIM_INDEX = 15; +constexpr U32 CONTROL_STAND_UP_INDEX = 16; +constexpr U32 CONTROL_SIT_ON_GROUND_INDEX = 17; +constexpr U32 CONTROL_MOUSELOOK_INDEX = 18; +constexpr U32 CONTROL_NUDGE_AT_POS_INDEX = 19; +constexpr U32 CONTROL_NUDGE_AT_NEG_INDEX = 20; +constexpr U32 CONTROL_NUDGE_LEFT_POS_INDEX = 21; +constexpr U32 CONTROL_NUDGE_LEFT_NEG_INDEX = 22; +constexpr U32 CONTROL_NUDGE_UP_POS_INDEX = 23; +constexpr U32 CONTROL_NUDGE_UP_NEG_INDEX = 24; +constexpr U32 CONTROL_TURN_LEFT_INDEX = 25; +constexpr U32 CONTROL_TURN_RIGHT_INDEX = 26; +constexpr U32 CONTROL_AWAY_INDEX = 27; +constexpr U32 CONTROL_LBUTTON_DOWN_INDEX = 28; +constexpr U32 CONTROL_LBUTTON_UP_INDEX = 29; +constexpr U32 CONTROL_ML_LBUTTON_DOWN_INDEX = 30; +constexpr U32 CONTROL_ML_LBUTTON_UP_INDEX = 31; +constexpr U32 TOTAL_CONTROLS = 32; + +constexpr U32 AGENT_CONTROL_AT_POS = 0x1 << CONTROL_AT_POS_INDEX; // 0x00000001 +constexpr U32 AGENT_CONTROL_AT_NEG = 0x1 << CONTROL_AT_NEG_INDEX; // 0x00000002 +constexpr U32 AGENT_CONTROL_LEFT_POS = 0x1 << CONTROL_LEFT_POS_INDEX; // 0x00000004 +constexpr U32 AGENT_CONTROL_LEFT_NEG = 0x1 << CONTROL_LEFT_NEG_INDEX; // 0x00000008 +constexpr U32 AGENT_CONTROL_UP_POS = 0x1 << CONTROL_UP_POS_INDEX; // 0x00000010 +constexpr U32 AGENT_CONTROL_UP_NEG = 0x1 << CONTROL_UP_NEG_INDEX; // 0x00000020 +constexpr U32 AGENT_CONTROL_PITCH_POS = 0x1 << CONTROL_PITCH_POS_INDEX; // 0x00000040 +constexpr U32 AGENT_CONTROL_PITCH_NEG = 0x1 << CONTROL_PITCH_NEG_INDEX; // 0x00000080 +constexpr U32 AGENT_CONTROL_YAW_POS = 0x1 << CONTROL_YAW_POS_INDEX; // 0x00000100 +constexpr U32 AGENT_CONTROL_YAW_NEG = 0x1 << CONTROL_YAW_NEG_INDEX; // 0x00000200 + +constexpr U32 AGENT_CONTROL_FAST_AT = 0x1 << CONTROL_FAST_AT_INDEX; // 0x00000400 +constexpr U32 AGENT_CONTROL_FAST_LEFT = 0x1 << CONTROL_FAST_LEFT_INDEX; // 0x00000800 +constexpr U32 AGENT_CONTROL_FAST_UP = 0x1 << CONTROL_FAST_UP_INDEX; // 0x00001000 + +constexpr U32 AGENT_CONTROL_FLY = 0x1 << CONTROL_FLY_INDEX; // 0x00002000 +constexpr U32 AGENT_CONTROL_STOP = 0x1 << CONTROL_STOP_INDEX; // 0x00004000 +constexpr U32 AGENT_CONTROL_FINISH_ANIM = 0x1 << CONTROL_FINISH_ANIM_INDEX; // 0x00008000 +constexpr U32 AGENT_CONTROL_STAND_UP = 0x1 << CONTROL_STAND_UP_INDEX; // 0x00010000 +constexpr U32 AGENT_CONTROL_SIT_ON_GROUND = 0x1 << CONTROL_SIT_ON_GROUND_INDEX; // 0x00020000 +constexpr U32 AGENT_CONTROL_MOUSELOOK = 0x1 << CONTROL_MOUSELOOK_INDEX; // 0x00040000 + +constexpr U32 AGENT_CONTROL_NUDGE_AT_POS = 0x1 << CONTROL_NUDGE_AT_POS_INDEX; // 0x00080000 +constexpr U32 AGENT_CONTROL_NUDGE_AT_NEG = 0x1 << CONTROL_NUDGE_AT_NEG_INDEX; // 0x00100000 +constexpr U32 AGENT_CONTROL_NUDGE_LEFT_POS = 0x1 << CONTROL_NUDGE_LEFT_POS_INDEX; // 0x00200000 +constexpr U32 AGENT_CONTROL_NUDGE_LEFT_NEG = 0x1 << CONTROL_NUDGE_LEFT_NEG_INDEX; // 0x00400000 +constexpr U32 AGENT_CONTROL_NUDGE_UP_POS = 0x1 << CONTROL_NUDGE_UP_POS_INDEX; // 0x00800000 +constexpr U32 AGENT_CONTROL_NUDGE_UP_NEG = 0x1 << CONTROL_NUDGE_UP_NEG_INDEX; // 0x01000000 +constexpr U32 AGENT_CONTROL_TURN_LEFT = 0x1 << CONTROL_TURN_LEFT_INDEX; // 0x02000000 +constexpr U32 AGENT_CONTROL_TURN_RIGHT = 0x1 << CONTROL_TURN_RIGHT_INDEX; // 0x04000000 + +constexpr U32 AGENT_CONTROL_AWAY = 0x1 << CONTROL_AWAY_INDEX; // 0x08000000 + +constexpr U32 AGENT_CONTROL_LBUTTON_DOWN = 0x1 << CONTROL_LBUTTON_DOWN_INDEX; // 0x10000000 +constexpr U32 AGENT_CONTROL_LBUTTON_UP = 0x1 << CONTROL_LBUTTON_UP_INDEX; // 0x20000000 +constexpr U32 AGENT_CONTROL_ML_LBUTTON_DOWN = 0x1 << CONTROL_ML_LBUTTON_DOWN_INDEX; // 0x40000000 +constexpr U32 AGENT_CONTROL_ML_LBUTTON_UP = ((U32)0x1) << CONTROL_ML_LBUTTON_UP_INDEX; // 0x80000000 // move these up so that we can hide them in "State" for object updates // (for now) -const U32 AGENT_ATTACH_OFFSET = 4; -const U32 AGENT_ATTACH_MASK = 0xf << AGENT_ATTACH_OFFSET; +constexpr U32 AGENT_ATTACH_OFFSET = 4; +constexpr U32 AGENT_ATTACH_MASK = 0xf << AGENT_ATTACH_OFFSET; // RN: this method swaps the upper and lower nibbles to maintain backward // compatibility with old objects that only used the upper nibble #define ATTACHMENT_ID_FROM_STATE(state) ((S32)((((U8)state & AGENT_ATTACH_MASK) >> 4) | (((U8)state & ~AGENT_ATTACH_MASK) << 4))) // DO NOT CHANGE THE SEQUENCE OF THIS LIST!! -const U8 CLICK_ACTION_NONE = 0; -const U8 CLICK_ACTION_TOUCH = 0; -const U8 CLICK_ACTION_SIT = 1; -const U8 CLICK_ACTION_BUY = 2; -const U8 CLICK_ACTION_PAY = 3; -const U8 CLICK_ACTION_OPEN = 4; -const U8 CLICK_ACTION_PLAY = 5; -const U8 CLICK_ACTION_OPEN_MEDIA = 6; -const U8 CLICK_ACTION_ZOOM = 7; -const U8 CLICK_ACTION_DISABLED = 8; -const U8 CLICK_ACTION_IGNORE = 9; +constexpr U8 CLICK_ACTION_NONE = 0; +constexpr U8 CLICK_ACTION_TOUCH = 0; +constexpr U8 CLICK_ACTION_SIT = 1; +constexpr U8 CLICK_ACTION_BUY = 2; +constexpr U8 CLICK_ACTION_PAY = 3; +constexpr U8 CLICK_ACTION_OPEN = 4; +constexpr U8 CLICK_ACTION_PLAY = 5; +constexpr U8 CLICK_ACTION_OPEN_MEDIA = 6; +constexpr U8 CLICK_ACTION_ZOOM = 7; +constexpr U8 CLICK_ACTION_DISABLED = 8; +constexpr U8 CLICK_ACTION_IGNORE = 9; // DO NOT CHANGE THE SEQUENCE OF THIS LIST!! diff --git a/indra/llcommon/llapp.h b/indra/llcommon/llapp.h index 3d18864b80..950f88e791 100644 --- a/indra/llcommon/llapp.h +++ b/indra/llcommon/llapp.h @@ -216,13 +216,6 @@ public: // soon as the application status changes away from APP_STATUS_RUNNING // (isRunning()). // - // sleep() returns true if it sleeps undisturbed for the entire specified - // duration. The idea is that you can code 'while sleep(duration) ...', - // which will break the loop once shutdown begins. - // - // Since any time-based LLUnit should be implicitly convertible to - // F32Milliseconds, accept that specific type as a proxy. - static bool sleep(F32Milliseconds duration); // Allow any duration defined in terms of <chrono>. // One can imagine a wonderfully general bidirectional conversion system // between any type derived from LLUnits::LLUnit<T, LLUnits::Seconds> and @@ -262,7 +255,7 @@ public: void setDebugFileNames(const std::string &path); // Return the Google Breakpad minidump filename after a crash. - char *getMiniDumpFilename() { return mMinidumpPath; } + char* getMiniDumpFilename() { return mMinidumpPath; } std::string* getStaticDebugFile() { return &mStaticDebugFileName; } std::string* getDynamicDebugFile() { return &mDynamicDebugFileName; } diff --git a/indra/llcommon/lldefs.h b/indra/llcommon/lldefs.h index d4b063f88c..96b48c1532 100644 --- a/indra/llcommon/lldefs.h +++ b/indra/llcommon/lldefs.h @@ -176,7 +176,7 @@ constexpr U32 MAXADDRSTR = 17; // 123.567.901.345 = 15 chars + \0 + // the negative value to a huge positive value, producing the wrong answer! // llless() specifically addresses that case. template <typename T0, typename T1> -inline bool llless(T0 d0, T1 d1) +constexpr bool llless(T0 d0, T1 d1) { if constexpr (std::is_signed_v<T0> && ! std::is_signed_v<T1>) { @@ -204,13 +204,13 @@ inline bool llless(T0 d0, T1 d1) // recursion tail template <typename T> -inline auto llmax(T data) +constexpr auto llmax(T data) { return data; } template <typename T0, typename T1, typename... Ts> -inline auto llmax(T0 d0, T1 d1, Ts... rest) +constexpr auto llmax(T0 d0, T1 d1, Ts... rest) { auto maxrest = llmax(d1, rest...); return llless(maxrest, d0)? d0 : maxrest; @@ -218,20 +218,20 @@ inline auto llmax(T0 d0, T1 d1, Ts... rest) // recursion tail template <typename T> -inline auto llmin(T data) +constexpr auto llmin(T data) { return data; } template <typename T0, typename T1, typename... Ts> -inline auto llmin(T0 d0, T1 d1, Ts... rest) +constexpr auto llmin(T0 d0, T1 d1, Ts... rest) { auto minrest = llmin(d1, rest...); return llless(d0, minrest) ? d0 : minrest; } template <typename A, typename MIN, typename MAX> -inline A llclamp(A a, MIN minval, MAX maxval) +constexpr A llclamp(A a, MIN minval, MAX maxval) { // The only troublesome case is if A is unsigned and either minval or // maxval is both signed and negative. Casting a negative number to @@ -262,13 +262,13 @@ inline A llclamp(A a, MIN minval, MAX maxval) } template <class LLDATATYPE> -inline LLDATATYPE llclampf(LLDATATYPE a) +constexpr LLDATATYPE llclampf(LLDATATYPE a) { return llmin(llmax(a, LLDATATYPE(0)), LLDATATYPE(1)); } template <class LLDATATYPE> -inline LLDATATYPE llclampb(LLDATATYPE a) +constexpr LLDATATYPE llclampb(LLDATATYPE a) { return llmin(llmax(a, LLDATATYPE(0)), LLDATATYPE(255)); } diff --git a/indra/llcommon/llinitparam.h b/indra/llcommon/llinitparam.h index 32d7b17034..170a171502 100644 --- a/indra/llcommon/llinitparam.h +++ b/indra/llcommon/llinitparam.h @@ -1771,8 +1771,13 @@ namespace LLInitParam // implicit conversion operator const container_t&() const { return mValues; } + operator container_t&() { return mValues; } // explicit conversion const container_t& operator()() const { return mValues; } + container_t& operator()() { return mValues; } + // direct Nth item access + const typename NAME_VALUE_LOOKUP::type_value_t& operator()(size_t index) const { return mValues[index]; } + typename NAME_VALUE_LOOKUP::type_value_t& operator()(size_t index) { return mValues[index]; } iterator begin() { return mValues.begin(); } iterator end() { return mValues.end(); } @@ -2102,13 +2107,13 @@ namespace LLInitParam class Multiple : public TypedParam<T, NAME_VALUE_LOOKUP, true> { typedef TypedParam<T, NAME_VALUE_LOOKUP, true> super_t; - typedef Multiple<T, RANGE, NAME_VALUE_LOOKUP> self_t; - typedef typename super_t::container_t container_t; + typedef Multiple<T, RANGE, NAME_VALUE_LOOKUP> self_t; + typedef typename super_t::container_t container_t; typedef typename super_t::value_t value_t; public: - typedef typename super_t::iterator iterator; - typedef typename super_t::const_iterator const_iterator; + typedef typename super_t::iterator iterator; + typedef typename super_t::const_iterator const_iterator; using super_t::operator(); using super_t::operator const container_t&; @@ -2836,3 +2841,4 @@ namespace LLInitParam #endif // LL_LLPARAM_H + diff --git a/indra/llcommon/llkeybind.cpp b/indra/llcommon/llkeybind.cpp index e36c1d0a4c..83c53d220d 100644 --- a/indra/llcommon/llkeybind.cpp +++ b/indra/llcommon/llkeybind.cpp @@ -123,7 +123,7 @@ LLKeyData& LLKeyData::operator=(const LLKeyData& rhs) return *this; } -bool LLKeyData::operator==(const LLKeyData& rhs) +bool LLKeyData::operator==(const LLKeyData& rhs) const { if (mMouse != rhs.mMouse) return false; if (mKey != rhs.mKey) return false; @@ -132,7 +132,7 @@ bool LLKeyData::operator==(const LLKeyData& rhs) return true; } -bool LLKeyData::operator!=(const LLKeyData& rhs) +bool LLKeyData::operator!=(const LLKeyData& rhs) const { if (mMouse != rhs.mMouse) return true; if (mKey != rhs.mKey) return true; @@ -179,7 +179,7 @@ LLKeyBind::LLKeyBind(const LLSD &key_bind) } } -bool LLKeyBind::operator==(const LLKeyBind& rhs) +bool LLKeyBind::operator==(const LLKeyBind& rhs) const { auto size = mData.size(); if (size != rhs.mData.size()) return false; @@ -192,7 +192,7 @@ bool LLKeyBind::operator==(const LLKeyBind& rhs) return true; } -bool LLKeyBind::operator!=(const LLKeyBind& rhs) +bool LLKeyBind::operator!=(const LLKeyBind& rhs) const { auto size = mData.size(); if (size != rhs.mData.size()) return true; diff --git a/indra/llcommon/llkeybind.h b/indra/llcommon/llkeybind.h index 1bbb2fadb5..eb9b68f9d1 100644 --- a/indra/llcommon/llkeybind.h +++ b/indra/llcommon/llkeybind.h @@ -44,8 +44,8 @@ public: bool empty() const { return isEmpty(); }; void reset(); LLKeyData& operator=(const LLKeyData& rhs); - bool operator==(const LLKeyData& rhs); - bool operator!=(const LLKeyData& rhs); + bool operator==(const LLKeyData& rhs) const; + bool operator!=(const LLKeyData& rhs) const; bool canHandle(const LLKeyData& data) const; bool canHandle(EMouseClickType mouse, KEY key, MASK mask) const; @@ -64,8 +64,8 @@ public: LLKeyBind() {} LLKeyBind(const LLSD &key_bind); - bool operator==(const LLKeyBind& rhs); - bool operator!=(const LLKeyBind& rhs); + bool operator==(const LLKeyBind& rhs) const; + bool operator!=(const LLKeyBind& rhs) const; bool isEmpty() const; bool empty() const { return isEmpty(); }; diff --git a/indra/llcommon/llsd.cpp b/indra/llcommon/llsd.cpp index 77fe545c3f..1058ab385b 100644 --- a/indra/llcommon/llsd.cpp +++ b/indra/llcommon/llsd.cpp @@ -974,6 +974,31 @@ void LLSD::clear() { Impl::assignUndefined(impl); } LLSD::Type LLSD::type() const { return safe(impl).type(); } +bool LLSD::isEmpty() const +{ + switch (type()) + { + case TypeUndefined: + return true; // Always empty + case TypeBinary: + return !asBoolean(); // Empty when default + case TypeInteger: + return !asInteger(); // Empty when default + case TypeReal: + return !asReal(); // Empty when default + case TypeString: + case TypeURI: + return asString().empty(); // Empty natively + case TypeArray: + case TypeMap: + return !size(); // Empty natively + default:; + } + // All other value types (TypeDate) don't have default values so can't be empty + return false; +} + + // Scalar Constructors LLSD::LLSD(Boolean v) : impl(0) { ALLOC_LLSD_OBJECT; assign(v); } LLSD::LLSD(Integer v) : impl(0) { ALLOC_LLSD_OBJECT; assign(v); } diff --git a/indra/llcommon/llsd.h b/indra/llcommon/llsd.h index d2b3548831..e018b400cb 100644 --- a/indra/llcommon/llsd.h +++ b/indra/llcommon/llsd.h @@ -420,6 +420,7 @@ public: bool isBinary() const { return type() == TypeBinary; } bool isMap() const { return type() == TypeMap; } bool isArray() const { return type() == TypeArray; } + bool isEmpty() const; //@} /** @name Automatic Cast Protection diff --git a/indra/llcommon/llstring.cpp b/indra/llcommon/llstring.cpp index 447fa2d9dd..e38622b43b 100644 --- a/indra/llcommon/llstring.cpp +++ b/indra/llcommon/llstring.cpp @@ -1144,18 +1144,27 @@ void LLStringOps::setupDayFormat(const std::string& data) } -std::string LLStringOps::getDatetimeCode (std::string key) +std::string LLStringOps::getDatetimeCode(std::string key) { - std::map<std::string, std::string>::iterator iter; + std::map<std::string, std::string>::iterator iter = datetimeToCodes.find(key); + return iter == datetimeToCodes.end() ? LLStringUtil::null : iter->second; +} - iter = datetimeToCodes.find (key); - if (iter != datetimeToCodes.end()) +void LLStringOps::splitString(const std::string& text, char delimiter, + std::function<void(const std::string&)> handler) +{ + std::size_t from = 0; + for (std::size_t i = 0; i < text.size(); ++i) { - return iter->second; + if (text[i] == delimiter) + { + handler(text.substr(from, i - from)); + from = i + 1; + } } - else + if (from <= text.size()) { - return std::string(""); + handler(text.substr(from)); } } diff --git a/indra/llcommon/llstring.h b/indra/llcommon/llstring.h index b552aede82..b15a85cb2a 100644 --- a/indra/llcommon/llstring.h +++ b/indra/llcommon/llstring.h @@ -36,6 +36,7 @@ //#include <locale> #include <iomanip> #include <algorithm> +#include <functional> #include <vector> #include <map> #include <type_traits> @@ -214,6 +215,9 @@ public: static std::string getDatetimeCode (std::string key); + static void splitString(const std::string& text, char delimiter, + std::function<void(const std::string&)> handler); + // Express a value like 1234567 as "1.23M" static std::string getReadableNumber(F64 num); }; @@ -443,6 +447,65 @@ public: static bool isPartOfWord(T c) { return (c == (T)'_') || LLStringOps::isAlnum(c); } + // Join non-empty strings from values using value itself and delimiter + template<class C> + static std::string join(const C& values, T delimiter = ',') + { + std::string result; + for (const std::string& value : values) + { + if (!value.empty()) + { + if (!result.empty()) + { + result += delimiter; + } + result += value; + } + } + return result; + } + + // Join non-empty strings from values using stringify(value) and delimiter + template<class C, class V> + static std::string join(const C& values, std::function<std::string(const V&)> stringify, T delimiter = ',') + { + std::string result; + for (const V& value : values) + { + std::string string = stringify(value); + if (!string.empty()) + { + if (!result.empty()) + { + result += delimiter; + } + result += string; + } + } + return result; + } + + // Join non-empty strings from values using stringify(index, value) and delimiter + template<class C, class V> + static std::string join(const C& values, std::function<std::string(size_t index, const V&)> stringify, T delimiter = ',') + { + std::string result; + for (size_t i = 0; i < values.size(); ++i) + { + std::string string = stringify(i, values[i]); + if (!string.empty()) + { + if (!result.empty()) + { + result += delimiter; + } + result += string; + } + } + return result; + } + #ifdef _DEBUG LL_COMMON_API static void testHarness(); #endif @@ -550,7 +613,13 @@ private: public: ll_convert(const FROM& ref): mRef(ref) {} - template <typename TO> + inline operator const FROM&() const + { + return mRef; + } + + template <typename TO, + std::enable_if_t<! std::is_same_v<std::decay_t<TO>, std::decay_t<FROM>>, bool> =true> inline operator TO() const { return ll_convert_impl<TO, std::decay_t<const FROM>>()(mRef); @@ -559,7 +628,15 @@ public: // When the TO type must be explicit, use a function template to get // ll_convert_to<TO>(from_value) API. -template<typename TO, typename FROM> +template<typename SAME> +const SAME& ll_convert_to(const SAME& in) +{ + return in; +} + +template<typename TO, + typename FROM, + std::enable_if_t<! std::is_same_v<std::decay_t<TO>, std::decay_t<FROM>>, bool> =true> TO ll_convert_to(const FROM& in) { return ll_convert_impl<TO, std::decay_t<const FROM>>()(in); diff --git a/indra/llcommon/llthreadsafequeue.h b/indra/llcommon/llthreadsafequeue.h index 034e3f7897..7a5eb5b33d 100644 --- a/indra/llcommon/llthreadsafequeue.h +++ b/indra/llcommon/llthreadsafequeue.h @@ -452,7 +452,10 @@ ElementT LLThreadSafeQueue<ElementT, QueueT>::pop(void) // so we can finish draining the queue. pop_result popped = pop_(lock1, value); if (popped == POPPED) - return std::move(value); + // don't use std::move when returning local value because + // it prevents the compiler from optimizing with copy elision + //return std::move(value); + return value; // Once the queue is DONE, there will never be any more coming. if (popped == DONE) diff --git a/indra/llcommon/tests/llerror_test.cpp b/indra/llcommon/tests/llerror_test.cpp index d597e90ba0..b6a1bea42c 100644 --- a/indra/llcommon/tests/llerror_test.cpp +++ b/indra/llcommon/tests/llerror_test.cpp @@ -61,6 +61,8 @@ namespace { #ifdef __clang__ # pragma clang diagnostic ignored "-Wunused-function" +#elif defined(LL_GNUC) +# pragma GCC diagnostic ignored "-Wunused-function" #endif void test_that_error_h_includes_enough_things_to_compile_a_message() { diff --git a/indra/llcommon/tests/llsingleton_test.cpp b/indra/llcommon/tests/llsingleton_test.cpp index adf5804272..91304b4885 100644 --- a/indra/llcommon/tests/llsingleton_test.cpp +++ b/indra/llcommon/tests/llsingleton_test.cpp @@ -240,12 +240,14 @@ namespace tut PSing1::initParamSingleton("again"); }); ensure_contains("second ctor(string) didn't throw", threw, "twice"); +#ifndef LL_GNUC // FIXME: Fails to build under GCC // try to initialize using the other constructor -- should be // well-formed, but illegal at runtime threw = catcherr.catch_llerrs([](){ PSing1::initParamSingleton(17); }); ensure_contains("other ctor(int) didn't throw", threw, "twice"); +#endif PSing1::deleteSingleton(); ensure("false negative on wasDeleted()", PSing1::wasDeleted()); threw = catcherr.catch_llerrs([](){ @@ -254,6 +256,7 @@ namespace tut ensure_contains("accessed deleted LLParamSingleton", threw, "deleted"); } +#ifndef LL_GNUC // FIXME: Fails to build under GCC template<> template<> void singleton_object_t::test<13>() { @@ -275,6 +278,7 @@ namespace tut }); ensure_contains("other ctor(string) didn't throw", threw, "twice"); } +#endif class CircularPCtor: public LLParamSingleton<CircularPCtor> { diff --git a/indra/llinventory/llsettingsdaycycle.cpp b/indra/llinventory/llsettingsdaycycle.cpp index a45ab5a09c..2baf140e6a 100644 --- a/indra/llinventory/llsettingsdaycycle.cpp +++ b/indra/llinventory/llsettingsdaycycle.cpp @@ -143,10 +143,6 @@ LLSettingsDay::LLSettingsDay() : //========================================================================= LLSD& LLSettingsDay::getSettings() { - if (mDaySettings.size() > 0) - { - return mDaySettings; - } mDaySettings = LLSD::emptyMap(); LLSD& settings = LLSettingsBase::getSettings(); diff --git a/indra/llmath/llcamera.h b/indra/llmath/llcamera.h index b6e0e4a2be..6201761c46 100644 --- a/indra/llmath/llcamera.h +++ b/indra/llmath/llcamera.h @@ -33,23 +33,23 @@ #include "llplane.h" #include "llvector4a.h" -const F32 DEFAULT_FIELD_OF_VIEW = 60.f * DEG_TO_RAD; -const F32 DEFAULT_ASPECT_RATIO = 640.f / 480.f; -const F32 DEFAULT_NEAR_PLANE = 0.25f; -const F32 DEFAULT_FAR_PLANE = 64.f; // far reaches across two horizontal, not diagonal, regions +constexpr F32 DEFAULT_FIELD_OF_VIEW = 60.f * DEG_TO_RAD; +constexpr F32 DEFAULT_ASPECT_RATIO = 640.f / 480.f; +constexpr F32 DEFAULT_NEAR_PLANE = 0.25f; +constexpr F32 DEFAULT_FAR_PLANE = 64.f; // far reaches across two horizontal, not diagonal, regions -const F32 MAX_ASPECT_RATIO = 50.0f; -const F32 MAX_NEAR_PLANE = 1023.9f; // Clamp the near plane just before the skybox ends -const F32 MAX_FAR_PLANE = 100000.0f; //1000000.0f; // Max allowed. Not good Z precision though. -const F32 MAX_FAR_CLIP = 512.0f; +constexpr F32 MAX_ASPECT_RATIO = 50.0f; +constexpr F32 MAX_NEAR_PLANE = 1023.9f; // Clamp the near plane just before the skybox ends +constexpr F32 MAX_FAR_PLANE = 100000.0f; //1000000.0f; // Max allowed. Not good Z precision though. +constexpr F32 MAX_FAR_CLIP = 512.0f; -const F32 MIN_ASPECT_RATIO = 0.02f; -const F32 MIN_NEAR_PLANE = 0.1f; -const F32 MIN_FAR_PLANE = 0.2f; +constexpr F32 MIN_ASPECT_RATIO = 0.02f; +constexpr F32 MIN_NEAR_PLANE = 0.1f; +constexpr 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; +constexpr F32 MIN_FIELD_OF_VIEW = 5.0f * DEG_TO_RAD; +constexpr F32 MAX_FIELD_OF_VIEW = 175.f * DEG_TO_RAD; // An LLCamera is an LLCoorFrame with a view frustum. // This means that it has several methods for moving it around diff --git a/indra/llmath/llsimdmath.h b/indra/llmath/llsimdmath.h index 40953dc2e8..592bb124c2 100644 --- a/indra/llmath/llsimdmath.h +++ b/indra/llmath/llsimdmath.h @@ -31,8 +31,15 @@ #error "Please include llmath.h before this file." #endif -#if ( ( LL_DARWIN || LL_LINUX ) && !(__SSE2__) ) || ( LL_WINDOWS && ( _M_IX86_FP < 2 && ADDRESS_SIZE == 32 ) ) -#error SSE2 not enabled. LLVector4a and related class will not compile. +// the check for this error case must be split into multiple parts +// because some versions of VS complain about '__SSE2__' +//#if ( ( LL_DARWIN || LL_LINUX ) && !(__SSE2__) ) || ( LL_WINDOWS && ( _M_IX86_FP < 2 && ADDRESS_SIZE == 32 ) ) +#if ( ( LL_DARWIN || LL_LINUX ) ) + #if !(__SSE2__) + #error SSE2 not enabled. LLVector4a and related class will not compile. + #endif +#elif ( LL_WINDOWS && ( _M_IX86_FP < 2 && ADDRESS_SIZE == 32 ) ) + #error SSE2 not enabled. LLVector4a and related class will not compile. #endif #if !LL_WINDOWS diff --git a/indra/llmath/v2math.cpp b/indra/llmath/v2math.cpp index 4649e13376..198fedcb03 100644 --- a/indra/llmath/v2math.cpp +++ b/indra/llmath/v2math.cpp @@ -26,7 +26,6 @@ #include "linden_common.h" -//#include "vmath.h" #include "v2math.h" #include "v3math.h" #include "v4math.h" @@ -47,8 +46,8 @@ bool LLVector2::abs() { bool ret{ false }; - if (mV[0] < 0.f) { mV[0] = -mV[0]; ret = true; } - if (mV[1] < 0.f) { mV[1] = -mV[1]; ret = true; } + if (mV[VX] < 0.f) { mV[VX] = -mV[VX]; ret = true; } + if (mV[VY] < 0.f) { mV[VY] = -mV[VY]; ret = true; } return ret; } @@ -67,7 +66,7 @@ F32 angle_between(const LLVector2& a, const LLVector2& b) return angle; } -bool are_parallel(const LLVector2 &a, const LLVector2 &b, float epsilon) +bool are_parallel(const LLVector2& a, const LLVector2& b, F32 epsilon) { LLVector2 an = a; LLVector2 bn = b; @@ -82,28 +81,28 @@ bool are_parallel(const LLVector2 &a, const LLVector2 &b, float epsilon) } -F32 dist_vec(const LLVector2 &a, const LLVector2 &b) +F32 dist_vec(const LLVector2& a, const LLVector2& b) { - F32 x = a.mV[0] - b.mV[0]; - F32 y = a.mV[1] - b.mV[1]; + F32 x = a.mV[VX] - b.mV[VX]; + F32 y = a.mV[VY] - b.mV[VY]; return (F32) sqrt( x*x + y*y ); } -F32 dist_vec_squared(const LLVector2 &a, const LLVector2 &b) +F32 dist_vec_squared(const LLVector2& a, const LLVector2& b) { - F32 x = a.mV[0] - b.mV[0]; - F32 y = a.mV[1] - b.mV[1]; + F32 x = a.mV[VX] - b.mV[VX]; + F32 y = a.mV[VY] - b.mV[VY]; return x*x + y*y; } -F32 dist_vec_squared2D(const LLVector2 &a, const LLVector2 &b) +F32 dist_vec_squared2D(const LLVector2& a, const LLVector2& b) { - F32 x = a.mV[0] - b.mV[0]; - F32 y = a.mV[1] - b.mV[1]; + F32 x = a.mV[VX] - b.mV[VX]; + F32 y = a.mV[VY] - b.mV[VY]; return x*x + y*y; } -LLVector2 lerp(const LLVector2 &a, const LLVector2 &b, F32 u) +LLVector2 lerp(const LLVector2& a, const LLVector2& b, F32 u) { return LLVector2( a.mV[VX] + (b.mV[VX] - a.mV[VX]) * u, @@ -113,14 +112,14 @@ LLVector2 lerp(const LLVector2 &a, const LLVector2 &b, F32 u) LLSD LLVector2::getValue() const { LLSD ret; - ret[0] = mV[0]; - ret[1] = mV[1]; + ret[0] = mV[VX]; + ret[1] = mV[VY]; return ret; } void LLVector2::setValue(const LLSD& sd) { - mV[0] = (F32) sd[0].asReal(); - mV[1] = (F32) sd[1].asReal(); + mV[VX] = (F32) sd[0].asReal(); + mV[VY] = (F32) sd[1].asReal(); } diff --git a/indra/llmath/v2math.h b/indra/llmath/v2math.h index a61c946304..a0ba3ec505 100644 --- a/indra/llmath/v2math.h +++ b/indra/llmath/v2math.h @@ -36,7 +36,7 @@ class LLQuaternion; // Llvector2 = |x y z w| -static const U32 LENGTHOFVECTOR2 = 2; +static constexpr U32 LENGTHOFVECTOR2 = 2; class LLVector2 { @@ -82,7 +82,7 @@ class LLVector2 const LLVector2& scaleVec(const LLVector2& vec); // scales per component by vec - bool isNull(); // Returns true if vector has a _very_small_ length + bool isNull() const; // Returns true if vector has a _very_small_ length bool isExactlyZero() const { return !mV[VX] && !mV[VY]; } F32 operator[](int idx) const { return mV[idx]; } @@ -113,16 +113,16 @@ class LLVector2 // Non-member functions -F32 angle_between(const LLVector2 &a, const LLVector2 &b); // Returns angle (radians) between a and b -bool are_parallel(const LLVector2 &a, const LLVector2 &b, F32 epsilon=F_APPROXIMATELY_ZERO); // Returns true if a and b are very close to parallel -F32 dist_vec(const LLVector2 &a, const LLVector2 &b); // Returns distance between a and b -F32 dist_vec_squared(const LLVector2 &a, const LLVector2 &b);// Returns distance squared between a and b -F32 dist_vec_squared2D(const LLVector2 &a, const LLVector2 &b);// Returns distance squared between a and b ignoring Z component -LLVector2 lerp(const LLVector2 &a, const LLVector2 &b, F32 u); // Returns a vector that is a linear interpolation between a and b +F32 angle_between(const LLVector2& a, const LLVector2& b); // Returns angle (radians) between a and b +bool are_parallel(const LLVector2& a, const LLVector2& b, F32 epsilon = F_APPROXIMATELY_ZERO); // Returns true if a and b are very close to parallel +F32 dist_vec(const LLVector2& a, const LLVector2& b); // Returns distance between a and b +F32 dist_vec_squared(const LLVector2& a, const LLVector2& b);// Returns distance squared between a and b +F32 dist_vec_squared2D(const LLVector2& a, const LLVector2& b);// Returns distance squared between a and b ignoring Z component +LLVector2 lerp(const LLVector2& a, const LLVector2& b, F32 u); // Returns a vector that is a linear interpolation between a and b // Constructors -inline LLVector2::LLVector2(void) +inline LLVector2::LLVector2() { mV[VX] = 0.f; mV[VY] = 0.f; @@ -153,27 +153,27 @@ inline LLVector2::LLVector2(const LLSD &sd) // Clear and Assignment Functions -inline void LLVector2::clear(void) +inline void LLVector2::clear() { mV[VX] = 0.f; mV[VY] = 0.f; } -inline void LLVector2::setZero(void) +inline void LLVector2::setZero() { mV[VX] = 0.f; mV[VY] = 0.f; } // deprecated -inline void LLVector2::clearVec(void) +inline void LLVector2::clearVec() { mV[VX] = 0.f; mV[VY] = 0.f; } // deprecated -inline void LLVector2::zeroVec(void) +inline void LLVector2::zeroVec() { mV[VX] = 0.f; mV[VY] = 0.f; @@ -222,31 +222,31 @@ inline void LLVector2::setVec(const F32 *vec) // LLVector2 Magnitude and Normalization Functions -inline F32 LLVector2::length(void) const +inline F32 LLVector2::length() const { - return (F32) sqrt(mV[0]*mV[0] + mV[1]*mV[1]); + return sqrt(mV[VX]*mV[VX] + mV[VY]*mV[VY]); } -inline F32 LLVector2::lengthSquared(void) const +inline F32 LLVector2::lengthSquared() const { - return mV[0]*mV[0] + mV[1]*mV[1]; + return mV[VX]*mV[VX] + mV[VY]*mV[VY]; } -inline F32 LLVector2::normalize(void) +inline F32 LLVector2::normalize() { - F32 mag = (F32) sqrt(mV[0]*mV[0] + mV[1]*mV[1]); + F32 mag = sqrt(mV[VX]*mV[VX] + mV[VY]*mV[VY]); F32 oomag; if (mag > FP_MAG_THRESHOLD) { oomag = 1.f/mag; - mV[0] *= oomag; - mV[1] *= oomag; + mV[VX] *= oomag; + mV[VY] *= oomag; } else { - mV[0] = 0.f; - mV[1] = 0.f; + mV[VX] = 0.f; + mV[VY] = 0.f; mag = 0; } return (mag); @@ -259,33 +259,33 @@ inline bool LLVector2::isFinite() const } // deprecated -inline F32 LLVector2::magVec(void) const +inline F32 LLVector2::magVec() const { - return (F32) sqrt(mV[0]*mV[0] + mV[1]*mV[1]); + return sqrt(mV[VX]*mV[VX] + mV[VY]*mV[VY]); } // deprecated -inline F32 LLVector2::magVecSquared(void) const +inline F32 LLVector2::magVecSquared() const { - return mV[0]*mV[0] + mV[1]*mV[1]; + return mV[VX]*mV[VX] + mV[VY]*mV[VY]; } // deprecated -inline F32 LLVector2::normVec(void) +inline F32 LLVector2::normVec() { - F32 mag = (F32) sqrt(mV[0]*mV[0] + mV[1]*mV[1]); + F32 mag = sqrt(mV[VX]*mV[VX] + mV[VY]*mV[VY]); F32 oomag; if (mag > FP_MAG_THRESHOLD) { oomag = 1.f/mag; - mV[0] *= oomag; - mV[1] *= oomag; + mV[VX] *= oomag; + mV[VY] *= oomag; } else { - mV[0] = 0.f; - mV[1] = 0.f; + mV[VX] = 0.f; + mV[VY] = 0.f; mag = 0; } return (mag); @@ -299,7 +299,7 @@ inline const LLVector2& LLVector2::scaleVec(const LLVector2& vec) return *this; } -inline bool LLVector2::isNull() +inline bool LLVector2::isNull() const { if ( F_APPROXIMATELY_ZERO > mV[VX]*mV[VX] + mV[VY]*mV[VY] ) { @@ -312,7 +312,7 @@ inline bool LLVector2::isNull() // LLVector2 Operators // For sorting. By convention, x is "more significant" than y. -inline bool operator<(const LLVector2 &a, const LLVector2 &b) +inline bool operator<(const LLVector2& a, const LLVector2& b) { if( a.mV[VX] == b.mV[VX] ) { @@ -325,95 +325,95 @@ inline bool operator<(const LLVector2 &a, const LLVector2 &b) } -inline LLVector2 operator+(const LLVector2 &a, const LLVector2 &b) +inline LLVector2 operator+(const LLVector2& a, const LLVector2& b) { LLVector2 c(a); return c += b; } -inline LLVector2 operator-(const LLVector2 &a, const LLVector2 &b) +inline LLVector2 operator-(const LLVector2& a, const LLVector2& b) { LLVector2 c(a); return c -= b; } -inline F32 operator*(const LLVector2 &a, const LLVector2 &b) +inline F32 operator*(const LLVector2& a, const LLVector2& b) { - return (a.mV[0]*b.mV[0] + a.mV[1]*b.mV[1]); + return (a.mV[VX]*b.mV[VX] + a.mV[VY]*b.mV[VY]); } -inline LLVector2 operator%(const LLVector2 &a, const LLVector2 &b) +inline LLVector2 operator%(const LLVector2& a, const LLVector2& b) { - return LLVector2(a.mV[0]*b.mV[1] - b.mV[0]*a.mV[1], a.mV[1]*b.mV[0] - b.mV[1]*a.mV[0]); + return LLVector2(a.mV[VX]*b.mV[VY] - b.mV[VX]*a.mV[VY], a.mV[VY]*b.mV[VX] - b.mV[VY]*a.mV[VX]); } -inline LLVector2 operator/(const LLVector2 &a, F32 k) +inline LLVector2 operator/(const LLVector2& a, F32 k) { F32 t = 1.f / k; - return LLVector2( a.mV[0] * t, a.mV[1] * t ); + return LLVector2( a.mV[VX] * t, a.mV[VY] * t ); } -inline LLVector2 operator*(const LLVector2 &a, F32 k) +inline LLVector2 operator*(const LLVector2& a, F32 k) { - return LLVector2( a.mV[0] * k, a.mV[1] * k ); + return LLVector2( a.mV[VX] * k, a.mV[VY] * k ); } -inline LLVector2 operator*(F32 k, const LLVector2 &a) +inline LLVector2 operator*(F32 k, const LLVector2& a) { - return LLVector2( a.mV[0] * k, a.mV[1] * k ); + return LLVector2( a.mV[VX] * k, a.mV[VY] * k ); } -inline bool operator==(const LLVector2 &a, const LLVector2 &b) +inline bool operator==(const LLVector2& a, const LLVector2& b) { - return ( (a.mV[0] == b.mV[0]) - &&(a.mV[1] == b.mV[1])); + return ( (a.mV[VX] == b.mV[VX]) + &&(a.mV[VY] == b.mV[VY])); } -inline bool operator!=(const LLVector2 &a, const LLVector2 &b) +inline bool operator!=(const LLVector2& a, const LLVector2& b) { - return ( (a.mV[0] != b.mV[0]) - ||(a.mV[1] != b.mV[1])); + return ( (a.mV[VX] != b.mV[VX]) + ||(a.mV[VY] != b.mV[VY])); } -inline const LLVector2& operator+=(LLVector2 &a, const LLVector2 &b) +inline const LLVector2& operator+=(LLVector2& a, const LLVector2& b) { - a.mV[0] += b.mV[0]; - a.mV[1] += b.mV[1]; + a.mV[VX] += b.mV[VX]; + a.mV[VY] += b.mV[VY]; return a; } -inline const LLVector2& operator-=(LLVector2 &a, const LLVector2 &b) +inline const LLVector2& operator-=(LLVector2& a, const LLVector2& b) { - a.mV[0] -= b.mV[0]; - a.mV[1] -= b.mV[1]; + a.mV[VX] -= b.mV[VX]; + a.mV[VY] -= b.mV[VY]; return a; } -inline const LLVector2& operator%=(LLVector2 &a, const LLVector2 &b) +inline const LLVector2& operator%=(LLVector2& a, const LLVector2& b) { - LLVector2 ret(a.mV[0]*b.mV[1] - b.mV[0]*a.mV[1], a.mV[1]*b.mV[0] - b.mV[1]*a.mV[0]); + LLVector2 ret(a.mV[VX]*b.mV[VY] - b.mV[VX]*a.mV[VY], a.mV[VY]*b.mV[VX] - b.mV[VY]*a.mV[VX]); a = ret; return a; } -inline const LLVector2& operator*=(LLVector2 &a, F32 k) +inline const LLVector2& operator*=(LLVector2& a, F32 k) { - a.mV[0] *= k; - a.mV[1] *= k; + a.mV[VX] *= k; + a.mV[VY] *= k; return a; } -inline const LLVector2& operator/=(LLVector2 &a, F32 k) +inline const LLVector2& operator/=(LLVector2& a, F32 k) { F32 t = 1.f / k; - a.mV[0] *= t; - a.mV[1] *= t; + a.mV[VX] *= t; + a.mV[VY] *= t; return a; } -inline LLVector2 operator-(const LLVector2 &a) +inline LLVector2 operator-(const LLVector2& a) { - return LLVector2( -a.mV[0], -a.mV[1] ); + return LLVector2( -a.mV[VX], -a.mV[VY] ); } inline void update_min_max(LLVector2& min, LLVector2& max, const LLVector2& pos) @@ -431,7 +431,7 @@ inline void update_min_max(LLVector2& min, LLVector2& max, const LLVector2& pos) } } -inline std::ostream& operator<<(std::ostream& s, const LLVector2 &a) +inline std::ostream& operator<<(std::ostream& s, const LLVector2& a) { s << "{ " << a.mV[VX] << ", " << a.mV[VY] << " }"; return s; diff --git a/indra/llmath/v3dmath.cpp b/indra/llmath/v3dmath.cpp index bb55c812b5..bd6d838186 100644 --- a/indra/llmath/v3dmath.cpp +++ b/indra/llmath/v3dmath.cpp @@ -57,13 +57,13 @@ bool LLVector3d::clamp(F64 min, F64 max) { bool ret{ false }; - if (mdV[0] < min) { mdV[0] = min; ret = true; } - if (mdV[1] < min) { mdV[1] = min; ret = true; } - if (mdV[2] < min) { mdV[2] = min; ret = true; } + if (mdV[VX] < min) { mdV[VX] = min; ret = true; } + if (mdV[VY] < min) { mdV[VY] = min; ret = true; } + if (mdV[VZ] < min) { mdV[VZ] = min; ret = true; } - if (mdV[0] > max) { mdV[0] = max; ret = true; } - if (mdV[1] > max) { mdV[1] = max; ret = true; } - if (mdV[2] > max) { mdV[2] = max; ret = true; } + if (mdV[VX] > max) { mdV[VX] = max; ret = true; } + if (mdV[VY] > max) { mdV[VY] = max; ret = true; } + if (mdV[VZ] > max) { mdV[VZ] = max; ret = true; } return ret; } @@ -74,9 +74,9 @@ bool LLVector3d::abs() { bool ret{ false }; - if (mdV[0] < 0.0) { mdV[0] = -mdV[0]; ret = true; } - if (mdV[1] < 0.0) { mdV[1] = -mdV[1]; ret = true; } - if (mdV[2] < 0.0) { mdV[2] = -mdV[2]; ret = true; } + if (mdV[VX] < 0.0) { mdV[VX] = -mdV[VX]; ret = true; } + if (mdV[VY] < 0.0) { mdV[VY] = -mdV[VY]; ret = true; } + if (mdV[VZ] < 0.0) { mdV[VZ] = -mdV[VZ]; ret = true; } return ret; } @@ -89,9 +89,9 @@ std::ostream& operator<<(std::ostream& s, const LLVector3d &a) const LLVector3d& LLVector3d::operator=(const LLVector4 &a) { - mdV[0] = a.mV[0]; - mdV[1] = a.mV[1]; - mdV[2] = a.mV[2]; + mdV[VX] = a.mV[VX]; + mdV[VY] = a.mV[VY]; + mdV[VZ] = a.mV[VZ]; return *this; } diff --git a/indra/llmath/v3dmath.h b/indra/llmath/v3dmath.h index ece8c54ea4..7c94ebdf9b 100644 --- a/indra/llmath/v3dmath.h +++ b/indra/llmath/v3dmath.h @@ -54,17 +54,17 @@ class LLVector3d void setValue(const LLSD& sd) { - mdV[0] = sd[0].asReal(); - mdV[1] = sd[1].asReal(); - mdV[2] = sd[2].asReal(); + mdV[VX] = sd[0].asReal(); + mdV[VY] = sd[1].asReal(); + mdV[VZ] = sd[2].asReal(); } LLSD getValue() const { LLSD ret; - ret[0] = mdV[0]; - ret[1] = mdV[1]; - ret[2] = mdV[2]; + ret[0] = mdV[VX]; + ret[1] = mdV[VY]; + ret[2] = mdV[VZ]; return ret; } @@ -134,26 +134,26 @@ typedef LLVector3d LLGlobalVec; inline const LLVector3d &LLVector3d::set(const LLVector3 &vec) { - mdV[0] = vec.mV[0]; - mdV[1] = vec.mV[1]; - mdV[2] = vec.mV[2]; + mdV[VX] = vec.mV[VX]; + mdV[VY] = vec.mV[VY]; + mdV[VZ] = vec.mV[VZ]; return *this; } inline const LLVector3d &LLVector3d::setVec(const LLVector3 &vec) { - mdV[0] = vec.mV[0]; - mdV[1] = vec.mV[1]; - mdV[2] = vec.mV[2]; + mdV[VX] = vec.mV[VX]; + mdV[VY] = vec.mV[VY]; + mdV[VZ] = vec.mV[VZ]; return *this; } inline LLVector3d::LLVector3d(void) { - mdV[0] = 0.f; - mdV[1] = 0.f; - mdV[2] = 0.f; + mdV[VX] = 0.f; + mdV[VY] = 0.f; + mdV[VZ] = 0.f; } inline LLVector3d::LLVector3d(const F64 x, const F64 y, const F64 z) @@ -199,33 +199,33 @@ inline bool LLVector3d::isFinite() const inline const LLVector3d& LLVector3d::clear(void) { - mdV[0] = 0.f; - mdV[1] = 0.f; - mdV[2]= 0.f; + mdV[VX] = 0.f; + mdV[VY] = 0.f; + mdV[VZ] = 0.f; return (*this); } inline const LLVector3d& LLVector3d::clearVec(void) { - mdV[0] = 0.f; - mdV[1] = 0.f; - mdV[2]= 0.f; + mdV[VX] = 0.f; + mdV[VY] = 0.f; + mdV[VZ] = 0.f; return (*this); } inline const LLVector3d& LLVector3d::setZero(void) { - mdV[0] = 0.f; - mdV[1] = 0.f; - mdV[2] = 0.f; + mdV[VX] = 0.f; + mdV[VY] = 0.f; + mdV[VZ] = 0.f; return (*this); } inline const LLVector3d& LLVector3d::zeroVec(void) { - mdV[0] = 0.f; - mdV[1] = 0.f; - mdV[2] = 0.f; + mdV[VX] = 0.f; + mdV[VY] = 0.f; + mdV[VZ] = 0.f; return (*this); } @@ -239,17 +239,17 @@ inline const LLVector3d& LLVector3d::set(const F64 x, const F64 y, const F64 inline const LLVector3d& LLVector3d::set(const LLVector3d &vec) { - mdV[0] = vec.mdV[0]; - mdV[1] = vec.mdV[1]; - mdV[2] = vec.mdV[2]; + mdV[VX] = vec.mdV[VX]; + mdV[VY] = vec.mdV[VY]; + mdV[VZ] = vec.mdV[VZ]; return (*this); } inline const LLVector3d& LLVector3d::set(const F64 *vec) { - mdV[0] = vec[0]; - mdV[1] = vec[1]; - mdV[2] = vec[2]; + mdV[VX] = vec[0]; + mdV[VY] = vec[1]; + mdV[VZ] = vec[2]; return (*this); } @@ -261,61 +261,61 @@ inline const LLVector3d& LLVector3d::setVec(const F64 x, const F64 y, const F return (*this); } -inline const LLVector3d& LLVector3d::setVec(const LLVector3d &vec) +inline const LLVector3d& LLVector3d::setVec(const LLVector3d& vec) { - mdV[0] = vec.mdV[0]; - mdV[1] = vec.mdV[1]; - mdV[2] = vec.mdV[2]; + mdV[VX] = vec.mdV[VX]; + mdV[VY] = vec.mdV[VY]; + mdV[VZ] = vec.mdV[VZ]; return (*this); } -inline const LLVector3d& LLVector3d::setVec(const F64 *vec) +inline const LLVector3d& LLVector3d::setVec(const F64* vec) { - mdV[0] = vec[0]; - mdV[1] = vec[1]; - mdV[2] = vec[2]; + mdV[VX] = vec[VX]; + mdV[VY] = vec[VY]; + mdV[VZ] = vec[VZ]; return (*this); } -inline F64 LLVector3d::normVec(void) +inline F64 LLVector3d::normVec() { - F64 mag = (F32) sqrt(mdV[0]*mdV[0] + mdV[1]*mdV[1] + mdV[2]*mdV[2]); + F64 mag = sqrt(mdV[VX]*mdV[VX] + mdV[VY]*mdV[VY] + mdV[VZ]*mdV[VZ]); F64 oomag; if (mag > FP_MAG_THRESHOLD) { oomag = 1.f/mag; - mdV[0] *= oomag; - mdV[1] *= oomag; - mdV[2] *= oomag; + mdV[VX] *= oomag; + mdV[VY] *= oomag; + mdV[VZ] *= oomag; } else { - mdV[0] = 0.f; - mdV[1] = 0.f; - mdV[2] = 0.f; + mdV[VX] = 0.f; + mdV[VY] = 0.f; + mdV[VZ] = 0.f; mag = 0; } return (mag); } -inline F64 LLVector3d::normalize(void) +inline F64 LLVector3d::normalize() { - F64 mag = (F32) sqrt(mdV[0]*mdV[0] + mdV[1]*mdV[1] + mdV[2]*mdV[2]); + F64 mag = sqrt(mdV[VX]*mdV[VX] + mdV[VY]*mdV[VY] + mdV[VZ]*mdV[VZ]); F64 oomag; if (mag > FP_MAG_THRESHOLD) { oomag = 1.f/mag; - mdV[0] *= oomag; - mdV[1] *= oomag; - mdV[2] *= oomag; + mdV[VX] *= oomag; + mdV[VY] *= oomag; + mdV[VZ] *= oomag; } else { - mdV[0] = 0.f; - mdV[1] = 0.f; - mdV[2] = 0.f; + mdV[VX] = 0.f; + mdV[VY] = 0.f; + mdV[VZ] = 0.f; mag = 0; } return (mag); @@ -323,24 +323,24 @@ inline F64 LLVector3d::normalize(void) // LLVector3d Magnitude and Normalization Functions -inline F64 LLVector3d::magVec(void) const +inline F64 LLVector3d::magVec() const { - return (F32) sqrt(mdV[0]*mdV[0] + mdV[1]*mdV[1] + mdV[2]*mdV[2]); + return sqrt(mdV[VX]*mdV[VX] + mdV[VY]*mdV[VY] + mdV[VZ]*mdV[VZ]); } -inline F64 LLVector3d::magVecSquared(void) const +inline F64 LLVector3d::magVecSquared() const { - return mdV[0]*mdV[0] + mdV[1]*mdV[1] + mdV[2]*mdV[2]; + return mdV[VX]*mdV[VX] + mdV[VY]*mdV[VY] + mdV[VZ]*mdV[VZ]; } -inline F64 LLVector3d::length(void) const +inline F64 LLVector3d::length() const { - return (F32) sqrt(mdV[0]*mdV[0] + mdV[1]*mdV[1] + mdV[2]*mdV[2]); + return sqrt(mdV[VX]*mdV[VX] + mdV[VY]*mdV[VY] + mdV[VZ]*mdV[VZ]); } -inline F64 LLVector3d::lengthSquared(void) const +inline F64 LLVector3d::lengthSquared() const { - return mdV[0]*mdV[0] + mdV[1]*mdV[1] + mdV[2]*mdV[2]; + return mdV[VX]*mdV[VX] + mdV[VY]*mdV[VY] + mdV[VZ]*mdV[VZ]; } inline LLVector3d operator+(const LLVector3d& a, const LLVector3d& b) @@ -357,109 +357,109 @@ inline LLVector3d operator-(const LLVector3d& a, const LLVector3d& b) inline F64 operator*(const LLVector3d& a, const LLVector3d& b) { - return (a.mdV[0]*b.mdV[0] + a.mdV[1]*b.mdV[1] + a.mdV[2]*b.mdV[2]); + return (a.mdV[VX]*b.mdV[VX] + a.mdV[VY]*b.mdV[VY] + a.mdV[VZ]*b.mdV[VZ]); } inline LLVector3d operator%(const LLVector3d& a, const LLVector3d& b) { - return LLVector3d( a.mdV[1]*b.mdV[2] - b.mdV[1]*a.mdV[2], a.mdV[2]*b.mdV[0] - b.mdV[2]*a.mdV[0], a.mdV[0]*b.mdV[1] - b.mdV[0]*a.mdV[1] ); + return LLVector3d( a.mdV[VY]*b.mdV[VZ] - b.mdV[VY]*a.mdV[VZ], a.mdV[VZ]*b.mdV[VX] - b.mdV[VZ]*a.mdV[VX], a.mdV[VX]*b.mdV[VY] - b.mdV[VX]*a.mdV[VY] ); } inline LLVector3d operator/(const LLVector3d& a, const F64 k) { F64 t = 1.f / k; - return LLVector3d( a.mdV[0] * t, a.mdV[1] * t, a.mdV[2] * t ); + return LLVector3d( a.mdV[VX] * t, a.mdV[VY] * t, a.mdV[VZ] * t ); } inline LLVector3d operator*(const LLVector3d& a, const F64 k) { - return LLVector3d( a.mdV[0] * k, a.mdV[1] * k, a.mdV[2] * k ); + return LLVector3d( a.mdV[VX] * k, a.mdV[VY] * k, a.mdV[VZ] * k ); } inline LLVector3d operator*(F64 k, const LLVector3d& a) { - return LLVector3d( a.mdV[0] * k, a.mdV[1] * k, a.mdV[2] * k ); + return LLVector3d( a.mdV[VX] * k, a.mdV[VY] * k, a.mdV[VZ] * k ); } inline bool operator==(const LLVector3d& a, const LLVector3d& b) { - return ( (a.mdV[0] == b.mdV[0]) - &&(a.mdV[1] == b.mdV[1]) - &&(a.mdV[2] == b.mdV[2])); + return ( (a.mdV[VX] == b.mdV[VX]) + &&(a.mdV[VY] == b.mdV[VY]) + &&(a.mdV[VZ] == b.mdV[VZ])); } inline bool operator!=(const LLVector3d& a, const LLVector3d& b) { - return ( (a.mdV[0] != b.mdV[0]) - ||(a.mdV[1] != b.mdV[1]) - ||(a.mdV[2] != b.mdV[2])); + return ( (a.mdV[VX] != b.mdV[VX]) + ||(a.mdV[VY] != b.mdV[VY]) + ||(a.mdV[VZ] != b.mdV[VZ])); } inline const LLVector3d& operator+=(LLVector3d& a, const LLVector3d& b) { - a.mdV[0] += b.mdV[0]; - a.mdV[1] += b.mdV[1]; - a.mdV[2] += b.mdV[2]; + a.mdV[VX] += b.mdV[VX]; + a.mdV[VY] += b.mdV[VY]; + a.mdV[VZ] += b.mdV[VZ]; return a; } inline const LLVector3d& operator-=(LLVector3d& a, const LLVector3d& b) { - a.mdV[0] -= b.mdV[0]; - a.mdV[1] -= b.mdV[1]; - a.mdV[2] -= b.mdV[2]; + a.mdV[VX] -= b.mdV[VX]; + a.mdV[VY] -= b.mdV[VY]; + a.mdV[VZ] -= b.mdV[VZ]; return a; } inline const LLVector3d& operator%=(LLVector3d& a, const LLVector3d& b) { - LLVector3d ret( a.mdV[1]*b.mdV[2] - b.mdV[1]*a.mdV[2], a.mdV[2]*b.mdV[0] - b.mdV[2]*a.mdV[0], a.mdV[0]*b.mdV[1] - b.mdV[0]*a.mdV[1]); + LLVector3d ret( a.mdV[VY]*b.mdV[VZ] - b.mdV[VY]*a.mdV[VZ], a.mdV[VZ]*b.mdV[VX] - b.mdV[VZ]*a.mdV[VX], a.mdV[VX]*b.mdV[VY] - b.mdV[VX]*a.mdV[VY]); a = ret; return a; } inline const LLVector3d& operator*=(LLVector3d& a, const F64 k) { - a.mdV[0] *= k; - a.mdV[1] *= k; - a.mdV[2] *= k; + a.mdV[VX] *= k; + a.mdV[VY] *= k; + a.mdV[VZ] *= k; return a; } inline const LLVector3d& operator/=(LLVector3d& a, const F64 k) { F64 t = 1.f / k; - a.mdV[0] *= t; - a.mdV[1] *= t; - a.mdV[2] *= t; + a.mdV[VX] *= t; + a.mdV[VY] *= t; + a.mdV[VZ] *= t; return a; } inline LLVector3d operator-(const LLVector3d& a) { - return LLVector3d( -a.mdV[0], -a.mdV[1], -a.mdV[2] ); + return LLVector3d( -a.mdV[VX], -a.mdV[VY], -a.mdV[VZ] ); } inline F64 dist_vec(const LLVector3d& a, const LLVector3d& b) { - F64 x = a.mdV[0] - b.mdV[0]; - F64 y = a.mdV[1] - b.mdV[1]; - F64 z = a.mdV[2] - b.mdV[2]; + F64 x = a.mdV[VX] - b.mdV[VX]; + F64 y = a.mdV[VY] - b.mdV[VY]; + F64 z = a.mdV[VZ] - b.mdV[VZ]; return (F32) sqrt( x*x + y*y + z*z ); } inline F64 dist_vec_squared(const LLVector3d& a, const LLVector3d& b) { - F64 x = a.mdV[0] - b.mdV[0]; - F64 y = a.mdV[1] - b.mdV[1]; - F64 z = a.mdV[2] - b.mdV[2]; + F64 x = a.mdV[VX] - b.mdV[VX]; + F64 y = a.mdV[VY] - b.mdV[VY]; + F64 z = a.mdV[VZ] - b.mdV[VZ]; return x*x + y*y + z*z; } inline F64 dist_vec_squared2D(const LLVector3d& a, const LLVector3d& b) { - F64 x = a.mdV[0] - b.mdV[0]; - F64 y = a.mdV[1] - b.mdV[1]; + F64 x = a.mdV[VX] - b.mdV[VX]; + F64 y = a.mdV[VY] - b.mdV[VY]; return x*x + y*y; } diff --git a/indra/llmath/v3math.cpp b/indra/llmath/v3math.cpp index 73ad2a4ed6..941a122528 100644 --- a/indra/llmath/v3math.cpp +++ b/indra/llmath/v3math.cpp @@ -58,13 +58,13 @@ bool LLVector3::clamp(F32 min, F32 max) { bool ret{ false }; - if (mV[0] < min) { mV[0] = min; ret = true; } - if (mV[1] < min) { mV[1] = min; ret = true; } - if (mV[2] < min) { mV[2] = min; ret = true; } + if (mV[VX] < min) { mV[VX] = min; ret = true; } + if (mV[VY] < min) { mV[VY] = min; ret = true; } + if (mV[VZ] < min) { mV[VZ] = min; ret = true; } - if (mV[0] > max) { mV[0] = max; ret = true; } - if (mV[1] > max) { mV[1] = max; ret = true; } - if (mV[2] > max) { mV[2] = max; ret = true; } + if (mV[VX] > max) { mV[VX] = max; ret = true; } + if (mV[VY] > max) { mV[VY] = max; ret = true; } + if (mV[VZ] > max) { mV[VZ] = max; ret = true; } return ret; } @@ -85,9 +85,9 @@ bool LLVector3::clampLength( F32 length_limit ) { length_limit = 0.f; } - mV[0] *= length_limit; - mV[1] *= length_limit; - mV[2] *= length_limit; + mV[VX] *= length_limit; + mV[VY] *= length_limit; + mV[VZ] *= length_limit; changed = true; } } @@ -116,35 +116,35 @@ bool LLVector3::clampLength( F32 length_limit ) { // yes it can be salvaged --> // bring the components down before we normalize - mV[0] /= max_abs_component; - mV[1] /= max_abs_component; - mV[2] /= max_abs_component; + mV[VX] /= max_abs_component; + mV[VY] /= max_abs_component; + mV[VZ] /= max_abs_component; normalize(); if (length_limit < 0.f) { length_limit = 0.f; } - mV[0] *= length_limit; - mV[1] *= length_limit; - mV[2] *= length_limit; + mV[VX] *= length_limit; + mV[VY] *= length_limit; + mV[VZ] *= length_limit; } } return changed; } -bool LLVector3::clamp(const LLVector3 &min_vec, const LLVector3 &max_vec) +bool LLVector3::clamp(const LLVector3& min_vec, const LLVector3& max_vec) { bool ret{ false }; - if (mV[0] < min_vec[0]) { mV[0] = min_vec[0]; ret = true; } - if (mV[1] < min_vec[1]) { mV[1] = min_vec[1]; ret = true; } - if (mV[2] < min_vec[2]) { mV[2] = min_vec[2]; ret = true; } + if (mV[VX] < min_vec[0]) { mV[VX] = min_vec[0]; ret = true; } + if (mV[VY] < min_vec[1]) { mV[VY] = min_vec[1]; ret = true; } + if (mV[VZ] < min_vec[2]) { mV[VZ] = min_vec[2]; ret = true; } - if (mV[0] > max_vec[0]) { mV[0] = max_vec[0]; ret = true; } - if (mV[1] > max_vec[1]) { mV[1] = max_vec[1]; ret = true; } - if (mV[2] > max_vec[2]) { mV[2] = max_vec[2]; ret = true; } + if (mV[VX] > max_vec[0]) { mV[VX] = max_vec[0]; ret = true; } + if (mV[VY] > max_vec[1]) { mV[VY] = max_vec[1]; ret = true; } + if (mV[VZ] > max_vec[2]) { mV[VZ] = max_vec[2]; ret = true; } return ret; } @@ -156,9 +156,9 @@ bool LLVector3::abs() { bool ret{ false }; - if (mV[0] < 0.f) { mV[0] = -mV[0]; ret = true; } - if (mV[1] < 0.f) { mV[1] = -mV[1]; ret = true; } - if (mV[2] < 0.f) { mV[2] = -mV[2]; ret = true; } + if (mV[VX] < 0.f) { mV[VX] = -mV[VX]; ret = true; } + if (mV[VY] < 0.f) { mV[VY] = -mV[VY]; ret = true; } + if (mV[VZ] < 0.f) { mV[VZ] = -mV[VZ]; ret = true; } return ret; } @@ -194,13 +194,13 @@ void LLVector3::snap(S32 sig_digits) mV[VZ] = snap_to_sig_figs(mV[VZ], sig_digits); } -const LLVector3& LLVector3::rotVec(const LLMatrix3 &mat) +const LLVector3& LLVector3::rotVec(const LLMatrix3& mat) { *this = *this * mat; return *this; } -const LLVector3& LLVector3::rotVec(const LLQuaternion &q) +const LLVector3& LLVector3::rotVec(const LLQuaternion& q) { *this = *this * q; return *this; @@ -228,7 +228,7 @@ const LLVector3& LLVector3::transVec(const LLMatrix4& mat) } -const LLVector3& LLVector3::rotVec(F32 angle, const LLVector3 &vec) +const LLVector3& LLVector3::rotVec(F32 angle, const LLVector3& vec) { if ( !vec.isExactlyZero() && angle ) { @@ -263,35 +263,35 @@ LLVector3 LLVector3::scaledVec(const LLVector3& vec) const return ret; } -const LLVector3& LLVector3::set(const LLVector3d &vec) +const LLVector3& LLVector3::set(const LLVector3d& vec) { - mV[0] = (F32)vec.mdV[0]; - mV[1] = (F32)vec.mdV[1]; - mV[2] = (F32)vec.mdV[2]; + mV[VX] = (F32)vec.mdV[VX]; + mV[VY] = (F32)vec.mdV[VY]; + mV[VZ] = (F32)vec.mdV[VZ]; return (*this); } -const LLVector3& LLVector3::set(const LLVector4 &vec) +const LLVector3& LLVector3::set(const LLVector4& vec) { - mV[0] = vec.mV[0]; - mV[1] = vec.mV[1]; - mV[2] = vec.mV[2]; + mV[VX] = vec.mV[VX]; + mV[VY] = vec.mV[VY]; + mV[VZ] = vec.mV[VZ]; return (*this); } -const LLVector3& LLVector3::setVec(const LLVector3d &vec) +const LLVector3& LLVector3::setVec(const LLVector3d& vec) { - mV[0] = (F32)vec.mdV[0]; - mV[1] = (F32)vec.mdV[1]; - mV[2] = (F32)vec.mdV[2]; + mV[VX] = (F32)vec.mdV[0]; + mV[VY] = (F32)vec.mdV[1]; + mV[VZ] = (F32)vec.mdV[2]; return (*this); } -const LLVector3& LLVector3::setVec(const LLVector4 &vec) +const LLVector3& LLVector3::setVec(const LLVector4& vec) { - mV[0] = vec.mV[0]; - mV[1] = vec.mV[1]; - mV[2] = vec.mV[2]; + mV[VX] = vec.mV[VX]; + mV[VY] = vec.mV[VY]; + mV[VZ] = vec.mV[VZ]; return (*this); } @@ -302,14 +302,14 @@ LLVector3::LLVector3(const LLVector2 &vec) mV[VZ] = 0; } -LLVector3::LLVector3(const LLVector3d &vec) +LLVector3::LLVector3(const LLVector3d& vec) { mV[VX] = (F32)vec.mdV[VX]; mV[VY] = (F32)vec.mdV[VY]; mV[VZ] = (F32)vec.mdV[VZ]; } -LLVector3::LLVector3(const LLVector4 &vec) +LLVector3::LLVector3(const LLVector4& vec) { mV[VX] = (F32)vec.mV[VX]; mV[VY] = (F32)vec.mV[VY]; @@ -330,20 +330,20 @@ LLVector3::LLVector3(const LLSD& sd) LLSD LLVector3::getValue() const { LLSD ret; - ret[0] = mV[0]; - ret[1] = mV[1]; - ret[2] = mV[2]; + ret[0] = mV[VX]; + ret[1] = mV[VY]; + ret[2] = mV[VZ]; return ret; } void LLVector3::setValue(const LLSD& sd) { - mV[0] = (F32) sd[0].asReal(); - mV[1] = (F32) sd[1].asReal(); - mV[2] = (F32) sd[2].asReal(); + mV[VX] = (F32) sd[0].asReal(); + mV[VY] = (F32) sd[1].asReal(); + mV[VZ] = (F32) sd[2].asReal(); } -const LLVector3& operator*=(LLVector3 &a, const LLQuaternion &rot) +const LLVector3& operator*=(LLVector3& a, const LLQuaternion& rot) { const F32 rw = - rot.mQ[VX] * a.mV[VX] - rot.mQ[VY] * a.mV[VY] - rot.mQ[VZ] * a.mV[VZ]; const F32 rx = rot.mQ[VW] * a.mV[VX] + rot.mQ[VY] * a.mV[VZ] - rot.mQ[VZ] * a.mV[VY]; diff --git a/indra/llmath/v3math.h b/indra/llmath/v3math.h index 4fc7585a46..53491533c2 100644 --- a/indra/llmath/v3math.h +++ b/indra/llmath/v3math.h @@ -41,7 +41,7 @@ class LLQuaternion; // LLvector3 = |x y z w| -static const U32 LENGTHOFVECTOR3 = 3; +static constexpr U32 LENGTHOFVECTOR3 = 3; class LLVector3 { @@ -169,11 +169,11 @@ LLVector3 lerp(const LLVector3 &a, const LLVector3 &b, F32 u); // Returns a vect LLVector3 point_to_box_offset(LLVector3& pos, const LLVector3* box); // Displacement from query point to nearest point on bounding box. bool box_valid_and_non_zero(const LLVector3* box); -inline LLVector3::LLVector3(void) +inline LLVector3::LLVector3() { - mV[0] = 0.f; - mV[1] = 0.f; - mV[2] = 0.f; + mV[VX] = 0.f; + mV[VY] = 0.f; + mV[VZ] = 0.f; } inline LLVector3::LLVector3(const F32 x, const F32 y, const F32 z) @@ -210,32 +210,32 @@ inline bool LLVector3::isFinite() const // Clear and Assignment Functions -inline void LLVector3::clear(void) +inline void LLVector3::clear() { - mV[0] = 0.f; - mV[1] = 0.f; - mV[2] = 0.f; + mV[VX] = 0.f; + mV[VY] = 0.f; + mV[VZ] = 0.f; } -inline void LLVector3::setZero(void) +inline void LLVector3::setZero() { - mV[0] = 0.f; - mV[1] = 0.f; - mV[2] = 0.f; + mV[VX] = 0.f; + mV[VY] = 0.f; + mV[VZ] = 0.f; } -inline void LLVector3::clearVec(void) +inline void LLVector3::clearVec() { - mV[0] = 0.f; - mV[1] = 0.f; - mV[2] = 0.f; + mV[VX] = 0.f; + mV[VY] = 0.f; + mV[VZ] = 0.f; } -inline void LLVector3::zeroVec(void) +inline void LLVector3::zeroVec() { - mV[0] = 0.f; - mV[1] = 0.f; - mV[2] = 0.f; + mV[VX] = 0.f; + mV[VY] = 0.f; + mV[VZ] = 0.f; } inline void LLVector3::set(F32 x, F32 y, F32 z) @@ -245,18 +245,18 @@ inline void LLVector3::set(F32 x, F32 y, F32 z) mV[VZ] = z; } -inline void LLVector3::set(const LLVector3 &vec) +inline void LLVector3::set(const LLVector3& vec) { - mV[0] = vec.mV[0]; - mV[1] = vec.mV[1]; - mV[2] = vec.mV[2]; + mV[VX] = vec.mV[VX]; + mV[VY] = vec.mV[VY]; + mV[VZ] = vec.mV[VZ]; } -inline void LLVector3::set(const F32 *vec) +inline void LLVector3::set(const F32* vec) { - mV[0] = vec[0]; - mV[1] = vec[1]; - mV[2] = vec[2]; + mV[VX] = vec[0]; + mV[VY] = vec[1]; + mV[VZ] = vec[2]; } // deprecated @@ -268,61 +268,61 @@ inline void LLVector3::setVec(F32 x, F32 y, F32 z) } // deprecated -inline void LLVector3::setVec(const LLVector3 &vec) +inline void LLVector3::setVec(const LLVector3& vec) { - mV[0] = vec.mV[0]; - mV[1] = vec.mV[1]; - mV[2] = vec.mV[2]; + mV[VX] = vec.mV[VX]; + mV[VY] = vec.mV[VY]; + mV[VZ] = vec.mV[VZ]; } // deprecated -inline void LLVector3::setVec(const F32 *vec) +inline void LLVector3::setVec(const F32* vec) { - mV[0] = vec[0]; - mV[1] = vec[1]; - mV[2] = vec[2]; + mV[VX] = vec[0]; + mV[VY] = vec[1]; + mV[VZ] = vec[2]; } -inline F32 LLVector3::normalize(void) +inline F32 LLVector3::normalize() { - F32 mag = (F32) sqrt(mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2]); + F32 mag = (F32) sqrt(mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]); F32 oomag; if (mag > FP_MAG_THRESHOLD) { oomag = 1.f/mag; - mV[0] *= oomag; - mV[1] *= oomag; - mV[2] *= oomag; + mV[VX] *= oomag; + mV[VY] *= oomag; + mV[VZ] *= oomag; } else { - mV[0] = 0.f; - mV[1] = 0.f; - mV[2] = 0.f; + mV[VX] = 0.f; + mV[VY] = 0.f; + mV[VZ] = 0.f; mag = 0; } return (mag); } // deprecated -inline F32 LLVector3::normVec(void) +inline F32 LLVector3::normVec() { - F32 mag = (F32) sqrt(mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2]); + F32 mag = sqrt(mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]); F32 oomag; if (mag > FP_MAG_THRESHOLD) { oomag = 1.f/mag; - mV[0] *= oomag; - mV[1] *= oomag; - mV[2] *= oomag; + mV[VX] *= oomag; + mV[VY] *= oomag; + mV[VZ] *= oomag; } else { - mV[0] = 0.f; - mV[1] = 0.f; - mV[2] = 0.f; + mV[VX] = 0.f; + mV[VY] = 0.f; + mV[VZ] = 0.f; mag = 0; } return (mag); @@ -330,178 +330,178 @@ inline F32 LLVector3::normVec(void) // LLVector3 Magnitude and Normalization Functions -inline F32 LLVector3::length(void) const +inline F32 LLVector3::length() const { - return (F32) sqrt(mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2]); + return sqrt(mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]); } -inline F32 LLVector3::lengthSquared(void) const +inline F32 LLVector3::lengthSquared() const { - return mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2]; + return mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]; } -inline F32 LLVector3::magVec(void) const +inline F32 LLVector3::magVec() const { - return (F32) sqrt(mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2]); + return sqrt(mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]); } -inline F32 LLVector3::magVecSquared(void) const +inline F32 LLVector3::magVecSquared() const { - return mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2]; + return mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]; } inline bool LLVector3::inRange( F32 min, F32 max ) const { - return mV[0] >= min && mV[0] <= max && - mV[1] >= min && mV[1] <= max && - mV[2] >= min && mV[2] <= max; + return mV[VX] >= min && mV[VX] <= max && + mV[VY] >= min && mV[VY] <= max && + mV[VZ] >= min && mV[VZ] <= max; } -inline LLVector3 operator+(const LLVector3 &a, const LLVector3 &b) +inline LLVector3 operator+(const LLVector3& a, const LLVector3& b) { LLVector3 c(a); return c += b; } -inline LLVector3 operator-(const LLVector3 &a, const LLVector3 &b) +inline LLVector3 operator-(const LLVector3& a, const LLVector3& b) { LLVector3 c(a); return c -= b; } -inline F32 operator*(const LLVector3 &a, const LLVector3 &b) +inline F32 operator*(const LLVector3& a, const LLVector3& b) { - return (a.mV[0]*b.mV[0] + a.mV[1]*b.mV[1] + a.mV[2]*b.mV[2]); + return (a.mV[VX]*b.mV[VX] + a.mV[VY]*b.mV[VY] + a.mV[VZ]*b.mV[VZ]); } -inline LLVector3 operator%(const LLVector3 &a, const LLVector3 &b) +inline LLVector3 operator%(const LLVector3& a, const LLVector3& b) { - return LLVector3( a.mV[1]*b.mV[2] - b.mV[1]*a.mV[2], a.mV[2]*b.mV[0] - b.mV[2]*a.mV[0], a.mV[0]*b.mV[1] - b.mV[0]*a.mV[1] ); + return LLVector3( a.mV[VY]*b.mV[VZ] - b.mV[VY]*a.mV[VZ], a.mV[VZ]*b.mV[VX] - b.mV[VZ]*a.mV[VX], a.mV[VX]*b.mV[VY] - b.mV[VX]*a.mV[VY] ); } -inline LLVector3 operator/(const LLVector3 &a, F32 k) +inline LLVector3 operator/(const LLVector3& a, F32 k) { F32 t = 1.f / k; - return LLVector3( a.mV[0] * t, a.mV[1] * t, a.mV[2] * t ); + return LLVector3( a.mV[VX] * t, a.mV[VY] * t, a.mV[VZ] * t ); } -inline LLVector3 operator*(const LLVector3 &a, F32 k) +inline LLVector3 operator*(const LLVector3& a, F32 k) { - return LLVector3( a.mV[0] * k, a.mV[1] * k, a.mV[2] * k ); + return LLVector3( a.mV[VX] * k, a.mV[VY] * k, a.mV[VZ] * k ); } -inline LLVector3 operator*(F32 k, const LLVector3 &a) +inline LLVector3 operator*(F32 k, const LLVector3& a) { - return LLVector3( a.mV[0] * k, a.mV[1] * k, a.mV[2] * k ); + return LLVector3( a.mV[VX] * k, a.mV[VY] * k, a.mV[VZ] * k ); } -inline bool operator==(const LLVector3 &a, const LLVector3 &b) +inline bool operator==(const LLVector3& a, const LLVector3& b) { - return ( (a.mV[0] == b.mV[0]) - &&(a.mV[1] == b.mV[1]) - &&(a.mV[2] == b.mV[2])); + return ( (a.mV[VX] == b.mV[VX]) + &&(a.mV[VY] == b.mV[VY]) + &&(a.mV[VZ] == b.mV[VZ])); } -inline bool operator!=(const LLVector3 &a, const LLVector3 &b) +inline bool operator!=(const LLVector3& a, const LLVector3& b) { - return ( (a.mV[0] != b.mV[0]) - ||(a.mV[1] != b.mV[1]) - ||(a.mV[2] != b.mV[2])); + return ( (a.mV[VX] != b.mV[VX]) + ||(a.mV[VY] != b.mV[VY]) + ||(a.mV[VZ] != b.mV[VZ])); } -inline bool operator<(const LLVector3 &a, const LLVector3 &b) +inline bool operator<(const LLVector3& a, const LLVector3& b) { - return (a.mV[0] < b.mV[0] - || (a.mV[0] == b.mV[0] - && (a.mV[1] < b.mV[1] - || ((a.mV[1] == b.mV[1]) - && a.mV[2] < b.mV[2])))); + return (a.mV[VX] < b.mV[VX] + || (a.mV[VX] == b.mV[VX] + && (a.mV[VY] < b.mV[VY] + || ((a.mV[VY] == b.mV[VY]) + && a.mV[VZ] < b.mV[VZ])))); } -inline const LLVector3& operator+=(LLVector3 &a, const LLVector3 &b) +inline const LLVector3& operator+=(LLVector3& a, const LLVector3& b) { - a.mV[0] += b.mV[0]; - a.mV[1] += b.mV[1]; - a.mV[2] += b.mV[2]; + a.mV[VX] += b.mV[VX]; + a.mV[VY] += b.mV[VY]; + a.mV[VZ] += b.mV[VZ]; return a; } -inline const LLVector3& operator-=(LLVector3 &a, const LLVector3 &b) +inline const LLVector3& operator-=(LLVector3& a, const LLVector3& b) { - a.mV[0] -= b.mV[0]; - a.mV[1] -= b.mV[1]; - a.mV[2] -= b.mV[2]; + a.mV[VX] -= b.mV[VX]; + a.mV[VY] -= b.mV[VY]; + a.mV[VZ] -= b.mV[VZ]; return a; } -inline const LLVector3& operator%=(LLVector3 &a, const LLVector3 &b) +inline const LLVector3& operator%=(LLVector3& a, const LLVector3& b) { - LLVector3 ret( a.mV[1]*b.mV[2] - b.mV[1]*a.mV[2], a.mV[2]*b.mV[0] - b.mV[2]*a.mV[0], a.mV[0]*b.mV[1] - b.mV[0]*a.mV[1]); + LLVector3 ret( a.mV[VY]*b.mV[VZ] - b.mV[VY]*a.mV[VZ], a.mV[VZ]*b.mV[VX] - b.mV[VZ]*a.mV[VX], a.mV[VX]*b.mV[VY] - b.mV[VX]*a.mV[VY]); a = ret; return a; } -inline const LLVector3& operator*=(LLVector3 &a, F32 k) +inline const LLVector3& operator*=(LLVector3& a, F32 k) { - a.mV[0] *= k; - a.mV[1] *= k; - a.mV[2] *= k; + a.mV[VX] *= k; + a.mV[VY] *= k; + a.mV[VZ] *= k; return a; } -inline const LLVector3& operator*=(LLVector3 &a, const LLVector3 &b) +inline const LLVector3& operator*=(LLVector3& a, const LLVector3& b) { - a.mV[0] *= b.mV[0]; - a.mV[1] *= b.mV[1]; - a.mV[2] *= b.mV[2]; + a.mV[VX] *= b.mV[VX]; + a.mV[VY] *= b.mV[VY]; + a.mV[VZ] *= b.mV[VZ]; return a; } -inline const LLVector3& operator/=(LLVector3 &a, F32 k) +inline const LLVector3& operator/=(LLVector3& a, F32 k) { - a.mV[0] /= k; - a.mV[1] /= k; - a.mV[2] /= k; + a.mV[VX] /= k; + a.mV[VY] /= k; + a.mV[VZ] /= k; return a; } inline const LLVector3& operator/=(LLVector3& a, const LLVector3& b) { - a.mV[0] /= b.mV[0]; - a.mV[1] /= b.mV[1]; - a.mV[2] /= b.mV[2]; + a.mV[VX] /= b.mV[VX]; + a.mV[VY] /= b.mV[VY]; + a.mV[VZ] /= b.mV[VZ]; return a; } -inline LLVector3 operator-(const LLVector3 &a) +inline LLVector3 operator-(const LLVector3& a) { - return LLVector3( -a.mV[0], -a.mV[1], -a.mV[2] ); + return LLVector3( -a.mV[VX], -a.mV[VY], -a.mV[VZ] ); } -inline F32 dist_vec(const LLVector3 &a, const LLVector3 &b) +inline F32 dist_vec(const LLVector3& a, const LLVector3& b) { - F32 x = a.mV[0] - b.mV[0]; - F32 y = a.mV[1] - b.mV[1]; - F32 z = a.mV[2] - b.mV[2]; - return (F32) sqrt( x*x + y*y + z*z ); + F32 x = a.mV[VX] - b.mV[VX]; + F32 y = a.mV[VY] - b.mV[VY]; + F32 z = a.mV[VZ] - b.mV[VZ]; + return sqrt( x*x + y*y + z*z ); } -inline F32 dist_vec_squared(const LLVector3 &a, const LLVector3 &b) +inline F32 dist_vec_squared(const LLVector3& a, const LLVector3& b) { - F32 x = a.mV[0] - b.mV[0]; - F32 y = a.mV[1] - b.mV[1]; - F32 z = a.mV[2] - b.mV[2]; + F32 x = a.mV[VX] - b.mV[VX]; + F32 y = a.mV[VY] - b.mV[VY]; + F32 z = a.mV[VZ] - b.mV[VZ]; return x*x + y*y + z*z; } -inline F32 dist_vec_squared2D(const LLVector3 &a, const LLVector3 &b) +inline F32 dist_vec_squared2D(const LLVector3& a, const LLVector3& b) { - F32 x = a.mV[0] - b.mV[0]; - F32 y = a.mV[1] - b.mV[1]; + F32 x = a.mV[VX] - b.mV[VX]; + F32 y = a.mV[VY] - b.mV[VY]; return x*x + y*y; } -inline LLVector3 projected_vec(const LLVector3 &a, const LLVector3 &b) +inline LLVector3 projected_vec(const LLVector3& a, const LLVector3& b) { F32 bb = b * b; if (bb > FP_MAG_THRESHOLD * FP_MAG_THRESHOLD) @@ -526,18 +526,18 @@ inline LLVector3 inverse_projected_vec(const LLVector3& a, const LLVector3& b) return normalized_a * (b_length / dot_product); } -inline LLVector3 parallel_component(const LLVector3 &a, const LLVector3 &b) +inline LLVector3 parallel_component(const LLVector3& a, const LLVector3& b) { return projected_vec(a, b); } -inline LLVector3 orthogonal_component(const LLVector3 &a, const LLVector3 &b) +inline LLVector3 orthogonal_component(const LLVector3& a, const LLVector3& b) { return a - projected_vec(a, b); } -inline LLVector3 lerp(const LLVector3 &a, const LLVector3 &b, F32 u) +inline LLVector3 lerp(const LLVector3& a, const LLVector3& b, F32 u) { return LLVector3( a.mV[VX] + (b.mV[VX] - a.mV[VX]) * u, @@ -596,7 +596,7 @@ inline F32 angle_between(const LLVector3& a, const LLVector3& b) return atan2f(sqrtf(c * c), ab); // return the angle } -inline bool are_parallel(const LLVector3 &a, const LLVector3 &b, F32 epsilon) +inline bool are_parallel(const LLVector3& a, const LLVector3& b, F32 epsilon) { LLVector3 an = a; LLVector3 bn = b; diff --git a/indra/llmath/v4math.cpp b/indra/llmath/v4math.cpp index 0aa6eb09c3..e87bfc0013 100644 --- a/indra/llmath/v4math.cpp +++ b/indra/llmath/v4math.cpp @@ -36,13 +36,13 @@ // LLVector4 // Axis-Angle rotations -const LLVector4& LLVector4::rotVec(const LLMatrix4 &mat) +const LLVector4& LLVector4::rotVec(const LLMatrix4& mat) { *this = *this * mat; return *this; } -const LLVector4& LLVector4::rotVec(const LLQuaternion &q) +const LLVector4& LLVector4::rotVec(const LLQuaternion& q) { *this = *this * q; return *this; @@ -64,16 +64,16 @@ bool LLVector4::abs() { bool ret{ false }; - if (mV[0] < 0.f) { mV[0] = -mV[0]; ret = true; } - if (mV[1] < 0.f) { mV[1] = -mV[1]; ret = true; } - if (mV[2] < 0.f) { mV[2] = -mV[2]; ret = true; } - if (mV[3] < 0.f) { mV[3] = -mV[3]; ret = true; } + if (mV[VX] < 0.f) { mV[VX] = -mV[VX]; ret = true; } + if (mV[VY] < 0.f) { mV[VY] = -mV[VY]; ret = true; } + if (mV[VZ] < 0.f) { mV[VZ] = -mV[VZ]; ret = true; } + if (mV[VW] < 0.f) { mV[VW] = -mV[VW]; ret = true; } return ret; } -std::ostream& operator<<(std::ostream& s, const LLVector4 &a) +std::ostream& operator<<(std::ostream& s, const LLVector4& a) { s << "{ " << a.mV[VX] << ", " << a.mV[VY] << ", " << a.mV[VZ] << ", " << a.mV[VW] << " }"; return s; @@ -108,12 +108,12 @@ bool are_parallel(const LLVector4 &a, const LLVector4 &b, F32 epsilon) } -LLVector3 vec4to3(const LLVector4 &vec) +LLVector3 vec4to3(const LLVector4& vec) { return LLVector3( vec.mV[VX], vec.mV[VY], vec.mV[VZ] ); } -LLVector4 vec3to4(const LLVector3 &vec) +LLVector4 vec3to4(const LLVector3& vec) { return LLVector4(vec.mV[VX], vec.mV[VY], vec.mV[VZ]); } diff --git a/indra/llmath/v4math.h b/indra/llmath/v4math.h index a5b6f506d7..e2092d1277 100644 --- a/indra/llmath/v4math.h +++ b/indra/llmath/v4math.h @@ -38,7 +38,7 @@ class LLQuaternion; // LLVector4 = |x y z w| -static const U32 LENGTHOFVECTOR4 = 4; +static constexpr U32 LENGTHOFVECTOR4 = 4; class LLVector4 { @@ -58,19 +58,19 @@ class LLVector4 LLSD getValue() const { LLSD ret; - ret[0] = mV[0]; - ret[1] = mV[1]; - ret[2] = mV[2]; - ret[3] = mV[3]; + ret[0] = mV[VX]; + ret[1] = mV[VY]; + ret[2] = mV[VZ]; + ret[3] = mV[VW]; return ret; } void setValue(const LLSD& sd) { - mV[0] = (F32)sd[0].asReal(); - mV[1] = (F32)sd[1].asReal(); - mV[2] = (F32)sd[2].asReal(); - mV[3] = (F32)sd[3].asReal(); + mV[VX] = (F32)sd[0].asReal(); + mV[VY] = (F32)sd[1].asReal(); + mV[VZ] = (F32)sd[2].asReal(); + mV[VW] = (F32)sd[3].asReal(); } @@ -231,7 +231,7 @@ inline bool LLVector4::isFinite() const // Clear and Assignment Functions -inline void LLVector4::clear(void) +inline void LLVector4::clear() { mV[VX] = 0.f; mV[VY] = 0.f; @@ -240,7 +240,7 @@ inline void LLVector4::clear(void) } // deprecated -inline void LLVector4::clearVec(void) +inline void LLVector4::clearVec() { mV[VX] = 0.f; mV[VY] = 0.f; @@ -249,7 +249,7 @@ inline void LLVector4::clearVec(void) } // deprecated -inline void LLVector4::zeroVec(void) +inline void LLVector4::zeroVec() { mV[VX] = 0.f; mV[VY] = 0.f; @@ -273,7 +273,7 @@ inline void LLVector4::set(F32 x, F32 y, F32 z, F32 w) mV[VW] = w; } -inline void LLVector4::set(const LLVector4 &vec) +inline void LLVector4::set(const LLVector4& vec) { mV[VX] = vec.mV[VX]; mV[VY] = vec.mV[VY]; @@ -281,7 +281,7 @@ inline void LLVector4::set(const LLVector4 &vec) mV[VW] = vec.mV[VW]; } -inline void LLVector4::set(const LLVector3 &vec, F32 w) +inline void LLVector4::set(const LLVector3& vec, F32 w) { mV[VX] = vec.mV[VX]; mV[VY] = vec.mV[VY]; @@ -289,7 +289,7 @@ inline void LLVector4::set(const LLVector3 &vec, F32 w) mV[VW] = w; } -inline void LLVector4::set(const F32 *vec) +inline void LLVector4::set(const F32* vec) { mV[VX] = vec[VX]; mV[VY] = vec[VY]; @@ -317,7 +317,7 @@ inline void LLVector4::setVec(F32 x, F32 y, F32 z, F32 w) } // deprecated -inline void LLVector4::setVec(const LLVector4 &vec) +inline void LLVector4::setVec(const LLVector4& vec) { mV[VX] = vec.mV[VX]; mV[VY] = vec.mV[VY]; @@ -326,7 +326,7 @@ inline void LLVector4::setVec(const LLVector4 &vec) } // deprecated -inline void LLVector4::setVec(const LLVector3 &vec, F32 w) +inline void LLVector4::setVec(const LLVector3& vec, F32 w) { mV[VX] = vec.mV[VX]; mV[VY] = vec.mV[VY]; @@ -335,7 +335,7 @@ inline void LLVector4::setVec(const LLVector3 &vec, F32 w) } // deprecated -inline void LLVector4::setVec(const F32 *vec) +inline void LLVector4::setVec(const F32* vec) { mV[VX] = vec[VX]; mV[VY] = vec[VY]; @@ -345,75 +345,75 @@ inline void LLVector4::setVec(const F32 *vec) // LLVector4 Magnitude and Normalization Functions -inline F32 LLVector4::length(void) const +inline F32 LLVector4::length() const { - return (F32) sqrt(mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]); + return sqrt(mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]); } -inline F32 LLVector4::lengthSquared(void) const +inline F32 LLVector4::lengthSquared() const { return mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]; } -inline F32 LLVector4::magVec(void) const +inline F32 LLVector4::magVec() const { - return (F32) sqrt(mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]); + return sqrt(mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]); } -inline F32 LLVector4::magVecSquared(void) const +inline F32 LLVector4::magVecSquared() const { return mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]; } // LLVector4 Operators -inline LLVector4 operator+(const LLVector4 &a, const LLVector4 &b) +inline LLVector4 operator+(const LLVector4& a, const LLVector4& b) { LLVector4 c(a); return c += b; } -inline LLVector4 operator-(const LLVector4 &a, const LLVector4 &b) +inline LLVector4 operator-(const LLVector4& a, const LLVector4& b) { LLVector4 c(a); return c -= b; } -inline F32 operator*(const LLVector4 &a, const LLVector4 &b) +inline F32 operator*(const LLVector4& a, const LLVector4& b) { return (a.mV[VX]*b.mV[VX] + a.mV[VY]*b.mV[VY] + a.mV[VZ]*b.mV[VZ]); } -inline LLVector4 operator%(const LLVector4 &a, const LLVector4 &b) +inline LLVector4 operator%(const LLVector4& a, const LLVector4& b) { return LLVector4(a.mV[VY]*b.mV[VZ] - b.mV[VY]*a.mV[VZ], a.mV[VZ]*b.mV[VX] - b.mV[VZ]*a.mV[VX], a.mV[VX]*b.mV[VY] - b.mV[VX]*a.mV[VY]); } -inline LLVector4 operator/(const LLVector4 &a, F32 k) +inline LLVector4 operator/(const LLVector4& a, F32 k) { F32 t = 1.f / k; return LLVector4( a.mV[VX] * t, a.mV[VY] * t, a.mV[VZ] * t ); } -inline LLVector4 operator*(const LLVector4 &a, F32 k) +inline LLVector4 operator*(const LLVector4& a, F32 k) { return LLVector4( a.mV[VX] * k, a.mV[VY] * k, a.mV[VZ] * k ); } -inline LLVector4 operator*(F32 k, const LLVector4 &a) +inline LLVector4 operator*(F32 k, const LLVector4& a) { return LLVector4( a.mV[VX] * k, a.mV[VY] * k, a.mV[VZ] * k ); } -inline bool operator==(const LLVector4 &a, const LLVector4 &b) +inline bool operator==(const LLVector4& a, const LLVector4& b) { return ( (a.mV[VX] == b.mV[VX]) &&(a.mV[VY] == b.mV[VY]) &&(a.mV[VZ] == b.mV[VZ])); } -inline bool operator!=(const LLVector4 &a, const LLVector4 &b) +inline bool operator!=(const LLVector4& a, const LLVector4& b) { return ( (a.mV[VX] != b.mV[VX]) ||(a.mV[VY] != b.mV[VY]) @@ -421,7 +421,7 @@ inline bool operator!=(const LLVector4 &a, const LLVector4 &b) ||(a.mV[VW] != b.mV[VW]) ); } -inline const LLVector4& operator+=(LLVector4 &a, const LLVector4 &b) +inline const LLVector4& operator+=(LLVector4& a, const LLVector4& b) { a.mV[VX] += b.mV[VX]; a.mV[VY] += b.mV[VY]; @@ -429,7 +429,7 @@ inline const LLVector4& operator+=(LLVector4 &a, const LLVector4 &b) return a; } -inline const LLVector4& operator-=(LLVector4 &a, const LLVector4 &b) +inline const LLVector4& operator-=(LLVector4& a, const LLVector4& b) { a.mV[VX] -= b.mV[VX]; a.mV[VY] -= b.mV[VY]; @@ -437,14 +437,14 @@ inline const LLVector4& operator-=(LLVector4 &a, const LLVector4 &b) return a; } -inline const LLVector4& operator%=(LLVector4 &a, const LLVector4 &b) +inline const LLVector4& operator%=(LLVector4& a, const LLVector4& b) { LLVector4 ret(a.mV[VY]*b.mV[VZ] - b.mV[VY]*a.mV[VZ], a.mV[VZ]*b.mV[VX] - b.mV[VZ]*a.mV[VX], a.mV[VX]*b.mV[VY] - b.mV[VX]*a.mV[VY]); a = ret; return a; } -inline const LLVector4& operator*=(LLVector4 &a, F32 k) +inline const LLVector4& operator*=(LLVector4& a, F32 k) { a.mV[VX] *= k; a.mV[VY] *= k; @@ -452,7 +452,7 @@ inline const LLVector4& operator*=(LLVector4 &a, F32 k) return a; } -inline const LLVector4& operator/=(LLVector4 &a, F32 k) +inline const LLVector4& operator/=(LLVector4& a, F32 k) { F32 t = 1.f / k; a.mV[VX] *= t; @@ -461,24 +461,24 @@ inline const LLVector4& operator/=(LLVector4 &a, F32 k) return a; } -inline LLVector4 operator-(const LLVector4 &a) +inline LLVector4 operator-(const LLVector4& a) { return LLVector4( -a.mV[VX], -a.mV[VY], -a.mV[VZ] ); } -inline F32 dist_vec(const LLVector4 &a, const LLVector4 &b) +inline F32 dist_vec(const LLVector4& a, const LLVector4& b) { LLVector4 vec = a - b; return (vec.length()); } -inline F32 dist_vec_squared(const LLVector4 &a, const LLVector4 &b) +inline F32 dist_vec_squared(const LLVector4& a, const LLVector4& b) { LLVector4 vec = a - b; return (vec.lengthSquared()); } -inline LLVector4 lerp(const LLVector4 &a, const LLVector4 &b, F32 u) +inline LLVector4 lerp(const LLVector4& a, const LLVector4& b, F32 u) { return LLVector4( a.mV[VX] + (b.mV[VX] - a.mV[VX]) * u, @@ -487,9 +487,9 @@ inline LLVector4 lerp(const LLVector4 &a, const LLVector4 &b, F32 u) a.mV[VW] + (b.mV[VW] - a.mV[VW]) * u); } -inline F32 LLVector4::normalize(void) +inline F32 LLVector4::normalize() { - F32 mag = (F32) sqrt(mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]); + F32 mag = sqrt(mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]); F32 oomag; if (mag > FP_MAG_THRESHOLD) @@ -501,18 +501,18 @@ inline F32 LLVector4::normalize(void) } else { - mV[0] = 0.f; - mV[1] = 0.f; - mV[2] = 0.f; - mag = 0; + mV[VX] = 0.f; + mV[VY] = 0.f; + mV[VZ] = 0.f; + mag = 0.f; } return (mag); } // deprecated -inline F32 LLVector4::normVec(void) +inline F32 LLVector4::normVec() { - F32 mag = (F32) sqrt(mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]); + F32 mag = sqrt(mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]); F32 oomag; if (mag > FP_MAG_THRESHOLD) @@ -524,22 +524,23 @@ inline F32 LLVector4::normVec(void) } else { - mV[0] = 0.f; - mV[1] = 0.f; - mV[2] = 0.f; - mag = 0; + mV[VX] = 0.f; + mV[VY] = 0.f; + mV[VZ] = 0.f; + mag = 0.f; } return (mag); } // Because apparently some parts of the viewer use this for color info. -inline const LLVector4 srgbVector4(const LLVector4 &a) { +inline const LLVector4 srgbVector4(const LLVector4& a) +{ LLVector4 srgbColor; - srgbColor.mV[0] = linearTosRGB(a.mV[0]); - srgbColor.mV[1] = linearTosRGB(a.mV[1]); - srgbColor.mV[2] = linearTosRGB(a.mV[2]); - srgbColor.mV[3] = a.mV[3]; + srgbColor.mV[VX] = linearTosRGB(a.mV[VX]); + srgbColor.mV[VY] = linearTosRGB(a.mV[VY]); + srgbColor.mV[VZ] = linearTosRGB(a.mV[VZ]); + srgbColor.mV[VW] = a.mV[VW]; return srgbColor; } diff --git a/indra/llmessage/message_prehash.cpp b/indra/llmessage/message_prehash.cpp index c264a9f086..d3b80d684f 100644 --- a/indra/llmessage/message_prehash.cpp +++ b/indra/llmessage/message_prehash.cpp @@ -1402,3 +1402,5 @@ char const* const _PREHASH_HoverHeight = LLMessageStringTable::getInstance()->ge char const* const _PREHASH_Experience = LLMessageStringTable::getInstance()->getString("Experience"); char const* const _PREHASH_ExperienceID = LLMessageStringTable::getInstance()->getString("ExperienceID"); char const* const _PREHASH_LargeGenericMessage = LLMessageStringTable::getInstance()->getString("LargeGenericMessage"); +char const* const _PREHASH_GameControlInput = LLMessageStringTable::getInstance()->getString("GameControlInput"); +char const* const _PREHASH_AxisData = LLMessageStringTable::getInstance()->getString("AxisData"); diff --git a/indra/llmessage/message_prehash.h b/indra/llmessage/message_prehash.h index 1d30b69b67..5449eaf2a5 100644 --- a/indra/llmessage/message_prehash.h +++ b/indra/llmessage/message_prehash.h @@ -1403,5 +1403,7 @@ extern char const* const _PREHASH_HoverHeight; extern char const* const _PREHASH_Experience; extern char const* const _PREHASH_ExperienceID; extern char const* const _PREHASH_LargeGenericMessage; +extern char const* const _PREHASH_GameControlInput; +extern char const* const _PREHASH_AxisData; #endif diff --git a/indra/llrender/CMakeLists.txt b/indra/llrender/CMakeLists.txt index 26a8ff070f..04401e9bea 100644 --- a/indra/llrender/CMakeLists.txt +++ b/indra/llrender/CMakeLists.txt @@ -10,7 +10,6 @@ include(LLImage) include(LLWindow) set(llrender_SOURCE_FILES - llatmosphere.cpp llcubemap.cpp llcubemaparray.cpp llfontbitmapcache.cpp @@ -39,7 +38,6 @@ set(llrender_SOURCE_FILES set(llrender_HEADER_FILES CMakeLists.txt - llatmosphere.h llcubemap.h llcubemaparray.h llfontgl.h diff --git a/indra/llrender/llatmosphere.cpp b/indra/llrender/llatmosphere.cpp deleted file mode 100644 index eae5623a3c..0000000000 --- a/indra/llrender/llatmosphere.cpp +++ /dev/null @@ -1,290 +0,0 @@ -/** - * @file llatmosphere.cpp - * @brief LLAtmosphere integration impl - * - * $LicenseInfo:firstyear=2018&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2018, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "linden_common.h" - -#include "llatmosphere.h" -#include "llfasttimer.h" -#include "llsys.h" -#include "llglheaders.h" -#include "llrender.h" -#include "llshadermgr.h" -#include "llglslshader.h" - -LLAtmosphere* gAtmosphere = nullptr; - -// Values from "Reference Solar Spectral Irradiance: ASTM G-173", ETR column -// (see http://rredc.nrel.gov/solar/spectra/am1.5/ASTMG173/ASTMG173.html), -// summed and averaged in each bin (e.g. the value for 360nm is the average -// of the ASTM G-173 values for all wavelengths between 360 and 370nm). -// Values in W.m^-2. -const int kLambdaMin = 360; -const int kLambdaMax = 830; -const double kSolarIrradiance[48] = { - 1.11776, 1.14259, 1.01249, 1.14716, 1.72765, 1.73054, 1.6887, 1.61253, - 1.91198, 2.03474, 2.02042, 2.02212, 1.93377, 1.95809, 1.91686, 1.8298, - 1.8685, 1.8931, 1.85149, 1.8504, 1.8341, 1.8345, 1.8147, 1.78158, 1.7533, - 1.6965, 1.68194, 1.64654, 1.6048, 1.52143, 1.55622, 1.5113, 1.474, 1.4482, - 1.41018, 1.36775, 1.34188, 1.31429, 1.28303, 1.26758, 1.2367, 1.2082, - 1.18737, 1.14683, 1.12362, 1.1058, 1.07124, 1.04992 -}; - -// Values from http://www.iup.uni-bremen.de/gruppen/molspec/databases/ -// referencespectra/o3spectra2011/index.html for 233K, summed and averaged in -// each bin (e.g. the value for 360nm is the average of the original values -// for all wavelengths between 360 and 370nm). Values in m^2. -const double kOzoneCrossSection[48] = { - 1.18e-27, 2.182e-28, 2.818e-28, 6.636e-28, 1.527e-27, 2.763e-27, 5.52e-27, - 8.451e-27, 1.582e-26, 2.316e-26, 3.669e-26, 4.924e-26, 7.752e-26, 9.016e-26, - 1.48e-25, 1.602e-25, 2.139e-25, 2.755e-25, 3.091e-25, 3.5e-25, 4.266e-25, - 4.672e-25, 4.398e-25, 4.701e-25, 5.019e-25, 4.305e-25, 3.74e-25, 3.215e-25, - 2.662e-25, 2.238e-25, 1.852e-25, 1.473e-25, 1.209e-25, 9.423e-26, 7.455e-26, - 6.566e-26, 5.105e-26, 4.15e-26, 4.228e-26, 3.237e-26, 2.451e-26, 2.801e-26, - 2.534e-26, 1.624e-26, 1.465e-26, 2.078e-26, 1.383e-26, 7.105e-27 -}; - -// From https://en.wikipedia.org/wiki/Dobson_unit, in molecules.m^-2. -const double kDobsonUnit = 2.687e20; -// Maximum number density of ozone molecules, in m^-3 (computed so at to get -// 300 Dobson units of ozone - for this we divide 300 DU by the integral of -// the ozone density profile defined below, which is equal to 15km). -const double kMaxOzoneNumberDensity = 300.0 * kDobsonUnit / 15000.0; -const double kRayleigh = 1.24062e-6; -const double kRayleighScaleHeight = 8000.0; -const double kMieScaleHeight = 1200.0; -const double kMieAngstromAlpha = 0.0; -const double kMieAngstromBeta = 5.328e-3; -const double kMieSingleScatteringAlbedo = 0.9; -const double kGroundAlbedo = 0.1; - -AtmosphericModelSettings::AtmosphericModelSettings() - : m_skyBottomRadius(6360.0f) - , m_skyTopRadius(6420.0f) - , m_sunArcRadians(0.00045f) - , m_mieAnisotropy(0.8f) -{ - DensityLayer rayleigh_density(0.0, 1.0, -1.0 / kRayleighScaleHeight, 0.0, 0.0); - DensityLayer mie_density(0.0, 1.0, -1.0 / kMieScaleHeight, 0.0, 0.0); - - m_rayleighProfile.push_back(rayleigh_density); - m_mieProfile.push_back(mie_density); - - // Density profile increasing linearly from 0 to 1 between 10 and 25km, and - // decreasing linearly from 1 to 0 between 25 and 40km. This is an approximate - // profile from http://www.kln.ac.lk/science/Chemistry/Teaching_Resources/ - // Documents/Introduction%20to%20atmospheric%20chemistry.pdf (page 10). - m_absorptionProfile.push_back(DensityLayer(25000.0, 0.0, 0.0, 1.0 / 15000.0, -2.0 / 3.0)); - m_absorptionProfile.push_back(DensityLayer(0.0, 0.0, 0.0, -1.0 / 15000.0, 8.0 / 3.0)); -} - -AtmosphericModelSettings::AtmosphericModelSettings( - DensityProfile& rayleighProfile, - DensityProfile& mieProfile, - DensityProfile& absorptionProfile) -: m_skyBottomRadius(6360.0f) -, m_skyTopRadius(6420.0f) -, m_rayleighProfile(rayleighProfile) -, m_mieProfile(mieProfile) -, m_absorptionProfile(absorptionProfile) -, m_sunArcRadians(0.00045f) -, m_mieAnisotropy(0.8f) -{ -} - -AtmosphericModelSettings::AtmosphericModelSettings( - F32 skyBottomRadius, - F32 skyTopRadius, - DensityProfile& rayleighProfile, - DensityProfile& mieProfile, - DensityProfile& absorptionProfile, - F32 sunArcRadians, - F32 mieAniso) -: m_skyBottomRadius(skyBottomRadius) -, m_skyTopRadius(skyTopRadius) -, m_rayleighProfile(rayleighProfile) -, m_mieProfile(mieProfile) -, m_absorptionProfile(absorptionProfile) -, m_sunArcRadians(sunArcRadians) -, m_mieAnisotropy(mieAniso) -{ -} - -bool AtmosphericModelSettings::operator==(const AtmosphericModelSettings& rhs) const -{ - if (m_skyBottomRadius != rhs.m_skyBottomRadius) - { - return false; - } - - if (m_skyTopRadius != rhs.m_skyTopRadius) - { - return false; - } - - if (m_sunArcRadians != rhs.m_sunArcRadians) - { - return false; - } - - if (m_mieAnisotropy != rhs.m_mieAnisotropy) - { - return false; - } - - if (m_rayleighProfile != rhs.m_rayleighProfile) - { - return false; - } - - if (m_mieProfile != rhs.m_mieProfile) - { - return false; - } - - if (m_absorptionProfile != rhs.m_absorptionProfile) - { - return false; - } - - return true; -} - -void LLAtmosphere::initClass() -{ - if (!gAtmosphere) - { - gAtmosphere = new LLAtmosphere; - } -} - -void LLAtmosphere::cleanupClass() -{ - if(gAtmosphere) - { - delete gAtmosphere; - } - gAtmosphere = NULL; -} - -LLAtmosphere::LLAtmosphere() -{ - for (int l = kLambdaMin; l <= kLambdaMax; l += 10) - { - double lambda = static_cast<double>(l) * 1e-3; // micro-meters - double mie = kMieAngstromBeta / kMieScaleHeight * pow(lambda, -kMieAngstromAlpha); - m_wavelengths.push_back(l); - m_solar_irradiance.push_back(kSolarIrradiance[(l - kLambdaMin) / 10]); - m_rayleigh_scattering.push_back(kRayleigh * pow(lambda, -4)); - m_mie_scattering.push_back(mie * kMieSingleScatteringAlbedo); - m_mie_extinction.push_back(mie); - m_absorption_extinction.push_back(kMaxOzoneNumberDensity * kOzoneCrossSection[(l - kLambdaMin) / 10]); - m_ground_albedo.push_back(kGroundAlbedo); - } - - AtmosphericModelSettings defaults; - configureAtmosphericModel(defaults); -} - -LLAtmosphere::~LLAtmosphere() -{ - // Cease referencing textures from atmosphere::model from our LLGLTextures wrappers for same. - if (m_transmittance) - { - m_transmittance->setTexName(0); - } - - if (m_scattering) - { - m_scattering->setTexName(0); - } - - if (m_mie_scatter_texture) - { - m_mie_scatter_texture->setTexName(0); - } -} - -bool LLAtmosphere::configureAtmosphericModel(AtmosphericModelSettings& settings) -{ - // TBD - return true; -} - -LLGLTexture* LLAtmosphere::getTransmittance() -{ - if (!m_transmittance) - { - m_transmittance = new LLGLTexture; - m_transmittance->generateGLTexture(); - m_transmittance->setAddressMode(LLTexUnit::eTextureAddressMode::TAM_CLAMP); - m_transmittance->setFilteringOption(LLTexUnit::eTextureFilterOptions::TFO_BILINEAR); - m_transmittance->setExplicitFormat(GL_RGB32F, GL_RGB, GL_FLOAT); - m_transmittance->setTarget(GL_TEXTURE_2D, LLTexUnit::TT_TEXTURE); - } - return m_transmittance; -} - -LLGLTexture* LLAtmosphere::getScattering() -{ - if (!m_scattering) - { - m_scattering = new LLGLTexture; - m_scattering->generateGLTexture(); - m_scattering->setAddressMode(LLTexUnit::eTextureAddressMode::TAM_CLAMP); - m_scattering->setFilteringOption(LLTexUnit::eTextureFilterOptions::TFO_BILINEAR); - m_scattering->setExplicitFormat(GL_RGB16F, GL_RGB, GL_FLOAT); - m_scattering->setTarget(GL_TEXTURE_3D, LLTexUnit::TT_TEXTURE_3D); - } - return m_scattering; -} - -LLGLTexture* LLAtmosphere::getMieScattering() -{ - if (!m_mie_scatter_texture) - { - m_mie_scatter_texture = new LLGLTexture; - m_mie_scatter_texture->generateGLTexture(); - m_mie_scatter_texture->setAddressMode(LLTexUnit::eTextureAddressMode::TAM_CLAMP); - m_mie_scatter_texture->setFilteringOption(LLTexUnit::eTextureFilterOptions::TFO_BILINEAR); - m_mie_scatter_texture->setExplicitFormat(GL_RGB16F, GL_RGB, GL_FLOAT); - m_mie_scatter_texture->setTarget(GL_TEXTURE_3D, LLTexUnit::TT_TEXTURE_3D); - } - return m_mie_scatter_texture; -} - -LLGLTexture* LLAtmosphere::getIlluminance() -{ - if (!m_illuminance) - { - m_illuminance = new LLGLTexture; - m_illuminance->generateGLTexture(); - m_illuminance->setAddressMode(LLTexUnit::eTextureAddressMode::TAM_CLAMP); - m_illuminance->setFilteringOption(LLTexUnit::eTextureFilterOptions::TFO_BILINEAR); - m_illuminance->setExplicitFormat(GL_RGB32F, GL_RGB, GL_FLOAT); - m_illuminance->setTarget(GL_TEXTURE_2D, LLTexUnit::TT_TEXTURE); - } - return m_illuminance; -} diff --git a/indra/llrender/llatmosphere.h b/indra/llrender/llatmosphere.h deleted file mode 100644 index 4b8c7d0819..0000000000 --- a/indra/llrender/llatmosphere.h +++ /dev/null @@ -1,173 +0,0 @@ -/** - * @file llatmosphere.h - * @brief LLAtmosphere class - * - * $LicenseInfo:firstyear=2018&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2018, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#ifndef LL_ATMOSPHERE_H -#define LL_ATMOSPHERE_H - -#include "llglheaders.h" -#include "llgltexture.h" - -// An atmosphere layer of width 'width' (in m), and whose density is defined as -// 'exp_term' * exp('exp_scale' * h) + 'linear_term' * h + 'constant_term', -// clamped to [0,1], and where h is the altitude (in m). 'exp_term' and -// 'constant_term' are unitless, while 'exp_scale' and 'linear_term' are in -// m^-1. -class DensityLayer { - public: - DensityLayer() - : width(0.0f) - , exp_term(0.0f) - , exp_scale(0.0f) - , linear_term(0.0f) - , constant_term(0.0f) - { - } - - DensityLayer(float width, float exp_term, float exp_scale, float linear_term, float constant_term) - : width(width) - , exp_term(exp_term) - , exp_scale(exp_scale) - , linear_term(linear_term) - , constant_term(constant_term) - { - } - - bool operator==(const DensityLayer& rhs) const - { - if (width != rhs.width) - { - return false; - } - - if (exp_term != rhs.exp_term) - { - return false; - } - - if (exp_scale != rhs.exp_scale) - { - return false; - } - - if (linear_term != rhs.linear_term) - { - return false; - } - - if (constant_term != rhs.constant_term) - { - return false; - } - - return true; - } - - float width = 1024.0f; - float exp_term = 1.0f; - float exp_scale = 1.0f; - float linear_term = 1.0f; - float constant_term = 0.0f; -}; - -typedef std::vector<DensityLayer> DensityProfile; - -class AtmosphericModelSettings -{ -public: - AtmosphericModelSettings(); - - AtmosphericModelSettings( - DensityProfile& rayleighProfile, - DensityProfile& mieProfile, - DensityProfile& absorptionProfile); - - AtmosphericModelSettings( - F32 skyBottomRadius, - F32 skyTopRadius, - DensityProfile& rayleighProfile, - DensityProfile& mieProfile, - DensityProfile& absorptionProfile, - F32 sunArcRadians, - F32 mieAniso); - - bool operator==(const AtmosphericModelSettings& rhs) const; - - F32 m_skyBottomRadius; - F32 m_skyTopRadius; - DensityProfile m_rayleighProfile; - DensityProfile m_mieProfile; - DensityProfile m_absorptionProfile; - F32 m_sunArcRadians; - F32 m_mieAnisotropy; -}; - -class LLAtmosphere -{ -public: - LLAtmosphere(); - ~LLAtmosphere(); - - static void initClass(); - static void cleanupClass(); - - const LLAtmosphere& operator=(const LLAtmosphere& rhs) - { - LL_ERRS() << "Illegal operation!" << LL_ENDL; - return *this; - } - - LLGLTexture* getTransmittance(); - LLGLTexture* getScattering(); - LLGLTexture* getMieScattering(); - LLGLTexture* getIlluminance(); - - bool configureAtmosphericModel(AtmosphericModelSettings& settings); - -protected: - LLAtmosphere(const LLAtmosphere& rhs) - { - *this = rhs; - } - - LLPointer<LLGLTexture> m_transmittance; - LLPointer<LLGLTexture> m_scattering; - LLPointer<LLGLTexture> m_mie_scatter_texture; - LLPointer<LLGLTexture> m_illuminance; - - std::vector<double> m_wavelengths; - std::vector<double> m_solar_irradiance; - std::vector<double> m_rayleigh_scattering; - std::vector<double> m_mie_scattering; - std::vector<double> m_mie_extinction; - std::vector<double> m_absorption_extinction; - std::vector<double> m_ground_albedo; - - AtmosphericModelSettings m_settings; -}; - -extern LLAtmosphere* gAtmosphere; - -#endif // LL_ATMOSPHERE_H diff --git a/indra/llrender/llfontfreetype.cpp b/indra/llrender/llfontfreetype.cpp index fa76669258..019fb07152 100644 --- a/indra/llrender/llfontfreetype.cpp +++ b/indra/llrender/llfontfreetype.cpp @@ -58,9 +58,9 @@ FT_Render_Mode gFontRenderMode = FT_RENDER_MODE_NORMAL; -LLFontManager *gFontManagerp = NULL; +LLFontManager *gFontManagerp = nullptr; -FT_Library gFTLibrary = NULL; +FT_Library gFTLibrary = nullptr; //static void LLFontManager::initClass() @@ -75,7 +75,7 @@ void LLFontManager::initClass() void LLFontManager::cleanupClass() { delete gFontManagerp; - gFontManagerp = NULL; + gFontManagerp = nullptr; } LLFontManager::LLFontManager() @@ -103,6 +103,7 @@ LLFontManager::LLFontManager() LLFontManager::~LLFontManager() { FT_Done_FreeType(gFTLibrary); + unloadAllFonts(); } @@ -141,12 +142,8 @@ LLFontFreetype::LLFontFreetype() mAscender(0.f), mDescender(0.f), mLineHeight(0.f), -#ifdef LL_WINDOWS - pFileStream(NULL), - pFtStream(NULL), -#endif mIsFallback(false), - mFTFace(NULL), + mFTFace(nullptr), mRenderGlyphCount(0), mAddGlyphCount(0), mStyle(0), @@ -160,35 +157,16 @@ LLFontFreetype::~LLFontFreetype() // Clean up freetype libs. if (mFTFace) FT_Done_Face(mFTFace); - mFTFace = NULL; + mFTFace = nullptr; // Delete glyph info std::for_each(mCharGlyphInfoMap.begin(), mCharGlyphInfoMap.end(), DeletePairedPointer()); mCharGlyphInfoMap.clear(); -#ifdef LL_WINDOWS - delete pFileStream; // closed by FT_Done_Face - delete pFtStream; -#endif delete mFontBitmapCachep; // mFallbackFonts cleaned up by LLPointer destructor } -#ifdef LL_WINDOWS -unsigned long ft_read_cb(FT_Stream stream, unsigned long offset, unsigned char *buffer, unsigned long count) { - if (count <= 0) return count; - llifstream *file_stream = static_cast<llifstream *>(stream->descriptor.pointer); - file_stream->seekg(offset, std::ios::beg); - file_stream->read((char*)buffer, count); - return (unsigned long)file_stream->gcount(); -} - -void ft_close_cb(FT_Stream stream) { - llifstream *file_stream = static_cast<llifstream *>(stream->descriptor.pointer); - file_stream->close(); -} -#endif - bool LLFontFreetype::loadFace(const std::string& filename, F32 point_size, F32 vert_dpi, F32 horz_dpi, bool is_fallback, S32 face_n) { // Don't leak face objects. This is also needed to deal with @@ -196,26 +174,21 @@ bool LLFontFreetype::loadFace(const std::string& filename, F32 point_size, F32 v if (mFTFace) { FT_Done_Face(mFTFace); - mFTFace = NULL; + mFTFace = nullptr; } - int error; -#ifdef LL_WINDOWS - error = ftOpenFace(filename, face_n); -#else - error = FT_New_Face( gFTLibrary, - filename.c_str(), - 0, - &mFTFace); -#endif + FT_Open_Args openArgs; + memset( &openArgs, 0, sizeof( openArgs ) ); + openArgs.memory_base = gFontManagerp->loadFont( filename, openArgs.memory_size ); + + if( !openArgs.memory_base ) + return false; + + openArgs.flags = FT_OPEN_MEMORY; + int error = FT_Open_Face( gFTLibrary, &openArgs, 0, &mFTFace ); if (error) - { -#ifdef LL_WINDOWS - clearFontStreams(); -#endif return false; - } mIsFallback = is_fallback; F32 pixels_per_em = (point_size / 72.f)*vert_dpi; // Size in inches * dpi @@ -230,10 +203,8 @@ bool LLFontFreetype::loadFace(const std::string& filename, F32 point_size, F32 v { // Clean up freetype libs. FT_Done_Face(mFTFace); -#ifdef LL_WINDOWS - clearFontStreams(); -#endif - mFTFace = NULL; + + mFTFace = nullptr; return false; } @@ -289,73 +260,30 @@ S32 LLFontFreetype::getNumFaces(const std::string& filename) if (mFTFace) { FT_Done_Face(mFTFace); - mFTFace = NULL; + mFTFace = nullptr; } S32 num_faces = 1; -#ifdef LL_WINDOWS - int error = ftOpenFace(filename, 0); + FT_Open_Args openArgs; + memset( &openArgs, 0, sizeof( openArgs ) ); + openArgs.memory_base = gFontManagerp->loadFont( filename, openArgs.memory_size ); + if( !openArgs.memory_base ) + return 0; + openArgs.flags = FT_OPEN_MEMORY; + int error = FT_Open_Face( gFTLibrary, &openArgs, 0, &mFTFace ); if (error) - { return 0; - } else - { num_faces = mFTFace->num_faces; - } FT_Done_Face(mFTFace); - clearFontStreams(); - mFTFace = NULL; -#endif + mFTFace = nullptr; return num_faces; } -#ifdef LL_WINDOWS -S32 LLFontFreetype::ftOpenFace(const std::string& filename, S32 face_n) -{ - S32 error = -1; - pFileStream = new llifstream(filename, std::ios::binary); - if (pFileStream->is_open()) - { - std::streampos beg = pFileStream->tellg(); - pFileStream->seekg(0, std::ios::end); - std::streampos end = pFileStream->tellg(); - std::size_t file_size = end - beg; - pFileStream->seekg(0, std::ios::beg); - - pFtStream = new LLFT_Stream(); - pFtStream->base = 0; - pFtStream->pos = 0; - pFtStream->size = static_cast<unsigned long>(file_size); - pFtStream->descriptor.pointer = pFileStream; - pFtStream->read = ft_read_cb; - pFtStream->close = ft_close_cb; - - FT_Open_Args args; - args.flags = FT_OPEN_STREAM; - args.stream = (FT_StreamRec*)pFtStream; - error = FT_Open_Face(gFTLibrary, &args, face_n, &mFTFace); - } - return error; -} - -void LLFontFreetype::clearFontStreams() -{ - if (pFileStream) - { - pFileStream->close(); - } - delete pFileStream; - delete pFtStream; - pFileStream = NULL; - pFtStream = NULL; -} -#endif - void LLFontFreetype::addFallbackFont(const LLPointer<LLFontFreetype>& fallback_font, const char_functor_t& functor) { @@ -379,7 +307,7 @@ F32 LLFontFreetype::getDescenderHeight() const F32 LLFontFreetype::getXAdvance(llwchar wch) const { - if (mFTFace == NULL) + if (mFTFace == nullptr) return 0.0; // Return existing info only if it is current @@ -403,7 +331,7 @@ F32 LLFontFreetype::getXAdvance(llwchar wch) const F32 LLFontFreetype::getXAdvance(const LLFontGlyphInfo* glyph) const { - if (mFTFace == NULL) + if (mFTFace == nullptr) return 0.0; return glyph->mXAdvance; @@ -411,7 +339,7 @@ F32 LLFontFreetype::getXAdvance(const LLFontGlyphInfo* glyph) const F32 LLFontFreetype::getXKerning(llwchar char_left, llwchar char_right) const { - if (mFTFace == NULL) + if (mFTFace == nullptr) return 0.0; //llassert(!mIsFallback); @@ -430,7 +358,7 @@ F32 LLFontFreetype::getXKerning(llwchar char_left, llwchar char_right) const F32 LLFontFreetype::getXKerning(const LLFontGlyphInfo* left_glyph_info, const LLFontGlyphInfo* right_glyph_info) const { - if (mFTFace == NULL) + if (mFTFace == nullptr) return 0.0; U32 left_glyph = left_glyph_info ? left_glyph_info->mGlyphIndex : 0; @@ -453,7 +381,7 @@ LLFontGlyphInfo* LLFontFreetype::addGlyph(llwchar wch, EFontGlyphType glyph_type { if (!mFTFace) { - return NULL; + return nullptr; } llassert(!mIsFallback); @@ -544,14 +472,14 @@ LLFontGlyphInfo* LLFontFreetype::addGlyph(llwchar wch, EFontGlyphType glyph_type { return addGlyphFromFont(this, wch, glyph_index, glyph_type); } - return NULL; + return nullptr; } LLFontGlyphInfo* LLFontFreetype::addGlyphFromFont(const LLFontFreetype *fontp, llwchar wch, U32 glyph_index, EFontGlyphType requested_glyph_type) const { LL_PROFILE_ZONE_SCOPED; - if (mFTFace == NULL) - return NULL; + if (mFTFace == nullptr) + return nullptr; llassert(!mIsFallback); fontp->renderGlyph(requested_glyph_type, glyph_index); @@ -604,7 +532,7 @@ LLFontGlyphInfo* LLFontFreetype::addGlyphFromFont(const LLFontFreetype *fontp, l { U8 *buffer_data = fontp->mFTFace->glyph->bitmap.buffer; S32 buffer_row_stride = fontp->mFTFace->glyph->bitmap.pitch; - U8 *tmp_graydata = NULL; + U8 *tmp_graydata = nullptr; if (fontp->mFTFace->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_MONO) @@ -701,7 +629,7 @@ void LLFontFreetype::insertGlyphInfo(llwchar wch, LLFontGlyphInfo* gi) const void LLFontFreetype::renderGlyph(EFontGlyphType bitmap_type, U32 glyph_index) const { - if (mFTFace == NULL) + if (mFTFace == nullptr) return; FT_Int32 load_flags = FT_LOAD_FORCE_AUTOHINT; @@ -886,3 +814,58 @@ void LLFontFreetype::setSubImageLuminanceAlpha(U32 x, U32 y, U32 bitmap_num, U32 } } + +namespace ll +{ + namespace fonts + { + class LoadedFont + { + public: + LoadedFont( std::string aName , std::string const &aAddress, std::size_t aSize ) + : mAddress( aAddress ) + { + mName = aName; + mSize = aSize; + mRefs = 1; + } + std::string mName; + std::string mAddress; + std::size_t mSize; + U32 mRefs; + }; + } +} + +U8 const* LLFontManager::loadFont( std::string const &aFilename, long &a_Size) +{ + a_Size = 0; + std::map< std::string, std::shared_ptr<ll::fonts::LoadedFont> >::iterator itr = m_LoadedFonts.find( aFilename ); + if( itr != m_LoadedFonts.end() ) + { + ++itr->second->mRefs; + // A possible overflow cannot happen here, as it is asserted that the size is less than std::numeric_limits<long>::max() a few lines below. + a_Size = static_cast<long>(itr->second->mSize); + return reinterpret_cast<U8 const*>(itr->second->mAddress.c_str()); + } + + auto strContent = LLFile::getContents(aFilename); + + if( strContent.empty() ) + return nullptr; + + // For fontconfig a type of long is required, std::string::size() returns size_t. I think it is safe to limit this to 2GiB and not support fonts that huge (can that even be a thing?) + llassert_always( strContent.size() < std::numeric_limits<long>::max() ); + + a_Size = static_cast<long>(strContent.size()); + + auto pCache = std::make_shared<ll::fonts::LoadedFont>( aFilename, strContent, a_Size ); + itr = m_LoadedFonts.insert( std::make_pair( aFilename, pCache ) ).first; + + return reinterpret_cast<U8 const*>(itr->second->mAddress.c_str()); +} + +void LLFontManager::unloadAllFonts() +{ + m_LoadedFonts.clear(); +} diff --git a/indra/llrender/llfontfreetype.h b/indra/llrender/llfontfreetype.h index eba89f5def..7173da5238 100644 --- a/indra/llrender/llfontfreetype.h +++ b/indra/llrender/llfontfreetype.h @@ -43,15 +43,28 @@ typedef struct FT_FaceRec_* LLFT_Face; struct FT_StreamRec_; typedef struct FT_StreamRec_ LLFT_Stream; +namespace ll +{ + namespace fonts + { + class LoadedFont; + } +} + class LLFontManager { public: static void initClass(); static void cleanupClass(); + U8 const *loadFont( std::string const &aFilename, long &a_Size ); + private: LLFontManager(); ~LLFontManager(); + + void unloadAllFonts(); + std::map< std::string, std::shared_ptr<ll::fonts::LoadedFont> > m_LoadedFonts; }; struct LLFontGlyphInfo @@ -90,11 +103,6 @@ public: S32 getNumFaces(const std::string& filename); -#ifdef LL_WINDOWS - S32 ftOpenFace(const std::string& filename, S32 face_n); - void clearFontStreams(); -#endif - typedef std::function<bool(llwchar)> char_functor_t; void addFallbackFont(const LLPointer<LLFontFreetype>& fallback_font, const char_functor_t& functor = nullptr); @@ -170,11 +178,6 @@ private: LLFT_Face mFTFace; -#ifdef LL_WINDOWS - llifstream *pFileStream; - LLFT_Stream *pFtStream; -#endif - bool mIsFallback; typedef std::pair<LLPointer<LLFontFreetype>, char_functor_t> fallback_font_t; typedef std::vector<fallback_font_t> fallback_font_vector_t; diff --git a/indra/llrender/llfontgl.cpp b/indra/llrender/llfontgl.cpp index a012d57b5a..97be43cf86 100644 --- a/indra/llrender/llfontgl.cpp +++ b/indra/llrender/llfontgl.cpp @@ -404,7 +404,6 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons { // recursively render ellipses at end of string // we've already reserved enough room - gGL.pushUIMatrix(); static LLWString elipses_wstr(utf8string_to_wstring(std::string("..."))); render(elipses_wstr, 0, @@ -417,7 +416,6 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons right_x, false, use_color); - gGL.popUIMatrix(); } gGL.popUIMatrix(); diff --git a/indra/llrender/llfontvertexbuffer.cpp b/indra/llrender/llfontvertexbuffer.cpp index 392f235aad..963aab7121 100644 --- a/indra/llrender/llfontvertexbuffer.cpp +++ b/indra/llrender/llfontvertexbuffer.cpp @@ -31,6 +31,8 @@ #include "llvertexbuffer.h" +bool LLFontVertexBuffer::sEnableBufferCollection = true; + LLFontVertexBuffer::LLFontVertexBuffer() { } @@ -119,6 +121,11 @@ S32 LLFontVertexBuffer::render( { return static_cast<S32>(text.length()); } + if (!sEnableBufferCollection) + { + // For debug purposes and performance testing + return fontp->render(text, begin_offset, x, y, color, halign, valign, style, shadow, max_chars, max_pixels, right_x, use_ellipses, use_color); + } if (mBufferList.empty()) { genBuffers(fontp, text, begin_offset, x, y, color, halign, valign, @@ -202,6 +209,17 @@ void LLFontVertexBuffer::renderBuffers() gGL.flush(); // deliberately empty pending verts gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE); gGL.pushUIMatrix(); + + gGL.loadUIIdentity(); + + // Depth translation, so that floating text appears 'in-world' + // and is correctly occluded. + gGL.translatef(0.f, 0.f, LLFontGL::sCurDepth); + gGL.setSceneBlendType(LLRender::BT_ALPHA); + + // Note: ellipses should technically be covered by push/load/translate of their own + // but it's more complexity, values do not change, skipping doesn't appear to break + // anything, so we can skip that until it proves to cause issues. for (LLVertexBufferData& buffer : mBufferList) { buffer.draw(); diff --git a/indra/llrender/llfontvertexbuffer.h b/indra/llrender/llfontvertexbuffer.h index 67cf2ca13c..59cb536b74 100644 --- a/indra/llrender/llfontvertexbuffer.h +++ b/indra/llrender/llfontvertexbuffer.h @@ -78,6 +78,8 @@ public: F32* right_x = NULL, bool use_ellipses = false, bool use_color = true); + + static void enableBufferCollection(bool enable) { sEnableBufferCollection = enable; } private: void genBuffers(const LLFontGL* fontp, @@ -114,6 +116,8 @@ private: F32 mLastScaleX = 1.f; F32 mLastScaleY = 1.f; LLCoordGL mLastOrigin; + + static bool sEnableBufferCollection; }; #endif diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp index a60f1efbdf..798b605f08 100644 --- a/indra/llrender/llgl.cpp +++ b/indra/llrender/llgl.cpp @@ -995,9 +995,6 @@ LLGLManager::LLGLManager() : mIsAMD(false), mIsNVIDIA(false), mIsIntel(false), -#if LL_DARWIN - mIsMobileGF(false), -#endif mHasRequirements(true), mDriverVersionMajor(1), mDriverVersionMinor(0), @@ -1039,7 +1036,6 @@ void LLGLManager::initWGL() GLH_EXT_NAME(wglGetGPUIDsAMD) = (PFNWGLGETGPUIDSAMDPROC)GLH_EXT_GET_PROC_ADDRESS("wglGetGPUIDsAMD"); GLH_EXT_NAME(wglGetGPUInfoAMD) = (PFNWGLGETGPUINFOAMDPROC)GLH_EXT_GET_PROC_ADDRESS("wglGetGPUInfoAMD"); } - mHasNVXGpuMemoryInfo = ExtensionExists("GL_NVX_gpu_memory_info", gGLHExts.mSysExts); if (ExtensionExists("WGL_EXT_swap_control", gGLHExts.mSysExts)) { @@ -1145,7 +1141,11 @@ bool LLGLManager::initGL() // Trailing space necessary to keep "nVidia Corpor_ati_on" cards // from being recognized as ATI. // NOTE: AMD has been pretty good about not breaking this check, do not rename without good reason - if (mGLVendor.substr(0,4) == "ATI ") + if (mGLVendor.substr(0,4) == "ATI " +#if LL_LINUX + || mGLVendor.find("AMD") != std::string::npos +#endif //LL_LINUX + ) { mGLVendorShort = "AMD"; // *TODO: Fix this? @@ -1211,8 +1211,10 @@ bool LLGLManager::initGL() { LL_WARNS("RenderInit") << "VRAM Detected (AMDAssociations):" << mVRAM << LL_ENDL; } - } - else if (mHasNVXGpuMemoryInfo) + } else +#endif +#if LL_WINDOWS || LL_LINUX + if (mHasNVXGpuMemoryInfo) { GLint mem_kb = 0; glGetIntegerv(GL_GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX, &mem_kb); @@ -1430,6 +1432,10 @@ void LLGLManager::initExtensions() mHasTransformFeedback = mGLVersion >= 3.99f; mHasDebugOutput = mGLVersion >= 4.29f; +#if LL_WINDOWS || LL_LINUX + mHasNVXGpuMemoryInfo = ExtensionExists("GL_NVX_gpu_memory_info", gGLHExts.mSysExts); +#endif + // Misc glGetIntegerv(GL_MAX_ELEMENTS_VERTICES, (GLint*) &mGLMaxVertexRange); glGetIntegerv(GL_MAX_ELEMENTS_INDICES, (GLint*) &mGLMaxIndexRange); diff --git a/indra/llrender/llgl.h b/indra/llrender/llgl.h index 8d7ac56d79..0e26961588 100644 --- a/indra/llrender/llgl.h +++ b/indra/llrender/llgl.h @@ -108,11 +108,6 @@ public: // hints to the render pipe U32 mDownScaleMethod = 0; // see settings.xml RenderDownScaleMethod -#if LL_DARWIN - // Needed to distinguish problem cards on older Macs that break with Materials - bool mIsMobileGF; -#endif - // Whether this version of GL is good enough for SL to use bool mHasRequirements; diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index 565071ff0d..3b74d360d0 100644 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -38,7 +38,7 @@ #include "hbxxh.h" #include "glm/gtc/type_ptr.hpp" -#if LL_WINDOWS +#if GL_ARB_debug_output && !LL_DARWIN extern void APIENTRY gl_debug_callback(GLenum source, GLenum type, GLuint id, @@ -866,7 +866,7 @@ LLRender::~LLRender() bool LLRender::init(bool needs_vertex_buffer) { -#if LL_WINDOWS +#if GL_ARB_debug_output && !LL_DARWIN if (gGLManager.mHasDebugOutput && gDebugGL) { //setup debug output callback //glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_LOW_ARB, 0, NULL, GL_TRUE); diff --git a/indra/llrender/llrender2dutils.cpp b/indra/llrender/llrender2dutils.cpp index 0cd0c5fe6e..971241ed05 100644 --- a/indra/llrender/llrender2dutils.cpp +++ b/indra/llrender/llrender2dutils.cpp @@ -1712,10 +1712,10 @@ void gl_segmented_rect_3d_tex(const LLRectf& clip_rect, const LLRectf& center_uv gGL.vertex3fv((center_draw_rect.mRight * width_vec + height_vec).mV); gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mTop); - gGL.vertex3fv((center_draw_rect.mLeft* width_vec + center_draw_rect.mTop * height_vec).mV); + gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mTop * height_vec).mV); - gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mTop); - gGL.vertex3fv((center_draw_rect.mRight* width_vec + center_draw_rect.mTop * height_vec).mV); + gGL.texCoord2f(center_uv_rect.mRight, clip_rect.mTop); + gGL.vertex3fv((center_draw_rect.mRight* width_vec + height_vec).mV); gGL.texCoord2f(center_uv_rect.mLeft, clip_rect.mTop); gGL.vertex3fv((center_draw_rect.mLeft * width_vec + height_vec).mV); diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp index 150277c8df..6097b09d96 100644 --- a/indra/llrender/llshadermgr.cpp +++ b/indra/llrender/llshadermgr.cpp @@ -1300,9 +1300,6 @@ void LLShaderMgr::initAttribsAndUniforms() mReservedUniforms.push_back("shadow_matrix"); mReservedUniforms.push_back("env_mat"); mReservedUniforms.push_back("shadow_clip"); - mReservedUniforms.push_back("sun_wash"); - mReservedUniforms.push_back("shadow_noise"); - mReservedUniforms.push_back("blur_size"); mReservedUniforms.push_back("ssao_radius"); mReservedUniforms.push_back("ssao_max_radius"); mReservedUniforms.push_back("ssao_factor"); @@ -1318,8 +1315,6 @@ void LLShaderMgr::initAttribsAndUniforms() mReservedUniforms.push_back("moon_dir"); mReservedUniforms.push_back("shadow_res"); mReservedUniforms.push_back("proj_shadow_res"); - mReservedUniforms.push_back("depth_cutoff"); - mReservedUniforms.push_back("norm_cutoff"); mReservedUniforms.push_back("shadow_target_width"); llassert(mReservedUniforms.size() == LLShaderMgr::DEFERRED_SHADOW_TARGET_WIDTH + 1); @@ -1369,9 +1364,7 @@ void LLShaderMgr::initAttribsAndUniforms() mReservedUniforms.push_back("noiseMap"); mReservedUniforms.push_back("lightFunc"); mReservedUniforms.push_back("lightMap"); - mReservedUniforms.push_back("bloomMap"); mReservedUniforms.push_back("projectionMap"); - mReservedUniforms.push_back("norm_mat"); mReservedUniforms.push_back("specular_color"); mReservedUniforms.push_back("env_intensity"); @@ -1450,10 +1443,6 @@ void LLShaderMgr::initAttribsAndUniforms() mReservedUniforms.push_back("sun_size"); mReservedUniforms.push_back("fog_color"); - mReservedUniforms.push_back("transmittance_texture"); - mReservedUniforms.push_back("scattering_texture"); - mReservedUniforms.push_back("single_mie_scattering_texture"); - mReservedUniforms.push_back("irradiance_texture"); mReservedUniforms.push_back("blend_factor"); mReservedUniforms.push_back("moisture_level"); mReservedUniforms.push_back("droplet_radius"); diff --git a/indra/llrender/llshadermgr.h b/indra/llrender/llshadermgr.h index 0eb9db6715..1bae0cd8a0 100644 --- a/indra/llrender/llshadermgr.h +++ b/indra/llrender/llshadermgr.h @@ -157,9 +157,6 @@ public: DEFERRED_SHADOW_MATRIX, // "shadow_matrix" DEFERRED_ENV_MAT, // "env_mat" DEFERRED_SHADOW_CLIP, // "shadow_clip" - DEFERRED_SUN_WASH, // "sun_wash" - DEFERRED_SHADOW_NOISE, // "shadow_noise" - DEFERRED_BLUR_SIZE, // "blur_size" DEFERRED_SSAO_RADIUS, // "ssao_radius" DEFERRED_SSAO_MAX_RADIUS, // "ssao_max_radius" DEFERRED_SSAO_FACTOR, // "ssao_factor" @@ -175,8 +172,6 @@ public: DEFERRED_MOON_DIR, // "moon_dir" DEFERRED_SHADOW_RES, // "shadow_res" DEFERRED_PROJ_SHADOW_RES, // "proj_shadow_res" - DEFERRED_DEPTH_CUTOFF, // "depth_cutoff" - DEFERRED_NORM_CUTOFF, // "norm_cutoff" DEFERRED_SHADOW_TARGET_WIDTH, // "shadow_target_width" DEFERRED_SSR_ITR_COUNT, // "iterationCount" @@ -221,9 +216,7 @@ public: DEFERRED_NOISE, // "noiseMap" DEFERRED_LIGHTFUNC, // "lightFunc" DEFERRED_LIGHT, // "lightMap" - DEFERRED_BLOOM, // "bloomMap" DEFERRED_PROJECTION, // "projectionMap" - DEFERRED_NORM_MATRIX, // "norm_mat" SPECULAR_COLOR, // "specular_color" ENVIRONMENT_INTENSITY, // "env_intensity" @@ -301,13 +294,7 @@ public: SUN_SIZE, // "sun_size" FOG_COLOR, // "fog_color" - // precomputed textures - TRANSMITTANCE_TEX, // "transmittance_texture" - SCATTER_TEX, // "scattering_texture" - SINGLE_MIE_SCATTER_TEX, // "single_mie_scattering_texture" - ILLUMINANCE_TEX, // "irradiance_texture" BLEND_FACTOR, // "blend_factor" - MOISTURE_LEVEL, // "moisture_level" DROPLET_RADIUS, // "droplet_radius" ICE_LEVEL, // "ice_level" diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index 6f4828397a..12ae36f4bb 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -604,7 +604,7 @@ public: static LLVBOPool* sVBOPool = nullptr; -void LLVertexBufferData::draw() +void LLVertexBufferData::drawWithMatrix() { if (!mVB) { @@ -642,6 +642,28 @@ void LLVertexBufferData::draw() gGL.popMatrix(); } +void LLVertexBufferData::draw() +{ + if (!mVB) + { + llassert(false); + // Not supposed to happen, check buffer generation + return; + } + + if (mTexName) + { + gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mTexName); + } + else + { + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + } + + mVB->setBuffer(); + mVB->drawArrays(mMode, 0, mCount); +} + //============================================================================ //static diff --git a/indra/llrender/llvertexbuffer.h b/indra/llrender/llvertexbuffer.h index d4c6fbaf18..375ad76fb8 100644 --- a/indra/llrender/llvertexbuffer.h +++ b/indra/llrender/llvertexbuffer.h @@ -77,6 +77,7 @@ public: , mModelView(projection) , mTexture0(texture0) {} + void drawWithMatrix(); void draw(); LLPointer<LLVertexBuffer> mVB; U8 mMode; diff --git a/indra/llui/CMakeLists.txt b/indra/llui/CMakeLists.txt index 69e1b57245..13a0250fe5 100644 --- a/indra/llui/CMakeLists.txt +++ b/indra/llui/CMakeLists.txt @@ -270,12 +270,13 @@ target_link_libraries(llui llmath ll::hunspell llcommon + ll::SDL2 ) # Add tests if(LL_TESTS) include(LLAddBuildTest) - set(test_libs llmessage llcorehttp llxml llrender llcommon ll::hunspell) + set(test_libs llmessage llcorehttp llxml llrender llcommon ll::hunspell ll::SDL2) SET(llui_TEST_SOURCE_FILES llurlmatch.cpp @@ -285,7 +286,7 @@ if(LL_TESTS) # INTEGRATION TESTS if(NOT LINUX) - set(test_libs llui llmessage llcorehttp llxml llrender llcommon ll::hunspell ) + set(test_libs llui llmessage llcorehttp llxml llrender llcommon ll::hunspell ll::SDL2) LL_ADD_INTEGRATION_TEST(llurlentry llurlentry.cpp "${test_libs}") endif(NOT LINUX) endif(LL_TESTS) diff --git a/indra/llui/llaccordionctrltab.h b/indra/llui/llaccordionctrltab.h index cf3569683e..3fdcf9f7f2 100644 --- a/indra/llui/llaccordionctrltab.h +++ b/indra/llui/llaccordionctrltab.h @@ -126,7 +126,7 @@ public: void setSelected(bool is_selected); - bool getCollapsible() { return mCollapsible; }; + bool getCollapsible() const { return mCollapsible; }; void setCollapsible(bool collapsible) { mCollapsible = collapsible; }; void changeOpenClose(bool is_open); @@ -181,7 +181,7 @@ public: void setHeaderVisible(bool value); - bool getHeaderVisible() { return mHeaderVisible;} + bool getHeaderVisible() const { return mHeaderVisible;} S32 mExpandedHeight; // Height of expanded ctrl. // Used to restore height after expand. diff --git a/indra/llui/llcheckboxctrl.h b/indra/llui/llcheckboxctrl.h index 135f128692..4068741978 100644 --- a/indra/llui/llcheckboxctrl.h +++ b/indra/llui/llcheckboxctrl.h @@ -36,8 +36,8 @@ // Constants // -const bool RADIO_STYLE = true; -const bool CHECK_STYLE = false; +constexpr bool RADIO_STYLE = true; +constexpr bool CHECK_STYLE = false; // // Classes @@ -94,7 +94,7 @@ public: // LLUICtrl interface virtual void setValue(const LLSD& value ); virtual LLSD getValue() const; - bool get() { return (bool)getValue().asBoolean(); } + bool get() const { return (bool)getValue().asBoolean(); } void set(bool value) { setValue(value); } virtual void setTentative(bool b); @@ -106,7 +106,7 @@ public: virtual void onCommit(); // LLCheckBoxCtrl interface - virtual bool toggle() { return mButton->toggleState(); } // returns new state + virtual bool toggle() { return mButton->toggleState(); } // returns new state void setBtnFocus() { mButton->setFocus(true); } diff --git a/indra/llui/llcombobox.cpp b/indra/llui/llcombobox.cpp index a1c16ccdec..da63003f39 100644 --- a/indra/llui/llcombobox.cpp +++ b/indra/llui/llcombobox.cpp @@ -120,7 +120,6 @@ LLComboBox::LLComboBox(const LLComboBox::Params& p) mButton = LLUICtrlFactory::create<LLButton>(button_params); - if (mAllowTextEntry) { //redo to compensate for button hack that leaves space for a character @@ -142,16 +141,12 @@ LLComboBox::LLComboBox(const LLComboBox::Params& p) // Grab the mouse-up event and make sure the button state is correct mList->setMouseUpCallback(boost::bind(&LLComboBox::onListMouseUp, this)); - for (LLInitParam::ParamIterator<ItemParams>::const_iterator it = p.items.begin(); - it != p.items.end(); - ++it) + for (LLComboBox::ItemParams item_params : p.items) { - LLScrollListItem::Params item_params = *it; - if (it->label.isProvided()) + if (item_params.label.isProvided()) { - item_params.columns.add().value(it->label()); + item_params.columns.add().value(item_params.label()); } - mList->addRow(item_params); } @@ -235,7 +230,7 @@ void LLComboBox::onCommit() bool LLComboBox::isDirty() const { bool grubby = false; - if ( mList ) + if (mList) { grubby = mList->isDirty(); } @@ -243,9 +238,9 @@ bool LLComboBox::isDirty() const } // virtual Clear dirty state -void LLComboBox::resetDirty() +void LLComboBox::resetDirty() { - if ( mList ) + if (mList) { mList->resetDirty(); } @@ -256,6 +251,11 @@ bool LLComboBox::itemExists(const std::string& name) return mList->getItemByLabel(name); } +std::vector<LLScrollListItem*> LLComboBox::getAllData() const +{ + return mList->getAllData(); +} + // add item "name" to menu LLScrollListItem* LLComboBox::add(const std::string& name, EAddPosition pos, bool enabled) { @@ -299,7 +299,7 @@ LLScrollListItem* LLComboBox::add(const std::string& name, void* userdata, EAddP { LLScrollListItem* item = mList->addSimpleElement(name, pos); item->setEnabled(enabled); - item->setUserdata( userdata ); + item->setUserdata(userdata); if (!mAllowTextEntry && mLabel.empty()) { if (mControlVariable) @@ -343,7 +343,6 @@ void LLComboBox::sortByName(bool ascending) mList->sortOnce(0, ascending); } - // Choose an item with a given name in the menu. // Returns true if the item was found. bool LLComboBox::setSimple(const LLStringExplicit& name) @@ -365,15 +364,13 @@ void LLComboBox::setValue(const LLSD& value) if (LLScrollListItem* item = mList->getFirstSelected()) { LLSD item_value = item->getValue(); - if (item_value.asStringRef() == value.asStringRef()) + if (item_value.asString() == value.asString()) return; } - bool found = mList->selectByValue(value); - if (found) + if (mList->selectByValue(value)) { - LLScrollListItem* item = mList->getFirstSelected(); - if (item) + if (mList->getFirstSelected()) { updateLabel(); } @@ -404,7 +401,8 @@ const std::string LLComboBox::getSelectedItemLabel(S32 column) const // virtual LLSD LLComboBox::getValue() const { - if (LLScrollListItem* item = mList->getFirstSelected()) + LLScrollListItem* item = mList->getFirstSelected(); + if(item) { return item->getValue(); } @@ -590,8 +588,7 @@ bool LLComboBox::selectPrevItem() void LLComboBox::setEnabledByValue(const LLSD& value, bool enabled) { - LLScrollListItem *found = mList->getItem(value); - if (found) + if (LLScrollListItem* found = mList->getItem(value)) { found->setEnabled(enabled); } @@ -654,7 +651,7 @@ void LLComboBox::setLeftTextPadding(S32 pad) void* LLComboBox::getCurrentUserdata() { LLScrollListItem* item = mList->getFirstSelected(); - if( item ) + if (item) { return item->getUserdata(); } @@ -760,15 +757,19 @@ void LLComboBox::hideList() if (mList->getVisible()) { // assert selection in list - if(mAllowNewValues) + if (mAllowNewValues) { // mLastSelectedIndex = -1 means that we entered a new value, don't select // any of existing items in this case. - if(mLastSelectedIndex >= 0) + if (mLastSelectedIndex >= 0) + { mList->selectNthItem(mLastSelectedIndex); + } } - else if(mLastSelectedIndex >= 0) + else if (mLastSelectedIndex >= 0) + { mList->selectNthItem(mLastSelectedIndex); + } mButton->setToggleState(false); mList->setVisible(false); @@ -854,7 +855,7 @@ bool LLComboBox::handleToolTip(S32 x, S32 y, MASK mask) { std::string tool_tip; - if(LLUICtrl::handleToolTip(x, y, mask)) + if (LLUICtrl::handleToolTip(x, y, mask)) { return true; } @@ -871,6 +872,7 @@ bool LLComboBox::handleToolTip(S32 x, S32 y, MASK mask) .message(tool_tip) .sticky_rect(calcScreenRect())); } + return true; } diff --git a/indra/llui/llcombobox.h b/indra/llui/llcombobox.h index 8be3eb57e4..06687e9368 100644 --- a/indra/llui/llcombobox.h +++ b/indra/llui/llcombobox.h @@ -144,6 +144,7 @@ public: bool remove( S32 index ); // remove item by index, return true if found and removed void removeall() { clearRows(); } bool itemExists(const std::string& name); + std::vector<LLScrollListItem*> getAllData() const; void sortByName(bool ascending = true); // Sort the entries in the combobox by name diff --git a/indra/llui/llcontainerview.h b/indra/llui/llcontainerview.h index c6dd401e85..2675d21c22 100644 --- a/indra/llui/llcontainerview.h +++ b/indra/llui/llcontainerview.h @@ -65,21 +65,21 @@ protected: public: ~LLContainerView(); - /*virtual*/ bool postBuild(); - /*virtual*/ bool addChild(LLView* view, S32 tab_group = 0); + bool postBuild() override; + bool addChild(LLView* view, S32 tab_group = 0) override; - /*virtual*/ bool handleDoubleClick(S32 x, S32 y, MASK mask); - /*virtual*/ bool handleMouseDown(S32 x, S32 y, MASK mask); - /*virtual*/ bool handleMouseUp(S32 x, S32 y, MASK mask); + bool handleDoubleClick(S32 x, S32 y, MASK mask) override; + bool handleMouseDown(S32 x, S32 y, MASK mask) override; + bool handleMouseUp(S32 x, S32 y, MASK mask) override; - /*virtual*/ void draw(); - /*virtual*/ void reshape(S32 width, S32 height, bool called_from_parent = true); - /*virtual*/ LLRect getRequiredRect(); // Return the height of this object, given the set options. + void draw() override; + void reshape(S32 width, S32 height, bool called_from_parent = true) override; + LLRect getRequiredRect() override; // Return the height of this object, given the set options. void setLabel(const std::string& label); void showLabel(bool show) { mShowLabel = show; } void setDisplayChildren(bool displayChildren); - bool getDisplayChildren() { return mDisplayChildren; } + bool getDisplayChildren() const { return mDisplayChildren; } void setScrollContainer(LLScrollContainer* scroll) {mScrollContainer = scroll;} private: diff --git a/indra/llui/lldockablefloater.h b/indra/llui/lldockablefloater.h index 3effc977db..9c516e23a4 100644 --- a/indra/llui/lldockablefloater.h +++ b/indra/llui/lldockablefloater.h @@ -112,8 +112,8 @@ public: virtual bool overlapsScreenChannel() { return mOverlapsScreenChannel && getVisible() && isDocked(); } virtual void setOverlapsScreenChannel(bool overlaps) { mOverlapsScreenChannel = overlaps; } - bool getUniqueDocking() { return mUniqueDocking; } - bool getUseTongue() { return mUseTongue; } + bool getUniqueDocking() const { return mUniqueDocking; } + bool getUseTongue() const { return mUseTongue; } void setUseTongue(bool use_tongue) { mUseTongue = use_tongue;} private: diff --git a/indra/llui/lldockcontrol.cpp b/indra/llui/lldockcontrol.cpp index 11dbad8c09..1a00c03856 100644 --- a/indra/llui/lldockcontrol.cpp +++ b/indra/llui/lldockcontrol.cpp @@ -156,7 +156,7 @@ void LLDockControl::repositionDockable() } } -bool LLDockControl::isDockVisible() +bool LLDockControl::isDockVisible() const { bool res = true; diff --git a/indra/llui/lldockcontrol.h b/indra/llui/lldockcontrol.h index 7e31330713..b6ac9c19dd 100644 --- a/indra/llui/lldockcontrol.h +++ b/indra/llui/lldockcontrol.h @@ -61,19 +61,19 @@ public: void off(); void forceRecalculatePosition(); void setDock(LLView* dockWidget); - LLView* getDock() + LLView* getDock() const { return mDockWidgetHandle.get(); } void repositionDockable(); void drawToungue(); - bool isDockVisible(); + bool isDockVisible() const; // gets a rect that bounds possible positions for a dockable control (EXT-1111) void getAllowedRect(LLRect& rect); - S32 getTongueWidth() { return mDockTongue->getWidth(); } - S32 getTongueHeight() { return mDockTongue->getHeight(); } + S32 getTongueWidth() const { return mDockTongue->getWidth(); } + S32 getTongueHeight() const { return mDockTongue->getHeight(); } private: virtual void moveDockable(); diff --git a/indra/llui/lldraghandle.h b/indra/llui/lldraghandle.h index a522e63243..73211d5292 100644 --- a/indra/llui/lldraghandle.h +++ b/indra/llui/lldraghandle.h @@ -66,7 +66,7 @@ public: void setMaxTitleWidth(S32 max_width) {mMaxTitleWidth = llmin(max_width, mMaxTitleWidth); } S32 getMaxTitleWidth() const { return mMaxTitleWidth; } void setButtonsRect(const LLRect& rect){ mButtonsRect = rect; } - LLRect getButtonsRect() { return mButtonsRect; } + LLRect getButtonsRect() const { return mButtonsRect; } void setTitleVisible(bool visible); virtual void setTitle( const std::string& title ) = 0; diff --git a/indra/llui/llfiltereditor.h b/indra/llui/llfiltereditor.h index 686827d94c..685219c9f6 100644 --- a/indra/llui/llfiltereditor.h +++ b/indra/llui/llfiltereditor.h @@ -49,7 +49,7 @@ protected: LLFilterEditor(const Params&); friend class LLUICtrlFactory; - /*virtual*/ void handleKeystroke(); + void handleKeystroke() override; }; #endif // LL_FILTEREDITOR_H diff --git a/indra/llui/llflashtimer.cpp b/indra/llui/llflashtimer.cpp index 2711e8088d..dc912bccf4 100644 --- a/indra/llui/llflashtimer.cpp +++ b/indra/llui/llflashtimer.cpp @@ -85,12 +85,12 @@ void LLFlashTimer::stopFlashing() mCurrentTickCount = 0; } -bool LLFlashTimer::isFlashingInProgress() +bool LLFlashTimer::isFlashingInProgress() const { return mIsFlashingInProgress; } -bool LLFlashTimer::isCurrentlyHighlighted() +bool LLFlashTimer::isCurrentlyHighlighted() const { return mIsCurrentlyHighlighted; } diff --git a/indra/llui/llflashtimer.h b/indra/llui/llflashtimer.h index 988b577ed2..7e55da4fb1 100644 --- a/indra/llui/llflashtimer.h +++ b/indra/llui/llflashtimer.h @@ -51,8 +51,8 @@ public: void startFlashing(); void stopFlashing(); - bool isFlashingInProgress(); - bool isCurrentlyHighlighted(); + bool isFlashingInProgress() const; + bool isCurrentlyHighlighted() const; /* * Use this instead of deleting this object. * The next call to tick() will return true and that will destroy this object. diff --git a/indra/llui/llflatlistview.cpp b/indra/llui/llflatlistview.cpp index 53f39766c6..b8c833f4fd 100644 --- a/indra/llui/llflatlistview.cpp +++ b/indra/llui/llflatlistview.cpp @@ -1337,7 +1337,7 @@ void LLFlatListViewEx::updateNoItemsMessage(const std::string& filter_string) } } -bool LLFlatListViewEx::getForceShowingUnmatchedItems() +bool LLFlatListViewEx::getForceShowingUnmatchedItems() const { return mForceShowingUnmatchedItems; } diff --git a/indra/llui/llflatlistview.h b/indra/llui/llflatlistview.h index 6d75e9f282..112c330a15 100644 --- a/indra/llui/llflatlistview.h +++ b/indra/llui/llflatlistview.h @@ -129,7 +129,7 @@ public: LLRect getRequiredRect() { return getItemsRect(); } /** Returns distance between items */ - const S32 getItemsPad() { return mItemPad; } + const S32 getItemsPad() const { return mItemPad; } /** * Adds and item and LLSD value associated with it to the list at specified position @@ -264,7 +264,7 @@ public: void setCommitOnSelectionChange(bool b) { mCommitOnSelectionChange = b; } /** Get number of selected items in the list */ - U32 numSelected() const {return static_cast<U32>(mSelectedItemPairs.size()); } + U32 numSelected() const { return static_cast<U32>(mSelectedItemPairs.size()); } /** Get number of (visible) items in the list */ U32 size(const bool only_visible_items = true) const; @@ -294,8 +294,8 @@ public: void scrollToShowFirstSelectedItem(); - void selectFirstItem (); - void selectLastItem (); + void selectFirstItem(); + void selectLastItem(); virtual S32 notify(const LLSD& info) ; @@ -478,7 +478,7 @@ public: void setNoItemsMsg(const std::string& msg) { mNoItemsMsg = msg; } void setNoFilteredItemsMsg(const std::string& msg) { mNoFilteredItemsMsg = msg; } - bool getForceShowingUnmatchedItems(); + bool getForceShowingUnmatchedItems() const; void setForceShowingUnmatchedItems(bool show); @@ -486,7 +486,7 @@ public: * Sets up new filter string and filters the list. */ void setFilterSubString(const std::string& filter_str, bool notify_parent); - std::string getFilterSubString() { return mFilterSubString; } + std::string getFilterSubString() const { return mFilterSubString; } /** * Filters the list, rearranges and notifies parent about shape changes. diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index 4b904f09e0..fd07b2ec5d 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -2165,7 +2165,7 @@ void LLFloater::setCanDrag(bool can_drag) } } -bool LLFloater::getCanDrag() +bool LLFloater::getCanDrag() const { return mDragHandle->getEnabled(); } diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h index 9be2240f6f..5bdbcdfcf8 100644 --- a/indra/llui/llfloater.h +++ b/indra/llui/llfloater.h @@ -46,24 +46,24 @@ class LLMultiFloater; class LLFloater; -const bool RESIZE_YES = true; -const bool RESIZE_NO = false; +constexpr bool RESIZE_YES = true; +constexpr bool RESIZE_NO = false; -const bool DRAG_ON_TOP = false; -const bool DRAG_ON_LEFT = true; +constexpr bool DRAG_ON_TOP = false; +constexpr bool DRAG_ON_LEFT = true; -const bool MINIMIZE_YES = true; -const bool MINIMIZE_NO = false; +constexpr bool MINIMIZE_YES = true; +constexpr bool MINIMIZE_NO = false; -const bool CLOSE_YES = true; -const bool CLOSE_NO = false; +constexpr bool CLOSE_YES = true; +constexpr bool CLOSE_NO = false; -const bool ADJUST_VERTICAL_YES = true; -const bool ADJUST_VERTICAL_NO = false; +constexpr bool ADJUST_VERTICAL_YES = true; +constexpr bool ADJUST_VERTICAL_NO = false; -const F32 CONTEXT_CONE_IN_ALPHA = 0.f; -const F32 CONTEXT_CONE_OUT_ALPHA = 1.f; -const F32 CONTEXT_CONE_FADE_TIME = .08f; +constexpr F32 CONTEXT_CONE_IN_ALPHA = 0.f; +constexpr F32 CONTEXT_CONE_OUT_ALPHA = 1.f; +constexpr F32 CONTEXT_CONE_FADE_TIME = .08f; namespace LLFloaterEnums { @@ -228,7 +228,7 @@ public: /*virtual*/ void setIsChrome(bool is_chrome); /*virtual*/ void setRect(const LLRect &rect); void setIsSingleInstance(bool is_single_instance); - bool getIsSingleInstance() { return mSingleInstance; } + bool getIsSingleInstance() const { return mSingleInstance; } void initFloater(const Params& p); @@ -274,17 +274,17 @@ public: static bool isShown(const LLFloater* floater); static bool isVisible(const LLFloater* floater); static bool isMinimized(const LLFloater* floater); - bool isFirstLook() { return mFirstLook; } // EXT-2653: This function is necessary to prevent overlapping for secondary showed toasts + bool isFirstLook() const { return mFirstLook; } // EXT-2653: This function is necessary to prevent overlapping for secondary showed toasts virtual bool isFrontmost(); - bool isDependent() { return !mDependeeHandle.isDead(); } + bool isDependent() const { return !mDependeeHandle.isDead(); } void setCanMinimize(bool can_minimize); void setCanClose(bool can_close); void setCanTearOff(bool can_tear_off); virtual void setCanResize(bool can_resize); void setCanDrag(bool can_drag); - bool getCanDrag(); + bool getCanDrag() const; void setHost(LLMultiFloater* host); - bool isResizable() const { return mResizable; } + bool isResizable() const { return mResizable; } void setResizeLimits( S32 min_width, S32 min_height ); void getResizeLimits( S32* min_width, S32* min_height ) { *min_width = mMinWidth; *min_height = mMinHeight; } @@ -347,7 +347,7 @@ public: virtual void setDocked(bool docked, bool pop_on_undock = true); virtual void setTornOff(bool torn_off) { mTornOff = torn_off; } - bool isTornOff() {return mTornOff;} + bool isTornOff() const { return mTornOff; } void setOpenPositioning(LLFloaterEnums::EOpenPositioning pos) {mPositioning = pos;} @@ -423,7 +423,6 @@ protected: private: void setForeground(bool b); // called only by floaterview void cleanupHandles(); // remove handles to dead floaters - void createMinimizeButton(); void buildButtons(const Params& p); // Images and tooltips are named in the XML, but we want to look them diff --git a/indra/llui/llfloaterreglistener.h b/indra/llui/llfloaterreglistener.h index 42e7178cbc..7c975edaea 100644 --- a/indra/llui/llfloaterreglistener.h +++ b/indra/llui/llfloaterreglistener.h @@ -30,7 +30,6 @@ #define LL_LLFLOATERREGLISTENER_H #include "lleventapi.h" -#include <string> class LLSD; diff --git a/indra/llui/llflyoutbutton.h b/indra/llui/llflyoutbutton.h index 7a49501318..73190fc984 100644 --- a/indra/llui/llflyoutbutton.h +++ b/indra/llui/llflyoutbutton.h @@ -54,7 +54,7 @@ protected: LLFlyoutButton(const Params&); friend class LLUICtrlFactory; public: - virtual void draw(); + void draw() override; void setToggleState(bool state); diff --git a/indra/llui/llfocusmgr.h b/indra/llui/llfocusmgr.h index 1fa0ac137e..89fee5c9f1 100644 --- a/indra/llui/llfocusmgr.h +++ b/indra/llui/llfocusmgr.h @@ -97,7 +97,7 @@ public: LLFocusableElement* getLastKeyboardFocus() const { return mLastKeyboardFocus; } bool childHasKeyboardFocus( const LLView* parent ) const; void removeKeyboardFocusWithoutCallback( const LLFocusableElement* focus ); - bool getKeystrokesOnly() { return mKeystrokesOnly; } + bool getKeystrokesOnly() const { return mKeystrokesOnly; } void setKeystrokesOnly(bool keystrokes_only) { mKeystrokesOnly = keystrokes_only; } F32 getFocusFlashAmt() const; diff --git a/indra/llui/llfolderview.h b/indra/llui/llfolderview.h index 62ef2a0626..e78dbf1e77 100644 --- a/indra/llui/llfolderview.h +++ b/indra/llui/llfolderview.h @@ -124,11 +124,11 @@ public: void setSelectCallback(const signal_t::slot_type& cb) { mSelectSignal.connect(cb); } void setReshapeCallback(const signal_t::slot_type& cb) { mReshapeSignal.connect(cb); } - bool getAllowMultiSelect() { return mAllowMultiSelect; } - bool getAllowDrag() { return mAllowDrag; } + bool getAllowMultiSelect() const { return mAllowMultiSelect; } + bool getAllowDrag() const { return mAllowDrag; } void setSingleFolderMode(bool is_single_mode) { mSingleFolderMode = is_single_mode; } - bool isSingleFolderMode() { return mSingleFolderMode; } + bool isSingleFolderMode() const { return mSingleFolderMode; } // Close all folders in the view void closeAllFolders(); @@ -142,7 +142,7 @@ public: virtual S32 getItemHeight() const; void arrangeAll() { mArrangeGeneration++; } - S32 getArrangeGeneration() { return mArrangeGeneration; } + S32 getArrangeGeneration() const { return mArrangeGeneration; } // applies filters to control visibility of items virtual void filter( LLFolderViewFilter& filter); @@ -227,27 +227,27 @@ public: void setShowSelectionContext(bool show) { mShowSelectionContext = show; } bool getShowSelectionContext(); void setShowSingleSelection(bool show); - bool getShowSingleSelection() { return mShowSingleSelection; } - F32 getSelectionFadeElapsedTime() { return mMultiSelectionFadeTimer.getElapsedTimeF32(); } - bool getUseEllipses() { return mUseEllipses; } - S32 getSelectedCount() { return (S32)mSelectedItems.size(); } + bool getShowSingleSelection() const { return mShowSingleSelection; } + F32 getSelectionFadeElapsedTime() const { return mMultiSelectionFadeTimer.getElapsedTimeF32(); } + bool getUseEllipses() const { return mUseEllipses; } + S32 getSelectedCount() const { return (S32)mSelectedItems.size(); } - void update(); // needs to be called periodically (e.g. once per frame) + void update(); // needs to be called periodically (e.g. once per frame) - bool needsAutoSelect() { return mNeedsAutoSelect && !mAutoSelectOverride; } - bool needsAutoRename() { return mNeedsAutoRename; } + bool needsAutoSelect() const { return mNeedsAutoSelect && !mAutoSelectOverride; } + bool needsAutoRename() const { return mNeedsAutoRename; } void setNeedsAutoRename(bool val) { mNeedsAutoRename = val; } void setPinningSelectedItem(bool val) { mPinningSelectedItem = val; } void setAutoSelectOverride(bool val) { mAutoSelectOverride = val; } - bool showItemLinkOverlays() { return mShowItemLinkOverlays; } + bool showItemLinkOverlays() const { return mShowItemLinkOverlays; } void setCallbackRegistrar(LLUICtrl::CommitCallbackRegistry::ScopedRegistrar* registrar) { mCallbackRegistrar = registrar; } void setEnableRegistrar(LLUICtrl::EnableCallbackRegistry::ScopedRegistrar* registrar) { mEnableRegistrar = registrar; } void setForceArrange(bool force) { mForceArrange = force; } - LLPanel* getParentPanel() { return mParentPanel.get(); } + LLPanel* getParentPanel() const { return mParentPanel.get(); } // DEBUG only void dumpSelectionInformation(); @@ -255,7 +255,7 @@ public: void setShowEmptyMessage(bool show_msg) { mShowEmptyMessage = show_msg; } - bool useLabelSuffix() { return mUseLabelSuffix; } + bool useLabelSuffix() const { return mUseLabelSuffix; } virtual void updateMenu(); void finishRenamingItem( void ); @@ -390,7 +390,7 @@ public: virtual ~LLSelectFirstFilteredItem() {} virtual void doFolder(LLFolderViewFolder* folder); virtual void doItem(LLFolderViewItem* item); - bool wasItemSelected() { return mItemSelected || mFolderSelected; } + bool wasItemSelected() const { return mItemSelected || mFolderSelected; } protected: bool mItemSelected; bool mFolderSelected; diff --git a/indra/llui/llfolderviewitem.h b/indra/llui/llfolderviewitem.h index cc8a7d934c..234d0dc7f9 100644 --- a/indra/llui/llfolderviewitem.h +++ b/indra/llui/llfolderviewitem.h @@ -282,7 +282,7 @@ public: // Does not need filter update virtual void refreshSuffix(); - bool isSingleFolderMode() { return mSingleFolderMode; } + bool isSingleFolderMode() const { return mSingleFolderMode; } // LLView functionality virtual bool handleRightMouseDown( S32 x, S32 y, MASK mask ); @@ -415,9 +415,6 @@ public: // doesn't delete it. virtual void extractItem( LLFolderViewItem* item, bool deparent_model = true); - // This function is called by a child that needs to be resorted. - void resort(LLFolderViewItem* item); - void setAutoOpenCountdown(F32 countdown) { mAutoOpenCountdown = countdown; } // folders can be opened. This will usually be called by internal diff --git a/indra/llui/llkeywords.cpp b/indra/llui/llkeywords.cpp index 7bf43c22c1..2bea8fb4ed 100644 --- a/indra/llui/llkeywords.cpp +++ b/indra/llui/llkeywords.cpp @@ -170,7 +170,7 @@ std::string LLKeywords::getAttribute(std::string_view key) return (it != mAttributes.end()) ? it->second : ""; } -LLUIColor LLKeywords::getColorGroup(std::string_view key_in) +LLUIColor LLKeywords::getColorGroup(std::string_view key_in) const { std::string color_group = "ScriptText"; if (key_in == "functions") diff --git a/indra/llui/llkeywords.h b/indra/llui/llkeywords.h index 328561c92a..5892238593 100644 --- a/indra/llui/llkeywords.h +++ b/indra/llui/llkeywords.h @@ -111,8 +111,8 @@ public: ~LLKeywords(); void clearLoaded() { mLoaded = false; } - LLUIColor getColorGroup(std::string_view key_in); - bool isLoaded() const { return mLoaded; } + LLUIColor getColorGroup(std::string_view key_in) const; + bool isLoaded() const { return mLoaded; } void findSegments(std::vector<LLTextSegmentPtr> *seg_list, const LLWString& text, diff --git a/indra/llui/lllayoutstack.cpp b/indra/llui/lllayoutstack.cpp index 1c59938f90..fe0591ce4b 100644 --- a/indra/llui/lllayoutstack.cpp +++ b/indra/llui/lllayoutstack.cpp @@ -36,8 +36,8 @@ #include "lliconctrl.h" #include "boost/foreach.hpp" -static const F32 MIN_FRACTIONAL_SIZE = 0.00001f; -static const F32 MAX_FRACTIONAL_SIZE = 1.f; +static constexpr F32 MIN_FRACTIONAL_SIZE = 0.00001f; +static constexpr F32 MAX_FRACTIONAL_SIZE = 1.f; static LLDefaultChildRegistry::Register<LLLayoutStack> register_layout_stack("layout_stack"); static LLLayoutStack::LayoutStackRegistry::Register<LLLayoutPanel> register_layout_panel("layout_panel"); diff --git a/indra/llui/lllayoutstack.h b/indra/llui/lllayoutstack.h index 8459921c60..9e3536aaff 100644 --- a/indra/llui/lllayoutstack.h +++ b/indra/llui/lllayoutstack.h @@ -75,9 +75,6 @@ public: /*virtual*/ bool addChild(LLView* child, S32 tab_group = 0); /*virtual*/ void reshape(S32 width, S32 height, bool called_from_parent = true); - - static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr output_node = NULL); - typedef enum e_animate { NO_ANIMATE, @@ -86,7 +83,7 @@ public: void addPanel(LLLayoutPanel* panel, EAnimate animate = NO_ANIMATE); void collapsePanel(LLPanel* panel, bool collapsed = true); - S32 getNumPanels() { return static_cast<S32>(mPanels.size()); } + S32 getNumPanels() const { return static_cast<S32>(mPanels.size()); } void updateLayout(); @@ -190,7 +187,6 @@ public: bool isCollapsed() const { return mCollapsed;} void setOrientation(LLView::EOrientation orientation); - void storeOriginalDim(); void setIgnoreReshape(bool ignore) { mIgnoreReshape = ignore; } diff --git a/indra/llui/lllineeditor.h b/indra/llui/lllineeditor.h index 12fe800acb..7533f76f1d 100644 --- a/indra/llui/lllineeditor.h +++ b/indra/llui/lllineeditor.h @@ -306,8 +306,6 @@ public: S32 calcCursorPos(S32 mouse_x); bool handleSpecialKey(KEY key, MASK mask); bool handleSelectionKey(KEY key, MASK mask); - bool handleControlKey(KEY key, MASK mask); - S32 handleCommitKey(KEY key, MASK mask); void updateTextPadding(); // Draw the background image depending on enabled/focused state. @@ -444,7 +442,7 @@ private: mText = ed->getText(); } - void doRollback( LLLineEditor* ed ) + void doRollback(LLLineEditor* ed) const { ed->mCursorPos = mCursorPos; ed->mScrollHPos = mScrollHPos; @@ -455,7 +453,7 @@ private: ed->mPrevText = mText; } - std::string getText() { return mText; } + std::string getText() const { return mText; } private: std::string mText; diff --git a/indra/llui/llmenubutton.h b/indra/llui/llmenubutton.h index a77ae7dae7..3f96b28246 100644 --- a/indra/llui/llmenubutton.h +++ b/indra/llui/llmenubutton.h @@ -65,8 +65,8 @@ public: boost::signals2::connection setMouseDownCallback( const mouse_signal_t::slot_type& cb ); - /*virtual*/ bool handleMouseDown(S32 x, S32 y, MASK mask); - /*virtual*/ bool handleKeyHere(KEY key, MASK mask ); + bool handleMouseDown(S32 x, S32 y, MASK mask) override; + bool handleKeyHere(KEY key, MASK mask) override; void hideMenu(); diff --git a/indra/llui/llmenugl.h b/indra/llui/llmenugl.h index 88608b20ab..e31cb184e5 100644 --- a/indra/llui/llmenugl.h +++ b/indra/llui/llmenugl.h @@ -439,8 +439,6 @@ protected: public: virtual ~LLMenuGL( void ); - void parseChildXML(LLXMLNodePtr child, LLView* parent); - // LLView Functionality /*virtual*/ bool handleUnicodeCharHere( llwchar uni_char ); /*virtual*/ bool handleHover( S32 x, S32 y, MASK mask ); diff --git a/indra/llui/llmultifloater.cpp b/indra/llui/llmultifloater.cpp index a7f9b8b2d9..f53e22c349 100644 --- a/indra/llui/llmultifloater.cpp +++ b/indra/llui/llmultifloater.cpp @@ -390,7 +390,7 @@ LLFloater* LLMultiFloater::getActiveFloater() return (LLFloater*)mTabContainer->getCurrentPanel(); } -S32 LLMultiFloater::getFloaterCount() +S32 LLMultiFloater::getFloaterCount() const { return mTabContainer->getTabCount(); } diff --git a/indra/llui/llmultifloater.h b/indra/llui/llmultifloater.h index eb0f917695..e0cd58aa3f 100644 --- a/indra/llui/llmultifloater.h +++ b/indra/llui/llmultifloater.h @@ -66,7 +66,7 @@ public: virtual LLFloater* getActiveFloater(); virtual bool isFloaterFlashing(LLFloater* floaterp); - virtual S32 getFloaterCount(); + virtual S32 getFloaterCount() const; virtual void setFloaterFlashing(LLFloater* floaterp, bool flashing); virtual bool closeAllFloaters(); //Returns false if the floater could not be closed due to pending confirmation dialogs diff --git a/indra/llui/llmultislider.h b/indra/llui/llmultislider.h index b2bfc8bc84..af255bcc8f 100644 --- a/indra/llui/llmultislider.h +++ b/indra/llui/llmultislider.h @@ -117,10 +117,10 @@ public: /*virtual*/ void onMouseLeave(S32 x, S32 y, MASK mask) override; /*virtual*/ void draw() override; - S32 getMaxNumSliders() { return mMaxNumSliders; } - S32 getCurNumSliders() { return static_cast<S32>(mValue.size()); } - F32 getOverlapThreshold() { return mOverlapThreshold; } - bool canAddSliders() { return mValue.size() < mMaxNumSliders; } + S32 getMaxNumSliders() const { return mMaxNumSliders; } + S32 getCurNumSliders() const { return static_cast<S32>(mValue.size()); } + F32 getOverlapThreshold() const { return mOverlapThreshold; } + bool canAddSliders() const { return mValue.size() < mMaxNumSliders; } protected: diff --git a/indra/llui/llmultisliderctrl.h b/indra/llui/llmultisliderctrl.h index dec6cb48b9..2c2bc5e4d9 100644 --- a/indra/llui/llmultisliderctrl.h +++ b/indra/llui/llmultisliderctrl.h @@ -124,10 +124,10 @@ public: F32 getMinValue() const { return mMultiSlider->getMinValue(); } F32 getMaxValue() const { return mMultiSlider->getMaxValue(); } - S32 getMaxNumSliders() { return mMultiSlider->getMaxNumSliders(); } - S32 getCurNumSliders() { return mMultiSlider->getCurNumSliders(); } - F32 getOverlapThreshold() { return mMultiSlider->getOverlapThreshold(); } - bool canAddSliders() { return mMultiSlider->canAddSliders(); } + S32 getMaxNumSliders() const { return mMultiSlider->getMaxNumSliders(); } + S32 getCurNumSliders() const { return mMultiSlider->getCurNumSliders(); } + F32 getOverlapThreshold() const { return mMultiSlider->getOverlapThreshold(); } + bool canAddSliders() const { return mMultiSlider->canAddSliders(); } void setLabel(const std::string& label) { if (mLabelBox) mLabelBox->setText(label); } void setLabelColor(const LLUIColor& c) { mTextEnabledColor = c; } @@ -147,7 +147,6 @@ public: static void onEditorCommit(LLUICtrl* ctrl, const LLSD& userdata); static void onEditorGainFocus(LLFocusableElement* caller, void *userdata); - static void onEditorChangeFocus(LLUICtrl* caller, S32 direction, void *userdata); private: void updateText(); diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h index 9b83da13ad..ef0762fc17 100644 --- a/indra/llui/llnotifications.h +++ b/indra/llui/llnotifications.h @@ -247,7 +247,6 @@ public: LLNotificationForm(const LLSD& sd); LLNotificationForm(const std::string& name, const Params& p); - void fromLLSD(const LLSD& sd); LLSD asLLSD() const; S32 getNumElements() { return static_cast<S32>(mFormData.size()); } @@ -266,8 +265,8 @@ public: bool getIgnored(); void setIgnored(bool ignored); - EIgnoreType getIgnoreType() { return mIgnore; } - std::string getIgnoreMessage() { return mIgnoreMsg; } + EIgnoreType getIgnoreType()const { return mIgnore; } + std::string getIgnoreMessage() const { return mIgnoreMsg; } private: LLSD mFormData; @@ -971,8 +970,6 @@ private: /*virtual*/ void initSingleton() override; /*virtual*/ void cleanupSingleton() override; - void loadPersistentNotifications(); - bool expirationFilter(LLNotificationPtr pNotification); bool expirationHandler(const LLSD& payload); bool uniqueFilter(LLNotificationPtr pNotification); diff --git a/indra/llui/llprogressbar.h b/indra/llui/llprogressbar.h index 0d5d32cf21..7245bbf1cf 100644 --- a/indra/llui/llprogressbar.h +++ b/indra/llui/llprogressbar.h @@ -48,9 +48,9 @@ public: LLProgressBar(const Params&); virtual ~LLProgressBar(); - void setValue(const LLSD& value); + void setValue(const LLSD& value) override; - /*virtual*/ void draw(); + void draw() override; private: F32 mPercentDone; diff --git a/indra/llui/llresizebar.h b/indra/llui/llresizebar.h index 4b0f435834..68bf0fd95e 100644 --- a/indra/llui/llresizebar.h +++ b/indra/llui/llresizebar.h @@ -61,7 +61,7 @@ public: void setResizeLimits( S32 min_size, S32 max_size ) { mMinSize = min_size; mMaxSize = max_size; } void setEnableSnapping(bool enable) { mSnappingEnabled = enable; } void setAllowDoubleClickSnapping(bool allow) { mAllowDoubleClickSnapping = allow; } - bool canResize() { return getEnabled() && mMaxSize > mMinSize; } + bool canResize() const { return getEnabled() && mMaxSize > mMinSize; } void setResizeListener(boost::function<void(void*)> listener) {mResizeListener = listener;} void setImagePanel(LLPanel * panelp); LLPanel * getImagePanel() const; diff --git a/indra/llui/llresizehandle.h b/indra/llui/llresizehandle.h index 9cc4123544..caec33405c 100644 --- a/indra/llui/llresizehandle.h +++ b/indra/llui/llresizehandle.h @@ -50,10 +50,10 @@ protected: LLResizeHandle(const LLResizeHandle::Params&); friend class LLUICtrlFactory; public: - virtual void draw(); - virtual bool handleHover(S32 x, S32 y, MASK mask); - virtual bool handleMouseDown(S32 x, S32 y, MASK mask); - virtual bool handleMouseUp(S32 x, S32 y, MASK mask); + void draw() override; + bool handleHover(S32 x, S32 y, MASK mask) override; + bool handleMouseDown(S32 x, S32 y, MASK mask) override; + bool handleMouseUp(S32 x, S32 y, MASK mask) override; void setResizeLimits( S32 min_width, S32 min_height ) { mMinWidth = min_width; mMinHeight = min_height; } @@ -71,8 +71,8 @@ private: const ECorner mCorner; }; -const S32 RESIZE_HANDLE_HEIGHT = 11; -const S32 RESIZE_HANDLE_WIDTH = 11; +constexpr S32 RESIZE_HANDLE_HEIGHT = 11; +constexpr S32 RESIZE_HANDLE_WIDTH = 11; #endif // LL_RESIZEHANDLE_H diff --git a/indra/llui/llrngwriter.h b/indra/llui/llrngwriter.h index 33ec049a1a..2c39472607 100644 --- a/indra/llui/llrngwriter.h +++ b/indra/llui/llrngwriter.h @@ -37,7 +37,7 @@ public: void writeRNG(const std::string& name, LLXMLNodePtr node, const LLInitParam::BaseBlock& block, const std::string& xml_namespace); void addDefinition(const std::string& type_name, const LLInitParam::BaseBlock& block); - /*virtual*/ std::string getCurrentElementName() { return LLStringUtil::null; } + std::string getCurrentElementName() override { return LLStringUtil::null; } LLRNGWriter(); diff --git a/indra/llui/llscrolllistcell.h b/indra/llui/llscrolllistcell.h index e7ff5c8424..7dded3c0b7 100644 --- a/indra/llui/llscrolllistcell.h +++ b/indra/llui/llscrolllistcell.h @@ -105,7 +105,7 @@ public: virtual const LLSD getAltValue() const; virtual void setValue(const LLSD& value) { } virtual void setAltValue(const LLSD& value) { } - virtual const std::string &getToolTip() const { return mToolTip; } + virtual const std::string& getToolTip() const { return mToolTip; } virtual void setToolTip(const std::string &str) { mToolTip = str; } virtual bool getVisible() const { return true; } virtual void setWidth(S32 width) { mWidth = width; } diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp index ea2caaa1c0..ddd1d81cb4 100644 --- a/indra/llui/llscrolllistctrl.cpp +++ b/indra/llui/llscrolllistctrl.cpp @@ -326,17 +326,11 @@ S32 LLScrollListCtrl::getSearchColumn() } return llclamp(mSearchColumn, 0, getNumColumns()); } -/*virtual*/ + +// virtual bool LLScrollListCtrl::preProcessChildNode(LLXMLNodePtr child) { - if (child->hasName("column") || child->hasName("row")) - { - return true; // skip - } - else - { - return false; - } + return child->hasName("column") || child->hasName("row"); } LLScrollListCtrl::~LLScrollListCtrl() @@ -356,7 +350,6 @@ LLScrollListCtrl::~LLScrollListCtrl() } } - bool LLScrollListCtrl::setMaxItemCount(S32 max_count) { if (max_count >= getItemCount()) @@ -379,10 +372,9 @@ S32 LLScrollListCtrl::getItemCount() const bool LLScrollListCtrl::hasSelectedItem() const { item_list::iterator iter; - for (iter = mItemList.begin(); iter < mItemList.end(); ) + for (LLScrollListItem* item : mItemList) { - LLScrollListItem* itemp = *iter; - if (itemp && itemp->getSelected()) + if (item->getSelected()) { return true; } @@ -396,7 +388,6 @@ void LLScrollListCtrl::clearRows() { std::for_each(mItemList.begin(), mItemList.end(), DeletePointer()); mItemList.clear(); - //mItemCount = 0; // Scroll the bar back up to the top. mScrollbar->setDocParams(0, 0); @@ -407,7 +398,6 @@ void LLScrollListCtrl::clearRows() mDirty = false; } - LLScrollListItem* LLScrollListCtrl::getFirstSelected() const { for (LLScrollListItem* item : mItemList) @@ -444,14 +434,12 @@ S32 LLScrollListCtrl::getNumSelected() const ++numSelected; } } - return numSelected; } S32 LLScrollListCtrl::getFirstSelectedIndex() const { S32 CurSelectedIndex = 0; - // make sure sort is up to date before returning an index updateSort(); @@ -463,7 +451,6 @@ S32 LLScrollListCtrl::getFirstSelectedIndex() const } CurSelectedIndex++; } - return -1; } @@ -477,6 +464,15 @@ LLScrollListItem* LLScrollListCtrl::getLastData() const return mItemList.empty() ? NULL : mItemList.back(); } +LLScrollListItem* LLScrollListCtrl::getNthData(size_t index) const +{ + if (mItemList.size() <= index) + { + return NULL; + } + return mItemList[index]; +} + std::vector<LLScrollListItem*> LLScrollListCtrl::getAllData() const { std::vector<LLScrollListItem*> ret; @@ -490,12 +486,12 @@ std::vector<LLScrollListItem*> LLScrollListCtrl::getAllData() const // returns first matching item LLScrollListItem* LLScrollListCtrl::getItem(const LLSD& sd) const { - const std::string& string_val = sd.asStringRef(); + std::string string_val = sd.asString(); for (LLScrollListItem* item : mItemList) { // assumes string representation is good enough for comparison - if (item->getValue().asStringRef() == string_val) + if (item->getValue().asString() == string_val) { return item; } @@ -1052,7 +1048,7 @@ S32 LLScrollListCtrl::selectMultiple( uuid_vec_t ids ) { LLScrollListItem* item = *iter; uuid_vec_t::iterator iditr; - for(iditr = ids.begin(); iditr != ids.end(); ++iditr) + for (iditr = ids.begin(); iditr != ids.end(); ++iditr) { if (item->getEnabled() && (item->getUUID() == (*iditr))) { @@ -1062,7 +1058,10 @@ S32 LLScrollListCtrl::selectMultiple( uuid_vec_t ids ) break; } } - if(ids.end() != iditr) ids.erase(iditr); + if (ids.end() != iditr) + { + ids.erase(iditr); + } } if (mCommitOnSelectionChange) @@ -1077,11 +1076,9 @@ S32 LLScrollListCtrl::getItemIndex( LLScrollListItem* target_item ) const updateSort(); S32 index = 0; - item_list::const_iterator iter; - for (iter = mItemList.begin(); iter != mItemList.end(); iter++) + for (LLScrollListItem* item : mItemList) { - LLScrollListItem *itemp = *iter; - if (target_item == itemp) + if (target_item == item) { return index; } @@ -1095,11 +1092,9 @@ S32 LLScrollListCtrl::getItemIndex( const LLUUID& target_id ) const updateSort(); S32 index = 0; - item_list::const_iterator iter; - for (iter = mItemList.begin(); iter != mItemList.end(); iter++) + for (LLScrollListItem* item : mItemList) { - LLScrollListItem *itemp = *iter; - if (target_id == itemp->getUUID()) + if (target_id == item->getUUID()) { return index; } @@ -1122,10 +1117,8 @@ void LLScrollListCtrl::selectPrevItem( bool extend_selection) updateSort(); item_list::iterator iter; - for (iter = mItemList.begin(); iter != mItemList.end(); iter++) + for (LLScrollListItem* cur_item : mItemList) { - LLScrollListItem* cur_item = *iter; - if (cur_item->getSelected()) { if (prev_item) @@ -1164,11 +1157,8 @@ void LLScrollListCtrl::selectNextItem( bool extend_selection) { updateSort(); - item_list::reverse_iterator iter; - for (iter = mItemList.rbegin(); iter != mItemList.rend(); iter++) + for (LLScrollListItem* cur_item : mItemList) { - LLScrollListItem* cur_item = *iter; - if (cur_item->getSelected()) { if (next_item) @@ -1197,10 +1187,8 @@ void LLScrollListCtrl::selectNextItem( bool extend_selection) void LLScrollListCtrl::deselectAllItems(bool no_commit_on_change) { - item_list::iterator iter; - for (iter = mItemList.begin(); iter != mItemList.end(); iter++) + for (LLScrollListItem* item : mItemList) { - LLScrollListItem* item = *iter; deselectItem(item); } @@ -1725,6 +1713,16 @@ void LLScrollListCtrl::setEnabled(bool enabled) mCanSelect = enabled; setTabStop(enabled); mScrollbar->setTabStop(!enabled && mScrollbar->getPageSize() < mScrollbar->getDocSize()); + + // when the table is disabled also disable its items + for (LLScrollListItem* item : mItemList) + { + item->setEnabled(enabled); + if (!enabled) + { + item->setSelected(false); + } + } } bool LLScrollListCtrl::handleScrollWheel(S32 x, S32 y, S32 clicks) @@ -2624,7 +2622,9 @@ bool LLScrollListCtrl::isRepeatedChars(const LLWString& string) const void LLScrollListCtrl::selectItem(LLScrollListItem* itemp, S32 cell, bool select_single_item) { - if (itemp && !itemp->getSelected()) + if (!itemp) return; + + if (!itemp->getSelected() || itemp->getSelectedCell() != cell) { if (mLastSelected) { @@ -2900,11 +2900,9 @@ bool LLScrollListCtrl::canCut() const void LLScrollListCtrl::selectAll() { // Deselects all other items - item_list::iterator iter; - for (iter = mItemList.begin(); iter != mItemList.end(); iter++) + for (LLScrollListItem* itemp : mItemList) { - LLScrollListItem *itemp = *iter; - if( itemp->getEnabled() ) + if (itemp->getEnabled()) { selectItem(itemp, -1, false); } @@ -2944,7 +2942,8 @@ void LLScrollListCtrl::addColumn(const LLSD& column, EAddPosition pos) void LLScrollListCtrl::addColumn(const LLScrollListColumn::Params& column_params, EAddPosition pos) { - if (!column_params.validateBlock()) return; + if (!column_params.validateBlock()) + return; std::string name = column_params.name; // if no column name provided, just use ordinal as name @@ -2971,7 +2970,7 @@ void LLScrollListCtrl::addColumn(const LLScrollListColumn::Params& column_params { new_column->setWidth((S32)ll_round(new_column->mRelWidth*mItemListRect.getWidth())); } - else if(new_column->mDynamicWidth) + else if (new_column->mDynamicWidth) { mNumDynamicWidthColumns++; new_column->setWidth((mItemListRect.getWidth() - mTotalStaticColumnWidth - mTotalColumnPadding) / mNumDynamicWidthColumns); @@ -2979,14 +2978,12 @@ void LLScrollListCtrl::addColumn(const LLScrollListColumn::Params& column_params S32 top = mItemListRect.mTop; S32 left = mItemListRect.mLeft; - for (column_map_t::iterator itor = mColumns.begin(); - itor != mColumns.end(); - ++itor) + for (const auto& data_pair : mColumns) { - if (itor->second->mIndex < new_column->mIndex && - itor->second->getWidth() > 0) + if (data_pair.second->mIndex < new_column->mIndex && + data_pair.second->getWidth() > 0) { - left += itor->second->getWidth() + mColumnPadding; + left += data_pair.second->getWidth() + mColumnPadding; } } @@ -3152,17 +3149,16 @@ LLScrollListItem* LLScrollListCtrl::addRow(const LLScrollListItem::Params& item_ LLScrollListItem* LLScrollListCtrl::addRow(LLScrollListItem *new_item, const LLScrollListItem::Params& item_p, EAddPosition pos) { LL_PROFILE_ZONE_SCOPED_CATEGORY_UI; - if (!item_p.validateBlock() || !new_item) return NULL; - new_item->setNumColumns(static_cast<S32>(mColumns.size())); + if (!item_p.validateBlock() || !new_item) + return nullptr; + + new_item->setNumColumns((S32)mColumns.size()); // Add any columns we don't already have S32 col_index = 0; - for(LLInitParam::ParamIterator<LLScrollListCell::Params>::const_iterator itor = item_p.columns.begin(); - itor != item_p.columns.end(); - ++itor) + for (LLScrollListCell::Params cell_p : item_p.columns) { - LLScrollListCell::Params cell_p = *itor; std::string column = cell_p.column; // empty columns strings index by ordinal @@ -3224,8 +3220,7 @@ LLScrollListItem* LLScrollListCtrl::addRow(LLScrollListItem *new_item, const LLS new_item->setNumColumns(static_cast<S32>(mColumns.size())); } - LLScrollListCell* cell = LLScrollListCell::create(LLScrollListCell::Params().value(item_p.value)); - if (cell) + if (LLScrollListCell* cell = LLScrollListCell::create(LLScrollListCell::Params().value(item_p.value))) { LLScrollListColumn* columnp = mColumns.begin()->second; @@ -3240,15 +3235,13 @@ LLScrollListItem* LLScrollListCtrl::addRow(LLScrollListItem *new_item, const LLS } // add dummy cells for missing columns - for (column_map_t::iterator column_it = mColumns.begin(); column_it != mColumns.end(); ++column_it) + for (const auto& column_it : mColumns) { - S32 column_idx = column_it->second->mIndex; + S32 column_idx = column_it.second->mIndex; if (new_item->getColumn(column_idx) == NULL) { - LLScrollListColumn* column_ptr = column_it->second; LLScrollListCell::Params cell_p; - cell_p.width = column_ptr->getWidth(); - + cell_p.width = column_it.second->getWidth(); new_item->setColumn(column_idx, new LLScrollListSpacer(cell_p)); } } diff --git a/indra/llui/llscrolllistctrl.h b/indra/llui/llscrolllistctrl.h index c24784338a..bfae08ab5b 100644 --- a/indra/llui/llscrolllistctrl.h +++ b/indra/llui/llscrolllistctrl.h @@ -165,7 +165,6 @@ public: void deleteAllItems() { clearRows(); } // Sets an array of column descriptors - void setColumnHeadings(const LLSD& headings); void sortByColumnIndex(U32 column, bool ascending); // LLCtrlListInterface functions @@ -291,6 +290,7 @@ public: // iterate over all items LLScrollListItem* getFirstData() const; LLScrollListItem* getLastData() const; + LLScrollListItem* getNthData(size_t index) const; std::vector<LLScrollListItem*> getAllData() const; LLScrollListItem* getItem(const LLSD& sd) const; @@ -318,7 +318,7 @@ public: void setAllowKeyboardMovement(bool b) { mAllowKeyboardMovement = b; } void setMaxSelectable(U32 max_selected) { mMaxSelectable = max_selected; } - S32 getMaxSelectable() { return mMaxSelectable; } + S32 getMaxSelectable() const { return mMaxSelectable; } virtual S32 getScrollPos() const; @@ -334,7 +334,7 @@ public: // support right-click context menus for avatar/group lists enum ContextMenuType { MENU_NONE, MENU_AVATAR, MENU_GROUP }; void setContextMenu(const ContextMenuType &menu) { mContextMenuType = menu; } - ContextMenuType getContextMenuType() { return mContextMenuType; } + ContextMenuType getContextMenuType() const { return mContextMenuType; } // Overridden from LLView /*virtual*/ void draw(); @@ -362,7 +362,6 @@ public: virtual void fitContents(S32 max_width, S32 max_height); virtual LLRect getRequiredRect(); - static bool rowPreceeds(LLScrollListItem *new_row, LLScrollListItem *test_row); LLRect getItemListRect() { return mItemListRect; } @@ -384,7 +383,6 @@ public: * then display all items. */ void setPageLines(S32 page_lines ); - void setCollapseEmptyColumns(bool collapse); LLScrollListItem* hitItem(S32 x,S32 y); virtual void scrollToShowSelected(); @@ -401,7 +399,7 @@ public: void setNumDynamicColumns(S32 num) { mNumDynamicWidthColumns = num; } void updateStaticColumnWidth(LLScrollListColumn* col, S32 new_width); - S32 getTotalStaticColumnWidth() { return mTotalStaticColumnWidth; } + S32 getTotalStaticColumnWidth() const { return mTotalStaticColumnWidth; } std::string getSortColumnName(); bool getSortAscending() { return mSortColumns.empty() ? true : mSortColumns.back().second; } diff --git a/indra/llui/llsliderctrl.h b/indra/llui/llsliderctrl.h index 311377a61f..23ce8fd955 100644 --- a/indra/llui/llsliderctrl.h +++ b/indra/llui/llsliderctrl.h @@ -132,7 +132,6 @@ public: static void onEditorCommit(LLUICtrl* ctrl, const LLSD& userdata); static void onEditorGainFocus(LLFocusableElement* caller, void *userdata); - static void onEditorChangeFocus(LLUICtrl* caller, S32 direction, void *userdata); protected: virtual std::string _getSearchText() const diff --git a/indra/llui/llspinctrl.h b/indra/llui/llspinctrl.h index 58b38dc630..4ba8c97c63 100644 --- a/indra/llui/llspinctrl.h +++ b/indra/llui/llspinctrl.h @@ -94,7 +94,6 @@ public: void onEditorCommit(const LLSD& data); static void onEditorGainFocus(LLFocusableElement* caller, void *userdata); static void onEditorLostFocus(LLFocusableElement* caller, void *userdata); - static void onEditorChangeFocus(LLUICtrl* caller, S32 direction, void *userdata); void onUpBtn(const LLSD& data); void onDownBtn(const LLSD& data); diff --git a/indra/llui/llstatbar.h b/indra/llui/llstatbar.h index c36a138566..bbbf0b3a19 100644 --- a/indra/llui/llstatbar.h +++ b/indra/llui/llstatbar.h @@ -67,7 +67,7 @@ public: void setStat(const std::string& stat_name); void setRange(F32 bar_min, F32 bar_max); - void getRange(F32& bar_min, F32& bar_max) { bar_min = mTargetMinBar; bar_max = mTargetMaxBar; } + void getRange(F32& bar_min, F32& bar_max) const { bar_min = mTargetMinBar; bar_max = mTargetMaxBar; } /*virtual*/ LLRect getRequiredRect(); // Return the height of this object, given the set options. diff --git a/indra/llui/llstatgraph.cpp b/indra/llui/llstatgraph.cpp index d97051247e..0af717d447 100644 --- a/indra/llui/llstatgraph.cpp +++ b/indra/llui/llstatgraph.cpp @@ -36,7 +36,6 @@ #include "llglheaders.h" #include "lltracerecording.h" #include "lltracethreadrecorder.h" -//#include "llviewercontrol.h" /////////////////////////////////////////////////////////////////////////////////// diff --git a/indra/llui/llstatgraph.h b/indra/llui/llstatgraph.h index c254821870..6d9e3d1064 100644 --- a/indra/llui/llstatgraph.h +++ b/indra/llui/llstatgraph.h @@ -99,9 +99,7 @@ public: void setMin(const F32 min); void setMax(const F32 max); - virtual void draw(); - - /*virtual*/ void setValue(const LLSD& value); + void draw() override; private: LLTrace::StatType<LLTrace::CountAccumulator>* mNewStatFloatp; @@ -133,9 +131,6 @@ private: }; typedef std::vector<Threshold> threshold_vec_t; threshold_vec_t mThresholds; - //S32 mNumThresholds; - //F32 mThresholds[4]; - //LLColor4 mThresholdColors[4]; }; #endif // LL_LLSTATGRAPH_H diff --git a/indra/llui/llstatview.h b/indra/llui/llstatview.h index b5187f886d..a396773057 100644 --- a/indra/llui/llstatview.h +++ b/indra/llui/llstatview.h @@ -29,7 +29,6 @@ #include "llstatbar.h" #include "llcontainerview.h" -#include <vector> class LLStatBar; diff --git a/indra/llui/llstyle.cpp b/indra/llui/llstyle.cpp index f1d57a2273..aafcfbc143 100644 --- a/indra/llui/llstyle.cpp +++ b/indra/llui/llstyle.cpp @@ -66,9 +66,9 @@ LLStyle* LLStyle::makeCopy() const copy->mDropShadow = mDropShadow; copy->mFontName = mFontName; copy->mLink = mLink; - copy->mColor = mColor; - copy->mReadOnlyColor = mReadOnlyColor; - copy->mSelectedColor = mSelectedColor; + copy->mColor.set(mColor.get()); + copy->mReadOnlyColor.set(mReadOnlyColor.get()); + copy->mSelectedColor.set(mSelectedColor.get()); copy->mFont = mFont; copy->mImagep = mImagep; copy->mAlpha = mAlpha; diff --git a/indra/llui/lltabcontainer.cpp b/indra/llui/lltabcontainer.cpp index 595ab0bd2b..7c9aa42e5f 100644 --- a/indra/llui/lltabcontainer.cpp +++ b/indra/llui/lltabcontainer.cpp @@ -1258,7 +1258,6 @@ void LLTabContainer::removeTabPanel(LLPanel* child) bool has_focus = gFocusMgr.childHasKeyboardFocus(this); - // If the tab being deleted is the selected one, select a different tab. for(std::vector<LLTabTuple*>::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter) { LLTabTuple* tuple = *iter; @@ -1296,6 +1295,7 @@ void LLTabContainer::removeTabPanel(LLPanel* child) // make sure we don't have more locked tabs than we have tabs mLockedTabCount = llmin(getTabCount(), mLockedTabCount); + // If the tab being deleted is the selected one, select a different tab. if (mCurrentTabIdx >= (S32)mTabList.size()) { mCurrentTabIdx = static_cast<S32>(mTabList.size()) - 1; @@ -1370,17 +1370,17 @@ LLPanel* LLTabContainer::getCurrentPanel() return NULL; } -S32 LLTabContainer::getCurrentPanelIndex() +S32 LLTabContainer::getCurrentPanelIndex() const { return mCurrentTabIdx; } -S32 LLTabContainer::getTabCount() +S32 LLTabContainer::getTabCount() const { return static_cast<S32>(mTabList.size()); } -LLPanel* LLTabContainer::getPanelByIndex(S32 index) +LLPanel* LLTabContainer::getPanelByIndex(S32 index) const { if (index >= 0 && index < (S32)mTabList.size()) { @@ -1389,7 +1389,7 @@ LLPanel* LLTabContainer::getPanelByIndex(S32 index) return NULL; } -S32 LLTabContainer::getIndexForPanel(LLPanel* panel) +S32 LLTabContainer::getIndexForPanel(LLPanel* panel) const { for (S32 index = 0; index < (S32)mTabList.size(); index++) { @@ -1401,7 +1401,7 @@ S32 LLTabContainer::getIndexForPanel(LLPanel* panel) return -1; } -S32 LLTabContainer::getPanelIndexByTitle(std::string_view title) +S32 LLTabContainer::getPanelIndexByTitle(std::string_view title) const { for (S32 index = 0 ; index < (S32)mTabList.size(); index++) { @@ -1723,7 +1723,7 @@ void LLTabContainer::reshapeTuple(LLTabTuple* tuple) { S32 image_overlay_width = 0; - if(mCustomIconCtrlUsed) + if (mCustomIconCtrlUsed) { LLCustomButtonIconCtrl* button = dynamic_cast<LLCustomButtonIconCtrl*>(tuple->mButton); LLIconCtrl* icon_ctrl = button ? button->getIconCtrl() : NULL; @@ -2173,12 +2173,22 @@ S32 LLTabContainer::getTotalTabWidth() const void LLTabContainer::setTabVisibility( LLPanel const *aPanel, bool aVisible ) { - for( tuple_list_t::const_iterator itr = mTabList.begin(); itr != mTabList.end(); ++itr ) + S32 num_tabs = S32(mTabList.size()); + for (S32 i = 0; i < num_tabs; ++i) { - LLTabTuple const *pTT = *itr; - if( pTT->mTabPanel == aPanel ) + LLTabTuple* tuple = mTabList[i]; + if( tuple->mTabPanel == aPanel ) { - pTT->mVisible = aVisible; + if (tuple->mVisible != aVisible) + { + tuple->mVisible = aVisible; + if (aVisible) + { + this->selectTab(i); + this->setVisible(true); + } + updateMaxScrollPos(); + } break; } } @@ -2194,11 +2204,7 @@ void LLTabContainer::setTabVisibility( LLPanel const *aPanel, bool aVisible ) break; } } - - if( foundTab ) - this->setVisible( true ); - else - this->setVisible( false ); + this->setVisible( foundTab ); updateMaxScrollPos(); } diff --git a/indra/llui/lltabcontainer.h b/indra/llui/lltabcontainer.h index 40f272ffa8..4ac7e73d25 100644 --- a/indra/llui/lltabcontainer.h +++ b/indra/llui/lltabcontainer.h @@ -182,15 +182,15 @@ public: void removeTabPanel( LLPanel* child ); void lockTabs(S32 num_tabs = 0); void unlockTabs(); - S32 getNumLockedTabs() { return mLockedTabCount; } + S32 getNumLockedTabs() const { return mLockedTabCount; } void enableTabButton(S32 which, bool enable); void deleteAllTabs(); LLPanel* getCurrentPanel(); - S32 getCurrentPanelIndex(); - S32 getTabCount(); - LLPanel* getPanelByIndex(S32 index); - S32 getIndexForPanel(LLPanel* panel); - S32 getPanelIndexByTitle(std::string_view title); + S32 getCurrentPanelIndex() const; + S32 getTabCount() const; + LLPanel* getPanelByIndex(S32 index) const; + S32 getIndexForPanel(LLPanel* panel) const; + S32 getPanelIndexByTitle(std::string_view title) const; LLPanel* getPanelByName(std::string_view name); S32 getTotalTabWidth() const; void setCurrentTabName(const std::string& name); diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h index b3fde84f5f..5cc0f03bd3 100644 --- a/indra/llui/lltextbase.h +++ b/indra/llui/lltextbase.h @@ -146,7 +146,6 @@ public: /*virtual*/ void setStyle(LLStyleConstSP style) { mStyle = style; } /*virtual*/ void setToken( LLKeywordToken* token ) { mToken = token; } /*virtual*/ LLKeywordToken* getToken() const { return mToken; } - /*virtual*/ bool getToolTip( std::string& msg ) const; /*virtual*/ void setToolTip(const std::string& tooltip); /*virtual*/ void dump() const; @@ -451,7 +450,7 @@ public: virtual void setText(const LLStringExplicit &utf8str , const LLStyle::Params& input_params = LLStyle::Params()); // uses default style /*virtual*/ const std::string& getText() const override; void setMaxTextLength(S32 length) { mMaxTextByteLength = length; } - S32 getMaxTextLength() { return mMaxTextByteLength; } + S32 getMaxTextLength() const { return mMaxTextByteLength; } // wide-char versions void setWText(const LLWString& text); @@ -490,10 +489,10 @@ public: LLRect getTextBoundingRect(); LLRect getVisibleDocumentRect() const; - S32 getVPad() { return mVPad; } - S32 getHPad() { return mHPad; } - F32 getLineSpacingMult() { return mLineSpacingMult; } - S32 getLineSpacingPixels() { return mLineSpacingPixels; } // only for multiline + S32 getVPad() const { return mVPad; } + S32 getHPad() const { return mHPad; } + F32 getLineSpacingMult() const { return mLineSpacingMult; } + S32 getLineSpacingPixels() const { return mLineSpacingPixels; } // only for multiline S32 getDocIndexFromLocalCoord( S32 local_x, S32 local_y, bool round, bool hit_past_end_of_line = true) const; LLRect getLocalRectFromDocIndex(S32 pos) const; @@ -503,7 +502,7 @@ public: bool getReadOnly() const { return mReadOnly; } void setSkipLinkUnderline(bool skip_link_underline) { mSkipLinkUnderline = skip_link_underline; } - bool getSkipLinkUnderline() { return mSkipLinkUnderline; } + bool getSkipLinkUnderline() const { return mSkipLinkUnderline; } void setParseURLs(bool parse_urls) { mParseHTML = parse_urls; } @@ -517,8 +516,8 @@ public: void endOfLine(); void startOfDoc(); void endOfDoc(); - void changePage( S32 delta ); - void changeLine( S32 delta ); + void changePage(S32 delta); + void changeLine(S32 delta); bool scrolledToStart(); bool scrolledToEnd(); @@ -680,7 +679,6 @@ protected: void appendTextImpl(const std::string &new_text, const LLStyle::Params& input_params = LLStyle::Params()); void appendAndHighlightTextImpl(const std::string &new_text, LLTextParser::EHighlightPosition highlight_part, const LLStyle::Params& style_params, bool underline_on_hover_only, std::string tooltip = LLStringUtil::null); - S32 normalizeUri(std::string& uri); protected: // virtual diff --git a/indra/llui/lltextbox.h b/indra/llui/lltextbox.h index a3cde45cd0..69a7567a44 100644 --- a/indra/llui/lltextbox.h +++ b/indra/llui/lltextbox.h @@ -46,32 +46,32 @@ protected: friend class LLUICtrlFactory; public: - virtual ~LLTextBox(); + ~LLTextBox() override; - /*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); + bool handleMouseDown(S32 x, S32 y, MASK mask) override; + bool handleMouseUp(S32 x, S32 y, MASK mask) override; + bool handleHover(S32 x, S32 y, MASK mask) override; - /*virtual*/ void setEnabled(bool enabled); + void setEnabled(bool enabled) override; - /*virtual*/ void setText( const LLStringExplicit& text, const LLStyle::Params& input_params = LLStyle::Params() ); + void setText(const LLStringExplicit& text, const LLStyle::Params& input_params = LLStyle::Params()) override; - void setRightAlign() { mHAlign = LLFontGL::RIGHT; } - void setHAlign( LLFontGL::HAlign align ) { mHAlign = align; } - void setClickedCallback( boost::function<void (void*)> cb, void* userdata = NULL ); + void setRightAlign() { mHAlign = LLFontGL::RIGHT; } + void setHAlign(LLFontGL::HAlign align) { mHAlign = align; } + void setClickedCallback(boost::function<void(void*)> cb, void* userdata = NULL); - void reshapeToFitText(bool called_from_parent = false); + void reshapeToFitText(bool called_from_parent = false); - S32 getTextPixelWidth(); - S32 getTextPixelHeight(); + S32 getTextPixelWidth(); + S32 getTextPixelHeight(); - /*virtual*/ LLSD getValue() const; - /*virtual*/ bool setTextArg( const std::string& key, const LLStringExplicit& text ); + LLSD getValue() const override; + bool setTextArg(const std::string& key, const LLStringExplicit& text) override; - void setShowCursorHand(bool show_cursor) { mShowCursorHand = show_cursor; } + void setShowCursorHand(bool show_cursor) { mShowCursorHand = show_cursor; } protected: - void onUrlLabelUpdated(const std::string &url, const std::string &label); + void onUrlLabelUpdated(const std::string& url, const std::string& label); LLUIString mText; callback_t mClickedCallback; diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp index c8cde90032..ecac800def 100644 --- a/indra/llui/lltexteditor.cpp +++ b/indra/llui/lltexteditor.cpp @@ -1594,9 +1594,7 @@ void LLTextEditor::cleanStringForPaste(LLWString & clean_string) } } - -template <> -void LLTextEditor::pasteTextWithLinebreaks<LLWString>(const LLWString & clean_string) +void LLTextEditor::pasteTextWithLinebreaksImpl(const LLWString & clean_string) { std::basic_string<llwchar>::size_type start = 0; std::basic_string<llwchar>::size_type pos = clean_string.find('\n',start); diff --git a/indra/llui/lltexteditor.h b/indra/llui/lltexteditor.h index 765c88a933..cedb79bf62 100644 --- a/indra/llui/lltexteditor.h +++ b/indra/llui/lltexteditor.h @@ -201,7 +201,6 @@ public: const LLUUID& getSourceID() const { return mSourceID; } const LLTextSegmentPtr getPreviousSegment() const; - const LLTextSegmentPtr getLastSegment() const; void getSelectedSegments(segment_vec_t& segments) const; void setShowContextMenu(bool show) { mShowContextMenu = show; } @@ -217,8 +216,6 @@ protected: void showContextMenu(S32 x, S32 y); void drawPreeditMarker(); - void assignEmbedded(const std::string &s); - void removeCharOrTab(); void indentSelectedLines( S32 spaces ); @@ -238,7 +235,6 @@ protected: void autoIndent(); - void findEmbeddedItemSegments(S32 start, S32 end); void getSegmentsInRange(segment_vec_t& segments, S32 start, S32 end, bool include_partial) const; virtual llwchar pasteEmbeddedItem(llwchar ext_char) { return ext_char; } @@ -307,18 +303,18 @@ private: // Methods // void pasteHelper(bool is_primary); - void cleanStringForPaste(LLWString & clean_string); + void cleanStringForPaste(LLWString& clean_string); public: template <typename STRINGTYPE> void pasteTextWithLinebreaks(const STRINGTYPE& clean_string) { - pasteTextWithLinebreaks<LLWString>(ll_convert(clean_string)); + pasteTextWithLinebreaksImpl(ll_convert(clean_string)); } - template <> - void pasteTextWithLinebreaks<LLWString>(const LLWString & clean_string); + void pasteTextWithLinebreaksImpl(const LLWString& clean_string); private: + void pasteTextWithLinebreaksInternal(const LLWString & clean_string); void onKeyStroke(); // Concrete TextCmd sub-classes used by the LLTextEditor base class diff --git a/indra/llui/lltoolbar.h b/indra/llui/lltoolbar.h index c57c979525..5556406fbd 100644 --- a/indra/llui/lltoolbar.h +++ b/indra/llui/lltoolbar.h @@ -68,7 +68,7 @@ public: void reshape(S32 width, S32 height, bool called_from_parent = true); void setEnabled(bool enabled); void setCommandId(const LLCommandId& id) { mId = id; } - LLCommandId getCommandId() { return mId; } + LLCommandId getCommandId() const { return mId; } void setStartDragCallback(tool_startdrag_callback_t cb) { mStartDragItemCallback = cb; } void setHandleDragCallback(tool_handledrag_callback_t cb) { mHandleDragItemCallback = cb; } @@ -256,7 +256,7 @@ public: // Methods used in loading and saving toolbar settings void setButtonType(LLToolBarEnums::ButtonType button_type); - LLToolBarEnums::ButtonType getButtonType() { return mButtonType; } + LLToolBarEnums::ButtonType getButtonType() const { return mButtonType; } command_id_list_t& getCommandsList() { return mButtonCommands; } void clearCommandsList(); diff --git a/indra/llui/lltooltip.cpp b/indra/llui/lltooltip.cpp index 86525c2f7e..74f03618cf 100644 --- a/indra/llui/lltooltip.cpp +++ b/indra/llui/lltooltip.cpp @@ -390,22 +390,22 @@ void LLToolTip::draw() } } -bool LLToolTip::isFading() +bool LLToolTip::isFading() const { return mFadeTimer.getStarted(); } -F32 LLToolTip::getVisibleTime() +F32 LLToolTip::getVisibleTime() const { return mVisibleTimer.getStarted() ? mVisibleTimer.getElapsedTimeF32() : 0.f; } -bool LLToolTip::hasClickCallback() +bool LLToolTip::hasClickCallback() const { return mHasClickCallback; } -void LLToolTip::getToolTipMessage(std::string & message) +void LLToolTip::getToolTipMessage(std::string& message) const { if (mTextBox) { diff --git a/indra/llui/lltooltip.h b/indra/llui/lltooltip.h index 8515504e3b..760acddd6f 100644 --- a/indra/llui/lltooltip.h +++ b/indra/llui/lltooltip.h @@ -44,15 +44,15 @@ public: Params(); }; LLToolTipView(const LLToolTipView::Params&); - /*virtual*/ bool handleHover(S32 x, S32 y, MASK mask); - /*virtual*/ bool handleMouseDown(S32 x, S32 y, MASK mask); - /*virtual*/ bool handleMiddleMouseDown(S32 x, S32 y, MASK mask); - /*virtual*/ bool handleRightMouseDown(S32 x, S32 y, MASK mask); - /*virtual*/ bool handleScrollWheel( S32 x, S32 y, S32 clicks ); + bool handleHover(S32 x, S32 y, MASK mask) override; + bool handleMouseDown(S32 x, S32 y, MASK mask) override; + bool handleMiddleMouseDown(S32 x, S32 y, MASK mask) override; + bool handleRightMouseDown(S32 x, S32 y, MASK mask) override; + bool handleScrollWheel( S32 x, S32 y, S32 clicks ) override; void drawStickyRect(); - /*virtual*/ void draw(); + void draw() override; }; class LLToolTip : public LLPanel @@ -98,20 +98,20 @@ public: Params(); }; - /*virtual*/ void draw(); - /*virtual*/ bool handleHover(S32 x, S32 y, MASK mask); - /*virtual*/ void onMouseLeave(S32 x, S32 y, MASK mask); - /*virtual*/ void setVisible(bool visible); + void draw() override; + bool handleHover(S32 x, S32 y, MASK mask) override; + void onMouseLeave(S32 x, S32 y, MASK mask) override; + void setVisible(bool visible) override; - bool isFading(); - F32 getVisibleTime(); - bool hasClickCallback(); + bool isFading() const; + F32 getVisibleTime() const; + bool hasClickCallback() const; LLToolTip(const Params& p); virtual void initFromParams(const LLToolTip::Params& params); - void getToolTipMessage(std::string & message); - bool isTooltipPastable() { return mIsTooltipPastable; } + void getToolTipMessage(std::string & message) const; + bool isTooltipPastable() const { return mIsTooltipPastable; } protected: void updateTextBox(); diff --git a/indra/llui/llui.h b/indra/llui/llui.h index 375cd539b7..051ecc4405 100644 --- a/indra/llui/llui.h +++ b/indra/llui/llui.h @@ -156,7 +156,7 @@ public: sanitizeRange(); } - S32 clamp(S32 input) + S32 clamp(S32 input) const { if (input < mMin) return mMin; if (input > mMax) return mMax; @@ -170,8 +170,8 @@ public: sanitizeRange(); } - S32 getMin() { return mMin; } - S32 getMax() { return mMax; } + S32 getMin() const { return mMin; } + S32 getMax() const { return mMax; } bool operator==(const RangeS32& other) const { @@ -225,7 +225,7 @@ public: mValue = clamp(value); } - S32 get() + S32 get() const { return mValue; } @@ -255,7 +255,7 @@ public: static std::string getLanguage(); // static for lldateutil_test compatibility //helper functions (should probably move free standing rendering helper functions here) - LLView* getRootView() { return mRootView; } + LLView* getRootView() const { return mRootView; } void setRootView(LLView* view) { mRootView = view; } /** * Walk the LLView tree to resolve a path @@ -298,7 +298,7 @@ public: LLControlGroup& getControlControlGroup (std::string_view controlname); F32 getMouseIdleTime() { return mMouseIdleTimer.getElapsedTimeF32(); } void resetMouseIdleTimer() { mMouseIdleTimer.reset(); } - LLWindow* getWindow() { return mWindow; } + LLWindow* getWindow() const { return mWindow; } void addPopup(LLView*); void removePopup(LLView*); diff --git a/indra/llui/lluiconstants.h b/indra/llui/lluiconstants.h index 5fdfd37c6e..a317c66008 100644 --- a/indra/llui/lluiconstants.h +++ b/indra/llui/lluiconstants.h @@ -28,23 +28,23 @@ #define LL_LLUICONSTANTS_H // spacing for small font lines of text, like LLTextBoxes -const S32 LINE = 16; +constexpr S32 LINE = 16; // spacing for larger lines of text -const S32 LINE_BIG = 24; +constexpr S32 LINE_BIG = 24; // default vertical padding -const S32 VPAD = 4; +constexpr S32 VPAD = 4; // default horizontal padding -const S32 HPAD = 4; +constexpr S32 HPAD = 4; // Account History, how far to look into past -const S32 SUMMARY_INTERVAL = 7; // one week -const S32 SUMMARY_MAX = 8; // -const S32 DETAILS_INTERVAL = 1; // one day -const S32 DETAILS_MAX = 30; // one month -const S32 TRANSACTIONS_INTERVAL = 1;// one day -const S32 TRANSACTIONS_MAX = 30; // one month +constexpr S32 SUMMARY_INTERVAL = 7; // one week +constexpr S32 SUMMARY_MAX = 8; // +constexpr S32 DETAILS_INTERVAL = 1; // one day +constexpr S32 DETAILS_MAX = 30; // one month +constexpr S32 TRANSACTIONS_INTERVAL = 1;// one day +constexpr S32 TRANSACTIONS_MAX = 30; // one month #endif diff --git a/indra/llui/lluictrl.h b/indra/llui/lluictrl.h index 2c73ff6b57..b95c221d68 100644 --- a/indra/llui/lluictrl.h +++ b/indra/llui/lluictrl.h @@ -39,9 +39,9 @@ #include "llviewmodel.h" // *TODO move dependency to .cpp file #include "llsearchablecontrol.h" -const bool TAKE_FOCUS_YES = true; -const bool TAKE_FOCUS_NO = false; -const S32 DROP_SHADOW_FLOATER = 5; +constexpr bool TAKE_FOCUS_YES = true; +constexpr bool TAKE_FOCUS_NO = false; +constexpr S32 DROP_SHADOW_FLOATER = 5; class LLUICtrl : public LLView, public boost::signals2::trackable diff --git a/indra/llui/lluictrlfactory.h b/indra/llui/lluictrlfactory.h index 75e7e396bc..91221dc7f3 100644 --- a/indra/llui/lluictrlfactory.h +++ b/indra/llui/lluictrlfactory.h @@ -184,7 +184,7 @@ fail: template<class T> static T* getDefaultWidget(std::string_view name) { - typename T::Params widget_params; + typename T::Params widget_params{}; widget_params.name = std::string(name); return create<T>(widget_params); } diff --git a/indra/llui/llundo.h b/indra/llui/llundo.h index dc40702be0..990745e530 100644 --- a/indra/llui/llundo.h +++ b/indra/llui/llundo.h @@ -42,7 +42,7 @@ public: LLUndoAction(): mClusterID(0) {}; virtual ~LLUndoAction(){}; private: - S32 mClusterID; + S32 mClusterID; }; LLUndoBuffer( LLUndoAction (*create_func()), S32 initial_count ); @@ -51,8 +51,8 @@ public: LLUndoAction *getNextAction(bool setClusterBegin = true); bool undoAction(); bool redoAction(); - bool canUndo() { return (mNextAction != mFirstAction); } - bool canRedo() { return (mNextAction != mLastAction); } + bool canUndo() const { return (mNextAction != mFirstAction); } + bool canRedo() const { return (mNextAction != mLastAction); } void flushActions(); diff --git a/indra/llui/llurlaction.h b/indra/llui/llurlaction.h index 0f54b66299..ac9741a7ad 100644 --- a/indra/llui/llurlaction.h +++ b/indra/llui/llurlaction.h @@ -45,8 +45,6 @@ class LLUrlAction { public: - LLUrlAction(); - /// load a Url in the user's preferred web browser static void openURL(std::string url); diff --git a/indra/llui/llurlentry.cpp b/indra/llui/llurlentry.cpp index 3cc0c05ffa..b9b2edc032 100644 --- a/indra/llui/llurlentry.cpp +++ b/indra/llui/llurlentry.cpp @@ -1683,6 +1683,7 @@ void LLUrlEntryKeybinding::initLocalization() initLocalizationFromFile("control_table_contents_camera.xml"); initLocalizationFromFile("control_table_contents_editing.xml"); initLocalizationFromFile("control_table_contents_media.xml"); + initLocalizationFromFile("control_table_contents_game_control.xml"); } void LLUrlEntryKeybinding::initLocalizationFromFile(const std::string& filename) diff --git a/indra/llui/llurlmatch.h b/indra/llui/llurlmatch.h index ba822fbda6..887796bb37 100644 --- a/indra/llui/llurlmatch.h +++ b/indra/llui/llurlmatch.h @@ -31,7 +31,6 @@ //#include "linden_common.h" #include <string> -#include <vector> #include "llstyle.h" /// diff --git a/indra/llui/llurlregistry.h b/indra/llui/llurlregistry.h index 64cfec3960..c22af0dbc4 100644 --- a/indra/llui/llurlregistry.h +++ b/indra/llui/llurlregistry.h @@ -34,7 +34,6 @@ #include "llstring.h" #include <string> -#include <vector> class LLKeyBindingToStringHandler; diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp index 0206e46b57..190ba07ad6 100644 --- a/indra/llui/llview.cpp +++ b/indra/llui/llview.cpp @@ -642,10 +642,10 @@ void LLView::onVisibilityChange ( bool new_visibility ) if(log_visibility_change) { - if (old_visibility!=new_visibility) - { - LLViewerEventRecorder::instance().logVisibilityChange( viewp->getPathname(), viewp->getName(), new_visibility,"widget"); - } + if (old_visibility!=new_visibility) + { + LLViewerEventRecorder::instance().logVisibilityChange( viewp->getPathname(), viewp->getName(), new_visibility,"widget"); + } } if (old_visibility) diff --git a/indra/llui/llview.h b/indra/llui/llview.h index 710ec3d05e..97212a9d2d 100644 --- a/indra/llui/llview.h +++ b/indra/llui/llview.h @@ -54,17 +54,17 @@ class LLSD; -const U32 FOLLOWS_NONE = 0x00; -const U32 FOLLOWS_LEFT = 0x01; -const U32 FOLLOWS_RIGHT = 0x02; -const U32 FOLLOWS_TOP = 0x10; -const U32 FOLLOWS_BOTTOM = 0x20; -const U32 FOLLOWS_ALL = 0x33; +constexpr U32 FOLLOWS_NONE = 0x00; +constexpr U32 FOLLOWS_LEFT = 0x01; +constexpr U32 FOLLOWS_RIGHT = 0x02; +constexpr U32 FOLLOWS_TOP = 0x10; +constexpr U32 FOLLOWS_BOTTOM = 0x20; +constexpr U32 FOLLOWS_ALL = 0x33; -const bool MOUSE_OPAQUE = true; -const bool NOT_MOUSE_OPAQUE = false; +constexpr bool MOUSE_OPAQUE = true; +constexpr bool NOT_MOUSE_OPAQUE = false; -const U32 GL_NAME_UI_RESERVED = 2; +constexpr U32 GL_NAME_UI_RESERVED = 2; // maintains render state during traversal of UI tree @@ -241,7 +241,7 @@ public: void setUseBoundingRect( bool use_bounding_rect ); bool getUseBoundingRect() const; - ECursorType getHoverCursor() { return mHoverCursor; } + ECursorType getHoverCursor() const { return mHoverCursor; } static F32 getTooltipTimeout(); virtual const std::string getToolTip() const; @@ -265,7 +265,7 @@ public: void setDefaultTabGroup(S32 d) { mDefaultTabGroup = d; } S32 getDefaultTabGroup() const { return mDefaultTabGroup; } - S32 getLastTabGroup() { return mLastTabGroup; } + S32 getLastTabGroup() const { return mLastTabGroup; } bool isInVisibleChain() const; bool isInEnabledChain() const; diff --git a/indra/llui/llviewborder.h b/indra/llui/llviewborder.h index 1f118a0d20..a4bb748b77 100644 --- a/indra/llui/llviewborder.h +++ b/indra/llui/llviewborder.h @@ -92,7 +92,6 @@ public: private: void drawOnePixelLines(); void drawTwoPixelLines(); - void drawTextures(); EBevel mBevel; EStyle mStyle; diff --git a/indra/llui/llviewereventrecorder.h b/indra/llui/llviewereventrecorder.h index 9e752e8090..5636c068d8 100644 --- a/indra/llui/llviewereventrecorder.h +++ b/indra/llui/llviewereventrecorder.h @@ -61,7 +61,7 @@ public: std::string get_xui(); void update_xui(std::string xui); - bool getLoggingStatus(){return logEvents;}; + bool getLoggingStatus() const { return logEvents; } void setEventLoggingOn(); void setEventLoggingOff(); diff --git a/indra/llui/llvirtualtrackball.h b/indra/llui/llvirtualtrackball.h index 61a78b2398..fbfda04585 100644 --- a/indra/llui/llvirtualtrackball.h +++ b/indra/llui/llvirtualtrackball.h @@ -78,20 +78,20 @@ public: }; - virtual ~LLVirtualTrackball(); - /*virtual*/ bool postBuild(); + ~LLVirtualTrackball() override; + bool postBuild() override; - virtual bool handleHover(S32 x, S32 y, MASK mask); - virtual bool handleMouseUp(S32 x, S32 y, MASK mask); - virtual bool handleMouseDown(S32 x, S32 y, MASK mask); - virtual bool handleRightMouseDown(S32 x, S32 y, MASK mask); - virtual bool handleKeyHere(KEY key, MASK mask); + bool handleHover(S32 x, S32 y, MASK mask) override; + bool handleMouseUp(S32 x, S32 y, MASK mask) override; + bool handleMouseDown(S32 x, S32 y, MASK mask) override; + bool handleRightMouseDown(S32 x, S32 y, MASK mask) override; + bool handleKeyHere(KEY key, MASK mask) override; - virtual void draw(); + void draw() override; - virtual void setValue(const LLSD& value); - void setValue(F32 x, F32 y, F32 z, F32 w); - virtual LLSD getValue() const; + void setValue(const LLSD& value) override; + void setValue(F32 x, F32 y, F32 z, F32 w); + LLSD getValue() const override; void setRotation(const LLQuaternion &value); LLQuaternion getRotation() const; @@ -102,7 +102,6 @@ public: protected: friend class LLUICtrlFactory; LLVirtualTrackball(const Params&); - void onEditChange(); protected: LLTextBox* mNLabel; diff --git a/indra/llui/llwindowshade.h b/indra/llui/llwindowshade.h index da29188943..ee230cd2f6 100644 --- a/indra/llui/llwindowshade.h +++ b/indra/llui/llwindowshade.h @@ -49,7 +49,7 @@ public: }; void show(LLNotificationPtr); - /*virtual*/ void draw(); + void draw() override; void hide(); bool isShown() const; diff --git a/indra/llui/llxyvector.h b/indra/llui/llxyvector.h index bc41213c13..646771f387 100644 --- a/indra/llui/llxyvector.h +++ b/indra/llui/llxyvector.h @@ -65,18 +65,18 @@ public: }; - virtual ~LLXYVector(); - /*virtual*/ bool postBuild(); + ~LLXYVector() override; + bool postBuild() override; - virtual bool handleHover(S32 x, S32 y, MASK mask); - virtual bool handleMouseUp(S32 x, S32 y, MASK mask); - virtual bool handleMouseDown(S32 x, S32 y, MASK mask); + bool handleHover(S32 x, S32 y, MASK mask) override; + bool handleMouseUp(S32 x, S32 y, MASK mask) override; + bool handleMouseDown(S32 x, S32 y, MASK mask) override; - virtual void draw(); + void draw() override; - virtual void setValue(const LLSD& value); - void setValue(F32 x, F32 y); - virtual LLSD getValue() const; + void setValue(const LLSD& value) override; + void setValue(F32 x, F32 y); + LLSD getValue() const override; protected: friend class LLUICtrlFactory; diff --git a/indra/llwindow/CMakeLists.txt b/indra/llwindow/CMakeLists.txt index 075e17235a..e86ef2d578 100644 --- a/indra/llwindow/CMakeLists.txt +++ b/indra/llwindow/CMakeLists.txt @@ -18,11 +18,15 @@ include(LLWindow) include(UI) include(ViewerMiscLibs) include(GLM) +include(SDL2) set(llwindow_SOURCE_FILES llcursortypes.cpp + llgamecontrol.cpp + llgamecontroltranslator.cpp llkeyboard.cpp llkeyboardheadless.cpp + llsdl.cpp llwindowheadless.cpp llwindowcallbacks.cpp llwindow.cpp @@ -32,8 +36,11 @@ set(llwindow_HEADER_FILES CMakeLists.txt llcursortypes.h + llgamecontrol.h + llgamecontroltranslator.h llkeyboard.h llkeyboardheadless.h + llsdl.h llwindowheadless.h llwindowcallbacks.h ) @@ -58,7 +65,7 @@ set(llwindow_LINK_LIBRARIES ll::glm ll::glext ll::uilibraries - ll::SDL + ll::SDL2 ll::zlib-ng ) @@ -173,11 +180,11 @@ endif (llwindow_HEADER_FILES) ${viewer_SOURCE_FILES} ) -if (SDL_FOUND) +if (SDL2_FOUND) set_property(TARGET llwindow PROPERTY COMPILE_DEFINITIONS LL_SDL=1 ) -endif (SDL_FOUND) +endif (SDL2_FOUND) target_link_libraries (llwindow ${llwindow_LINK_LIBRARIES}) target_include_directories(llwindow INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) diff --git a/indra/llwindow/llgamecontrol.cpp b/indra/llwindow/llgamecontrol.cpp new file mode 100644 index 0000000000..9d3c854ca2 --- /dev/null +++ b/indra/llwindow/llgamecontrol.cpp @@ -0,0 +1,2122 @@ +/** + * @file llgamecontrol.h + * @brief GameController detection and management + * + * $LicenseInfo:firstyear=2023&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2023, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llgamecontrol.h" + +#include <algorithm> +#include <chrono> +#include <unordered_map> + +#include "SDL2/SDL.h" +#include "SDL2/SDL_gamecontroller.h" +#include "SDL2/SDL_joystick.h" + +#include "indra_constants.h" +#include "llfile.h" +#include "llgamecontroltranslator.h" +#include "llsd.h" + +namespace std +{ + string to_string(const SDL_JoystickGUID& guid) + { + char buffer[33] = { 0 }; + SDL_JoystickGetGUIDString(guid, buffer, sizeof(guid)); + return buffer; + } + + string to_string(SDL_JoystickType type) + { + switch (type) + { + case SDL_JOYSTICK_TYPE_GAMECONTROLLER: + return "GAMECONTROLLER"; + case SDL_JOYSTICK_TYPE_WHEEL: + return "WHEEL"; + case SDL_JOYSTICK_TYPE_ARCADE_STICK: + return "ARCADE_STICK"; + case SDL_JOYSTICK_TYPE_FLIGHT_STICK: + return "FLIGHT_STICK"; + case SDL_JOYSTICK_TYPE_DANCE_PAD: + return "DANCE_PAD"; + case SDL_JOYSTICK_TYPE_GUITAR: + return "GUITAR"; + case SDL_JOYSTICK_TYPE_DRUM_KIT: + return "DRUM_KIT"; + case SDL_JOYSTICK_TYPE_ARCADE_PAD: + return "ARCADE_PAD"; + case SDL_JOYSTICK_TYPE_THROTTLE: + return "THROTTLE"; + default:; + } + return "UNKNOWN"; + } + + string to_string(SDL_GameControllerType type) + { + switch (type) + { + case SDL_CONTROLLER_TYPE_XBOX360: + return "XBOX360"; + case SDL_CONTROLLER_TYPE_XBOXONE: + return "XBOXONE"; + case SDL_CONTROLLER_TYPE_PS3: + return "PS3"; + case SDL_CONTROLLER_TYPE_PS4: + return "PS4"; + case SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO: + return "NINTENDO_SWITCH_PRO"; + case SDL_CONTROLLER_TYPE_VIRTUAL: + return "VIRTUAL"; + case SDL_CONTROLLER_TYPE_PS5: + return "PS5"; + case SDL_CONTROLLER_TYPE_AMAZON_LUNA: + return "AMAZON_LUNA"; + case SDL_CONTROLLER_TYPE_GOOGLE_STADIA: + return "GOOGLE_STADIA"; + case SDL_CONTROLLER_TYPE_NVIDIA_SHIELD: + return "NVIDIA_SHIELD"; + case SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_LEFT: + return "NINTENDO_SWITCH_JOYCON_LEFT"; + case SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_RIGHT: + return "NINTENDO_SWITCH_JOYCON_RIGHT"; + case SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_PAIR: + return "NINTENDO_SWITCH_JOYCON_PAIR"; + default:; + } + return "UNKNOWN"; + } +} + +// Util for dumping SDL_JoystickGUID info +std::ostream& operator<<(std::ostream& out, SDL_JoystickGUID& guid) +{ + return out << std::to_string(guid); +} + +// Util for dumping SDL_JoystickType type name +std::ostream& operator<<(std::ostream& out, SDL_JoystickType type) +{ + return out << std::to_string(type); +} + +// Util for dumping SDL_GameControllerType type name +std::ostream& operator<<(std::ostream& out, SDL_GameControllerType type) +{ + return out << std::to_string(type); +} + +namespace std +{ + string to_string(SDL_Joystick* joystick) + { + if (!joystick) + { + return "nullptr"; + } + + std::stringstream ss; + + ss << "{id:" << SDL_JoystickInstanceID(joystick); + SDL_JoystickGUID guid = SDL_JoystickGetGUID(joystick); + ss << ",guid:'" << guid << "'"; + ss << ",type:'" << SDL_JoystickGetType(joystick) << "'"; + ss << ",name:'" << ll_safe_string(SDL_JoystickName(joystick)) << "'"; + ss << ",vendor:" << SDL_JoystickGetVendor(joystick); + ss << ",product:" << SDL_JoystickGetProduct(joystick); + if (U16 version = SDL_JoystickGetProductVersion(joystick)) + { + ss << ",version:" << version; + } + if (const char* serial = SDL_JoystickGetSerial(joystick)) + { + ss << ",serial:'" << serial << "'"; + } + ss << ",num_axes:" << SDL_JoystickNumAxes(joystick); + ss << ",num_balls:" << SDL_JoystickNumBalls(joystick); + ss << ",num_hats:" << SDL_JoystickNumHats(joystick); + ss << ",num_buttons:" << SDL_JoystickNumHats(joystick); + ss << "}"; + + return ss.str(); + } + + string to_string(SDL_GameController* controller) + { + if (!controller) + { + return "nullptr"; + } + + stringstream ss; + + ss << "{type:'" << SDL_GameControllerGetType(controller) << "'"; + ss << ",name:'" << ll_safe_string(SDL_GameControllerName(controller)) << "'"; + ss << ",vendor:" << SDL_GameControllerGetVendor(controller); + ss << ",product:" << SDL_GameControllerGetProduct(controller); + if (U16 version = SDL_GameControllerGetProductVersion(controller)) + { + ss << ",version:" << version; + } + if (const char* serial = SDL_GameControllerGetSerial(controller)) + { + ss << ",serial:'" << serial << "'"; + } + ss << "}"; + + return ss.str(); + } +} + +// Util for dumping SDL_Joystick info +std::ostream& operator<<(std::ostream& out, SDL_Joystick* joystick) +{ + return out << std::to_string(joystick); +} + +// Util for dumping SDL_GameController info +std::ostream& operator<<(std::ostream& out, SDL_GameController* controller) +{ + return out << std::to_string(controller); +} + +std::string LLGameControl::InputChannel::getLocalName() const +{ + // HACK: we hard-code English channel names, but + // they should be loaded from localized XML config files. + + if ((mType == LLGameControl::InputChannel::TYPE_AXIS) && (mIndex < NUM_AXES)) + { + return "AXIS_" + std::to_string((U32)mIndex) + + (mSign < 0 ? "-" : mSign > 0 ? "+" : ""); + } + + if ((mType == LLGameControl::InputChannel::TYPE_BUTTON) && (mIndex < NUM_BUTTONS)) + { + return "BUTTON_" + std::to_string((U32)mIndex); + } + + return "NONE"; +} + +std::string LLGameControl::InputChannel::getRemoteName() const +{ + // HACK: we hard-code English channel names, but + // they should be loaded from localized XML config files. + std::string name = " "; + // GAME_CONTROL_AXIS_LEFTX, GAME_CONTROL_BUTTON_A, etc + if (mType == LLGameControl::InputChannel::TYPE_AXIS) + { + switch (mIndex) + { + case 0: + name = "GAME_CONTROL_AXIS_LEFTX"; + break; + case 1: + name = "GAME_CONTROL_AXIS_LEFTY"; + break; + case 2: + name = "GAME_CONTROL_AXIS_RIGHTX"; + break; + case 3: + name = "GAME_CONTROL_AXIS_RIGHTY"; + break; + case 4: + name = "GAME_CONTROL_AXIS_PADDLELEFT"; + break; + case 5: + name = "GAME_CONTROL_AXIS_PADDLERIGHT"; + break; + default: + break; + } + } + else if (mType == LLGameControl::InputChannel::TYPE_BUTTON) + { + switch(mIndex) + { + case 0: + name = "GAME_CONTROL_BUTTON_A"; + break; + case 1: + name = "GAME_CONTROL_BUTTON_B"; + break; + case 2: + name = "GAME_CONTROL_BUTTON_X"; + break; + case 3: + name = "GAME_CONTROL_BUTTON_Y"; + break; + case 4: + name = "GAME_CONTROL_BUTTON_BACK"; + break; + case 5: + name = "GAME_CONTROL_BUTTON_GUIDE"; + break; + case 6: + name = "GAME_CONTROL_BUTTON_START"; + break; + case 7: + name = "GAME_CONTROL_BUTTON_LEFTSTICK"; + break; + case 8: + name = "GAME_CONTROL_BUTTON_RIGHTSTICK"; + break; + case 9: + name = "GAME_CONTROL_BUTTON_LEFTSHOULDER"; + break; + case 10: + name = "GAME_CONTROL_BUTTON_RIGHTSHOULDER"; + break; + case 11: + name = "GAME_CONTROL_BUTTON_DPAD_UP"; + break; + case 12: + name = "GAME_CONTROL_BUTTON_DPAD_DOWN"; + break; + case 13: + name = "GAME_CONTROL_BUTTON_DPAD_LEFT"; + break; + case 14: + name = "GAME_CONTROL_BUTTON_DPAD_RIGHT"; + break; + case 15: + name = "GAME_CONTROL_BUTTON_MISC1"; + break; + case 16: + name = "GAME_CONTROL_BUTTON_PADDLE1"; + break; + case 17: + name = "GAME_CONTROL_BUTTON_PADDLE2"; + break; + case 18: + name = "GAME_CONTROL_BUTTON_PADDLE3"; + break; + case 19: + name = "GAME_CONTROL_BUTTON_PADDLE4"; + break; + case 20: + name = "GAME_CONTROL_BUTTON_TOUCHPAD"; + break; + default: + break; + } + } + return name; +} + + +// internal class for managing list of controllers and per-controller state +class LLGameControllerManager +{ +public: + using ActionToChannelMap = std::map< std::string, LLGameControl::InputChannel >; + LLGameControllerManager(); + + static void getDefaultMappings(std::vector<std::pair<std::string, LLGameControl::InputChannel>>& agent_channels, + std::vector<LLGameControl::InputChannel>& flycam_channels); + void getDefaultMappings(std::vector<std::pair<std::string, LLGameControl::InputChannel>>& mappings); + void initializeMappingsByDefault(); + void resetDeviceOptionsToDefaults(); + void loadDeviceOptionsFromSettings(); + void saveDeviceOptionsToSettings() const; + void setDeviceOptions(const std::string& guid, const LLGameControl::Options& options); + + void addController(SDL_JoystickID id, const std::string& guid, const std::string& name); + void removeController(SDL_JoystickID id); + + void onAxis(SDL_JoystickID id, U8 axis, S16 value); + void onButton(SDL_JoystickID id, U8 button, bool pressed); + + void clearAllStates(); + + void accumulateInternalState(); + void computeFinalState(); + + LLGameControl::ActionNameType getActionNameType(const std::string& action) const; + LLGameControl::InputChannel getChannelByAction(const std::string& action) const; + LLGameControl::InputChannel getFlycamChannelByAction(const std::string& action) const; + + bool updateActionMap(const std::string& name, LLGameControl::InputChannel channel); + U32 computeInternalActionFlags(); + void getFlycamInputs(std::vector<F32>& inputs_out); + void setExternalInput(U32 action_flags, U32 buttons); + + U32 getMappedFlags() const { return mActionTranslator.getMappedFlags(); } + + void clear(); + + std::string getAnalogMappings() const; + std::string getBinaryMappings() const; + std::string getFlycamMappings() const; + + void setAnalogMappings(const std::string& mappings); + void setBinaryMappings(const std::string& mappings); + void setFlycamMappings(const std::string& mappings); + +private: + void updateFlycamMap(const std::string& action, LLGameControl::InputChannel channel); + + std::list<LLGameControl::Device> mDevices; // all connected devices + using device_it = std::list<LLGameControl::Device>::iterator; + device_it findDevice(SDL_JoystickID id) + { + return std::find_if(mDevices.begin(), mDevices.end(), + [id](LLGameControl::Device& device) + { + return device.getJoystickID() == id; + }); + } + + LLGameControl::State mExternalState; + LLGameControlTranslator mActionTranslator; + std::map<std::string, LLGameControl::ActionNameType> mActions; + std::vector <std::string> mAnalogActions; + std::vector <std::string> mBinaryActions; + std::vector <std::string> mFlycamActions; + std::vector<LLGameControl::InputChannel> mFlycamChannels; + std::vector<S32> mAxesAccumulator; + U32 mButtonAccumulator { 0 }; + U32 mLastActiveFlags { 0 }; + U32 mLastFlycamActionFlags { 0 }; + + friend class LLGameControl; +}; + +// local globals +namespace +{ + LLGameControl* g_gameControl = nullptr; + LLGameControllerManager g_manager; + + // The GameControlInput message is sent via UDP which is lossy. + // Since we send the only the list of pressed buttons the receiving + // side can compute the difference between subsequent states to + // find button-down/button-up events. + // + // To reduce the likelihood of buttons being stuck "pressed" forever + // on the receiving side (for lost final packet) we resend the last + // data state. However, to keep the ambient resend bandwidth low we + // expand the resend period at a geometric rate. + // + constexpr U64 MSEC_PER_NSEC = 1000000; + constexpr U64 FIRST_RESEND_PERIOD = 100 * MSEC_PER_NSEC; + constexpr U64 RESEND_EXPANSION_RATE = 10; + LLGameControl::State g_outerState; // from controller devices + LLGameControl::State g_innerState; // state from gAgent + LLGameControl::State g_finalState; // sum of inner and outer + U64 g_lastSend = 0; + U64 g_nextResendPeriod = FIRST_RESEND_PERIOD; + + bool g_enabled = false; + bool g_sendToServer = false; + bool g_controlAgent = false; + bool g_translateAgentActions = false; + LLGameControl::AgentControlMode g_agentControlMode = LLGameControl::CONTROL_MODE_AVATAR; + + std::map<std::string, std::string> g_deviceOptions; + + std::function<bool(const std::string&)> s_loadBoolean; + std::function<void(const std::string&, bool)> s_saveBoolean; + std::function<std::string(const std::string&)> s_loadString; + std::function<void(const std::string&, const std::string&)> s_saveString; + std::function<LLSD(const std::string&)> s_loadObject; + std::function<void(const std::string&, LLSD&)> s_saveObject; + std::function<void()> s_updateUI; + + std::string SETTING_ENABLE("EnableGameControl"); + std::string SETTING_SENDTOSERVER("GameControlToServer"); + std::string SETTING_CONTROLAGENT("GameControlToAgent"); + std::string SETTING_TRANSLATEACTIONS("AgentToGameControl"); + std::string SETTING_AGENTCONTROLMODE("AgentControlMode"); + std::string SETTING_ANALOGMAPPINGS("AnalogChannelMappings"); + std::string SETTING_BINARYMAPPINGS("BinaryChannelMappings"); + std::string SETTING_FLYCAMMAPPINGS("FlycamChannelMappings"); + std::string SETTING_KNOWNCONTROLLERS("KnownGameControllers"); + + std::string ENUM_AGENTCONTROLMODE_FLYCAM("flycam"); + std::string ENUM_AGENTCONTROLMODE_NONE("none"); + + LLGameControl::AgentControlMode convertStringToAgentControlMode(const std::string& mode) + { + if (mode == ENUM_AGENTCONTROLMODE_NONE) + return LLGameControl::CONTROL_MODE_NONE; + if (mode == ENUM_AGENTCONTROLMODE_FLYCAM) + return LLGameControl::CONTROL_MODE_FLYCAM; + // All values except NONE and FLYCAM are treated as default (AVATAR) + return LLGameControl::CONTROL_MODE_AVATAR; + } + + const std::string& convertAgentControlModeToString(LLGameControl::AgentControlMode mode) + { + if (mode == LLGameControl::CONTROL_MODE_NONE) + return ENUM_AGENTCONTROLMODE_NONE; + if (mode == LLGameControl::CONTROL_MODE_FLYCAM) + return ENUM_AGENTCONTROLMODE_FLYCAM; + // All values except NONE and FLYCAM are treated as default (AVATAR) + return LLStringUtil::null; + } + + const std::string& getDeviceOptionsString(const std::string& guid) + { + const auto& it = g_deviceOptions.find(guid); + return it == g_deviceOptions.end() ? LLStringUtil::null : it->second; + } +} + +LLGameControl::~LLGameControl() +{ + terminate(); +} + +LLGameControl::State::State() +: mButtons(0) +{ + mAxes.resize(NUM_AXES, 0); + mPrevAxes.resize(NUM_AXES, 0); +} + +void LLGameControl::State::clear() +{ + std::fill(mAxes.begin(), mAxes.end(), 0); + + // DO NOT clear mPrevAxes because those are managed by external logic. + //std::fill(mPrevAxes.begin(), mPrevAxes.end(), 0); + + mButtons = 0; +} + +bool LLGameControl::State::onButton(U8 button, bool pressed) +{ + U32 old_buttons = mButtons; + if (button < NUM_BUTTONS) + { + if (pressed) + { + mButtons |= (0x01 << button); + } + else + { + mButtons &= ~(0x01 << button); + } + } + return mButtons != old_buttons; +} + +LLGameControl::Device::Device(int joystickID, const std::string& guid, const std::string& name) +: mJoystickID(joystickID) +, mGUID(guid) +, mName(name) +{ +} + +LLGameControl::Options::Options() +{ + mAxisOptions.resize(NUM_AXES); + mAxisMap.resize(NUM_AXES); + mButtonMap.resize(NUM_BUTTONS); + resetToDefaults(); +} + +void LLGameControl::Options::resetToDefaults() +{ + for (size_t i = 0; i < NUM_AXES; ++i) + { + mAxisOptions[i].resetToDefaults(); + mAxisMap[i] = (U8)i; + } + for (size_t i = 0; i < NUM_BUTTONS; ++i) + { + mButtonMap[i] = (U8)i; + } +} + +U8 LLGameControl::Options::mapAxis(U8 axis) const +{ + if (axis >= NUM_AXES) + { + LL_WARNS("SDL2") << "Invalid input axis: " << axis << LL_ENDL; + return axis; + } + return mAxisMap[axis]; +} + +U8 LLGameControl::Options::mapButton(U8 button) const +{ + if (button >= NUM_BUTTONS) + { + LL_WARNS("SDL2") << "Invalid input button: " << button << LL_ENDL; + return button; + } + return mButtonMap[button]; +} + +S16 LLGameControl::Options::fixAxisValue(U8 axis, S16 value) const +{ + if (axis >= NUM_AXES) + { + LL_WARNS("SDL2") << "Invalid input axis: " << axis << LL_ENDL; + } + else + { + value = mAxisOptions[axis].computeModifiedValue(value); + } + return value; +} + +std::string LLGameControl::Options::AxisOptions::saveToString() const +{ + std::list<std::string> options; + + if (mMultiplier == -1) + { + options.push_back("invert:1"); + } + if (mDeadZone) + { + options.push_back(llformat("dead_zone:%u", mDeadZone)); + } + if (mOffset) + { + options.push_back(llformat("offset:%d", mOffset)); + } + + std::string result = LLStringUtil::join(options); + + return result.empty() ? result : "{" + result + "}"; +} + +// Parse string "{key:value,key:{key:value,key:value}}" and fill the map +static bool parse(std::map<std::string, std::string>& result, std::string source) +{ + result.clear(); + + LLStringUtil::trim(source); + if (source.empty()) + return true; + + if (source.front() != '{' || source.back() != '}') + return false; + + source = source.substr(1, source.size() - 2); + + LLStringUtil::trim(source); + if (source.empty()) + return true; + + // Split the string "key:value" and add the pair to the map + auto split = [&](const std::string& pair) -> bool + { + size_t pos = pair.find(':'); + if (!pos || pos == std::string::npos) + return false; + std::string key = pair.substr(0, pos); + std::string value = pair.substr(pos + 1); + LLStringUtil::trim(key); + LLStringUtil::trim(value); + if (key.empty() || value.empty()) + return false; + result[key] = value; + return true; + }; + + U32 depth = 0; + size_t offset = 0; + while (true) + { + size_t pos = source.find_first_of(depth ? "{}" : ",{}", offset); + if (pos == std::string::npos) + { + return !depth && split(source); + } + if (source[pos] == ',') + { + if (!split(source.substr(0, pos))) + return false; + source = source.substr(pos + 1); + offset = 0; + } + else if (source[pos] == '{') + { + depth++; + offset = pos + 1; + } + else if (depth) // Assume '}' here + { + depth--; + offset = pos + 1; + } + else + { + return false; // Extra '}' found + } + } + + return true; +} + +void LLGameControl::Options::AxisOptions::loadFromString(std::string options) +{ + resetToDefaults(); + + if (options.empty()) + return; + + std::map<std::string, std::string> pairs; + if (!parse(pairs, options)) + { + LL_WARNS("SDL2") << "Invalid axis options: '" << options << "'" << LL_ENDL; + } + + mMultiplier = 1; + std::string invert = pairs["invert"]; + if (!invert.empty()) + { + if (invert == "1") + { + mMultiplier = -1; + } + else + { + LL_WARNS("SDL2") << "Invalid invert value: '" << invert << "'" << LL_ENDL; + } + } + + std::string dead_zone = pairs["dead_zone"]; + if (!dead_zone.empty()) + { + size_t number = std::stoull(dead_zone); + if (number <= MAX_AXIS_DEAD_ZONE && std::to_string(number) == dead_zone) + { + mDeadZone = (U16)number; + } + else + { + LL_WARNS("SDL2") << "Invalid dead_zone value: '" << dead_zone << "'" << LL_ENDL; + } + } + + std::string offset = pairs["offset"]; + if (!offset.empty()) + { + S32 number = std::stoi(offset); + if (abs(number) > MAX_AXIS_OFFSET || std::to_string(number) != offset) + { + LL_WARNS("SDL2") << "Invalid offset value: '" << offset << "'" << LL_ENDL; + } + else + { + mOffset = (S16)number; + } + } +} + +std::string LLGameControl::Options::saveToString(const std::string& name, bool force_empty) const +{ + return stringifyDeviceOptions(name, mAxisOptions, mAxisMap, mButtonMap, force_empty); +} + +bool LLGameControl::Options::loadFromString(std::string& name, std::string options) +{ + resetToDefaults(); + return LLGameControl::parseDeviceOptions(options, name, mAxisOptions, mAxisMap, mButtonMap); +} + +bool LLGameControl::Options::loadFromString(std::string options) +{ + resetToDefaults(); + std::string dummy_name; + return LLGameControl::parseDeviceOptions(options, dummy_name, mAxisOptions, mAxisMap, mButtonMap); +} + +LLGameControllerManager::LLGameControllerManager() +{ + mAxesAccumulator.resize(LLGameControl::NUM_AXES, 0); + + mAnalogActions = { "push", "slide", "jump", "turn", "look" }; + mBinaryActions = { "toggle_run", "toggle_fly", "toggle_flycam", "stop" }; + mFlycamActions = { "advance", "pan", "rise", "pitch", "yaw", "zoom" }; + + // Collect all known action names with their types in one container + for (const std::string& name : mAnalogActions) + { + mActions[name] = LLGameControl::ACTION_NAME_ANALOG; + mActions[name + "+"] = LLGameControl::ACTION_NAME_ANALOG_POS; + mActions[name + "-"] = LLGameControl::ACTION_NAME_ANALOG_NEG; + } + for (const std::string& name : mBinaryActions) + { + mActions[name] = LLGameControl::ACTION_NAME_BINARY; + } + for (const std::string& name : mFlycamActions) + { + mActions[name] = LLGameControl::ACTION_NAME_FLYCAM; + } + + // Here we build an invariant map between the named agent actions + // and control bit sent to the server. This map will be used, + // in combination with the action->InputChannel map below, + // to maintain an inverse map from control bit masks to GameControl data. + LLGameControlTranslator::ActionToMaskMap actionMasks = + { + // Analog actions (pairs) + { "push+", AGENT_CONTROL_AT_POS | AGENT_CONTROL_FAST_AT }, + { "push-", AGENT_CONTROL_AT_NEG | AGENT_CONTROL_FAST_AT }, + { "slide+", AGENT_CONTROL_LEFT_POS | AGENT_CONTROL_FAST_LEFT }, + { "slide-", AGENT_CONTROL_LEFT_NEG | AGENT_CONTROL_FAST_LEFT }, + { "jump+", AGENT_CONTROL_UP_POS | AGENT_CONTROL_FAST_UP }, + { "jump-", AGENT_CONTROL_UP_NEG | AGENT_CONTROL_FAST_UP }, + { "turn+", AGENT_CONTROL_YAW_POS }, + { "turn-", AGENT_CONTROL_YAW_NEG }, + { "look+", AGENT_CONTROL_PITCH_POS }, + { "look-", AGENT_CONTROL_PITCH_NEG }, + // Button actions + { "stop", AGENT_CONTROL_STOP }, + // These are HACKs. We borrow some AGENT_CONTROL bits for "unrelated" features. + // Not a problem because these bits are only used internally. + { "toggle_run", AGENT_CONTROL_NUDGE_AT_POS }, // HACK + { "toggle_fly", AGENT_CONTROL_FLY }, // HACK + { "toggle_flycam", AGENT_CONTROL_NUDGE_AT_NEG }, // HACK + }; + mActionTranslator.setAvailableActionMasks(actionMasks); + + initializeMappingsByDefault(); +} + +// static +void LLGameControllerManager::getDefaultMappings( + std::vector<std::pair<std::string, LLGameControl::InputChannel>>& agent_channels, + std::vector<LLGameControl::InputChannel>& flycam_channels) +{ + // Here we build a list of pairs between named agent actions and + // GameControl channels. Note: we only supply the non-signed names + // (e.g. "push" instead of "push+" and "push-") because mActionTranslator + // automatially expands action names as necessary. + using type = LLGameControl::InputChannel::Type; + agent_channels = + { + // Analog actions (associated by common name - without '+' or '-') + { "push", { type::TYPE_AXIS, LLGameControl::AXIS_LEFTY, 1 } }, + { "slide", { type::TYPE_AXIS, LLGameControl::AXIS_LEFTX, 1 } }, + { "jump", { type::TYPE_AXIS, LLGameControl::AXIS_TRIGGERLEFT, 1 } }, + { "turn", { type::TYPE_AXIS, LLGameControl::AXIS_RIGHTX, 1 } }, + { "look", { type::TYPE_AXIS, LLGameControl::AXIS_RIGHTY, 1 } }, + // Button actions (associated by name) + { "toggle_run", { type::TYPE_BUTTON, LLGameControl::BUTTON_LEFTSHOULDER } }, + { "toggle_fly", { type::TYPE_BUTTON, LLGameControl::BUTTON_DPAD_UP } }, + { "toggle_flycam", { type::TYPE_BUTTON, LLGameControl::BUTTON_RIGHTSHOULDER } }, + { "stop", { type::TYPE_BUTTON, LLGameControl::BUTTON_LEFTSTICK } } + }; + + // Flycam actions don't need bitwise translation, so we maintain the map + // of channels here directly rather than using an LLGameControlTranslator. + flycam_channels = + { + // Flycam actions (associated just by an order index) + { type::TYPE_AXIS, LLGameControl::AXIS_LEFTY, 1 }, // advance + { type::TYPE_AXIS, LLGameControl::AXIS_LEFTX, 1 }, // pan + { type::TYPE_AXIS, LLGameControl::AXIS_TRIGGERRIGHT, 1 }, // rise + { type::TYPE_AXIS, LLGameControl::AXIS_RIGHTY, -1 }, // pitch + { type::TYPE_AXIS, LLGameControl::AXIS_RIGHTX, 1 }, // yaw + { type::TYPE_NONE, 0 } // zoom + }; +} + +void LLGameControllerManager::getDefaultMappings(std::vector<std::pair<std::string, LLGameControl::InputChannel>>& mappings) +{ + // Join two different data structures into the one + std::vector<LLGameControl::InputChannel> flycam_channels; + getDefaultMappings(mappings, flycam_channels); + for (size_t i = 0; i < flycam_channels.size(); ++i) + { + mappings.emplace_back(mFlycamActions[i], flycam_channels[i]); + } +} + +void LLGameControllerManager::initializeMappingsByDefault() +{ + std::vector<std::pair<std::string, LLGameControl::InputChannel>> agent_channels; + getDefaultMappings(agent_channels, mFlycamChannels); + mActionTranslator.setMappings(agent_channels); +} + +void LLGameControllerManager::resetDeviceOptionsToDefaults() +{ + for (LLGameControl::Device& device : mDevices) + { + device.resetOptionsToDefaults(); + } +} + +void LLGameControllerManager::loadDeviceOptionsFromSettings() +{ + for (LLGameControl::Device& device : mDevices) + { + device.loadOptionsFromString(getDeviceOptionsString(device.getGUID())); + } +} + +void LLGameControllerManager::saveDeviceOptionsToSettings() const +{ + for (const LLGameControl::Device& device : mDevices) + { + std::string options = device.saveOptionsToString(); + if (options.empty()) + { + g_deviceOptions.erase(device.getGUID()); + } + else + { + g_deviceOptions[device.getGUID()] = options; + } + } +} + +void LLGameControllerManager::setDeviceOptions(const std::string& guid, const LLGameControl::Options& options) +{ + // find Device by name + for (LLGameControl::Device& device : mDevices) + { + if (device.getGUID() == guid) + { + device.mOptions = options; + return; + } + } +} + +void LLGameControllerManager::addController(SDL_JoystickID id, const std::string& guid, const std::string& name) +{ + llassert(id >= 0); + + for (const LLGameControl::Device& device : mDevices) + { + if (device.getJoystickID() == id) + { + LL_WARNS("SDL2") << "device with id=" << id << " was already added" + << ", guid: '" << device.getGUID() << "'" + << ", name: '" << device.getName() << "'" + << LL_ENDL; + return; + } + } + + mDevices.emplace_back(id, guid, name).loadOptionsFromString(getDeviceOptionsString(guid)); +} + +void LLGameControllerManager::removeController(SDL_JoystickID id) +{ + LL_INFOS("SDL2") << "joystick id: " << id << LL_ENDL; + + mDevices.remove_if([id](LLGameControl::Device& device) + { + return device.getJoystickID() == id; + }); +} + +void LLGameControllerManager::onAxis(SDL_JoystickID id, U8 axis, S16 value) +{ + device_it it = findDevice(id); + if (it == mDevices.end()) + { + LL_WARNS("SDL2") << "Unknown device: joystick=0x" << std::hex << id << std::dec + << " axis=" << (S32)axis + << " value=" << (S32)value << LL_ENDL; + return; + } + + // Map axis using device-specific settings + // or leave the value unchanged + U8 mapped_axis = it->mOptions.mapAxis(axis); + if (mapped_axis != axis) + { + LL_DEBUGS("SDL2") << "Axis mapped: joystick=0x" << std::hex << id << std::dec + << " input axis i=" << (S32)axis + << " mapped axis i=" << (S32)mapped_axis << LL_ENDL; + axis = mapped_axis; + } + + if (axis >= LLGameControl::NUM_AXES) + { + LL_WARNS("SDL2") << "Unknown axis: joystick=0x" << std::hex << id << std::dec + << " axis=" << (S32)(axis) + << " value=" << (S32)(value) << LL_ENDL; + return; + } + + // Fix value using device-specific settings + // or leave the value unchanged + S16 fixed_value = it->mOptions.fixAxisValue(axis, value); + if (fixed_value != value) + { + LL_DEBUGS("SDL2") << "Value fixed: joystick=0x" << std::hex << id << std::dec + << " axis i=" << (S32)axis + << " input value=" << (S32)value + << " fixed value=" << (S32)fixed_value << LL_ENDL; + value = fixed_value; + } + + // Note: the RAW analog joysticks provide NEGATIVE X,Y values for LEFT,FORWARD + // whereas those directions are actually POSITIVE in SL's local right-handed + // reference frame. Therefore we implicitly negate those axes here where + // they are extracted from SDL, before being used anywhere. + if (axis < SDL_CONTROLLER_AXIS_TRIGGERLEFT) + { + // Note: S16 value is in range [-32768, 32767] which means + // the negative range has an extra possible value. We need + // to add (or subtract) one during negation. + if (value < 0) + { + value = - (value + 1); + } + else if (value > 0) + { + value = (-value) - 1; + } + } + + LL_DEBUGS("SDL2") << "joystick=0x" << std::hex << id << std::dec + << " axis=" << (S32)(axis) + << " value=" << (S32)(value) << LL_ENDL; + it->mState.mAxes[axis] = value; +} + +void LLGameControllerManager::onButton(SDL_JoystickID id, U8 button, bool pressed) +{ + device_it it = findDevice(id); + if (it == mDevices.end()) + { + LL_WARNS("SDL2") << "Unknown device: joystick=0x" << std::hex << id << std::dec + << " button i=" << (S32)button << LL_ENDL; + return; + } + + // Map button using device-specific settings + // or leave the value unchanged + U8 mapped_button = it->mOptions.mapButton(button); + if (mapped_button != button) + { + LL_DEBUGS("SDL2") << "Button mapped: joystick=0x" << std::hex << id << std::dec + << " input button i=" << (S32)button + << " mapped button i=" << (S32)mapped_button << LL_ENDL; + button = mapped_button; + } + + if (button >= LLGameControl::NUM_BUTTONS) + { + LL_WARNS("SDL2") << "Unknown button: joystick=0x" << std::hex << id << std::dec + << " button i=" << (S32)button << LL_ENDL; + return; + } + + if (it->mState.onButton(button, pressed)) + { + LL_DEBUGS("SDL2") << "joystick=0x" << std::hex << id << std::dec + << " button i=" << (S32)button + << " pressed=" << pressed << LL_ENDL; + } +} + +void LLGameControllerManager::clearAllStates() +{ + for (auto& device : mDevices) + { + device.mState.clear(); + } + mExternalState.clear(); + mLastActiveFlags = 0; + mLastFlycamActionFlags = 0; +} + +void LLGameControllerManager::accumulateInternalState() +{ + // clear the old state + std::fill(mAxesAccumulator.begin(), mAxesAccumulator.end(), 0); + mButtonAccumulator = 0; + + // accumulate the controllers + for (const auto& device : mDevices) + { + mButtonAccumulator |= device.mState.mButtons; + for (size_t i = 0; i < LLGameControl::NUM_AXES; ++i) + { + // Note: we don't bother to clamp the axes yet + // because at this stage we haven't yet accumulated the "inner" state. + mAxesAccumulator[i] += (S32)device.mState.mAxes[i]; + } + } +} + +void LLGameControllerManager::computeFinalState() +{ + // We assume accumulateInternalState() has already been called and we will + // finish by accumulating "external" state (if enabled) + U32 old_buttons = g_finalState.mButtons; + g_finalState.mButtons = mButtonAccumulator; + if (g_translateAgentActions) + { + // accumulate from mExternalState + g_finalState.mButtons |= mExternalState.mButtons; + } + if (old_buttons != g_finalState.mButtons) + { + g_nextResendPeriod = 0; // packet needs to go out ASAP + } + + // clamp the accumulated axes + for (size_t i = 0; i < LLGameControl::NUM_AXES; ++i) + { + S32 axis = mAxesAccumulator[i]; + if (g_translateAgentActions) + { + // Note: we accumulate mExternalState onto local 'axis' variable + // rather than onto mAxisAccumulator[i] because the internal + // accumulated value is also used to drive the Flycam, and + // we don't want any external state leaking into that value. + axis += (S32)mExternalState.mAxes[i]; + } + axis = (S16)std::min(std::max(axis, -32768), 32767); + // check for change + if (g_finalState.mAxes[i] != axis) + { + // When axis changes we explicitly update the corresponding prevAxis + // prior to storing axis. The only other place where prevAxis + // is updated in updateResendPeriod() which is explicitly called after + // a packet is sent. The result is: unchanged axes are included in + // first resend but not later ones. + g_finalState.mPrevAxes[i] = g_finalState.mAxes[i]; + g_finalState.mAxes[i] = axis; + g_nextResendPeriod = 0; // packet needs to go out ASAP + } + } +} + +LLGameControl::ActionNameType LLGameControllerManager::getActionNameType(const std::string& action) const +{ + auto it = mActions.find(action); + return it == mActions.end() ? LLGameControl::ACTION_NAME_UNKNOWN : it->second; +} + +LLGameControl::InputChannel LLGameControllerManager::getChannelByAction(const std::string& action) const +{ + LLGameControl::InputChannel channel; + auto action_it = mActions.find(action); + if (action_it != mActions.end()) + { + if (action_it->second == LLGameControl::ACTION_NAME_FLYCAM) + { + channel = getFlycamChannelByAction(action); + } + else + { + channel = mActionTranslator.getChannelByAction(action); + } + } + return channel; +} + +LLGameControl::InputChannel LLGameControllerManager::getFlycamChannelByAction(const std::string& action) const +{ + auto flycam_it = std::find(mFlycamActions.begin(), mFlycamActions.end(), action); + llassert(flycam_it != mFlycamActions.end()); + std::ptrdiff_t index = std::distance(mFlycamActions.begin(), flycam_it); + return mFlycamChannels[(std::size_t)index]; +} + +// Common implementation of getAnalogMappings(), getBinaryMappings() and getFlycamMappings() +static std::string getMappings(const std::vector<std::string>& actions, LLGameControl::InputChannel::Type type, + std::function<LLGameControl::InputChannel(const std::string& action)> getChannel) +{ + std::list<std::string> mappings; + + std::vector<std::pair<std::string, LLGameControl::InputChannel>> default_mappings; + LLGameControl::getDefaultMappings(default_mappings); + + // Walk through the all known actions of the chosen type + for (const std::string& action : actions) + { + LLGameControl::InputChannel channel = getChannel(action); + // Only channels of the expected type should be stored + if (channel.mType == type) + { + bool mapping_differs = false; + for (const auto& pair : default_mappings) + { + if (pair.first == action) + { + mapping_differs = !channel.isEqual(pair.second); + break; + } + } + // Only mappings different from the default should be stored + if (mapping_differs) + { + mappings.push_back(action + ":" + channel.getLocalName()); + } + } + } + + std::string result = LLStringUtil::join(mappings); + + return result; +} + +std::string LLGameControllerManager::getAnalogMappings() const +{ + return getMappings(mAnalogActions, LLGameControl::InputChannel::TYPE_AXIS, + [&](const std::string& action) -> LLGameControl::InputChannel + { + return mActionTranslator.getChannelByAction(action + "+"); + }); +} + +std::string LLGameControllerManager::getBinaryMappings() const +{ + return getMappings(mBinaryActions, LLGameControl::InputChannel::TYPE_BUTTON, + [&](const std::string& action) -> LLGameControl::InputChannel + { + return mActionTranslator.getChannelByAction(action); + }); +} + +std::string LLGameControllerManager::getFlycamMappings() const +{ + return getMappings(mFlycamActions, LLGameControl::InputChannel::TYPE_AXIS, + [&](const std::string& action) -> LLGameControl::InputChannel + { + return getFlycamChannelByAction(action); + }); +} + +// Common implementation of setAnalogMappings(), setBinaryMappings() and setFlycamMappings() +static void setMappings(const std::string& mappings, + const std::vector<std::string>& actions, LLGameControl::InputChannel::Type type, + std::function<void(const std::string& action, LLGameControl::InputChannel channel)> updateMap) +{ + if (mappings.empty()) + return; + + std::map<std::string, std::string> pairs; + LLStringOps::splitString(mappings, ',', [&](const std::string& mapping) + { + std::size_t pos = mapping.find(':'); + if (pos > 0 && pos != std::string::npos) + { + pairs[mapping.substr(0, pos)] = mapping.substr(pos + 1); + } + }); + + static const LLGameControl::InputChannel channelNone; + + for (const std::string& action : actions) + { + auto it = pairs.find(action); + if (it != pairs.end()) + { + LLGameControl::InputChannel channel = LLGameControl::getChannelByName(it->second); + if (channel.isNone() || channel.mType == type) + { + updateMap(action, channel); + continue; + } + } + updateMap(action, channelNone); + } +} + +void LLGameControllerManager::setAnalogMappings(const std::string& mappings) +{ + setMappings(mappings, mAnalogActions, LLGameControl::InputChannel::TYPE_AXIS, + [&](const std::string& action, LLGameControl::InputChannel channel) + { + mActionTranslator.updateMap(action, channel); + }); +} + +void LLGameControllerManager::setBinaryMappings(const std::string& mappings) +{ + setMappings(mappings, mBinaryActions, LLGameControl::InputChannel::TYPE_BUTTON, + [&](const std::string& action, LLGameControl::InputChannel channel) + { + mActionTranslator.updateMap(action, channel); + }); +} + +void LLGameControllerManager::setFlycamMappings(const std::string& mappings) +{ + setMappings(mappings, mFlycamActions, LLGameControl::InputChannel::TYPE_AXIS, + [&](const std::string& action, LLGameControl::InputChannel channel) + { + updateFlycamMap(action, channel); + }); +} + +bool LLGameControllerManager::updateActionMap(const std::string& action, LLGameControl::InputChannel channel) +{ + auto action_it = mActions.find(action); + if (action_it == mActions.end()) + { + LL_WARNS("SDL2") << "unmappable action='" << action << "'" << LL_ENDL; + return false; + } + + if (action_it->second == LLGameControl::ACTION_NAME_FLYCAM) + { + updateFlycamMap(action, channel); + } + else + { + mActionTranslator.updateMap(action, channel); + } + return true; +} + +void LLGameControllerManager::updateFlycamMap(const std::string& action, LLGameControl::InputChannel channel) +{ + auto flycam_it = std::find(mFlycamActions.begin(), mFlycamActions.end(), action); + llassert(flycam_it != mFlycamActions.end()); + std::ptrdiff_t index = std::distance(mFlycamActions.begin(), flycam_it); + llassert(index >= 0 && (std::size_t)index < mFlycamChannels.size()); + mFlycamChannels[(std::size_t)index] = channel; +} + +U32 LLGameControllerManager::computeInternalActionFlags() +{ + // add up device inputs + accumulateInternalState(); + if (g_controlAgent) + { + return mActionTranslator.computeFlagsFromState(mAxesAccumulator, mButtonAccumulator); + } + return 0; +} + +void LLGameControllerManager::getFlycamInputs(std::vector<F32>& inputs) +{ + // The inputs are packed in the same order as they exist in mFlycamChannels: + // + // advance + // pan + // rise + // pitch + // yaw + // zoom + // + for (const auto& channel: mFlycamChannels) + { + S16 axis; + if (channel.mIndex == LLGameControl::AXIS_TRIGGERLEFT || + channel.mIndex == LLGameControl::AXIS_TRIGGERRIGHT) + { + // TIED TRIGGER HACK: we assume the two triggers are paired together + S32 total_axis = mAxesAccumulator[LLGameControl::AXIS_TRIGGERLEFT] + - mAxesAccumulator[LLGameControl::AXIS_TRIGGERRIGHT]; + if (channel.mIndex == LLGameControl::AXIS_TRIGGERRIGHT) + { + // negate previous math when TRIGGERRIGHT is positive channel + total_axis *= -1; + } + axis = S16(std::min(std::max(total_axis, -32768), 32767)); + } + else + { + axis = S16(std::min(std::max(mAxesAccumulator[channel.mIndex], -32768), 32767)); + } + // value arrives as S16 in range [-32768, 32767] + // so we scale positive and negative values by slightly different factors + // to try to map it to [-1, 1] + F32 input = F32(axis) / ((axis > 0.0f) ? 32767 : 32768) * channel.mSign; + inputs.push_back(input); + } +} + +void LLGameControllerManager::setExternalInput(U32 action_flags, U32 buttons) +{ + if (g_translateAgentActions) + { + // HACK: these are the bits we can safely translate from control flags to GameControl + // Extracting LLGameControl::InputChannels that are mapped to other bits is a WIP. + // TODO: translate other bits to GameControl, which might require measure of gAgent + // state changes (e.g. sitting <--> standing, flying <--> not-flying, etc) + const U32 BITS_OF_INTEREST = + AGENT_CONTROL_AT_POS | AGENT_CONTROL_AT_NEG + | AGENT_CONTROL_LEFT_POS | AGENT_CONTROL_LEFT_NEG + | AGENT_CONTROL_UP_POS | AGENT_CONTROL_UP_NEG + | AGENT_CONTROL_YAW_POS | AGENT_CONTROL_YAW_NEG + | AGENT_CONTROL_PITCH_POS | AGENT_CONTROL_PITCH_NEG + | AGENT_CONTROL_STOP + | AGENT_CONTROL_FAST_AT + | AGENT_CONTROL_FAST_LEFT + | AGENT_CONTROL_FAST_UP; + action_flags &= BITS_OF_INTEREST; + + U32 active_flags = action_flags & mActionTranslator.getMappedFlags(); + if (active_flags != mLastActiveFlags) + { + mLastActiveFlags = active_flags; + mExternalState = mActionTranslator.computeStateFromFlags(action_flags); + mExternalState.mButtons |= buttons; + } + else + { + mExternalState.mButtons = buttons; + } + } + else + { + mExternalState.mButtons = buttons; + } +} + +void LLGameControllerManager::clear() +{ + mDevices.clear(); +} + +U64 get_now_nsec() +{ + std::chrono::time_point<std::chrono::steady_clock> t0; + return (std::chrono::steady_clock::now() - t0).count(); +} + +void onJoystickDeviceAdded(const SDL_Event& event) +{ + SDL_JoystickGUID guid(SDL_JoystickGetDeviceGUID(event.cdevice.which)); + SDL_JoystickType type(SDL_JoystickGetDeviceType(event.cdevice.which)); + std::string name(ll_safe_string(SDL_JoystickNameForIndex(event.cdevice.which))); + + LL_INFOS("SDL2") << "joystick {id:" << event.cdevice.which + << ",guid:'" << guid << "'" + << ",type:'" << type << "'" + << ",name:'" << name << "'" + << "}" << LL_ENDL; + + if (SDL_Joystick* joystick = SDL_JoystickOpen(event.cdevice.which)) + { + LL_INFOS("SDL2") << "joystick " << joystick << LL_ENDL; + } + else + { + LL_WARNS("SDL2") << "Can't open joystick: " << SDL_GetError() << LL_ENDL; + } +} + +void onJoystickDeviceRemoved(const SDL_Event& event) +{ + LL_INFOS("SDL2") << "joystick id: " << event.cdevice.which << LL_ENDL; +} + +void onControllerDeviceAdded(const SDL_Event& event) +{ + std::string guid(std::to_string(SDL_JoystickGetDeviceGUID(event.cdevice.which))); + SDL_GameControllerType type(SDL_GameControllerTypeForIndex(event.cdevice.which)); + std::string name(ll_safe_string(SDL_GameControllerNameForIndex(event.cdevice.which))); + + LL_INFOS("SDL2") << "controller {id:" << event.cdevice.which + << ",guid:'" << guid << "'" + << ",type:'" << type << "'" + << ",name:'" << name << "'" + << "}" << LL_ENDL; + + SDL_JoystickID id = SDL_JoystickGetDeviceInstanceID(event.cdevice.which); + if (id < 0) + { + LL_WARNS("SDL2") << "Can't get device instance ID: " << SDL_GetError() << LL_ENDL; + return; + } + + SDL_GameController* controller = SDL_GameControllerOpen(event.cdevice.which); + if (!controller) + { + LL_WARNS("SDL2") << "Can't open game controller: " << SDL_GetError() << LL_ENDL; + return; + } + + g_manager.addController(id, guid, name); + + // this event could happen while the preferences UI is open + // in which case we need to force it to update + s_updateUI(); +} + +void onControllerDeviceRemoved(const SDL_Event& event) +{ + LL_INFOS("SDL2") << "joystick id=" << event.cdevice.which << LL_ENDL; + + SDL_JoystickID id = event.cdevice.which; + g_manager.removeController(id); + + // this event could happen while the preferences UI is open + // in which case we need to force it to update + s_updateUI(); +} + +void onControllerButton(const SDL_Event& event) +{ + g_manager.onButton(event.cbutton.which, event.cbutton.button, event.cbutton.state == SDL_PRESSED); +} + +void onControllerAxis(const SDL_Event& event) +{ + LL_DEBUGS("SDL2") << "joystick=0x" << std::hex << event.caxis.which << std::dec + << " axis=" << (S32)(event.caxis.axis) + << " value=" << (S32)(event.caxis.value) << LL_ENDL; + g_manager.onAxis(event.caxis.which, event.caxis.axis, event.caxis.value); +} + +// static +bool LLGameControl::isEnabled() +{ + return g_enabled; +} + +void LLGameControl::setEnabled(bool enable) +{ + if (enable != g_enabled) + { + g_enabled = enable; + s_saveBoolean(SETTING_ENABLE, g_enabled); + } +} + +// static +bool LLGameControl::isInitialized() +{ + return g_gameControl != nullptr; +} + +// static +// TODO: find a cleaner way to provide callbacks to LLGameControl +void LLGameControl::init(const std::string& gamecontrollerdb_path, + std::function<bool(const std::string&)> loadBoolean, + std::function<void(const std::string&, bool)> saveBoolean, + std::function<std::string(const std::string&)> loadString, + std::function<void(const std::string&, const std::string&)> saveString, + std::function<LLSD(const std::string&)> loadObject, + std::function<void(const std::string&, const LLSD&)> saveObject, + std::function<void()> updateUI) +{ + if (g_gameControl) + return; + + llassert(loadBoolean); + llassert(saveBoolean); + llassert(loadString); + llassert(saveString); + llassert(loadObject); + llassert(saveObject); + llassert(updateUI); + + int result = SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER | SDL_INIT_SENSOR); + if (result < 0) + { + // This error is critical, we stop working with SDL and return + LL_WARNS("SDL2") << "Error initializing GameController subsystems : " << SDL_GetError() << LL_ENDL; + return; + } + + // The inability to read this file is not critical, we can continue working + if (!LLFile::isfile(gamecontrollerdb_path.c_str())) + { + LL_WARNS("SDL2") << "Device mapping db file not found: " << gamecontrollerdb_path << LL_ENDL; + } + else + { + int count = SDL_GameControllerAddMappingsFromFile(gamecontrollerdb_path.c_str()); + if (count < 0) + { + LL_WARNS("SDL2") << "Error adding mappings from " << gamecontrollerdb_path << " : " << SDL_GetError() << LL_ENDL; + } + else + { + LL_INFOS("SDL2") << "Total " << count << " mappings added from " << gamecontrollerdb_path << LL_ENDL; + } + } + + g_gameControl = LLGameControl::getInstance(); + + s_loadBoolean = loadBoolean; + s_saveBoolean = saveBoolean; + s_loadString = loadString; + s_saveString = saveString; + s_loadObject = loadObject; + s_saveObject = saveObject; + s_updateUI = updateUI; + + loadFromSettings(); +} + +// static +void LLGameControl::terminate() +{ + g_manager.clear(); +} + +// static +const std::list<LLGameControl::Device>& LLGameControl::getDevices() +{ + return g_manager.mDevices; +} + +//static +const std::map<std::string, std::string>& LLGameControl::getDeviceOptions() +{ + return g_deviceOptions; +} + +//static +// returns 'true' if GameControlInput message needs to go out, +// which will be the case for new data or resend. Call this right +// before deciding to put a GameControlInput packet on the wire +// or not. +bool LLGameControl::computeFinalStateAndCheckForChanges() +{ + // Note: LLGameControllerManager::computeFinalState() modifies g_nextResendPeriod as a side-effect + g_manager.computeFinalState(); + + // should send input when: + // sending is enabled and + // g_lastSend has "expired" + // either because g_nextResendPeriod has been zeroed + // or the last send really has expired. + return g_enabled && g_sendToServer && (g_lastSend + g_nextResendPeriod < get_now_nsec()); +} + +// static +void LLGameControl::clearAllStates() +{ + g_manager.clearAllStates(); +} + +// static +void LLGameControl::processEvents(bool app_has_focus) +{ + // This method used by non-linux platforms which only use SDL for GameController input + SDL_Event event; + if (!app_has_focus) + { + // when SL window lacks focus: pump SDL events but ignore them + while (g_gameControl && SDL_PollEvent(&event)) + { + // do nothing: SDL_PollEvent() is the operator + } + g_manager.clearAllStates(); + return; + } + + while (g_gameControl && SDL_PollEvent(&event)) + { + handleEvent(event, app_has_focus); + } +} + +void LLGameControl::handleEvent(const SDL_Event& event, bool app_has_focus) +{ + switch (event.type) + { + case SDL_JOYDEVICEADDED: + onJoystickDeviceAdded(event); + break; + case SDL_JOYDEVICEREMOVED: + onJoystickDeviceRemoved(event); + break; + case SDL_CONTROLLERDEVICEADDED: + onControllerDeviceAdded(event); + break; + case SDL_CONTROLLERDEVICEREMOVED: + onControllerDeviceRemoved(event); + break; + case SDL_CONTROLLERBUTTONDOWN: + /* FALLTHROUGH */ + case SDL_CONTROLLERBUTTONUP: + if (app_has_focus) + { + onControllerButton(event); + } + break; + case SDL_CONTROLLERAXISMOTION: + if (app_has_focus) + { + onControllerAxis(event); + } + break; + default: + break; + } +} + +// static +const LLGameControl::State& LLGameControl::getState() +{ + return g_finalState; +} + +// static +LLGameControl::InputChannel LLGameControl::getActiveInputChannel() +{ + InputChannel input; + + State state = g_finalState; + if (state.mButtons > 0) + { + // check buttons + input.mType = LLGameControl::InputChannel::TYPE_BUTTON; + for (U8 i = 0; i < 32; ++i) + { + if ((0x1 << i) & state.mButtons) + { + input.mIndex = i; + break; + } + } + } + else + { + // scan axes + constexpr S16 threshold = std::numeric_limits<S16>::max() / 2; + for (U8 i = 0; i < 6; ++i) + { + if (abs(state.mAxes[i]) > threshold) + { + input.mType = LLGameControl::InputChannel::TYPE_AXIS; + // input.mIndex ultimately translates to a LLGameControl::KeyboardAxis + // which distinguishes between negative and positive directions + // so we must translate to axis index "i" according to the sign + // of the axis value. + input.mIndex = i; + input.mSign = state.mAxes[i] > 0 ? 1 : -1; + break; + } + } + } + + return input; +} + +// static +void LLGameControl::getFlycamInputs(std::vector<F32>& inputs_out) +{ + return g_manager.getFlycamInputs(inputs_out); +} + +// static +void LLGameControl::setSendToServer(bool enable) +{ + g_sendToServer = enable; + s_saveBoolean(SETTING_SENDTOSERVER, g_sendToServer); +} + +// static +void LLGameControl::setControlAgent(bool enable) +{ + g_controlAgent = enable; + s_saveBoolean(SETTING_CONTROLAGENT, g_controlAgent); +} + +// static +void LLGameControl::setTranslateAgentActions(bool enable) +{ + g_translateAgentActions = enable; + s_saveBoolean(SETTING_TRANSLATEACTIONS, g_translateAgentActions); +} + +// static +void LLGameControl::setAgentControlMode(LLGameControl::AgentControlMode mode) +{ + g_agentControlMode = mode; + s_saveString(SETTING_AGENTCONTROLMODE, convertAgentControlModeToString(mode)); +} + +// static +bool LLGameControl::getSendToServer() +{ + return g_sendToServer; +} + +// static +bool LLGameControl::getControlAgent() +{ + return g_controlAgent; +} + +// static +bool LLGameControl::getTranslateAgentActions() +{ + return g_translateAgentActions; +} + +// static +LLGameControl::AgentControlMode LLGameControl::getAgentControlMode() +{ + return g_agentControlMode; +} + +// static +LLGameControl::ActionNameType LLGameControl::getActionNameType(const std::string& action) +{ + return g_manager.getActionNameType(action); +} + +// static +bool LLGameControl::willControlAvatar() +{ + return g_enabled && g_controlAgent && g_agentControlMode == CONTROL_MODE_AVATAR; +} + +// static +// +// Given a name like "AXIS_1-" or "BUTTON_5" returns the corresponding InputChannel +// If the axis name lacks the +/- postfix it assumes '+' postfix. +LLGameControl::InputChannel LLGameControl::getChannelByName(const std::string& name) +{ + LLGameControl::InputChannel channel; + + // 'name' has two acceptable formats: AXIS_<index>[sign] or BUTTON_<index> + if (LLStringUtil::startsWith(name, "AXIS_")) + { + channel.mType = LLGameControl::InputChannel::Type::TYPE_AXIS; + // Decimal postfix is only one character + channel.mIndex = atoi(name.substr(5, 1).c_str()); + // AXIS_n can have an optional +/- at index 6 + // Assume positive axis when sign not provided + channel.mSign = name.back() == '-' ? -1 : 1; + } + else if (LLStringUtil::startsWith(name, "BUTTON_")) + { + channel.mType = LLGameControl::InputChannel::Type::TYPE_BUTTON; + // Decimal postfix is only one or two characters + channel.mIndex = atoi(name.substr(7).c_str()); + } + + return channel; +} + +// static +// Given an action_name like "push+", or "strafe-", returns the InputChannel +// mapped to it if found, else channel.isNone() will be true. +LLGameControl::InputChannel LLGameControl::getChannelByAction(const std::string& action) +{ + return g_manager.getChannelByAction(action); +} + +// static +bool LLGameControl::updateActionMap(const std::string& action, LLGameControl::InputChannel channel) +{ + return g_manager.updateActionMap(action, channel); +} + +// static +U32 LLGameControl::computeInternalActionFlags() +{ + return g_manager.computeInternalActionFlags(); +} + +// static +void LLGameControl::setExternalInput(U32 action_flags, U32 buttons) +{ + g_manager.setExternalInput(action_flags, buttons); +} + +//static +void LLGameControl::updateResendPeriod() +{ + // we expect this method to be called right after data is sent + g_lastSend = get_now_nsec(); + if (g_nextResendPeriod == 0) + { + g_nextResendPeriod = FIRST_RESEND_PERIOD; + } + else + { + // Reset mPrevAxes only on second resend or higher + // because when the joysticks are being used we expect a steady stream + // of recorrection data rather than sparse changes. + // + // (The above assumption is not necessarily true for "Actions" input + // (e.g. keyboard events). TODO: figure out what to do about this.) + // + // In other words: we want to include changed axes in the first resend + // so we only overwrite g_finalState.mPrevAxes on higher resends. + g_finalState.mPrevAxes = g_finalState.mAxes; + g_nextResendPeriod *= RESEND_EXPANSION_RATE; + } +} + +// static +std::string LLGameControl::stringifyAnalogMappings(getChannel_t getChannel) +{ + return getMappings(g_manager.mAnalogActions, InputChannel::TYPE_AXIS, getChannel); +} + +// static +std::string LLGameControl::stringifyBinaryMappings(getChannel_t getChannel) +{ + return getMappings(g_manager.mBinaryActions, InputChannel::TYPE_BUTTON, getChannel); +} + +// static +std::string LLGameControl::stringifyFlycamMappings(getChannel_t getChannel) +{ + return getMappings(g_manager.mFlycamActions, InputChannel::TYPE_AXIS, getChannel); +} + +// static +void LLGameControl::getDefaultMappings(std::vector<std::pair<std::string, LLGameControl::InputChannel>>& mappings) +{ + g_manager.getDefaultMappings(mappings); +} + +// static +bool LLGameControl::parseDeviceOptions(const std::string& options, std::string& name, + std::vector<LLGameControl::Options::AxisOptions>& axis_options, + std::vector<U8>& axis_map, std::vector<U8>& button_map) +{ + if (options.empty()) + return false; + + name.clear(); + axis_options.resize(NUM_AXES); + axis_map.resize(NUM_AXES); + button_map.resize(NUM_BUTTONS); + + for (size_t i = 0; i < NUM_AXES; ++i) + { + axis_options[i].resetToDefaults(); + axis_map[i] = (U8)i; + } + + for (size_t i = 0; i < NUM_BUTTONS; ++i) + { + button_map[i] = (U8)i; + } + + std::map<std::string, std::string> pairs; + if (!parse(pairs, options)) + { + LL_WARNS("SDL2") << "Invalid options: '" << options << "'" << LL_ENDL; + return false; + } + + std::map<std::string, std::string> axis_string_options; + if (!parse(axis_string_options, pairs["axis_options"])) + { + LL_WARNS("SDL2") << "Invalid axis_options: '" << pairs["axis_options"] << "'" << LL_ENDL; + return false; + } + + std::map<std::string, std::string> axis_string_map; + if (!parse(axis_string_map, pairs["axis_map"])) + { + LL_WARNS("SDL2") << "Invalid axis_map: '" << pairs["axis_map"] << "'" << LL_ENDL; + return false; + } + + std::map<std::string, std::string> button_string_map; + if (!parse(button_string_map, pairs["button_map"])) + { + LL_WARNS("SDL2") << "Invalid button_map: '" << pairs["button_map"] << "'" << LL_ENDL; + return false; + } + + name = pairs["name"]; + + for (size_t i = 0; i < NUM_AXES; ++i) + { + std::string key = std::to_string(i); + + std::string one_axis_options = axis_string_options[key]; + if (!one_axis_options.empty()) + { + axis_options[i].loadFromString(one_axis_options); + } + + std::string value = axis_string_map[key]; + if (!value.empty()) + { + size_t number = std::stoull(value); + if (number >= NUM_AXES || std::to_string(number) != value) + { + LL_WARNS("SDL2") << "Invalid axis mapping: " << i << "->" << value << LL_ENDL; + } + else + { + axis_map[i] = (U8)number; + } + } + } + + for (size_t i = 0; i < NUM_BUTTONS; ++i) + { + std::string value = button_string_map[std::to_string(i)]; + if (!value.empty()) + { + size_t number = std::stoull(value); + if (number >= NUM_BUTTONS || std::to_string(number) != value) + { + LL_WARNS("SDL2") << "Invalid button mapping: " << i << "->" << value << LL_ENDL; + } + else + { + button_map[i] = (U8)number; + } + } + } + + return true; +} + +// static +std::string LLGameControl::stringifyDeviceOptions(const std::string& name, + const std::vector<LLGameControl::Options::AxisOptions>& axis_options, + const std::vector<U8>& axis_map, const std::vector<U8>& button_map, + bool force_empty) +{ + std::list<std::string> options; + + auto opts2str = [](size_t i, const Options::AxisOptions& options) -> std::string + { + std::string string = options.saveToString(); + return string.empty() ? string : llformat("%u:%s", i, string.c_str()); + }; + + std::string axis_options_string = LLStringUtil::join<std::vector<Options::AxisOptions>, Options::AxisOptions>(axis_options, opts2str); + if (!axis_options_string.empty()) + { + options.push_back("axis_options:{" + axis_options_string + "}"); + } + + auto map2str = [](size_t index, const U8& value) -> std::string + { + return value == index ? LLStringUtil::null : llformat("%u:%u", index, value); + }; + + std::string axis_map_string = LLStringUtil::join<std::vector<U8>, U8>(axis_map, map2str); + if (!axis_map_string.empty()) + { + options.push_back("axis_map:{" + axis_map_string + "}"); + } + + std::string button_map_string = LLStringUtil::join<std::vector<U8>, U8>(button_map, map2str); + if (!button_map_string.empty()) + { + options.push_back("button_map:{" + button_map_string + "}"); + } + + if (!force_empty && options.empty()) + return LLStringUtil::null; + + // Remove control characters [',', '{', '}'] from name + std::string safe_name; + safe_name.reserve(name.size()); + for (char c : name) + { + if (c != ',' && c != '{' && c != '}') + { + safe_name.push_back(c); + } + } + options.push_front(llformat("name:%s", safe_name.c_str())); + + std::string result = LLStringUtil::join(options); + + return "{" + result + "}"; +} + +// static +void LLGameControl::initByDefault() +{ + g_sendToServer = false; + g_controlAgent = false; + g_translateAgentActions = false; + g_agentControlMode = CONTROL_MODE_AVATAR; + g_manager.initializeMappingsByDefault(); + g_manager.resetDeviceOptionsToDefaults(); + g_deviceOptions.clear(); +} + +// static +void LLGameControl::loadFromSettings() +{ + // In case of absence of the required setting the default value is assigned + g_enabled = s_loadBoolean(SETTING_ENABLE); + g_sendToServer = s_loadBoolean(SETTING_SENDTOSERVER); + g_controlAgent = s_loadBoolean(SETTING_CONTROLAGENT); + g_translateAgentActions = s_loadBoolean(SETTING_TRANSLATEACTIONS); + g_agentControlMode = convertStringToAgentControlMode(s_loadString(SETTING_AGENTCONTROLMODE)); + + g_manager.initializeMappingsByDefault(); + + // Load action-to-channel mappings + std::string analogMappings = s_loadString(SETTING_ANALOGMAPPINGS); + std::string binaryMappings = s_loadString(SETTING_BINARYMAPPINGS); + std::string flycamMappings = s_loadString(SETTING_FLYCAMMAPPINGS); + g_manager.setAnalogMappings(analogMappings); + g_manager.setBinaryMappings(binaryMappings); + g_manager.setFlycamMappings(flycamMappings); + + // Load device-specific settings + g_deviceOptions.clear(); + LLSD options = s_loadObject(SETTING_KNOWNCONTROLLERS); + for (auto it = options.beginMap(); it != options.endMap(); ++it) + { + g_deviceOptions.emplace(it->first, it->second); + } + g_manager.loadDeviceOptionsFromSettings(); +} + +// static +void LLGameControl::saveToSettings() +{ + s_saveBoolean(SETTING_ENABLE, g_enabled); + s_saveBoolean(SETTING_SENDTOSERVER, g_sendToServer); + s_saveBoolean(SETTING_CONTROLAGENT, g_controlAgent); + s_saveBoolean(SETTING_TRANSLATEACTIONS, g_translateAgentActions); + s_saveString(SETTING_AGENTCONTROLMODE, convertAgentControlModeToString(g_agentControlMode)); + s_saveString(SETTING_ANALOGMAPPINGS, g_manager.getAnalogMappings()); + s_saveString(SETTING_BINARYMAPPINGS, g_manager.getBinaryMappings()); + s_saveString(SETTING_FLYCAMMAPPINGS, g_manager.getFlycamMappings()); + + g_manager.saveDeviceOptionsToSettings(); + + // construct LLSD version of g_deviceOptions but only include non-empty values + LLSD deviceOptions = LLSD::emptyMap(); + for (const auto& data_pair : g_deviceOptions) + { + if (!data_pair.second.empty()) + { + LLSD value(data_pair.second); + deviceOptions.insert(data_pair.first, value); + } + } + + s_saveObject(SETTING_KNOWNCONTROLLERS, deviceOptions); +} + +// static +void LLGameControl::setDeviceOptions(const std::string& guid, const Options& options) +{ + g_manager.setDeviceOptions(guid, options); +} diff --git a/indra/llwindow/llgamecontrol.h b/indra/llwindow/llgamecontrol.h new file mode 100644 index 0000000000..a4b47cc47f --- /dev/null +++ b/indra/llwindow/llgamecontrol.h @@ -0,0 +1,347 @@ +/** + * @file llgamecontrol.h + * @brief GameController detection and management + * + * $LicenseInfo:firstyear=2023&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2023, 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$ + */ + +#pragma once + +#include <vector> + + +#include "llerror.h" +#include "llsingleton.h" +#include "stdtypes.h" +#include "SDL2/SDL_events.h" + +// For reference, here are the RAW indices of the various input channels +// of a standard XBox controller. Button (N) is numbered in parentheses, +// whereas axisN has N+ and N- labels. +// +// leftpaddle rightpaddle +// _______ _______ +// / 4+ '-. .-' 5+ \. +// leftshoulder _(9)_________'-.____ ____.-'_________(10) rightshoulder +// / _________ \_________/ \. +// / / 1- \ (3) \. +// | | | (4) (5) (6) Y | +// | |0- (7) 0+| _________ (2)X B(1) | +// | | | / 3- \ A | +// | | 1+ | | | (0) | +// | \_________/ |2- (8) 2+| | +// | leftstick (11) | | | +// | (13) (14) | 3+ | | +// | (12) \_________/ | +// | d-pad rightstick | +// | ____________________ | +// | / \ | +// | / \ | +// | / \ | +// \__________/ \__________/ +// +// Note: the analog joysticks provide NEGATIVE X,Y values for LEFT,FORWARD +// whereas those directions are actually POSITIVE in SL's local right-handed +// reference frame. This is why we implicitly negate those axes the moment +// they are extracted from SDL, before being used anywhere. See the +// implementation in LLGameControllerManager::onAxis(). + +// LLGameControl is a singleton with pure static public interface +class LLGameControl : public LLSingleton<LLGameControl> +{ + LLSINGLETON_EMPTY_CTOR(LLGameControl); + virtual ~LLGameControl(); + LOG_CLASS(LLGameControl); + +public: + enum AgentControlMode + { + CONTROL_MODE_AVATAR, + CONTROL_MODE_FLYCAM, + CONTROL_MODE_NONE + }; + + enum ActionNameType + { + ACTION_NAME_UNKNOWN, + ACTION_NAME_ANALOG, // E.g., "push" + ACTION_NAME_ANALOG_POS, // E.g., "push+" + ACTION_NAME_ANALOG_NEG, // E.g., "push-" + ACTION_NAME_BINARY, // E.g., "stop" + ACTION_NAME_FLYCAM // E.g., "zoom" + }; + + enum KeyboardAxis : U8 + { + AXIS_LEFTX, + AXIS_LEFTY, + AXIS_RIGHTX, + AXIS_RIGHTY, + AXIS_TRIGGERLEFT, + AXIS_TRIGGERRIGHT, + NUM_AXES + }; + + enum Button + { + BUTTON_A, + BUTTON_B, + BUTTON_X, + BUTTON_Y, + BUTTON_BACK, + BUTTON_GUIDE, + BUTTON_START, + BUTTON_LEFTSTICK, + BUTTON_RIGHTSTICK, + BUTTON_LEFTSHOULDER, + BUTTON_RIGHTSHOULDER, // 10 + BUTTON_DPAD_UP, + BUTTON_DPAD_DOWN, + BUTTON_DPAD_LEFT, + BUTTON_DPAD_RIGHT, + BUTTON_MISC1, + BUTTON_PADDLE1, + BUTTON_PADDLE2, + BUTTON_PADDLE3, + BUTTON_PADDLE4, + BUTTON_TOUCHPAD, // 20 + BUTTON_21, + BUTTON_22, + BUTTON_23, + BUTTON_24, + BUTTON_25, + BUTTON_26, + BUTTON_27, + BUTTON_28, + BUTTON_29, + BUTTON_30, + BUTTON_31, + NUM_BUTTONS + }; + + static const U16 MAX_AXIS_DEAD_ZONE = 16384; + static const U16 MAX_AXIS_OFFSET = 16384; + + class InputChannel + { + public: + enum Type + { + TYPE_NONE, + TYPE_AXIS, + TYPE_BUTTON + }; + + InputChannel() {} + InputChannel(Type type, U8 index) : mType(type), mIndex(index) {} + InputChannel(Type type, U8 index, S32 sign) : mType(type), mSign(sign), mIndex(index) {} + + // these methods for readability + bool isNone() const { return mType == TYPE_NONE; } + bool isAxis() const { return mType == TYPE_AXIS; } + bool isButton() const { return mType == TYPE_BUTTON; } + + bool isEqual(const InputChannel& other) + { + return mType == other.mType && mSign == other.mSign && mIndex == other.mIndex; + } + + std::string getLocalName() const; // AXIS_0-, AXIS_0+, BUTTON_0, NONE etc. + std::string getRemoteName() const; // GAME_CONTROL_AXIS_LEFTX, GAME_CONTROL_BUTTON_A, etc + + Type mType { TYPE_NONE }; + S32 mSign { 0 }; + U8 mIndex { 255 }; + }; + + // Options is a data structure for storing device-specific settings + class Options + { + public: + struct AxisOptions + { + S32 mMultiplier = 1; + U16 mDeadZone { 0 }; + S16 mOffset { 0 }; + + void resetToDefaults() + { + mMultiplier = 1; + mDeadZone = 0; + mOffset = 0; + } + + S16 computeModifiedValue(S16 raw_value) const + { + S32 new_value = ((S32)raw_value + S32(mOffset)) * mMultiplier; + return (S16)(std::clamp(new_value, -32768, 32767)); + } + + std::string saveToString() const; + void loadFromString(std::string options); + }; + + Options(); + + void resetToDefaults(); + + U8 mapAxis(U8 axis) const; + U8 mapButton(U8 button) const; + + S16 fixAxisValue(U8 axis, S16 value) const; + + std::string saveToString(const std::string& name, bool force_empty = false) const; + bool loadFromString(std::string& name, std::string options); + bool loadFromString(std::string options); + + const std::vector<AxisOptions>& getAxisOptions() const { return mAxisOptions; } + std::vector<AxisOptions>& getAxisOptions() { return mAxisOptions; } + const std::vector<U8>& getAxisMap() const { return mAxisMap; } + std::vector<U8>& getAxisMap() { return mAxisMap; } + const std::vector<U8>& getButtonMap() const { return mButtonMap; } + std::vector<U8>& getButtonMap() { return mButtonMap; } + + private: + std::vector<AxisOptions> mAxisOptions; + std::vector<U8> mAxisMap; + std::vector<U8> mButtonMap; + }; + + // State is a minimal class for storing axes and buttons values + class State + { + public: + State(); + void clear(); + bool onButton(U8 button, bool pressed); + std::vector<S16> mAxes; // [ -32768, 32767 ] + std::vector<S16> mPrevAxes; // value in last outgoing packet + U32 mButtons; + }; + + // Device is a data structure for describing any detected controller + class Device + { + const int mJoystickID { -1 }; + const std::string mGUID; + const std::string mName; + Options mOptions; + State mState; + + public: + Device(int joystickID, const std::string& guid, const std::string& name); + int getJoystickID() const { return mJoystickID; } + std::string getGUID() const { return mGUID; } + std::string getName() const { return mName; } + const Options& getOptions() const { return mOptions; } + const State& getState() const { return mState; } + + void resetOptionsToDefaults() { mOptions.resetToDefaults(); } + std::string saveOptionsToString(bool force_empty = false) const { return mOptions.saveToString(mName, force_empty); } + void loadOptionsFromString(const std::string& options) { mOptions.loadFromString(options); } + + friend class LLGameControllerManager; + }; + + static bool isEnabled(); + static void setEnabled(bool enabled); + + static bool isInitialized(); + static void init(const std::string& gamecontrollerdb_path, + std::function<bool(const std::string&)> loadBoolean, + std::function<void(const std::string&, bool)> saveBoolean, + std::function<std::string(const std::string&)> loadString, + std::function<void(const std::string&, const std::string&)> saveString, + std::function<LLSD(const std::string&)> loadObject, + std::function<void(const std::string&, const LLSD&)> saveObject, + std::function<void()> updateUI); + static void terminate(); + + static const std::list<LLGameControl::Device>& getDevices(); + static const std::map<std::string, std::string>& getDeviceOptions(); + + // returns 'true' if GameControlInput message needs to go out, + // which will be the case for new data or resend. Call this right + // before deciding to put a GameControlInput packet on the wire + // or not. + static bool computeFinalStateAndCheckForChanges(); + + static void clearAllStates(); + + static void processEvents(bool app_has_focus = true); + static void handleEvent(const SDL_Event& event, bool app_has_focus); + static const State& getState(); + static InputChannel getActiveInputChannel(); + static void getFlycamInputs(std::vector<F32>& inputs_out); + + // these methods for accepting input from keyboard + static void setSendToServer(bool enable); + static void setControlAgent(bool enable); + static void setTranslateAgentActions(bool enable); + static void setAgentControlMode(AgentControlMode mode); + + static bool getSendToServer(); + static bool getControlAgent(); + static bool getTranslateAgentActions(); + static AgentControlMode getAgentControlMode(); + static ActionNameType getActionNameType(const std::string& action); + + static bool willControlAvatar(); + + // Given a name like "AXIS_1-" or "BUTTON_5" returns the corresponding InputChannel + // If the axis name lacks the +/- postfix it assumes '+' postfix. + static LLGameControl::InputChannel getChannelByName(const std::string& name); + + // action_name = push+, strafe-, etc + static LLGameControl::InputChannel getChannelByAction(const std::string& action); + + static bool updateActionMap(const std::string& action_name, LLGameControl::InputChannel channel); + + // Keyboard presses produce action_flags which can be translated into State + // and game_control devices produce State which can be translated into action_flags. + // These methods help exchange such translations. + static U32 computeInternalActionFlags(); + static void setExternalInput(U32 action_flags, U32 buttons_from_keys); + + // call this after putting a GameControlInput packet on the wire + static void updateResendPeriod(); + + using getChannel_t = std::function<LLGameControl::InputChannel(const std::string& action)>; + static std::string stringifyAnalogMappings(getChannel_t getChannel); + static std::string stringifyBinaryMappings(getChannel_t getChannel); + static std::string stringifyFlycamMappings(getChannel_t getChannel); + static void getDefaultMappings(std::vector<std::pair<std::string, LLGameControl::InputChannel>>& mappings); + + static bool parseDeviceOptions(const std::string& options, std::string& name, + std::vector<LLGameControl::Options::AxisOptions>& axis_options, + std::vector<U8>& axis_map, std::vector<U8>& button_map); + static std::string stringifyDeviceOptions(const std::string& name, + const std::vector<LLGameControl::Options::AxisOptions>& axis_options, + const std::vector<U8>& axis_map, const std::vector<U8>& button_map, + bool force_empty = false); + + static void initByDefault(); + static void loadFromSettings(); + static void saveToSettings(); + static void setDeviceOptions(const std::string& guid, const Options& options); +}; + diff --git a/indra/llwindow/llgamecontroltranslator.cpp b/indra/llwindow/llgamecontroltranslator.cpp new file mode 100644 index 0000000000..84468ab657 --- /dev/null +++ b/indra/llwindow/llgamecontroltranslator.cpp @@ -0,0 +1,275 @@ +/** + * @file llgamecontroltranslator.cpp + * @brief LLGameControlTranslator class implementation + * + * $LicenseInfo:firstyear=2023&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2023, 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$ + */ + +/* + * App-wide preferences. Note that these are not per-user, + * because we need to load many preferences before we have + * a login name. + */ + +#include "llgamecontroltranslator.h" +#include "llsd.h" + + +using ActionToMaskMap = LLGameControlTranslator::ActionToMaskMap; + +LLGameControlTranslator::LLGameControlTranslator() +{ +} + +void LLGameControlTranslator::setAvailableActionMasks(ActionToMaskMap& action_to_mask) +{ + mActionToMask = std::move(action_to_mask); +} + +LLGameControl::InputChannel LLGameControlTranslator::getChannelByAction(const std::string& action) const +{ + LLGameControl::InputChannel channel; + auto mask_itr = mActionToMask.find(action); + if (mask_itr != mActionToMask.end()) + { + U32 mask = mask_itr->second; + auto channel_itr = mMaskToChannel.find(mask); + if (channel_itr != mMaskToChannel.end()) + { + channel = channel_itr->second; + } + } + else + { + // It is expected that sometimes 'action' lacks the postfix '+' or '-'. + // When it is missing we append '+' and try again. + std::string action_plus = action; + action_plus.append("+"); + mask_itr = mActionToMask.find(action_plus); + if (mask_itr != mActionToMask.end()) + { + U32 mask = mask_itr->second; + auto channel_itr = mMaskToChannel.find(mask); + if (channel_itr != mMaskToChannel.end()) + { + channel = channel_itr->second; + } + } + } + return channel; +} + +void LLGameControlTranslator::setMappings(LLGameControlTranslator::NamedChannels& named_channels) +{ + mMaskToChannel.clear(); + mMappedFlags = 0; + mPrevActiveFlags = 0; + mCachedState.clear(); + + for (const auto& named_channel : named_channels) + { + updateMap(named_channel.first, named_channel.second); + } +} + +void LLGameControlTranslator::updateMap(const std::string& action, const LLGameControl::InputChannel& channel) +{ + // First, get the action name type + LLGameControl::ActionNameType actionNameType = LLGameControl::getActionNameType(action); + if (actionNameType == LLGameControl::ACTION_NAME_UNKNOWN || + actionNameType == LLGameControl::ACTION_NAME_FLYCAM) + { + LL_WARNS("SDL2") << "unmappable action='" << action << "' (type=" << actionNameType << ")" << LL_ENDL; + return; + } + + // Second, get the expected associated channel type (except of TYPE_NONE) + LLGameControl::InputChannel::Type expectedChannelType = + actionNameType == LLGameControl::ACTION_NAME_BINARY ? + LLGameControl::InputChannel::TYPE_BUTTON : + LLGameControl::InputChannel::TYPE_AXIS; + if (!channel.isNone() && (channel.mType != expectedChannelType)) + { + LL_WARNS("SDL2") << "unmappable channel (type=" << channel.mType << ")" + << " for action='" << action << "' (type=" << actionNameType << ")" << LL_ENDL; + return; + } + + if (actionNameType == LLGameControl::ACTION_NAME_ANALOG) // E.g., "push" + { + // Special (double) processing for analog action names + // sequentially adding '+' and '-' to the given action + updateMapInternal(action + "+", channel); + + // For the channel type TYPE_NONE we can map the same channel + // In fact, the mapping will be removed from the mapping list + if (channel.isNone()) + { + updateMapInternal(action + "-", channel); + } + else + { + // For the channel type except of TYPE_NONE we construct the other channel + // with the same type and index but with the opposite sign + LLGameControl::InputChannel other_channel(channel.mType, channel.mIndex, -channel.mSign); + + // TIED TRIGGER HACK: this works for XBox and similar controllers, + // and those are pretty much the only supported devices right now + // however TODO: figure out how to do this better. + // + // AXIS_TRIGGERLEFT and AXIS_TRIGGERRIGHT are separate axes and most devices + // only allow them to read positive, not negative. When used for motion control + // they are typically paired together. We assume as much here when computing + // the other_channel. + if (channel.mIndex == LLGameControl::AXIS_TRIGGERLEFT) + { + other_channel.mIndex = LLGameControl::AXIS_TRIGGERRIGHT; + other_channel.mSign = 1; + } + else if (channel.mIndex == LLGameControl::AXIS_TRIGGERRIGHT) + { + other_channel.mIndex = LLGameControl::AXIS_TRIGGERLEFT; + other_channel.mSign = 1; + } + updateMapInternal(action + "-", other_channel); + } + } + else + { + // Simple (single) processing for other action name types + updateMapInternal(action, channel); + } + + // recompute mMappedFlags + mMappedFlags = 0; + for (auto& pair : mMaskToChannel) + { + mMappedFlags |= pair.first; + } + mPrevActiveFlags = 0; + mCachedState.clear(); +} + +// Given external action_flags (i.e. raw avatar input) +// compute the corresponding LLGameControl::State that would have produced those flags. +// Note: "action flags" are similar to, but not quite the same as, "control flags". +// "Action flags" are the raw input of avatar movement intent, whereas "control flags" +// are the consequential set of instructions that are sent to the server for moving +// the avatar character. +const LLGameControl::State& LLGameControlTranslator::computeStateFromFlags(U32 action_flags) +{ + // translate action_flag bits to equivalent game controller state + // according to data in mMaskToChannel + + // only bother to update mCachedState if active_flags have changed + U32 active_flags = action_flags & mMappedFlags; + if (active_flags != mPrevActiveFlags) + { + mCachedState.clear(); + for (const auto& pair : mMaskToChannel) + { + U32 mask = pair.first; + if (mask == (mask & action_flags)) + { + LLGameControl::InputChannel channel = pair.second; + if (channel.isAxis()) + { + if (channel.mSign < 0) + { + mCachedState.mAxes[channel.mIndex] = std::numeric_limits<S16>::min(); + } + else + { + mCachedState.mAxes[channel.mIndex] = std::numeric_limits<S16>::max(); + } + } + else if (channel.isButton()) + { + mCachedState.mButtons |= 0x01U << channel.mIndex; + } + } + } + mPrevActiveFlags = active_flags; + } + return mCachedState; +} + +// Given LLGameControl::State (i.e. from a real controller) +// compute corresponding action flags (e.g. for moving the avatar around) +U32 LLGameControlTranslator::computeFlagsFromState(const std::vector<S32>& axes, U32 buttons) +{ + // HACK: supply hard-coded threshold for ON/OFF zones + constexpr S32 AXIS_THRESHOLD = 32768 / 8; + U32 action_flags = 0; + for (const auto& pair : mMaskToChannel) + { + // pair = { mask, channel } + const LLGameControl::InputChannel& channel = pair.second; + if (channel.isAxis()) + { + if (channel.mSign < 0) + { + if (axes[channel.mIndex] < -AXIS_THRESHOLD) + { + action_flags |= pair.first; + } + } + else if (axes[channel.mIndex] > AXIS_THRESHOLD) + { + action_flags |= pair.first; + } + } + else if (channel.isButton()) + { + U32 bit_set = buttons & (0x01U << channel.mIndex); + if (bit_set) + { + action_flags |= pair.first; + } + } + } + return action_flags; +} + +void LLGameControlTranslator::updateMapInternal(const std::string& name, const LLGameControl::InputChannel& channel) +{ + auto action_it = mActionToMask.find(name); + llassert(action_it != mActionToMask.end()); + U32 mask = action_it->second; + auto channel_it = mMaskToChannel.find(mask); + if (channel_it == mMaskToChannel.end()) + { + // create new mapping + mMaskToChannel[mask] = channel; + } + else if (channel.isNone()) + { + // remove old mapping + mMaskToChannel.erase(channel_it); + } + else + { + // update old mapping + channel_it->second = channel; + } +} + diff --git a/indra/llwindow/llgamecontroltranslator.h b/indra/llwindow/llgamecontroltranslator.h new file mode 100644 index 0000000000..533408014c --- /dev/null +++ b/indra/llwindow/llgamecontroltranslator.h @@ -0,0 +1,93 @@ +/** + * @file llgamecontroltranslator.h + * @brief LLGameControlTranslator class definition + * + * $LicenseInfo:firstyear=2023&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2023, 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$ + */ + +#pragma once + +#include <map> + +#include "stdtypes.h" +#include "llgamecontrol.h" + + +// GameControl data is sent to the server to expose game controller input to LSL scripts, +// however not everyone will have a game controller device. To allow keyboard users to provide +// GameControl data we allow the User to configure equivalences between avatar actions +// (i.e. "push forward", "strafe left", etc) and keyboard buttons to GameControl axes +// and buttons. +// +// The LLGameControlTranslator stores the equivalences and translates avatar action_flags +// and keyboard state into GameContrl data, and in some cases the other direction: from +// LLGameControl::State into avatar action_flags. +// + +class LLGameControlTranslator +{ +public: + + using ActionToMaskMap = std::map< std::string, U32 >; // < action : mask > + using MaskToChannelMap = std::map< U32, LLGameControl::InputChannel >; // < mask : channel > + using NamedChannel = std::pair < std::string , LLGameControl::InputChannel >; + using NamedChannels = std::vector< NamedChannel >; + + + LLGameControlTranslator(); + void setAvailableActionMasks(ActionToMaskMap& action_to_mask); + LLGameControl::InputChannel getChannelByAction(const std::string& action) const; + void setMappings(NamedChannels& named_channels); + void updateMap(const std::string& action, const LLGameControl::InputChannel& channel); + // Note: to remove a mapping you can call updateMap() with a TYPE_NONE channel + + // Given external action_flags (i.e. raw avatar input) + // compute the corresponding LLGameControl::State that would have produced those flags. + // Note: "action_flags" are similar to, but not quite the same as, "control_flags". + const LLGameControl::State& computeStateFromFlags(U32 action_flags); + + // Given LLGameControl::State (i.e. from a real controller) + // compute corresponding action flags (e.g. for moving the avatar around) + U32 computeFlagsFromState(const std::vector<S32>& axes, U32 buttons); + + U32 getMappedFlags() const { return mMappedFlags; } + +private: + void updateMapInternal(const std::string& name, const LLGameControl::InputChannel& channel); + +private: + // mActionToMask is an invarient map between the possible actions + // and the action bit masks. Only actions therein can have their + // bit masks mapped to channels. + ActionToMaskMap mActionToMask; // invariant map after init + + // mMaskToChannel is a dynamic map between action bit masks + // and GameControl channels. + MaskToChannelMap mMaskToChannel; // dynamic map, per preference changes + + // mCachedState is an optimization: + // it is only recomputed when external action_flags change + LLGameControl::State mCachedState; + + U32 mMappedFlags { 0 }; + U32 mPrevActiveFlags { 0 }; +}; diff --git a/indra/llwindow/llkeyboard.cpp b/indra/llwindow/llkeyboard.cpp index a16c0a318a..cb0c312a1d 100644 --- a/indra/llwindow/llkeyboard.cpp +++ b/indra/llwindow/llkeyboard.cpp @@ -161,6 +161,7 @@ void LLKeyboard::resetKeyDownAndHandle() mCallbacks->handleTranslatedKeyUp(i, mask); } } + mCurTranslatedKey = KEY_NONE; } // BUG this has to be called when an OS dialog is shown, otherwise modifier key state @@ -226,7 +227,7 @@ LLKeyboard::NATIVE_KEY_TYPE LLKeyboard::inverseTranslateKey(const KEY translated } -bool LLKeyboard::handleTranslatedKeyDown(KEY translated_key, U32 translated_mask) +bool LLKeyboard::handleTranslatedKeyDown(KEY translated_key, MASK translated_mask) { bool handled = false; bool repeated = false; @@ -254,7 +255,7 @@ bool LLKeyboard::handleTranslatedKeyDown(KEY translated_key, U32 translated_mask } -bool LLKeyboard::handleTranslatedKeyUp(KEY translated_key, U32 translated_mask) +bool LLKeyboard::handleTranslatedKeyUp(KEY translated_key, MASK translated_mask) { bool handled = false; if( mKeyLevel[translated_key] ) @@ -276,6 +277,32 @@ bool LLKeyboard::handleTranslatedKeyUp(KEY translated_key, U32 translated_mask) } +bool LLKeyboard::handleKeyDown(const NATIVE_KEY_TYPE key, const MASK mask) +{ + MASK translated_mask = updateModifiers(mask); + KEY translated_key = 0; + bool handled = false; + if(translateKey(key, &translated_key)) + { + handled = handleTranslatedKeyDown(translated_key, translated_mask); + } + return handled; +} + + +bool LLKeyboard::handleKeyUp(const NATIVE_KEY_TYPE key, const MASK mask) +{ + MASK translated_mask = updateModifiers(mask); + KEY translated_key = 0; + bool handled = false; + if(translateKey(key, &translated_key)) + { + handled = handleTranslatedKeyUp(translated_key, translated_mask); + } + return handled; +} + + void LLKeyboard::toggleInsertMode() { if (LL_KIM_INSERT == mInsertMode) diff --git a/indra/llwindow/llkeyboard.h b/indra/llwindow/llkeyboard.h index d3c35b1ed4..c092f55685 100644 --- a/indra/llwindow/llkeyboard.h +++ b/indra/llwindow/llkeyboard.h @@ -55,10 +55,12 @@ class LLWindowCallbacks; class LLKeyboard { public: -#ifndef LL_SDL - typedef U16 NATIVE_KEY_TYPE; -#else +#ifdef LL_USE_SDL_KEYBOARD + // linux relies on SDL2 which uses U32 for its native key type typedef U32 NATIVE_KEY_TYPE; +#else + // on non-linux platforms we can get by with a smaller native key type + typedef U16 NATIVE_KEY_TYPE; #endif LLKeyboard(); virtual ~LLKeyboard(); @@ -73,17 +75,14 @@ public: bool getKeyRepeated(const KEY key) { return mKeyRepeated[key]; } bool translateKey(const NATIVE_KEY_TYPE os_key, KEY *translated_key); - NATIVE_KEY_TYPE inverseTranslateKey(const KEY translated_key); - bool handleTranslatedKeyUp(KEY translated_key, U32 translated_mask); // Translated into "Linden" keycodes - bool handleTranslatedKeyDown(KEY translated_key, U32 translated_mask); // Translated into "Linden" keycodes + NATIVE_KEY_TYPE inverseTranslateKey(const KEY translated_key); + bool handleTranslatedKeyUp(KEY translated_key, MASK translated_mask); // Translated into "Linden" keycodes + bool handleTranslatedKeyDown(KEY translated_key, MASK translated_mask); // Translated into "Linden" keycodes virtual bool handleKeyUp(const NATIVE_KEY_TYPE key, MASK mask) = 0; virtual bool handleKeyDown(const NATIVE_KEY_TYPE key, MASK mask) = 0; -#ifdef LL_DARWIN - // We only actually use this for macOS. - virtual void handleModifier(MASK mask) = 0; -#endif // LL_DARWIN + virtual void handleModifier(MASK mask) { } // Asynchronously poll the control, alt, and shift keys and set the // appropriate internal key masks. @@ -113,6 +112,7 @@ public: protected: void addKeyName(KEY key, const std::string& name); + virtual MASK updateModifiers(const MASK mask) { return mask; } protected: std::map<NATIVE_KEY_TYPE, KEY> mTranslateKeyMap; // Map of translations from OS keys to Linden KEYs diff --git a/indra/llwindow/llkeyboardheadless.cpp b/indra/llwindow/llkeyboardheadless.cpp index ad8e42a412..0ca8c09f42 100644 --- a/indra/llwindow/llkeyboardheadless.cpp +++ b/indra/llwindow/llkeyboardheadless.cpp @@ -31,6 +31,16 @@ LLKeyboardHeadless::LLKeyboardHeadless() { } +bool LLKeyboardHeadless::handleKeyUp(const LLKeyboard::NATIVE_KEY_TYPE key, MASK mask) +{ + return false; +} + +bool LLKeyboardHeadless::handleKeyDown(const LLKeyboard::NATIVE_KEY_TYPE key, MASK mask) +{ + return false; +} + void LLKeyboardHeadless::resetMaskKeys() { } @@ -57,6 +67,7 @@ void LLKeyboardHeadless::scanKeyboard() mCallbacks->handleScanKey(key, mKeyDown[key], mKeyUp[key], mKeyLevel[key]); } } + mCurScanKey = KEY_NONE; // Reset edges for next frame for (S32 key = 0; key < KEY_COUNT; key++) diff --git a/indra/llwindow/llkeyboardheadless.h b/indra/llwindow/llkeyboardheadless.h index 439abaf25b..60c4d61e1c 100644 --- a/indra/llwindow/llkeyboardheadless.h +++ b/indra/llwindow/llkeyboardheadless.h @@ -33,20 +33,15 @@ class LLKeyboardHeadless : public LLKeyboard { public: LLKeyboardHeadless(); - /*virtual*/ ~LLKeyboardHeadless() {}; + ~LLKeyboardHeadless() {}; -#ifndef LL_SDL - /*virtual*/ bool handleKeyUp(const U16 key, MASK mask) { return false; } - /*virtual*/ bool handleKeyDown(const U16 key, MASK mask) { return false; } -#else - /*virtual*/ bool handleKeyUp(const U32 key, MASK mask) { return false; } - /*virtual*/ bool handleKeyDown(const U32 key, MASK mask) { return false; } -#endif - /*virtual*/ void resetMaskKeys(); - /*virtual*/ MASK currentMask(bool for_mouse_event); - /*virtual*/ void scanKeyboard(); + bool handleKeyUp(const LLKeyboard::NATIVE_KEY_TYPE key, MASK mask) override; + bool handleKeyDown(const LLKeyboard::NATIVE_KEY_TYPE key, MASK mask) override; + void resetMaskKeys() override; + MASK currentMask(bool for_mouse_event) override; + void scanKeyboard() override; #ifdef LL_DARWIN - /*virtual*/ void handleModifier(MASK mask); + void handleModifier(MASK mask) override; #endif }; diff --git a/indra/llwindow/llkeyboardmacosx.cpp b/indra/llwindow/llkeyboardmacosx.cpp index 89ff7c6d3f..1a403e5d94 100644 --- a/indra/llwindow/llkeyboardmacosx.cpp +++ b/indra/llwindow/llkeyboardmacosx.cpp @@ -162,7 +162,7 @@ LLKeyboardMacOSX::LLKeyboardMacOSX() void LLKeyboardMacOSX::resetMaskKeys() { - U32 mask = getModifiers(); + MASK mask = getModifiers(); // MBW -- XXX -- This mirrors the operation of the Windows version of resetMaskKeys(). // It looks a bit suspicious, as it won't correct for keys that have been released. @@ -187,7 +187,7 @@ void LLKeyboardMacOSX::resetMaskKeys() } /* -static bool translateKeyMac(const U16 key, const U32 mask, KEY &outKey, U32 &outMask) +static bool translateKeyMac(const U16 key, const MASK mask, KEY &outKey, U32 &outMask) { // Translate the virtual keycode into the keycodes the keyboard system expects. U16 virtualKey = (mask >> 24) & 0x0000007F; @@ -203,7 +203,7 @@ void LLKeyboardMacOSX::handleModifier(MASK mask) updateModifiers(mask); } -MASK LLKeyboardMacOSX::updateModifiers(const U32 mask) +MASK LLKeyboardMacOSX::updateModifiers(const MASK mask) { // translate the mask MASK out_mask = 0; @@ -226,7 +226,7 @@ MASK LLKeyboardMacOSX::updateModifiers(const U32 mask) return out_mask; } -bool LLKeyboardMacOSX::handleKeyDown(const U16 key, const U32 mask) +bool LLKeyboardMacOSX::handleKeyDown(const U16 key, MASK mask) { KEY translated_key = 0; U32 translated_mask = 0; @@ -243,7 +243,7 @@ bool LLKeyboardMacOSX::handleKeyDown(const U16 key, const U32 mask) } -bool LLKeyboardMacOSX::handleKeyUp(const U16 key, const U32 mask) +bool LLKeyboardMacOSX::handleKeyUp(const U16 key, MASK mask) { KEY translated_key = 0; U32 translated_mask = 0; @@ -262,7 +262,7 @@ bool LLKeyboardMacOSX::handleKeyUp(const U16 key, const U32 mask) MASK LLKeyboardMacOSX::currentMask(bool for_mouse_event) { MASK result = MASK_NONE; - U32 mask = getModifiers(); + MASK mask = getModifiers(); if (mask & MAC_SHIFT_KEY) result |= MASK_SHIFT; if (mask & MAC_CTRL_KEY) result |= MASK_CONTROL; @@ -291,6 +291,7 @@ void LLKeyboardMacOSX::scanKeyboard() mCallbacks->handleScanKey(key, mKeyDown[key], mKeyUp[key], mKeyLevel[key]); } } + mCurScanKey = KEY_NONE; // Reset edges for next frame for (key = 0; key < KEY_COUNT; key++) diff --git a/indra/llwindow/llkeyboardmacosx.h b/indra/llwindow/llkeyboardmacosx.h index 92ab5c9a85..a5f59f3fba 100644 --- a/indra/llwindow/llkeyboardmacosx.h +++ b/indra/llwindow/llkeyboardmacosx.h @@ -42,17 +42,17 @@ class LLKeyboardMacOSX : public LLKeyboard { public: LLKeyboardMacOSX(); - /*virtual*/ ~LLKeyboardMacOSX() {}; + ~LLKeyboardMacOSX() {}; - /*virtual*/ bool handleKeyUp(const U16 key, MASK mask); - /*virtual*/ bool handleKeyDown(const U16 key, MASK mask); - /*virtual*/ void resetMaskKeys(); - /*virtual*/ MASK currentMask(bool for_mouse_event); - /*virtual*/ void scanKeyboard(); - /*virtual*/ void handleModifier(MASK mask); + bool handleKeyUp(const U16 key, MASK mask) override; + bool handleKeyDown(const U16 key, MASK mask) override; + void resetMaskKeys() override; + MASK currentMask(bool for_mouse_event) override; + void scanKeyboard() override; + void handleModifier(MASK mask) override; protected: - MASK updateModifiers(const U32 mask); + MASK updateModifiers(const MASK mask) override; void setModifierKeyLevel( KEY key, bool new_state ); bool translateNumpadKey( const U16 os_key, KEY *translated_key ); U16 inverseTranslateNumpadKey(const KEY translated_key); diff --git a/indra/llwindow/llkeyboardsdl.cpp b/indra/llwindow/llkeyboardsdl.cpp index 543882fc8f..b6666195a6 100644 --- a/indra/llwindow/llkeyboardsdl.cpp +++ b/indra/llwindow/llkeyboardsdl.cpp @@ -26,7 +26,7 @@ #include "linden_common.h" #include "llkeyboardsdl.h" #include "llwindowcallbacks.h" -#include "SDL2/SDL.h" + #include "SDL2/SDL_keycode.h" LLKeyboardSDL::LLKeyboardSDL() @@ -42,7 +42,7 @@ LLKeyboardSDL::LLKeyboardSDL() // <FS:ND> Looks like we need to map those despite of SDL_TEXTINPUT handling most of this, but without // the translation lower->upper here accelerators will not work. - U16 cur_char; + LLKeyboard::NATIVE_KEY_TYPE cur_char; for (cur_char = 'A'; cur_char <= 'Z'; cur_char++) { mTranslateKeyMap[cur_char] = cur_char; @@ -177,7 +177,7 @@ void LLKeyboardSDL::resetMaskKeys() } -MASK LLKeyboardSDL::updateModifiers(const U32 mask) +MASK LLKeyboardSDL::updateModifiers(const MASK mask) { // translate the mask MASK out_mask = MASK_NONE; @@ -201,7 +201,7 @@ MASK LLKeyboardSDL::updateModifiers(const U32 mask) } -static U32 adjustNativekeyFromUnhandledMask(const U32 key, const U32 mask) +U32 adjustNativekeyFromUnhandledMask(const LLKeyboard::NATIVE_KEY_TYPE key, const MASK mask) { // SDL doesn't automatically adjust the keysym according to // whether NUMLOCK is engaged, so we massage the keysym manually. @@ -226,11 +226,11 @@ static U32 adjustNativekeyFromUnhandledMask(const U32 key, const U32 mask) } -bool LLKeyboardSDL::handleKeyDown(const U32 key, const U32 mask) +bool LLKeyboardSDL::handleKeyDown(const LLKeyboard::NATIVE_KEY_TYPE key, const MASK mask) { U32 adjusted_nativekey; KEY translated_key = 0; - U32 translated_mask = MASK_NONE; + MASK translated_mask = MASK_NONE; bool handled = false; adjusted_nativekey = adjustNativekeyFromUnhandledMask(key, mask); @@ -246,7 +246,7 @@ bool LLKeyboardSDL::handleKeyDown(const U32 key, const U32 mask) } -bool LLKeyboardSDL::handleKeyUp(const U32 key, const U32 mask) +bool LLKeyboardSDL::handleKeyUp(const LLKeyboard::NATIVE_KEY_TYPE key, const MASK mask) { U32 adjusted_nativekey; KEY translated_key = 0; @@ -300,6 +300,7 @@ void LLKeyboardSDL::scanKeyboard() mCallbacks->handleScanKey(key, mKeyDown[key], mKeyUp[key], mKeyLevel[key]); } } + mCurScanKey = KEY_NONE; // Reset edges for next frame for (S32 key = 0; key < KEY_COUNT; key++) @@ -314,12 +315,12 @@ void LLKeyboardSDL::scanKeyboard() } -bool LLKeyboardSDL::translateNumpadKey( const U32 os_key, KEY *translated_key) +bool LLKeyboardSDL::translateNumpadKey( const LLKeyboard::NATIVE_KEY_TYPE os_key, KEY *translated_key) { return translateKey(os_key, translated_key); } -U16 LLKeyboardSDL::inverseTranslateNumpadKey(const KEY translated_key) +LLKeyboard::NATIVE_KEY_TYPE LLKeyboardSDL::inverseTranslateNumpadKey(const KEY translated_key) { return inverseTranslateKey(translated_key); } @@ -497,7 +498,6 @@ enum class WindowsVK : U32 }; std::map< U32, U32 > mSDL2_to_Win; -std::set< U32 > mIgnoreSDL2Keys; U32 LLKeyboardSDL::mapSDL2toWin( U32 aSymbol ) { diff --git a/indra/llwindow/llkeyboardsdl.h b/indra/llwindow/llkeyboardsdl.h index 9ebff66865..7671e4c859 100644 --- a/indra/llwindow/llkeyboardsdl.h +++ b/indra/llwindow/llkeyboardsdl.h @@ -33,22 +33,22 @@ class LLKeyboardSDL : public LLKeyboard { public: LLKeyboardSDL(); - /*virtual*/ ~LLKeyboardSDL() {}; + ~LLKeyboardSDL() {}; - /*virtual*/ bool handleKeyUp(const U32 key, MASK mask); - /*virtual*/ bool handleKeyDown(const U32 key, MASK mask); - /*virtual*/ void resetMaskKeys(); - /*virtual*/ MASK currentMask(bool for_mouse_event); - /*virtual*/ void scanKeyboard(); + bool handleKeyUp(const LLKeyboard::NATIVE_KEY_TYPE key, MASK mask) override; + bool handleKeyDown(const LLKeyboard::NATIVE_KEY_TYPE key, MASK mask) override; + void resetMaskKeys() override; + MASK currentMask(bool for_mouse_event) override; + void scanKeyboard() override; protected: - MASK updateModifiers(const U32 mask); + MASK updateModifiers(const MASK mask) override; void setModifierKeyLevel( KEY key, bool new_state ); - bool translateNumpadKey( const U32 os_key, KEY *translated_key ); - U16 inverseTranslateNumpadKey(const KEY translated_key); + bool translateNumpadKey( const LLKeyboard::NATIVE_KEY_TYPE os_key, KEY *translated_key ); + LLKeyboard::NATIVE_KEY_TYPE inverseTranslateNumpadKey(const KEY translated_key); private: - std::map<U32, KEY> mTranslateNumpadMap; // special map for translating OS keys to numpad keys - std::map<KEY, U32> mInvTranslateNumpadMap; // inverse of the above + std::map<LLKeyboard::NATIVE_KEY_TYPE, KEY> mTranslateNumpadMap; // special map for translating OS keys to numpad keys + std::map<KEY, LLKeyboard::NATIVE_KEY_TYPE> mInvTranslateNumpadMap; // inverse of the above public: static U32 mapSDL2toWin( U32 ); diff --git a/indra/llwindow/llkeyboardwin32.cpp b/indra/llwindow/llkeyboardwin32.cpp index 8d6b8d9b93..c31ef5c9a3 100644 --- a/indra/llwindow/llkeyboardwin32.cpp +++ b/indra/llwindow/llkeyboardwin32.cpp @@ -182,7 +182,7 @@ void LLKeyboardWin32::resetMaskKeys() //} -MASK LLKeyboardWin32::updateModifiers() +MASK LLKeyboardWin32::updateModifiers(const U32 mask) { //RN: this seems redundant, as we should have already received the appropriate // messages for the modifier keys @@ -191,8 +191,7 @@ MASK LLKeyboardWin32::updateModifiers() // (keydown encoded in high order bit of short) mKeyLevel[KEY_CAPSLOCK] = (GetKeyState(VK_CAPITAL) & 0x0001) != 0; // Low order bit carries the toggle state. // Get mask for keyboard events - MASK mask = currentMask(false); - return mask; + return currentMask(false); } @@ -203,7 +202,7 @@ bool LLKeyboardWin32::handleKeyDown(const U16 key, MASK mask) U32 translated_mask; bool handled = false; - translated_mask = updateModifiers(); + translated_mask = updateModifiers(mask); if (translateExtendedKey(key, mask, &translated_key)) { @@ -220,7 +219,7 @@ bool LLKeyboardWin32::handleKeyUp(const U16 key, MASK mask) U32 translated_mask; bool handled = false; - translated_mask = updateModifiers(); + translated_mask = updateModifiers(mask); if (translateExtendedKey(key, mask, &translated_key)) { @@ -259,6 +258,7 @@ void LLKeyboardWin32::scanKeyboard() mCallbacks->handleScanKey(key, mKeyDown[key], mKeyUp[key], mKeyLevel[key]); } } + mCurScanKey = KEY_NONE; // Reset edges for next frame for (key = 0; key < KEY_COUNT; key++) @@ -321,4 +321,4 @@ U16 LLKeyboardWin32::inverseTranslateExtendedKey(const KEY translated_key) return inverseTranslateKey(converted_key); } -#endif +#endif // LL_WINDOWS diff --git a/indra/llwindow/llkeyboardwin32.h b/indra/llwindow/llkeyboardwin32.h index d0dfc5cfdd..ea7bb4d866 100644 --- a/indra/llwindow/llkeyboardwin32.h +++ b/indra/llwindow/llkeyboardwin32.h @@ -37,18 +37,19 @@ class LLKeyboardWin32 : public LLKeyboard { public: LLKeyboardWin32(); - /*virtual*/ ~LLKeyboardWin32() {}; + ~LLKeyboardWin32() {}; - /*virtual*/ bool handleKeyUp(const U16 key, MASK mask); - /*virtual*/ bool handleKeyDown(const U16 key, MASK mask); - /*virtual*/ void resetMaskKeys(); - /*virtual*/ MASK currentMask(bool for_mouse_event); - /*virtual*/ void scanKeyboard(); - bool translateExtendedKey(const U16 os_key, const MASK mask, KEY *translated_key); - U16 inverseTranslateExtendedKey(const KEY translated_key); + bool handleKeyUp(const U16 key, MASK mask) override; + bool handleKeyDown(const U16 key, MASK mask) override; + void resetMaskKeys() override; + MASK currentMask(bool for_mouse_event) override; + void scanKeyboard() override; + + bool translateExtendedKey(const U16 os_key, const MASK mask, KEY *translated_key); + U16 inverseTranslateExtendedKey(const KEY translated_key); protected: - MASK updateModifiers(); + MASK updateModifiers(const MASK mask) override; //void setModifierKeyLevel( KEY key, bool new_state ); private: std::map<U16, KEY> mTranslateNumpadMap; diff --git a/indra/llwindow/llsdl.cpp b/indra/llwindow/llsdl.cpp new file mode 100644 index 0000000000..6161bd2972 --- /dev/null +++ b/indra/llwindow/llsdl.cpp @@ -0,0 +1,102 @@ +/** + * @file llsdl.cpp + * @brief SDL2 initialization + * + * $LicenseInfo:firstyear=2007&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$ + */ + +#include <initializer_list> +#include <list> + +#include "SDL2/SDL.h" + +#include "llerror.h" +#include "llwindow.h" + +void sdl_logger(void *userdata, int category, SDL_LogPriority priority, const char *message) +{ + LL_DEBUGS("SDL2") << "log='" << message << "'" << LL_ENDL; +} + +void init_sdl() +{ + SDL_version c_sdl_version; + SDL_VERSION(&c_sdl_version); + LL_INFOS() << "Compiled against SDL " + << int(c_sdl_version.major) << "." + << int(c_sdl_version.minor) << "." + << int(c_sdl_version.patch) << LL_ENDL; + SDL_version r_sdl_version; + SDL_GetVersion(&r_sdl_version); + LL_INFOS() << "Running with SDL " + << int(r_sdl_version.major) << "." + << int(r_sdl_version.minor) << "." + << int(r_sdl_version.patch) << LL_ENDL; +#ifdef LL_LINUX + // For linux we SDL_INIT_VIDEO and _AUDIO + std::initializer_list<std::tuple< char const*, char const * > > hintList = + { + {SDL_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR,"0"}, + {SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH,"1"}, + {SDL_HINT_IME_INTERNAL_EDITING,"1"} + }; + + for (auto hint: hintList) + { + SDL_SetHint(std::get<0>(hint), std::get<1>(hint)); + } + + std::initializer_list<std::tuple<uint32_t, char const*, bool>> initList= + { {SDL_INIT_VIDEO,"SDL_INIT_VIDEO", true}, + {SDL_INIT_AUDIO,"SDL_INIT_AUDIO", false}, + }; +#else + // For non-linux platforms we still SDL_INIT_VIDEO because it is a pre-requisite + // for SDL_INIT_GAMECONTROLLER. + std::initializer_list<std::tuple<uint32_t, char const*, bool>> initList= + { {SDL_INIT_VIDEO,"SDL_INIT_VIDEO", false}, + }; +#endif // LL_LINUX + // We SDL_INIT_GAMECONTROLLER later in the startup process to make it + // more likely we'll catch initial SDL_CONTROLLERDEVICEADDED events. + + for (auto subSystem : initList) + { + if (SDL_InitSubSystem(std::get<0>(subSystem)) < 0) + { + LL_WARNS() << "SDL_InitSubSystem for " << std::get<1>(subSystem) << " failed " << SDL_GetError() << LL_ENDL; + + if (std::get<2>(subSystem)) + { + OSMessageBox("SDL_Init() failure", "error", OSMB_OK); + return; + } + } + } + + SDL_LogSetOutputFunction(&sdl_logger, nullptr); +} + +void quit_sdl() +{ + SDL_Quit(); +} diff --git a/indra/llwindow/llsdl.h b/indra/llwindow/llsdl.h new file mode 100644 index 0000000000..9fc8de129c --- /dev/null +++ b/indra/llwindow/llsdl.h @@ -0,0 +1,30 @@ +/** + * @file llsdl.h + * @brief SDL2 initialization + * + * $LicenseInfo:firstyear=2007&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$ + */ + +#pragma once + +void init_sdl(); +void quit_sdl(); diff --git a/indra/llwindow/llwindow.cpp b/indra/llwindow/llwindow.cpp index 378e633cd2..93ac58ca6f 100644 --- a/indra/llwindow/llwindow.cpp +++ b/indra/llwindow/llwindow.cpp @@ -27,18 +27,19 @@ #include "linden_common.h" #include "llwindowheadless.h" -#if LL_MESA_HEADLESS -#include "llwindowmesaheadless.h" -#elif LL_SDL -#include "llwindowsdl.h" -#elif LL_WINDOWS +#if LL_WINDOWS #include "llwindowwin32.h" #elif LL_DARWIN #include "llwindowmacosx.h" +#elif LL_MESA_HEADLESS +#include "llwindowmesaheadless.h" +#elif LL_LINUX +#include "llwindowsdl.h" #endif #include "llerror.h" #include "llkeyboard.h" +#include "llsdl.h" #include "llwindowcallbacks.h" @@ -72,13 +73,13 @@ S32 OSMessageBox(const std::string& text, const std::string& caption, U32 type) S32 result = 0; LL_WARNS() << "OSMessageBox: " << text << LL_ENDL; -#if LL_MESA_HEADLESS // !!! *FIX: (?) - return OSBTN_OK; -#elif LL_WINDOWS +#if LL_WINDOWS result = OSMessageBoxWin32(text, caption, type); #elif LL_DARWIN result = OSMessageBoxMacOSX(text, caption, type); -#elif LL_SDL +#elif LL_MESA_HEADLESS // !!! *FIX: (?) + return OSBTN_OK; +#elif LL_LINUX result = OSMessageBoxSDL(text, caption, type); #else #error("OSMessageBox not implemented for this platform!") @@ -263,7 +264,7 @@ std::vector<std::string> LLWindow::getDynamicFallbackFontList() return LLWindowWin32::getDynamicFallbackFontList(); #elif LL_DARWIN return LLWindowMacOSX::getDynamicFallbackFontList(); -#elif LL_SDL +#elif LL_LINUX return LLWindowSDL::getDynamicFallbackFontList(); #else return std::vector<std::string>(); @@ -342,12 +343,12 @@ bool LLSplashScreen::isVisible() // static LLSplashScreen *LLSplashScreen::create() { -#if LL_MESA_HEADLESS || LL_SDL // !!! *FIX: (?) - return 0; -#elif LL_WINDOWS +#if LL_WINDOWS return new LLSplashScreenWin32; #elif LL_DARWIN return new LLSplashScreenMacOSX; +#elif LL_MESA_HEADLESS || LL_LINUX // !!! *FIX: (?) + return 0; #else #error("LLSplashScreen not implemented on this platform!") #endif @@ -415,15 +416,8 @@ LLWindow* LLWindowManager::createWindow( if (use_gl) { -#if LL_MESA_HEADLESS - new_window = new LLWindowMesaHeadless(callbacks, - title, name, x, y, width, height, flags, - fullscreen, clearBg, enable_vsync, use_gl, ignore_pixel_depth); -#elif LL_SDL - new_window = new LLWindowSDL(callbacks, - title, x, y, width, height, flags, - fullscreen, clearBg, enable_vsync, use_gl, ignore_pixel_depth, fsaa_samples); -#elif LL_WINDOWS + init_sdl(); +#if LL_WINDOWS new_window = new LLWindowWin32(callbacks, title, name, x, y, width, height, flags, fullscreen, clearBg, enable_vsync, use_gl, ignore_pixel_depth, fsaa_samples, max_cores, max_gl_version); @@ -431,6 +425,14 @@ LLWindow* LLWindowManager::createWindow( new_window = new LLWindowMacOSX(callbacks, title, name, x, y, width, height, flags, fullscreen, clearBg, enable_vsync, use_gl, ignore_pixel_depth, fsaa_samples); +#elif LL_MESA_HEADLESS + new_window = new LLWindowMesaHeadless(callbacks, + title, name, x, y, width, height, flags, + fullscreen, clearBg, enable_vsync, use_gl, ignore_pixel_depth); +#elif LL_LINUX + new_window = new LLWindowSDL(callbacks, + title, name, x, y, width, height, flags, + fullscreen, clearBg, enable_vsync, use_gl, ignore_pixel_depth, fsaa_samples); #endif } else @@ -462,6 +464,7 @@ bool LLWindowManager::destroyWindow(LLWindow* window) window->close(); sWindowList.erase(window); + quit_sdl(); delete window; diff --git a/indra/llwindow/llwindow.h b/indra/llwindow/llwindow.h index fcc4fd863a..e74142c7df 100644 --- a/indra/llwindow/llwindow.h +++ b/indra/llwindow/llwindow.h @@ -24,8 +24,7 @@ * $/LicenseInfo$ */ -#ifndef LL_LLWINDOW_H -#define LL_LLWINDOW_H +#pragma once #include "llrect.h" #include "llcoord.h" @@ -33,6 +32,7 @@ #include "llcursortypes.h" #include "llinstancetracker.h" #include "llsd.h" +#include "llsdl.h" class LLSplashScreen; class LLPreeditor; @@ -63,16 +63,16 @@ public: virtual void show() = 0; virtual void hide() = 0; virtual void close() = 0; - virtual bool getVisible() = 0; - virtual bool getMinimized() = 0; - virtual bool getMaximized() = 0; + virtual bool getVisible() const = 0; + virtual bool getMinimized() const = 0; + virtual bool getMaximized() const = 0; virtual bool maximize() = 0; virtual void minimize() = 0; virtual void restore() = 0; - bool getFullscreen() { return mFullscreen; }; - virtual bool getPosition(LLCoordScreen *position) = 0; - virtual bool getSize(LLCoordScreen *size) = 0; - virtual bool getSize(LLCoordWindow *size) = 0; + virtual bool getFullscreen() const { return mFullscreen; }; + virtual bool getPosition(LLCoordScreen *position) const = 0; + virtual bool getSize(LLCoordScreen *size) const = 0; + virtual bool getSize(LLCoordWindow *size) const = 0; virtual bool setPosition(LLCoordScreen position) = 0; bool setSize(LLCoordScreen size); bool setSize(LLCoordWindow size); @@ -93,7 +93,7 @@ public: virtual bool setCursorPosition(LLCoordWindow position) = 0; virtual bool getCursorPosition(LLCoordWindow *position) = 0; #if LL_WINDOWS - virtual bool getCursorDelta(LLCoordCommon* delta) = 0; + virtual bool getCursorDelta(LLCoordCommon* delta) const = 0; #endif virtual void showCursor() = 0; virtual void hideCursor() = 0; @@ -135,14 +135,14 @@ public: virtual bool copyTextToPrimary(const LLWString &src); virtual void flashIcon(F32 seconds) = 0; - virtual F32 getGamma() = 0; + virtual F32 getGamma() const = 0; virtual bool setGamma(const F32 gamma) = 0; // Set the gamma virtual void setFSAASamples(const U32 fsaa_samples) = 0; //set number of FSAA samples - virtual U32 getFSAASamples() = 0; + virtual U32 getFSAASamples() const = 0; virtual bool restoreGamma() = 0; // Restore original gamma table (before updating gamma) - virtual ESwapMethod getSwapMethod() { return mSwapMethod; } + ESwapMethod getSwapMethod() { return mSwapMethod; } virtual void processMiscNativeEvents(); - virtual void gatherInput() = 0; + virtual void gatherInput(bool app_has_focus) = 0; virtual void delayInputProcessing() = 0; virtual void swapBuffers() = 0; virtual void bringToFront() = 0; @@ -151,12 +151,12 @@ public: // handy coordinate space conversion routines // NB: screen to window and vice verse won't work on width/height coordinate pairs, // as the conversion must take into account left AND right border widths, etc. - virtual bool convertCoords( LLCoordScreen from, LLCoordWindow *to) = 0; - virtual bool convertCoords( LLCoordWindow from, LLCoordScreen *to) = 0; - virtual bool convertCoords( LLCoordWindow from, LLCoordGL *to) = 0; - virtual bool convertCoords( LLCoordGL from, LLCoordWindow *to) = 0; - virtual bool convertCoords( LLCoordScreen from, LLCoordGL *to) = 0; - virtual bool convertCoords( LLCoordGL from, LLCoordScreen *to) = 0; + virtual bool convertCoords( LLCoordScreen from, LLCoordWindow *to) const = 0; + virtual bool convertCoords( LLCoordWindow from, LLCoordScreen *to) const = 0; + virtual bool convertCoords( LLCoordWindow from, LLCoordGL *to) const = 0; + virtual bool convertCoords( LLCoordGL from, LLCoordWindow *to) const = 0; + virtual bool convertCoords( LLCoordScreen from, LLCoordGL *to) const = 0; + virtual bool convertCoords( LLCoordGL from, LLCoordScreen *to) const = 0; // query supported resolutions virtual LLWindowResolution* getSupportedResolutions(S32 &num_resolutions) = 0; @@ -189,7 +189,7 @@ public: static std::vector<std::string> getDynamicFallbackFontList(); // Provide native key event data - virtual LLSD getNativeKeyData() { return LLSD::emptyMap(); } + virtual LLSD getNativeKeyData() const { return LLSD::emptyMap(); } // Get system UI size based on DPI (for 96 DPI UI size should be 1.0) virtual F32 getSystemUISize() { return 1.0; } @@ -206,7 +206,7 @@ public: return false; }; - virtual S32 getRefreshRate() { return mRefreshRate; } + virtual S32 getRefreshRate() const { return mRefreshRate; } protected: LLWindow(LLWindowCallbacks* callbacks, bool fullscreen, U32 flags); virtual ~LLWindow(); @@ -328,4 +328,3 @@ extern const S32 gURLProtocolWhitelistCount; extern const std::string gURLProtocolWhitelist[]; //extern const std::string gURLProtocolWhitelistHandler[]; -#endif // _LL_window_h_ diff --git a/indra/llwindow/llwindowheadless.h b/indra/llwindow/llwindowheadless.h index 5696b69a59..96654b8838 100644 --- a/indra/llwindow/llwindowheadless.h +++ b/indra/llwindow/llwindowheadless.h @@ -32,77 +32,70 @@ class LLWindowHeadless : public LLWindow { public: - /*virtual*/ void show() override {} - /*virtual*/ void hide() override {} - /*virtual*/ void close() override {} - /*virtual*/ bool getVisible() override {return false;} - /*virtual*/ bool getMinimized() override {return false;} - /*virtual*/ bool getMaximized() override {return false;} - /*virtual*/ bool maximize() override {return false;} - /*virtual*/ void minimize() override {} - /*virtual*/ void restore() override {} - // TODO: LLWindow::getFullscreen() is (intentionally?) NOT virtual. - // Apparently the coder of LLWindowHeadless didn't realize that. Is it a - // mistake to shadow the base-class method with an LLWindowHeadless - // override when called on the subclass, yet call the base-class method - // when indirecting through a polymorphic pointer or reference? - bool getFullscreen() {return false;} - /*virtual*/ bool getPosition(LLCoordScreen *position) override {return false;} - /*virtual*/ bool getSize(LLCoordScreen *size) override {return false;} - /*virtual*/ bool getSize(LLCoordWindow *size) override {return false;} - /*virtual*/ bool setPosition(LLCoordScreen position) override {return false;} - /*virtual*/ bool setSizeImpl(LLCoordScreen size) override {return false;} - /*virtual*/ bool setSizeImpl(LLCoordWindow size) override {return false;} - /*virtual*/ bool switchContext(bool fullscreen, const LLCoordScreen &size, bool enable_vsync, const LLCoordScreen * const posp = NULL) override {return false;} + void show() override {} + void hide() override {} + void close() override {} + bool getVisible() const override {return false;} + bool getMinimized() const override {return false;} + bool getMaximized() const override {return false;} + bool maximize() override {return false;} + void minimize() override {} + void restore() override {} + bool getFullscreen() const override {return false;}; + bool getPosition(LLCoordScreen *position) const override {return false;} + bool getSize(LLCoordScreen *size) const override {return false;} + bool getSize(LLCoordWindow *size) const override {return false;} + bool setPosition(LLCoordScreen position) override {return false;} + bool setSizeImpl(LLCoordScreen size) override {return false;} + bool setSizeImpl(LLCoordWindow size) override {return false;} + bool switchContext(bool fullscreen, const LLCoordScreen &size, bool enable_vsync, const LLCoordScreen * const posp = NULL) override {return false;} void* createSharedContext() override { return nullptr; } void makeContextCurrent(void*) override {} void destroySharedContext(void*) override {} - /*virtual*/ void toggleVSync(bool enable_vsync) override { } - /*virtual*/ bool setCursorPosition(LLCoordWindow position) override {return false;} - /*virtual*/ bool getCursorPosition(LLCoordWindow *position) override {return false;} + void toggleVSync(bool enable_vsync) override { } + bool setCursorPosition(LLCoordWindow position) override {return false;} + bool getCursorPosition(LLCoordWindow *position) override {return false;} #if LL_WINDOWS - /*virtual*/ bool getCursorDelta(LLCoordCommon* delta) override { return false; } + bool getCursorDelta(LLCoordCommon* delta) const override { return false; } #endif - /*virtual*/ void showCursor() override {} - /*virtual*/ void hideCursor() override {} - /*virtual*/ void showCursorFromMouseMove() override {} - /*virtual*/ void hideCursorUntilMouseMove() override {} - /*virtual*/ bool isCursorHidden() override {return false;} - /*virtual*/ void updateCursor() override {} - //virtual ECursorType getCursor() override { return mCurrentCursor; } - /*virtual*/ void captureMouse() override {} - /*virtual*/ void releaseMouse() override {} - /*virtual*/ void setMouseClipping( bool b ) override {} - /*virtual*/ bool isClipboardTextAvailable() override {return false; } - /*virtual*/ bool pasteTextFromClipboard(LLWString &dst) override {return false; } - /*virtual*/ bool copyTextToClipboard(const LLWString &src) override {return false; } - /*virtual*/ void flashIcon(F32 seconds) override {} - /*virtual*/ F32 getGamma() override {return 1.0f; } - /*virtual*/ bool setGamma(const F32 gamma) override {return false; } // Set the gamma - /*virtual*/ void setFSAASamples(const U32 fsaa_samples) override { } - /*virtual*/ U32 getFSAASamples() override { return 0; } - /*virtual*/ bool restoreGamma() override {return false; } // Restore original gamma table (before updating gamma) - //virtual ESwapMethod getSwapMethod() override { return mSwapMethod; } - /*virtual*/ void gatherInput() override {} - /*virtual*/ void delayInputProcessing() override {} - /*virtual*/ void swapBuffers() override; + void showCursor() override {} + void hideCursor() override {} + void showCursorFromMouseMove() override {} + void hideCursorUntilMouseMove() override {} + bool isCursorHidden() override {return false;} + void updateCursor() override {} + void captureMouse() override {} + void releaseMouse() override {} + void setMouseClipping( bool b ) override {} + bool isClipboardTextAvailable() override {return false; } + bool pasteTextFromClipboard(LLWString &dst) override {return false; } + bool copyTextToClipboard(const LLWString &src) override {return false; } + void flashIcon(F32 seconds) override {} + F32 getGamma() const override {return 1.0f; } + bool setGamma(const F32 gamma) override {return false; } // Set the gamma + void setFSAASamples(const U32 fsaa_samples) override { } + U32 getFSAASamples() const override { return 0; } + bool restoreGamma() override {return false; } // Restore original gamma table (before updating gamma) + void gatherInput(bool app_has_focus) override {} + void delayInputProcessing() override {} + void swapBuffers() override; // handy coordinate space conversion routines - /*virtual*/ bool convertCoords(LLCoordScreen from, LLCoordWindow *to) override { return false; } - /*virtual*/ bool convertCoords(LLCoordWindow from, LLCoordScreen *to) override { return false; } - /*virtual*/ bool convertCoords(LLCoordWindow from, LLCoordGL *to) override { return false; } - /*virtual*/ bool convertCoords(LLCoordGL from, LLCoordWindow *to) override { return false; } - /*virtual*/ bool convertCoords(LLCoordScreen from, LLCoordGL *to) override { return false; } - /*virtual*/ bool convertCoords(LLCoordGL from, LLCoordScreen *to) override { return false; } + bool convertCoords(LLCoordScreen from, LLCoordWindow *to) const override { return false; } + bool convertCoords(LLCoordWindow from, LLCoordScreen *to) const override { return false; } + bool convertCoords(LLCoordWindow from, LLCoordGL *to) const override { return false; } + bool convertCoords(LLCoordGL from, LLCoordWindow *to) const override { return false; } + bool convertCoords(LLCoordScreen from, LLCoordGL *to) const override { return false; } + bool convertCoords(LLCoordGL from, LLCoordScreen *to) const override { return false; } - /*virtual*/ LLWindowResolution* getSupportedResolutions(S32 &num_resolutions) override { return NULL; } - /*virtual*/ F32 getNativeAspectRatio() override { return 1.0f; } - /*virtual*/ F32 getPixelAspectRatio() override { return 1.0f; } - /*virtual*/ void setNativeAspectRatio(F32 ratio) override {} + LLWindowResolution* getSupportedResolutions(S32 &num_resolutions) override { return NULL; } + F32 getNativeAspectRatio() override { return 1.0f; } + F32 getPixelAspectRatio() override { return 1.0f; } + void setNativeAspectRatio(F32 ratio) override {} - /*virtual*/ void *getPlatformWindow() override { return 0; } - /*virtual*/ void bringToFront() override {} + void *getPlatformWindow() override { return 0; } + void bringToFront() override {} LLWindowHeadless(LLWindowCallbacks* callbacks, const std::string& title, const std::string& name, diff --git a/indra/llwindow/llwindowmacosx.cpp b/indra/llwindow/llwindowmacosx.cpp index e95ad4d970..1883c6c9c1 100644 --- a/indra/llwindow/llwindowmacosx.cpp +++ b/indra/llwindow/llwindowmacosx.cpp @@ -28,6 +28,7 @@ #include "llwindowmacosx.h" +#include "llgamecontrol.h" #include "llkeyboardmacosx.h" #include "llwindowcallbacks.h" #include "llpreeditor.h" @@ -625,7 +626,7 @@ void LLWindowMacOSX::updateMouseDeltas(float* deltas) } } -void LLWindowMacOSX::getMouseDeltas(float* delta) +void LLWindowMacOSX::getMouseDeltas(float* delta) const { delta[0] = mCursorLastEventDeltaX; delta[1] = mCursorLastEventDeltaY; @@ -845,7 +846,7 @@ bool LLWindowMacOSX::isValid() return (mWindow != NULL); } -bool LLWindowMacOSX::getVisible() +bool LLWindowMacOSX::getVisible() const { bool result = false; @@ -860,12 +861,12 @@ bool LLWindowMacOSX::getVisible() return(result); } -bool LLWindowMacOSX::getMinimized() +bool LLWindowMacOSX::getMinimized() const { return mMinimized; } -bool LLWindowMacOSX::getMaximized() +bool LLWindowMacOSX::getMaximized() const { return mMaximized; } @@ -879,17 +880,13 @@ bool LLWindowMacOSX::maximize() return mMaximized; } -bool LLWindowMacOSX::getFullscreen() -{ - return mFullscreen; -} - -void LLWindowMacOSX::gatherInput() +void LLWindowMacOSX::gatherInput(bool app_has_focus) { updateCursor(); + LLGameControl::processEvents(app_has_focus); } -bool LLWindowMacOSX::getPosition(LLCoordScreen *position) +bool LLWindowMacOSX::getPosition(LLCoordScreen *position) const { S32 err = -1; @@ -916,7 +913,7 @@ bool LLWindowMacOSX::getPosition(LLCoordScreen *position) return (err == noErr); } -bool LLWindowMacOSX::getSize(LLCoordScreen *size) +bool LLWindowMacOSX::getSize(LLCoordScreen *size) const { S32 err = -1; @@ -942,7 +939,7 @@ bool LLWindowMacOSX::getSize(LLCoordScreen *size) return (err == noErr); } -bool LLWindowMacOSX::getSize(LLCoordWindow *size) +bool LLWindowMacOSX::getSize(LLCoordWindow *size) const { S32 err = -1; @@ -1016,7 +1013,7 @@ void LLWindowMacOSX::restoreGLContext() CGLSetCurrentContext(mContext); } -F32 LLWindowMacOSX::getGamma() +F32 LLWindowMacOSX::getGamma() const { F32 result = 2.2; // Default to something sane @@ -1050,7 +1047,7 @@ F32 LLWindowMacOSX::getGamma() return result; } -U32 LLWindowMacOSX::getFSAASamples() +U32 LLWindowMacOSX::getFSAASamples() const { return mFSAASamples; } @@ -1376,21 +1373,21 @@ LLWindow::LLWindowResolution* LLWindowMacOSX::getSupportedResolutions(S32 &num_r return mSupportedResolutions; } -bool LLWindowMacOSX::convertCoords(LLCoordGL from, LLCoordWindow *to) +bool LLWindowMacOSX::convertCoords(LLCoordGL from, LLCoordWindow *to) const { to->mX = from.mX; to->mY = from.mY; return true; } -bool LLWindowMacOSX::convertCoords(LLCoordWindow from, LLCoordGL* to) +bool LLWindowMacOSX::convertCoords(LLCoordWindow from, LLCoordGL* to) const { to->mX = from.mX; to->mY = from.mY; return true; } -bool LLWindowMacOSX::convertCoords(LLCoordScreen from, LLCoordWindow* to) +bool LLWindowMacOSX::convertCoords(LLCoordScreen from, LLCoordWindow* to) const { if(mWindow) { @@ -1409,7 +1406,7 @@ bool LLWindowMacOSX::convertCoords(LLCoordScreen from, LLCoordWindow* to) return false; } -bool LLWindowMacOSX::convertCoords(LLCoordWindow from, LLCoordScreen *to) +bool LLWindowMacOSX::convertCoords(LLCoordWindow from, LLCoordScreen *to) const { if(mWindow) { @@ -1428,14 +1425,14 @@ bool LLWindowMacOSX::convertCoords(LLCoordWindow from, LLCoordScreen *to) return false; } -bool LLWindowMacOSX::convertCoords(LLCoordScreen from, LLCoordGL *to) +bool LLWindowMacOSX::convertCoords(LLCoordScreen from, LLCoordGL *to) const { LLCoordWindow window_coord; return(convertCoords(from, &window_coord) && convertCoords(window_coord, to)); } -bool LLWindowMacOSX::convertCoords(LLCoordGL from, LLCoordScreen *to) +bool LLWindowMacOSX::convertCoords(LLCoordGL from, LLCoordScreen *to) const { LLCoordWindow window_coord; @@ -2321,7 +2318,7 @@ bool LLWindowMacOSX::getInputDevices(U32 device_type_filter, return return_value; } -LLSD LLWindowMacOSX::getNativeKeyData() +LLSD LLWindowMacOSX::getNativeKeyData() const { LLSD result = LLSD::emptyMap(); @@ -2505,6 +2502,7 @@ void LLWindowMacOSX::interruptLanguageTextInput() commitCurrentPreedit(mGLView); } +// static std::vector<std::string> LLWindowMacOSX::getDisplaysResolutionList() { std::vector<std::string> resolution_list; @@ -2534,7 +2532,7 @@ std::vector<std::string> LLWindowMacOSX::getDisplaysResolutionList() return resolution_list; } -//static +// static std::vector<std::string> LLWindowMacOSX::getDynamicFallbackFontList() { // Fonts previously in getFontListSans() have moved to fonts.xml. diff --git a/indra/llwindow/llwindowmacosx.h b/indra/llwindow/llwindowmacosx.h index 211ae872c6..14a56a038e 100644 --- a/indra/llwindow/llwindowmacosx.h +++ b/indra/llwindow/llwindowmacosx.h @@ -47,16 +47,15 @@ public: void show() override; void hide() override; void close() override; - bool getVisible() override; - bool getMinimized() override; - bool getMaximized() override; + bool getVisible() const override; + bool getMinimized() const override; + bool getMaximized() const override; bool maximize() override; void minimize() override; void restore() override; - bool getFullscreen(); - bool getPosition(LLCoordScreen *position) override; - bool getSize(LLCoordScreen *size) override; - bool getSize(LLCoordWindow *size) override; + bool getPosition(LLCoordScreen *position) const override; + bool getSize(LLCoordScreen *size) const override; + bool getSize(LLCoordWindow *size) const override; bool setPosition(LLCoordScreen position) override; bool setSizeImpl(LLCoordScreen size) override; bool setSizeImpl(LLCoordWindow size) override; @@ -77,23 +76,22 @@ public: bool pasteTextFromClipboard(LLWString &dst) override; bool copyTextToClipboard(const LLWString & src) override; void flashIcon(F32 seconds) override; - F32 getGamma() override; + F32 getGamma() const override; bool setGamma(const F32 gamma) override; // Set the gamma - U32 getFSAASamples() override; + U32 getFSAASamples() const override; void setFSAASamples(const U32 fsaa_samples) override; bool restoreGamma() override; // Restore original gamma table (before updating gamma) - ESwapMethod getSwapMethod() override { return mSwapMethod; } - void gatherInput() override; + void gatherInput(bool app_has_focus) override; void delayInputProcessing() override {}; void swapBuffers() override; // handy coordinate space conversion routines - bool convertCoords(LLCoordScreen from, LLCoordWindow *to) override; - bool convertCoords(LLCoordWindow from, LLCoordScreen *to) override; - bool convertCoords(LLCoordWindow from, LLCoordGL *to) override; - bool convertCoords(LLCoordGL from, LLCoordWindow *to) override; - bool convertCoords(LLCoordScreen from, LLCoordGL *to) override; - bool convertCoords(LLCoordGL from, LLCoordScreen *to) override; + bool convertCoords(LLCoordScreen from, LLCoordWindow *to) const override; + bool convertCoords(LLCoordWindow from, LLCoordScreen *to) const override; + bool convertCoords(LLCoordWindow from, LLCoordGL *to) const override; + bool convertCoords(LLCoordGL from, LLCoordWindow *to) const override; + bool convertCoords(LLCoordScreen from, LLCoordGL *to) const override; + bool convertCoords(LLCoordGL from, LLCoordScreen *to) const override; LLWindowResolution* getSupportedResolutions(S32 &num_resolutions) override; F32 getNativeAspectRatio() override; @@ -125,14 +123,14 @@ public: static std::vector<std::string> getDynamicFallbackFontList(); // Provide native key event data - LLSD getNativeKeyData() override; + LLSD getNativeKeyData() const override; void* getWindow() { return mWindow; } LLWindowCallbacks* getCallbacks() { return mCallbacks; } LLPreeditor* getPreeditor() { return mPreeditor; } void updateMouseDeltas(float* deltas); - void getMouseDeltas(float* delta); + void getMouseDeltas(float* delta) const; void handleDragNDrop(std::string url, LLWindowCallbacks::DragNDropAction action); diff --git a/indra/llwindow/llwindowmesaheadless.h b/indra/llwindow/llwindowmesaheadless.h index 0bf8c46a30..0a29ddfa5b 100644 --- a/indra/llwindow/llwindowmesaheadless.h +++ b/indra/llwindow/llwindowmesaheadless.h @@ -36,64 +36,64 @@ class LLWindowMesaHeadless : public LLWindow { public: - /*virtual*/ void show() {}; - /*virtual*/ void hide() {}; - /*virtual*/ void close() {}; - /*virtual*/ bool getVisible() {return false;}; - /*virtual*/ bool getMinimized() {return false;}; - /*virtual*/ bool getMaximized() {return false;}; - /*virtual*/ bool maximize() {return false;}; - /*virtual*/ void minimize() {}; - /*virtual*/ void restore() {}; - /*virtual*/ bool getFullscreen() {return false;}; - /*virtual*/ bool getPosition(LLCoordScreen *position) {return false;}; - /*virtual*/ bool getSize(LLCoordScreen *size) {return false;}; - /*virtual*/ bool getSize(LLCoordWindow *size) {return false;}; - /*virtual*/ bool setPosition(LLCoordScreen position) {return false;}; - /*virtual*/ bool setSizeImpl(LLCoordScreen size) {return false;}; - /*virtual*/ bool switchContext(bool fullscreen, const LLCoordScreen &size, bool disable_vsync, const LLCoordScreen * const posp = NULL) {return false;}; - /*virtual*/ bool setCursorPosition(LLCoordWindow position) {return false;}; - /*virtual*/ bool getCursorPosition(LLCoordWindow *position) {return false;}; - /*virtual*/ void showCursor() {}; - /*virtual*/ void hideCursor() {}; - /*virtual*/ void showCursorFromMouseMove() {}; - /*virtual*/ void hideCursorUntilMouseMove() {}; - /*virtual*/ bool isCursorHidden() {return false;}; - /*virtual*/ void updateCursor() {}; - //virtual ECursorType getCursor() { return mCurrentCursor; }; - /*virtual*/ void captureMouse() {}; - /*virtual*/ void releaseMouse() {}; - /*virtual*/ void setMouseClipping( bool b ) {}; - /*virtual*/ bool isClipboardTextAvailable() {return false; }; - /*virtual*/ bool pasteTextFromClipboard(LLWString &dst) {return false; }; - /*virtual*/ bool copyTextToClipboard(const LLWString &src) {return false; }; - /*virtual*/ void flashIcon(F32 seconds) {}; - /*virtual*/ F32 getGamma() {return 1.0f; }; - /*virtual*/ bool setGamma(const F32 gamma) {return false; }; // Set the gamma - /*virtual*/ bool restoreGamma() {return false; }; // Restore original gamma table (before updating gamma) - /*virtual*/ void setFSAASamples(const U32 fsaa_samples) { /* FSAA not supported yet on Mesa headless.*/ } - /*virtual*/ U32 getFSAASamples() { return 0; } - //virtual ESwapMethod getSwapMethod() { return mSwapMethod; } - /*virtual*/ void gatherInput() {}; - /*virtual*/ void delayInputProcessing() {}; - /*virtual*/ void swapBuffers(); - /*virtual*/ void restoreGLContext() {}; + void show() override {}; + void hide() override {}; + void close() override {}; + bool getVisible() override {return false;}; + bool getMinimized() override {return false;}; + bool getMaximized() override {return false;}; + bool maximize() override {return false;}; + void minimize() override {}; + void restore() override {}; + bool getFullscreen() override {return false;}; + bool getPosition(LLCoordScreen *position) override {return false;}; + bool getSize(LLCoordScreen *size) override {return false;}; + bool getSize(LLCoordWindow *size) override {return false;}; + bool setPosition(LLCoordScreen position) override {return false;}; + bool setSizeImpl(LLCoordScreen size) override {return false;}; + bool switchContext(bool fullscreen, const LLCoordScreen &size, bool disable_vsync, const LLCoordScreen * const posp = NULL) override {return false;}; + bool setCursorPosition(LLCoordWindow position) override {return false;}; + bool getCursorPosition(LLCoordWindow *position) override {return false;}; + void showCursor() override {}; + void hideCursor() override {}; + void showCursorFromMouseMove() override {}; + void hideCursorUntilMouseMove() override {}; + bool isCursorHidden() override {return false;}; + void updateCursor() override {}; + //ECursorType getCursor() override { return mCurrentCursor; }; + void captureMouse() override {}; + void releaseMouse() override {}; + void setMouseClipping( bool b ) override {}; + bool isClipboardTextAvailable() override {return false; }; + bool pasteTextFromClipboard(LLWString &dst) override {return false; }; + bool copyTextToClipboard(const LLWString &src) override {return false; }; + void flashIcon(F32 seconds) override {}; + F32 getGamma() override {return 1.0f; }; + bool setGamma(const F32 gamma) override {return false; }; // Set the gamma + bool restoreGamma() override {return false; }; // Restore original gamma table (before updating gamma) + void setFSAASamples(const U32 fsaa_samples) override { /* FSAA not supported yet on Mesa headless.*/ } + U32 getFSAASamples() override { return 0; } + //ESwapMethod getSwapMethod() override { return mSwapMethod; } + void gatherInput(bool app_has_focus) override {}; + void delayInputProcessing() override {}; + void swapBuffers() override; + void restoreGLContext() override {}; // handy coordinate space conversion routines - /*virtual*/ bool convertCoords(LLCoordScreen from, LLCoordWindow *to) { return false; }; - /*virtual*/ bool convertCoords(LLCoordWindow from, LLCoordScreen *to) { return false; }; - /*virtual*/ bool convertCoords(LLCoordWindow from, LLCoordGL *to) { return false; }; - /*virtual*/ bool convertCoords(LLCoordGL from, LLCoordWindow *to) { return false; }; - /*virtual*/ bool convertCoords(LLCoordScreen from, LLCoordGL *to) { return false; }; - /*virtual*/ bool convertCoords(LLCoordGL from, LLCoordScreen *to) { return false; }; + bool convertCoords(LLCoordScreen from, LLCoordWindow *to) override { return false; }; + bool convertCoords(LLCoordWindow from, LLCoordScreen *to) override { return false; }; + bool convertCoords(LLCoordWindow from, LLCoordGL *to) override { return false; }; + bool convertCoords(LLCoordGL from, LLCoordWindow *to) override { return false; }; + bool convertCoords(LLCoordScreen from, LLCoordGL *to) override { return false; }; + bool convertCoords(LLCoordGL from, LLCoordScreen *to) override { return false; }; - /*virtual*/ LLWindowResolution* getSupportedResolutions(S32 &num_resolutions) { return NULL; }; - /*virtual*/ F32 getNativeAspectRatio() { return 1.0f; }; - /*virtual*/ F32 getPixelAspectRatio() { return 1.0f; }; - /*virtual*/ void setNativeAspectRatio(F32 ratio) {} + LLWindowResolution* getSupportedResolutions(S32 &num_resolutions) override { return NULL; }; + F32 getNativeAspectRatio() override { return 1.0f; }; + F32 getPixelAspectRatio() override { return 1.0f; }; + void setNativeAspectRatio(F32 ratio) override {} - /*virtual*/ void *getPlatformWindow() { return 0; }; - /*virtual*/ void bringToFront() {}; + void *getPlatformWindow() override { return 0; }; + void bringToFront() override {}; LLWindowMesaHeadless(LLWindowCallbacks* callbacks, const std::string& title, const std::string& name, S32 x, S32 y, S32 width, S32 height, @@ -112,9 +112,9 @@ public: LLSplashScreenMesaHeadless() {}; virtual ~LLSplashScreenMesaHeadless() {}; - /*virtual*/ void showImpl() {}; - /*virtual*/ void updateImpl(const std::string& mesg) {}; - /*virtual*/ void hideImpl() {}; + void showImpl() override {}; + void updateImpl(const std::string& mesg) override {}; + void hideImpl() override {}; }; diff --git a/indra/llwindow/llwindowsdl.cpp b/indra/llwindow/llwindowsdl.cpp index 89f0d152c6..ea95a5aa2e 100644 --- a/indra/llwindow/llwindowsdl.cpp +++ b/indra/llwindow/llwindowsdl.cpp @@ -37,6 +37,7 @@ #include "llstring.h" #include "lldir.h" #include "llfindlocale.h" +#include "llgamecontrol.h" #ifdef LL_GLIB #include <glib.h> @@ -59,9 +60,6 @@ extern bool gDebugWindowProc; const S32 MAX_NUM_RESOLUTIONS = 200; -// static variable for ATI mouse cursor crash work-around: -static bool ATIbug = false; - // // LLWindowSDL // @@ -113,250 +111,8 @@ Display* LLWindowSDL::get_SDL_Display(void) } #endif // LL_X11 -#if LL_X11 - -// Clipboard handing via native X11, base on the implementation in Cool VL by Henri Beauchamp - -namespace -{ - std::array<Atom, 3> gSupportedAtoms; - - Atom XA_CLIPBOARD; - Atom XA_TARGETS; - Atom PVT_PASTE_BUFFER; - long const MAX_PASTE_BUFFER_SIZE = 16383; - - void filterSelectionRequest( XEvent aEvent ) - { - auto *display = LLWindowSDL::getSDLDisplay(); - auto &request = aEvent.xselectionrequest; - - XSelectionEvent reply { SelectionNotify, aEvent.xany.serial, aEvent.xany.send_event, display, - request.requestor, request.selection, request.target, - request.property,request.time }; - - if (request.target == XA_TARGETS) - { - XChangeProperty(display, request.requestor, request.property, - XA_ATOM, 32, PropModeReplace, - (unsigned char *) &gSupportedAtoms.front(), gSupportedAtoms.size()); - } - else if (std::find(gSupportedAtoms.begin(), gSupportedAtoms.end(), request.target) != - gSupportedAtoms.end()) - { - std::string utf8; - if (request.selection == XA_PRIMARY) - utf8 = wstring_to_utf8str(gWindowImplementation->getPrimaryText()); - else - utf8 = wstring_to_utf8str(gWindowImplementation->getSecondaryText()); - - XChangeProperty(display, request.requestor, request.property, - request.target, 8, PropModeReplace, - (unsigned char *) utf8.c_str(), utf8.length()); - } - else if (request.selection == XA_CLIPBOARD) - { - // Did not have what they wanted, so no property set - reply.property = None; - } - else - return; - - XSendEvent(request.display, request.requestor, False, NoEventMask, (XEvent *) &reply); - XSync(display, False); - } - - void filterSelectionClearRequest( XEvent aEvent ) - { - auto &request = aEvent.xselectionrequest; - if (request.selection == XA_PRIMARY) - gWindowImplementation->clearPrimaryText(); - else if (request.selection == XA_CLIPBOARD) - gWindowImplementation->clearSecondaryText(); - } - - int x11_clipboard_filter(void*, SDL_Event *evt) - { - Display *display = LLWindowSDL::getSDLDisplay(); - if (!display) - return 1; - - if (evt->type != SDL_SYSWMEVENT) - return 1; - - auto xevent = evt->syswm.msg->msg.x11.event; - - if (xevent.type == SelectionRequest) - filterSelectionRequest( xevent ); - else if (xevent.type == SelectionClear) - filterSelectionClearRequest( xevent ); - return 1; - } - - bool grab_property(Display* display, Window window, Atom selection, Atom target) - { - if( !display ) - return false; - - maybe_lock_display(); - - XDeleteProperty(display, window, PVT_PASTE_BUFFER); - XFlush(display); - - XConvertSelection(display, selection, target, PVT_PASTE_BUFFER, window, CurrentTime); - - // Unlock the connection so that the SDL event loop may function - maybe_unlock_display(); - - const auto start{ SDL_GetTicks() }; - const auto end{ start + 1000 }; - - XEvent xevent {}; - bool response = false; - - do - { - SDL_Event event {}; - - // Wait for an event - SDL_WaitEvent(&event); - - // If the event is a window manager event - if (event.type == SDL_SYSWMEVENT) - { - xevent = event.syswm.msg->msg.x11.event; - - if (xevent.type == SelectionNotify && xevent.xselection.requestor == window) - response = true; - } - } while (!response && SDL_GetTicks() < end ); - - return response && xevent.xselection.property != None; - } -} - -void LLWindowSDL::initialiseX11Clipboard() -{ - if (!mSDL_Display) - return; - - SDL_EventState(SDL_SYSWMEVENT, SDL_ENABLE); - SDL_SetEventFilter(x11_clipboard_filter, nullptr); - - maybe_lock_display(); - - XA_CLIPBOARD = XInternAtom(mSDL_Display, "CLIPBOARD", False); - - gSupportedAtoms[0] = XInternAtom(mSDL_Display, "UTF8_STRING", False); - gSupportedAtoms[1] = XInternAtom(mSDL_Display, "COMPOUND_TEXT", False); - gSupportedAtoms[2] = XA_STRING; - - // TARGETS atom - XA_TARGETS = XInternAtom(mSDL_Display, "TARGETS", False); - - // SL_PASTE_BUFFER atom - PVT_PASTE_BUFFER = XInternAtom(mSDL_Display, "FS_PASTE_BUFFER", False); - - maybe_unlock_display(); -} - -bool LLWindowSDL::getSelectionText( Atom aSelection, Atom aType, LLWString &text ) -{ - if( !mSDL_Display ) - return false; - - if( !grab_property(mSDL_Display, mSDL_XWindowID, aSelection,aType ) ) - return false; - - maybe_lock_display(); - - Atom type; - int format{}; - unsigned long len{},remaining {}; - unsigned char* data = nullptr; - int res = XGetWindowProperty(mSDL_Display, mSDL_XWindowID, - PVT_PASTE_BUFFER, 0, MAX_PASTE_BUFFER_SIZE, False, - AnyPropertyType, &type, &format, &len, - &remaining, &data); - if (data && len) - { - text = LLWString( - utf8str_to_wstring(reinterpret_cast< char const *>( data ) ) - ); - XFree(data); - } - - maybe_unlock_display(); - return res == Success; -} - -bool LLWindowSDL::getSelectionText(Atom selection, LLWString& text) -{ - if (!mSDL_Display) - return false; - - maybe_lock_display(); - - Window owner = XGetSelectionOwner(mSDL_Display, selection); - if (owner == None) - { - if (selection == XA_PRIMARY) - { - owner = DefaultRootWindow(mSDL_Display); - selection = XA_CUT_BUFFER0; - } - else - { - maybe_unlock_display(); - return false; - } - } - - maybe_unlock_display(); - - for( Atom atom : gSupportedAtoms ) - { - if(getSelectionText(selection, atom, text ) ) - return true; - } - - return false; -} - -bool LLWindowSDL::setSelectionText(Atom selection, const LLWString& text) -{ - maybe_lock_display(); - - if (selection == XA_PRIMARY) - { - std::string utf8 = wstring_to_utf8str(text); - XStoreBytes(mSDL_Display, utf8.c_str(), utf8.length() + 1); - mPrimaryClipboard = text; - } - else - mSecondaryClipboard = text; - - XSetSelectionOwner(mSDL_Display, selection, mSDL_XWindowID, CurrentTime); - - auto owner = XGetSelectionOwner(mSDL_Display, selection); - - maybe_unlock_display(); - - return owner == mSDL_XWindowID; -} - -Display* LLWindowSDL::getSDLDisplay() -{ - if (gWindowImplementation) - return gWindowImplementation->mSDL_Display; - return nullptr; -} - -#endif - - LLWindowSDL::LLWindowSDL(LLWindowCallbacks* callbacks, - const std::string& title, S32 x, S32 y, S32 width, + const std::string& title, const std::string& name, S32 x, S32 y, S32 width, S32 height, U32 flags, bool fullscreen, bool clearBg, bool enable_vsync, bool use_gl, @@ -390,7 +146,7 @@ LLWindowSDL::LLWindowSDL(LLWindowCallbacks* callbacks, mOriginalAspectRatio = 1024.0 / 768.0; if (title.empty()) - mWindowTitle = "SDL Window"; // *FIX: (?) + mWindowTitle = "Second Life"; else mWindowTitle = title; @@ -409,10 +165,7 @@ LLWindowSDL::LLWindowSDL(LLWindowCallbacks* callbacks, // Stash an object pointer for OSMessageBox() gWindowImplementation = this; -#if LL_X11 mFlashing = false; - initialiseX11Clipboard(); -#endif // LL_X11 mKeyVirtualKey = 0; mKeyModifiers = KMOD_NONE; @@ -434,145 +187,6 @@ static SDL_Surface *Load_BMP_Resource(const char *basename) return SDL_LoadBMP(path_buffer); } -#if LL_X11 -// This is an XFree86/XOrg-specific hack for detecting the amount of Video RAM -// on this machine. It works by searching /var/log/var/log/Xorg.?.log or -// /var/log/XFree86.?.log for a ': (VideoRAM ?|Memory): (%d+) kB' regex, where -// '?' is the X11 display number derived from $DISPLAY -static int x11_detect_VRAM_kb_fp(FILE *fp, const char *prefix_str) -{ - const int line_buf_size = 1000; - char line_buf[line_buf_size]; - while (fgets(line_buf, line_buf_size, fp)) - { - //LL_DEBUGS() << "XLOG: " << line_buf << LL_ENDL; - - // Why the ad-hoc parser instead of using a regex? Our - // favourite regex implementation - libboost_regex - is - // quite a heavy and troublesome dependency for the client, so - // it seems a shame to introduce it for such a simple task. - // *FIXME: libboost_regex is a dependency now anyway, so we may - // as well use it instead of this hand-rolled nonsense. - const char *part1_template = prefix_str; - const char part2_template[] = " kB"; - char *part1 = strstr(line_buf, part1_template); - if (part1) // found start of matching line - { - part1 = &part1[strlen(part1_template)]; // -> after - char *part2 = strstr(part1, part2_template); - if (part2) // found end of matching line - { - // now everything between part1 and part2 is - // supposed to be numeric, describing the - // number of kB of Video RAM supported - int rtn = 0; - for (; part1 < part2; ++part1) - { - if (*part1 < '0' || *part1 > '9') - { - // unexpected char, abort parse - rtn = 0; - break; - } - rtn *= 10; - rtn += (*part1) - '0'; - } - if (rtn > 0) - { - // got the kB number. return it now. - return rtn; - } - } - } - } - return 0; // 'could not detect' -} - -static int x11_detect_VRAM_kb() -{ - std::string x_log_location("/var/log/"); - std::string fname; - int rtn = 0; // 'could not detect' - int display_num = 0; - FILE *fp; - char *display_env = getenv("DISPLAY"); // e.g. :0 or :0.0 or :1.0 etc - // parse DISPLAY number so we can go grab the right log file - if (display_env[0] == ':' && - display_env[1] >= '0' && display_env[1] <= '9') - { - display_num = display_env[1] - '0'; - } - - // *TODO: we could be smarter and see which of Xorg/XFree86 has the - // freshest time-stamp. - - // Try Xorg log first - fname = x_log_location; - fname += "Xorg."; - fname += ('0' + display_num); - fname += ".log"; - fp = fopen(fname.c_str(), "r"); - if (fp) - { - LL_INFOS() << "Looking in " << fname - << " for VRAM info..." << LL_ENDL; - rtn = x11_detect_VRAM_kb_fp(fp, ": VideoRAM: "); - fclose(fp); - if (0 == rtn) - { - fp = fopen(fname.c_str(), "r"); - if (fp) - { - rtn = x11_detect_VRAM_kb_fp(fp, ": Video RAM: "); - fclose(fp); - if (0 == rtn) - { - fp = fopen(fname.c_str(), "r"); - if (fp) - { - rtn = x11_detect_VRAM_kb_fp(fp, ": Memory: "); - fclose(fp); - } - } - } - } - } - else - { - LL_INFOS() << "Could not open " << fname - << " - skipped." << LL_ENDL; - // Try old XFree86 log otherwise - fname = x_log_location; - fname += "XFree86."; - fname += ('0' + display_num); - fname += ".log"; - fp = fopen(fname.c_str(), "r"); - if (fp) - { - LL_INFOS() << "Looking in " << fname - << " for VRAM info..." << LL_ENDL; - rtn = x11_detect_VRAM_kb_fp(fp, ": VideoRAM: "); - fclose(fp); - if (0 == rtn) - { - fp = fopen(fname.c_str(), "r"); - if (fp) - { - rtn = x11_detect_VRAM_kb_fp(fp, ": Memory: "); - fclose(fp); - } - } - } - else - { - LL_INFOS() << "Could not open " << fname - << " - skipped." << LL_ENDL; - } - } - return rtn; -} -#endif // LL_X11 - void LLWindowSDL::setTitle(const std::string title) { SDL_SetWindowTitle( mWindow, title.c_str() ); @@ -633,8 +247,10 @@ void LLWindowSDL::tryFindFullscreenSize( int &width, int &height ) bool LLWindowSDL::createContext(int x, int y, int width, int height, int bits, bool fullscreen, bool enable_vsync) { - //bool glneedsinit = false; - + if (width == 0) + width = 1024; + if (height == 0) + width = 768; LL_INFOS() << "createContext, fullscreen=" << fullscreen << " size=" << width << "x" << height << LL_ENDL; @@ -642,54 +258,14 @@ bool LLWindowSDL::createContext(int x, int y, int width, int height, int bits, b mGrabbyKeyFlags = 0; mReallyCapturedCount = 0; - std::initializer_list<std::tuple< char const*, char const * > > hintList = - { - {SDL_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR,"0"}, - {SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH,"1"}, - {SDL_HINT_IME_INTERNAL_EDITING,"1"} - }; - - for( auto hint: hintList ) - { - SDL_SetHint( std::get<0>(hint), std::get<1>(hint)); - } - - std::initializer_list<std::tuple<uint32_t, char const*, bool>> initList= - { {SDL_INIT_VIDEO,"SDL_INIT_VIDEO", true}, - {SDL_INIT_AUDIO,"SDL_INIT_AUDIO", false}, - {SDL_INIT_GAMECONTROLLER,"SDL_INIT_GAMECONTROLLER", false}, - {SDL_INIT_SENSOR,"SDL_INIT_SENSOR", false} - }; - - for( auto subSystem : initList) - { - if( SDL_InitSubSystem( std::get<0>(subSystem) ) < 0 ) - { - LL_WARNS() << "SDL_InitSubSystem for " << std::get<1>(subSystem) << " failed " << SDL_GetError() << LL_ENDL; - - if( std::get<2>(subSystem)) - setupFailure("SDL_Init() failure", "error", OSMB_OK); - - } - } - - SDL_version c_sdl_version; - SDL_VERSION(&c_sdl_version); - LL_INFOS() << "Compiled against SDL " - << int(c_sdl_version.major) << "." - << int(c_sdl_version.minor) << "." - << int(c_sdl_version.patch) << LL_ENDL; - SDL_version r_sdl_version; - SDL_GetVersion(&r_sdl_version); - LL_INFOS() << " Running against SDL " - << int(r_sdl_version.major) << "." - << int(r_sdl_version.minor) << "." - << int(r_sdl_version.patch) << LL_ENDL; - if (width == 0) width = 1024; if (height == 0) width = 768; + if (x == 0) + x = SDL_WINDOWPOS_UNDEFINED; + if (y == 0) + y = SDL_WINDOWPOS_UNDEFINED; mFullscreen = fullscreen; @@ -703,51 +279,54 @@ bool LLWindowSDL::createContext(int x, int y, int width, int height, int bits, b mSDLFlags = sdlflags; + // Setup default backing colors GLint redBits{8}, greenBits{8}, blueBits{8}, alphaBits{8}; + GLint depthBits{24}, stencilBits{8}; - GLint depthBits{(bits <= 16) ? 16 : 24}, stencilBits{8}; - - if (getenv("LL_GL_NO_STENCIL")) - stencilBits = 0; - - SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, alphaBits); SDL_GL_SetAttribute(SDL_GL_RED_SIZE, redBits); SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, greenBits); SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, blueBits); - SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, depthBits ); - - // We need stencil support for a few (minor) things. - if (stencilBits) - SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, stencilBits); - // *FIX: try to toggle vsync here? + SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, alphaBits); + SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, depthBits); + SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, stencilBits); SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); - if (mFSAASamples > 0) + U32 context_flags = 0; + if (gDebugGL) { - SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1); - SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, mFSAASamples); + context_flags |= SDL_GL_CONTEXT_DEBUG_FLAG; } - + SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, context_flags); SDL_GL_SetAttribute(SDL_GL_SHARE_WITH_CURRENT_CONTEXT, 1); - mWindow = SDL_CreateWindow( mWindowTitle.c_str(), SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width, height, mSDLFlags ); - if( mWindow ) + // Create the window + mWindow = SDL_CreateWindow(mWindowTitle.c_str(), x, y, width, height, mSDLFlags); + if (mWindow == nullptr) { - mContext = SDL_GL_CreateContext( mWindow ); + LL_WARNS() << "Window creation failure. SDL: " << SDL_GetError() << LL_ENDL; + setupFailure("Window creation error", "Error", OSMB_OK); + return false; + } - if( mContext == 0 ) - { - LL_WARNS() << "Cannot create GL context " << SDL_GetError() << LL_ENDL; - setupFailure("GL Context creation error creation error", "Error", OSMB_OK); - return false; - } - // SDL_GL_SetSwapInterval(1); - mSurface = SDL_GetWindowSurface( mWindow ); + // Create the context + mContext = SDL_GL_CreateContext(mWindow); + if(!mContext) + { + LL_WARNS() << "Cannot create GL context " << SDL_GetError() << LL_ENDL; + setupFailure("GL Context creation error", "Error", OSMB_OK); + return false; } + if (SDL_GL_MakeCurrent(mWindow, mContext) != 0) + { + LL_WARNS() << "Failed to make context current. SDL: " << SDL_GetError() << LL_ENDL; + setupFailure("GL Context failed to set current failure", "Error", OSMB_OK); + return false; + } - if( mFullscreen ) + mSurface = SDL_GetWindowSurface(mWindow); + if(mFullscreen) { if (mSurface) { @@ -788,40 +367,6 @@ bool LLWindowSDL::createContext(int x, int y, int width, int height, int bits, b } } - // Set the application icon. - SDL_Surface *bmpsurface; - bmpsurface = Load_BMP_Resource("ll_icon.BMP"); - if (bmpsurface) - { - SDL_SetWindowIcon(mWindow, bmpsurface); - SDL_FreeSurface(bmpsurface); - bmpsurface = NULL; - } - - // Detect video memory size. -# if LL_X11 - gGLManager.mVRAM = x11_detect_VRAM_kb() / 1024; - if (gGLManager.mVRAM != 0) - { - LL_INFOS() << "X11 log-parser detected " << gGLManager.mVRAM << "MB VRAM." << LL_ENDL; - } else -# endif // LL_X11 - { - // fallback to letting SDL detect VRAM. - // note: I've not seen SDL's detection ever actually find - // VRAM != 0, but if SDL *does* detect it then that's a bonus. - gGLManager.mVRAM = 0; - if (gGLManager.mVRAM != 0) - { - LL_INFOS() << "SDL detected " << gGLManager.mVRAM << "MB VRAM." << LL_ENDL; - } - } - // If VRAM is not detected, that is handled later - - // *TODO: Now would be an appropriate time to check for some - // explicitly unsupported cards. - //const char* RENDERER = (const char*) glGetString(GL_RENDERER); - SDL_GL_GetAttribute(SDL_GL_RED_SIZE, &redBits); SDL_GL_GetAttribute(SDL_GL_GREEN_SIZE, &greenBits); SDL_GL_GetAttribute(SDL_GL_BLUE_SIZE, &blueBits); @@ -855,6 +400,20 @@ bool LLWindowSDL::createContext(int x, int y, int width, int height, int bits, b return false; } + LL_PROFILER_GPU_CONTEXT; + + // Enable vertical sync + toggleVSync(enable_vsync); + + // Set the application icon. + SDL_Surface* bmpsurface = Load_BMP_Resource("ll_icon.BMP"); + if (bmpsurface) + { + SDL_SetWindowIcon(mWindow, bmpsurface); + SDL_FreeSurface(bmpsurface); + bmpsurface = NULL; + } + #if LL_X11 /* Grab the window manager specific information */ SDL_SysWMinfo info; @@ -880,7 +439,6 @@ bool LLWindowSDL::createContext(int x, int y, int width, int height, int bits, b } #endif // LL_X11 - SDL_StartTextInput(); //make sure multisampling is disabled by default glDisable(GL_MULTISAMPLE_ARB); @@ -889,6 +447,43 @@ bool LLWindowSDL::createContext(int x, int y, int width, int height, int bits, b return true; } +void* LLWindowSDL::createSharedContext() +{ + SDL_GLContext pContext = SDL_GL_CreateContext(mWindow); + if (pContext) + { + LL_DEBUGS() << "Creating shared OpenGL context successful!" << LL_ENDL; + return (void*)pContext; + } + + LL_WARNS() << "Creating shared OpenGL context failed!" << LL_ENDL; + return nullptr; +} + +void LLWindowSDL::makeContextCurrent(void* contextPtr) +{ + SDL_GL_MakeCurrent(mWindow, contextPtr); + LL_PROFILER_GPU_CONTEXT; +} + +void LLWindowSDL::destroySharedContext(void* contextPtr) +{ + SDL_GL_DeleteContext(contextPtr); +} + +void LLWindowSDL::toggleVSync(bool enable_vsync) +{ + if (!enable_vsync) + { + LL_INFOS("Window") << "Disabling vertical sync" << LL_ENDL; + SDL_GL_SetSwapInterval(0); + } + else + { + LL_INFOS("Window") << "Enabling vertical sync" << LL_ENDL; + SDL_GL_SetSwapInterval(1); + } +} // changing fullscreen resolution, or switching between windowed and fullscreen mode. bool LLWindowSDL::switchContext(bool fullscreen, const LLCoordScreen &size, bool enable_vsync, const LLCoordScreen * const posp) @@ -901,7 +496,7 @@ bool LLWindowSDL::switchContext(bool fullscreen, const LLCoordScreen &size, bool if(needsRebuild) { destroyContext(); - result = createContext(0, 0, size.mX, size.mY, 0, fullscreen, enable_vsync); + result = createContext(0, 0, size.mX, size.mY, 32, fullscreen, enable_vsync); if (result) { gGLManager.initGL(); @@ -921,7 +516,13 @@ void LLWindowSDL::destroyContext() { LL_INFOS() << "destroyContext begins" << LL_ENDL; + // Stop unicode input SDL_StopTextInput(); + + // Clean up remaining GL state before blowing away window + LL_INFOS() << "shutdownGL begins" << LL_ENDL; + gGLManager.shutdownGL(); + #if LL_X11 mSDL_Display = NULL; mSDL_XWindowID = None; @@ -929,18 +530,38 @@ void LLWindowSDL::destroyContext() Unlock_Display = NULL; #endif // LL_X11 - // Clean up remaining GL state before blowing away window - LL_INFOS() << "shutdownGL begins" << LL_ENDL; - gGLManager.shutdownGL(); + LL_INFOS() << "Destroying SDL cursors" << LL_ENDL; + quitCursors(); + + if (mContext) + { + LL_INFOS() << "Destroying SDL GL Context" << LL_ENDL; + SDL_GL_DeleteContext(mContext); + mContext = nullptr; + } + else + { + LL_INFOS() << "SDL GL Context already destroyed" << LL_ENDL; + } + + if (mWindow) + { + LL_INFOS() << "Destroying SDL Window" << LL_ENDL; + SDL_DestroyWindow(mWindow); + mWindow = nullptr; + } + else + { + LL_INFOS() << "SDL Window already destroyed" << LL_ENDL; + } + LL_INFOS() << "destroyContext end" << LL_ENDL; + LL_INFOS() << "SDL_QuitSS/VID begins" << LL_ENDL; SDL_QuitSubSystem(SDL_INIT_VIDEO); // *FIX: this might be risky... - - mWindow = NULL; } LLWindowSDL::~LLWindowSDL() { - quitCursors(); destroyContext(); if(mSupportedResolutions != NULL) @@ -954,27 +575,38 @@ LLWindowSDL::~LLWindowSDL() void LLWindowSDL::show() { - // *FIX: What to do with SDL? + if (mWindow) + { + SDL_ShowWindow(mWindow); + } } void LLWindowSDL::hide() { - // *FIX: What to do with SDL? + if (mWindow) + { + SDL_HideWindow(mWindow); + } } //virtual void LLWindowSDL::minimize() { - // *FIX: What to do with SDL? + if (mWindow) + { + SDL_MinimizeWindow(mWindow); + } } //virtual void LLWindowSDL::restore() { - // *FIX: What to do with SDL? + if (mWindow) + { + SDL_RestoreWindow(mWindow); + } } - // close() destroys all OS-specific code associated with a window. // Usually called from LLWindowManager::destroyWindow() void LLWindowSDL::close() @@ -997,63 +629,70 @@ bool LLWindowSDL::isValid() return (mWindow != NULL); } -bool LLWindowSDL::getVisible() +bool LLWindowSDL::getVisible() const { bool result = false; - - // *FIX: This isn't really right... - // Then what is? if (mWindow) { - result = true; + Uint32 flags = SDL_GetWindowFlags(mWindow); + if (flags & SDL_WINDOW_SHOWN) + { + result = true; + } } - - return(result); + return result; } -bool LLWindowSDL::getMinimized() +bool LLWindowSDL::getMinimized() const { bool result = false; - - if (mWindow && (1 == mIsMinimized)) + if (mWindow) { - result = true; + Uint32 flags = SDL_GetWindowFlags(mWindow); + if (flags & SDL_WINDOW_MINIMIZED) + { + result = true; + } } - return(result); + return result; } -bool LLWindowSDL::getMaximized() +bool LLWindowSDL::getMaximized() const { bool result = false; - if (mWindow) { - // TODO + Uint32 flags = SDL_GetWindowFlags(mWindow); + if (flags & SDL_WINDOW_MAXIMIZED) + { + result = true; + } } - return(result); + return result; } bool LLWindowSDL::maximize() { - // TODO + if (mWindow) + { + SDL_MaximizeWindow(mWindow); + return true; + } return false; } -bool LLWindowSDL::getFullscreen() -{ - return mFullscreen; -} - -bool LLWindowSDL::getPosition(LLCoordScreen *position) +bool LLWindowSDL::getPosition(LLCoordScreen *position) const { - // *FIX: can anything be done with this? - position->mX = 0; - position->mY = 0; - return true; + if (mWindow) + { + SDL_GetWindowPosition(mWindow, &position->mX, &position->mY); + return true; + } + return false; } -bool LLWindowSDL::getSize(LLCoordScreen *size) +bool LLWindowSDL::getSize(LLCoordScreen *size) const { if (mSurface) { @@ -1065,7 +704,7 @@ bool LLWindowSDL::getSize(LLCoordScreen *size) return (false); } -bool LLWindowSDL::getSize(LLCoordWindow *size) +bool LLWindowSDL::getSize(LLCoordWindow *size) const { if (mSurface) { @@ -1079,13 +718,13 @@ bool LLWindowSDL::getSize(LLCoordWindow *size) bool LLWindowSDL::setPosition(const LLCoordScreen position) { - if(mWindow) + if (mWindow) { - // *FIX: (?) - //MacMoveWindow(mWindow, position.mX, position.mY, false); + SDL_SetWindowPosition(mWindow, position.mX, position.mY); + return true; } - return true; + return false; } template< typename T > bool setSizeImpl( const T& newSize, SDL_Window *pWin ) @@ -1126,11 +765,12 @@ void LLWindowSDL::swapBuffers() { if (mWindow) { - SDL_GL_SwapWindow( mWindow ); + SDL_GL_SwapWindow(mWindow); } + LL_PROFILER_GPU_COLLECT; } -U32 LLWindowSDL::getFSAASamples() +U32 LLWindowSDL::getFSAASamples() const { return mFSAASamples; } @@ -1140,24 +780,35 @@ void LLWindowSDL::setFSAASamples(const U32 samples) mFSAASamples = samples; } -F32 LLWindowSDL::getGamma() +F32 LLWindowSDL::getGamma() const { - return 1/mGamma; + return 1.f / mGamma; } bool LLWindowSDL::restoreGamma() { - //CGDisplayRestoreColorSyncSettings(); - // SDL_SetGamma(1.0f, 1.0f, 1.0f); + if (mWindow) + { + Uint16 ramp[256]; + SDL_CalculateGammaRamp(1.f, ramp); + SDL_SetWindowGammaRamp(mWindow, ramp, ramp, ramp); + } return true; } bool LLWindowSDL::setGamma(const F32 gamma) { - mGamma = gamma; - if (mGamma == 0) mGamma = 0.1f; - mGamma = 1/mGamma; - // SDL_SetGamma(mGamma, mGamma, mGamma); + if (mWindow) + { + Uint16 ramp[256]; + + mGamma = gamma; + if (mGamma == 0) mGamma = 0.1f; + mGamma = 1.f / mGamma; + + SDL_CalculateGammaRamp(mGamma, ramp); + SDL_SetWindowGammaRamp(mWindow, ramp, ramp, ramp); + } return true; } @@ -1166,10 +817,8 @@ bool LLWindowSDL::isCursorHidden() return mCursorHidden; } - - // Constrains the mouse to the window. -void LLWindowSDL::setMouseClipping( bool b ) +void LLWindowSDL::setMouseClipping(bool b) { //SDL_WM_GrabInput(b ? SDL_GRAB_ON : SDL_GRAB_OFF); } @@ -1179,18 +828,10 @@ void LLWindowSDL::setMinSize(U32 min_width, U32 min_height, bool enforce_immedia { LLWindow::setMinSize(min_width, min_height, enforce_immediately); -#if LL_X11 - // Set the minimum size limits for X11 window - // so the window manager doesn't allow resizing below those limits. - XSizeHints* hints = XAllocSizeHints(); - hints->flags |= PMinSize; - hints->min_width = mMinWindowWidth; - hints->min_height = mMinWindowHeight; - - XSetWMNormalHints(mSDL_Display, mSDL_XWindowID, hints); - - XFree(hints); -#endif + if (mWindow && min_width > 0 && min_height > 0) + { + SDL_SetWindowMinimumSize(mWindow, mMinWindowWidth, mMinWindowHeight); + } } bool LLWindowSDL::setCursorPosition(const LLCoordWindow position) @@ -1218,7 +859,6 @@ bool LLWindowSDL::getCursorPosition(LLCoordWindow *position) //Point cursor_point; LLCoordScreen screen_pos; - //GetMouse(&cursor_point); int x, y; SDL_GetMouseState(&x, &y); @@ -1333,85 +973,70 @@ void LLWindowSDL::afterDialog() } } - -#if LL_X11 -// set/reset the XWMHints flag for 'urgency' that usually makes the icon flash -void LLWindowSDL::x11_set_urgent(bool urgent) -{ - if (mSDL_Display && !mFullscreen) - { - XWMHints *wm_hints; - - LL_INFOS() << "X11 hint for urgency, " << urgent << LL_ENDL; - - maybe_lock_display(); - wm_hints = XGetWMHints(mSDL_Display, mSDL_XWindowID); - if (!wm_hints) - wm_hints = XAllocWMHints(); - - if (urgent) - wm_hints->flags |= XUrgencyHint; - else - wm_hints->flags &= ~XUrgencyHint; - - XSetWMHints(mSDL_Display, mSDL_XWindowID, wm_hints); - XFree(wm_hints); - XSync(mSDL_Display, False); - maybe_unlock_display(); - } -} -#endif // LL_X11 - void LLWindowSDL::flashIcon(F32 seconds) { - if (getMinimized()) - { -#if !LL_X11 - LL_INFOS() << "Stub LLWindowSDL::flashIcon(" << seconds << ")" << LL_ENDL; -#else - LL_INFOS() << "X11 LLWindowSDL::flashIcon(" << seconds << ")" << LL_ENDL; + LL_INFOS() << "LLWindowSDL::flashIcon(" << seconds << ")" << LL_ENDL; - F32 remaining_time = mFlashTimer.getRemainingTimeF32(); - if (remaining_time < seconds) - remaining_time = seconds; - mFlashTimer.reset(); - mFlashTimer.setTimerExpirySec(remaining_time); + F32 remaining_time = mFlashTimer.getRemainingTimeF32(); + if (remaining_time < seconds) + remaining_time = seconds; + mFlashTimer.reset(); + mFlashTimer.setTimerExpirySec(remaining_time); - x11_set_urgent(true); - mFlashing = true; -#endif // LL_X11 - } + SDL_FlashWindow(mWindow, SDL_FLASH_UNTIL_FOCUSED); + mFlashing = true; } bool LLWindowSDL::isClipboardTextAvailable() { - return mSDL_Display && XGetSelectionOwner(mSDL_Display, XA_CLIPBOARD) != None; + return SDL_HasClipboardText() == SDL_TRUE; } bool LLWindowSDL::pasteTextFromClipboard(LLWString &dst) { - return getSelectionText(XA_CLIPBOARD, dst); + if (isClipboardTextAvailable()) + { + char* data = SDL_GetClipboardText(); + if (data) + { + dst = LLWString(utf8str_to_wstring(data)); + SDL_free(data); + return true; + } + } + return false; } -bool LLWindowSDL::copyTextToClipboard(const LLWString &s) +bool LLWindowSDL::copyTextToClipboard(const LLWString& text) { - return setSelectionText(XA_CLIPBOARD, s); + const std::string utf8 = wstring_to_utf8str(text); + return SDL_SetClipboardText(utf8.c_str()) == 0; // success == 0 } bool LLWindowSDL::isPrimaryTextAvailable() { - LLWString text; - return getSelectionText(XA_PRIMARY, text) && !text.empty(); + return SDL_HasPrimarySelectionText() == SDL_TRUE; } bool LLWindowSDL::pasteTextFromPrimary(LLWString &dst) { - return getSelectionText(XA_PRIMARY, dst); + if (isPrimaryTextAvailable()) + { + char* data = SDL_GetPrimarySelectionText(); + if (data) + { + dst = LLWString(utf8str_to_wstring(data)); + SDL_free(data); + return true; + } + } + return false; } -bool LLWindowSDL::copyTextToPrimary(const LLWString &s) +bool LLWindowSDL::copyTextToPrimary(const LLWString& text) { - return setSelectionText(XA_PRIMARY, s); + const std::string utf8 = wstring_to_utf8str(text); + return SDL_SetPrimarySelectionText(utf8.c_str()) == 0; // success == 0 } LLWindow::LLWindowResolution* LLWindowSDL::getSupportedResolutions(S32 &num_resolutions) @@ -1454,7 +1079,7 @@ LLWindow::LLWindowResolution* LLWindowSDL::getSupportedResolutions(S32 &num_reso return mSupportedResolutions; } -bool LLWindowSDL::convertCoords(LLCoordGL from, LLCoordWindow *to) +bool LLWindowSDL::convertCoords(LLCoordGL from, LLCoordWindow *to) const { if (!to) return false; @@ -1465,7 +1090,7 @@ bool LLWindowSDL::convertCoords(LLCoordGL from, LLCoordWindow *to) return true; } -bool LLWindowSDL::convertCoords(LLCoordWindow from, LLCoordGL* to) +bool LLWindowSDL::convertCoords(LLCoordWindow from, LLCoordGL* to) const { if (!to) return false; @@ -1476,7 +1101,7 @@ bool LLWindowSDL::convertCoords(LLCoordWindow from, LLCoordGL* to) return true; } -bool LLWindowSDL::convertCoords(LLCoordScreen from, LLCoordWindow* to) +bool LLWindowSDL::convertCoords(LLCoordScreen from, LLCoordWindow* to) const { if (!to) return false; @@ -1487,7 +1112,7 @@ bool LLWindowSDL::convertCoords(LLCoordScreen from, LLCoordWindow* to) return (true); } -bool LLWindowSDL::convertCoords(LLCoordWindow from, LLCoordScreen *to) +bool LLWindowSDL::convertCoords(LLCoordWindow from, LLCoordScreen *to) const { if (!to) return false; @@ -1498,23 +1123,20 @@ bool LLWindowSDL::convertCoords(LLCoordWindow from, LLCoordScreen *to) return (true); } -bool LLWindowSDL::convertCoords(LLCoordScreen from, LLCoordGL *to) +bool LLWindowSDL::convertCoords(LLCoordScreen from, LLCoordGL *to) const { LLCoordWindow window_coord; return(convertCoords(from, &window_coord) && convertCoords(window_coord, to)); } -bool LLWindowSDL::convertCoords(LLCoordGL from, LLCoordScreen *to) +bool LLWindowSDL::convertCoords(LLCoordGL from, LLCoordScreen *to) const { LLCoordWindow window_coord; return(convertCoords(from, &window_coord) && convertCoords(window_coord, to)); } - - - void LLWindowSDL::setupFailure(const std::string& text, const std::string& caption, U32 type) { destroyContext(); @@ -1549,47 +1171,24 @@ bool LLWindowSDL::SDLReallyCaptureInput(bool capture) bool newGrab = wantGrab; -#if LL_X11 if (!mFullscreen) /* only bother if we're windowed anyway */ { - if (mSDL_Display) + int result; + if (wantGrab == true) { - /* we dirtily mix raw X11 with SDL so that our pointer - isn't (as often) constrained to the limits of the - window while grabbed, which feels nicer and - hopefully eliminates some reported 'sticky pointer' - problems. We use raw X11 instead of - SDL_WM_GrabInput() because the latter constrains - the pointer to the window and also steals all - *keyboard* input from the window manager, which was - frustrating users. */ - int result; - if (wantGrab == true) - { - maybe_lock_display(); - result = XGrabPointer(mSDL_Display, mSDL_XWindowID, - True, 0, GrabModeAsync, - GrabModeAsync, - None, None, CurrentTime); - maybe_unlock_display(); - if (GrabSuccess == result) - newGrab = true; - else - newGrab = false; - } + result = SDL_CaptureMouse(SDL_TRUE); + if (0 == result) + newGrab = true; else - { newGrab = false; - - maybe_lock_display(); - XUngrabPointer(mSDL_Display, CurrentTime); - // Make sure the ungrab happens RIGHT NOW. - XSync(mSDL_Display, False); - maybe_unlock_display(); - } + } + else + { + newGrab = false; + result = SDL_CaptureMouse(SDL_FALSE); } } -#endif // LL_X11 + // return boolean success for whether we ended up in the desired state return capture == newGrab; } @@ -1719,7 +1318,7 @@ void check_vm_bloat() last_rss_size = this_rss_size; last_vm_size = this_vm_size; - finally: +finally: if (NULL != ptr) { free(ptr); @@ -1753,13 +1352,8 @@ void LLWindowSDL::processMiscNativeEvents() } } -void LLWindowSDL::gatherInput() +void LLWindowSDL::gatherInput(bool app_has_focus) { - const Uint32 CLICK_THRESHOLD = 300; // milliseconds - static int leftClick = 0; - static int rightClick = 0; - static Uint32 lastLeftDown = 0; - static Uint32 lastRightDown = 0; SDL_Event event; // Handle all outstanding SDL events @@ -1768,13 +1362,21 @@ void LLWindowSDL::gatherInput() switch (event.type) { case SDL_MOUSEWHEEL: + { if( event.wheel.y != 0 ) + { mCallbacks->handleScrollWheel(this, -event.wheel.y); + } + if (event.wheel.x != 0) + { + mCallbacks->handleScrollHWheel(this, -event.wheel.x); + } break; + } case SDL_MOUSEMOTION: { - LLCoordWindow winCoord(event.button.x, event.button.y); + LLCoordWindow winCoord(event.motion.x, event.motion.y); LLCoordGL openGlCoord; convertCoords(winCoord, &openGlCoord); MASK mask = gKeyboard->currentMask(true); @@ -1847,64 +1449,30 @@ void LLWindowSDL::gatherInput() case SDL_MOUSEBUTTONDOWN: { - bool isDoubleClick = false; LLCoordWindow winCoord(event.button.x, event.button.y); LLCoordGL openGlCoord; convertCoords(winCoord, &openGlCoord); MASK mask = gKeyboard->currentMask(true); - if (event.button.button == SDL_BUTTON_LEFT) // SDL doesn't manage double clicking... - { - Uint32 now = SDL_GetTicks(); - if ((now - lastLeftDown) > CLICK_THRESHOLD) - leftClick = 1; - else - { - if (++leftClick >= 2) - { - leftClick = 0; - isDoubleClick = true; - } - } - lastLeftDown = now; - } - else if (event.button.button == SDL_BUTTON_RIGHT) - { - Uint32 now = SDL_GetTicks(); - if ((now - lastRightDown) > CLICK_THRESHOLD) - rightClick = 1; - else - { - if (++rightClick >= 2) - { - rightClick = 0; - isDoubleClick = true; - } - } - lastRightDown = now; - } - if (event.button.button == SDL_BUTTON_LEFT) // left { - if (isDoubleClick) + if (event.button.clicks >= 2) mCallbacks->handleDoubleClick(this, openGlCoord, mask); else mCallbacks->handleMouseDown(this, openGlCoord, mask); } - else if (event.button.button == SDL_BUTTON_RIGHT) // right { mCallbacks->handleRightMouseDown(this, openGlCoord, mask); } - else if (event.button.button == SDL_BUTTON_MIDDLE) // middle { mCallbacks->handleMiddleMouseDown(this, openGlCoord, mask); } - else if (event.button.button == 4) // mousewheel up...thanks to X11 for making SDL consider these "buttons". - mCallbacks->handleScrollWheel(this, -1); - else if (event.button.button == 5) // mousewheel down...thanks to X11 for making SDL consider these "buttons". - mCallbacks->handleScrollWheel(this, 1); + else + { + mCallbacks->handleOtherMouseDown(this, openGlCoord, mask, event.button.button); + } break; } @@ -1917,64 +1485,65 @@ void LLWindowSDL::gatherInput() MASK mask = gKeyboard->currentMask(true); if (event.button.button == SDL_BUTTON_LEFT) // left + { mCallbacks->handleMouseUp(this, openGlCoord, mask); + } else if (event.button.button == SDL_BUTTON_RIGHT) // right + { mCallbacks->handleRightMouseUp(this, openGlCoord, mask); + } else if (event.button.button == SDL_BUTTON_MIDDLE) // middle + { mCallbacks->handleMiddleMouseUp(this, openGlCoord, mask); - // don't handle mousewheel here... + } + else + { + mCallbacks->handleOtherMouseUp(this, openGlCoord, mask, event.button.button); + } break; } - case SDL_WINDOWEVENT: // *FIX: handle this? + case SDL_WINDOWEVENT: { - if( event.window.event == SDL_WINDOWEVENT_RESIZED - /* || event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED*/ ) // <FS:ND> SDL_WINDOWEVENT_SIZE_CHANGED is followed by SDL_WINDOWEVENT_RESIZED, so handling one shall be enough - { - LL_INFOS() << "Handling a resize event: " << event.window.data1 << "x" << event.window.data2 << LL_ENDL; - - S32 width = llmax(event.window.data1, (S32)mMinWindowWidth); - S32 height = llmax(event.window.data2, (S32)mMinWindowHeight); - mSurface = SDL_GetWindowSurface( mWindow ); - - // *FIX: I'm not sure this is necessary! - // <FS:ND> I think is is not - // SDL_SetWindowSize(mWindow, width, height); - // - - mCallbacks->handleResize(this, width, height); - } - else if( event.window.event == SDL_WINDOWEVENT_FOCUS_GAINED ) // <FS:ND> What about SDL_WINDOWEVENT_ENTER (mouse focus) - { - // We have to do our own state massaging because SDL - // can send us two unfocus events in a row for example, - // which confuses the focus code [SL-24071]. - mHaveInputFocus = true; - - mCallbacks->handleFocus(this); - } - else if( event.window.event == SDL_WINDOWEVENT_FOCUS_LOST ) // <FS:ND> What about SDL_WINDOWEVENT_LEAVE (mouse focus) + switch(event.window.event) { - // We have to do our own state massaging because SDL - // can send us two unfocus events in a row for example, - // which confuses the focus code [SL-24071]. - mHaveInputFocus = false; + //case SDL_WINDOWEVENT_SIZE_CHANGED: <FS:ND> SDL_WINDOWEVENT_SIZE_CHANGED is followed by SDL_WINDOWEVENT_RESIZED, so handling one shall be enough + case SDL_WINDOWEVENT_RESIZED: + { + LL_INFOS() << "Handling a resize event: " << event.window.data1 << "x" << event.window.data2 << LL_ENDL; + S32 width = llmax(event.window.data1, (S32)mMinWindowWidth); + S32 height = llmax(event.window.data2, (S32)mMinWindowHeight); - mCallbacks->handleFocusLost(this); - } - else if( event.window.event == SDL_WINDOWEVENT_MINIMIZED || - event.window.event == SDL_WINDOWEVENT_MAXIMIZED || - event.window.event == SDL_WINDOWEVENT_RESTORED || - event.window.event == SDL_WINDOWEVENT_EXPOSED || - event.window.event == SDL_WINDOWEVENT_SHOWN ) - { - mIsMinimized = (event.window.event == SDL_WINDOWEVENT_MINIMIZED); + mSurface = SDL_GetWindowSurface(mWindow); + mCallbacks->handleResize(this, width, height); + break; + } + case SDL_WINDOWEVENT_LEAVE: + mCallbacks->handleMouseLeave(this); + break; + case SDL_WINDOWEVENT_FOCUS_GAINED: + mCallbacks->handleFocus(this); + break; + case SDL_WINDOWEVENT_FOCUS_LOST: + mCallbacks->handleFocusLost(this); + break; + case SDL_WINDOWEVENT_EXPOSED: + case SDL_WINDOWEVENT_SHOWN: + case SDL_WINDOWEVENT_HIDDEN: + case SDL_WINDOWEVENT_MINIMIZED: + case SDL_WINDOWEVENT_MAXIMIZED: + case SDL_WINDOWEVENT_RESTORED: + { + Uint32 flags = SDL_GetWindowFlags(mWindow); + bool minimized = (flags & SDL_WINDOW_MINIMIZED); + bool hidden = (flags & SDL_WINDOW_HIDDEN); - mCallbacks->handleActivate(this, !mIsMinimized); - LL_INFOS() << "SDL deiconification state switched to " << mIsMinimized << LL_ENDL; + mCallbacks->handleActivate(this, !minimized || !hidden); + LL_INFOS() << "SDL deiconification state switched to " << minimized << LL_ENDL; + break; + } } - break; } case SDL_QUIT: @@ -1986,27 +1555,25 @@ void LLWindowSDL::gatherInput() } break; default: - //LL_INFOS() << "Unhandled SDL event type " << event.type << LL_ENDL; + LLGameControl::handleEvent(event, app_has_focus); break; } } updateCursor(); -#if LL_X11 // This is a good time to stop flashing the icon if our mFlashTimer has // expired. if (mFlashing && mFlashTimer.hasExpired()) { - x11_set_urgent(false); + SDL_FlashWindow(mWindow, SDL_FLASH_CANCEL); mFlashing = false; } -#endif // LL_X11 } static SDL_Cursor *makeSDLCursorFromBMP(const char *filename, int hotx, int hoty) { - SDL_Cursor *sdlcursor = NULL; + SDL_Cursor *sdlcursor = nullptr; SDL_Surface *bmpsurface; // Load cursor pixel data from BMP file @@ -2080,12 +1647,6 @@ static SDL_Cursor *makeSDLCursorFromBMP(const char *filename, int hotx, int hoty void LLWindowSDL::updateCursor() { - if (ATIbug) { - // cursor-updating is very flaky when this bug is - // present; do nothing. - return; - } - if (mCurrentCursor != mNextCursor) { if (mNextCursor < UI_CURSOR_COUNT) @@ -2097,10 +1658,13 @@ void LLWindowSDL::updateCursor() sdlcursor = mSDLCursors[UI_CURSOR_ARROW]; if (sdlcursor) SDL_SetCursor(sdlcursor); - } else { + + mCurrentCursor = mNextCursor; + } + else + { LL_WARNS() << "Tried to set invalid cursor number " << mNextCursor << LL_ENDL; } - mCurrentCursor = mNextCursor; } } @@ -2110,24 +1674,24 @@ void LLWindowSDL::initCursors() // Blank the cursor pointer array for those we may miss. for (i=0; i<UI_CURSOR_COUNT; ++i) { - mSDLCursors[i] = NULL; + mSDLCursors[i] = nullptr; } // Pre-make an SDL cursor for each of the known cursor types. // We hardcode the hotspots - to avoid that we'd have to write // a .cur file loader. // NOTE: SDL doesn't load RLE-compressed BMP files. - mSDLCursors[UI_CURSOR_ARROW] = makeSDLCursorFromBMP("llarrow.BMP",0,0); - mSDLCursors[UI_CURSOR_WAIT] = makeSDLCursorFromBMP("wait.BMP",12,15); - mSDLCursors[UI_CURSOR_HAND] = makeSDLCursorFromBMP("hand.BMP",7,10); - mSDLCursors[UI_CURSOR_IBEAM] = makeSDLCursorFromBMP("ibeam.BMP",15,16); - mSDLCursors[UI_CURSOR_CROSS] = makeSDLCursorFromBMP("cross.BMP",16,14); - mSDLCursors[UI_CURSOR_SIZENWSE] = makeSDLCursorFromBMP("sizenwse.BMP",14,17); - mSDLCursors[UI_CURSOR_SIZENESW] = makeSDLCursorFromBMP("sizenesw.BMP",17,17); - mSDLCursors[UI_CURSOR_SIZEWE] = makeSDLCursorFromBMP("sizewe.BMP",16,14); - mSDLCursors[UI_CURSOR_SIZENS] = makeSDLCursorFromBMP("sizens.BMP",17,16); - mSDLCursors[UI_CURSOR_SIZEALL] = makeSDLCursorFromBMP("sizeall.BMP", 17, 17); - mSDLCursors[UI_CURSOR_NO] = makeSDLCursorFromBMP("llno.BMP",8,8); - mSDLCursors[UI_CURSOR_WORKING] = makeSDLCursorFromBMP("working.BMP",12,15); + mSDLCursors[UI_CURSOR_ARROW] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_ARROW); + mSDLCursors[UI_CURSOR_WAIT] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_WAIT); + mSDLCursors[UI_CURSOR_HAND] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_HAND); + mSDLCursors[UI_CURSOR_IBEAM] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_IBEAM); + mSDLCursors[UI_CURSOR_CROSS] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_CROSSHAIR); + mSDLCursors[UI_CURSOR_SIZENWSE] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENWSE); + mSDLCursors[UI_CURSOR_SIZENESW] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENESW); + mSDLCursors[UI_CURSOR_SIZEWE] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEWE); + mSDLCursors[UI_CURSOR_SIZENS] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENS); + mSDLCursors[UI_CURSOR_SIZEALL] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEALL); + mSDLCursors[UI_CURSOR_NO] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_NO); + mSDLCursors[UI_CURSOR_WORKING] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_WAITARROW); mSDLCursors[UI_CURSOR_TOOLGRAB] = makeSDLCursorFromBMP("lltoolgrab.BMP",2,13); mSDLCursors[UI_CURSOR_TOOLLAND] = makeSDLCursorFromBMP("lltoolland.BMP",1,6); mSDLCursors[UI_CURSOR_TOOLFOCUS] = makeSDLCursorFromBMP("lltoolfocus.BMP",8,5); @@ -2160,11 +1724,6 @@ void LLWindowSDL::initCursors() mSDLCursors[UI_CURSOR_TOOLPATHFINDING_PATH_END] = makeSDLCursorFromBMP("lltoolpathfindingpathend.BMP", 16, 16); mSDLCursors[UI_CURSOR_TOOLPATHFINDING_PATH_END_ADD] = makeSDLCursorFromBMP("lltoolpathfindingpathendadd.BMP", 16, 16); mSDLCursors[UI_CURSOR_TOOLNO] = makeSDLCursorFromBMP("llno.BMP",8,8); - - if (getenv("LL_ATI_MOUSE_CURSOR_BUG") != NULL) { - LL_INFOS() << "Disabling cursor updating due to LL_ATI_MOUSE_CURSOR_BUG" << LL_ENDL; - ATIbug = true; - } } void LLWindowSDL::quitCursors() @@ -2214,7 +1773,7 @@ void LLWindowSDL::hideCursor() // LL_INFOS() << "hideCursor: hiding" << LL_ENDL; mCursorHidden = true; mHideCursorPermanent = true; - SDL_ShowCursor(0); + SDL_ShowCursor(SDL_DISABLE); } else { @@ -2229,7 +1788,7 @@ void LLWindowSDL::showCursor() // LL_INFOS() << "showCursor: showing" << LL_ENDL; mCursorHidden = false; mHideCursorPermanent = false; - SDL_ShowCursor(1); + SDL_ShowCursor(SDL_ENABLE); } else { @@ -2320,7 +1879,7 @@ bool LLWindowSDL::dialogColorPicker( F32 *r, F32 *g, F32 *b) Make the raw keyboard data available - used to poke through to LLQtWebKit so that Qt/Webkit has access to the virtual keycodes etc. that it needs */ -LLSD LLWindowSDL::getNativeKeyData() +LLSD LLWindowSDL::getNativeKeyData() const { LLSD result = LLSD::emptyMap(); @@ -2347,62 +1906,6 @@ LLSD LLWindowSDL::getNativeKeyData() return result; } -#if LL_LINUX || LL_SOLARIS -// extracted from spawnWebBrowser for clarity and to eliminate -// compiler confusion regarding close(int fd) vs. LLWindow::close() -void exec_cmd(const std::string& cmd, const std::string& arg) -{ - char* const argv[] = {(char*)cmd.c_str(), (char*)arg.c_str(), NULL}; - fflush(NULL); - pid_t pid = fork(); - if (pid == 0) - { // child - // disconnect from stdin/stdout/stderr, or child will - // keep our output pipe undesirably alive if it outlives us. - // close(0); - // close(1); - // close(2); - // <FS:TS> Reopen stdin, stdout, and stderr to /dev/null. - // It's good practice to always have those file - // descriptors open to something, lest the exec'd - // program actually try to use them. - FILE *result; - result = freopen("/dev/null","r",stdin); - if (result == NULL) - { - LL_WARNS() << "Error reopening stdin for web browser: " - << strerror(errno) << LL_ENDL; - } - result = freopen("/dev/null","w",stdout); - if (result == NULL) - { - LL_WARNS() << "Error reopening stdout for web browser: " - << strerror(errno) << LL_ENDL; - } - result = freopen("/dev/null","w",stderr); - if (result == NULL) - { - LL_WARNS() << "Error reopening stderr for web browser: " - << strerror(errno) << LL_ENDL; - } - // end ourself by running the command - execv(cmd.c_str(), argv); /* Flawfinder: ignore */ - // if execv returns at all, there was a problem. - LL_WARNS() << "execv failure when trying to start " << cmd << LL_ENDL; - _exit(1); // _exit because we don't want atexit() clean-up! - } else { - if (pid > 0) - { - // parent - wait for child to die - int childExitStatus; - waitpid(pid, &childExitStatus, 0); - } else { - LL_WARNS() << "fork failure." << LL_ENDL; - } - } -} -#endif - // Open a URL with the user's default web browser. // Must begin with protocol identifier. void LLWindowSDL::spawnWebBrowser(const std::string& escaped_url, bool async) @@ -2426,35 +1929,14 @@ void LLWindowSDL::spawnWebBrowser(const std::string& escaped_url, bool async) LL_INFOS() << "spawn_web_browser: " << escaped_url << LL_ENDL; -#if LL_LINUX -# if LL_X11 - if (mSDL_Display) + if (SDL_OpenURL(escaped_url.c_str()) != 0) { - maybe_lock_display(); - // Just in case - before forking. - XSync(mSDL_Display, False); - maybe_unlock_display(); + LL_WARNS() << "spawn_web_browser failed with error: " << SDL_GetError() << LL_ENDL; } -# endif // LL_X11 - - std::string cmd, arg; - cmd = gDirUtilp->getAppRODataDir(); - cmd += gDirUtilp->getDirDelimiter(); - cmd += "etc"; - cmd += gDirUtilp->getDirDelimiter(); - cmd += "launch_url.sh"; - arg = escaped_url; - exec_cmd(cmd, arg); -#endif // LL_LINUX LL_INFOS() << "spawn_web_browser returning." << LL_ENDL; } -void LLWindowSDL::openFile(const std::string& file_name) -{ - spawnWebBrowser("file://"+file_name,true); -} - void *LLWindowSDL::getPlatformWindow() { return NULL; @@ -2465,15 +1947,10 @@ void LLWindowSDL::bringToFront() // This is currently used when we are 'launched' to a specific // map position externally. LL_INFOS() << "bringToFront" << LL_ENDL; -#if LL_X11 - if (mSDL_Display && !mFullscreen) + if (mWindow && !mFullscreen) { - maybe_lock_display(); - XRaiseWindow(mSDL_Display, mSDL_XWindowID); - XSync(mSDL_Display, False); - maybe_unlock_display(); + SDL_RaiseWindow(mWindow); } -#endif // LL_X11 } //static @@ -2577,44 +2054,6 @@ std::vector<std::string> LLWindowSDL::getDynamicFallbackFontList() return rtns; } - -void* LLWindowSDL::createSharedContext() -{ - auto *pContext = SDL_GL_CreateContext(mWindow); - if ( pContext) - { - SDL_GL_SetSwapInterval(0); - SDL_GL_MakeCurrent(mWindow, mContext); - - LLCoordScreen size; - if (getSize(&size)) - setSize(size); - - LL_DEBUGS() << "Creating shared OpenGL context successful!" << LL_ENDL; - - return (void*)pContext; - } - - LL_WARNS() << "Creating shared OpenGL context failed!" << LL_ENDL; - - return nullptr; -} - -void LLWindowSDL::makeContextCurrent(void* contextPtr) -{ - LL_PROFILER_GPU_CONTEXT; - SDL_GL_MakeCurrent( mWindow, contextPtr ); -} - -void LLWindowSDL::destroySharedContext(void* contextPtr) -{ - SDL_GL_DeleteContext( contextPtr ); -} - -void LLWindowSDL::toggleVSync(bool enable_vsync) -{ -} - void LLWindowSDL::setLanguageTextInput(const LLCoordGL& position) { LLCoordWindow win_pos; diff --git a/indra/llwindow/llwindowsdl.h b/indra/llwindow/llwindowsdl.h index 10769bb3ba..a85b7c11e7 100644 --- a/indra/llwindow/llwindowsdl.h +++ b/indra/llwindow/llwindowsdl.h @@ -29,6 +29,7 @@ // Simple Directmedia Layer (http://libsdl.org/) implementation of LLWindow class +#if LL_LINUX #include "llwindow.h" #include "lltimer.h" @@ -54,11 +55,11 @@ public: void close() override; - bool getVisible() override; + bool getVisible() const override; - bool getMinimized() override; + bool getMinimized() const override; - bool getMaximized() override; + bool getMaximized() const override; bool maximize() override; @@ -66,13 +67,11 @@ public: void restore() override; - bool getFullscreen(); + bool getPosition(LLCoordScreen *position) const override; - bool getPosition(LLCoordScreen *position) override; + bool getSize(LLCoordScreen *size) const override; - bool getSize(LLCoordScreen *size) override; - - bool getSize(LLCoordWindow *size) override; + bool getSize(LLCoordWindow *size) const override; bool setPosition(LLCoordScreen position) override; @@ -121,19 +120,19 @@ public: void flashIcon(F32 seconds) override; - F32 getGamma() override; + F32 getGamma() const override; bool setGamma(const F32 gamma) override; // Set the gamma - U32 getFSAASamples() override; + + U32 getFSAASamples() const override; void setFSAASamples(const U32 samples) override; bool restoreGamma() override; // Restore original gamma table (before updating gamma) - ESwapMethod getSwapMethod() override { return mSwapMethod; } void processMiscNativeEvents() override; - void gatherInput() override; + void gatherInput(bool app_has_focus) override; void swapBuffers() override; @@ -142,17 +141,17 @@ public: void delayInputProcessing() override {}; // handy coordinate space conversion routines - bool convertCoords(LLCoordScreen from, LLCoordWindow *to) override; + bool convertCoords(LLCoordScreen from, LLCoordWindow *to) const override; - bool convertCoords(LLCoordWindow from, LLCoordScreen *to) override; + bool convertCoords(LLCoordWindow from, LLCoordScreen *to) const override; - bool convertCoords(LLCoordWindow from, LLCoordGL *to) override; + bool convertCoords(LLCoordWindow from, LLCoordGL *to) const override; - bool convertCoords(LLCoordGL from, LLCoordWindow *to) override; + bool convertCoords(LLCoordGL from, LLCoordWindow *to) const override; - bool convertCoords(LLCoordScreen from, LLCoordGL *to) override; + bool convertCoords(LLCoordScreen from, LLCoordGL *to) const override; - bool convertCoords(LLCoordGL from, LLCoordScreen *to) override; + bool convertCoords(LLCoordGL from, LLCoordScreen *to) const override; LLWindowResolution *getSupportedResolutions(S32 &num_resolutions) override; @@ -176,8 +175,6 @@ public: void spawnWebBrowser(const std::string &escaped_url, bool async) override; - void openFile(const std::string &file_name); - void setTitle(const std::string title) override; static std::vector<std::string> getDynamicFallbackFontList(); @@ -211,7 +208,7 @@ public: protected: LLWindowSDL(LLWindowCallbacks *callbacks, - const std::string &title, int x, int y, int width, int height, U32 flags, + const std::string &title, const std::string& name, int x, int y, int width, int height, U32 flags, bool fullscreen, bool clearBg, bool enable_vsync, bool use_gl, bool ignore_pixel_depth, U32 fsaa_samples); @@ -219,7 +216,7 @@ protected: bool isValid() override; - LLSD getNativeKeyData() override; + LLSD getNativeKeyData() const override; void initCursors(); @@ -247,8 +244,6 @@ protected: void setupFailure(const std::string &text, const std::string &caption, U32 type); - void fixWindowSize(void); - U32 SDLCheckGrabbyKeys(U32 keysym, bool gain); bool SDLReallyCaptureInput(bool capture); @@ -280,45 +275,15 @@ protected: friend class LLWindowManager; private: -#if LL_X11 - - void x11_set_urgent(bool urgent); - bool mFlashing; LLTimer mFlashTimer; -#endif //LL_X11 - U32 mKeyVirtualKey; U32 mKeyModifiers; std::string mInputType; -public: -#if LL_X11 - - static Display *getSDLDisplay(); - - LLWString const &getPrimaryText() const { return mPrimaryClipboard; } - - LLWString const &getSecondaryText() const { return mSecondaryClipboard; } - - void clearPrimaryText() { mPrimaryClipboard.clear(); } - - void clearSecondaryText() { mSecondaryClipboard.clear(); } private: void tryFindFullscreenSize(int &aWidth, int &aHeight); - - void initialiseX11Clipboard(); - - bool getSelectionText(Atom selection, LLWString &text); - - bool getSelectionText(Atom selection, Atom type, LLWString &text); - - bool setSelectionText(Atom selection, const LLWString &text); - -#endif - LLWString mPrimaryClipboard; - LLWString mSecondaryClipboard; }; class LLSplashScreenSDL : public LLSplashScreen @@ -334,4 +299,5 @@ public: S32 OSMessageBoxSDL(const std::string& text, const std::string& caption, U32 type); +#endif //LL_LINUX #endif //LL_LLWINDOWSDL_H diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index b19fa13b41..f8294f063f 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -31,6 +31,7 @@ #include "llwindowwin32.h" // LLWindow library includes +#include "llgamecontrol.h" #include "llkeyboardwin32.h" #include "lldragdropwin32.h" #include "llpreeditor.h" @@ -982,17 +983,17 @@ bool LLWindowWin32::isValid() return (mWindowHandle != NULL); } -bool LLWindowWin32::getVisible() +bool LLWindowWin32::getVisible() const { return (mWindowHandle && IsWindowVisible(mWindowHandle)); } -bool LLWindowWin32::getMinimized() +bool LLWindowWin32::getMinimized() const { return (mWindowHandle && IsIconic(mWindowHandle)); } -bool LLWindowWin32::getMaximized() +bool LLWindowWin32::getMaximized() const { return (mWindowHandle && IsZoomed(mWindowHandle)); } @@ -1017,26 +1018,21 @@ bool LLWindowWin32::maximize() return true; } -bool LLWindowWin32::getFullscreen() -{ - return mFullscreen; -} - -bool LLWindowWin32::getPosition(LLCoordScreen *position) +bool LLWindowWin32::getPosition(LLCoordScreen *position) const { position->mX = mRect.left; position->mY = mRect.top; return true; } -bool LLWindowWin32::getSize(LLCoordScreen *size) +bool LLWindowWin32::getSize(LLCoordScreen *size) const { size->mX = mRect.right - mRect.left; size->mY = mRect.bottom - mRect.top; return true; } -bool LLWindowWin32::getSize(LLCoordWindow *size) +bool LLWindowWin32::getSize(LLCoordWindow *size) const { size->mX = mClientRect.right - mClientRect.left; size->mY = mClientRect.bottom - mClientRect.top; @@ -1974,7 +1970,7 @@ bool LLWindowWin32::getCursorPosition(LLCoordWindow *position) return true; } -bool LLWindowWin32::getCursorDelta(LLCoordCommon* delta) +bool LLWindowWin32::getCursorDelta(LLCoordCommon* delta) const { if (delta == nullptr) { @@ -2162,7 +2158,7 @@ void LLWindowWin32::delayInputProcessing() } -void LLWindowWin32::gatherInput() +void LLWindowWin32::gatherInput(bool app_has_focus) { ASSERT_MAIN_THREAD(); LL_PROFILE_ZONE_SCOPED_CATEGORY_WIN32; @@ -2242,6 +2238,8 @@ void LLWindowWin32::gatherInput() mInputProcessingPaused = false; updateCursor(); + + LLGameControl::processEvents(app_has_focus); } static LLTrace::BlockTimerStatHandle FTM_KEYHANDLER("Handle Keyboard"); @@ -3112,7 +3110,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ return ret; } -bool LLWindowWin32::convertCoords(LLCoordGL from, LLCoordWindow *to) +bool LLWindowWin32::convertCoords(LLCoordGL from, LLCoordWindow *to) const { S32 client_height; RECT client_rect; @@ -3132,7 +3130,7 @@ bool LLWindowWin32::convertCoords(LLCoordGL from, LLCoordWindow *to) return true; } -bool LLWindowWin32::convertCoords(LLCoordWindow from, LLCoordGL* to) +bool LLWindowWin32::convertCoords(LLCoordWindow from, LLCoordGL* to) const { S32 client_height; RECT client_rect; @@ -3151,7 +3149,7 @@ bool LLWindowWin32::convertCoords(LLCoordWindow from, LLCoordGL* to) return true; } -bool LLWindowWin32::convertCoords(LLCoordScreen from, LLCoordWindow* to) +bool LLWindowWin32::convertCoords(LLCoordScreen from, LLCoordWindow* to) const { POINT mouse_point; @@ -3168,7 +3166,7 @@ bool LLWindowWin32::convertCoords(LLCoordScreen from, LLCoordWindow* to) return result; } -bool LLWindowWin32::convertCoords(LLCoordWindow from, LLCoordScreen *to) +bool LLWindowWin32::convertCoords(LLCoordWindow from, LLCoordScreen *to) const { POINT mouse_point; @@ -3185,7 +3183,7 @@ bool LLWindowWin32::convertCoords(LLCoordWindow from, LLCoordScreen *to) return result; } -bool LLWindowWin32::convertCoords(LLCoordScreen from, LLCoordGL *to) +bool LLWindowWin32::convertCoords(LLCoordScreen from, LLCoordGL *to) const { LLCoordWindow window_coord; @@ -3199,7 +3197,7 @@ bool LLWindowWin32::convertCoords(LLCoordScreen from, LLCoordGL *to) return true; } -bool LLWindowWin32::convertCoords(LLCoordGL from, LLCoordScreen *to) +bool LLWindowWin32::convertCoords(LLCoordGL from, LLCoordScreen *to) const { LLCoordWindow window_coord; @@ -3318,7 +3316,7 @@ void LLWindowWin32::setMouseClipping( bool b ) } } -bool LLWindowWin32::getClientRectInScreenSpace( RECT* rectp ) +bool LLWindowWin32::getClientRectInScreenSpace( RECT* rectp ) const { bool success = false; @@ -3362,7 +3360,7 @@ void LLWindowWin32::flashIcon(F32 seconds) }); } -F32 LLWindowWin32::getGamma() +F32 LLWindowWin32::getGamma() const { return mCurrentGamma; } @@ -3424,7 +3422,7 @@ void LLWindowWin32::setFSAASamples(const U32 fsaa_samples) mFSAASamples = fsaa_samples; } -U32 LLWindowWin32::getFSAASamples() +U32 LLWindowWin32::getFSAASamples() const { return mFSAASamples; } @@ -3787,7 +3785,7 @@ void LLWindowWin32::openFolder(const std::string &path) Make the raw keyboard data available - used to poke through to LLQtWebKit so that Qt/Webkit has access to the virtual keycodes etc. that it needs */ -LLSD LLWindowWin32::getNativeKeyData() +LLSD LLWindowWin32::getNativeKeyData() const { LLSD result = LLSD::emptyMap(); diff --git a/indra/llwindow/llwindowwin32.h b/indra/llwindow/llwindowwin32.h index e38cfe7ebc..f4964d064e 100644 --- a/indra/llwindow/llwindowwin32.h +++ b/indra/llwindow/llwindowwin32.h @@ -45,84 +45,82 @@ typedef void (*LLW32MsgCallback)(const MSG &msg); class LLWindowWin32 : public LLWindow { public: - /*virtual*/ void show(); - /*virtual*/ void hide(); - /*virtual*/ void close(); - /*virtual*/ bool getVisible(); - /*virtual*/ bool getMinimized(); - /*virtual*/ bool getMaximized(); - /*virtual*/ bool maximize(); - /*virtual*/ void minimize(); - /*virtual*/ void restore(); - /*virtual*/ bool getFullscreen(); - /*virtual*/ bool getPosition(LLCoordScreen *position); - /*virtual*/ bool getSize(LLCoordScreen *size); - /*virtual*/ bool getSize(LLCoordWindow *size); - /*virtual*/ bool setPosition(LLCoordScreen position); - /*virtual*/ bool setSizeImpl(LLCoordScreen size); - /*virtual*/ bool setSizeImpl(LLCoordWindow size); - /*virtual*/ bool switchContext(bool fullscreen, const LLCoordScreen &size, bool enable_vsync, const LLCoordScreen * const posp = NULL); - /*virtual*/ void setTitle(const std::string title); + void show() override; + void hide() override; + void close() override; + bool getVisible() const override; + bool getMinimized() const override; + bool getMaximized() const override; + bool maximize() override; + void minimize() override; + void restore() override; + bool getPosition(LLCoordScreen *position) const override; + bool getSize(LLCoordScreen *size) const override; + bool getSize(LLCoordWindow *size) const override; + bool setPosition(LLCoordScreen position) override; + bool setSizeImpl(LLCoordScreen size) override; + bool setSizeImpl(LLCoordWindow size) override; + bool switchContext(bool fullscreen, const LLCoordScreen &size, bool enable_vsync, const LLCoordScreen * const posp = NULL) override; + void setTitle(const std::string title) override; void* createSharedContext() override; void makeContextCurrent(void* context) override; void destroySharedContext(void* context) override; - /*virtual*/ void toggleVSync(bool enable_vsync); - /*virtual*/ bool setCursorPosition(LLCoordWindow position); - /*virtual*/ bool getCursorPosition(LLCoordWindow *position); - /*virtual*/ bool getCursorDelta(LLCoordCommon* delta); - /*virtual*/ void showCursor(); - /*virtual*/ void hideCursor(); - /*virtual*/ void showCursorFromMouseMove(); - /*virtual*/ void hideCursorUntilMouseMove(); - /*virtual*/ bool isCursorHidden(); - /*virtual*/ void updateCursor(); - /*virtual*/ ECursorType getCursor() const; - /*virtual*/ void captureMouse(); - /*virtual*/ void releaseMouse(); - /*virtual*/ void setMouseClipping( bool b ); - /*virtual*/ bool isClipboardTextAvailable(); - /*virtual*/ bool pasteTextFromClipboard(LLWString &dst); - /*virtual*/ bool copyTextToClipboard(const LLWString &src); - /*virtual*/ void flashIcon(F32 seconds); - /*virtual*/ F32 getGamma(); - /*virtual*/ bool setGamma(const F32 gamma); // Set the gamma - /*virtual*/ void setFSAASamples(const U32 fsaa_samples); - /*virtual*/ U32 getFSAASamples(); - /*virtual*/ bool restoreGamma(); // Restore original gamma table (before updating gamma) - /*virtual*/ ESwapMethod getSwapMethod() { return mSwapMethod; } - /*virtual*/ void gatherInput(); - /*virtual*/ void delayInputProcessing(); - /*virtual*/ void swapBuffers(); - /*virtual*/ void restoreGLContext() {}; + void toggleVSync(bool enable_vsync) override; + bool setCursorPosition(LLCoordWindow position) override; + bool getCursorPosition(LLCoordWindow *position) override; + bool getCursorDelta(LLCoordCommon* delta) const override; + void showCursor() override; + void hideCursor() override; + void showCursorFromMouseMove() override; + void hideCursorUntilMouseMove() override; + bool isCursorHidden() override; + void updateCursor() override; + ECursorType getCursor() const override; + void captureMouse() override; + void releaseMouse() override; + void setMouseClipping( bool b ) override; + bool isClipboardTextAvailable() override; + bool pasteTextFromClipboard(LLWString &dst) override; + bool copyTextToClipboard(const LLWString &src) override; + void flashIcon(F32 seconds) override; + F32 getGamma() const override; + bool setGamma(const F32 gamma) override; // Set the gamma + void setFSAASamples(const U32 fsaa_samples) override; + U32 getFSAASamples() const override; + bool restoreGamma() override; // Restore original gamma table (before updating gamma) + void gatherInput(bool app_has_focus) override; + void delayInputProcessing() override; + void swapBuffers() override; + void restoreGLContext() {}; // handy coordinate space conversion routines - /*virtual*/ bool convertCoords(LLCoordScreen from, LLCoordWindow *to); - /*virtual*/ bool convertCoords(LLCoordWindow from, LLCoordScreen *to); - /*virtual*/ bool convertCoords(LLCoordWindow from, LLCoordGL *to); - /*virtual*/ bool convertCoords(LLCoordGL from, LLCoordWindow *to); - /*virtual*/ bool convertCoords(LLCoordScreen from, LLCoordGL *to); - /*virtual*/ bool convertCoords(LLCoordGL from, LLCoordScreen *to); - - /*virtual*/ LLWindowResolution* getSupportedResolutions(S32 &num_resolutions); - /*virtual*/ F32 getNativeAspectRatio(); - /*virtual*/ F32 getPixelAspectRatio(); - /*virtual*/ void setNativeAspectRatio(F32 ratio) { mOverrideAspectRatio = ratio; } - - /*virtual*/ bool dialogColorPicker(F32 *r, F32 *g, F32 *b ); - - /*virtual*/ void *getPlatformWindow(); - /*virtual*/ void bringToFront(); - /*virtual*/ void focusClient(); - - /*virtual*/ void allowLanguageTextInput(LLPreeditor *preeditor, bool b); - /*virtual*/ void setLanguageTextInput( const LLCoordGL & pos ); - /*virtual*/ void updateLanguageTextInputArea(); - /*virtual*/ void interruptLanguageTextInput(); - /*virtual*/ void spawnWebBrowser(const std::string& escaped_url, bool async); + bool convertCoords(LLCoordScreen from, LLCoordWindow *to) const override; + bool convertCoords(LLCoordWindow from, LLCoordScreen *to) const override; + bool convertCoords(LLCoordWindow from, LLCoordGL *to) const override; + bool convertCoords(LLCoordGL from, LLCoordWindow *to) const override; + bool convertCoords(LLCoordScreen from, LLCoordGL *to) const override; + bool convertCoords(LLCoordGL from, LLCoordScreen *to) const override; + + LLWindowResolution* getSupportedResolutions(S32 &num_resolutions) override; + F32 getNativeAspectRatio() override; + F32 getPixelAspectRatio() override; + void setNativeAspectRatio(F32 ratio) override { mOverrideAspectRatio = ratio; } + + bool dialogColorPicker(F32 *r, F32 *g, F32 *b ) override; + + void *getPlatformWindow() override; + void bringToFront() override; + void focusClient() override; + + void allowLanguageTextInput(LLPreeditor *preeditor, bool b) override; + void setLanguageTextInput( const LLCoordGL & pos ) override; + void updateLanguageTextInputArea() override; + void interruptLanguageTextInput() override; + void spawnWebBrowser(const std::string& escaped_url, bool async) override; void openFolder(const std::string &path) override; - /*virtual*/ F32 getSystemUISize(); + F32 getSystemUISize() override; LLWindowCallbacks::DragNDropResult completeDragNDropRequest( const LLCoordGL gl_coord, const MASK mask, LLWindowCallbacks::DragNDropAction action, const std::string url ); @@ -130,13 +128,13 @@ public: static std::vector<std::string> getDynamicFallbackFontList(); static void setDPIAwareness(); - /*virtual*/ void* getDirectInput8(); - /*virtual*/ bool getInputDevices(U32 device_type_filter, + void* getDirectInput8() override; + bool getInputDevices(U32 device_type_filter, std::function<bool(std::string&, LLSD&, void*)> osx_callback, void* win_callback, - void* userdata); + void* userdata) override; - U32 getRawWParam() { return mRawWParam; } + U32 getRawWParam() const { return mRawWParam; } protected: LLWindowWin32(LLWindowCallbacks* callbacks, @@ -149,7 +147,7 @@ protected: HCURSOR loadColorCursor(LPCTSTR name); bool isValid(); void moveWindow(const LLCoordScreen& position,const LLCoordScreen& size); - virtual LLSD getNativeKeyData(); + LLSD getNativeKeyData() const override; // Changes display resolution. Returns true if successful bool setDisplayResolution(S32 width, S32 height, S32 bits, S32 refresh); @@ -175,7 +173,7 @@ protected: // Platform specific methods // - bool getClientRectInScreenSpace(RECT* rectp); + bool getClientRectInScreenSpace(RECT* rectp) const; static LRESULT CALLBACK mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_param, LPARAM l_param); @@ -266,9 +264,9 @@ public: LLSplashScreenWin32(); virtual ~LLSplashScreenWin32(); - /*virtual*/ void showImpl(); - /*virtual*/ void updateImpl(const std::string& mesg); - /*virtual*/ void hideImpl(); + void showImpl() override; + void updateImpl(const std::string& mesg) override; + void hideImpl() override; #if LL_WINDOWS static LRESULT CALLBACK windowProc(HWND h_wnd, UINT u_msg, diff --git a/indra/media_plugins/base/media_plugin_base.cpp b/indra/media_plugins/base/media_plugin_base.cpp index 9bb3bad035..f31708c4d7 100644 --- a/indra/media_plugins/base/media_plugin_base.cpp +++ b/indra/media_plugins/base/media_plugin_base.cpp @@ -169,6 +169,8 @@ void MediaPluginBase::sendStatus() #if LL_LINUX +#include <dlfcn.h> + size_t SymbolGrabber::registerSymbol( SymbolToGrab aSymbol ) { gSymbolsToGrab.emplace_back(aSymbol); @@ -177,25 +179,22 @@ size_t SymbolGrabber::registerSymbol( SymbolToGrab aSymbol ) bool SymbolGrabber::grabSymbols(std::vector< std::string > const &aDSONames) { - std::cerr << "SYMBOLS: " << gSymbolsToGrab.size() << std::endl; - if (sSymsGrabbed) return true; - //attempt to load the shared libraries - apr_pool_create(&sSymDSOMemoryPool, nullptr); - for( std::vector< std::string >::const_iterator itr = aDSONames.begin(); itr != aDSONames.end(); ++itr ) { - apr_dso_handle_t *pDSO(NULL); - std::string strDSO{ *itr }; - if( APR_SUCCESS == apr_dso_load( &pDSO, strDSO.c_str(), sSymDSOMemoryPool )) - sLoadedLibraries.push_back( pDSO ); + auto pDSO = dlopen( itr->c_str(), RTLD_NOW ); - for( auto i = 0; i < gSymbolsToGrab.size(); ++i ) + if( pDSO ) { - if( !*gSymbolsToGrab[i].mPPFunc ) - apr_dso_sym( gSymbolsToGrab[i].mPPFunc, pDSO, gSymbolsToGrab[i].mName ); + sLoadedLibraries.push_back(pDSO); + + for (auto i = 0; i < gSymbolsToGrab.size(); ++i) + { + if (!*gSymbolsToGrab[i].mPPFunc) + *gSymbolsToGrab[i].mPPFunc = dlsym(pDSO, gSymbolsToGrab[i].mName); + } } } diff --git a/indra/media_plugins/base/media_plugin_base.h b/indra/media_plugins/base/media_plugin_base.h index a084fc9834..98e9ce0316 100644 --- a/indra/media_plugins/base/media_plugin_base.h +++ b/indra/media_plugins/base/media_plugin_base.h @@ -38,7 +38,7 @@ struct SymbolToGrab { bool mRequired; char const *mName; - apr_dso_handle_sym_t *mPPFunc; + void **mPPFunc; }; class SymbolGrabber @@ -52,8 +52,7 @@ private: std::vector< SymbolToGrab > gSymbolsToGrab; bool sSymsGrabbed = false; - apr_pool_t *sSymDSOMemoryPool = nullptr; - std::vector<apr_dso_handle_t *> sLoadedLibraries; + std::vector<void *> sLoadedLibraries; }; extern SymbolGrabber gSymbolGrabber; @@ -63,7 +62,7 @@ extern SymbolGrabber gSymbolGrabber; #define LL_GRAB_SYM(SYMBOL_GRABBER, REQUIRED, SYMBOL_NAME, RETURN, ...) \ RETURN (*ll##SYMBOL_NAME)(__VA_ARGS__) = nullptr; \ size_t gRegistered##SYMBOL_NAME = SYMBOL_GRABBER.registerSymbol( \ - { REQUIRED, #SYMBOL_NAME , (apr_dso_handle_sym_t*)&ll##SYMBOL_NAME} \ + { REQUIRED, #SYMBOL_NAME , (void**)&ll##SYMBOL_NAME} \ ); #endif diff --git a/indra/media_plugins/cef/volume_catcher.h b/indra/media_plugins/cef/volume_catcher.h index 6933854e8e..ead0511149 100644 --- a/indra/media_plugins/cef/volume_catcher.h +++ b/indra/media_plugins/cef/volume_catcher.h @@ -49,7 +49,9 @@ public: #endif private: +#if LL_LINUX || LL_WINDOWS VolumeCatcherImpl *pimpl; +#endif }; #endif // VOLUME_CATCHER_H diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 29dbceedac..6c8d7b910e 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -28,6 +28,7 @@ include(LLKDU) include(LLPhysicsExtensions) include(LLPrimitive) include(LLWindow) +include(SDL2) include(NDOF) include(NVAPI) include(OPENAL) @@ -316,6 +317,7 @@ set(viewer_SOURCE_FILES llfollowcam.cpp llfriendcard.cpp llflyoutcombobtn.cpp + llflycam.cpp llgesturelistener.cpp llgesturemgr.cpp llgiveinventory.cpp @@ -990,6 +992,7 @@ set(viewer_HEADER_FILES llfollowcam.h llfriendcard.h llflyoutcombobtn.h + llflycam.h llgesturelistener.h llgesturemgr.h llgiveinventory.h @@ -1652,6 +1655,7 @@ set(viewer_APPSETTINGS_FILES app_settings/toolbars.xml app_settings/trees.xml app_settings/viewerart.xml + app_settings/gamecontrollerdb.txt ${CMAKE_SOURCE_DIR}/../etc/message.xml ${CMAKE_SOURCE_DIR}/../scripts/messages/message_template.msg packages-info.txt @@ -1745,7 +1749,7 @@ if (WINDOWS) # And of course it's straightforward to read a text file in Python. set(COPY_INPUT_DEPENDENCIES - # The following commented dependencies are determined at variably at build time. Can't do this here. + # The following commented dependencies are determined variably at build time. Can't do this here. ${CMAKE_SOURCE_DIR}/../etc/message.xml ${CMAKE_SOURCE_DIR}/../scripts/messages/message_template.msg ${SHARED_LIB_STAGING_DIR}/openjp2.dll @@ -1870,7 +1874,7 @@ else (WINDOWS) # Linux set_target_properties(${VIEWER_BINARY_NAME} PROPERTIES - LINK_FLAGS_RELEASE "${LINK_FLAGS_RELEASE} -Wl,--Map=${VIEWER_BINARY_NAME}.MAP" + LINK_FLAGS_RELEASE "${LINK_FLAGS_RELEASE} -no-pie -Wl,--Map=${VIEWER_BINARY_NAME}.MAP" ) endif (WINDOWS) @@ -2245,6 +2249,7 @@ if (LL_TESTS) lllogin llplugin llappearance + ll::SDL2 ) set_source_files_properties( @@ -2296,6 +2301,7 @@ if (LL_TESTS) lllogin llprimitive lllogin + ll::SDL2 ) LL_ADD_INTEGRATION_TEST(cppfeatures diff --git a/indra/newview/app_settings/gamecontrollerdb.txt b/indra/newview/app_settings/gamecontrollerdb.txt new file mode 100644 index 0000000000..edf904a65a --- /dev/null +++ b/indra/newview/app_settings/gamecontrollerdb.txt @@ -0,0 +1,2043 @@ +# Game Controller DB for SDL in 2.0.16 format +# Source: https://github.com/gabomdq/SDL_GameControllerDB + +# Windows +03000000300f00000a01000000000000,3 In 1 Conversion Box,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b8,x:b3,y:b0,platform:Windows, +03000000fa2d00000100000000000000,3dRudder Foot Motion Controller,leftx:a0,lefty:a1,rightx:a5,righty:a2,platform:Windows, +03000000d0160000040d000000000000,4Play Adapter,a:b1,b:b3,back:b4,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b6,leftstick:b14,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b15,righttrigger:b9,rightx:a3,righty:a4,start:b5,x:b0,y:b2,platform:Windows, +03000000d0160000050d000000000000,4Play Adapter,a:b1,b:b3,back:b4,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b6,leftstick:b14,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b15,righttrigger:b9,rightx:a3,righty:a4,start:b5,x:b0,y:b2,platform:Windows, +03000000d0160000060d000000000000,4Play Adapter,a:b1,b:b3,back:b4,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b6,leftstick:b14,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b15,righttrigger:b9,rightx:a3,righty:a4,start:b5,x:b0,y:b2,platform:Windows, +03000000d0160000070d000000000000,4Play Adapter,a:b1,b:b3,back:b4,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b6,leftstick:b14,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b15,righttrigger:b9,rightx:a3,righty:a4,start:b5,x:b0,y:b2,platform:Windows, +03000000d0160000600a000000000000,4Play Adapter,a:b1,b:b3,back:b4,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b6,leftstick:b14,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b15,righttrigger:b9,rightx:a3,righty:a4,start:b5,x:b0,y:b2,platform:Windows, +03000000c82d00000031000000000000,8BitDo Adapter,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, +03000000c82d00000531000000000000,8BitDo Adapter 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, +03000000c82d00000951000000000000,8BitDo Dogbone,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a2,rightx:a3,righty:a5,start:b11,platform:Windows, +03000000008000000210000000000000,8BitDo F30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows, +030000003512000011ab000000000000,8BitDo F30 Arcade Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000c82d00001028000000000000,8BitDo F30 Arcade Joystick,a:b0,b:b1,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Windows, +03000000c82d000011ab000000000000,8BitDo F30 Arcade Joystick,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows, +03000000801000000900000000000000,8BitDo F30 Arcade Stick,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows, +03000000c82d00001038000000000000,8BitDo F30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d00000090000000000000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d00001251000000000000,8BitDo Lite 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d00001151000000000000,8BitDo Lite SE,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d00000150000000000000,8BitDo M30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a3,righty:a5,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d00000151000000000000,8BitDo M30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a2,rightshoulder:b6,righttrigger:b7,rightx:a3,righty:a5,start:b11,x:b3,y:b4,platform:Windows, +03000000c82d00000650000000000000,8BitDo M30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b8,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, +03000000c82d00005106000000000000,8BitDo M30,a:b0,b:b1,back:b10,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,guide:b2,leftshoulder:b8,lefttrigger:b9,rightshoulder:b6,righttrigger:b7,start:b11,x:b3,y:b4,platform:Windows, +03000000c82d00002090000000000000,8BitDo Micro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d00000310000000000000,8BitDo N30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Windows, +03000000c82d00000451000000000000,8BitDo N30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a2,rightx:a3,righty:a5,start:b11,platform:Windows, +03000000c82d00002028000000000000,8BitDo N30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d00008010000000000000,8BitDo N30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Windows, +03000000c82d0000e002000000000000,8BitDo N30,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,start:b6,platform:Windows, +03000000c82d00000190000000000000,8BitDo N30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d00001590000000000000,8BitDo N30 Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d00006528000000000000,8BitDo N30 Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d00000290000000000000,8BitDo N64,+rightx:b9,+righty:b3,-rightx:b4,-righty:b8,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,platform:Windows, +03000000c82d00003038000000000000,8BitDo N64,+rightx:b9,+righty:b3,-rightx:b4,-righty:b8,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,platform:Windows, +03000000c82d00006928000000000000,8BitDo N64,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a3,righty:a4,start:b11,platform:Windows, +03000000c82d00002590000000000000,8BitDo NEOGEO,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, +030000003512000012ab000000000000,8BitDo NES30,a:b2,b:b1,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b0,platform:Windows, +03000000c82d000012ab000000000000,8BitDo NES30,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows, +03000000022000000090000000000000,8BitDo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows, +03000000203800000900000000000000,8BitDo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d00002038000000000000,8BitDo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d00000751000000000000,8BitDo P30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a2,rightshoulder:b7,righttrigger:b9,rightx:a3,righty:a5,start:b11,x:b3,y:b4,platform:Windows, +03000000c82d00000851000000000000,8BitDo P30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a2,rightshoulder:b7,righttrigger:b9,rightx:a3,righty:a5,start:b11,x:b3,y:b4,platform:Windows, +03000000c82d00000360000000000000,8BitDo Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d00000361000000000000,8BitDo Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d00000660000000000000,8BitDo Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d00000131000000000000,8BitDo Receiver,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d00000231000000000000,8BitDo Receiver,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d00000331000000000000,8BitDo Receiver,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d00000431000000000000,8BitDo Receiver,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d00002867000000000000,8BitDo S30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,lefttrigger:b9,leftx:a0,lefty:a2,rightshoulder:b6,righttrigger:b7,rightx:a3,righty:a5,start:b10,x:b3,y:b4,platform:Windows, +03000000c82d00000130000000000000,8BitDo SF30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d00000060000000000000,8BitDo SF30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d00000061000000000000,8BitDo SF30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows, +03000000102800000900000000000000,8BitDo SFC30,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d000021ab000000000000,8BitDo SFC30,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d00003028000000000000,8BitDo SFC30,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows, +030000003512000020ab000000000000,8BitDo SN30,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d00000030000000000000,8BitDo SN30,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d00000351000000000000,8BitDo SN30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a2,rightshoulder:b7,rightx:a3,righty:a5,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d00001290000000000000,8BitDo SN30,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d000020ab000000000000,8BitDo SN30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d00004028000000000000,8BitDo SN30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d00006228000000000000,8BitDo SN30,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d00000021000000000000,8BitDo SN30 Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows, +03000000c82d00000160000000000000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d00000161000000000000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d00000260000000000000,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d00000261000000000000,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d00001230000000000000,8BitDo Ultimate,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,paddle1:b2,paddle2:b5,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, +03000000c82d00001530000000000000,8BitDo Ultimate C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, +03000000c82d00001630000000000000,8BitDo Ultimate C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, +03000000c82d00001730000000000000,8BitDo Ultimate C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, +03000000c82d00001130000000000000,8BitDo Ultimate Wired,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,misc1:b26,paddle1:b24,paddle2:b25,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, +03000000c82d00001330000000000000,8BitDo Ultimate Wireless,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b26,paddle1:b23,paddle2:b19,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Windows, +03000000c82d00000121000000000000,8BitDo Xbox One SN30 Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, +03000000a00500003232000000000000,8BitDo Zero,a:b0,b:b1,back:b10,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Windows, +03000000c82d00001890000000000000,8BitDo Zero 2,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d00003032000000000000,8BitDo Zero 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows, +030000008f0e00001200000000000000,Acme GA02,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Windows, +03000000c01100000355000000000000,Acrux,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000fa190000f0ff000000000000,Acteck AGJ 3200,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, +03000000d1180000402c000000000000,ADT1,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a3,rightx:a2,righty:a5,x:b3,y:b4,platform:Windows, +030000006f0e00008801000000000000,Afterglow Deluxe Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000341a00003608000000000000,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000006f0e00000263000000000000,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000006f0e00001101000000000000,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000006f0e00001401000000000000,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000006f0e00001402000000000000,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000006f0e00001901000000000000,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000006f0e00001a01000000000000,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000006f0e00001301000000000000,Afterglow Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000006f0e00001302000000000000,Afterglow Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000006f0e00001304000000000000,Afterglow Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000006f0e00001413000000000000,Afterglow Xbox Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000006f0e00003901000000000000,Afterglow Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000ab1200000103000000000000,Afterglow Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000ad1b000000f9000000000000,Afterglow Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000100000008200000000000000,Akishop Customs PS360,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, +030000007c1800000006000000000000,Alienware Dual Compatible PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b3,platform:Windows, +03000000491900001904000000000000,Amazon Luna Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b9,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b7,x:b2,y:b3,platform:Windows, +03000000710100001904000000000000,Amazon Luna Controller,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b5,leftstick:b8,leftx:a0,lefty:a1,misc1:b9,rightshoulder:b4,rightstick:b7,rightx:a3,righty:a4,start:b6,x:b3,y:b2,platform:Windows, +0300000008100000e501000000000000,Anbernic Game Pad,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a4,start:b11,x:b3,y:b4,platform:Windows, +03000000830500000160000000000000,Arcade,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b3,x:b4,y:b4,platform:Windows, +03000000120c0000100e000000000000,Armor 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000490b00004406000000000000,ASCII Seamic Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b9,x:b3,y:b4,platform:Windows, +03000000869800002500000000000000,Astro C40 TR PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000a30c00002700000000000000,Astro City Mini,a:b2,b:b1,back:b8,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Windows, +03000000a30c00002800000000000000,Astro City Mini,a:b2,b:b1,back:b8,leftx:a3,lefty:a4,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Windows, +03000000050b00000579000000000000,ASUS ROG Kunai 3,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, +03000000050b00000679000000000000,ASUS ROG Kunai 3,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, +03000000503200000110000000000000,Atari VCS Classic Controller,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,start:b3,platform:Windows, +03000000503200000210000000000000,Atari VCS Modern Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,rightx:a3,righty:a4,start:b9,x:b2,y:b3,platform:Windows, +030000008a3500000102000000000000,Backbone One,a:b4,b:b5,back:b14,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b16,leftshoulder:b10,leftstick:b17,lefttrigger:b12,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b18,righttrigger:b13,rightx:a3,righty:a4,start:b15,x:b7,y:b8,platform:Windows, +030000008a3500000201000000000000,Backbone One,a:b4,b:b5,back:b14,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b16,leftshoulder:b10,leftstick:b17,lefttrigger:b12,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b18,righttrigger:b13,rightx:a3,righty:a4,start:b15,x:b7,y:b8,platform:Windows, +030000008a3500000302000000000000,Backbone One,a:b4,b:b5,back:b14,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b16,leftshoulder:b10,leftstick:b17,lefttrigger:b12,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b18,righttrigger:b13,rightx:a3,righty:a4,start:b15,x:b7,y:b8,platform:Windows, +030000008a3500000402000000000000,Backbone One,a:b4,b:b5,back:b14,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b16,leftshoulder:b10,leftstick:b17,lefttrigger:b12,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b18,righttrigger:b13,rightx:a3,righty:a4,start:b15,x:b7,y:b8,platform:Windows, +03000000e4150000103f000000000000,Batarang,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000d6200000e557000000000000,Batarang PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000c01100001352000000000000,Battalife Joystick,a:b6,b:b7,back:b2,leftshoulder:b0,leftx:a0,lefty:a1,rightshoulder:b1,start:b3,x:b4,y:b5,platform:Windows, +030000006f0e00003201000000000000,Battlefield 4 PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000ad1b000001f9000000000000,BB 070,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000d62000002a79000000000000,BDA PS4 Fightpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000bc2000005250000000000000,Beitong G3,a:b0,b:b1,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b5,righttrigger:b9,rightx:a3,righty:a4,start:b15,x:b3,y:b4,platform:Windows, +030000000d0500000208000000000000,Belkin Nostromo N40,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a5,righty:a2,start:b9,x:b2,y:b3,platform:Windows, +03000000bc2000006012000000000000,Betop 2126F,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, +03000000bc2000000055000000000000,Betop BFM,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, +03000000bc2000006312000000000000,Betop Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, +03000000bc2000006321000000000000,Betop Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, +03000000bc2000006412000000000000,Betop Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, +03000000c01100000555000000000000,Betop Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, +03000000c01100000655000000000000,Betop Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, +03000000790000000700000000000000,Betop Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b3,y:b0,platform:Windows, +03000000808300000300000000000000,Betop Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b3,y:b0,platform:Windows, +030000006f0e00006401000000000000,BF One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a2,righty:a5,start:b7,x:b2,y:b3,platform:Windows, +03000000300f00000202000000000000,Bigben,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a5,righty:a2,start:b7,x:b2,y:b3,platform:Windows, +030000006b1400000209000000000000,Bigben,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000006b1400000055000000000000,Bigben PS3 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, +030000006b1400000103000000000000,Bigben PS3 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Windows, +03000000120c0000200e000000000000,Brook Mars PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000120c0000210e000000000000,Brook Mars PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000120c0000f10e000000000000,Brook PS2 Adapter,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000120c0000310c000000000000,Brook Super Converter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Windows, +03000000d81d00000b00000000000000,Buffalo BSGP1601 Series,a:b5,b:b3,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b9,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b13,x:b4,y:b2,platform:Windows, +030000005b1c00002400000000000000,Capcom Home Arcade Controller,a:b3,b:b4,back:b7,leftshoulder:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b6,x:b0,y:b1,platform:Windows, +030000005b1c00002500000000000000,Capcom Home Arcade Controller,a:b3,b:b4,back:b7,leftshoulder:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b6,x:b0,y:b1,platform:Windows, +030000006d04000042c2000000000000,ChillStream,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000e82000006058000000000000,Cideko AK08b,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, +03000000457500000401000000000000,Cobra,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +030000000b0400003365000000000000,Competition Pro,a:b0,b:b1,back:b2,leftx:a0,lefty:a1,start:b3,platform:Windows, +030000004c050000c505000000000000,CronusMax Adapter,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000d814000007cd000000000000,Cthulhu,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000d8140000cefa000000000000,Cthulhu,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000260900008888000000000000,Cyber Gadget GameCube Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:a4,rightx:a2,righty:a3~,start:b7,x:b2,y:b3,platform:Windows, +030000003807000002cb000000000000,Cyborg,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000a306000022f6000000000000,Cyborg V.3 Rumble,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:+a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:-a3,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Windows, +03000000f806000000a3000000000000,DA Leader,a:b7,b:b6,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b0,leftstick:b8,lefttrigger:b1,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:b3,rightx:a2,righty:a3,start:b12,x:b4,y:b5,platform:Windows, +030000001a1c00000001000000000000,Datel Arcade Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000451300000830000000000000,Defender Game Racer X7,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, +03000000791d00000103000000000000,Dual Box Wii,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, +03000000c0160000e105000000000000,Dual Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows, +030000004f040000070f000000000000,Dual Power,a:b8,b:b9,back:b4,dpdown:b1,dpleft:b2,dpright:b3,dpup:b0,leftshoulder:b13,leftstick:b6,lefttrigger:b14,leftx:a0,lefty:a1,rightshoulder:b12,rightstick:b7,righttrigger:b15,start:b5,x:b10,y:b11,platform:Windows, +030000004f04000012b3000000000000,Dual Power 3,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Windows, +030000004f04000020b3000000000000,Dual Trigger,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Windows, +03000000bd12000002e0000000000000,Dual Vibration Joystick,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a3,righty:a2,start:b11,x:b3,y:b0,platform:Windows, +03000000ff1100003133000000000000,DualForce,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b0,y:b1,platform:Windows, +030000008f0e00000910000000000000,DualShock 2,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a3,righty:a2,start:b11,x:b3,y:b0,platform:Windows, +03000000317300000100000000000000,DualShock 3,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows, +030000006f0e00003001000000000000,EA Sports PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000fc0400000250000000000000,Easy Grip,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b9,x:b3,y:b4,platform:Windows, +03000000bc2000000091000000000000,EasySMX Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, +030000006e0500000a20000000000000,Elecom DUX60 MMO,a:b2,b:b3,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,leftstick:b14,lefttrigger:b12,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b15,righttrigger:b13,rightx:a3,righty:a4,start:b20,x:b0,y:b1,platform:Windows, +03000000b80500000410000000000000,Elecom Gamepad,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b1,platform:Windows, +03000000b80500000610000000000000,Elecom Gamepad,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b1,platform:Windows, +030000006e0500000520000000000000,Elecom P301U PlayStation Controller Adapter,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b0,y:b1,platform:Windows, +03000000411200004450000000000000,Elecom U1012,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b0,y:b1,platform:Windows, +030000006e0500000320000000000000,Elecom U3613M,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b0,y:b1,platform:Windows, +030000006e0500000e20000000000000,Elecom U3912T,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b0,y:b1,platform:Windows, +030000006e0500000f20000000000000,Elecom U4013S,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b0,y:b1,platform:Windows, +030000006e0500001320000000000000,Elecom U4113,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000006e0500001020000000000000,Elecom U4113S,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,start:b11,x:b0,y:b1,platform:Windows, +030000006e0500000720000000000000,Elecom W01U,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b1,platform:Windows, +030000007d0400000640000000000000,Eliminator AfterShock,a:b1,b:b2,back:b9,dpdown:+a3,dpleft:-a5,dpright:+a5,dpup:-a3,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a4,righty:a2,start:b8,x:b0,y:b3,platform:Windows, +03000000120c0000f61c000000000000,Elite,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000430b00000300000000000000,EMS Production PS2 Adapter,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows, +03000000242f000000b7000000000000,ESM 9110,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Windows, +03000000101c0000181c000000000000,Essential,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b4,leftx:a1,lefty:a0,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows, +030000008f0e00000f31000000000000,EXEQ,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Windows, +03000000341a00000108000000000000,EXEQ RF Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, +030000006f0e00008401000000000000,Faceoff Deluxe Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000006f0e00008101000000000000,Faceoff Deluxe Pro Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000006f0e00008001000000000000,Faceoff Pro Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000021000000090000000000000,FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,leftstick:b13,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b9,rightstick:b14,righttrigger:b7,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows, +0300000011040000c600000000000000,FC801,a:b0,b:b1,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Windows, +03000000852100000201000000000000,FF GP1,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000ad1b000028f0000000000000,Fightpad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000ad1b00002ef0000000000000,Fightpad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000ad1b000038f0000000000000,Fightpad TE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b8,rightshoulder:b5,righttrigger:b9,start:b7,x:b2,y:b3,platform:Windows, +03005036852100000000000000000000,Final Fantasy XIV Online Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000f806000001a3000000000000,Firestorm,a:b9,b:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b0,leftstick:b10,lefttrigger:b1,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b11,righttrigger:b3,start:b12,x:b8,y:b4,platform:Windows, +03000000b50700000399000000000000,Firestorm 2,a:b2,b:b4,back:b10,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b8,righttrigger:b9,start:b11,x:b3,y:b5,platform:Windows, +03000000b50700001302000000000000,Firestorm D3,a:b0,b:b2,leftshoulder:b4,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,x:b1,y:b3,platform:Windows, +03000000b40400001024000000000000,Flydigi Apex,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows, +03000000151900004000000000000000,Flydigi Vader 2,a:b27,b:b26,back:b19,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b23,leftstick:b17,lefttrigger:b21,leftx:a0,lefty:a1,misc1:b15,paddle1:b11,paddle2:b10,paddle3:b13,paddle4:b12,rightshoulder:b22,rightstick:b16,righttrigger:b20,rightx:a3,righty:a4,start:b18,x:b25,y:b24,platform:Windows, +03000000b40400001124000000000000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b12,lefttrigger:b8,leftx:a0,lefty:a1,misc1:b14,paddle1:b4,paddle2:b5,paddle3:b16,paddle4:b17,rightshoulder:b7,rightstick:b13,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b2,y:b3,platform:Windows, +03000000b40400001224000000000000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b12,lefttrigger:b8,leftx:a0,lefty:a1,misc1:b2,paddle1:b16,paddle2:b17,paddle3:b14,paddle4:b15,rightshoulder:b7,rightstick:b13,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, +030000008305000000a0000000000000,G08XU,a:b0,b:b1,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b5,x:b2,y:b3,platform:Windows, +0300000066f700000100000000000000,Game VIB Joystick,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,start:b11,x:b0,y:b1,platform:Windows, +03000000260900002625000000000000,GameCube Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,lefttrigger:a4,leftx:a0,lefty:a1,righttrigger:a5,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Windows, +03000000341a000005f7000000000000,GameCube Controller,a:b2,b:b3,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b1,y:b0,platform:Windows, +03000000430b00000500000000000000,GameCube Controller,a:b0,b:b2,dpdown:b10,dpleft:b8,dpright:b9,dpup:b11,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:a3,rightx:a5,righty:a2,start:b7,x:b1,y:b3,platform:Windows, +03000000790000004718000000000000,GameCube Controller,a:b1,b:b0,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b2,y:b3,platform:Windows, +03000000790000004618000000000000,GameCube Controller Adapter,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b2,y:b3,platform:Windows, +030000008f0e00000d31000000000000,Gamepad 3 Turbo,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000ac0500003d03000000000000,GameSir G3,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, +03000000ac0500005b05000000000000,GameSir G3w,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, +03000000ac0500002d02000000000000,GameSir G4,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows, +03000000ac0500004d04000000000000,GameSir G4,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, +03000000ac0500001a06000000000000,GameSir-T3 2.02,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, +030000004c0e00001035000000000000,Gamester,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows, +030000000d0f00001110000000000000,GameStick Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows, +0300000047530000616d000000000000,GameStop,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, +03000000c01100000140000000000000,GameStop PS4 Fun Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000b62500000100000000000000,Gametel GT004 01,a:b3,b:b0,dpdown:b10,dpleft:b9,dpright:b8,dpup:b11,leftshoulder:b4,rightshoulder:b5,start:b7,x:b1,y:b2,platform:Windows, +030000008f0e00001411000000000000,Gamo2 Divaller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000120c0000a857000000000000,Gator Claw,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000c9110000f055000000000000,GC100XF,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, +030000008305000009a0000000000000,Genius,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, +030000008305000031b0000000000000,Genius Maxfire Blaze 3,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, +03000000451300000010000000000000,Genius Maxfire Grandias 12,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, +030000005c1a00003330000000000000,Genius MaxFire Grandias 12V,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Windows, +03000000300f00000b01000000000000,GGE909 Recoil,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows, +03000000f0250000c283000000000000,Gioteck PlayStation Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, +03000000f025000021c1000000000000,Gioteck PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, +03000000f025000031c1000000000000,Gioteck PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, +03000000f0250000c383000000000000,Gioteck VX2 PlayStation Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, +03000000f0250000c483000000000000,Gioteck VX2 PlayStation Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, +030000004f04000026b3000000000000,GP XID,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +0300000079000000d418000000000000,GPD Win,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000c6240000025b000000000000,GPX,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000007d0400000840000000000000,Gravis Destroyer Tilt,+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b1,b:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,x:b0,y:b3,platform:Windows, +030000007d0400000540000000000000,Gravis Eliminator Pro,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, +03000000280400000140000000000000,Gravis GamePad Pro,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a3,dpup:-a4,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, +030000008f0e00000610000000000000,GreenAsia,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a5,righty:a2,start:b11,x:b3,y:b0,platform:Windows, +03000000ac0500006b05000000000000,GT2a,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows, +03000000341a00000302000000000000,Hama Scorpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00004900000000000000,Hatsune Miku Sho PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000001008000001e1000000000000,Havit HV G60,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b3,y:b0,platform:Windows, +030000000d0f00000c00000000000000,HEXT,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000d81400000862000000000000,HitBox Edition Cthulhu,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,lefttrigger:b4,rightshoulder:b7,righttrigger:b6,start:b9,x:b0,y:b3,platform:Windows, +03000000632500002605000000000000,HJD X,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, +030000000d0f00000a00000000000000,Hori DOA,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000000d0f00008500000000000000,Hori Fighting Commander 2016 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00002500000000000000,Hori Fighting Commander 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00002d00000000000000,Hori Fighting Commander 3 Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00005f00000000000000,Hori Fighting Commander 4 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00005e00000000000000,Hori Fighting Commander 4 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00008400000000000000,Hori Fighting Commander 5,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00006201000000000000,Hori Fighting Commander Octa,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00006401000000000000,Hori Fighting Commander Octa,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:-a2,start:b7,x:b2,y:b3,platform:Windows, +030000000d0f00005100000000000000,Hori Fighting Commander PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00008600000000000000,Hori Fighting Commander Xbox 360,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000000d0f0000ba00000000000000,Hori Fighting Commander Xbox 360,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000000d0f00008800000000000000,Hori Fighting Stick mini 4 (PS3),a:b1,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b8,x:b0,y:b3,platform:Windows, +030000000d0f00008700000000000000,Hori Fighting Stick mini 4 (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00001000000000000000,Hori Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00003200000000000000,Hori Fightstick 3W,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f0000c000000000000000,Hori Fightstick 4,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000000d0f00000d00000000000000,Hori Fightstick EX2,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows, +030000000d0f00003701000000000000,Hori Fightstick Mini,a:b1,b:b0,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b3,y:b2,platform:Windows, +030000000d0f00004000000000000000,Hori Fightstick Mini 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,lefttrigger:b4,rightshoulder:b7,righttrigger:b6,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00002100000000000000,Hori Fightstick V3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00002700000000000000,Hori Fightstick V3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f0000a000000000000000,Hori Grip TAC4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b13,x:b0,y:b3,platform:Windows, +030000000d0f0000a500000000000000,Hori Miku Project Diva X HD PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f0000a600000000000000,Hori Miku Project Diva X HD PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00000101000000000000,Hori Mini Hatsune Miku FT,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00005400000000000000,Hori Pad 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00000900000000000000,Hori Pad 3 Turbo,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00004d00000000000000,Hori Pad A,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00003801000000000000,Hori PC Engine Mini Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b9,platform:Windows, +030000000d0f00009200000000000000,Hori Pokken Tournament DX Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00002301000000000000,Hori PS4 Controller Light,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows, +030000000d0f00001100000000000000,Hori Real Arcade Pro 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00002600000000000000,Hori Real Arcade Pro 3P,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00004b00000000000000,Hori Real Arcade Pro 3W,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00006a00000000000000,Hori Real Arcade Pro 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00006b00000000000000,Hori Real Arcade Pro 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00008a00000000000000,Hori Real Arcade Pro 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00008b00000000000000,Hori Real Arcade Pro 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00006f00000000000000,Hori Real Arcade Pro 4 VLX,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00007000000000000000,Hori Real Arcade Pro 4 VLX,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00003d00000000000000,Hori Real Arcade Pro N3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b10,leftstick:b4,lefttrigger:b11,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b6,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f0000ae00000000000000,Hori Real Arcade Pro N4,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000000d0f00008c00000000000000,Hori Real Arcade Pro P4,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000000d0f0000aa00000000000000,Hori Real Arcade Pro S,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f0000d800000000000000,Hori Real Arcade Pro S,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Windows, +030000000d0f00002200000000000000,Hori Real Arcade Pro V3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00005b00000000000000,Hori Real Arcade Pro V4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00005c00000000000000,Hori Real Arcade Pro V4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f0000af00000000000000,Hori Real Arcade Pro VHS,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00001b00000000000000,Hori Real Arcade Pro VX,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000ad1b000002f5000000000000,Hori Real Arcade Pro VX,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b11,rightx:a2,righty:a5,start:b6,x:b2,y:b3,platform:Windows, +030000000d0f00009c00000000000000,Hori TAC Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f0000c900000000000000,Hori Taiko Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00006400000000000000,Horipad 3TP,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00001300000000000000,Horipad 3W,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00005500000000000000,Horipad 4 FPS,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00006e00000000000000,Horipad 4 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00006600000000000000,Horipad 4 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f00004200000000000000,Horipad A,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000ad1b000001f5000000000000,Horipad EXT2,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000000d0f0000ee00000000000000,Horipad Mini 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f0000c100000000000000,Horipad Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000000d0f0000f600000000000000,Horipad Nintendo Switch Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, +030000000d0f00006700000000000000,Horipad One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000000d0f0000dc00000000000000,Horipad Switch,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000242e00000b20000000000000,Hyperkin Admiral N64 Controller,+rightx:b11,+righty:b13,-rightx:b8,-righty:b12,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b14,leftx:a0,lefty:a1,rightshoulder:b5,start:b9,platform:Windows, +03000000242e0000ff0b000000000000,Hyperkin N64 Adapter,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a2,righty:a3,start:b9,platform:Windows, +03000000790000004e95000000000000,Hyperkin N64 Controller Adapter,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b7,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a5,righty:a2,start:b9,platform:Windows, +03000000242e00006a48000000000000,Hyperkin RetroN Sq,a:b3,b:b7,back:b5,dpdown:+a4,dpleft:-a0,dpright:+a0,dpup:-a4,leftshoulder:b0,rightshoulder:b1,start:b4,x:b2,y:b6,platform:Windows, +03000000242e00006a38000000000000,Hyperkin Trooper 2,a:b0,b:b1,back:b4,leftshoulder:b2,leftx:a0,lefty:a1,rightshoulder:b3,start:b5,platform:Windows, +03000000d81d00000e00000000000000,iBuffalo AC02 Arcade Joystick,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b11,righttrigger:b3,rightx:a2,righty:a5,start:b8,x:b4,y:b5,platform:Windows, +03000000d81d00000f00000000000000,iBuffalo BSGP1204 Series,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, +03000000d81d00001000000000000000,iBuffalo BSGP1204P Series,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, +030000005c0a00000285000000000000,iDroidCon,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b6,platform:Windows, +03000000696400006964000000000000,iDroidCon Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000511d00000230000000000000,iGUGU Gamecore,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b1,leftstick:b4,lefttrigger:b3,leftx:a0,lefty:a1,rightshoulder:b0,righttrigger:b2,platform:Windows, +03000000b50700001403000000000000,Impact Black,a:b2,b:b3,back:b8,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows, +030000006f0e00002401000000000000,Injustice Fightstick PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, +03000000830500005130000000000000,InterAct ActionPad,a:b0,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b5,righttrigger:b2,start:b9,x:b3,y:b4,platform:Windows, +03000000ef0500000300000000000000,InterAct AxisPad,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,start:b11,x:b0,y:b1,platform:Windows, +03000000fd0500000230000000000000,InterAct AxisPad,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a5,start:b11,x:b0,y:b1,platform:Windows, +03000000fd0500000030000000000000,Interact GoPad,a:b3,b:b4,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,x:b0,y:b1,platform:Windows, +03000000fd0500003902000000000000,InterAct Hammerhead,a:b3,b:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b2,lefttrigger:b8,rightshoulder:b7,rightstick:b5,righttrigger:b9,start:b10,x:b0,y:b1,platform:Windows, +03000000fd0500002a26000000000000,InterAct Hammerhead FX,a:b3,b:b4,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b0,y:b1,platform:Windows, +03000000fd0500002f26000000000000,InterAct Hammerhead FX,a:b4,b:b5,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b1,y:b2,platform:Windows, +03000000fd0500005302000000000000,InterAct ProPad,a:b3,b:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,x:b0,y:b1,platform:Windows, +03000000ac0500002c02000000000000,Ipega Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,leftstick:b13,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b9,rightstick:b14,righttrigger:b7,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, +03000000491900000204000000000000,Ipega PG9023,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, +03000000491900000304000000000000,Ipega PG9087,+righty:+a5,-righty:-a4,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,start:b11,x:b3,y:b4,platform:Windows, +030000007e0500000620000000000000,Joy-Con (L),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b13,leftshoulder:b4,leftstick:b10,rightshoulder:b5,start:b8,x:b2,y:b3,platform:Windows, +030000007e0500000720000000000000,Joy-Con (R),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b12,leftshoulder:b4,leftstick:b11,rightshoulder:b5,start:b9,x:b2,y:b3,platform:Windows, +03000000250900000017000000000000,Joypad Adapter,a:b2,b:b1,back:b9,leftshoulder:b5,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b6,start:b8,x:b3,y:b0,platform:Windows, +03000000bd12000003c0000000000000,Joypad Alpha Shock,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000ff1100004033000000000000,JPD FFB,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a2,start:b15,x:b3,y:b0,platform:Windows, +03000000242f00002d00000000000000,JYS Adapter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, +03000000242f00008a00000000000000,JYS Adapter,a:b1,b:b4,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b0,y:b3,platform:Windows, +03000000c4100000c082000000000000,KADE,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000828200000180000000000000,Keio,a:b4,b:b5,back:b8,leftshoulder:b2,lefttrigger:b3,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,start:b9,x:b0,y:b1,platform:Windows, +03000000790000000200000000000000,King PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b3,y:b0,platform:Windows, +03000000bd12000001e0000000000000,Leadership,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows, +030000006f0e00000103000000000000,Logic3,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000006f0e00000104000000000000,Logic3,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000008f0e00001300000000000000,Logic3,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, +030000006d040000d1ca000000000000,Logitech ChillStream,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000006d040000d2ca000000000000,Logitech Cordless Precision,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000006d04000011c2000000000000,Logitech Cordless Wingman,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b5,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b2,righttrigger:b7,rightx:a3,righty:a4,x:b4,platform:Windows, +030000006d04000016c2000000000000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000006d0400001dc2000000000000,Logitech F310,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000006d04000018c2000000000000,Logitech F510,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000006d0400001ec2000000000000,Logitech F510,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000006d04000019c2000000000000,Logitech F710,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000006d0400001fc2000000000000,Logitech F710,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000006d0400001ac2000000000000,Logitech Precision,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, +030000006d04000009c2000000000000,Logitech WingMan,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b8,x:b3,y:b4,platform:Windows, +030000006d0400000bc2000000000000,Logitech WingMan Action Pad,a:b0,b:b1,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b8,lefttrigger:a5~,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b5,righttrigger:a2~,start:b8,x:b3,y:b4,platform:Windows, +030000006d0400000ac2000000000000,Logitech WingMan RumblePad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,rightx:a3,righty:a4,x:b3,y:b4,platform:Windows, +03000000380700005645000000000000,Lynx,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000222200006000000000000000,Macally,a:b1,b:b2,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b33,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000380700003888000000000000,Mad Catz Arcade Fightstick TE S Plus PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000380700008532000000000000,Mad Catz Arcade Fightstick TE S PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000380700006352000000000000,Mad Catz CTRLR,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000380700006652000000000000,Mad Catz CTRLR,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows, +03000000380700005032000000000000,Mad Catz Fightpad Pro PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000380700005082000000000000,Mad Catz Fightpad Pro PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000380700008031000000000000,Mad Catz FightStick Alpha PS3 ,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +030000003807000038b7000000000000,Mad Catz Fightstick TE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b8,rightshoulder:b5,righttrigger:b9,start:b7,x:b2,y:b3,platform:Windows, +03000000380700008433000000000000,Mad Catz Fightstick TE S PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000380700008483000000000000,Mad Catz Fightstick TE S PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000380700008134000000000000,Mad Catz Fightstick TE2 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b7,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b4,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000380700008184000000000000,Mad Catz Fightstick TE2 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,leftstick:b10,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000380700006252000000000000,Mad Catz Micro CTRLR,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows, +03000000380700008232000000000000,Mad Catz PlayStation Brawlpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000380700008731000000000000,Mad Catz PlayStation Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000003807000056a8000000000000,Mad Catz PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000380700001888000000000000,Mad Catz SFIV Fightstick PS3,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b4,righttrigger:b6,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, +03000000380700008081000000000000,Mad Catz SFV Arcade Fightstick Alpha PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000380700001847000000000000,Mad Catz Street Fighter 4 Xbox 360 FightStick,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b8,rightshoulder:b5,righttrigger:b9,start:b7,x:b2,y:b3,platform:Windows, +03000000380700008034000000000000,Mad Catz TE2 PS3 Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000380700008084000000000000,Mad Catz TE2 PS4 Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +030000002a0600001024000000000000,Matricom,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b2,y:b3,platform:Windows, +030000009f000000adbb000000000000,MaxJoypad Virtual Controller,a:b1,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows, +03000000250900000128000000000000,Mayflash Arcade Stick,a:b1,b:b2,back:b8,leftshoulder:b0,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b3,righttrigger:b7,start:b9,x:b5,y:b6,platform:Windows, +030000008f0e00001330000000000000,Mayflash Controller Adapter,a:b1,b:b2,back:b8,dpdown:h0.8,dpleft:h0.2,dpright:h0.1,dpup:h0.4,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a3~,righty:a2,start:b9,x:b0,y:b3,platform:Windows, +03000000242f00003700000000000000,Mayflash F101,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, +03000000790000003018000000000000,Mayflash F300 Arcade Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, +03000000242f00003900000000000000,Mayflash F300 Elite Arcade Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000790000004418000000000000,Mayflash GameCube Controller,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Windows, +03000000790000004318000000000000,Mayflash GameCube Controller Adapter,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Windows, +03000000242f00007300000000000000,Mayflash Magic NS,a:b1,b:b4,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b0,y:b3,platform:Windows, +0300000079000000d218000000000000,Mayflash Magic NS,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, +03000000d620000010a7000000000000,Mayflash Magic NS,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000242f0000f400000000000000,Mayflash N64 Controller Adapter,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a2,righty:a5,start:b9,platform:Windows, +03000000790000007918000000000000,Mayflash N64 Controller Adapter,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b9,leftx:a0,lefty:a1,righttrigger:b7,rightx:a3,righty:a2,start:b8,platform:Windows, +030000008f0e00001030000000000000,Mayflash Saturn Adapter,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,lefttrigger:b7,rightshoulder:b6,righttrigger:b2,start:b9,x:b3,y:b4,platform:Windows, +0300000025090000e803000000000000,Mayflash Wii Classic Adapter,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:a4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:a5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Windows, +03000000790000000318000000000000,Mayflash Wii DolphinBar,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b1,platform:Windows, +03000000790000000018000000000000,Mayflash Wii U Pro Adapter,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000790000002418000000000000,Mega Drive Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,rightshoulder:b2,start:b9,x:b3,y:b4,platform:Windows, +0300000079000000ae18000000000000,Mega Drive Controller,a:b0,b:b1,back:b7,dpdown:b14,dpleft:b15,dpright:b13,dpup:b2,rightshoulder:b6,righttrigger:b2,start:b9,x:b3,y:b4,platform:Windows, +03000000c0160000990a000000000000,Mega Drive Controller,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,righttrigger:b2,start:b3,platform:Windows, +030000005e0400002800000000000000,Microsoft Dual Strike,a:b3,b:b2,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,rightshoulder:b7,rightx:a0,righty:a1~,start:b5,x:b1,y:b0,platform:Windows, +030000005e0400000300000000000000,Microsoft SideWinder,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b8,x:b3,y:b4,platform:Windows, +030000005e0400000700000000000000,Microsoft SideWinder,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b9,x:b3,y:b4,platform:Windows, +030000005e0400000e00000000000000,Microsoft SideWinder Freestyle Pro,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,start:b8,x:b3,y:b4,platform:Windows, +030000005e0400002700000000000000,Microsoft SideWinder Plug and Play,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,lefttrigger:b4,righttrigger:b5,x:b2,y:b3,platform:Windows, +03000000280d00000202000000000000,Miller Lite Cantroller,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,start:b5,x:b2,y:b3,platform:Windows, +03000000ad1b000023f0000000000000,MLG,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a6,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows, +03000000ad1b00003ef0000000000000,MLG Fightstick TE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b8,rightshoulder:b5,righttrigger:b9,start:b7,x:b2,y:b3,platform:Windows, +03000000380700006382000000000000,MLG PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000004523000015e0000000000000,Mobapad Chitu HD,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, +03000000491900000904000000000000,Mobapad Chitu HD,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, +03000000ffff00000000000000000000,Mocute M053,a:b3,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b11,leftstick:b7,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b6,righttrigger:b4,rightx:a3,righty:a4,start:b8,x:b1,y:b0,platform:Windows, +03000000d6200000e589000000000000,Moga 2,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a2,righty:a5,start:b7,x:b2,y:b3,platform:Windows, +03000000d62000007162000000000000,Moga Pro,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a2,righty:a5,start:b7,x:b2,y:b3,platform:Windows, +03000000d6200000ad0d000000000000,Moga Pro,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000c62400002a89000000000000,Moga XP5A Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, +03000000c62400002b89000000000000,Moga XP5A Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, +03000000c62400001a89000000000000,Moga XP5X Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, +03000000c62400001b89000000000000,Moga XP5X Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, +03000000250900006688000000000000,MP-8866 Super Dual Box,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows, +03000000091200004488000000000000,MUSIA PlayStation 2 Input Display,a:b0,b:b2,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,leftstick:b6,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b9,rightstick:b7,righttrigger:b11,rightx:a2,righty:a3,start:b5,x:b1,y:b3,platform:Windows, +03000000f70600000100000000000000,N64 Adaptoid,+rightx:b2,+righty:b1,-rightx:b4,-righty:b5,a:b0,b:b3,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b6,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b7,start:b8,platform:Windows, +030000006f0e00001311000000000000,N64 Controller,+rightx:b10,+righty:b3,-rightx:b0,-righty:b11,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,platform:Windows, +030000006b140000010c000000000000,Nacon GC 400ES,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, +030000006b1400001106000000000000,Nacon Revolution 3 PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +0300000085320000170d000000000000,Nacon Revolution 5 Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows, +0300000085320000190d000000000000,Nacon Revolution 5 Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows, +030000006b140000100d000000000000,Nacon Revolution Infinity PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000006b140000080d000000000000,Nacon Revolution Unlimited Pro Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000bd12000001c0000000000000,Nebular,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a5,righty:a2,start:b9,x:b3,y:b0,platform:Windows, +03000000eb0300000000000000000000,NeGcon Adapter,a:a2,b:b13,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,lefttrigger:a4,leftx:a1,righttrigger:b11,start:b3,x:a3,y:b12,platform:Windows, +0300000038070000efbe000000000000,NEO SE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +0300000092120000474e000000000000,NeoGeo X Arcade Stick,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b9,x:b3,y:b2,platform:Windows, +03000000921200004b46000000000000,NES 2 port Adapter,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b11,platform:Windows, +03000000000f00000100000000000000,NES Controller,a:b1,b:b0,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,start:b3,platform:Windows, +03000000921200004346000000000000,NES Controller,a:b0,b:b1,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,start:b3,platform:Windows, +03000000790000004518000000000000,NEXILUX GameCube Controller Adapter,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b2,y:b3,platform:Windows, +030000001008000001e5000000000000,NEXT SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,righttrigger:b6,start:b9,x:b3,y:b0,platform:Windows, +03000000050b00000045000000000000,Nexus,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b10,x:b2,y:b3,platform:Windows, +03000000152000000182000000000000,NGDS,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b3,y:b0,platform:Windows, +030000007e0500000920000000000000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, +030000000d0500000308000000000000,Nostromo N45,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b12,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b10,x:b2,y:b3,platform:Windows, +030000007e0500001920000000000000,NSO N64 Controller,+rightx:b8,+righty:b2,-rightx:b3,-righty:b7,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,righttrigger:b10,start:b9,platform:Windows, +030000007e0500001720000000000000,NSO SNES Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b15,start:b9,x:b2,y:b3,platform:Windows, +03000000550900001472000000000000,NVIDIA Controller,a:b11,b:b10,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b7,leftstick:b5,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b4,righttrigger:a5,rightx:a3,righty:a6,start:b3,x:b9,y:b8,platform:Windows, +03000000550900001072000000000000,NVIDIA Shield,a:b9,b:b8,back:b11,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b3,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b2,righttrigger:a4,rightx:a2,righty:a5,start:b0,x:b7,y:b6,platform:Windows, +030000005509000000b4000000000000,NVIDIA Virtual,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:-a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000120c00000288000000000000,Nyko Air Flo Xbox Controller,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows, +030000004b120000014d000000000000,NYKO Airflo EX,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Windows, +03000000d62000001d57000000000000,Nyko Airflo PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000791d00000900000000000000,Nyko Playpad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows, +03000000782300000a10000000000000,Onlive Controller,a:b15,b:b14,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b11,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b13,y:b12,platform:Windows, +030000000d0f00000401000000000000,Onyx,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000008916000001fd000000000000,Onza CE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a3,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000008916000000fd000000000000,Onza TE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000d62000006d57000000000000,OPP PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000006b14000001a1000000000000,Orange Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b2,y:b3,platform:Windows, +03000000362800000100000000000000,OUYA Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b2,platform:Windows, +03000000120c0000f60e000000000000,P4 Gamepad,a:b1,b:b2,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b5,lefttrigger:b7,rightshoulder:b4,righttrigger:b6,start:b9,x:b0,y:b3,platform:Windows, +03000000790000002201000000000000,PC Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, +030000006f0e00008501000000000000,PDP Fightpad Pro GameCube Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, +030000006f0e00000901000000000000,PDP PS3 Versus Fighting,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, +030000008f0e00004100000000000000,PlaySega,a:b1,b:b0,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b5,righttrigger:b2,start:b8,x:b4,y:b3,platform:Windows, +03000000666600006706000000000000,PlayStation Adapter,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a2,righty:a3,start:b11,x:b3,y:b0,platform:Windows, +03000000e30500009605000000000000,PlayStation Adapter,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows, +030000004c050000da0c000000000000,PlayStation Classic Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Windows, +03000000632500002306000000000000,PlayStation Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Windows, +03000000f0250000c183000000000000,PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000d9040000160f000000000000,PlayStation Controller Adapter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows, +030000004c0500003713000000000000,PlayStation Vita,a:b1,b:b2,back:b8,dpdown:b13,dpleft:b15,dpright:b14,dpup:b12,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows, +03000000d620000011a7000000000000,PowerA Core Plus GameCube Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, +03000000dd62000015a7000000000000,PowerA Fusion Nintendo Switch Arcade Stick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000d620000012a7000000000000,PowerA Fusion Nintendo Switch Fight Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000dd62000016a7000000000000,PowerA Fusion Pro Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000d620000013a7000000000000,PowerA Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000d62000006dca000000000000,PowerA Pro Ex,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +0300000062060000d570000000000000,PowerA PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000d620000014a7000000000000,PowerA Spectra Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000006d04000084ca000000000000,Precision,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows, +03000000d62000009557000000000000,Pro Elite PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000c62400001a53000000000000,Pro Ex Mini,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000d62000009f31000000000000,Pro Ex mini PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000d6200000c757000000000000,Pro Ex mini PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000120c0000110e000000000000,Pro5,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000100800000100000000000000,PS1 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows, +030000008f0e00007530000000000000,PS1 Controller,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b1,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000100800000300000000000000,PS2 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a4,righty:a2,start:b9,x:b3,y:b0,platform:Windows, +03000000250900000088000000000000,PS2 Controller,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows, +03000000250900006888000000000000,PS2 Controller,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b6,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows, +03000000250900008888000000000000,PS2 Controller,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows, +030000006b1400000303000000000000,PS2 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, +030000009d0d00001330000000000000,PS2 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, +03000000151a00006222000000000000,PS2 Dual Plus Adapter,a:b2,b:b1,back:b9,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows, +03000000120a00000100000000000000,PS3 Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows, +03000000120c00001307000000000000,PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000120c00001cf1000000000000,PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000120c0000f90e000000000000,PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000250900000118000000000000,PS3 Controller,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows, +03000000250900000218000000000000,PS3 Controller,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows, +03000000250900000500000000000000,PS3 Controller,a:b2,b:b1,back:b9,dpdown:h0.8,dpleft:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b0,y:b3,platform:Windows, +030000004c0500006802000000000000,PS3 Controller,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b10,lefttrigger:a3~,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:a4~,rightx:a2,righty:a5,start:b8,x:b3,y:b0,platform:Windows, +030000004f1f00000800000000000000,PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, +03000000632500007505000000000000,PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, +03000000888800000803000000000000,PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b9,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:b7,rightx:a3,righty:a4,start:b11,x:b3,y:b0,platform:Windows, +03000000888800000804000000000000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Windows, +030000008f0e00000300000000000000,PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b3,y:b0,platform:Windows, +030000008f0e00001431000000000000,PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000ba2200002010000000000000,PS3 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a5,righty:a2,start:b9,x:b3,y:b2,platform:Windows, +03000000120c00000807000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000120c0000111e000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000120c0000121e000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000120c0000130e000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000120c0000150e000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000120c0000180e000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000120c0000181e000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000120c0000191e000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000120c00001e0e000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000120c0000a957000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000120c0000aa57000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000120c0000f21c000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000120c0000f31c000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000120c0000f41c000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000120c0000f51c000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000120c0000f70e000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000120e0000120c000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000160e0000120c000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +030000001a1e0000120c000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +030000004c050000a00b000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +030000004c050000c405000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows, +030000004c050000cc09000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +030000004c0500005f0e000000000000,PS5 Access Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b14,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows, +030000004c050000e60c000000000000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b14,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows, +030000004c050000f20d000000000000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b14,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows, +03000000830500005020000000000000,PSX,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b2,y:b3,platform:Windows, +03000000300f00000111000000000000,Qanba 2,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000300f00000211000000000000,Qanba 2P,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, +03000000300f00000011000000000000,Qanba Arcade Stick 1008,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b10,x:b0,y:b3,platform:Windows, +03000000300f00001611000000000000,Qanba Arcade Stick 4018,a:b1,b:b2,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b8,x:b0,y:b3,platform:Windows, +03000000222c00000025000000000000,Qanba Dragon Arcade Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000222c00000020000000000000,Qanba Drone Arcade Stick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,rightshoulder:b5,righttrigger:a4,start:b9,x:b0,y:b3,platform:Windows, +03000000300f00001211000000000000,Qanba Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000300f00001210000000000000,Qanba Joystick Plus,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b2,y:b3,platform:Windows, +03000000341a00000104000000000000,Qanba Joystick Q4RAF,a:b5,b:b6,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b0,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b3,righttrigger:b7,start:b9,x:b1,y:b2,platform:Windows, +03000000222c00000223000000000000,Qanba Obsidian Arcade Stick PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000222c00000023000000000000,Qanba Obsidian Arcade Stick PS4,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +030000008a2400006682000000000000,R1 Mobile Controller,a:b3,b:b1,back:b7,leftx:a0,lefty:a1,start:b6,x:b4,y:b0,platform:Windows, +03000000086700006626000000000000,RadioShack,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b3,y:b0,platform:Windows, +03000000ff1100004733000000000000,Ramox FPS Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b3,y:b0,platform:Windows, +030000009b2800002300000000000000,Raphnet 3DO Adapter,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b2,start:b3,platform:Windows, +030000009b2800006900000000000000,Raphnet 3DO Adapter,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b2,start:b3,platform:Windows, +030000009b2800000800000000000000,Raphnet Dreamcast Adapter,a:b2,b:b1,dpdown:b5,dpleft:b6,dpright:b7,dpup:b4,lefttrigger:a2,leftx:a0,righttrigger:a3,righty:a1,start:b3,x:b10,y:b9,platform:Windows, +030000009b280000d000000000000000,Raphnet Dreamcast Adapter,a:b1,b:b0,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,lefttrigger:+a5,leftx:a0,lefty:a1,righttrigger:+a2,start:b3,x:b5,y:b4,platform:Windows, +030000009b2800006200000000000000,Raphnet GameCube Adapter,a:b0,b:b7,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,rightx:a3,righty:a4,start:b3,x:b1,y:b8,platform:Windows, +030000009b2800003200000000000000,Raphnet GC and N64 Adapter,a:b0,b:b7,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,lefttrigger:+a5,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:+a2,rightx:a3,righty:a4,start:b3,x:b1,y:b8,platform:Windows, +030000009b2800006000000000000000,Raphnet GC and N64 Adapter,a:b0,b:b7,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,lefttrigger:+a5,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:+a2,rightx:a3,righty:a4,start:b3,x:b1,y:b8,platform:Windows, +030000009b2800001800000000000000,Raphnet Jaguar Adapter,a:b2,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b0,righttrigger:b10,start:b3,x:b11,y:b12,platform:Windows, +030000009b2800006100000000000000,Raphnet N64 Adapter,+rightx:b9,+righty:b7,-rightx:b8,-righty:b6,a:b0,b:b1,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b4,lefttrigger:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b3,platform:Windows, +030000009b2800006300000000000000,Raphnet N64 Adapter,+rightx:b9,+righty:b7,-rightx:b8,-righty:b6,a:b0,b:b1,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b4,lefttrigger:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b3,platform:Windows, +030000009b2800000200000000000000,Raphnet NES Adapter,a:b7,b:b6,back:b5,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,start:b4,platform:Windows, +030000009b2800004400000000000000,Raphnet PS1 and PS2 Adapter,a:b1,b:b2,back:b5,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,leftshoulder:b6,leftstick:b10,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b9,rightx:a3,righty:a4,start:b4,x:b0,y:b3,platform:Windows, +030000009b2800004300000000000000,Raphnet Saturn,a:b0,b:b1,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b8,x:b3,y:b4,platform:Windows, +030000009b2800000500000000000000,Raphnet Saturn Adapter 2.0,a:b1,b:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,start:b9,x:b0,y:b3,platform:Windows, +030000009b2800000300000000000000,Raphnet SNES Adapter,a:b0,b:b4,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Windows, +030000009b2800002600000000000000,Raphnet SNES Adapter,a:b1,b:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b3,x:b0,y:b5,platform:Windows, +030000009b2800002e00000000000000,Raphnet SNES Adapter,a:b1,b:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b3,x:b0,y:b5,platform:Windows, +030000009b2800002f00000000000000,Raphnet SNES Adapter,a:b1,b:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b3,x:b0,y:b5,platform:Windows, +030000009b2800005600000000000000,Raphnet SNES Adapter,a:b1,b:b4,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b3,x:b0,y:b5,platform:Windows, +030000009b2800005700000000000000,Raphnet SNES Adapter,a:b1,b:b4,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b3,x:b0,y:b5,platform:Windows, +030000009b2800001e00000000000000,Raphnet Vectrex Adapter,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a1,lefty:a2,x:b2,y:b3,platform:Windows, +030000009b2800002b00000000000000,Raphnet Wii Classic Adapter,a:b1,b:b4,back:b2,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,guide:b10,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a3,righty:a4,start:b3,x:b0,y:b5,platform:Windows, +030000009b2800002c00000000000000,Raphnet Wii Classic Adapter,a:b1,b:b4,back:b2,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,guide:b10,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a3,righty:a4,start:b3,x:b0,y:b5,platform:Windows, +030000009b2800008000000000000000,Raphnet Wii Classic Adapter,a:b1,b:b4,back:b2,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,guide:b10,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a3,righty:a4,start:b3,x:b0,y:b5,platform:Windows, +03000000790000008f18000000000000,Rapoo Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b3,y:b0,platform:Windows, +03000000321500000003000000000000,Razer Hydra,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000f8270000bf0b000000000000,Razer Kishi,a:b6,b:b7,back:b16,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b18,leftshoulder:b12,leftstick:b19,lefttrigger:b14,leftx:a0,lefty:a1,rightshoulder:b13,rightstick:b20,righttrigger:b15,rightx:a3,righty:a4,start:b17,x:b9,y:b10,platform:Windows, +03000000321500000204000000000000,Razer Panthera PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000321500000104000000000000,Razer Panthera PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000321500000010000000000000,Razer Raiju,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000321500000507000000000000,Razer Raiju Mobile,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, +03000000321500000707000000000000,Razer Raiju Mobile,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, +03000000321500000710000000000000,Razer Raiju TE,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000321500000a10000000000000,Razer Raiju TE,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000321500000410000000000000,Razer Raiju UE,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000321500000910000000000000,Razer Raiju UE,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000321500000011000000000000,Razer Raion PS4 Fightpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000321500000009000000000000,Razer Serval,+lefty:+a2,-lefty:-a1,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,leftx:a0,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000921200004547000000000000,Retro Bit Sega Genesis Controller Adapter,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,lefttrigger:b7,rightshoulder:b5,righttrigger:b2,start:b6,x:b3,y:b4,platform:Windows, +03000000790000001100000000000000,Retro Controller,a:b1,b:b2,back:b8,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,leftshoulder:b6,lefttrigger:b7,rightshoulder:b4,righttrigger:b5,start:b9,x:b0,y:b3,platform:Windows, +03000000830500006020000000000000,Retro Controller,a:b0,b:b1,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b8,righttrigger:b9,start:b7,x:b2,y:b3,platform:Windows, +0300000003040000c197000000000000,Retrode Adapter,a:b0,b:b4,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Windows, +03000000bd12000013d0000000000000,Retrolink Sega Saturn Classic Controller,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b5,lefttrigger:b6,rightshoulder:b2,righttrigger:b7,start:b8,x:b3,y:b4,platform:Windows, +03000000bd12000015d0000000000000,Retrolink SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Windows, +03000000341200000400000000000000,RetroUSB N64 RetroPort,+rightx:b8,+righty:b10,-rightx:b9,-righty:b11,a:b7,b:b6,dpdown:b2,dpleft:b1,dpright:b0,dpup:b3,leftshoulder:b13,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b12,start:b4,platform:Windows, +0300000000f000000300000000000000,RetroUSB RetroPad,a:b1,b:b5,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Windows, +0300000000f00000f100000000000000,RetroUSB Super RetroPort,a:b1,b:b5,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Windows, +03000000830500000960000000000000,Revenger,a:b0,b:b1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b3,x:b4,y:b5,platform:Windows, +030000006b140000010d000000000000,Revolution Pro Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +030000006b140000020d000000000000,Revolution Pro Controller 2,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +030000006b140000130d000000000000,Revolution Pro Controller 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +030000006f0e00001f01000000000000,Rock Candy,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000006f0e00004601000000000000,Rock Candy,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000c6240000fefa000000000000,Rock Candy Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000006f0e00008701000000000000,Rock Candy Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000006f0e00001e01000000000000,Rock Candy PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000006f0e00002801000000000000,Rock Candy PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000006f0e00002f01000000000000,Rock Candy PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000050b0000e318000000000000,ROG Chakram,a:b1,b:b0,leftx:a0,lefty:a1,x:b2,y:b3,platform:Windows, +03000000050b0000e518000000000000,ROG Chakram,a:b1,b:b0,leftx:a0,lefty:a1,x:b2,y:b3,platform:Windows, +03000000050b00005819000000000000,ROG Chakram Core,a:b1,b:b0,leftx:a0,lefty:a1,x:b2,y:b3,platform:Windows, +03000000050b0000181a000000000000,ROG Chakram X,a:b1,b:b0,leftx:a0,lefty:a1,x:b2,y:b3,platform:Windows, +03000000050b00001a1a000000000000,ROG Chakram X,a:b1,b:b0,leftx:a0,lefty:a1,x:b2,y:b3,platform:Windows, +03000000050b00001c1a000000000000,ROG Chakram X,a:b1,b:b0,leftx:a0,lefty:a1,x:b2,y:b3,platform:Windows, +030000004f04000001d0000000000000,Rumble Force,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Windows, +030000000d0f0000ad00000000000000,RX Gamepad,a:b0,b:b4,back:b11,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,rightshoulder:b6,start:b9,x:b2,y:b1,platform:Windows, +030000008916000000fe000000000000,Sabertooth,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000c6240000045d000000000000,Sabertooth,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000a30600001af5000000000000,Saitek Cyborg,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows, +03000000a306000023f6000000000000,Saitek Cyborg V.1 Game,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Windows, +03000000300f00001201000000000000,Saitek Dual Analog,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows, +03000000a30600000701000000000000,Saitek P220,a:b2,b:b3,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b4,righttrigger:b5,x:b0,y:b1,platform:Windows, +03000000a30600000cff000000000000,Saitek P2500 Force Rumble,a:b2,b:b3,back:b11,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b0,y:b1,platform:Windows, +03000000a30600000d5f000000000000,Saitek P2600,a:b1,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a3,righty:a2,start:b8,x:b0,y:b3,platform:Windows, +03000000a30600000dff000000000000,Saitek P2600,a:b1,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a5,righty:a2,start:b8,x:b0,y:b3,platform:Windows, +03000000a30600000c04000000000000,Saitek P2900,a:b1,b:b2,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b3,platform:Windows, +03000000a306000018f5000000000000,Saitek P3200,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows, +03000000300f00001001000000000000,Saitek P480 Rumble,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows, +03000000a30600000901000000000000,Saitek P880,a:b2,b:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b8,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b9,righttrigger:b5,rightx:a3,righty:a2,x:b0,y:b1,platform:Windows, +03000000a30600000b04000000000000,Saitek P990,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b3,platform:Windows, +03000000a30600002106000000000000,Saitek PS1000 PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Windows, +03000000a306000020f6000000000000,Saitek PS2700 PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Windows, +03000000300f00001101000000000000,Saitek Rumble,a:b2,b:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows, +03000000e804000000a0000000000000,Samsung EIGP20,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, +03000000c01100000252000000000000,Sanwa Easy Grip,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b9,x:b3,y:b4,platform:Windows, +03000000c01100004350000000000000,Sanwa Micro Grip P3,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,x:b3,y:b2,platform:Windows, +03000000411200004550000000000000,Sanwa Micro Grip Pro,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a1,righty:a2,start:b9,x:b1,y:b3,platform:Windows, +03000000c01100004150000000000000,Sanwa Micro Grip Pro,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Windows, +03000000c01100004450000000000000,Sanwa Online Grip,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b8,rightstick:b11,righttrigger:b9,rightx:a3,righty:a2,start:b14,x:b3,y:b4,platform:Windows, +03000000730700000401000000000000,Sanwa PlayOnline Mobile,a:b0,b:b1,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,start:b3,platform:Windows, +03000000830500006120000000000000,Sanwa Smart Grip II,a:b0,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,x:b1,y:b3,platform:Windows, +03000000c01100000051000000000000,Satechi Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows, +030000004f04000028b3000000000000,Score A,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000952e00002577000000000000,Scuf PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000a30c00002500000000000000,Sega Genesis Mini 3B Controller,a:b2,b:b1,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,righttrigger:b5,start:b9,platform:Windows, +03000000a30c00002400000000000000,Sega Mega Drive Mini 6B Controller,a:b2,b:b1,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Windows, +03000000d804000086e6000000000000,Sega Multi Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b7,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b8,x:b3,y:b4,platform:Windows, +0300000000050000289b000000000000,Sega Saturn Adapter,a:b1,b:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,start:b9,x:b0,y:b3,platform:Windows, +0300000000f000000800000000000000,Sega Saturn Controller,a:b1,b:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,rightshoulder:b7,righttrigger:b3,start:b0,x:b5,y:b6,platform:Windows, +03000000730700000601000000000000,Sega Saturn Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b9,x:b3,y:b4,platform:Windows, +03000000b40400000a01000000000000,Sega Saturn Controller,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b5,righttrigger:b2,start:b8,x:b3,y:b4,platform:Windows, +030000003b07000004a1000000000000,SFX,a:b0,b:b2,back:b7,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b9,righttrigger:b5,start:b8,x:b1,y:b3,platform:Windows, +03000000f82100001900000000000000,Shogun Bros Chameleon X1,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows, +03000000120c00001c1e000000000000,SnakeByte 4S PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000140300000918000000000000,SNES Controller,a:b0,b:b1,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Windows, +0300000081170000960a000000000000,SNES Controller,a:b4,b:b0,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b3,x:b5,y:b1,platform:Windows, +03000000811700009d0a000000000000,SNES Controller,a:b0,b:b4,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Windows, +030000008b2800000300000000000000,SNES Controller,a:b0,b:b4,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Windows, +03000000921200004653000000000000,SNES Controller,a:b0,b:b4,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Windows, +03000000ff000000cb01000000000000,Sony PlayStation Portable,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Windows, +03000000341a00000208000000000000,Speedlink 6555,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:-a4,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a4,rightx:a3,righty:a2,start:b7,x:b2,y:b3,platform:Windows, +03000000341a00000908000000000000,Speedlink 6566,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, +03000000380700001722000000000000,Speedlink Competition Pro,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,x:b2,y:b3,platform:Windows, +030000008f0e00000800000000000000,Speedlink Strike FX,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, +03000000c01100000591000000000000,Speedlink Torid,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, +03000000d11800000094000000000000,Stadia Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:b12,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:b11,rightx:a3,righty:a4,start:b9,x:b2,y:b3,platform:Windows, +03000000de280000fc11000000000000,Steam Virtual Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000de280000ff11000000000000,Steam Virtual Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:-a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000120c0000160e000000000000,Steel Play Metaltech PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000110100001914000000000000,SteelSeries,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftstick:b13,lefttrigger:b6,leftx:a0,lefty:a1,rightstick:b14,righttrigger:b7,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, +03000000381000001214000000000000,SteelSeries Free,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Windows, +03000000110100003114000000000000,SteelSeries Stratus Duo,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, +03000000381000003014000000000000,SteelSeries Stratus Duo,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000381000003114000000000000,SteelSeries Stratus Duo,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000381000001814000000000000,SteelSeries Stratus XL,a:b0,b:b1,back:b18,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,guide:b19,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b2,y:b3,platform:Windows, +03000000790000001c18000000000000,STK 7024X,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, +03000000380700003847000000000000,Street Fighter Fightstick TE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b11,start:b7,x:b2,y:b3,platform:Windows, +030000001f08000001e4000000000000,Super Famicom Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Windows, +03000000790000000418000000000000,Super Famicom Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b33,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Windows, +03000000341200001300000000000000,Super Racer,a:b2,b:b3,back:b8,leftshoulder:b5,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b4,righttrigger:b7,x:b0,y:b1,platform:Windows, +03000000457500002211000000000000,Szmy Power PC Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000004f0400000ab1000000000000,T16000M,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b4,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,start:b10,x:b2,y:b3,platform:Windows, +030000000d0f00007b00000000000000,TAC GEAR,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000e40a00000307000000000000,Taito Egret II Mini Control Panel,a:b4,b:b2,back:b6,guide:b9,leftx:a0,lefty:a1,rightshoulder:b0,righttrigger:b1,start:b7,x:b8,y:b3,platform:Windows, +03000000e40a00000207000000000000,Taito Egret II Mini Controller,a:b4,b:b2,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,guide:b9,rightshoulder:b0,righttrigger:b1,start:b7,x:b8,y:b3,platform:Windows, +03000000d814000001a0000000000000,TE Kitty,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000fa1900000706000000000000,Team 5,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, +03000000b50700001203000000000000,Techmobility X6-38V,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows, +03000000ba2200000701000000000000,Technology Innovation PS2 Adapter,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b3,y:b2,platform:Windows, +03000000c61100001000000000000000,Tencent Xianyou Gamepad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,x:b3,y:b4,platform:Windows, +03000000790000002601000000000000,TGZ,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b3,y:b0,platform:Windows, +03000000591c00002400000000000000,THEC64 Joystick,a:b0,b:b1,back:b6,leftshoulder:b4,leftx:a0,lefty:a4,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Windows, +03000000591c00002600000000000000,THEGamepad,a:b2,b:b1,back:b6,leftx:a0,lefty:a1,start:b7,x:b3,y:b0,platform:Windows, +030000004f04000015b3000000000000,Thrustmaster Dual Analog 4,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Windows, +030000004f04000023b3000000000000,Thrustmaster Dual Trigger PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +030000004f0400000ed0000000000000,ThrustMaster eSwap Pro Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +030000004f04000008d0000000000000,ThrustMaster Ferrari 150 PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +030000004f04000000b3000000000000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b11,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b1,y:b3,platform:Windows, +030000004f04000004b3000000000000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Windows, +030000004f04000003d0000000000000,ThrustMaster Run N Drive PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b7,leftshoulder:a3,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:a4,rightstick:b11,righttrigger:b5,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +030000004f04000009d0000000000000,ThrustMaster Run N Drive PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +030000006d04000088ca000000000000,Thunderpad,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows, +03000000666600000288000000000000,TigerGame PlayStation Adapter,a:b2,b:b1,back:b9,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows, +03000000666600000488000000000000,TigerGame PlayStation Adapter,a:b2,b:b1,back:b9,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows, +030000004f04000007d0000000000000,TMini,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000571d00002100000000000000,Tomee NES Controller Adapter,a:b1,b:b0,back:b2,dpdown:+a4,dpleft:-a0,dpright:+a0,dpup:-a4,start:b3,platform:Windows, +03000000571d00002000000000000000,Tomee SNES Controller Adapter,a:b0,b:b1,back:b6,dpdown:+a4,dpleft:-a0,dpright:+a0,dpup:-a4,leftshoulder:b4,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Windows, +03000000d62000006000000000000000,Tournament PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000c01100000055000000000000,Tronsmart,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, +030000005f140000c501000000000000,Trust Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, +03000000b80500000210000000000000,Trust Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, +030000004f04000087b6000000000000,TWCS Throttle,dpdown:b8,dpleft:b9,dpright:b7,dpup:b6,leftstick:b5,lefttrigger:-a5,leftx:a0,lefty:a1,righttrigger:+a5,platform:Windows, +03000000411200000450000000000000,Twin Shock,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a3,righty:a4,start:b11,x:b3,y:b0,platform:Windows, +03000000d90400000200000000000000,TwinShock PS2 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows, +03000000151900005678000000000000,Uniplay U6,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, +03000000101c0000171c000000000000,uRage Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, +030000000b0400003065000000000000,USB Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b3,y:b0,platform:Windows, +03000000242f00006e00000000000000,USB Controller,a:b1,b:b4,back:b10,leftshoulder:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b9,righttrigger:b7,rightx:a2,righty:a5,start:b11,x:b0,y:b3,platform:Windows, +03000000300f00000701000000000000,USB Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows, +03000000341a00002308000000000000,USB Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, +03000000666600000188000000000000,USB Controller,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows, +030000006b1400000203000000000000,USB Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, +03000000790000000a00000000000000,USB Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b3,y:b0,platform:Windows, +03000000b404000081c6000000000000,USB Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b3,y:b0,platform:Windows, +03000000b50700001503000000000000,USB Controller,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a5,righty:a2,start:b9,x:b0,y:b1,platform:Windows, +03000000bd12000012d0000000000000,USB Controller,a:b0,b:b1,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Windows, +03000000ff1100004133000000000000,USB Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a4,righty:a2,start:b9,x:b3,y:b0,platform:Windows, +03000000632500002305000000000000,USB Vibration Joystick,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, +03000000790000001a18000000000000,Venom,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, +03000000790000001b18000000000000,Venom Arcade Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, +030000006f0e00000302000000000000,Victrix PS4 Pro Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, +030000006f0e00000702000000000000,Victrix PS4 Pro Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, +0300000034120000adbe000000000000,vJoy Device,a:b0,b:b1,back:b15,dpdown:b6,dpleft:b7,dpright:b8,dpup:b5,guide:b16,leftshoulder:b9,leftstick:b13,lefttrigger:b11,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b14,righttrigger:b12,rightx:a3,righty:a4,start:b4,x:b2,y:b3,platform:Windows, +03000000120c0000ab57000000000000,Warrior Joypad JS083,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +030000007e0500003003000000000000,Wii U Pro,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,leftshoulder:b6,leftstick:b11,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b12,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Windows, +0300000032150000030a000000000000,Wildcat,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +0300000032150000140a000000000000,Wolverine,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000002e160000efbe000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b10,rightshoulder:b5,righttrigger:b11,start:b7,x:b2,y:b3,platform:Windows, +03000000380700001647000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000380700002045000000000000,Xbox 360 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, +03000000380700002644000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a2,righty:a5,start:b8,x:b2,y:b3,platform:Windows, +03000000380700002647000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000003807000026b7000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000380700003647000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a7,righty:a5,start:b7,x:b2,y:b3,platform:Windows, +030000005e0400001907000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000005e0400008e02000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:-a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000005e0400009102000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000ad1b000000fd000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000ad1b000001fd000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000ad1b000016f0000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000ad1b00008e02000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000c62400000053000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000c6240000fdfa000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000380700002847000000000000,Xbox 360 Fightpad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000005e040000a102000000000000,Xbox 360 Wireless Receiver,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:-a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000005e0400000a0b000000000000,Xbox Adaptive Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:-a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000120c00000a88000000000000,Xbox Controller,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a2,righty:a4,start:b6,x:b2,y:b3,platform:Windows, +03000000120c00001088000000000000,Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2~,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5~,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000002a0600002000000000000000,Xbox Controller,a:b0,b:b1,back:b13,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,leftshoulder:b5,leftstick:b14,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b15,righttrigger:b7,rightx:a2,righty:a5,start:b12,x:b2,y:b3,platform:Windows, +03000000300f00008888000000000000,Xbox Controller,a:b0,b:b1,back:b7,dpdown:b13,dpleft:b10,dpright:b11,dpup:b12,leftshoulder:b5,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows, +03000000380700001645000000000000,Xbox Controller,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows, +03000000380700002645000000000000,Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000380700003645000000000000,Xbox Controller,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows, +03000000380700008645000000000000,Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000005e0400000202000000000000,Xbox Controller,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows, +030000005e0400008502000000000000,Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000005e0400008702000000000000,Xbox Controller,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b9,righttrigger:b7,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows, +030000005e0400008902000000000000,Xbox Controller,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b10,leftstick:b8,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b9,righttrigger:b4,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows, +030000000d0f00006300000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000005e0400000c0b000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000005e040000d102000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000005e040000dd02000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000005e040000e002000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000005e040000e302000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000005e040000ea02000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:-a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000005e040000fd02000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000005e040000ff02000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:-a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000006f0e0000a802000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000006f0e0000c802000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000c62400003a54000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000005e040000130b000000000000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +03000000341a00000608000000000000,Xeox,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, +03000000450c00002043000000000000,Xeox SL6556BK,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, +030000006f0e00000300000000000000,XGear,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a5,righty:a2,start:b9,x:b3,y:b0,platform:Windows, +03000000e0ff00000201000000000000,Xiaomi Black Shark (L),back:b0,dpdown:b11,dpleft:b9,dpright:b10,dpup:b8,leftshoulder:b5,lefttrigger:b7,leftx:a0,lefty:a1,platform:Windows, +03000000172700004431000000000000,Xiaomi Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b20,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a7,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows, +03000000172700003350000000000000,Xiaomi XMGP01YM,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, +03000000bc2000005060000000000000,Xiaomi XMGP01YM,+lefty:+a2,+righty:+a5,-lefty:-a1,-righty:-a4,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,start:b11,x:b3,y:b4,platform:Windows, +xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000007d0400000340000000000000,Xterminator Digital Gamepad,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:-a4,lefttrigger:+a4,leftx:a0,lefty:a1,paddle1:b7,paddle2:b6,rightshoulder:b5,rightstick:b9,righttrigger:b2,rightx:a3,righty:a5,start:b8,x:b3,y:b4,platform:Windows, +030000002c3600000100000000000000,Yawman Arrow,+rightx:h0.2,+righty:h0.4,-rightx:h0.8,-righty:h0.1,a:b4,b:b5,back:b6,dpdown:b15,dpleft:b14,dpright:b16,dpup:b13,leftshoulder:b10,leftstick:b0,lefttrigger:-a4,leftx:a0,lefty:a1,paddle1:b11,paddle2:b12,rightshoulder:b8,rightstick:b9,righttrigger:+a4,start:b3,x:b1,y:b2,platform:Windows, +03000000790000004f18000000000000,ZDT Android Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, +03000000120c00000500000000000000,Zeroplus Adapter,a:b2,b:b1,back:b11,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b0,righttrigger:b5,rightx:a3,righty:a2,start:b8,x:b3,y:b0,platform:Windows, +03000000120c0000101e000000000000,Zeroplus P4 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, + +# Mac OS X +030000008f0e00000300000009010000,2 In 1 Joystick,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X, +03000000c82d00000031000001000000,8BitDo Adapter,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, +03000000c82d00000531000000020000,8BitDo Adapter 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, +03000000c82d00000951000000010000,8BitDo Dogbone,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightx:a2,righty:a3,start:b11,platform:Mac OS X, +03000000c82d00000090000001000000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, +03000000c82d00001038000000010000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, +03000000c82d00001251000000010000,8BitDo Lite 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, +03000000c82d00001251000000020000,8BitDo Lite 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, +03000000c82d00001151000000010000,8BitDo Lite SE,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, +03000000c82d00001151000000020000,8BitDo Lite SE,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, +03000000a30c00002400000006020000,8BitDo M30,a:b2,b:b1,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,guide:b9,leftshoulder:b6,lefttrigger:b5,rightshoulder:b4,righttrigger:b7,start:b8,x:b3,y:b0,platform:Mac OS X, +03000000c82d00000151000000010000,8BitDo M30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, +03000000c82d00000650000001000000,8BitDo M30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b8,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, +03000000c82d00005106000000010000,8BitDo M30,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,guide:b2,leftshoulder:b6,lefttrigger:a5,rightshoulder:b7,righttrigger:a4,start:b11,x:b4,y:b3,platform:Mac OS X, +03000000c82d00002090000000010000,8BitDo Micro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, +03000000c82d00000451000000010000,8BitDo N30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightx:a2,righty:a3,start:b11,platform:Mac OS X, +03000000c82d00001590000001000000,8BitDo N30 Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, +03000000c82d00006528000000010000,8BitDo N30 Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, +03000000c82d00006928000000010000,8BitDo N64,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a3,start:b11,platform:Mac OS X, +03000000c82d00002590000000010000,8BitDo NEOGEO,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, +03000000c82d00002590000001000000,8BitDo NEOGEO,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, +03000000c82d00002690000000010000,8BitDo NEOGEO,+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b10,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Mac OS X, +030000003512000012ab000001000000,8BitDo NES30,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X, +03000000c82d000012ab000001000000,8BitDo NES30,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Mac OS X, +03000000c82d00002028000000010000,8BitDo NES30,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Mac OS X, +03000000022000000090000001000000,8BitDo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, +03000000203800000900000000010000,8BitDo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, +03000000c82d00000190000001000000,8BitDo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, +03000000c82d00000751000000010000,8BitDo P30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, +03000000c82d00000851000000010000,8BitDo P30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, +03000000c82d00000660000000010000,8BitDo Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, +03000000c82d00000660000000020000,8BitDo Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, +03000000c82d00000131000001000000,8BitDo Receiver,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, +03000000c82d00000231000001000000,8BitDo Receiver,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, +03000000c82d00000331000001000000,8BitDo Receiver,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, +03000000c82d00000431000001000000,8BitDo Receiver,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, +03000000c82d00002867000000010000,8BitDo S30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b3,y:b4,platform:Mac OS X, +03000000c82d00003028000000010000,8Bitdo SFC30 Gamepad,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X, +03000000102800000900000000000000,8BitDo SFC30 Joystick,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X, +03000000c82d00000351000000010000,8BitDo SN30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, +03000000c82d00001290000001000000,8BitDo SN30,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X, +03000000c82d00004028000000010000,8BitDo SN30,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X, +03000000c82d00000160000001000000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, +03000000c82d00000161000000010000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Mac OS X, +03000000c82d00000260000001000000,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, +03000000c82d00000261000000010000,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, +03000000c82d00001230000000010000,8BitDo Ultimate,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b2,paddle2:b5,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, +03000000c82d00001530000001000000,8BitDo Ultimate C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, +03000000c82d00001630000001000000,8BitDo Ultimate C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, +03000000c82d00001730000001000000,8BitDo Ultimate C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, +03000000c82d00001130000000020000,8BitDo Ultimate Wired,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b26,paddle1:b24,paddle2:b25,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, +03000000c82d00001330000001000000,8BitDo Ultimate Wireless,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b26,paddle1:b23,paddle2:b19,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, +03000000c82d00001330000000020000,8BitDo Ultimate Wireless Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b26,paddle1:b23,paddle2:b19,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, +03000000a00500003232000008010000,8BitDo Zero,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Mac OS X, +03000000a00500003232000009010000,8BitDo Zero,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Mac OS X, +03000000c82d00001890000001000000,8BitDo Zero 2,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X, +03000000c82d00003032000000010000,8BitDo Zero 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2,righty:a31,start:b11,x:b4,y:b3,platform:Mac OS X, +03000000491900001904000001010000,Amazon Luna Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b9,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b7,x:b2,y:b3,platform:Mac OS X, +03000000710100001904000000010000,Amazon Luna Controller,a:b0,b:b1,back:b11,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b9,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Mac OS X, +0300000008100000e501000019040000,Anbernic Gamepad,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a4,start:b11,x:b4,y:b3,platform:Mac OS X, +03000000a30c00002700000003030000,Astro City Mini,a:b2,b:b1,back:b8,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Mac OS X, +03000000a30c00002800000003030000,Astro City Mini,a:b2,b:b1,back:b8,leftx:a3,lefty:a4,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Mac OS X, +03000000050b00000045000031000000,ASUS Gamepad,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X, +03000000050b00000579000000010000,ASUS ROG Kunai 3,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b14,leftshoulder:b6,leftstick:b15,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b42,paddle1:b9,paddle2:b11,rightshoulder:b7,rightstick:b16,righttrigger:a4,rightx:a2,righty:a3,start:b13,x:b3,y:b4,platform:Mac OS X, +03000000050b00000679000000010000,ASUS ROG Kunai 3,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b14,leftshoulder:b6,leftstick:b15,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b23,rightshoulder:b7,rightstick:b16,righttrigger:a4,rightx:a2,righty:a3,start:b13,x:b3,y:b4,platform:Mac OS X, +03000000503200000110000047010000,Atari VCS Classic Controller,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b3,start:b2,platform:Mac OS X, +03000000503200000210000047010000,Atari VCS Modern Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a4,rightx:a2,righty:a3,start:b8,x:b2,y:b3,platform:Mac OS X, +030000008a3500000102000000010000,Backbone One,a:b0,b:b1,back:b16,dpdown:b11,dpleft:b13,dpright:b12,dpup:b10,guide:b17,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3~,start:b15,x:b2,y:b3,platform:Mac OS X, +030000008a3500000201000000010000,Backbone One,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, +030000008a3500000202000000010000,Backbone One,a:b0,b:b1,back:b16,dpdown:b11,dpleft:b13,dpright:b12,dpup:b10,guide:b17,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3~,start:b15,x:b2,y:b3,platform:Mac OS X, +030000008a3500000402000000010000,Backbone One,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, +030000008a3500000302000000010000,Backbone One PlayStationÆ Edition,a:b0,b:b1,back:b16,dpdown:b11,dpleft:b13,dpright:b12,dpup:b10,guide:b17,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3~,start:b15,x:b2,y:b3,platform:Mac OS X, +03000000c62400001a89000000010000,BDA MOGA XP5-X Plus,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b14,leftshoulder:b6,leftstick:b15,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b16,righttrigger:a4,rightx:a2,righty:a3,start:b13,x:b3,y:b4,platform:Mac OS X, +03000000c62400001b89000000010000,BDA MOGA XP5-X Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, +03000000d62000002a79000000010000,BDA PS4 Fightpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, +03000000120c0000200e000000010000,Brook Mars PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, +03000000120c0000210e000000010000,Brook Mars PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +030000008305000031b0000000000000,Cideko AK08b,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +03000000d8140000cecf000000000000,Cthulhu,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X, +03000000260900008888000088020000,Cyber Gadget GameCube Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:a5,rightx:a2,righty:a3~,start:b7,x:b2,y:b3,platform:Mac OS X, +03000000a306000022f6000001030000,Cyborg V3 Rumble Pad PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:+a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:-a3,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Mac OS X, +03000000791d00000103000009010000,Dual Box Wii Classic Adapter,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b10,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X, +030000006e0500000720000010020000,Elecom JC-W01U,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b1,platform:Mac OS X, +030000006f0e00008401000003010000,Faceoff Deluxe Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b13,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +03000000151900004000000001000000,Flydigi Vader 2,a:b14,b:b15,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b21,leftshoulder:b6,leftstick:b12,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b2,paddle2:b5,paddle3:b16,paddle4:b17,rightshoulder:b7,rightstick:b13,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b0,y:b1,platform:Mac OS X, +03000000b40400001124000001040000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b12,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b14,paddle1:b2,paddle2:b5,paddle3:b16,paddle4:b17,rightshoulder:b7,rightstick:b13,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, +03000000b40400001224000003030000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b12,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b2,paddle1:b16,paddle2:b17,paddle3:b14,paddle4:b15,rightshoulder:b7,rightstick:b13,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, +03000000790000004618000000010000,GameCube Controller Adapter,a:b4,b:b0,dpdown:b56,dpleft:b60,dpright:b52,dpup:b48,lefttrigger:a12,leftx:a0,lefty:a4,rightshoulder:b28,righttrigger:a16,rightx:a20,righty:a8,start:b36,x:b8,y:b12,platform:Mac OS X, +03000000ac0500001a06000002020000,GameSir-T3 2.02,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, +03000000ad1b000001f9000000000000,Gamestop BB070 X360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, +0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X, +03000000c01100000140000000010000,GameStop PS4 Fun Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, +030000006f0e00000102000000000000,GameStop Xbox 360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, +03000000ff1100003133000007010000,GameWare PC Control Pad,a:b2,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a4,start:b11,x:b3,y:b0,platform:Mac OS X, +030000007d0400000540000001010000,Gravis Eliminator Pro,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X, +03000000280400000140000000020000,Gravis GamePad Pro,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X, +030000008f0e00000300000007010000,GreenAsia Joystick,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Mac OS X, +030000000d0f00002d00000000100000,Hori Fighting Commander 3 Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +030000000d0f00005f00000000000000,Hori Fighting Commander 4 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +030000000d0f00005f00000000010000,Hori Fighting Commander 4 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +030000000d0f00005e00000000000000,Hori Fighting Commander 4 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +030000000d0f00005e00000000010000,Hori Fighting Commander 4 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, +030000000d0f00008400000000010000,Hori Fighting Commander PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, +030000000d0f00008500000000010000,Hori Fighting Commander PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +03000000341a00000302000014010000,Hori Fighting Stick Mini,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X, +030000000d0f00008800000000010000,Hori Fighting Stick mini 4 (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X, +030000000d0f00008700000000010000,Hori Fighting Stick mini 4 (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X, +030000000d0f00004d00000000000000,Hori Gem Pad 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +030000000d0f00003801000008010000,Hori PC Engine Mini Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b9,platform:Mac OS X, +030000000d0f00009200000000010000,Hori Pokken Tournament DX Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X, +030000000d0f0000aa00000072050000,Hori Real Arcade Pro for Nintendo Switch,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X, +030000000d0f00000002000017010000,Hori Split Pad Fit,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +030000000d0f00000002000015010000,Hori Switch Split Pad Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +030000000d0f00006e00000000010000,Horipad 4 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +030000000d0f00006600000000010000,Horipad 4 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, +030000000d0f00006600000000000000,Horipad FPS Plus 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, +030000000d0f0000ee00000000010000,Horipad Mini 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, +030000000d0f0000c100000072050000,Horipad Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +03000000242e0000ff0b000000010000,Hyperkin N64 Adapter,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a2,righty:a3,start:b9,platform:Mac OS X, +03000000790000004e95000000010000,Hyperkin N64 Controller Adapter,a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b7,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a5,righty:a2,start:b9,platform:Mac OS X, +03000000830500006020000000000000,iBuffalo Super Famicom Controller,a:b1,b:b0,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Mac OS X, +03000000ef0500000300000000020000,InterAct AxisPad,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,start:b11,x:b0,y:b1,platform:Mac OS X, +03000000fd0500000030000010010000,Interact GoPad,a:b3,b:b4,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,x:b0,y:b1,platform:Mac OS X, +030000007e0500000620000001000000,Joy-Con (L),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b13,leftshoulder:b4,leftstick:b10,rightshoulder:b5,start:b8,x:b2,y:b3,platform:Mac OS X, +030000007e0500000720000001000000,Joy-Con (R),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b12,leftshoulder:b4,leftstick:b11,rightshoulder:b5,start:b9,x:b2,y:b3,platform:Mac OS X, +03000000242f00002d00000007010000,JYS Adapter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X, +030000006d04000019c2000000000000,Logitech Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +030000006d04000016c2000000020000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +030000006d04000016c2000000030000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +030000006d04000016c2000014040000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +030000006d04000016c2000000000000,Logitech F310,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +030000006d04000018c2000000000000,Logitech F510,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +030000006d04000019c2000005030000,Logitech F710,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +030000006d0400001fc2000000000000,Logitech F710,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, +030000006d04000018c2000000010000,Logitech RumblePad 2,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3~,start:b9,x:b0,y:b3,platform:Mac OS X, +03000000380700005032000000010000,Mad Catz PS3 Fightpad Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +03000000380700008433000000010000,Mad Catz PS3 Fightstick TE S Plus,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +03000000380700005082000000010000,Mad Catz PS4 Fightpad Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, +03000000380700008483000000010000,Mad Catz PS4 Fightstick TE S Plus,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, +03000000790000000600000007010000,Marvo GT-004,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X, +030000008f0e00001330000011010000,Mayflash Controller Adapter,a:b2,b:b4,back:b16,dpdown:h0.8,dpleft:h0.2,dpright:h0.1,dpup:h0.4,leftshoulder:b12,lefttrigger:b16,leftx:a0,lefty:a2,rightshoulder:b14,rightx:a6~,righty:a4,start:b18,x:b0,y:b6,platform:Mac OS X, +03000000790000004318000000010000,Mayflash GameCube Adapter,a:b4,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a12,leftx:a0,lefty:a4,rightshoulder:b28,righttrigger:a16,rightx:a20,righty:a8,start:b36,x:b8,y:b12,platform:Mac OS X, +03000000790000004418000000010000,Mayflash GameCube Controller,a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Mac OS X, +03000000242f00007300000000020000,Mayflash Magic NS,a:b1,b:b4,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b0,y:b3,platform:Mac OS X, +0300000079000000d218000026010000,Mayflash Magic NS,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X, +03000000d620000010a7000003010000,Mayflash Magic NS,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +030000008f0e00001030000011010000,Mayflash Saturn Adapter,a:b0,b:b2,dpdown:b28,dpleft:b30,dpright:b26,dpup:b24,leftshoulder:b10,lefttrigger:b14,rightshoulder:b12,righttrigger:b4,start:b18,x:b6,y:b8,platform:Mac OS X, +0300000025090000e803000000000000,Mayflash Wii Classic Adapter,a:b1,b:b0,back:b8,dpdown:b13,dpleft:b12,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Mac OS X, +03000000790000000318000000010000,Mayflash Wii DolphinBar,a:b8,b:b12,back:b32,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b44,leftshoulder:b16,lefttrigger:b24,leftx:a0,lefty:a4,rightshoulder:b20,righttrigger:b28,rightx:a8,righty:a12,start:b36,x:b0,y:b4,platform:Mac OS X, +03000000790000000018000000000000,Mayflash Wii U Pro Adapter,a:b4,b:b8,back:b32,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b16,leftstick:b40,lefttrigger:b24,leftx:a0,lefty:a4,rightshoulder:b20,rightstick:b44,righttrigger:b28,rightx:a8,righty:a12,start:b36,x:b0,y:b12,platform:Mac OS X, +03000000790000000018000000010000,Mayflash Wii U Pro Adapter,a:b4,b:b8,back:b32,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b16,leftstick:b40,lefttrigger:b24,leftx:a0,lefty:a4,rightshoulder:b20,rightstick:b44,righttrigger:b28,rightx:a8,righty:a12,start:b36,x:b0,y:b12,platform:Mac OS X, +030000005e0400002800000002010000,Microsoft Dual Strike,a:b3,b:b2,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,rightshoulder:b7,rightx:a0,righty:a1~,start:b5,x:b1,y:b0,platform:Mac OS X, +030000005e0400000300000006010000,Microsoft SideWinder,a:b0,b:b1,back:b9,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b8,x:b3,y:b4,platform:Mac OS X, +030000005e0400000700000006010000,Microsoft SideWinder,a:b0,b:b1,back:b8,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b9,x:b3,y:b4,platform:Mac OS X, +030000005e0400002700000001010000,Microsoft SideWinder Plug and Play,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,lefttrigger:b4,righttrigger:b5,x:b2,y:b3,platform:Mac OS X, +030000004523000015e0000072050000,Mobapad Chitu HD,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X, +03000000d62000007162000001000000,Moga Pro 2,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Mac OS X, +03000000c62400002a89000000010000,MOGA XP5A Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b21,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, +03000000c62400002b89000000010000,MOGA XP5A Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, +03000000632500007505000000020000,NeoGeo mini PAD Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b9,x:b2,y:b3,platform:Mac OS X, +03000000921200004b46000003020000,NES 2-port Adapter,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b11,platform:Mac OS X, +030000001008000001e5000006010000,NEXT SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,righttrigger:b6,start:b9,x:b3,y:b0,platform:Mac OS X, +030000007e0500000920000000000000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X, +030000007e0500000920000001000000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X, +030000007e0500000920000010020000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,platform:Mac OS X, +050000007e05000009200000ff070000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,platform:Mac OS X, +030000007e0500001920000001000000,NSO N64 Controller,+rightx:b8,+righty:b7,-rightx:b3,-righty:b2,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,righttrigger:b10,start:b9,platform:Mac OS X, +030000007e0500001720000001000000,NSO SNES Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b15,start:b9,x:b2,y:b3,platform:Mac OS X, +03000000550900001472000025050000,NVIDIA Controller,a:b0,b:b1,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b4,leftstick:b7,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a5,start:b6,x:b2,y:b3,platform:Mac OS X, +030000004b120000014d000000010000,Nyko Airflo EX,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Mac OS X, +030000006f0e00000901000002010000,PDP PS3 Versus Fighting,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X, +030000008f0e00000300000000000000,Piranha Xtreme PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Mac OS X, +03000000666600006706000088020000,PlayStation Adapter,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a2,righty:a3,start:b11,x:b3,y:b0,platform:Mac OS X, +030000004c050000da0c000000010000,PlayStation Classic Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Mac OS X, +030000004c0500003713000000010000,PlayStation Vita,a:b1,b:b2,back:b8,dpdown:b13,dpleft:b15,dpright:b14,dpup:b12,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Mac OS X, +03000000d620000011a7000000020000,PowerA Core Plus Gamecube Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X, +03000000d620000011a7000010050000,PowerA Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +03000000d62000006dca000000010000,PowerA Pro Ex,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +03000000100800000300000006010000,PS2 Adapter,a:b2,b:b1,back:b8,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a4,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X, +030000004c0500006802000000000000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Mac OS X, +030000004c0500006802000000010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Mac OS X, +030000004c0500006802000072050000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Mac OS X, +030000004c050000a00b000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, +030000004c050000c405000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, +030000004c050000c405000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, +030000004c050000cc09000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, +0300004b4c0500005f0e000000010000,PS5 Access Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b14,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X, +030000004c050000e60c000000010000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b14,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X, +030000004c050000f20d000000010000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b14,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X, +050000004c050000e60c000000010000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X, +050000004c050000f20d000000010000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X, +030000005e040000e002000001000000,PXN P30 Pro Mobile,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Mac OS X, +03000000222c00000225000000010000,Qanba Dragon Arcade Joystick (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +03000000222c00000020000000010000,Qanba Drone Arcade Stick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, +030000009b2800005600000020020000,Raphnet SNES Adapter,a:b1,b:b4,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b3,x:b0,y:b5,platform:Mac OS X, +030000009b2800008000000022020000,Raphnet Wii Classic Adapter,a:b1,b:b4,back:b2,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,guide:b10,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a3,righty:a4,start:b3,x:b0,y:b5,platform:Mac OS X, +030000008916000000fd000000000000,Razer Onza TE,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, +03000000321500000204000000010000,Razer Panthera PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +03000000321500000104000000010000,Razer Panthera PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, +03000000321500000010000000010000,Razer Raiju,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, +03000000321500000507000001010000,Razer Raiju Mobile,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b21,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, +03000000321500000011000000010000,Razer Raion PS4 Fightpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, +03000000321500000009000000020000,Razer Serval,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Mac OS X, +030000003215000000090000163a0000,Razer Serval,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Mac OS X, +0300000032150000030a000000000000,Razer Wildcat,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, +03000000632500008005000000010000,Redgear,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X, +03000000921200004547000000020000,Retro Bit Sega Genesis Controller Adapter,a:b0,b:b2,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,lefttrigger:b14,rightshoulder:b10,righttrigger:b4,start:b12,x:b6,y:b8,platform:Mac OS X, +03000000790000001100000000000000,Retro Controller,a:b1,b:b2,back:b8,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,leftshoulder:b6,lefttrigger:b7,rightshoulder:b4,righttrigger:b5,start:b9,x:b0,y:b3,platform:Mac OS X, +03000000790000001100000005010000,Retro Controller,a:b1,b:b2,back:b8,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,leftshoulder:b6,lefttrigger:b7,rightshoulder:b5,righttrigger:b4,start:b9,x:b0,y:b3,platform:Mac OS X, +03000000830500006020000000010000,Retro Controller,a:b0,b:b1,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b8,righttrigger:b9,start:b7,x:b2,y:b3,platform:Mac OS X, +0300000003040000c197000000000000,Retrode Adapter,a:b0,b:b4,back:b2,dpdown:+a4,dpleft:-a0,dpright:+a0,dpup:-a4,leftshoulder:b6,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Mac OS X, +03000000790000001100000006010000,Retrolink SNES Controller,a:b2,b:b1,back:b8,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Mac OS X, +03000000341200000400000000000000,RetroUSB N64 RetroPort,+rightx:b8,+righty:b10,-rightx:b9,-righty:b11,a:b7,b:b6,dpdown:b2,dpleft:b1,dpright:b0,dpup:b3,leftshoulder:b13,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b12,start:b4,platform:Mac OS X, +030000006b140000010d000000010000,Revolution Pro Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, +030000006b140000130d000000010000,Revolution Pro Controller 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, +030000004c0500006802000002100000,Rii RK707,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b2,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b3,righttrigger:b9,rightx:a2,righty:a3,start:b1,x:b15,y:b12,platform:Mac OS X, +030000006f0e00008701000005010000,Rock Candy Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +03000000c6240000fefa000000000000,Rock Candy PS3,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, +03000000e804000000a000001b010000,Samsung EIGP20,a:b1,b:b3,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b20,leftshoulder:b11,leftx:a1,lefty:a3,rightshoulder:b12,rightx:a4,righty:a5,start:b16,x:b7,y:b9,platform:Mac OS X, +03000000730700000401000000010000,Sanwa PlayOnline Mobile,a:b0,b:b1,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,start:b3,platform:Mac OS X, +03000000a30c00002500000006020000,Sega Genesis Mini 3B Controller,a:b2,b:b1,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,righttrigger:b5,start:b9,platform:Mac OS X, +03000000811700007e05000000000000,Sega Saturn,a:b2,b:b4,dpdown:b16,dpleft:b15,dpright:b14,dpup:b17,leftshoulder:b8,lefttrigger:a5,leftx:a0,lefty:a2,rightshoulder:b9,righttrigger:a4,start:b13,x:b0,y:b6,platform:Mac OS X, +03000000b40400000a01000000000000,Sega Saturn,a:b0,b:b1,back:b5,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,guide:b2,leftshoulder:b6,rightshoulder:b7,start:b8,x:b3,y:b4,platform:Mac OS X, +030000003512000021ab000000000000,SFC30 Joystick,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X, +0300000000f00000f100000000000000,SNES RetroPort,a:b2,b:b3,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b5,rightshoulder:b7,start:b6,x:b0,y:b1,platform:Mac OS X, +030000004c050000a00b000000000000,Sony DualShock 4 Adapter,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, +030000004c050000cc09000000000000,Sony DualShock 4 V2,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, +03000000d11800000094000000010000,Stadia Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Mac OS X, +030000005e0400008e02000001000000,Steam Virtual Gamepad,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, +03000000110100002014000000000000,SteelSeries Nimbus,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,x:b2,y:b3,platform:Mac OS X, +03000000110100002014000001000000,SteelSeries Nimbus,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,x:b2,y:b3,platform:Mac OS X, +03000000381000002014000001000000,SteelSeries Nimbus,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,x:b2,y:b3,platform:Mac OS X, +05000000484944204465766963650000,SteelSeries Nimbus Plus,a:b0,b:b1,back:b15,dpdown:b11,dpleft:b13,dpright:b12,dpup:b10,guide:b16,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3~,start:b14,x:b2,y:b3,platform:Mac OS X, +050000004e696d6275732b0000000000,SteelSeries Nimbus Plus,a:b0,b:b1,back:b15,dpdown:b11,dpleft:b13,dpright:b12,dpup:b10,guide:b16,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3~,start:b14,x:b2,y:b3,platform:Mac OS X, +03000000381000003014000000000000,SteelSeries Stratus Duo,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, +03000000381000003114000000000000,SteelSeries Stratus Duo,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, +03000000110100001714000000000000,SteelSeries Stratus XL,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,start:b12,x:b2,y:b3,platform:Mac OS X, +03000000110100001714000020010000,SteelSeries Stratus XL,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,start:b12,x:b2,y:b3,platform:Mac OS X, +030000000d0f0000f600000000010000,Switch Hori Pad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X, +03000000457500002211000000010000,SZMY Power PC Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +03000000e40a00000307000001000000,Taito Egret II Mini Control Panel,a:b4,b:b2,back:b6,guide:b9,leftx:a0,lefty:a1,rightshoulder:b0,righttrigger:b1,start:b7,x:b8,y:b3,platform:Mac OS X, +03000000e40a00000207000001000000,Taito Egret II Mini Controller,a:b4,b:b2,back:b6,guide:b9,leftx:a0,lefty:a1,rightshoulder:b0,righttrigger:b1,start:b7,x:b8,y:b3,platform:Mac OS X, +03000000790000001c18000003100000,TGZ Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, +03000000591c00002400000021000000,THEC64 Joystick,a:b0,b:b1,back:b6,leftshoulder:b4,leftx:a0,lefty:a4,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Mac OS X, +03000000591c00002600000021000000,THEGamepad,a:b2,b:b1,back:b6,dpdown:+a4,dpleft:-a0,dpright:+a0,dpup:-a4,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b0,platform:Mac OS X, +030000004f04000015b3000000000000,Thrustmaster Dual Analog 3.2,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Mac OS X, +030000004f0400000ed0000000020000,ThrustMaster eSwap Pro Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, +030000004f04000000b3000000000000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b11,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b1,y:b3,platform:Mac OS X, +03000000571d00002100000021000000,Tomee NES Controller Adapter,a:b1,b:b0,back:b2,dpdown:+a4,dpleft:-a0,dpright:+a0,dpup:-a4,start:b3,platform:Mac OS X, +03000000bd12000015d0000000010000,Tomee Retro Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Mac OS X, +03000000bd12000015d0000000000000,Tomee SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Mac OS X, +03000000571d00002000000021000000,Tomee SNES Controller Adapter,a:b0,b:b1,back:b6,dpdown:+a4,dpleft:-a0,dpright:+a0,dpup:-a4,leftshoulder:b4,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Mac OS X, +030000005f140000c501000000020000,Trust Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X, +03000000100800000100000000000000,Twin USB Joystick,a:b4,b:b2,back:b16,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b12,leftstick:b20,lefttrigger:b8,leftx:a0,lefty:a2,rightshoulder:b14,rightstick:b22,righttrigger:b10,rightx:a6,righty:a4,start:b18,x:b6,y:b0,platform:Mac OS X, +03000000632500002605000000010000,Uberwith Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, +03000000151900005678000010010000,Uniplay U6,a:b3,b:b6,back:b25,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b17,leftstick:b31,lefttrigger:b21,leftx:a1,lefty:a3,rightshoulder:b19,rightstick:b33,righttrigger:b23,rightx:a4,righty:a5,start:b27,x:b11,y:b13,platform:Mac OS X, +030000006f0e00000302000025040000,Victrix PS4 Pro Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X, +030000006f0e00000702000003060000,Victrix PS4 Pro Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X, +050000005769696d6f74652028303000,Wii Remote,a:b4,b:b5,back:b7,dpdown:b3,dpleft:b0,dpright:b1,dpup:b2,guide:b8,leftshoulder:b11,lefttrigger:b12,leftx:a0,lefty:a1,start:b6,x:b10,y:b9,platform:Mac OS X, +050000005769696d6f74652028313800,Wii U Pro Controller,a:b16,b:b15,back:b7,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b8,leftshoulder:b19,leftstick:b23,lefttrigger:b21,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b24,righttrigger:b22,rightx:a2,righty:a3,start:b6,x:b18,y:b17,platform:Mac OS X, +030000005e0400008e02000000000000,Xbox 360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, +030000006f0e00000104000000000000,Xbox 360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, +03000000c6240000045d000000000000,Xbox 360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, +030000005e0400000a0b000000000000,Xbox Adaptive Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, +030000005e040000050b000003090000,Xbox Elite Controller Series 2,a:b0,b:b1,back:b31,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b53,leftshoulder:b6,leftstick:b13,lefttrigger:a6,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, +030000005e040000130b000011050000,Xbox One Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, +030000005e040000200b000011050000,Xbox One Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, +030000005e040000200b000013050000,Xbox One Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, +030000005e040000200b000015050000,Xbox One Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, +030000005e040000d102000000000000,Xbox One Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, +030000005e040000dd02000000000000,Xbox One Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, +030000005e040000e002000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Mac OS X, +030000005e040000e002000003090000,Xbox One Controller,a:b0,b:b1,back:b16,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, +030000005e040000e302000000000000,Xbox One Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, +030000005e040000ea02000000000000,Xbox One Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, +030000005e040000fd02000003090000,Xbox One Controller,a:b0,b:b1,back:b16,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, +03000000c62400003a54000000000000,Xbox One PowerA Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, +030000005e040000130b000001050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, +030000005e040000130b000005050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, +030000005e040000130b000009050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, +030000005e040000130b000013050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, +030000005e040000130b000015050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, +030000005e040000130b000017050000,Xbox Wireless Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, +030000005e040000220b000017050000,Xbox Wireless Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, +03000000172700004431000029010000,XiaoMi Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a6,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Mac OS X, +03000000120c0000100e000000010000,Zeroplus P4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, +03000000120c0000101e000000010000,Zeroplus P4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, + +# Linux +03000000c82d00000031000011010000,8BitDo Adapter,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +03000000c82d00000951000000010000,8BitDo Dogbone,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightx:a2,righty:a3,start:b11,platform:Linux, +03000000021000000090000011010000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, +03000000c82d00000090000011010000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, +05000000c82d00001038000000010000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, +03000000c82d00001251000011010000,8BitDo Lite 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, +05000000c82d00001251000000010000,8BitDo Lite 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, +03000000c82d00001151000011010000,8BitDo Lite SE,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, +05000000c82d00001151000000010000,8BitDo Lite SE,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, +03000000c82d00000151000000010000,8BitDo M30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +03000000c82d00000650000011010000,8BitDo M30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +05000000c82d00005106000000010000,8BitDo M30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,start:b11,x:b3,y:b4,platform:Linux, +03000000c82d00002090000011010000,8BitDo Micro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, +05000000c82d00002090000000010000,8BitDo Micro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, +03000000c82d00000451000000010000,8BitDo N30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightx:a2,righty:a3,start:b11,platform:Linux, +03000000c82d00001590000011010000,8BitDo N30 Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, +05000000c82d00006528000000010000,8BitDo N30 Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, +05000000c82d00006928000000010000,8BitDo N64,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a3,start:b11,platform:Linux, +05000000c82d00002590000001000000,8BitDo NEOGEO,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +03000000008000000210000011010000,8BitDo NES30,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, +03000000c82d00000310000011010000,8BitDo NES30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b7,lefttrigger:b6,rightshoulder:b9,righttrigger:b8,start:b11,x:b3,y:b4,platform:Linux, +05000000c82d00008010000000010000,8BitDo NES30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b7,lefttrigger:b6,rightshoulder:b9,righttrigger:b8,start:b11,x:b3,y:b4,platform:Linux, +03000000022000000090000011010000,8BitDo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, +03000000c82d00000190000011010000,8BitDo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, +05000000203800000900000000010000,8BitDo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, +05000000c82d00002038000000010000,8BitDo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, +03000000c82d00000751000000010000,8BitDo P30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:a8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +05000000c82d00000851000000010000,8BitDo P30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:a8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +03000000c82d00000660000011010000,8BitDo Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, +03000000c82d00001030000011010000,8BitDo Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, +05000000c82d00000660000000010000,8BitDo Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, +03000000c82d00000020000000000000,8BitDo Pro 2 for Xbox,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +06000000c82d00000020000006010000,8BitDo Pro 2 for Xbox,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000c82d00000131000011010000,8BitDo Receiver,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, +03000000c82d00000231000011010000,8BitDo Receiver,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, +03000000c82d00000331000011010000,8BitDo Receiver,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, +03000000c82d00000431000011010000,8BitDo Receiver,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, +03000000c82d00002867000000010000,8BitDo S30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b3,y:b4,platform:Linux, +05000000c82d00000060000000010000,8BitDo SF30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, +05000000c82d00000061000000010000,8BitDo SF30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, +030000003512000012ab000010010000,8BitDo SFC30,a:b2,b:b1,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b0,platform:Linux, +030000003512000021ab000010010000,8BitDo SFC30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux, +03000000c82d000021ab000010010000,8BitDo SFC30,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux, +05000000102800000900000000010000,8BitDo SFC30,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux, +05000000c82d00003028000000010000,8BitDo SFC30,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux, +05000000c82d00000351000000010000,8BitDo SN30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, +03000000c82d00000160000000000000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Linux, +03000000c82d00000160000011010000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, +03000000c82d00000161000000000000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Linux, +03000000c82d00001290000011010000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Linux, +05000000c82d00000161000000010000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, +05000000c82d00006228000000010000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, +03000000c82d00000260000011010000,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, +05000000c82d00000261000000010000,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, +05000000202800000900000000010000,8BitDo SNES30,a:b1,b:b0,back:b10,dpdown:b122,dpleft:b119,dpright:b120,dpup:b117,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux, +05000000c82d00001230000000010000,8BitDo Ultimate,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +03000000c82d00001530000011010000,8BitDo Ultimate C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +03000000c82d00001630000011010000,8BitDo Ultimate C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +03000000c82d00001730000011010000,8BitDo Ultimate C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +03000000c82d00001130000011010000,8BitDo Ultimate Wired,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b26,paddle1:b24,paddle2:b25,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +03000000c82d00000631000010010000,8BitDo Ultimate Wireless,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000c82d00000760000011010000,8BitDo Ultimate Wireless,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, +03000000c82d00001230000011010000,8BitDo Ultimate Wireless,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b2,paddle2:b5,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +03000000c82d00001330000011010000,8BitDo Ultimate Wireless,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b26,paddle1:b23,paddle2:b19,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +03000000c82d00000631000014010000,8BitDo Ultimate Wireless Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000c82d00000121000011010000,8BitDo Xbox One SN30 Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +05000000c82d00000121000000010000,8BitDo Xbox One SN30 Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +05000000a00500003232000001000000,8BitDo Zero,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Linux, +05000000a00500003232000008010000,8BitDo Zero,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Linux, +03000000c82d00001890000011010000,8BitDo Zero 2,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux, +050000005e040000e002000030110000,8BitDo Zero 2,a:b0,b:b1,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Linux, +05000000c82d00003032000000010000,8BitDo Zero 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, +03000000c01100000355000011010000,Acrux Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +030000006f0e00008801000011010000,Afterglow Deluxe Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +030000006f0e00003901000000430000,Afterglow Prismatic Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000006f0e00003901000013020000,Afterglow Prismatic Controller 048-007-NA,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000006f0e00001302000000010000,Afterglow Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000006f0e00003901000020060000,Afterglow Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000100000008200000011010000,Akishop Customs PS360,a:b1,b:b2,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, +030000007c1800000006000010010000,Alienware Dual Compatible Game PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b3,platform:Linux, +05000000491900000204000021000000,Amazon Fire Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b17,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b12,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +03000000491900001904000011010000,Amazon Luna Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b9,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b7,x:b2,y:b3,platform:Linux, +05000000710100001904000000010000,Amazon Luna Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Linux, +0300000008100000e501000001010000,Anbernic Gamepad,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a4,start:b11,x:b3,y:b4,platform:Linux, +03000000790000003018000011010000,Arcade Fightstick F300,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, +03000000a30c00002700000011010000,Astro City Mini,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Linux, +03000000a30c00002800000011010000,Astro City Mini,a:b2,b:b1,back:b8,leftx:a0,lefty:a1,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Linux, +05000000050b00000045000031000000,ASUS Gamepad,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b10,x:b2,y:b3,platform:Linux, +05000000050b00000045000040000000,ASUS Gamepad,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b10,x:b2,y:b3,platform:Linux, +03000000050b00000579000011010000,ASUS ROG Kunai 3,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b36,paddle1:b52,paddle2:b53,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +05000000050b00000679000000010000,ASUS ROG Kunai 3,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b21,paddle1:b22,paddle2:b23,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +03000000503200000110000000000000,Atari VCS Classic Controller,a:b0,b:b1,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b4,start:b3,platform:Linux, +03000000503200000110000011010000,Atari VCS Classic Controller,a:b0,b:b1,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b4,start:b3,platform:Linux, +05000000503200000110000000000000,Atari VCS Classic Controller,a:b0,b:b1,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b4,start:b3,platform:Linux, +05000000503200000110000044010000,Atari VCS Classic Controller,a:b0,b:b1,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b4,start:b3,platform:Linux, +05000000503200000110000046010000,Atari VCS Classic Controller,a:b0,b:b1,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b4,start:b3,platform:Linux, +03000000503200000210000000000000,Atari VCS Modern Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a4,rightx:a2,righty:a3,start:b8,x:b2,y:b3,platform:Linux, +03000000503200000210000011010000,Atari VCS Modern Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b2,platform:Linux, +05000000503200000210000000000000,Atari VCS Modern Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b2,platform:Linux, +05000000503200000210000045010000,Atari VCS Modern Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b2,platform:Linux, +05000000503200000210000046010000,Atari VCS Modern Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b2,platform:Linux, +05000000503200000210000047010000,Atari VCS Modern Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:+a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:-a4,rightx:a2,righty:a3,start:b8,x:b2,y:b3,platform:Linux, +030000008a3500000201000011010000,Backbone One,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +030000008a3500000202000011010000,Backbone One,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +030000008a3500000302000011010000,Backbone One,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +030000008a3500000402000011010000,Backbone One,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +03000000c62400001b89000011010000,BDA MOGA XP5X Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +03000000d62000002a79000011010000,BDA PS4 Fightpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +03000000c21100000791000011010000,Be1 GC101 Controller 1.03,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, +03000000c31100000791000011010000,Be1 GC101 Controller 1.03,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +030000005e0400008e02000003030000,Be1 GC101 Xbox 360,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000bc2000004d50000011010000,Beitong A1T2 BFM,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +05000000bc2000000055000001000000,Betop AX1 BFM,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +03000000bc2000006412000011010000,Betop Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b30,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, +030000006b1400000209000011010000,Bigben,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +03000000120c0000200e000011010000,Brook Mars PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +03000000120c0000210e000011010000,Brook Mars PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +03000000120c0000f70e000011010000,Brook Universal Fighting Board,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, +03000000e82000006058000001010000,Cideko AK08b,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, +03000000af1e00002400000010010000,Clockwork Pi DevTerm,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,start:b9,x:b3,y:b0,platform:Linux, +030000000b0400003365000000010000,Competition Pro,a:b0,b:b1,back:b2,leftx:a0,lefty:a1,start:b3,platform:Linux, +03000000260900008888000000010000,Cyber Gadget GameCube Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:a5,rightx:a2,righty:a3~,start:b7,x:b2,y:b3,platform:Linux, +03000000a306000022f6000011010000,Cyborg V3 Rumble,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:+a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:-a3,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Linux, +03000000791d00000103000010010000,Dual Box Wii Classic Adapter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, +030000006f0e00003001000001010000,EA Sports PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +03000000c11100000191000011010000,EasySMX,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, +03000000242f00009100000000010000,EasySMX ESM-9101,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000006e0500000320000010010000,Elecom U3613M,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b0,y:b1,platform:Linux, +030000006e0500000720000010010000,Elecom W01U,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b1,platform:Linux, +030000007d0400000640000010010000,Eliminator AfterShock,a:b1,b:b2,back:b9,dpdown:+a3,dpleft:-a5,dpright:+a5,dpup:-a3,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a4,righty:a2,start:b8,x:b0,y:b3,platform:Linux, +03000000430b00000300000000010000,EMS Production PS2 Adapter,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a5,righty:a2,start:b9,x:b3,y:b0,platform:Linux, +030000006f0e00008401000011010000,Faceoff Deluxe Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +030000006f0e00008101000011010000,Faceoff Deluxe Pro Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +030000006f0e00008001000011010000,Faceoff Pro Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +03005036852100000201000010010000,Final Fantasy XIV Online Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +03000000b40400001124000011010000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b12,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b14,paddle1:b2,paddle2:b5,paddle3:b16,paddle4:b17,rightshoulder:b7,rightstick:b13,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +03000000b40400001224000011010000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b12,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b2,paddle1:b16,paddle2:b17,paddle3:b14,paddle4:b15,rightshoulder:b7,rightstick:b13,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +05000000151900004000000001000000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b21,leftshoulder:b6,leftstick:b12,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b14,paddle1:b2,paddle2:b5,paddle3:b16,paddle4:b17,rightshoulder:b7,rightstick:b13,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +030000007e0500003703000000000000,GameCube Adapter,a:b0,b:b1,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b2,platform:Linux, +19000000030000000300000002030000,GameForce Controller,a:b1,b:b0,back:b8,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,guide:b16,leftshoulder:b4,leftstick:b14,lefttrigger:b6,leftx:a1,lefty:a0,rightshoulder:b5,rightstick:b15,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Linux, +03000000ac0500005b05000010010000,GameSir G3w,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, +03000000bc2000000055000011010000,GameSir G3w,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +03000000558500001b06000010010000,GameSir G4 Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +05000000ac0500002d0200001b010000,GameSir G4s,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b33,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +03000000ac0500007a05000011010000,GameSir G5,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b16,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +03000000bc2000005656000011010000,GameSir T4w,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +03000000ac0500001a06000011010000,GameSir-T3 2.02,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, +030000006f0e00000104000000010000,Gamestop Logic3 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000008f0e00000800000010010000,Gasia PlayStation Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, +03000000451300000010000010010000,Genius Maxfire Grandias 12,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, +190000004b4800000010000000010000,GO-Advance Controller,a:b1,b:b0,back:b10,dpdown:b7,dpleft:b8,dpright:b9,dpup:b6,leftshoulder:b4,lefttrigger:b12,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b13,start:b15,x:b2,y:b3,platform:Linux, +190000004b4800000010000001010000,GO-Advance Controller,a:b1,b:b0,back:b12,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,leftshoulder:b4,leftstick:b13,lefttrigger:b14,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b16,righttrigger:b15,start:b17,x:b2,y:b3,platform:Linux, +190000004b4800000011000000010000,GO-Super Controller,a:b1,b:b0,back:b12,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b16,leftshoulder:b4,leftstick:b14,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b15,righttrigger:b7,rightx:a2,righty:a3,start:b13,x:b2,y:b3,platform:Linux, +03000000f0250000c183000010010000,Goodbetterbest Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +0300000079000000d418000000010000,GPD Win 2 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000005e0400008e02000001010000,GPD Win Max 2 (6800U) Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000007d0400000540000000010000,Gravis Eliminator Pro,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, +03000000280400000140000000010000,Gravis GamePad Pro,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, +030000008f0e00000610000000010000,GreenAsia Electronics Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a3,righty:a2,start:b11,x:b3,y:b0,platform:Linux, +030000008f0e00001200000010010000,GreenAsia Joystick,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Linux, +0500000047532067616d657061640000,GS gamepad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, +03000000f0250000c383000010010000,GT VX2,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, +06000000adde0000efbe000002010000,Hidromancer Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000d81400000862000011010000,HitBox PS3 PC Analog Mode,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,guide:b9,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b12,x:b0,y:b3,platform:Linux, +03000000c9110000f055000011010000,HJC Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, +030000000d0f00006d00000020010000,Hori EDGE 301,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:+a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000000d0f00008400000011010000,Hori Fighting Commander,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +030000000d0f00005f00000011010000,Hori Fighting Commander 4 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +030000000d0f00005e00000011010000,Hori Fighting Commander 4 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +030000000d0f00005001000009040000,Hori Fighting Commander OCTA Xbox One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000000d0f00008500000010010000,Hori Fighting Commander PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +030000000d0f00008600000002010000,Hori Fighting Commander Xbox 360,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, +030000000d0f00003701000013010000,Hori Fighting Stick Mini,a:b1,b:b0,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,start:b7,x:b3,y:b2,platform:Linux, +030000000d0f00008800000011010000,Hori Fighting Stick mini 4 (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, +030000000d0f00008700000011010000,Hori Fighting Stick mini 4 (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,rightshoulder:b5,rightstick:b11,righttrigger:a4,start:b9,x:b0,y:b3,platform:Linux, +030000000d0f00001000000011010000,Hori Fightstick 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, +03000000ad1b000003f5000033050000,Hori Fightstick VX,+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b8,guide:b10,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b2,y:b3,platform:Linux, +030000000d0f00004d00000011010000,Hori Gem Pad 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +03000000ad1b000001f5000033050000,Hori Pad EX Turbo 2,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000000d0f00003801000011010000,Hori PC Engine Mini Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b9,platform:Linux, +030000000d0f00009200000011010000,Hori Pokken Tournament DX Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, +030000000d0f00001100000011010000,Hori Real Arcade Pro 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +030000000d0f00002200000011010000,Hori Real Arcade Pro 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, +030000000d0f00006a00000011010000,Hori Real Arcade Pro 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +030000000d0f00006b00000011010000,Hori Real Arcade Pro 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +030000000d0f00001600000000010000,Hori Real Arcade Pro EXSE,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b2,y:b3,platform:Linux, +030000000d0f0000aa00000011010000,Hori Real Arcade Pro for Nintendo Switch,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, +030000000d0f00008501000017010000,Hori Split Pad Fit,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000000d0f00008501000015010000,Hori Switch Split Pad Pro,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000000d0f00006e00000011010000,Horipad 4 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +030000000d0f00006600000011010000,Horipad 4 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +030000000d0f0000ee00000011010000,Horipad Mini 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +030000000d0f0000c100000011010000,Horipad Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +030000000d0f00006700000001010000,Horipad One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +050000000d0f0000f600000001000000,Horipad Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, +03000000341a000005f7000010010000,HuiJia GameCube Controller Adapter,a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Linux, +05000000242e00000b20000001000000,Hyperkin Admiral N64 Controller,+rightx:b11,+righty:b13,-rightx:b8,-righty:b12,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b14,leftx:a0,lefty:a1,rightshoulder:b5,start:b9,platform:Linux, +03000000242e0000ff0b000011010000,Hyperkin N64 Adapter,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a2,righty:a3,start:b9,platform:Linux, +03000000242e00006a38000010010000,Hyperkin Trooper 2,a:b0,b:b1,back:b4,leftshoulder:b2,leftx:a0,lefty:a1,rightshoulder:b3,start:b5,platform:Linux, +03000000242e00008816000001010000,Hyperkin X91,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000f00300008d03000011010000,HyperX Clutch,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +03000000830500006020000010010000,iBuffalo Super Famicom Controller,a:b1,b:b0,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Linux, +030000008f0e00001330000001010000,iCode Retro Adapter,b:b3,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b9,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b1,start:b7,x:b2,y:b0,platform:Linux, +050000006964726f69643a636f6e0000,idroidcon Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +03000000b50700001503000010010000,Impact,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Linux, +03000000d80400008200000003000000,IMS PCU0,a:b1,b:b0,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,start:b5,x:b3,y:b2,platform:Linux, +03000000120c00000500000010010000,InterAct AxisPad,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,start:b11,x:b0,y:b1,platform:Linux, +03000000ef0500000300000000010000,InterAct AxisPad,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,start:b11,x:b0,y:b1,platform:Linux, +03000000fd0500000030000000010000,InterAct GoPad,a:b3,b:b4,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,x:b0,y:b1,platform:Linux, +03000000fd0500002a26000000010000,InterAct HammerHead FX,a:b3,b:b4,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b2,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b5,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b0,y:b1,platform:Linux, +0500000049190000020400001b010000,Ipega PG 9069,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b161,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +03000000632500007505000011010000,Ipega PG 9099,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, +0500000049190000030400001b010000,Ipega PG9099,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +05000000491900000204000000000000,Ipega PG9118,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +03000000300f00001001000010010000,Jess Tech Dual Analog Rumble,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Linux, +03000000300f00000b01000010010000,Jess Tech GGE909 PC Recoil,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux, +03000000ba2200002010000001010000,Jess Technology Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux, +030000007e0500000620000001000000,Joy-Con (L),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b13,leftshoulder:b4,leftstick:b10,rightshoulder:b5,start:b8,x:b2,y:b3,platform:Linux, +050000007e0500000620000001000000,Joy-Con (L),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b13,leftshoulder:b4,leftstick:b10,rightshoulder:b5,start:b8,x:b2,y:b3,platform:Linux, +030000007e0500000720000001000000,Joy-Con (R),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b12,leftshoulder:b4,leftstick:b11,rightshoulder:b5,start:b9,x:b2,y:b3,platform:Linux, +050000007e0500000720000001000000,Joy-Con (R),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b12,leftshoulder:b4,leftstick:b11,rightshoulder:b5,start:b9,x:b2,y:b3,platform:Linux, +03000000bd12000003c0000010010000,Joypad Alpha Shock,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +03000000242f00002d00000011010000,JYS Adapter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, +03000000242f00008a00000011010000,JYS Adapter,a:b1,b:b4,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b0,y:b3,platform:Linux, +030000006f0e00000103000000020000,Logic3 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000006d040000d1ca000000000000,Logitech Chillstream,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +030000006d040000d1ca000011010000,Logitech Chillstream,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +030000006d04000019c2000010010000,Logitech Cordless RumblePad 2,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +030000006d04000016c2000010010000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +030000006d04000016c2000011010000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +030000006d0400001dc2000014400000,Logitech F310,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000006d0400001ec2000019200000,Logitech F510,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000006d0400001ec2000020200000,Logitech F510,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000006d04000019c2000011010000,Logitech F710,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +030000006d0400001fc2000005030000,Logitech F710,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000006d04000018c2000010010000,Logitech RumblePad 2,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +030000006d04000011c2000010010000,Logitech WingMan Cordless RumblePad,a:b0,b:b1,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b6,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b10,rightx:a3,righty:a4,start:b8,x:b3,y:b4,platform:Linux, +030000006d0400000ac2000010010000,Logitech WingMan RumblePad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,rightx:a3,righty:a4,x:b3,y:b4,platform:Linux, +05000000380700006652000025010000,Mad Catz CTRLR,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +03000000380700008532000010010000,Mad Catz Fightpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b5,rightshoulder:b6,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, +03000000380700005032000011010000,Mad Catz Fightpad Pro PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +03000000380700005082000011010000,Mad Catz Fightpad Pro PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +03000000ad1b00002ef0000090040000,Mad Catz Fightpad SFxT,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,start:b7,x:b2,y:b3,platform:Linux, +03000000380700008034000011010000,Mad Catz Fightstick PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +03000000380700008084000011010000,Mad Catz Fightstick PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +03000000380700008433000011010000,Mad Catz Fightstick TE S PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +03000000380700008483000011010000,Mad Catz Fightstick TE S PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +03000000380700001888000010010000,Mad Catz Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +03000000380700003888000010010000,Mad Catz Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:a0,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +03000000380700001647000010040000,Mad Catz Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000380700003847000090040000,Mad Catz Xbox 360 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, +03000000ad1b000016f0000090040000,Mad Catz Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000120c00000500000000010000,Manta Dualshock 2,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Linux, +030000008f0e00001330000010010000,Mayflash Controller Adapter,a:b1,b:b2,back:b8,dpdown:h0.8,dpleft:h0.2,dpright:h0.1,dpup:h0.4,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a3~,righty:a2,start:b9,x:b0,y:b3,platform:Linux, +03000000790000004318000010010000,Mayflash GameCube Adapter,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b2,y:b3,platform:Linux, +03000000790000004418000010010000,Mayflash GameCube Controller,a:b1,b:b0,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b2,y:b3,platform:Linux, +03000000242f00007300000011010000,Mayflash Magic NS,a:b1,b:b4,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b0,y:b3,platform:Linux, +0300000079000000d218000011010000,Mayflash Magic NS,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +03000000d620000010a7000011010000,Mayflash Magic NS,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +03000000242f0000f700000001010000,Mayflash Magic S Pro,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000008f0e00001030000010010000,Mayflash Saturn Adapter,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,lefttrigger:b7,rightshoulder:b6,righttrigger:b2,start:b9,x:b3,y:b4,platform:Linux, +0300000025090000e803000001010000,Mayflash Wii Classic Adapter,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:a4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:a5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Linux, +03000000790000000318000011010000,Mayflash Wii DolphinBar,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b1,platform:Linux, +03000000790000000018000011010000,Mayflash Wii U Pro Adapter,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +03000000b50700001203000010010000,Mega World Logic 3 Controller,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Linux, +03000000b50700004f00000000010000,Mega World Logic 3 Controller,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b1,platform:Linux, +03000000780000000600000010010000,Microntek Joystick,a:b2,b:b1,back:b8,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Linux, +030000005e0400002800000000010000,Microsoft Dual Strike,a:b3,b:b2,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,rightshoulder:b7,rightx:a0,righty:a1~,start:b5,x:b1,y:b0,platform:Linux, +030000005e0400000300000000010000,Microsoft SideWinder,a:b0,b:b1,back:b9,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b8,x:b3,y:b4,platform:Linux, +030000005e0400000700000000010000,Microsoft SideWinder,a:b0,b:b1,back:b8,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b9,x:b3,y:b4,platform:Linux, +030000005e0400000e00000000010000,Microsoft SideWinder Freestyle Pro,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,rightshoulder:b7,start:b8,x:b3,y:b4,platform:Linux, +030000005e0400002700000000010000,Microsoft SideWinder Plug and Play,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,lefttrigger:b4,righttrigger:b5,x:b2,y:b3,platform:Linux, +030000005e0400008502000000010000,Microsoft Xbox,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b4,platform:Linux, +030000005e0400008902000021010000,Microsoft Xbox,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b4,platform:Linux, +030000005e0400008e02000001000000,Microsoft Xbox 360,a:b0,b:b1,back:b6,dpdown:h0.1,dpleft:h0.2,dpright:h0.8,dpup:h0.4,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000005e0400008e02000004010000,Microsoft Xbox 360,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000005e0400008e02000056210000,Microsoft Xbox 360,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000005e0400008e02000062230000,Microsoft Xbox 360,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000005e040000d102000001010000,Microsoft Xbox One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000005e040000d102000003020000,Microsoft Xbox One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000005e040000dd02000003020000,Microsoft Xbox One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000005e040000ea02000008040000,Microsoft Xbox One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +060000005e040000120b000009050000,Microsoft Xbox One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000005e040000e302000003020000,Microsoft Xbox One Elite,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000005e040000000b000007040000,Microsoft Xbox One Elite 2,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b12,paddle2:b14,paddle3:b13,paddle4:b15,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000005e040000000b000008040000,Microsoft Xbox One Elite 2,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b12,paddle2:b14,paddle3:b13,paddle4:b15,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +050000005e040000050b000003090000,Microsoft Xbox One Elite 2,a:b0,b:b1,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a6,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +050000005e0400008e02000030110000,Microsoft Xbox One Elite 2,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b13,paddle3:b12,paddle4:b14,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000005e040000120b00000b050000,Microsoft Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000030000000300000002000000,Miroof,a:b1,b:b0,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Linux, +03000000790000001c18000010010000,Mobapad Chitu HD,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +050000004d4f435554452d3035335800,Mocute 053X,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, +05000000e80400006e0400001b010000,Mocute 053X M59,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +050000004d4f435554452d3035305800,Mocute 054X,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +05000000d6200000e589000001000000,Moga 2,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Linux, +05000000d6200000ad0d000001000000,Moga Pro,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Linux, +05000000d62000007162000001000000,Moga Pro 2,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Linux, +03000000c62400002b89000011010000,MOGA XP5A Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +05000000c62400002a89000000010000,MOGA XP5A Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b22,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +05000000c62400001a89000000010000,MOGA XP5X Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +03000000250900006688000000010000,MP8866 Super Dual Box,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Linux, +030000005e0400008e02000010020000,MSI GC20 V2,a:b0,b:b1,back:b6,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000006f0e00001311000011010000,N64 Controller,+rightx:b10,+righty:b3,-rightx:b0,-righty:b11,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,platform:Linux, +030000006b1400000906000014010000,Nacon Asymmetric Wireless PS4 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000006b140000010c000010010000,Nacon GC 400ES,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, +03000000853200000706000012010000,Nacon GC-100,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000000d0f00000900000010010000,Natec Genesis P44,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +030000004f1f00000800000011010000,NeoGeo PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, +0300000092120000474e000000010000,NeoGeo X Arcade Stick,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b9,x:b3,y:b2,platform:Linux, +03000000790000004518000010010000,Nexilux GameCube Controller Adapter,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b2,y:b3,platform:Linux, +030000001008000001e5000010010000,NEXT SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,righttrigger:b6,start:b9,x:b3,y:b0,platform:Linux, +060000007e0500003713000000000000,Nintendo 3DS,a:b0,b:b1,back:b8,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Linux, +030000007e0500003703000000016800,Nintendo GameCube Controller,a:b0,b:b2,dpdown:b6,dpleft:b4,dpright:b5,dpup:b7,lefttrigger:a4,leftx:a0,lefty:a1~,rightshoulder:b9,righttrigger:a5,rightx:a2,righty:a3~,start:b8,x:b1,y:b3,platform:Linux, +03000000790000004618000010010000,Nintendo GameCube Controller Adapter,a:b1,b:b0,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a5~,righty:a2~,start:b9,x:b2,y:b3,platform:Linux, +060000004e696e74656e646f20537700,Nintendo Switch Combined Joy-Cons,a:b0,b:b1,back:b9,dpdown:b15,dpleft:b16,dpright:b17,dpup:b14,guide:b11,leftshoulder:b5,leftstick:b12,lefttrigger:b7,leftx:a0,lefty:a1,misc1:b4,rightshoulder:b6,rightstick:b13,righttrigger:b8,rightx:a2,righty:a3,start:b10,x:b3,y:b2,platform:Linux, +060000007e0500000620000000000000,Nintendo Switch Combined Joy-Cons,a:b0,b:b1,back:b9,dpdown:b15,dpleft:b16,dpright:b17,dpup:b14,guide:b11,leftshoulder:b5,leftstick:b12,lefttrigger:b7,leftx:a0,lefty:a1,misc1:b4,rightshoulder:b6,rightstick:b13,righttrigger:b8,rightx:a2,righty:a3,start:b10,x:b3,y:b2,platform:Linux, +060000007e0500000820000000000000,Nintendo Switch Combined Joy-Cons,a:b0,b:b1,back:b9,dpdown:b15,dpleft:b16,dpright:b17,dpup:b14,guide:b11,leftshoulder:b5,leftstick:b12,lefttrigger:b7,leftx:a0,lefty:a1,misc1:b4,rightshoulder:b6,rightstick:b13,righttrigger:b8,rightx:a2,righty:a3,start:b10,x:b3,y:b2,platform:Linux, +050000004c69632050726f20436f6e00,Nintendo Switch Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, +050000007e0500000620000001800000,Nintendo Switch Left Joy-Con,a:b16,b:b15,back:b4,leftshoulder:b6,leftstick:b12,leftx:a1,lefty:a0~,rightshoulder:b8,start:b9,x:b14,y:b17,platform:Linux, +030000007e0500000920000000026803,Nintendo Switch Pro Controller,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Linux, +030000007e0500000920000011810000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b5,leftstick:b12,lefttrigger:b7,leftx:a0,lefty:a1,misc1:b4,rightshoulder:b6,rightstick:b13,righttrigger:b8,rightx:a2,righty:a3,start:b10,x:b3,y:b2,platform:Linux, +050000007e0500000920000001000000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, +050000007e0500000920000001800000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b5,leftstick:b12,lefttrigger:b7,leftx:a0,lefty:a1,misc1:b4,rightshoulder:b6,rightstick:b13,righttrigger:b8,rightx:a2,righty:a3,start:b10,x:b3,y:b2,platform:Linux, +050000007e0500000720000001800000,Nintendo Switch Right Joy-Con,a:b1,b:b2,back:b9,leftshoulder:b4,leftstick:b10,leftx:a1~,lefty:a0,rightshoulder:b6,start:b8,x:b0,y:b3,platform:Linux, +05000000010000000100000003000000,Nintendo Wii Remote,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, +050000007e0500003003000001000000,Nintendo Wii U Pro Controller,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Linux, +030000000d0500000308000010010000,Nostromo n45 Dual Analog,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b12,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b10,x:b2,y:b3,platform:Linux, +030000007e0500001920000011810000,NSO N64 Controller,+rightx:b10,+righty:b8,-rightx:b9,-righty:b7,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b3,lefttrigger:b2,leftx:a0,lefty:a1,misc1:b12,rightshoulder:b4,righttrigger:b5,start:b6,platform:Linux, +050000007e0500001920000001000000,NSO N64 Controller,+rightx:b8,+righty:b7,-rightx:b3,-righty:b2,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,righttrigger:b10,start:b9,platform:Linux, +050000007e0500001920000001800000,NSO N64 Controller,+rightx:b10,+righty:b8,-rightx:b9,-righty:b7,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b3,lefttrigger:b2,leftx:a0,lefty:a1,misc1:b12,rightshoulder:b4,righttrigger:b5,start:b6,platform:Linux, +030000007e0500001720000011810000,NSO SNES Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b3,y:b2,platform:Linux, +050000007e0500001720000001000000,NSO SNES Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,lefttrigger:b7,rightshoulder:b6,righttrigger:b8,start:b10,x:b3,y:b2,platform:Linux, +050000007e0500001720000001800000,NSO SNES Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b3,y:b2,platform:Linux, +03000000550900001072000011010000,NVIDIA Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b13,leftshoulder:b4,leftstick:b8,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux, +03000000550900001472000011010000,NVIDIA Controller v01.04,a:b0,b:b1,back:b14,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b16,leftshoulder:b4,leftstick:b7,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a5,start:b6,x:b2,y:b3,platform:Linux, +05000000550900001472000001000000,NVIDIA Controller v01.04,a:b0,b:b1,back:b14,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b16,leftshoulder:b4,leftstick:b7,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a5,start:b6,x:b2,y:b3,platform:Linux, +030000004b120000014d000000010000,NYKO Airflo EX,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Linux, +03000000451300000830000010010000,NYKO CORE,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +19000000010000000100000001010000,ODROID Go 2,a:b1,b:b0,dpdown:b7,dpleft:b8,dpright:b9,dpup:b6,guide:b10,leftshoulder:b4,leftstick:b12,lefttrigger:b11,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b13,righttrigger:b14,start:b15,x:b2,y:b3,platform:Linux, +19000000010000000200000011000000,ODROID Go 2,a:b1,b:b0,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b12,leftshoulder:b4,leftstick:b14,lefttrigger:b13,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b15,righttrigger:b16,start:b17,x:b2,y:b3,platform:Linux, +05000000362800000100000002010000,OUYA Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b2,platform:Linux, +05000000362800000100000003010000,OUYA Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b2,platform:Linux, +05000000362800000100000004010000,OUYA Controller,a:b0,b:b3,back:b14,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,leftshoulder:b4,leftstick:b6,lefttrigger:b12,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:b13,rightx:a3,righty:a4,start:b16,x:b1,y:b2,platform:Linux, +03000000830500005020000010010000,Padix Rockfire PlayStation Bridge,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b2,y:b3,platform:Linux, +03000000ff1100003133000010010000,PC Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, +030000006f0e0000b802000001010000,PDP Afterglow Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000006f0e0000b802000013020000,PDP Afterglow Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000006f0e00006401000001010000,PDP Battlefield One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000006f0e0000d702000006640000,PDP Black Camo Wired Xbox Series X Controller,a:b0,b:b1,back:b6,dpdown:b13,dpleft:b14,dpright:b13,dpup:b14,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000006f0e00003101000000010000,PDP EA Sports Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000006f0e00008501000011010000,PDP Fightpad Pro Gamecube Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, +030000006f0e0000c802000012010000,PDP Kingdom Hearts Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000006f0e00002801000011010000,PDP PS3 Rock Candy Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +030000006f0e00000901000011010000,PDP PS3 Versus Fighting,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, +030000006f0e00002f01000011010000,PDP Wired PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +03000000ad1b000004f9000000010000,PDP Xbox 360 Versus Fighting,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,start:b7,x:b2,y:b3,platform:Linux, +030000006f0e0000a802000023020000,PDP Xbox One Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, +030000006f0e0000a702000023020000,PDP Xbox One Raven Black,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000006f0e0000d802000006640000,PDP Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000006f0e0000ef02000007640000,PDP Xbox Series Kinetic Wired Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000666600006706000000010000,PlayStation Adapter,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a2,righty:a3,start:b11,x:b3,y:b0,platform:Linux, +030000004c050000da0c000011010000,PlayStation Controller,a:b2,b:b1,back:b8,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Linux, +03000000d9040000160f000000010000,PlayStation Controller Adapter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux, +030000004c0500003713000011010000,PlayStation Vita,a:b1,b:b2,back:b8,dpdown:b13,dpleft:b15,dpright:b14,dpup:b12,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Linux, +03000000c62400000053000000010000,PowerA,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000c62400003a54000001010000,PowerA 1428124-01,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000d620000011a7000011010000,PowerA Core Plus Gamecube Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, +03000000dd62000015a7000011010000,PowerA Fusion Nintendo Switch Arcade Stick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +03000000d620000012a7000011010000,PowerA Fusion Nintendo Switch Fight Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +03000000d62000000140000001010000,PowerA Fusion Pro 2 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000dd62000016a7000000000000,PowerA Fusion Pro Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +03000000c62400001a53000000010000,PowerA Mini Pro Ex,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000d620000013a7000011010000,PowerA Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +03000000d62000006dca000011010000,PowerA Pro Ex,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +03000000d620000014a7000011010000,PowerA Spectra Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +03000000c62400001a58000001010000,PowerA Xbox One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000d62000000220000001010000,PowerA Xbox One Controller,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Linux, +03000000d62000000228000001010000,PowerA Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000c62400001a54000001010000,PowerA Xbox One Mini Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000d62000000240000001010000,PowerA Xbox One Spectra Infinity,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000d62000000f20000001010000,PowerA Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b7,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000006d040000d2ca000011010000,Precision Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +03000000ff1100004133000010010000,PS2 Controller,a:b2,b:b1,back:b8,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Linux, +03000000341a00003608000011010000,PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +030000004c0500006802000010010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux, +030000004c0500006802000010810000,PS3 Controller,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux, +030000004c0500006802000011010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux, +030000004c0500006802000011810000,PS3 Controller,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux, +030000005f1400003102000010010000,PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, +030000006f0e00001402000011010000,PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +030000008f0e00000300000010010000,PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, +050000004c0500006802000000000000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux, +050000004c0500006802000000010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:a12,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:a13,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux, +050000004c0500006802000000800000,PS3 Controller,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux, +050000004c0500006802000000810000,PS3 Controller,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux, +05000000504c415953544154494f4e00,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux, +060000004c0500006802000000010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux, +030000004c050000a00b000011010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +030000004c050000a00b000011810000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux, +030000004c050000c405000011010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +030000004c050000c405000011810000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux, +030000004c050000cc09000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +030000004c050000cc09000011010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +030000004c050000cc09000011810000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux, +03000000c01100000140000011010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +050000004c050000c405000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +050000004c050000c405000000810000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux, +050000004c050000c405000001800000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux, +050000004c050000cc09000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +050000004c050000cc09000000810000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux, +050000004c050000cc09000001800000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux, +0300004b4c0500005f0e000011010000,PS5 Access Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b14,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux, +030000004c050000e60c000011010000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b14,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux, +030000004c050000e60c000011810000,PS5 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux, +030000004c050000f20d000011010000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b14,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux, +050000004c050000e60c000000010000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux, +050000004c050000e60c000000810000,PS5 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux, +050000004c050000f20d000000010000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux, +03000000300f00001211000011010000,Qanba Arcade Joystick,a:b2,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b5,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b6,start:b9,x:b1,y:b3,platform:Linux, +03000000222c00000225000011010000,Qanba Dragon Arcade Joystick (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +03000000222c00000025000011010000,Qanba Dragon Arcade Joystick (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +03000000222c00000020000011010000,Qanba Drone Arcade PS4 Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,rightshoulder:b5,righttrigger:a4,start:b9,x:b0,y:b3,platform:Linux, +03000000300f00001210000010010000,Qanba Joystick Plus,a:b0,b:b1,back:b8,leftshoulder:b5,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b4,righttrigger:b6,start:b9,x:b2,y:b3,platform:Linux, +03000000222c00000223000011010000,Qanba Obsidian Arcade Joystick (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +03000000222c00000023000011010000,Qanba Obsidian Arcade Joystick (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +030000009b2800000300000001010000,Raphnet 4nes4snes,a:b0,b:b4,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Linux, +030000009b2800004200000001010000,Raphnet Dual NES Adapter,a:b0,b:b1,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,start:b3,platform:Linux, +030000009b2800003200000001010000,Raphnet GC and N64 Adapter,a:b0,b:b7,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,rightx:a3,righty:a4,start:b3,x:b1,y:b8,platform:Linux, +030000009b2800006000000001010000,Raphnet GC and N64 Adapter,a:b0,b:b7,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,rightx:a3,righty:a4,start:b3,x:b1,y:b8,platform:Linux, +030000009b2800008000000020020000,Raphnet Wii Classic Adapter,a:b1,b:b4,back:b2,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,leftshoulder:b6,rightshoulder:b7,start:b3,x:b0,y:b5,platform:Linux, +03000000f8270000bf0b000011010000,Razer Kishi,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +030000008916000001fd000024010000,Razer Onza Classic Edition,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000321500000204000011010000,Razer Panthera PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +03000000321500000104000011010000,Razer Panthera PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +03000000321500000810000011010000,Razer Panthera PS4 Evo Arcade Stick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b13,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +03000000321500000010000011010000,Razer Raiju,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +03000000321500000507000000010000,Razer Raiju Mobile,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b21,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +05000000321500000a10000001000000,Razer Raiju Tournament Edition,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b13,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +03000000321500000011000011010000,Razer Raion PS4 Fightpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +030000008916000000fe000024010000,Razer Sabertooth,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000c6240000045d000024010000,Razer Sabertooth,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000c6240000045d000025010000,Razer Sabertooth,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000321500000009000011010000,Razer Serval,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux, +050000003215000000090000163a0000,Razer Serval,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux, +0300000032150000030a000001010000,Razer Wildcat,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000321500000b10000011010000,Razer Wolverine PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux, +03000000790000001100000010010000,Retro Controller,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b4,righttrigger:b5,start:b9,x:b0,y:b3,platform:Linux, +0300000003040000c197000011010000,Retrode Adapter,a:b0,b:b4,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Linux, +190000004b4800000111000000010000,RetroGame Joypad,a:b1,b:b0,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, +0300000081170000990a000001010000,Retronic Adapter,a:b0,leftx:a0,lefty:a1,platform:Linux, +0300000000f000000300000000010000,RetroPad,a:b1,b:b5,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Linux, +00000000526574726f53746f6e653200,RetroStone 2 Controller,a:b1,b:b0,back:b10,dpdown:b15,dpleft:b16,dpright:b17,dpup:b14,leftshoulder:b6,lefttrigger:b8,rightshoulder:b7,righttrigger:b9,start:b11,x:b4,y:b3,platform:Linux, +03000000341200000400000000010000,RetroUSB N64 RetroPort,+rightx:b8,+righty:b10,-rightx:b9,-righty:b11,a:b7,b:b6,dpdown:b2,dpleft:b1,dpright:b0,dpup:b3,leftshoulder:b13,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b12,start:b4,platform:Linux, +030000006b140000010d000011010000,Revolution Pro Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +030000006b140000130d000011010000,Revolution Pro Controller 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +030000006f0e00001f01000000010000,Rock Candy,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000006f0e00008701000011010000,Rock Candy Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +030000006f0e00001e01000011010000,Rock Candy PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +03000000c6240000fefa000000010000,Rock Candy Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000006f0e00004601000001010000,Rock Candy Xbox One Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000a306000023f6000011010000,Saitek Cyborg V1 PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Linux, +03000000a30600001005000000010000,Saitek P150,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b7,lefttrigger:b6,rightshoulder:b2,righttrigger:b5,x:b3,y:b4,platform:Linux, +03000000a30600000701000000010000,Saitek P220,a:b2,b:b3,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b4,righttrigger:b5,x:b0,y:b1,platform:Linux, +03000000a30600000cff000010010000,Saitek P2500 Force Rumble,a:b2,b:b3,back:b11,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,start:b10,x:b0,y:b1,platform:Linux, +03000000a30600000c04000011010000,Saitek P2900,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b12,x:b0,y:b3,platform:Linux, +03000000a306000018f5000010010000,Saitek P3200 Rumble,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Linux, +03000000300f00001201000010010000,Saitek P380,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Linux, +03000000a30600000901000000010000,Saitek P880,a:b2,b:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,x:b0,y:b1,platform:Linux, +03000000a30600000b04000000010000,Saitek P990 Dual Analog,a:b1,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b8,x:b0,y:b3,platform:Linux, +03000000a306000020f6000011010000,Saitek PS2700 Rumble,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Linux, +05000000e804000000a000001b010000,Samsung EIGP20,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +03000000d81d00000e00000010010000,Savior,a:b0,b:b1,back:b8,leftshoulder:b6,leftstick:b10,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b11,righttrigger:b3,start:b9,x:b4,y:b5,platform:Linux, +03000000a30c00002500000011010000,Sega Genesis Mini 3B Controller,a:b2,b:b1,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,righttrigger:b5,start:b9,platform:Linux, +03000000790000001100000011010000,Sega Saturn,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b5,righttrigger:b4,start:b9,x:b0,y:b3,platform:Linux, +03000000790000002201000011010000,Sega Saturn,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b6,righttrigger:b7,start:b9,x:b2,y:b3,platform:Linux, +03000000b40400000a01000000010000,Sega Saturn,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b5,righttrigger:b2,start:b8,x:b3,y:b4,platform:Linux, +030000001f08000001e4000010010000,SFC Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Linux, +03000000632500002305000010010000,ShanWan Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, +03000000632500002605000010010000,Shanwan Gamepad,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +03000000632500007505000010010000,Shanwan Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, +03000000bc2000000055000010010000,Shanwan Gamepad,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +03000000f025000021c1000010010000,Shanwan Gioteck PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, +03000000341a00000908000010010000,SL6566,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, +050000004c050000cc09000001000000,Sony DualShock 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +03000000ff000000cb01000010010000,Sony PlayStation Portable,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Linux, +03000000250900000500000000010000,Sony PS2 pad with SmartJoy Adapter,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Linux, +030000005e0400008e02000073050000,Speedlink Torid,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000005e0400008e02000020200000,SpeedLink Xeox Pro Analog,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000d11800000094000011010000,Stadia Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux, +05000000d11800000094000000010000,Stadia Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux, +03000000de2800000112000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux, +03000000de2800000112000011010000,Steam Controller,a:b2,b:b3,back:b10,dpdown:+a5,dpleft:-a4,dpright:+a4,dpup:-a5,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a7,leftx:a0,lefty:a1,paddle1:b15,paddle2:b16,rightshoulder:b7,rightstick:b14,righttrigger:a6,rightx:a2,righty:a3,start:b11,x:b4,y:b5,platform:Linux, +03000000de2800000211000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux, +03000000de2800000211000011010000,Steam Controller,a:b2,b:b3,back:b10,dpdown:b18,dpleft:b19,dpright:b20,dpup:b17,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,paddle1:b16,paddle2:b15,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b5,platform:Linux, +03000000de2800004211000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux, +03000000de2800004211000011010000,Steam Controller,a:b2,b:b3,back:b10,dpdown:b18,dpleft:b19,dpright:b20,dpup:b17,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a7,leftx:a0,lefty:a1,paddle1:b16,paddle2:b15,rightshoulder:b7,righttrigger:a6,rightx:a2,righty:a3,start:b11,x:b4,y:b5,platform:Linux, +03000000de280000fc11000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +05000000de2800000212000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux, +05000000de2800000511000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux, +05000000de2800000611000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux, +03000000de2800000512000010010000,Steam Deck,a:b3,b:b4,back:b11,dpdown:b17,dpleft:b18,dpright:b19,dpup:b16,guide:b13,leftshoulder:b7,leftstick:b14,lefttrigger:a9,leftx:a0,lefty:a1,rightshoulder:b8,rightstick:b15,righttrigger:a8,rightx:a2,righty:a3,start:b12,x:b5,y:b6,platform:Linux, +03000000de2800000512000011010000,Steam Deck,a:b3,b:b4,back:b11,dpdown:b17,dpleft:b18,dpright:b19,dpup:b16,guide:b13,leftshoulder:b7,leftstick:b14,lefttrigger:a9,leftx:a0,lefty:a1,misc1:b2,paddle1:b21,paddle2:b20,paddle3:b23,paddle4:b22,rightshoulder:b8,rightstick:b15,righttrigger:a8,rightx:a2,righty:a3,start:b12,x:b5,y:b6,platform:Linux, +03000000de280000ff11000001000000,Steam Virtual Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +050000004e696d6275732b0000000000,SteelSeries Nimbus Plus,a:b0,b:b1,back:b10,guide:b11,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b12,x:b2,y:b3,platform:Linux, +03000000381000003014000075010000,SteelSeries Stratus Duo,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000381000003114000075010000,SteelSeries Stratus Duo,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +0500000011010000311400001b010000,SteelSeries Stratus Duo,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b32,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +05000000110100001914000009010000,SteelSeries Stratus XL,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +03000000ad1b000038f0000090040000,Street Fighter IV Fightstick TE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000003b07000004a1000000010000,Suncom SFX Plus,a:b0,b:b2,back:b7,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b9,righttrigger:b5,start:b8,x:b1,y:b3,platform:Linux, +03000000666600000488000000010000,Super Joy Box 5 Pro,a:b2,b:b1,back:b9,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Linux, +0300000000f00000f100000000010000,Super RetroPort,a:b1,b:b5,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Linux, +030000008f0e00000d31000010010000,SZMY Power 3 Turbo,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +03000000457500000401000011010000,SZMY Power DS4 Wired Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +03000000457500002211000010010000,SZMY Power Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, +030000008f0e00001431000010010000,SZMY Power PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +03000000e40a00000307000011010000,Taito Egret II Mini Control Panel,a:b4,b:b2,back:b6,guide:b9,leftx:a0,lefty:a1,rightshoulder:b0,righttrigger:b1,start:b7,x:b8,y:b3,platform:Linux, +03000000e40a00000207000011010000,Taito Egret II Mini Controller,a:b4,b:b2,back:b6,guide:b9,leftx:a0,lefty:a1,rightshoulder:b0,righttrigger:b1,start:b7,x:b8,y:b3,platform:Linux, +03000000ba2200000701000001010000,Technology Innovation PS2 Adapter,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a5,righty:a2,start:b9,x:b3,y:b2,platform:Linux, +03000000790000001c18000011010000,TGZ Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +03000000591c00002400000010010000,THEC64 Joystick,a:b0,b:b1,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Linux, +03000000591c00002600000010010000,THEGamepad,a:b2,b:b1,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b3,y:b0,platform:Linux, +030000004f04000015b3000001010000,Thrustmaster Dual Analog 3.2,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Linux, +030000004f04000015b3000010010000,Thrustmaster Dual Analog 4,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Linux, +030000004f04000020b3000010010000,Thrustmaster Dual Trigger,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Linux, +030000004f04000023b3000000010000,Thrustmaster Dual Trigger PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +030000004f0400000ed0000011010000,Thrustmaster eSwap Pro Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +03000000b50700000399000000010000,Thrustmaster Firestorm Digital 2,a:b2,b:b4,back:b11,leftshoulder:b6,leftstick:b10,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b8,rightstick:b0,righttrigger:b9,start:b1,x:b3,y:b5,platform:Linux, +030000004f04000003b3000010010000,Thrustmaster Firestorm Dual Analog 2,a:b0,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b9,rightx:a2,righty:a3,x:b1,y:b3,platform:Linux, +030000004f04000000b3000010010000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b11,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b1,y:b3,platform:Linux, +030000004f04000004b3000010010000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Linux, +030000004f04000026b3000002040000,Thrustmaster GP XID,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000c6240000025b000002020000,Thrustmaster GPX,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000004f04000008d0000000010000,Thrustmaster Run N Drive PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +030000004f04000009d0000000010000,Thrustmaster Run N Drive PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +030000004f04000007d0000000010000,Thrustmaster T Mini,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +030000004f04000012b3000010010000,Thrustmaster Vibrating Gamepad,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Linux, +03000000571d00002000000010010000,Tomee SNES Adapter,a:b0,b:b1,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Linux, +03000000bd12000015d0000010010000,Tomee SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Linux, +03000000d814000007cd000011010000,Toodles 2008 Chimp PC PS3,a:b0,b:b1,back:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b3,y:b2,platform:Linux, +030000005e0400008e02000070050000,Torid,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000c01100000591000011010000,Torid,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, +03000000680a00000300000003000000,TRBot Virtual Joypad,a:b11,b:b12,back:b15,dpdown:b6,dpleft:b3,dpright:b4,dpup:b5,leftshoulder:b17,leftstick:b21,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b22,righttrigger:a2,rightx:a3,righty:a4,start:b16,x:b13,y:b14,platform:Linux, +03000000780300000300000003000000,TRBot Virtual Joypad,a:b11,b:b12,back:b15,dpdown:b6,dpleft:b3,dpright:b4,dpup:b5,leftshoulder:b17,leftstick:b21,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b22,righttrigger:a2,rightx:a3,righty:a4,start:b16,x:b13,y:b14,platform:Linux, +03000000e00d00000300000003000000,TRBot Virtual Joypad,a:b11,b:b12,back:b15,dpdown:b6,dpleft:b3,dpright:b4,dpup:b5,leftshoulder:b17,leftstick:b21,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b22,righttrigger:a2,rightx:a3,righty:a4,start:b16,x:b13,y:b14,platform:Linux, +03000000f00600000300000003000000,TRBot Virtual Joypad,a:b11,b:b12,back:b15,dpdown:b6,dpleft:b3,dpright:b4,dpup:b5,leftshoulder:b17,leftstick:b21,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b22,righttrigger:a2,rightx:a3,righty:a4,start:b16,x:b13,y:b14,platform:Linux, +030000005f140000c501000010010000,Trust Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, +06000000f51000000870000003010000,Turtle Beach Recon,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000100800000100000010010000,Twin PS2 Adapter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux, +03000000151900005678000010010000,Uniplay U6,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +03000000100800000300000010010000,USB Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux, +03000000790000000600000007010000,USB gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b3,y:b0,platform:Linux, +03000000790000001100000000010000,USB Gamepad,a:b2,b:b1,back:b8,dpdown:a0,dpleft:a1,dpright:a2,dpup:a4,start:b9,platform:Linux, +030000006f0e00000302000011010000,Victrix Pro Fightstick PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, +030000006f0e00000702000011010000,Victrix Pro Fightstick PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, +05000000ac0500003232000001000000,VR Box Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Linux, +05000000434f4d4d414e440000000000,VX Gaming Command Series,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, +0000000058626f782033363020576900,Xbox 360 Controller,a:b0,b:b1,back:b14,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,guide:b7,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Linux, +030000005e0400001907000000010000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000005e0400008e02000010010000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000005e0400008e02000014010000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000005e0400009102000007010000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000005e040000a102000000010000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000005e040000a102000007010000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000005e040000a102000030060000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000005e0400008e02000000010000,Xbox 360 EasySMX,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000005e040000a102000014010000,Xbox 360 Receiver,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000005e0400000202000000010000,Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b4,platform:Linux, +030000006f0e00001304000000010000,Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000ffff0000ffff000000010000,Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b4,platform:Linux, +0000000058626f782047616d65706100,Xbox Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux, +030000005e0400000a0b000005040000,Xbox One Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Linux, +030000005e040000d102000002010000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000005e040000ea02000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000005e040000ea02000001030000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +050000005e040000e002000003090000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +050000005e040000fd02000003090000,Xbox One Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b16,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +050000005e040000fd02000030110000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +050000005e040000e302000002090000,Xbox One Elite,a:b0,b:b1,back:b136,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a6,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +050000005e040000220b000013050000,Xbox One Elite 2 Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +050000005e040000050b000002090000,Xbox One Elite Series 2,a:b0,b:b1,back:b136,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a6,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +030000005e040000ea02000011050000,Xbox One S Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +060000005e040000ea0200000b050000,Xbox One S Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +060000005e040000ea0200000d050000,Xbox One S Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000005e040000120b000001050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000005e040000120b000005050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000005e040000120b000007050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000005e040000120b000009050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000005e040000120b00000d050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000005e040000120b00000f050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000005e040000130b000005050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +050000005e040000130b000001050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +050000005e040000130b000005050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +050000005e040000130b000007050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +050000005e040000130b000009050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +050000005e040000130b000011050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +050000005e040000130b000013050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +050000005e040000130b000015050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +060000005e040000120b000007050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +060000005e040000120b00000b050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +060000005e040000120b00000f050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000005e040000120b000011050000,Xbox Series X Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000005e040000120b000014050000,Xbox Series X Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +050000005e040000130b000017050000,Xbox Series X Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +060000005e040000120b00000d050000,Xbox Series X Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +050000005e040000200b000013050000,Xbox Wireless Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +050000005e040000200b000017050000,Xbox Wireless Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +050000005e040000220b000017050000,Xbox Wireless Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, +03000000450c00002043000010010000,XEOX SL6556 BK,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, +05000000172700004431000029010000,XiaoMi Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b20,leftshoulder:b6,leftstick:b13,lefttrigger:a7,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a6,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Linux, +03000000c0160000e105000001010000,XinMo Dual Arcade,a:b4,b:b3,back:b6,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b9,leftshoulder:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b1,y:b0,platform:Linux, +030000005e0400008e02000020010000,XInput Adapter,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000120c0000100e000011010000,Zeroplus P4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +03000000120c0000101e000011010000,Zeroplus P4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, + +# Android +38653964633230666463343334313533,8BitDo Adapter,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +36666264316630653965636634386234,8BitDo Adapter 2,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b19,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +38426974446f20417263616465205374,8BitDo Arcade Stick,a:b0,b:b1,back:b15,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,guide:b5,leftshoulder:b9,lefttrigger:a4,rightshoulder:b10,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +61393962646434393836356631636132,8BitDo Arcade Stick,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b20,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b19,y:b2,platform:Android, +64323139346131306233636562663738,8BitDo Arcade Stick,a:b0,b:b1,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b19,y:b2,platform:Android, +64643565386136613265663236636564,8BitDo Arcade Stick,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b20,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b19,y:b2,platform:Android, +33313433353539306634656436353432,8BitDo Dogbone,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +38426974446f20446f67626f6e65204d,8BitDo Dogbone,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightx:a2,righty:a3,start:b6,platform:Android, +34343439373236623466343934376233,8BitDo FC30 Pro,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b28,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b29,righttrigger:b7,start:b5,x:b30,y:b2,platform:Android, +38426974446f2038426974446f204c69,8BitDo Lite,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, +30643332373663313263316637356631,8BitDo Lite 2,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, +38426974446f204c6974652032000000,8BitDo Lite 2,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, +62656331626461363634633735353032,8BitDo Lite 2,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, +38393936616436383062666232653338,8BitDo Lite SE,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, +38426974446f204c6974652053450000,8BitDo Lite SE,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, +39356430616562366466646636643435,8BitDo Lite SE,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, +05000000c82d000006500000ffff3f00,8BitDo M30,a:b1,b:b0,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,guide:b17,leftshoulder:b9,lefttrigger:a5,rightshoulder:b10,righttrigger:a4,start:b6,x:b3,y:b2,platform:Android, +05000000c82d000051060000ffff3f00,8BitDo M30,a:b1,b:b0,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,guide:b17,leftshoulder:b9,lefttrigger:a4,rightshoulder:b10,righttrigger:a5,start:b6,x:b3,y:b2,platform:Android, +32323161363037623637326438643634,8BitDo M30,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightshoulder:b9,righttrigger:b10,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +33656266353630643966653238646264,8BitDo M30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b20,righttrigger:a5,start:b10,x:b19,y:b2,platform:Android, +38426974446f204d3330204d6f646b69,8BitDo M30,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightshoulder:b9,righttrigger:b10,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +39366630663062373237616566353437,8BitDo M30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:b18,start:b6,x:b2,y:b3,platform:Android, +64653533313537373934323436343563,8BitDo M30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:a4,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b9,righttrigger:b10,start:b6,x:b2,y:b3,platform:Android, +66356438346136366337386437653934,8BitDo M30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,righttrigger:b10,start:b18,x:b19,y:b2,platform:Android, +66393064393162303732356665666366,8BitDo M30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:a5,start:b6,x:b2,y:b3,platform:Android, +38426974446f204d6963726f2067616d,8BitDo Micro,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,lefttrigger:a4,leftx:b0,lefty:b1,rightshoulder:b10,righttrigger:a5,rightx:b2,righty:b3,start:b6,x:b3,y:b2,platform:Android, +61653365323561356263373333643266,8BitDo Micro,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,lefttrigger:a4,leftx:b0,lefty:b1,rightshoulder:b10,righttrigger:a5,rightx:b2,righty:b3,start:b6,x:b3,y:b2,platform:Android, +62613137616239666338343866326336,8BitDo Micro,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,lefttrigger:a4,leftx:b0,lefty:b1,rightshoulder:b10,righttrigger:a5,rightx:b2,righty:b3,start:b6,x:b3,y:b2,platform:Android, +33663431326134333366393233616633,8BitDo N30,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightx:a2,righty:a3,start:b6,platform:Android, +38426974446f204e3330204d6f646b69,8BitDo N30,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightx:a2,righty:a3,start:b6,platform:Android, +05000000c82d000015900000ffff3f00,8BitDo N30 Pro 2,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, +05000000c82d000065280000ffff3f00,8BitDo N30 Pro 2,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b17,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, +38323035343766666239373834336637,8BitDo N64,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:b18,rightx:a2,righty:a3,start:b6,platform:Android, +38426974446f204e3634204d6f646b69,8BitDo N64,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:b18,rightx:a2,righty:a3,start:b6,platform:Android, +32363135613966656338666638666237,8BitDo NEOGEO,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +35363534633333373639386466346631,8BitDo NEOGEO,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +38426974446f204e454f47454f204750,8BitDo NEOGEO,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +39383963623932353561633733306334,8BitDo NEOGEO,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +050000000220000000900000ffff3f00,8BitDo NES30 Pro,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, +050000002038000009000000ffff3f00,8BitDo NES30 Pro,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, +38313433643131656262306631373166,8BitDo P30,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +38326536643339353865323063616339,8BitDo P30,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +38426974446f2050333020636c617373,8BitDo P30,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +35376664343164386333616535333434,8BitDo Pro 2,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b17,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b18,righttrigger:a5,rightx:a3,start:b10,x:b19,y:b2,platform:Android, +38426974446f2038426974446f205072,8BitDo Pro 2,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, +38426974446f2050726f203200000000,8BitDo Pro 2,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, +62373739366537363166326238653463,8BitDo Pro 2,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,x:b3,y:b2,platform:Android, +38386464613034326435626130396565,8BitDo Receiver,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b19,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, +38426974446f2038426974446f205265,8BitDo Receiver,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b19,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, +66303230343038613365623964393766,8BitDo Receiver,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b19,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, +38426974446f20533330204d6f646b69,8BitDo S30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:a4,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b9,righttrigger:b10,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +66316462353561376330346462316137,8BitDo S30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:a4,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b9,righttrigger:b10,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +05000000c82d000000600000ffff3f00,8BitDo SF30 Pro,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:b15,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b16,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, +05000000c82d000000610000ffff3f00,8BitDo SF30 Pro,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, +38426974646f20534633302050726f00,8BitDo SF30 Pro,a:b1,b:b0,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b16,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b17,platform:Android, +61623334636338643233383735326439,8BitDo SFC30,a:b0,b:b1,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b3,rightshoulder:b31,start:b5,x:b30,y:b2,platform:Android, +05000000c82d000012900000ffff3f00,8BitDo SN30,a:b1,b:b0,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,rightshoulder:b10,start:b6,x:b3,y:b2,platform:Android, +05000000c82d000062280000ffff3f00,8BitDo SN30,a:b1,b:b0,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,rightshoulder:b10,start:b6,x:b3,y:b2,platform:Android, +38316230613931613964356666353839,8BitDo SN30,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, +38426974446f20534e3330204d6f646b,8BitDo SN30,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, +65323563303231646531383162646335,8BitDo SN30,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, +35383531346263653330306238353131,8BitDo SN30 PP,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +05000000c82d000001600000ffff3f00,8BitDo SN30 Pro,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, +05000000c82d000002600000ffff0f00,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b17,leftshoulder:b9,leftstick:b7,lefttrigger:b15,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b16,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, +36653638656632326235346264663661,8BitDo SN30 Pro Plus,a:b0,b:b1,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b19,y:b2,platform:Android, +38303232393133383836366330346462,8BitDo SN30 Pro Plus,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b17,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b18,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b19,y:b2,platform:Android, +38346630346135363335366265656666,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, +38426974446f20534e33302050726f2b,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b19,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, +536f6e7920436f6d707574657220456e,8BitDo SN30 Pro Plus,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +66306331643531333230306437353936,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, +050000002028000009000000ffff3f00,8BitDo SNES30,a:b1,b:b0,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, +050000003512000020ab000000780f00,8BitDo SNES30,a:b21,b:b20,back:b30,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b26,rightshoulder:b27,start:b31,x:b24,y:b23,platform:Android, +33666663316164653937326237613331,8BitDo Zero,a:b0,b:b1,back:b15,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,rightshoulder:b10,start:b6,x:b2,y:b3,platform:Android, +38426974646f205a65726f2047616d65,8BitDo Zero,a:b0,b:b1,back:b15,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,rightshoulder:b10,start:b6,x:b2,y:b3,platform:Android, +05000000c82d000018900000ffff0f00,8BitDo Zero 2,a:b1,b:b0,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,rightshoulder:b10,start:b6,x:b3,y:b2,platform:Android, +05000000c82d000030320000ffff0f00,8BitDo Zero 2,a:b1,b:b0,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,rightshoulder:b10,start:b6,x:b3,y:b2,platform:Android, +33663434393362303033616630346337,8BitDo Zero 2,a:b0,b:b1,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftx:a0,lefty:a1,rightshoulder:b20,start:b18,x:b19,y:b2,platform:Android, +34656330626361666438323266633963,8BitDo Zero 2,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b20,start:b10,x:b19,y:b2,platform:Android, +63396666386564393334393236386630,8BitDo Zero 2,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,start:b6,x:b3,y:b2,platform:Android, +63633435623263373466343461646430,8BitDo Zero 2,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,start:b6,x:b2,y:b3,platform:Android, +32333634613735616163326165323731,Amazon Luna Controller,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,x:b2,y:b3,platform:Android, +4c696e757820342e31392e3137322077,Anbernic Gamepad,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a4,start:b6,x:b2,y:b3,platform:Android, +417374726f2063697479206d696e6920,Astro City Mini,a:b23,b:b22,back:b29,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,rightshoulder:b25,righttrigger:b26,start:b30,x:b24,y:b21,platform:Android, +35643263313264386134376362363435,Atari VCS Classic Controller,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,start:b6,platform:Android, +32353831643566306563643065356239,Atari VCS Modern Controller,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +32303165626138343962363666346165,Brook Mars PS4 Controller,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android, +38383337343564366131323064613561,Brook Mars PS4 Controller,a:b1,b:b19,back:b17,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android, +34313430343161653665353737323365,Elecom JC-W01U,a:b23,b:b24,back:b29,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b25,lefttrigger:b27,leftx:a0,lefty:a1,rightshoulder:b26,righttrigger:b28,rightx:a2,righty:a3,start:b30,x:b21,y:b22,platform:Android, +4875694a6961204a432d573031550000,Elecom JC-W01U,a:b23,b:b24,back:b29,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b25,lefttrigger:b27,leftx:a0,lefty:a1,rightshoulder:b26,righttrigger:b28,rightx:a2,righty:a3,start:b30,x:b21,y:b22,platform:Android, +30363230653635633863366338623265,Evo VR,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,x:b2,y:b3,platform:Android, +05000000b404000011240000dfff3f00,Flydigi Vader 2,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,paddle1:b17,paddle2:b18,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +05000000bc20000000550000ffff3f00,GameSir G3w,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +34323662653333636330306631326233,Google Nexus,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +35383633353935396534393230616564,Google Stadia Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +05000000d6020000e5890000dfff3f00,GPD XD Plus,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a5,start:b6,x:b2,y:b3,platform:Android, +05000000d6020000e5890000dfff3f80,GPD XD Plus,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a3,rightx:a4,righty:a5,start:b6,x:b2,y:b3,platform:Android, +66633030656131663837396562323935,Hori Battle,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Android, +35623466343433653739346434636330,Hori Fighting Commander 3 Pro,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android, +484f524920434f2e2c4c54442e203130,Hori Fighting Commander 3 Pro,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b20,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b3,righttrigger:b9,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android, +484f524920434f2e2c4c544420205041,Hori Gem Pad 3,a:b1,b:b17,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b4,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b16,x:b0,y:b2,platform:Android, +65656436646661313232656661616130,Hori PC Engine Mini Controller,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b18,platform:Android, +31303433326562636431653534636633,Hori Real Arcade Pro 3,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android, +32656664353964393561366362333636,Hori Switch Split Pad Pro,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Android, +30306539356238653637313730656134,HORIPAD Switch Pro Controller,a:b0,b:b1,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b19,y:b2,platform:Android, +48797065726b696e2050616400000000,Hyperkin Admiral N64 Controller,+rightx:b6,+righty:b7,-rightx:b17,-righty:b5,a:b1,b:b0,leftshoulder:b3,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b20,start:b18,platform:Android, +62333331353131353034386136626636,Hyperkin Admiral N64 Controller,+rightx:b6,+righty:b7,-rightx:b17,-righty:b5,a:b1,b:b0,leftshoulder:b3,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b20,start:b18,platform:Android, +31306635363562663834633739396333,Hyperkin N64 Adapter,a:b1,b:b19,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightx:a2,righty:a3,start:b18,platform:Android, +5368616e57616e202020202048797065,Hyperkin N64 Adapter,a:b1,b:b19,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightx:a2,righty:a3,start:b18,platform:Android, +0500000083050000602000000ffe0000,iBuffalo SNES Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b15,rightshoulder:b16,start:b10,x:b2,y:b3,platform:Android, +5553422c322d6178697320382d627574,iBuffalo Super Famicom Controller,a:b1,b:b0,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b17,rightshoulder:b18,start:b10,x:b3,y:b2,platform:Android, +64306137363261396266353433303531,InterAct GoPad,a:b24,b:b25,leftshoulder:b23,lefttrigger:b27,leftx:a0,lefty:a1,rightshoulder:b26,righttrigger:b28,x:b21,y:b22,platform:Android, +532e542e442e20496e74657261637420,InterAct HammerHead FX,a:b23,b:b24,back:b30,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b26,leftstick:b22,lefttrigger:b28,leftx:a0,lefty:a1,rightshoulder:b27,rightstick:b25,righttrigger:b29,rightx:a2,righty:a3,start:b31,x:b20,y:b21,platform:Android, +65346535636333663931613264643164,Joy-Con,a:b21,b:b22,back:b29,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b25,lefttrigger:b27,leftx:a0,lefty:a1,rightshoulder:b26,righttrigger:b28,rightx:a2,righty:a3,start:b30,x:b23,y:b24,platform:Android, +33346566643039343630376565326335,Joy-Con (L),a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,rightshoulder:b20,start:b17,x:b19,y:b2,platform:Android, +35313531613435623366313835326238,Joy-Con (L),a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,rightshoulder:b20,start:b17,x:b19,y:b2,platform:Android, +4a6f792d436f6e20284c290000000000,Joy-Con (L),a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,rightshoulder:b20,start:b17,x:b19,y:b2,platform:Android, +38383665633039363066383334653465,Joy-Con (R),a:b0,b:b1,back:b5,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,rightshoulder:b20,start:b18,x:b19,y:b2,platform:Android, +39363561613936303237333537383931,Joy-Con (R),a:b0,b:b1,back:b5,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,rightshoulder:b20,start:b18,x:b19,y:b2,platform:Android, +4a6f792d436f6e202852290000000000,Joy-Con (R),a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,rightshoulder:b20,start:b18,x:b19,y:b2,platform:Android, +39656136363638323036303865326464,JYS Aapter,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android, +63316564383539663166353034616434,JYS Adapter,a:b1,b:b3,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b0,y:b2,platform:Android, +64623163333561643339623235373232,Logitech F310,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +35623364393661626231343866613337,Logitech F710,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +4c6f6769746563682047616d65706164,Logitech F710,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +64396331333230326333313330336533,Logitech F710,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +39653365373864633935383236363438,Logitech G Cloud,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +416d617a6f6e2047616d6520436f6e74,Luna Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Android, +4c756e612047616d6570616400000000,Luna Controller,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +30363066623539323534363639323363,Magic NS,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android, +31353762393935386662336365626334,Magic NS,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android, +39623565346366623931666633323530,Magic NS,a:b1,b:b3,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b0,y:b2,platform:Android, +6d6179666c617368206c696d69746564,Mayflash GameCube Adapter,a:b22,b:b21,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:b25,leftx:a0,lefty:a1,rightshoulder:b28,righttrigger:b26,rightx:a5,righty:a2,start:b30,x:b23,y:b24,platform:Android, +436f6e74726f6c6c6572000000000000,Mayflash N64 Adapter,a:b1,b:b19,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightx:a2,righty:a3,start:b18,platform:Android, +65666330633838383061313633326461,Mayflash N64 Adapter,a:b1,b:b19,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightx:a2,righty:a3,start:b18,platform:Android, +37316565396364386635383230353365,Mayflash Saturn Adapter,a:b21,b:b22,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b26,lefttrigger:b28,rightshoulder:b27,righttrigger:b23,start:b30,x:b24,y:b25,platform:Android, +4875694a696120205553422047616d65,Mayflash Saturn Adapter,a:b21,b:b22,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b26,lefttrigger:b28,rightshoulder:b27,righttrigger:b23,start:b30,x:b24,y:b25,platform:Android, +535a4d792d706f776572204c54442043,Mayflash Wii Classic Adapter,a:b23,b:b22,back:b29,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b31,leftshoulder:b27,lefttrigger:b25,leftx:a0,lefty:a1,rightshoulder:b28,righttrigger:b26,rightx:a2,righty:a3,start:b30,x:b24,y:b21,platform:Android, +30653962643666303631376438373532,Mayflash Wii DolphinBar,a:b23,b:b24,back:b29,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b0,leftshoulder:b25,lefttrigger:b27,leftx:a0,lefty:a1,rightshoulder:b26,righttrigger:b28,rightx:a2,righty:a3,start:b30,x:b21,y:b22,platform:Android, +39346131396233376535393665363161,Mayflash Wii U Pro Adapter,a:b22,b:b23,back:b29,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b25,leftstick:b31,lefttrigger:b27,rightshoulder:b26,rightstick:b0,righttrigger:b28,rightx:a0,righty:a1,start:b30,x:b21,y:b24,platform:Android, +31323564663862633234646330373138,Mega Drive,a:b23,b:b22,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,rightshoulder:b25,righttrigger:b26,start:b30,x:b24,y:b21,platform:Android, +37333564393261653735306132613061,Mega Drive,a:b21,b:b22,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b26,lefttrigger:b28,rightshoulder:b27,righttrigger:b23,start:b30,x:b24,y:b25,platform:Android, +64363363336633363736393038313464,Mega Drive,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b9,x:b2,y:b3,platform:Android, +33323763323132376537376266393366,Microsoft Dual Strike,a:b24,b:b23,back:b25,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b27,lefttrigger:b29,rightshoulder:b78,rightx:a0,righty:a1~,start:b26,x:b22,y:b21,platform:Android, +30306461613834333439303734316539,Microsoft SideWinder Pro,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b20,lefttrigger:b9,rightshoulder:b19,righttrigger:b10,start:b17,x:b2,y:b3,platform:Android, +32386235353630393033393135613831,Microsoft Xbox Series Controller,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +4d4f42415041442050726f2d48440000,Mobapad Chitu HD,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +4d4f435554452d303533582d4d35312d,Mocute 053X,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +33343361376163623438613466616531,Mocute M053,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +39306635663061636563316166303966,Mocute M053,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +7573622067616d657061642020202020,NEXT SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,righttrigger:b6,start:b9,x:b3,y:b0,platform:Android, +050000007e05000009200000ffff0f00,Nintendo Switch Pro Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b3,leftstick:b4,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b16,x:b17,y:b2,platform:Android, +34323437396534643531326161633738,Nintendo Switch Pro Controller,a:b0,b:b1,back:b15,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,leftstick:b7,lefttrigger:b17,misc1:b5,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +50726f20436f6e74726f6c6c65720000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b2,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b10,rightx:a2,righty:a3,start:b18,y:b3,platform:Android, +36326533353166323965623661303933,NSO N64 Controller,+rightx:b17,+righty:b10,-rightx:b2,-righty:b19,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,misc1:b7,rightshoulder:b20,righttrigger:b15,start:b18,platform:Android, +4e363420436f6e74726f6c6c65720000,NSO N64 Controller,+rightx:b17,+righty:b10,-rightx:b2,-righty:b19,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,misc1:b7,rightshoulder:b20,righttrigger:b15,start:b18,platform:Android, +534e455320436f6e74726f6c6c657200,NSO SNES Controller,a:b0,b:b1,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,rightshoulder:b20,start:b18,x:b19,y:b2,platform:Android, +64623863346133633561626136366634,NSO SNES Controller,a:b0,b:b1,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,rightshoulder:b20,start:b18,x:b19,y:b2,platform:Android, +050000005509000003720000cf7f3f00,NVIDIA Controller,a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +050000005509000010720000ffff3f00,NVIDIA Controller,a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +050000005509000014720000df7f3f00,NVIDIA Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a5,start:b6,x:b2,y:b3,platform:Android, +050000005509000014720000df7f3f80,NVIDIA Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a3,rightx:a4,righty:a5,start:b6,x:b2,y:b3,platform:Android, +37336435666338653565313731303834,NVIDIA Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +4e564944494120436f72706f72617469,NVIDIA Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +61363931656135336130663561616264,NVIDIA Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +39383335313438623439373538343266,OUYA Controller,a:b0,b:b2,dpdown:b18,dpleft:b15,dpright:b16,dpup:b17,leftshoulder:b3,leftstick:b9,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b10,righttrigger:b7,rightx:a3,righty:a4,x:b1,y:b19,platform:Android, +4f5559412047616d6520436f6e74726f,OUYA Controller,a:b0,b:b2,dpdown:b18,dpleft:b15,dpright:b6,dpup:b17,leftshoulder:b3,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b19,platform:Android, +506572666f726d616e63652044657369,PDP PS3 Rock Candy Controller,a:b1,b:b17,back:h0.2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b4,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b16,x:b0,y:b2,platform:Android, +62653335326261303663356263626339,PlayStation Classic Controller,a:b19,b:b1,back:b17,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,lefttrigger:b3,rightshoulder:b10,righttrigger:b20,start:b18,x:b2,y:b0,platform:Android, +536f6e7920496e746572616374697665,PlayStation Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,misc1:b8,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +576972656c65737320436f6e74726f6c,PlayStation Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +61653962353232366130326530363061,Pokken,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,lefttrigger:b9,rightshoulder:b20,righttrigger:b10,start:b18,x:b0,y:b2,platform:Android, +32666633663735353234363064386132,PS2,a:b23,b:b22,back:b29,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b27,lefttrigger:b25,leftx:a0,lefty:a1,rightshoulder:b28,righttrigger:b26,rightx:a3,righty:a2,start:b30,x:b24,y:b21,platform:Android, +050000004c05000068020000dfff3f00,PS3 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +536f6e7920504c415953544154494f4e,PS3 Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +61363034663839376638653463633865,PS3 Controller,a:b0,b:b1,back:b15,dpdown:a14,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +66366539656564653432353139356536,PS3 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +66383132326164626636313737373037,PS3 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +050000004c050000c405000000783f00,PS4 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +050000004c050000c4050000fffe3f00,PS4 Controller,a:b1,b:b17,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b3,leftstick:b4,lefttrigger:+a3,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:+a4,rightx:a2,righty:a5,start:b16,x:b0,y:b2,platform:Android, +050000004c050000c4050000fffe3f80,PS4 Controller,a:b1,b:b17,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b3,leftstick:b4,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:+a3,rightx:a4,righty:a5,start:b16,x:b0,y:b2,platform:Android, +050000004c050000c4050000ffff3f00,PS4 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +050000004c050000cc090000fffe3f00,PS4 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +050000004c050000cc090000ffff3f00,PS4 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +30303839663330346632363232623138,PS4 Controller,a:b1,b:b17,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:a4,rightx:a2,righty:a5,start:b16,x:b0,y:b2,platform:Android, +31326235383662333266633463653332,PS4 Controller,a:b1,b:b16,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:a4,rightx:a2,righty:a5,start:b17,x:b0,y:b2,platform:Android, +31373231336561636235613666323035,PS4 Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +31663838336334393132303338353963,PS4 Controller,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +34613139376634626133336530386430,PS4 Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +35643031303033326130316330353564,PS4 Controller,a:b1,b:b17,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b3,leftstick:b4,lefttrigger:+a3,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:+a4,rightx:a2,righty:a5,start:b16,x:b0,y:b2,platform:Android, +37626233336235343937333961353732,PS4 Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +37626464343430636562316661643863,PS4 Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +38393161636261653636653532386639,PS4 Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +63313733393535663339656564343962,PS4 Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +63393662363836383439353064663939,PS4 Controller,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +65366465656364636137653363376531,PS4 Controller,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android, +66613532303965383534396638613230,PS4 Controller,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a5,start:b18,x:b0,y:b2,platform:Android, +050000004c050000e60c0000fffe3f00,PS5 Controller,a:b1,b:b17,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b3,leftstick:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:a4,rightx:a2,righty:a5,start:b16,x:b0,y:b2,platform:Android, +050000004c050000e60c0000fffe3f80,PS5 Controller,a:b1,b:b17,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b3,leftstick:b4,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:a3,rightx:a4,righty:a5,start:b16,x:b0,y:b2,platform:Android, +050000004c050000e60c0000ffff3f00,PS5 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +32346465346533616263386539323932,PS5 Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +32633532643734376632656664383733,PS5 Controller,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a5,start:b18,x:b0,y:b2,platform:Android, +37363764353731323963323639666565,PS5 Controller,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a5,start:b18,x:b0,y:b2,platform:Android, +61303162353165316365336436343139,PS5 Controller,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,misc1:b8,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a5,start:b18,x:b0,y:b2,platform:Android, +64336263393933626535303339616332,Qanba 4RAF,a:b0,b:b1,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b20,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b3,righttrigger:b9,rightx:a2,righty:a3,start:b18,x:b19,y:b2,platform:Android, +36626666353861663864336130363137,Razer Junglecat,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +05000000f8270000bf0b0000ffff3f00,Razer Kishi,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +62653861643333663663383332396665,Razer Kishi,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +050000003215000005070000ffff3f00,Razer Raiju Mobile,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +050000003215000007070000ffff3f00,Razer Raiju Mobile,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +050000003215000000090000bf7f3f00,Razer Serval,a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,x:b2,y:b3,platform:Android, +5a6869587520526574726f2042697420,Retro Bit Saturn Controller,a:b21,b:b22,back:b29,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b25,lefttrigger:b26,rightshoulder:b27,righttrigger:b28,start:b30,x:b23,y:b24,platform:Android, +32417865732031314b6579732047616d,Retro Bit SNES Controller,a:b0,b:b1,back:b15,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,rightshoulder:b10,start:b6,x:b2,y:b3,platform:Android, +36313938306539326233393732613361,Retro Bit SNES Controller,a:b0,b:b1,back:b15,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,rightshoulder:b10,start:b6,x:b2,y:b3,platform:Android, +526574726f466c616720576972656420,Retro Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b17,rightshoulder:b18,start:b10,x:b2,y:b3,platform:Android, +61343739353764363165343237303336,Retro Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b17,lefttrigger:b18,leftx:a0,lefty:a1,start:b10,x:b2,y:b3,platform:Android, +526574726f696420506f636b65742043,Retroid Pocket,a:b1,b:b0,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b17,paddle2:b18,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, +582d426f7820436f6e74726f6c6c6572,Retroid Pocket,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b17,paddle2:b18,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +38653130373365613538333235303036,Retroid Pocket 2,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +64363363336633363736393038313463,Retrolink,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b6,platform:Android, +37393234373533633333323633646531,RetroUSB N64 RetroPort,+rightx:b17,+righty:b15,-rightx:b18,-righty:b6,a:b10,b:b9,dpdown:b19,dpleft:b1,dpright:b0,dpup:b2,leftshoulder:b7,lefttrigger:b20,leftx:a0,lefty:a1,rightshoulder:b5,start:b3,platform:Android, +5365616c6965436f6d707574696e6720,RetroUSB N64 RetroPort,+rightx:b17,+righty:b15,-rightx:b18,-righty:b6,a:b10,b:b9,dpdown:b19,dpleft:b1,dpright:b0,dpup:b2,leftshoulder:b7,lefttrigger:b20,leftx:a0,lefty:a1,rightshoulder:b5,start:b3,platform:Android, +526574726f5553422e636f6d20534e45,RetroUSB SNES RetroPort,a:b1,b:b20,back:b19,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,rightshoulder:b10,start:b2,x:b0,y:b3,platform:Android, +64643037633038386238303966376137,RetroUSB SNES RetroPort,a:b1,b:b20,back:b19,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,rightshoulder:b10,start:b2,x:b0,y:b3,platform:Android, +37656564346533643138636436356230,Rock Candy Switch Controller,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,misc1:b7,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android, +33373336396634316434323337666361,RumblePad 2,a:b22,b:b23,back:b29,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b25,lefttrigger:b27,leftx:a0,lefty:a1,rightshoulder:b26,righttrigger:b28,rightx:a2,righty:a3,start:b30,x:b21,y:b24,platform:Android, +36363537303435333566386638366333,Samsung EIGP20,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +53616d73756e672047616d6520506164,Samsung EIGP20,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +66386565396238363534313863353065,Sanwa PlayOnline Mobile,a:b21,b:b22,back:b23,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,start:b24,platform:Android, +32383165316333383766336338373261,Saturn,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:a4,righttrigger:a5,x:b2,y:b3,platform:Android, +38613865396530353338373763623431,Saturn,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,lefttrigger:b10,rightshoulder:b20,righttrigger:b19,start:b17,x:b2,y:b3,platform:Android, +61316232336262373631343137633631,Saturn,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:a4,righttrigger:a5,x:b2,y:b3,platform:Android, +30353835333338613130373363646337,SG H510,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b17,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b18,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b19,y:b2,platform:Android, +66386262366536653765333235343634,SG H510,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,x:b2,y:b3,platform:Android, +66633132393363353531373465633064,SG H510,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b17,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b18,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b19,y:b2,platform:Android, +62653761636366393366613135366338,SN30 PP,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android, +38376662666661636265313264613039,SNES,a:b0,b:b1,back:b9,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b3,rightshoulder:b20,start:b10,x:b19,y:b2,platform:Android, +5346432f555342205061640000000000,SNES Adapter,a:b0,b:b1,back:b9,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b3,rightshoulder:b20,start:b10,x:b19,y:b2,platform:Android, +5553422047616d657061642000000000,SNES Controller,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,rightshoulder:b10,start:b6,x:b3,y:b2,platform:Android, +63303964303462366136616266653561,Sony PSP,a:b21,b:b22,back:b27,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b25,leftx:a0,lefty:a1,rightshoulder:b26,start:b28,x:b23,y:b24,platform:Android, +63376637643462343766333462383235,Sony Vita,a:b1,b:b19,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftx:a0,lefty:a1,rightshoulder:b20,rightx:a3,righty:a4,start:b18,x:b0,y:b2,platform:Android, +476f6f676c65204c4c43205374616469,Stadia Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +5374616469614e3848532d6532633400,Stadia Controller,a:b0,b:b1,back:b15,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +05000000de2800000511000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Android, +05000000de2800000611000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Android, +0500000011010000201400000f7e0f00,SteelSeries Nimbus,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,righttrigger:b10,rightx:a2,righty:a3,x:b19,y:b2,platform:Android, +35306436396437373135383665646464,SteelSeries Nimbus Plus,a:b0,b:b1,leftshoulder:b3,leftstick:b17,lefttrigger:b9,leftx:a0,rightshoulder:b20,rightstick:b18,righttrigger:b10,rightx:a2,x:b19,y:b2,platform:Android, +33313930373536613937326534303931,Taito Egret II Mini Control Panel,a:b25,b:b23,back:b27,guide:b30,leftx:a0,lefty:a1,rightshoulder:b21,righttrigger:b22,start:b28,x:b29,y:b24,platform:Android, +54475a20436f6e74726f6c6c65720000,TGZ Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +62363434353532386238336663643836,TGZ Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +37323236633763666465316365313236,THEC64 Joystick,a:b21,b:b22,back:b27,leftshoulder:b25,leftx:a0,lefty:a1,rightshoulder:b26,start:b27,x:b23,y:b24,platform:Android, +38346162326232346533316164363336,THEGamepad,a:b23,b:b22,back:b27,leftshoulder:b25,leftx:a0,lefty:a1,rightshoulder:b26,start:b28,x:b24,y:b21,platform:Android, +050000004f0400000ed00000fffe3f00,ThrustMaster eSwap Pro Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +5477696e20555342204a6f7973746963,Twin Joystick,a:b22,b:b21,back:b28,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b26,leftstick:b30,lefttrigger:b24,leftx:a0,lefty:a1,rightshoulder:b27,rightstick:b31,righttrigger:b25,rightx:a3,righty:a2,start:b29,x:b23,y:b20,platform:Android, +30623739343039643830333266346439,Valve Steam Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,leftx:a0,lefty:a1,paddle1:b24,paddle2:b23,rightshoulder:b10,rightstick:b8,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +31643365666432386133346639383937,Valve Steam Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,leftx:a0,lefty:a1,paddle1:b24,paddle2:b23,rightshoulder:b10,rightstick:b8,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +30386438313564306161393537333663,Wii Classic Adapter,a:b23,b:b22,back:b29,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b27,lefttrigger:b25,leftx:a0,lefty:a1,rightshoulder:b28,righttrigger:b26,rightx:a2,righty:a3,start:b30,x:b24,y:b21,platform:Android, +33333034646336346339646538643633,Wii Classic Adapter,a:b23,b:b22,back:b29,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b27,lefttrigger:b25,leftx:a0,lefty:a1,rightshoulder:b28,righttrigger:b26,rightx:a2,righty:a3,start:b30,x:b24,y:b21,platform:Android, +050000005e0400008e02000000783f00,Xbox 360 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +30396232393162346330326334636566,Xbox 360 Controller,a:b0,b:b1,back:b4,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +38313038323730383864666463383533,Xbox 360 Controller,a:b0,b:b1,back:b4,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +58626f782033363020576972656c6573,Xbox 360 Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +65353331386662343338643939643636,Xbox 360 Controller,a:b0,b:b1,back:b4,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +65613532386633373963616462363038,Xbox 360 Controller,a:b0,b:b1,back:b4,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +47656e6572696320582d426f78207061,Xbox Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +4d6963726f736f667420582d426f7820,Xbox Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +64633436313965656664373634323364,Xbox Controller,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b19,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +050000005e04000091020000ff073f00,Xbox One Controller,a:b0,b:b1,back:b4,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Android, +050000005e04000091020000ff073f80,Xbox One Controller,a:b0,b:b1,back:b4,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +050000005e040000e00200000ffe3f00,Xbox One Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b15,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b16,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b17,y:b2,platform:Android, +050000005e040000e00200000ffe3f80,Xbox One Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b15,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b16,righttrigger:a5,rightx:a2,righty:a3,start:b10,x:b17,y:b2,platform:Android, +050000005e040000e0020000ffff3f00,Xbox One Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b4,leftshoulder:b3,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b17,y:b2,platform:Android, +050000005e040000e0020000ffff3f80,Xbox One Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b4,leftshoulder:b3,leftstick:b8,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b7,righttrigger:a5,rightx:a2,righty:a3,start:b10,x:b17,y:b2,platform:Android, +050000005e040000fd020000ffff3f00,Xbox One Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +33356661323266333733373865656366,Xbox One Controller,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +34356136633366613530316338376136,Xbox One Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b3,leftstick:b15,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b16,righttrigger:a5,rightx:a3,righty:a4,x:b17,y:b2,platform:Android, +35623965373264386238353433656138,Xbox One Controller,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +36616131643361333337396261666433,Xbox One Controller,a:b0,b:b1,back:b15,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +58626f7820576972656c65737320436f,Xbox One Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +050000005e040000000b000000783f00,Xbox One Elite 2 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Android, +050000005e040000000b000000783f80,Xbox One Elite 2 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +050000005e040000050b0000ffff3f00,Xbox One Elite 2 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a6,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +050000005e040000e002000000783f00,Xbox One S Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +050000005e040000ea02000000783f00,Xbox One S Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +050000005e040000fd020000ff7f3f00,Xbox One S Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +050000005e040000120b000000783f00,Xbox Series Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Android, +050000005e040000120b000000783f80,Xbox Series Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +050000005e040000130b0000ffff3f00,Xbox Series Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +65633038363832353634653836396239,Xbox Series Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, +050000001727000044310000ffff3f00,XiaoMi Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a7,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a6,rightx:a2,righty:a5,start:b6,x:b2,y:b3,platform:Android, + +# iOS +05000000ac0500000100000000006d01,*,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b4,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a5,rightx:a3,righty:a4,x:b2,y:b3,platform:iOS, +05000000ac050000010000004f066d01,*,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b4,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a5,rightx:a3,righty:a4,x:b2,y:b3,platform:iOS, +05000000ac05000001000000cf076d01,*,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b2,y:b3,platform:iOS, +05000000ac05000001000000df076d01,*,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b2,y:b3,platform:iOS, +05000000ac05000001000000ff076d01,*,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,platform:iOS, +05000000ac0500000200000000006d02,*,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b4,rightshoulder:b5,x:b2,y:b3,platform:iOS, +05000000ac050000020000004f066d02,*,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b4,rightshoulder:b5,x:b2,y:b3,platform:iOS, +050000008a35000003010000ff070000,Backbone One,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,platform:iOS, +050000008a35000004010000ff070000,Backbone One,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,platform:iOS, +4d466947616d65706164010000000000,MFi Extended Gamepad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:iOS, +4d466947616d65706164020000000000,MFi Gamepad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,rightshoulder:b5,start:b6,x:b2,y:b3,platform:iOS, +050000007e050000062000000f060000,Nintendo Switch Joy-Con (L),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b2,leftshoulder:b4,rightshoulder:b5,x:b1,y:b3,platform:iOS, +050000007e050000062000004f060000,Nintendo Switch Joy-Con (L),+leftx:h0.1,+lefty:h0.2,-leftx:h0.4,-lefty:h0.8,dpdown:b2,dpleft:b0,dpright:b3,dpup:b1,leftshoulder:b4,misc1:b6,rightshoulder:b5,platform:iOS, +050000007e05000008200000df070000,Nintendo Switch Joy-Con (L/R),a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b2,y:b3,platform:iOS, +050000007e0500000e200000df070000,Nintendo Switch Joy-Con (L/R),a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:iOS, +050000007e050000072000004f060000,Nintendo Switch Joy-Con (R),+rightx:h0.4,+righty:h0.8,-rightx:h0.1,-righty:h0.2,a:b1,b:b0,guide:b6,leftshoulder:b4,rightshoulder:b5,x:b3,y:b2,platform:iOS, +050000007e05000009200000df870000,Nintendo Switch Pro Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b10,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:iOS, +050000007e05000009200000ff870000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,platform:iOS, +050000004c050000cc090000df070000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b2,y:b3,platform:iOS, +050000004c050000cc090000df870001,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b2,y:b3,platform:iOS, +050000004c050000cc090000ff070000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,platform:iOS, +050000004c050000cc090000ff870001,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,touchpad:b11,x:b2,y:b3,platform:iOS, +050000004c050000cc090000ff876d01,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,platform:iOS, +050000004c050000e60c0000df870000,PS5 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,touchpad:b10,x:b2,y:b3,platform:iOS, +050000004c050000e60c0000ff870000,PS5 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,touchpad:b11,x:b2,y:b3,platform:iOS, +05000000ac0500000300000000006d03,Remote,a:b0,b:b2,leftx:a0,lefty:a1,platform:iOS, +05000000ac0500000300000043006d03,Remote,a:b0,b:b2,leftx:a0,lefty:a1,platform:iOS, +05000000de2800000511000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:iOS, +05000000de2800000611000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:iOS, +050000005e040000050b0000df070001,Xbox Elite Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b10,paddle2:b12,paddle3:b11,paddle4:b13,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b2,y:b3,platform:iOS, +050000005e040000050b0000ff070001,Xbox Elite Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b13,paddle3:b12,paddle4:b14,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,platform:iOS, +050000005e040000e0020000df070000,Xbox One Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b2,y:b3,platform:iOS, +050000005e040000e0020000ff070000,Xbox One Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,platform:iOS, +050000005e040000130b0000df870001,Xbox Series X Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b10,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b2,y:b3,platform:iOS, +050000005e040000130b0000ff870001,Xbox Series X Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,platform:iOS, diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index cb32789cad..d58ff17aaa 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -82,10 +82,10 @@ <key>AFKTimeout</key> <map> <key>Comment</key> - <string> - Time before automatically setting AFK (away from keyboard) mode (seconds, 0=never). - Valid values are: 0, 120, 300, 600, 1800 -</string> + <string> + Time before automatically setting AFK (away from keyboard) mode (seconds, 0=never). + Valid values are: 0, 120, 300, 600, 1800 + </string> <key>Persist</key> <integer>1</integer> <key>Type</key> @@ -379,7 +379,7 @@ <key>Value</key> <integer>0</integer> </map> - <key>AutoAcceptNewInventory</key> + <key>AutoAcceptNewInventory</key> <map> <key>Comment</key> <string>Automatically accept new notecards/textures/landmarks</string> @@ -2612,6 +2612,94 @@ <key>Value</key> <integer>1</integer> </map> + <key>EnableGameControl</key> + <map> + <key>Comment</key> + <string>Enable GameControl feature</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> + <key>GameControlToServer</key> + <map> + <key>Comment</key> + <string>Transmit game controller data to server</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> + <key>GameControlToAgent</key> + <map> + <key>Comment</key> + <string>GameControl data moves avatar/flycam</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> + <key>AgentToGameControl</key> + <map> + <key>Comment</key> + <string>Avatar/flycam movement produces GameControl data</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> + <key>AnalogChannelMappings</key> + <map> + <key>Comment</key> + <string>GameControl analog button to channel mappings</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>String</string> + <key>Value</key> + <string>push:AXIS_1+,slide:AXIS_0+,jump:AXIS_4+,turn:AXIS_2+,look:AXIS_3+</string> + </map> + <key>BinaryChannelMappings</key> + <map> + <key>Comment</key> + <string>GameControl binary button to channel mappings</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>String</string> + <key>Value</key> + <string>toggle_run:BUTTON_9,toggle_fly:BUTTON_11,toggle_flycam:BUTTON_10,stop:BUTTON_7</string> + </map> + <key>FlycamChannelMappings</key> + <map> + <key>Comment</key> + <string>GameControl flycam button to channel mappings</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>String</string> + <key>Value</key> + <string>advance:AXIS_1+,pan:AXIS_0+,rise:AXIS_5+,pitch:AXIS_3-,yaw:AXIS_2+</string> + </map> + <key>KnownGameControllers</key> + <map> + <key>Comment</key> + <string>Map of controller device-specific options.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>LLSD</string> + <key>Value</key> + <map/> + </map> <key>EnableGestureSounds</key> <map> <key>Comment</key> @@ -9680,6 +9768,17 @@ <key>Value</key> <integer>0</integer> </map> + <key>CollectFontVertexBuffers</key> + <map> + <key>Comment</key> + <string>When enabled some UI elements with cache buffers generated by fonts and reuse them. When disabled general cahce will be used with a significant overhead for hash, but it regenerates vertices each frame so it's always up to date.</string> + <key>Persist</key> + <integer>0</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <real>1</real> + </map> <key>ShowMyComplexityChanges</key> <map> <key>Comment</key> diff --git a/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl index 23a3ca4911..41ff2913e9 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl @@ -30,7 +30,6 @@ out vec4 frag_color; uniform sampler2D lightMap; uniform float dist_factor; -uniform float blur_size; uniform vec2 delta; uniform vec2 screen_res; uniform vec3 kern[4]; diff --git a/indra/newview/app_settings/shaders/class1/deferred/cofF.glsl b/indra/newview/app_settings/shaders/class1/deferred/cofF.glsl index 0a0fa0a374..4a26b8924a 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/cofF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/cofF.glsl @@ -30,8 +30,6 @@ out vec4 frag_color; uniform sampler2D diffuseRect; uniform sampler2D depthMap; -uniform float depth_cutoff; -uniform float norm_cutoff; uniform float focal_distance; uniform float blur_constant; uniform float tan_pixel_angle; diff --git a/indra/newview/app_settings/shaders/class3/deferred/multiPointLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/multiPointLightF.glsl index 4ed778371f..809ad2f0bd 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/multiPointLightF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/multiPointLightF.glsl @@ -33,7 +33,6 @@ uniform sampler2D emissiveRect; // PBR linear packed Occlusion, Roughness, Metal uniform sampler2D lightFunc; uniform vec3 env_mat[3]; -uniform float sun_wash; uniform int light_count; uniform vec4 light[LIGHT_COUNT]; // .w = size; see C++ fullscreen_lights.push_back() uniform vec4 light_col[LIGHT_COUNT]; // .a = falloff diff --git a/indra/newview/app_settings/shaders/class3/deferred/pointLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/pointLightF.glsl index 6c13757149..41a19ea1b6 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/pointLightF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/pointLightF.glsl @@ -33,7 +33,6 @@ uniform sampler2D emissiveRect; // PBR linear packed Occlusion, Roughness, Metal uniform sampler2D lightFunc; uniform vec3 env_mat[3]; -uniform float sun_wash; // light params uniform vec3 color; @@ -46,7 +45,6 @@ in vec3 trans_center; uniform vec2 screen_res; uniform mat4 inv_proj; -uniform vec4 viewport; void calcHalfVectors(vec3 lv, vec3 n, vec3 v, out vec3 h, out vec3 l, out float nh, out float nl, out float nv, out float vh, out float lightDist); float calcLegacyDistanceAttenuation(float distance, float falloff); diff --git a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl index 4231d8580e..a34e97c171 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl @@ -39,9 +39,6 @@ uniform sampler2D lightMap; uniform sampler2D lightFunc; -uniform float blur_size; -uniform float blur_fidelity; - #if defined(HAS_SSAO) uniform float ssao_irradiance_scale; uniform float ssao_irradiance_max; diff --git a/indra/newview/app_settings/shaders/class3/deferred/spotLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/spotLightF.glsl index bc4d36d10d..e99aa5ace4 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/spotLightF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/spotLightF.glsl @@ -47,7 +47,6 @@ uniform float near_clip; uniform float far_clip; uniform vec3 proj_origin; //origin of projection to be used for angular attenuation -uniform float sun_wash; uniform int proj_shadow_idx; uniform float shadow_fade; diff --git a/indra/newview/featuretable_linux.txt b/indra/newview/featuretable_linux.txt index 6f7f553cec..dc5d1ff6c4 100644 --- a/indra/newview/featuretable_linux.txt +++ b/indra/newview/featuretable_linux.txt @@ -28,27 +28,27 @@ version 29 // list all RenderAnisotropic 1 1 -RenderAvatarCloth 1 1 RenderAvatarLODFactor 1 1.0 RenderAvatarPhysicsLODFactor 1 1.0 RenderAvatarMaxNonImpostors 1 16 RenderAvatarMaxComplexity 1 350000 RenderAutoMuteSurfaceAreaLimit 1 1000.0 RenderCubeMap 1 1 -RenderDelayVBUpdate 1 0 RenderFarClip 1 256 RenderFlexTimeFactor 1 1.0 RenderFogRatio 1 4.0 RenderGamma 1 0 RenderGlowResolutionPow 1 9 -RenderGround 1 1 RenderMaxPartCount 1 8192 RenderObjectBump 1 1 -RenderLocalLights 1 1 -RenderReflectionDetail 1 4 +RenderLocalLightCount 1 4096 +RenderTransparentWater 1 1 +RenderReflectionsEnabled 1 1 +RenderReflectionProbeDetail 1 2 RenderTerrainDetail 1 1 RenderTerrainLODFactor 1 2.0 -RenderTransparentWater 1 1 +RenderTerrainPBRDetail 1 0 +RenderTerrainPBRPlanarSampleCount 1 3 RenderTreeLODFactor 1 1.0 RenderVBOEnable 1 1 RenderVBOMappingDisable 1 1 @@ -61,48 +61,26 @@ Disregard128DefaultDrawDistance 1 1 Disregard96DefaultDrawDistance 1 1 RenderCompressTextures 1 1 RenderShaderLightingMaxLevel 1 3 +RenderReflectionProbeLevel 1 3 RenderDeferred 1 1 RenderDeferredSSAO 1 1 -RenderUseAdvancedAtmospherics 1 0 RenderShadowDetail 1 2 -RenderFSAASamples 1 16 +RenderUseStreamVBO 1 1 +RenderFSAAType 1 2 +RenderFSAASamples 1 3 RenderMaxTextureIndex 1 16 +RenderGLContextCoreProfile 1 1 +RenderGLMultiThreadedTextures 1 0 +RenderGLMultiThreadedMedia 1 0 +RenderReflectionProbeResolution 1 128 +RenderScreenSpaceReflections 1 1 RenderMirrors 1 1 - -// -// Low Graphics Settings (fixed function) -// -list LowFixedFunction -RenderAnisotropic 1 0 -RenderAvatarCloth 1 0 -RenderAvatarLODFactor 1 0 -RenderAvatarPhysicsLODFactor 1 0 -RenderAvatarMaxNonImpostors 1 3 -RenderAvatarMaxComplexity 1 25000 -RenderFarClip 1 64 -RenderFlexTimeFactor 1 0 -RenderGlowResolutionPow 1 8 -RenderLocalLights 1 0 -RenderMaxPartCount 1 0 -RenderObjectBump 1 0 -RenderReflectionDetail 1 0 -RenderTerrainDetail 1 0 -RenderTerrainLODFactor 1 1 -RenderTransparentWater 1 0 -RenderTreeLODFactor 1 0 -RenderVolumeLODFactor 1 1.125 -WindLightUseAtmosShaders 1 0 -RenderDeferred 1 0 -RenderDeferredSSAO 1 0 -RenderUseAdvancedAtmospherics 1 0 -RenderShadowDetail 1 0 -WLSkyDetail 1 48 -RenderFSAASamples 1 0 -RenderMirrors 1 0 -RenderHeroProbeResolution 1 256 -RenderHeroProbeDistance 1 4 -RenderHeroProbeUpdateRate 1 6 +RenderHeroProbeResolution 1 2048 +RenderHeroProbeDistance 1 16 +RenderHeroProbeUpdateRate 1 4 RenderHeroProbeConservativeUpdateMultiplier 1 16 +RenderDownScaleMethod 1 1 +RenderCASSharpness 1 1 // @@ -110,7 +88,6 @@ RenderHeroProbeConservativeUpdateMultiplier 1 16 // list Low RenderAnisotropic 1 0 -RenderAvatarCloth 1 0 RenderAvatarLODFactor 1 0 RenderAvatarPhysicsLODFactor 1 0 RenderAvatarMaxNonImpostors 1 3 @@ -118,276 +95,260 @@ RenderAvatarMaxComplexity 1 35000 RenderFarClip 1 64 RenderFlexTimeFactor 1 0 RenderGlowResolutionPow 1 8 -RenderLocalLights 1 0 +RenderLocalLightCount 1 8 RenderMaxPartCount 1 0 -RenderObjectBump 1 0 -RenderReflectionDetail 1 0 +RenderTransparentWater 1 0 +RenderReflectionsEnabled 1 1 +RenderReflectionProbeDetail 1 0 RenderTerrainDetail 1 0 RenderTerrainLODFactor 1 1 -RenderTransparentWater 1 0 +RenderTerrainPBRDetail 1 -4 +RenderTerrainPBRPlanarSampleCount 1 1 RenderTreeLODFactor 1 0 RenderVolumeLODFactor 1 1.125 -WindLightUseAtmosShaders 1 0 -RenderDeferred 1 0 RenderDeferredSSAO 1 0 -RenderUseAdvancedAtmospherics 1 0 RenderShadowDetail 1 0 -WLSkyDetail 1 48 +WLSkyDetail 1 96 +RenderFSAAType 1 0 RenderFSAASamples 1 0 +RenderScreenSpaceReflections 1 0 +RenderReflectionProbeLevel 1 0 RenderMirrors 1 0 RenderHeroProbeResolution 1 256 RenderHeroProbeDistance 1 4 -RenderHeroProbeUpdateRate 1 6 +RenderHeroProbeUpdateRate 1 6 RenderHeroProbeConservativeUpdateMultiplier 1 16 +RenderCASSharpness 1 0 // // Medium Low Graphics Settings // list LowMid RenderAnisotropic 1 0 -RenderAvatarCloth 1 0 RenderAvatarLODFactor 1 0.5 RenderAvatarMaxComplexity 1 100000 RenderAvatarPhysicsLODFactor 1 0.75 +RenderAvatarMaxNonImpostors 1 5 RenderFarClip 1 96 RenderFlexTimeFactor 1 1.0 RenderGlowResolutionPow 1 8 RenderMaxPartCount 1 2048 -RenderObjectBump 1 1 -RenderLocalLights 1 1 -RenderReflectionDetail 1 0 +RenderLocalLightCount 1 256 +RenderTransparentWater 1 0 +RenderReflectionsEnabled 1 1 +RenderReflectionProbeDetail 1 0 RenderTerrainDetail 1 1 RenderTerrainLODFactor 1 1.0 -RenderTransparentWater 1 1 +RenderTerrainPBRDetail 1 -1 +RenderTerrainPBRPlanarSampleCount 1 1 RenderTreeLODFactor 1 0.5 RenderVolumeLODFactor 1 1.125 -WindLightUseAtmosShaders 1 0 -RenderDeferred 1 0 RenderDeferredSSAO 1 0 -RenderUseAdvancedAtmospherics 1 0 RenderShadowDetail 1 0 -WLSkyDetail 1 48 +WLSkyDetail 1 96 +RenderFSAAType 1 0 RenderFSAASamples 1 0 +RenderScreenSpaceReflections 1 0 +RenderReflectionProbeLevel 1 0 RenderMirrors 1 0 RenderHeroProbeResolution 1 256 RenderHeroProbeDistance 1 6 RenderHeroProbeUpdateRate 1 3 RenderHeroProbeConservativeUpdateMultiplier 1 16 +RenderCASSharpness 1 0 // // Medium Graphics Settings (standard) // list Mid RenderAnisotropic 1 1 -RenderAvatarCloth 1 0 RenderAvatarLODFactor 1 1.0 RenderAvatarMaxComplexity 1 200000 RenderAvatarPhysicsLODFactor 1 1.0 +RenderAvatarMaxNonImpostors 1 7 RenderFarClip 1 128 RenderFlexTimeFactor 1 1.0 RenderGlowResolutionPow 1 9 RenderMaxPartCount 1 4096 -RenderObjectBump 1 1 -RenderLocalLights 1 1 -RenderReflectionDetail 1 0 +RenderLocalLightCount 1 512 +RenderTransparentWater 1 0 RenderTerrainDetail 1 1 RenderTerrainLODFactor 1 2.0 -RenderTransparentWater 1 1 +RenderTerrainPBRDetail 1 0 +RenderTerrainPBRPlanarSampleCount 1 1 RenderTreeLODFactor 1 0.5 -RenderVolumeLODFactor 1 1.125 -WindLightUseAtmosShaders 1 1 -RenderDeferred 1 0 +RenderVolumeLODFactor 1 1.25 RenderDeferredSSAO 1 0 -RenderUseAdvancedAtmospherics 1 0 RenderShadowDetail 1 0 -WLSkyDetail 1 48 -RenderFSAASamples 1 2 +WLSkyDetail 1 96 +RenderFSAAType 1 1 +RenderFSAASamples 1 1 +RenderReflectionsEnabled 1 1 +RenderReflectionProbeDetail 1 0 +RenderScreenSpaceReflections 1 0 +RenderReflectionProbeLevel 1 1 RenderMirrors 1 0 RenderHeroProbeResolution 1 512 RenderHeroProbeDistance 1 6 RenderHeroProbeUpdateRate 1 3 RenderHeroProbeConservativeUpdateMultiplier 1 16 +RenderCASSharpness 1 0 // -// Medium High Graphics Settings (deferred enabled) +// Medium High Graphics Settings // list MidHigh RenderAnisotropic 1 1 -RenderAvatarCloth 1 0 RenderAvatarLODFactor 1 1.0 RenderAvatarMaxComplexity 1 250000 RenderAvatarPhysicsLODFactor 1 1.0 +RenderAvatarMaxNonImpostors 1 9 RenderFarClip 1 128 RenderFlexTimeFactor 1 1.0 RenderGlowResolutionPow 1 9 RenderMaxPartCount 1 4096 -RenderObjectBump 1 1 -RenderLocalLights 1 1 -RenderReflectionDetail 1 0 +RenderLocalLightCount 1 1024 +RenderTransparentWater 1 0 RenderTerrainDetail 1 1 RenderTerrainLODFactor 1 2.0 -RenderTransparentWater 1 1 +RenderTerrainPBRDetail 1 0 +RenderTerrainPBRPlanarSampleCount 1 1 RenderTreeLODFactor 1 0.5 -RenderVolumeLODFactor 1 1.125 -WindLightUseAtmosShaders 1 1 -RenderDeferred 1 1 -RenderUseAdvancedAtmospherics 1 0 +RenderVolumeLODFactor 1 1.375 RenderDeferredSSAO 1 0 RenderShadowDetail 1 0 -WLSkyDetail 1 48 -RenderFSAASamples 1 2 +WLSkyDetail 1 96 +RenderFSAAType 1 1 +RenderFSAASamples 1 1 +RenderReflectionsEnabled 1 1 +RenderReflectionProbeDetail 1 1 +RenderScreenSpaceReflections 1 0 +RenderReflectionProbeLevel 1 2 RenderMirrors 1 0 RenderHeroProbeResolution 1 512 RenderHeroProbeDistance 1 6 RenderHeroProbeUpdateRate 1 2 RenderHeroProbeConservativeUpdateMultiplier 1 8 +RenderCASSharpness 1 0 // -// High Graphics Settings (deferred + SSAO) +// High Graphics Settings (SSAO + sun shadows) // list High RenderAnisotropic 1 1 -RenderAvatarCloth 1 0 RenderAvatarLODFactor 1 1.0 RenderAvatarMaxComplexity 1 300000 RenderAvatarPhysicsLODFactor 1 1.0 +RenderAvatarMaxNonImpostors 1 11 RenderFarClip 1 128 RenderFlexTimeFactor 1 1.0 RenderGlowResolutionPow 1 9 RenderMaxPartCount 1 4096 -RenderObjectBump 1 1 -RenderLocalLights 1 1 -RenderReflectionDetail 1 0 +RenderLocalLightCount 1 2048 +RenderTransparentWater 1 1 RenderTerrainDetail 1 1 RenderTerrainLODFactor 1 2.0 -RenderTransparentWater 1 1 +RenderTerrainPBRDetail 1 0 +RenderTerrainPBRPlanarSampleCount 1 3 RenderTreeLODFactor 1 0.5 -RenderVolumeLODFactor 1 1.125 -WindLightUseAtmosShaders 1 1 -RenderDeferred 1 1 +RenderVolumeLODFactor 1 1.5 RenderDeferredSSAO 1 1 -RenderUseAdvancedAtmospherics 1 0 -RenderShadowDetail 1 0 -WLSkyDetail 1 48 +RenderShadowDetail 1 1 +WLSkyDetail 1 96 +RenderFSAAType 1 2 RenderFSAASamples 1 2 +RenderReflectionsEnabled 1 1 +RenderReflectionProbeDetail 1 1 +RenderScreenSpaceReflections 1 0 +RenderReflectionProbeLevel 1 3 RenderMirrors 1 0 RenderHeroProbeResolution 1 512 RenderHeroProbeDistance 1 8 RenderHeroProbeUpdateRate 1 2 RenderHeroProbeConservativeUpdateMultiplier 1 8 +RenderCASSharpness 1 0.4 // -// High Ultra Graphics Settings (deferred + SSAO + shadows) +// High Ultra Graphics Settings (deferred + SSAO + all shadows) // list HighUltra RenderAnisotropic 1 1 -RenderAvatarCloth 1 0 RenderAvatarLODFactor 1 1.0 RenderAvatarMaxComplexity 1 350000 RenderAvatarPhysicsLODFactor 1 1.0 +RenderAvatarMaxNonImpostors 1 16 RenderFarClip 1 128 RenderFlexTimeFactor 1 1.0 RenderGlowResolutionPow 1 9 RenderMaxPartCount 1 4096 -RenderObjectBump 1 1 -RenderLocalLights 1 1 -RenderReflectionDetail 1 0 +RenderLocalLightCount 1 4096 RenderTerrainDetail 1 1 RenderTerrainLODFactor 1 2.0 +RenderTerrainPBRDetail 1 0 +RenderTerrainPBRPlanarSampleCount 1 3 RenderTransparentWater 1 1 RenderTreeLODFactor 1 0.5 -RenderVolumeLODFactor 1 1.125 -WindLightUseAtmosShaders 1 1 -RenderDeferred 1 1 +RenderVolumeLODFactor 1 1.75 RenderDeferredSSAO 1 1 -RenderUseAdvancedAtmospherics 1 0 RenderShadowDetail 1 2 -WLSkyDetail 1 48 +WLSkyDetail 1 96 +RenderFSAAType 1 2 RenderFSAASamples 1 2 +RenderReflectionsEnabled 1 1 +RenderReflectionProbeDetail 1 1 +RenderScreenSpaceReflections 1 0 +RenderReflectionProbeLevel 1 3 RenderMirrors 1 0 -RenderHeroProbeResolution 1 512 +RenderHeroProbeResolution 1 1024 RenderHeroProbeDistance 1 16 RenderHeroProbeUpdateRate 1 1 RenderHeroProbeConservativeUpdateMultiplier 1 4 +RenderCASSharpness 1 0.4 // // Ultra graphics (REALLY PURTY!) // list Ultra RenderAnisotropic 1 1 -RenderAvatarCloth 1 1 RenderAvatarLODFactor 1 1.0 +RenderAvatarMaxNonImpostors 1 16 RenderAvatarPhysicsLODFactor 1 1.0 RenderFarClip 1 256 RenderFlexTimeFactor 1 1.0 RenderGlowResolutionPow 1 9 -RenderLocalLights 1 1 +RenderLocalLightCount 1 8192 RenderMaxPartCount 1 8192 -RenderObjectBump 1 1 -RenderReflectionDetail 1 4 RenderTerrainDetail 1 1 RenderTerrainLODFactor 1 2.0 +RenderTerrainPBRDetail 1 0 +RenderTerrainPBRPlanarSampleCount 1 3 RenderTransparentWater 1 1 RenderTreeLODFactor 1 1.0 RenderVolumeLODFactor 1 2.0 WindLightUseAtmosShaders 1 1 WLSkyDetail 1 128 -RenderDeferred 1 1 RenderDeferredSSAO 1 1 -RenderUseAdvancedAtmospherics 1 0 RenderShadowDetail 1 2 -RenderFSAASamples 1 2 +RenderFSAAType 1 2 +RenderFSAASamples 1 3 +RenderReflectionsEnabled 1 1 +RenderReflectionProbeDetail 1 1 +RenderScreenSpaceReflections 1 0 +RenderReflectionProbeLevel 1 3 RenderMirrors 1 0 -RenderHeroProbeResolution 1 1024 +RenderHeroProbeResolution 1 2048 RenderHeroProbeDistance 1 16 RenderHeroProbeUpdateRate 1 1 RenderHeroProbeConservativeUpdateMultiplier 1 4 +RenderCASSharpness 1 0.4 // // Class Unknown Hardware (unknown) // list Unknown -RenderVBOEnable 1 0 RenderShadowDetail 1 0 -RenderDeferred 1 0 RenderDeferredSSAO 1 0 -RenderUseAdvancedAtmospherics 1 0 - -// -// Class 0 Hardware (just old) -// -list Class0 -RenderVBOEnable 1 1 - -// -// Class 1 Hardware -// -list Class1 -RenderVBOEnable 1 1 - -// -// Class 2 Hardware -// -list Class2 -RenderVBOEnable 1 1 - -// -// Class 3 Hardware -// -list Class3 -RenderVBOEnable 1 1 - -// -// Class 4 Hardware -// -list Class4 -RenderVBOEnable 1 1 - -// -// Class 5 Hardware -// -list Class5 -RenderVBOEnable 1 1 +RenderMirrors 1 0 // // VRAM > 512MB @@ -396,339 +357,41 @@ list VRAMGT512 RenderCompressTextures 1 0 // -// No Pixel Shaders available -// -list NoPixelShaders -RenderAvatarCloth 0 0 -RenderReflectionDetail 0 0 -WindLightUseAtmosShaders 0 0 -RenderDeferred 0 0 -RenderDeferredSSAO 0 0 -RenderUseAdvancedAtmospherics 0 0 -RenderShadowDetail 0 0 - -// -// No Vertex Shaders available -// -list NoVertexShaders -RenderAvatarCloth 0 0 -RenderReflectionDetail 0 0 -WindLightUseAtmosShaders 0 0 -RenderDeferred 0 0 -RenderDeferredSSAO 0 0 -RenderUseAdvancedAtmospherics 0 0 -RenderShadowDetail 0 0 - -// -// GL_ARB_map_buffer_range exists -// -list MapBufferRange -RenderVBOMappingDisable 1 1 - - -// // "Default" setups for safe, low, medium, high // list safe RenderAnisotropic 1 0 -RenderAvatarCloth 0 0 RenderAvatarMaxNonImpostors 1 16 RenderAvatarMaxComplexity 1 80000 -RenderObjectBump 0 0 -RenderLocalLights 1 0 +RenderLocalLightCount 1 0 RenderMaxPartCount 1 1024 RenderTerrainDetail 1 0 -RenderVBOEnable 1 0 -RenderReflectionDetail 0 0 -WindLightUseAtmosShaders 0 0 -RenderDeferred 0 0 +RenderTransparentWater 1 0 RenderDeferredSSAO 0 0 -RenderUseAdvancedAtmospherics 0 0 RenderShadowDetail 0 0 - -// -// CPU based feature masks -// - -// 1Ghz or less (equiv) -list CPUSlow -RenderMaxPartCount 1 1024 - -// -// RAM based feature masks -// -list RAM256MB -RenderObjectBump 0 0 - -// -// Graphics card based feature masks -// -list OpenGLPre15 -RenderVBOEnable 1 0 - -list OpenGLPre30 -RenderDeferred 0 0 -RenderMaxTextureIndex 1 1 +RenderReflectionProbeDetail 0 -1 +RenderMirrors 0 0 list Intel RenderAnisotropic 1 0 -// Avoid some Intel crashes on Linux -RenderCubeMap 0 0 +RenderFSAAType 1 0 RenderFSAASamples 1 0 +RenderGLContextCoreProfile 1 0 +RenderGLMultiThreadedMedia 1 0 +RenderDownScaleMethod 1 0 -list GeForce2 -RenderAnisotropic 1 0 -RenderMaxPartCount 1 2048 -RenderTerrainDetail 1 0 -RenderVBOEnable 1 1 - -list SiS -UseOcclusion 0 0 - - -list Intel_830M -RenderTerrainDetail 1 0 -RenderVBOEnable 1 0 - -list Intel_845G -RenderTerrainDetail 1 0 -RenderVBOEnable 1 0 - -list Intel_855GM -RenderTerrainDetail 1 0 -RenderVBOEnable 1 0 - -list Intel_865G -RenderTerrainDetail 1 0 -RenderVBOEnable 1 0 - -list Intel_900 -RenderTerrainDetail 1 0 -RenderVBOEnable 1 0 - -list Intel_915GM -RenderTerrainDetail 1 0 -RenderVBOEnable 1 0 - -list Intel_915G -RenderTerrainDetail 1 0 -RenderVBOEnable 1 0 - -list Intel_945GM -RenderTerrainDetail 1 0 -RenderVBOEnable 1 0 - -list Intel_945G -RenderTerrainDetail 1 0 -RenderVBOEnable 1 0 - -list Intel_950 -RenderTerrainDetail 1 0 -RenderVBOEnable 1 0 - -list Intel_965 -RenderTerrainDetail 1 0 -RenderVBOEnable 1 0 -UseOcclusion 0 0 - -list Intel_G33 -RenderTerrainDetail 1 0 -RenderVBOEnable 1 0 - -list Intel_Bear_Lake -RenderTerrainDetail 1 0 -RenderVBOEnable 1 0 - -list Intel_Broadwater -RenderTerrainDetail 1 0 -RenderVBOEnable 1 0 - -list Intel_Brookdale -RenderTerrainDetail 1 0 -RenderVBOEnable 1 0 - -list Intel_Montara -RenderTerrainDetail 1 0 -RenderVBOEnable 1 0 - -list Intel_Springdale -RenderTerrainDetail 1 0 -RenderVBOEnable 1 0 - - -list ATI_FireGL_5200 -RenderVBOEnable 1 0 -WindLightUseAtmosShaders 0 0 - - -list ATI_Mobility_Radeon_7xxx -RenderVBOEnable 0 0 - -list ATI_Radeon_7xxx -RenderVBOEnable 0 0 - -list ATI_All-in-Wonder_Radeon -RenderVBOEnable 0 0 - -list ATI_All-in-Wonder_7500 -RenderVBOEnable 0 0 - -list ATI_Mobility_Radeon_9600 -Disregard96DefaultDrawDistance 1 0 - - -/// tweaked ATI to 96 Draw distance - -list ATI_Radeon_9000 -Disregard96DefaultDrawDistance 1 0 -list ATI_Radeon_9200 -Disregard96DefaultDrawDistance 1 0 -list ATI_Radeon_9500 -Disregard96DefaultDrawDistance 1 0 -list ATI_Radeon_9600 -Disregard96DefaultDrawDistance 1 0 - -/// tweaked ATI to 128 draw distance - -list ATI_Radeon_X300 -Disregard128DefaultDrawDistance 1 0 -list ATI_Radeon_X400 -Disregard128DefaultDrawDistance 1 0 -list ATI_Radeon_X500 -Disregard128DefaultDrawDistance 1 0 -list ATI_Radeon_X600 -Disregard128DefaultDrawDistance 1 0 -list ATI_Radeon_X700 -Disregard128DefaultDrawDistance 1 0 -list ATI_Radeon_X1300 -Disregard128DefaultDrawDistance 1 0 -UseStartScreen 0 0 -list ATI_Radeon_X1400 -Disregard128DefaultDrawDistance 1 0 -list ATI_Radeon_X1500 -Disregard128DefaultDrawDistance 1 0 -UseStartScreen 0 0 -list ATI_Radeon_X1600 -Disregard128DefaultDrawDistance 1 0 -list ATI_Radeon_X1700 -Disregard128DefaultDrawDistance 1 0 -list ATI_Mobility_Radeon_X1xxx -Disregard128DefaultDrawDistance 1 0 -list ATI_Radeon_HD_2300 -Disregard128DefaultDrawDistance 1 0 -list ATI_Radeon_HD_2400 -Disregard128DefaultDrawDistance 1 0 -list ATI_ASUS_AH24xx -Disregard128DefaultDrawDistance 1 0 - - -// Avatar hardware skinning causes invisible avatars -// on various ATI chipsets on drivers before 8.2 - -list ATIOldDriver -RenderAvatarCloth 0 0 -// Avoid driver crashes with some features on Linux with old ATI drivers -UseOcclusion 0 0 -WindLightUseAtmosShaders 0 0 - - -/// Tweaked NVIDIA - -list NVIDIA_GeForce_FX_5100 -Disregard96DefaultDrawDistance 1 0 -list NVIDIA_GeForce_FX_5200 -Disregard96DefaultDrawDistance 1 0 -list NVIDIA_GeForce_FX_5500 -Disregard96DefaultDrawDistance 1 0 -list NVIDIA_GeForce_FX_5600 -Disregard96DefaultDrawDistance 1 0 - -list NVIDIA_GeForce_FX_Go5100 -Disregard96DefaultDrawDistance 1 0 -list NVIDIA_GeForce_FX_Go5200 -Disregard96DefaultDrawDistance 1 0 -list NVIDIA_GeForce_FX_Go5300 -Disregard96DefaultDrawDistance 1 0 -list NVIDIA_GeForce_FX_Go5500 -Disregard96DefaultDrawDistance 1 0 -list NVIDIA_GeForce_FX_Go5600 -Disregard96DefaultDrawDistance 1 0 - -list NVIDIA_GeForce_6100 -Disregard128DefaultDrawDistance 1 0 -list NVIDIA_GeForce_6200 -Disregard128DefaultDrawDistance 1 0 -list NVIDIA_GeForce_6500 -Disregard128DefaultDrawDistance 1 0 -list NVIDIA_GeForce_6600 -Disregard128DefaultDrawDistance 1 0 - -list NVIDIA_G73 -Disregard128DefaultDrawDistance 1 0 - -list NVIDIA_GeForce_Go_6100 -RenderVBOEnable 1 0 -Disregard128DefaultDrawDistance 1 0 -list NVIDIA_GeForce_Go_6200 -RenderVBOEnable 1 0 -Disregard128DefaultDrawDistance 1 0 -list NVIDIA_GeForce_Go_6500 -RenderVBOEnable 1 0 -Disregard128DefaultDrawDistance 1 0 -list NVIDIA_GeForce_Go_6600 -RenderVBOEnable 1 0 -Disregard128DefaultDrawDistance 1 0 -list NVIDIA_GeForce_Go_6700 -RenderVBOEnable 1 0 -Disregard128DefaultDrawDistance 1 0 -list NVIDIA_GeForce_Go_6800 -RenderVBOEnable 1 0 -Disregard128DefaultDrawDistance 1 0 -list NVIDIA_GeForce_Go_6 -RenderVBOEnable 1 0 -Disregard128DefaultDrawDistance 1 0 +list AMD +RenderGLMultiThreadedTextures 1 0 -list NVIDIA_GeForce_7000 -RenderShaderLightingMaxLevel 1 2 -list NVIDIA_GeForce_7100 -RenderShaderLightingMaxLevel 1 2 -list NVIDIA_GeForce_7200 -Disregard128DefaultDrawDistance 1 0 -RenderShaderLightingMaxLevel 1 2 -list NVIDIA_GeForce_7300 -Disregard128DefaultDrawDistance 1 0 -RenderShaderLightingMaxLevel 1 2 -list NVIDIA_GeForce_7400 -Disregard128DefaultDrawDistance 1 0 -RenderShaderLightingMaxLevel 1 2 -list NVIDIA_GeForce_7500 -RenderShaderLightingMaxLevel 1 2 -list NVIDIA_GeForce_7600 -RenderShaderLightingMaxLevel 1 2 -list NVIDIA_GeForce_7700 -RenderShaderLightingMaxLevel 1 2 -list NVIDIA_GeForce_7800 -RenderShaderLightingMaxLevel 1 2 -list NVIDIA_GeForce_7900 -RenderShaderLightingMaxLevel 1 2 +list NVIDIA +RenderGLMultiThreadedMedia 1 1 -list NVIDIA_GeForce_Go_7200 -Disregard128DefaultDrawDistance 1 0 -RenderShaderLightingMaxLevel 1 2 -list NVIDIA_GeForce_Go_7300 -Disregard128DefaultDrawDistance 1 0 -RenderShaderLightingMaxLevel 1 2 -list NVIDIA_GeForce_Go_7300_LE -RenderShaderLightingMaxLevel 1 2 -list NVIDIA_GeForce_Go_7400 -Disregard128DefaultDrawDistance 1 0 -RenderShaderLightingMaxLevel 1 2 -list NVIDIA_GeForce_Go_7600 -RenderShaderLightingMaxLevel 1 2 -list NVIDIA_GeForce_Go_7700 -RenderShaderLightingMaxLevel 1 2 -list NVIDIA_GeForce_Go_7800 -RenderShaderLightingMaxLevel 1 2 -list NVIDIA_GeForce_Go_7900 -RenderShaderLightingMaxLevel 1 2 +list GL3 +RenderFSAAType 0 0 +RenderFSAASamples 0 0 +RenderReflectionsEnabled 0 0 +RenderReflectionProbeDetail 0 0 +RenderMirrors 0 0 +list TexUnit16orLess +RenderTerrainPBRDetail 1 -1 diff --git a/indra/newview/linux_tools/wrapper.sh b/indra/newview/linux_tools/wrapper.sh index a027aaf6d1..3019e844d2 100755 --- a/indra/newview/linux_tools/wrapper.sh +++ b/indra/newview/linux_tools/wrapper.sh @@ -4,16 +4,9 @@ ## These options are for self-assisted troubleshooting during this beta ## testing phase; you should not usually need to touch them. -## - Avoids using any FMOD STUDIO audio driver. -#export LL_BAD_FMODSTUDIO_DRIVER=x ## - Avoids using any OpenAL audio driver. #export LL_BAD_OPENAL_DRIVER=x -## - Avoids using the FMOD Studio or FMOD Ex PulseAudio audio driver. -#export LL_BAD_FMOD_PULSEAUDIO=x -## - Avoids using the FMOD Studio or FMOD Ex ALSA audio driver. -#export LL_BAD_FMOD_ALSA=x - ## - Avoids the optional OpenGL extensions which have proven most problematic ## on some hardware. Disabling this option may cause BETTER PERFORMANCE but ## may also cause CRASHES and hangs on some unstable combinations of drivers @@ -34,16 +27,10 @@ ## LL_GL_BLACKLIST which solves your problems. #export LL_GL_BLACKLIST=abcdefghijklmno -## - Some ATI/Radeon users report random X server crashes when the mouse -## cursor changes shape. If you suspect that you are a victim of this -## driver bug, try enabling this option and report whether it helps: -#export LL_ATI_MOUSE_CURSOR_BUG=x - if [ "`uname -m`" = "x86_64" ]; then echo '64-bit Linux detected.' fi - ## Everything below this line is just for advanced troubleshooters. ##------------------------------------------------------------------- @@ -55,9 +42,6 @@ fi #export LL_WRAPPER='gdb --args' #export LL_WRAPPER='valgrind --smc-check=all --error-limit=no --log-file=secondlife.vg --leak-check=full --suppressions=/usr/lib/valgrind/glibc-2.5.supp --suppressions=secondlife-i686.supp' -## - Avoids an often-buggy X feature that doesn't really benefit us anyway. -export SDL_VIDEO_X11_DGAMOUSE=0 - ## - The 'scim' GTK IM module widely crashes the viewer. Avoid it. if [ "$GTK_IM_MODULE" = "scim" ]; then export GTK_IM_MODULE=xim @@ -67,13 +51,6 @@ if [ "$XMODIFIERS" = "" ]; then export XMODIFIERS="@im=fcitx" fi -## - Automatically work around the ATI mouse cursor crash bug: -## (this workaround is disabled as most fglrx users do not see the bug) -#if lsmod | grep fglrx &>/dev/null ; then -# export LL_ATI_MOUSE_CURSOR_BUG=x -#fi - - ## Nothing worth editing below this line. ##------------------------------------------------------------------- diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index c8b0adbaf8..ca35608175 100644 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -1463,7 +1463,7 @@ LLVector3 LLAgent::getReferenceUpVector() } -// Radians, positive is forward into ground +// Radians, positive is downward toward ground //----------------------------------------------------------------------------- // pitch() //----------------------------------------------------------------------------- @@ -1477,27 +1477,23 @@ void LLAgent::pitch(F32 angle) LLVector3 skyward = getReferenceUpVector(); + // SL-19286 Avatar is upside down when viewed from below + // after left-clicking the mouse on the avatar and dragging down + // + // The issue is observed on angle below 10 degrees + const F32 look_down_limit = 179.f * DEG_TO_RAD; + const F32 look_up_limit = 10.f * DEG_TO_RAD; + + F32 angle_from_skyward = acos(mFrameAgent.getAtAxis() * skyward); + // clamp pitch to limits - if (angle >= 0.f) + if ((angle >= 0.f) && (angle_from_skyward + angle > look_down_limit)) { - const F32 look_down_limit = 179.f * DEG_TO_RAD; - F32 angle_from_skyward = acos(mFrameAgent.getAtAxis() * skyward); - if (angle_from_skyward + angle > look_down_limit) - { - angle = look_down_limit - angle_from_skyward; - } + angle = look_down_limit - angle_from_skyward; } - else if (angle < 0.f) + else if ((angle < 0.f) && (angle_from_skyward + angle < look_up_limit)) { - const F32 look_up_limit = 5.f * DEG_TO_RAD; - const LLVector3& viewer_camera_pos = LLViewerCamera::getInstance()->getOrigin(); - LLVector3 agent_focus_pos = getPosAgentFromGlobal(gAgentCamera.calcFocusPositionTargetGlobal()); - LLVector3 look_dir = agent_focus_pos - viewer_camera_pos; - F32 angle_from_skyward = angle_between(look_dir, skyward); - if (angle_from_skyward + angle < look_up_limit) - { - angle = look_up_limit - angle_from_skyward; - } + angle = look_up_limit - angle_from_skyward; } if (fabs(angle) > 1e-4) @@ -4986,6 +4982,218 @@ void LLAgent::renderAutoPilotTarget() } } +static U64 g_lastUpdateTime { 0 }; +static F32 g_deltaTime { 0.0f }; +static S32 g_lastUpdateFrame { 0 }; +static S32 g_deltaFrame { 0 }; + +void LLAgent::applyExternalActionFlags(U32 outer_flags) +{ + llassert(LLCoros::on_main_thread_main_coro()); + assert(LLGameControl::isEnabled() && LLGameControl::willControlAvatar()); + mExternalActionFlags = outer_flags; + + // HACK: AGENT_CONTROL_NUDGE_AT_NEG is used to toggle Flycam + if ((mExternalActionFlags & AGENT_CONTROL_NUDGE_AT_NEG) > 0) + { + if (mToggleFlycam) + { + mUsingFlycam = !mUsingFlycam; + if (mUsingFlycam) + { + // copy main camera transform to flycam + LLViewerCamera* camera = LLViewerCamera::getInstance(); + mFlycam.setTransform(camera->getOrigin(), camera->getQuaternion()); + mFlycam.setView(camera->getView()); + mLastFlycamUpdate = LLFrameTimer::getTotalTime(); + } + } + mToggleFlycam = false; + } + else + { + mToggleFlycam = true; + } + + // measure delta time and frame + // Note: it is possible for the deltas to be very large + // and it is the duty of the code that uses them to clamp as necessary + U64 now = LLFrameTimer::getTotalTime(); + g_deltaTime = F32(now - g_lastUpdateTime) / (F32)(USEC_PER_SEC); + g_lastUpdateTime = now; + + S32 frame_count = LLFrameTimer::getFrameCount(); + g_deltaFrame = frame_count - g_lastUpdateFrame; + g_lastUpdateFrame = frame_count; + + if (mUsingFlycam) + { + // Flycam will be updated later by exernal context + return; + } + + S32 direction = (S32)(mExternalActionFlags & AGENT_CONTROL_AT_POS) + - (S32)((mExternalActionFlags & AGENT_CONTROL_AT_NEG) >> 1); + if (direction != 0) + { + moveAt(direction); + } + + static U32 last_non_fly_frame = 0; + static U64 last_non_fly_time = 0; + direction = (S32)(mExternalActionFlags & AGENT_CONTROL_UP_POS) + - (S32)((mExternalActionFlags & AGENT_CONTROL_UP_NEG) >> 1); + if (direction != 0) + { + // HACK: this auto-fly logic based on original code still extant in llviewerinput.cpp::agent_jump() + // but has been cleaned up. + // TODO?: DRY this logic + if (direction > 0) + { + if (!getFlying() + && !upGrabbed() + && gSavedSettings.getBOOL("AutomaticFly")) + { + constexpr F32 FLY_TIME = 0.5f; + constexpr U32 FLY_FRAMES = 4; + F32 delta_time = (F32)(now - last_non_fly_time) / (F32)(USEC_PER_SEC); + U32 delta_frames = frame_count - last_non_fly_frame; + if( delta_time > FLY_TIME + && delta_frames > FLY_FRAMES) + { + setFlying(TRUE); + } + } + } + else + { + last_non_fly_frame = frame_count; + last_non_fly_time = now; + } + + moveUp(direction); + } + else if (!getFlying()) + { + last_non_fly_frame = frame_count; + last_non_fly_time = now; + } + + direction = (S32)(mExternalActionFlags & AGENT_CONTROL_LEFT_POS) + - (S32)((mExternalActionFlags & AGENT_CONTROL_LEFT_NEG) >> 1); + if (direction != 0) + { + moveLeft(direction); + } + + direction = (S32)(mExternalActionFlags & AGENT_CONTROL_YAW_POS) + - (S32)((mExternalActionFlags & AGENT_CONTROL_YAW_NEG) >> 1); + if (direction != 0) + { + F32 sign = (direction < 0 ? -1.0f : 1.0f); + // HACK: hard-code 3.0 seconds for YawRate measure. It is simpler, + // and the missing variable yaw rate is unnoticeable. + moveYaw(sign * LLFloaterMove::getYawRate(3.0f)); + } + + { + F32 pitch = ((mExternalActionFlags & AGENT_CONTROL_PITCH_POS) > 0 ? 1.0f : 0.0f) + - ((mExternalActionFlags & AGENT_CONTROL_PITCH_NEG) > 0 ? 1.0f : 0.0f); + movePitch(pitch); + } + + if ((mExternalActionFlags & AGENT_CONTROL_FLY) > 0) + { + if (mToggleFly) + { + setFlying(!getFlying()); + } + mToggleFly = false; + } + else + { + mToggleFly = true; + } + + if (mExternalActionFlags & AGENT_CONTROL_STOP) + { + setControlFlags(AGENT_CONTROL_STOP); + } + + // HACK: AGENT_CONTROL_NUDGE_AT_POS is used to toggle running + if ((mExternalActionFlags & AGENT_CONTROL_NUDGE_AT_POS) > 0) + { + if (mToggleRun) + { + if (getRunning()) + { + clearRunning(); + sendWalkRun(false); + } + else + { + setRunning(); + sendWalkRun(true); + } + } + mToggleRun = false; + } + else + { + mToggleRun = true; + } +} + +void LLAgent::pressGameControlButton(U8 button_index) +{ + mGameControlButtonsFromKeys |= (1U << button_index); +} + +void LLAgent::releaseGameControlButton(U8 button_index) +{ + mGameControlButtonsFromKeys &= !(1U << button_index); +} + +void LLAgent::updateFlycam() +{ + // Note: flycam_inputs arrive in range [-1,1] + std::vector<F32> flycam_inputs; + LLGameControl::getFlycamInputs(flycam_inputs); + + // Note: no matter how flycam_inputs are mapped to the controller + // they arrive in the following order: + constexpr S32 FLYCAM_ADVANCE = 0; + constexpr S32 FLYCAM_PAN = 1; + constexpr S32 FLYCAM_RISE = 2; + constexpr S32 FLYCAM_PITCH = 3; + constexpr S32 FLYCAM_YAW = 4; + constexpr S32 FLYCAM_ZOOM = 5; + + LLVector3 linear_velocity( + flycam_inputs[FLYCAM_ADVANCE], + flycam_inputs[FLYCAM_PAN], + flycam_inputs[FLYCAM_RISE]); + constexpr F32 MAX_FLYCAM_SPEED = 10.0f; + mFlycam.setLinearVelocity(MAX_FLYCAM_SPEED * linear_velocity); + + mFlycam.setPitchRate(flycam_inputs[FLYCAM_PITCH]); + mFlycam.setYawRate(flycam_inputs[FLYCAM_YAW]); + mFlycam.setZoomRate(flycam_inputs[FLYCAM_ZOOM]); + + mFlycam.integrate(g_deltaTime); + + LLVector3 pos; + LLQuaternion rot; + mFlycam.getTransform(pos, rot); + LLMatrix3 mat(rot); + LLViewerCamera::getInstance()->setOrigin(pos); + LLViewerCamera::getInstance()->mXAxis = LLVector3(mat.mMatrix[0]); + LLViewerCamera::getInstance()->mYAxis = LLVector3(mat.mMatrix[1]); + LLViewerCamera::getInstance()->mZAxis = LLVector3(mat.mMatrix[2]); + + LLViewerCamera::getInstance()->setView(mFlycam.getView()); +} + /********************************************************************************/ //----------------------------------------------------------------------------- diff --git a/indra/newview/llagent.h b/indra/newview/llagent.h index afc34f747f..448ee575f5 100644 --- a/indra/newview/llagent.h +++ b/indra/newview/llagent.h @@ -33,6 +33,8 @@ #include "llcharacter.h" #include "llcoordframe.h" // for mFrameAgent #include "llavatarappearancedefines.h" +#include "llflycam.h" +#include "llkeyboard.h" #include "llpermissionsflags.h" #include "llevents.h" #include "v3dmath.h" @@ -485,6 +487,7 @@ public: void resetControlFlags(); bool anyControlGrabbed() const; // True iff a script has taken over a control bool isControlGrabbed(S32 control_index) const; + bool isUsingFlycam() const { return mUsingFlycam; } // Send message to simulator to force grabbed controls to be // released, in case of a poorly written script. void forceReleaseControls(); @@ -492,7 +495,39 @@ public: private: S32 mControlsTakenCount[TOTAL_CONTROLS]; S32 mControlsTakenPassedOnCount[TOTAL_CONTROLS]; - U32 mControlFlags; // Replacement for the mFooKey's + // mControlFlags is a bitmask of behavior instructions for compact + // transmission to the server. It does NOT represent "input", rather + // the consequences of it, which will sometimes depend on "state". + U32 mControlFlags; + + //-------------------------------------------------------------------- + // GameControls + //-------------------------------------------------------------------- +public: + // ActionFlags are similar to, but not the same as, ControlFlags! + // An 'ActionFlags' bitmask stores 'simplified input' from key/button + // presses that correspond to avatar/camera movement actions + // whereas 'mControlFlags' are a more complicated set of behavior bits + // computed as a function of input and state, and are sent to the server + // to steer its character controller for the avatar. + // + void applyExternalActionFlags(U32 flags); + void updateFlycam(); + + void pressGameControlButton(U8 button); + void releaseGameControlButton(U8 button); + U32 getGameControlButtonsFromKeys() const { return mGameControlButtonsFromKeys; } + +private: + + U64 mLastFlycamUpdate { 0 }; + U32 mExternalActionFlags { 0 }; + U32 mGameControlButtonsFromKeys { 0 }; + LLFlycam mFlycam; + bool mToggleFly { true }; + bool mToggleRun { true }; + bool mToggleFlycam { true }; + bool mUsingFlycam { false }; //-------------------------------------------------------------------- // Animations diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 7fc97558f1..acc79ed994 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -47,6 +47,7 @@ #include "llagentwearables.h" #include "lldirpicker.h" #include "llfloaterimcontainer.h" +#include "llfloaterpreference.h" #include "llimprocessing.h" #include "llwindow.h" #include "llviewerstats.h" @@ -64,6 +65,7 @@ #include "llluamanager.h" #include "llurlfloaterdispatchhandler.h" #include "llviewerjoystick.h" +#include "llgamecontrol.h" #include "llcalc.h" #include "llconversationlog.h" #if LL_WINDOWS @@ -135,8 +137,8 @@ #include "stringize.h" #include "llcoros.h" #include "llexception.h" -#if !LL_LINUX #include "cef/dullahan_version.h" +#if !LL_LINUX #include "vlc/libvlc_version.h" #endif // LL_LINUX @@ -214,12 +216,12 @@ #include "llvosurfacepatch.h" #include "llviewerfloaterreg.h" #include "llcommandlineparser.h" +#include "llfloaterpreference.h" #include "llfloatermemleak.h" #include "llfloaterreg.h" #include "llfloatersimplesnapshot.h" #include "llfloatersnapshot.h" #include "llsidepanelinventory.h" -#include "llatmosphere.h" // includes for idle() idleShutdown() #include "llviewercontrol.h" @@ -1134,6 +1136,15 @@ bool LLAppViewer::init() LLViewerJoystick::getInstance()->init(false); } + LLGameControl::init(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "gamecontrollerdb.txt"), + [&](const std::string& name) -> bool { return gSavedSettings.getBOOL(name); }, + [&](const std::string& name, bool value) { gSavedSettings.setBOOL(name, value); }, + [&](const std::string& name) -> std::string { return gSavedSettings.getString(name); }, + [&](const std::string& name, const std::string& value) { gSavedSettings.setString(name, value); }, + [&](const std::string& name) -> LLSD { return gSavedSettings.getLLSD(name); }, + [&](const std::string& name, const LLSD& value) { gSavedSettings.setLLSD(name, value); }, + [&]() { LLPanelPreferenceGameControl::updateDeviceList(); }); + try { initializeSecHandler(); @@ -1417,6 +1428,48 @@ bool LLAppViewer::frame() return ret; } +void sendGameControlInput() +{ + LLMessageSystem* msg = gMessageSystem; + const LLGameControl::State& state = LLGameControl::getState(); + + msg->newMessageFast(_PREHASH_GameControlInput); + msg->nextBlock("AgentData"); + msg->addUUID("AgentID", gAgentID); + msg->addUUID("SessionID", gAgentSessionID); + + size_t num_indices = state.mAxes.size(); + for (U8 i = 0; i < num_indices; ++i) + { + if (state.mAxes[i] != state.mPrevAxes[i]) + { + // only pack an axis if it differs from previously packed value + msg->nextBlockFast(_PREHASH_AxisData); + msg->addU8Fast(_PREHASH_Index, i); + msg->addS16Fast(_PREHASH_Value, state.mAxes[i]); + } + } + + U32 button_flags = state.mButtons; + if (button_flags > 0) + { + std::vector<U8> buttons; + for (U8 i = 0; i < 32; i++) + { + if (button_flags & (0x1 << i)) + { + buttons.push_back(i); + } + } + msg->nextBlockFast(_PREHASH_ButtonData); + msg->addBinaryDataFast(_PREHASH_Data, (void*)(buttons.data()), (S32)(buttons.size())); + } + + LLGameControl::updateResendPeriod(); + gAgent.sendMessage(); +} + + bool LLAppViewer::doFrame() { LL_RECORD_BLOCK_TIME(FTM_FRAME); @@ -1478,7 +1531,7 @@ bool LLAppViewer::doFrame() LL_WARNS() << " Someone took over my signal/exception handler (post messagehandling)!" << LL_ENDL; } - gViewerWindow->getWindow()->gatherInput(); + gViewerWindow->getWindow()->gatherInput(gFocusMgr.getAppHasFocus()); } //memory leaking simulation @@ -1762,8 +1815,6 @@ void LLAppViewer::flushLFSIO() bool LLAppViewer::cleanup() { - LLAtmosphere::cleanupClass(); - //ditch LLVOAvatarSelf instance gAgentAvatarp = NULL; @@ -1964,6 +2015,7 @@ bool LLAppViewer::cleanup() // Turn off Space Navigator and similar devices LLViewerJoystick::getInstance()->terminate(); } + LLGameControl::terminate(); LL_INFOS() << "Cleaning up Objects" << LL_ENDL; @@ -3449,7 +3501,6 @@ LLSD LLAppViewer::getViewerInfo() const info["VOICE_VERSION"] = LLTrans::getString("NotConnected"); } -#if !LL_LINUX std::ostringstream cef_ver_codec; cef_ver_codec << "Dullahan: "; cef_ver_codec << DULLAHAN_VERSION_MAJOR; @@ -3475,9 +3526,6 @@ LLSD LLAppViewer::getViewerInfo() const cef_ver_codec << CHROME_VERSION_PATCH; info["LIBCEF_VERSION"] = cef_ver_codec.str(); -#else - info["LIBCEF_VERSION"] = "Undefined"; -#endif #if !LL_LINUX std::ostringstream vlc_ver_codec; @@ -4771,6 +4819,30 @@ void LLAppViewer::idle() gAgent.autoPilot(&yaw); } + // get control flags from each side + U32 control_flags = gAgent.getControlFlags(); + U32 game_control_action_flags = LLGameControl::computeInternalActionFlags(); + + // apply to GameControl + LLGameControl::setExternalInput(control_flags, gAgent.getGameControlButtonsFromKeys()); + bool should_send_game_control = LLGameControl::computeFinalStateAndCheckForChanges(); + if (LLPanelPreferenceGameControl::isWaitingForInputChannel()) + { + LLPanelPreferenceGameControl::applyGameControlInput(); + // skip this send because input is being used to set preferences + should_send_game_control = false; + } + if (should_send_game_control) + { + sendGameControlInput(); + } + + // apply to AvatarControl + if (LLGameControl::isEnabled() && LLGameControl::willControlAvatar()) + { + gAgent.applyExternalActionFlags(game_control_action_flags); + } + send_agent_update(false); // After calling send_agent_update() in the mainloop we always clear @@ -5028,6 +5100,10 @@ void LLAppViewer::idle() { LLViewerJoystick::getInstance()->moveFlycam(); } + else if (gAgent.isUsingFlycam()) + { + gAgent.updateFlycam(); + } else { if (LLToolMgr::getInstance()->inBuildMode()) diff --git a/indra/newview/llappviewerlinux.cpp b/indra/newview/llappviewerlinux.cpp index 38f2f1ae7f..7ce74649e2 100644 --- a/indra/newview/llappviewerlinux.cpp +++ b/indra/newview/llappviewerlinux.cpp @@ -129,7 +129,7 @@ int main( int argc, char **argv ) return -1; } - // Run the application main loop + // Run the application main loop while (! viewer_app_ptr->frame()) {} diff --git a/indra/newview/lldrawpoolalpha.cpp b/indra/newview/lldrawpoolalpha.cpp index 87b6ce6cb3..5379bcc985 100644 --- a/indra/newview/lldrawpoolalpha.cpp +++ b/indra/newview/lldrawpoolalpha.cpp @@ -732,15 +732,6 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, bool depth_only, bool rigged) {// If we need shaders, and we're not ALREADY using the proper shader, then bind it // (this way we won't rebind shaders unnecessarily). gPipeline.bindDeferredShaderFast(*target_shader); - - if (params.mFullbright) - { // make sure the bind the exposure map for fullbright shaders so they can cancel out exposure - S32 channel = target_shader->enableTexture(LLShaderMgr::EXPOSURE_MAP); - if (channel > -1) - { - gGL.getTexUnit(channel)->bind(&gPipeline.mExposureMap); - } - } } LLVector4 spec_color(1, 1, 1, 1); diff --git a/indra/newview/lldrawpoolbump.cpp b/indra/newview/lldrawpoolbump.cpp index bf593bff07..754fcd4c17 100644 --- a/indra/newview/lldrawpoolbump.cpp +++ b/indra/newview/lldrawpoolbump.cpp @@ -300,13 +300,6 @@ void LLDrawPoolBump::beginFullbrightShiny() shader = shader->mRiggedVariant; } - // bind exposure map so fullbright shader can cancel out exposure - S32 channel = shader->enableTexture(LLShaderMgr::EXPOSURE_MAP); - if (channel > -1) - { - gGL.getTexUnit(channel)->bind(&gPipeline.mExposureMap); - } - LLCubeMap* cube_map = gSky.mVOSkyp ? gSky.mVOSkyp->getCubeMap() : NULL; if (cube_map && !LLPipeline::sReflectionProbesEnabled) diff --git a/indra/newview/lldrawpoolwlsky.cpp b/indra/newview/lldrawpoolwlsky.cpp index 305215f541..e6d0b036e0 100644 --- a/indra/newview/lldrawpoolwlsky.cpp +++ b/indra/newview/lldrawpoolwlsky.cpp @@ -32,7 +32,6 @@ #include "llface.h" #include "llimage.h" #include "llrender.h" -#include "llatmosphere.h" #include "llenvironment.h" #include "llglslshader.h" #include "llgl.h" diff --git a/indra/newview/llenvironment.cpp b/indra/newview/llenvironment.cpp index 05bd704556..a125dcb7aa 100644 --- a/indra/newview/llenvironment.cpp +++ b/indra/newview/llenvironment.cpp @@ -54,7 +54,6 @@ #include "llregioninfomodel.h" -#include "llatmosphere.h" #include "llagent.h" #include "roles_constants.h" #include "llestateinfomodel.h" @@ -965,54 +964,6 @@ LLSettingsWater::ptr_t LLEnvironment::getCurrentWater() const return pwater; } -void LayerConfigToDensityLayer(const LLSD& layerConfig, DensityLayer& layerOut) -{ - layerOut.constant_term = (F32)layerConfig[LLSettingsSky::SETTING_DENSITY_PROFILE_CONSTANT_TERM].asReal(); - layerOut.exp_scale = (F32)layerConfig[LLSettingsSky::SETTING_DENSITY_PROFILE_EXP_SCALE_FACTOR].asReal(); - layerOut.exp_term = (F32)layerConfig[LLSettingsSky::SETTING_DENSITY_PROFILE_EXP_TERM].asReal(); - layerOut.linear_term = (F32)layerConfig[LLSettingsSky::SETTING_DENSITY_PROFILE_LINEAR_TERM].asReal(); - layerOut.width = (F32)layerConfig[LLSettingsSky::SETTING_DENSITY_PROFILE_WIDTH].asReal(); -} - -void LLEnvironment::getAtmosphericModelSettings(AtmosphericModelSettings& settingsOut, const LLSettingsSky::ptr_t &psky) -{ - settingsOut.m_skyBottomRadius = psky->getSkyBottomRadius(); - settingsOut.m_skyTopRadius = psky->getSkyTopRadius(); - settingsOut.m_sunArcRadians = psky->getSunArcRadians(); - settingsOut.m_mieAnisotropy = psky->getMieAnisotropy(); - - LLSD rayleigh = psky->getRayleighConfigs(); - settingsOut.m_rayleighProfile.clear(); - for (LLSD::array_iterator itf = rayleigh.beginArray(); itf != rayleigh.endArray(); ++itf) - { - DensityLayer layer; - LLSD& layerConfig = (*itf); - LayerConfigToDensityLayer(layerConfig, layer); - settingsOut.m_rayleighProfile.push_back(layer); - } - - LLSD mie = psky->getMieConfigs(); - settingsOut.m_mieProfile.clear(); - for (LLSD::array_iterator itf = mie.beginArray(); itf != mie.endArray(); ++itf) - { - DensityLayer layer; - LLSD& layerConfig = (*itf); - LayerConfigToDensityLayer(layerConfig, layer); - settingsOut.m_mieProfile.push_back(layer); - } - settingsOut.m_mieAnisotropy = psky->getMieAnisotropy(); - - LLSD absorption = psky->getAbsorptionConfigs(); - settingsOut.m_absorptionProfile.clear(); - for (LLSD::array_iterator itf = absorption.beginArray(); itf != absorption.endArray(); ++itf) - { - DensityLayer layer; - LLSD& layerConfig = (*itf); - LayerConfigToDensityLayer(layerConfig, layer); - settingsOut.m_absorptionProfile.push_back(layer); - } -} - bool LLEnvironment::canAgentUpdateParcelEnvironment() const { LLParcel *parcel(LLViewerParcelMgr::instance().getAgentOrSelectedParcel()); @@ -2744,13 +2695,6 @@ bool LLEnvironment::DayInstance::setSky(const LLSettingsSky::ptr_t &psky) mSky->update(); mBlenderSky.reset(); - if (gAtmosphere) - { - AtmosphericModelSettings settings; - LLEnvironment::getAtmosphericModelSettings(settings, psky); - gAtmosphere->configureAtmosphericModel(settings); - } - return changed; } diff --git a/indra/newview/llenvironment.h b/indra/newview/llenvironment.h index f1205a72b7..217c069705 100644 --- a/indra/newview/llenvironment.h +++ b/indra/newview/llenvironment.h @@ -36,8 +36,6 @@ #include "llsettingswater.h" #include "llsettingsdaycycle.h" -#include "llatmosphere.h" - #include "llglslshader.h" #include <boost/signals2.hpp> @@ -131,8 +129,6 @@ public: LLSettingsSky::ptr_t getCurrentSky() const; LLSettingsWater::ptr_t getCurrentWater() const; - static void getAtmosphericModelSettings(AtmosphericModelSettings& settingsOut, const LLSettingsSky::ptr_t &psky); - void update(const LLViewerCamera * cam); static void updateGLVariablesForSettings(LLShaderUniforms* uniforms, const LLSettingsBase::ptr_t &psetting); diff --git a/indra/newview/llfilepicker.cpp b/indra/newview/llfilepicker.cpp index d5e3627d8e..3639064cc4 100644 --- a/indra/newview/llfilepicker.cpp +++ b/indra/newview/llfilepicker.cpp @@ -36,11 +36,8 @@ #include "llviewercontrol.h" #include "llwindow.h" // beforeDialog() -#if LL_SDL -#include "llwindowsdl.h" // for some X/GTK utils to help with filepickers -#endif // LL_SDL - #if LL_LINUX +#include "llwindowsdl.h" // for some X/GTK utils to help with filepickers #include "llhttpconstants.h" // file picker uses some of thes constants on Linux #endif diff --git a/indra/newview/llfloaterjoystick.cpp b/indra/newview/llfloaterjoystick.cpp index 68b11ec92b..4736e30036 100644 --- a/indra/newview/llfloaterjoystick.cpp +++ b/indra/newview/llfloaterjoystick.cpp @@ -44,6 +44,7 @@ #include "llwindow.h" #include "llcheckboxctrl.h" #include "llcombobox.h" +#include "llgamecontrol.h" #if LL_WINDOWS && !LL_MESA_HEADLESS // Require DirectInput version 8 @@ -78,15 +79,22 @@ BOOL CALLBACK di8_list_devices_callback(LPCDIDEVICEINSTANCE device_instance_ptr, // Capable of detecting devices like Oculus Rift if (device_instance_ptr && pvRef) { + // We always include the device if it is from 3DConnexion, otherwise + // if the GameControl feature is enabled then we perfer to route other devices to it. std::string product_name = utf16str_to_utf8str(llutf16string(device_instance_ptr->tszProductName)); - S32 size = sizeof(GUID); - LLSD::Binary data; //just an std::vector - data.resize(size); - memcpy(&data[0], &device_instance_ptr->guidInstance /*POD _GUID*/, size); - - LLFloaterJoystick * floater = (LLFloaterJoystick*)pvRef; - LLSD value = data; - floater->addDevice(product_name, value); + bool include_device = LLViewerJoystick::is3DConnexionDevice(product_name) || !LLGameControl::isEnabled(); + + if (include_device) + { + S32 size = sizeof(GUID); + LLSD::Binary data; //just an std::vector + data.resize(size); + memcpy(&data[0], &device_instance_ptr->guidInstance /*POD _GUID*/, size); + + LLFloaterJoystick * floater = (LLFloaterJoystick*)pvRef; + LLSD value = data; + floater->addDevice(product_name, value); + } } return DIENUM_CONTINUE; } @@ -303,8 +311,13 @@ void LLFloaterJoystick::refreshListOfDevices() #if LL_WINDOWS && !LL_MESA_HEADLESS LL_WARNS() << "NDOF connected to device without using SL provided handle" << LL_ENDL; #endif - std::string desc = joystick->getDescription(); - if (!desc.empty()) + // We always include the device if it is from 3DConnexion, otherwise we only + // support the device in this context when GameControl feature is disabled. + std::string desc = LLViewerJoystick::getInstance()->getDescription(); + bool include_device = LLViewerJoystick::is3DConnexionDevice(desc) || + (!LLGameControl::isEnabled() && !desc.empty()); + + if (include_device) { LLSD value = LLSD::Integer(1); // value for selection addDevice(desc, value); diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index d60d41ae3c..0c96c93d31 100644 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -54,6 +54,7 @@ #include "llfloaterperformance.h" #include "llfloatersidepanelcontainer.h" #include "llfloaterimsession.h" +#include "llgamecontrol.h" #include "llkeyboard.h" #include "llmodaldialog.h" #include "llnavigationbar.h" @@ -401,6 +402,7 @@ void LLFloaterPreference::saveAvatarProperties( void ) } } +// static void LLFloaterPreference::saveAvatarPropertiesCoro(const std::string cap_url, bool allow_publish) { LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID); @@ -438,6 +440,7 @@ bool LLFloaterPreference::postBuild() mDisabledPopups = getChild<LLScrollListCtrl>("disabled_popups"); mEnablePopupBtn = getChild<LLButton>("enable_this_popup"); mDisablePopupBtn = getChild<LLButton>("disable_this_popup"); + setPanelVisibility("game_control", LLGameControl::isEnabled()); gSavedSettings.getControl("ChatFontSize")->getSignal()->connect(boost::bind(&LLFloaterIMSessionTab::processChatHistoryStyleUpdate, false)); @@ -562,21 +565,19 @@ void LLFloaterPreference::draw() void LLFloaterPreference::saveSettings() { LLTabContainer* tabcontainer = getChild<LLTabContainer>("pref core"); - child_list_t::const_iterator iter = tabcontainer->getChildList()->begin(); - child_list_t::const_iterator end = tabcontainer->getChildList()->end(); - for ( ; iter != end; ++iter) + for (LLView* view : *tabcontainer->getChildList()) { - LLView* view = *iter; - LLPanelPreference* panel = dynamic_cast<LLPanelPreference*>(view); - if (panel) + if (LLPanelPreference* panel = dynamic_cast<LLPanelPreference*>(view)) + { panel->saveSettings(); + } } saveIgnoredNotifications(); } void LLFloaterPreference::apply() { - LLAvatarPropertiesProcessor::getInstance()->addObserver( gAgent.getID(), this ); + LLAvatarPropertiesProcessor::getInstance()->addObserver(gAgent.getID(), this); LLTabContainer* tabcontainer = getChild<LLTabContainer>("pref core"); if (sSkin != gSavedSettings.getString("SkinCurrent")) @@ -584,14 +585,14 @@ void LLFloaterPreference::apply() LLNotificationsUtil::add("ChangeSkin"); refreshSkin(this); } + // Call apply() on all panels that derive from LLPanelPreference - for (child_list_t::const_iterator iter = tabcontainer->getChildList()->begin(); - iter != tabcontainer->getChildList()->end(); ++iter) + for (LLView* view : *tabcontainer->getChildList()) { - LLView* view = *iter; - LLPanelPreference* panel = dynamic_cast<LLPanelPreference*>(view); - if (panel) + if (LLPanelPreference* panel = dynamic_cast<LLPanelPreference*>(view)) + { panel->apply(); + } } gViewerWindow->requestResolutionUpdate(); // for UIScaleFactor @@ -605,7 +606,7 @@ void LLFloaterPreference::apply() LLViewerMedia::getInstance()->setCookiesEnabled(getChild<LLUICtrl>("cookies_enabled")->getValue()); - if (hasChild("web_proxy_enabled", true) &&hasChild("web_proxy_editor", true) && hasChild("web_proxy_port", true)) + if (hasChild("web_proxy_enabled", true) && hasChild("web_proxy_editor", true) && hasChild("web_proxy_port", true)) { bool proxy_enable = getChild<LLUICtrl>("web_proxy_enabled")->getValue(); std::string proxy_address = getChild<LLUICtrl>("web_proxy_editor")->getValue(); @@ -642,13 +643,12 @@ void LLFloaterPreference::cancel(const std::vector<std::string> settings_to_skip { LLTabContainer* tabcontainer = getChild<LLTabContainer>("pref core"); // Call cancel() on all panels that derive from LLPanelPreference - for (child_list_t::const_iterator iter = tabcontainer->getChildList()->begin(); - iter != tabcontainer->getChildList()->end(); ++iter) + for (LLView* view : *tabcontainer->getChildList()) { - LLView* view = *iter; - LLPanelPreference* panel = dynamic_cast<LLPanelPreference*>(view); - if (panel) + if (LLPanelPreference* panel = dynamic_cast<LLPanelPreference*>(view)) + { panel->cancel(settings_to_skip); + } } // hide joystick pref floater LLFloaterReg::hideInstance("pref_joystick"); @@ -677,7 +677,7 @@ void LLFloaterPreference::cancel(const std::vector<std::string> settings_to_skip } //Need to reload the navmesh if the pathing console is up LLHandle<LLFloaterPathfindingConsole> pathfindingConsoleHandle = LLFloaterPathfindingConsole::getInstanceHandle(); - if ( !pathfindingConsoleHandle.isDead() ) + if (!pathfindingConsoleHandle.isDead()) { LLFloaterPathfindingConsole* pPathfindingConsole = pathfindingConsoleHandle.get(); pPathfindingConsole->onRegionBoundaryCross(); @@ -694,6 +694,15 @@ void LLFloaterPreference::cancel(const std::vector<std::string> settings_to_skip void LLFloaterPreference::onOpen(const LLSD& key) { + LLTabContainer* tabcontainer = getChild<LLTabContainer>("pref core"); + for (LLView* view : *tabcontainer->getChildList()) + { + if (LLPanelPreference* panel = dynamic_cast<LLPanelPreference*>(view)) + { + panel->onOpen(key); + } + } + // this variable and if that follows it are used to properly handle do not disturb mode response message static bool initialized = false; // if user is logged in and we haven't initialized do not disturb mode response yet, do it @@ -761,8 +770,7 @@ void LLFloaterPreference::onOpen(const LLSD& key) // while preferences floater was closed. buildPopupLists(); - - //get the options that were checked + // get the options that were checked onNotificationsChange("FriendIMOptions"); onNotificationsChange("NonFriendIMOptions"); onNotificationsChange("ConferenceIMOptions"); @@ -774,8 +782,7 @@ void LLFloaterPreference::onOpen(const LLSD& key) refresh(); // Make sure the current state of prefs are saved away when - // when the floater is opened. That will make cancel do its - // job + // the floater is opened. That will make cancel() do its job saveSettings(); // Make sure there is a default preference file @@ -975,9 +982,9 @@ void LLFloaterPreference::onBtnOK(const LLSD& userdata) } //Conversation transcript and log path changed so reload conversations based on new location - if(mPriorInstantMessageLogPath.length()) + if (mPriorInstantMessageLogPath.length()) { - if(moveTranscriptsAndLog()) + if (moveTranscriptsAndLog()) { //When floaters are empty but have a chat history files, reload chat history into them LLFloaterIMSessionTab::reloadEmptyFloaters(); @@ -994,11 +1001,14 @@ void LLFloaterPreference::onBtnOK(const LLSD& userdata) LLUIColorTable::instance().saveUserSettings(); gSavedSettings.saveToFile(gSavedSettings.getString("ClientSettingsFile"), true); - //Only save once logged in and loaded per account settings - if(mGotPersonalInfo) + // save current config to settings + LLGameControl::saveToSettings(); + + // Only save once logged in and loaded per account settings + if (mGotPersonalInfo) { gSavedPerAccountSettings.saveToFile(gSavedSettings.getString("PerAccountSettingsFile"), true); - } + } } else { @@ -1039,28 +1049,38 @@ void LLFloaterPreference::onBtnCancel(const LLSD& userdata) cancel(); closeFloater(); } + + // restore config from settings + LLGameControl::loadFromSettings(); +} + +//static +void LLFloaterPreference::refreshInstance() +{ + if (LLFloaterPreference* instance = LLFloaterReg::findTypedInstance<LLFloaterPreference>("preferences")) + { + instance->refresh(); + } } // static void LLFloaterPreference::updateUserInfo(const std::string& visibility) { - LLFloaterPreference* instance = LLFloaterReg::findTypedInstance<LLFloaterPreference>("preferences"); - if (instance) + if (LLFloaterPreference* instance = LLFloaterReg::findTypedInstance<LLFloaterPreference>("preferences")) { instance->setPersonalInfo(visibility); } } +// static void LLFloaterPreference::refreshEnabledGraphics() { - LLFloaterPreference* instance = LLFloaterReg::findTypedInstance<LLFloaterPreference>("preferences"); - if (instance) + if (LLFloaterPreference* instance = LLFloaterReg::findTypedInstance<LLFloaterPreference>("preferences")) { instance->refresh(); } - LLFloater* advanced = LLFloaterReg::findTypedInstance<LLFloater>("prefs_graphics_advanced"); - if (advanced) + if (LLFloater* advanced = LLFloaterReg::findTypedInstance<LLFloater>("prefs_graphics_advanced")) { advanced->refresh(); } @@ -1095,7 +1115,7 @@ void LLFloaterPreference::onNotificationsChange(const std::string& OptionName) bool show_notifications_alert = true; for (notifications_map::iterator it_notification = mNotificationOptions.begin(); it_notification != mNotificationOptions.end(); it_notification++) { - if(it_notification->second != "No action") + if (it_notification->second != "No action") { show_notifications_alert = false; break; @@ -1107,8 +1127,7 @@ void LLFloaterPreference::onNotificationsChange(const std::string& OptionName) void LLFloaterPreference::onNameTagOpacityChange(const LLSD& newvalue) { - LLColorSwatchCtrl* color_swatch = findChild<LLColorSwatchCtrl>("background"); - if (color_swatch) + if (LLColorSwatchCtrl* color_swatch = findChild<LLColorSwatchCtrl>("background")) { LLColor4 new_color = color_swatch->get(); color_swatch->set(new_color.setAlpha((F32)newvalue.asReal())); @@ -1289,7 +1308,17 @@ void LLAvatarComplexityControls::setIndirectMaxArc() void LLFloaterPreference::refresh() { - LLPanel::refresh(); + setPanelVisibility("game_control", LLGameControl::isEnabled()); + LLTabContainer* tabcontainer = getChild<LLTabContainer>("pref core"); + for (LLView* view : *tabcontainer->getChildList()) + { + if (LLPanelPreferenceControls* panel = dynamic_cast<LLPanelPreferenceControls*>(view)) + { + panel->refresh(); + break; + } + } + LLFloater::refresh(); setMaxNonImpostorsText( gSavedSettings.getU32("RenderAvatarMaxNonImpostors"), getChild<LLTextBox>("IndirectMaxNonImpostorsText", true)); @@ -1297,8 +1326,7 @@ void LLFloaterPreference::refresh() gSavedSettings.getU32("RenderAvatarMaxComplexity"), getChild<LLTextBox>("IndirectMaxComplexityText", true)); refreshEnabledState(); - LLFloater* advanced = LLFloaterReg::findTypedInstance<LLFloater>("prefs_graphics_advanced"); - if (advanced) + if (LLFloater* advanced = LLFloaterReg::findTypedInstance<LLFloater>("prefs_graphics_advanced")) { advanced->refresh(); } @@ -1312,7 +1340,7 @@ void LLFloaterPreference::onCommitWindowedMode() void LLFloaterPreference::onChangeQuality(const LLSD& data) { - U32 level = (U32)(data.asReal()); + U32 level = (U32)data.asReal(); LLFeatureManager::getInstance()->setGraphicsLevel(level, true); refreshEnabledGraphics(); refresh(); @@ -1392,7 +1420,6 @@ void LLFloaterPreference::onClickLogPath() std::string proposed_name(gSavedPerAccountSettings.getString("InstantMessageLogPath")); mPriorInstantMessageLogPath.clear(); - (new LLDirPickerThread(boost::bind(&LLFloaterPreference::changeLogPath, this, _1, _2), proposed_name))->getFile(); } @@ -1417,10 +1444,10 @@ bool LLFloaterPreference::moveTranscriptsAndLog() bool madeDirectory = false; //Does the directory really exist, if not then make it - if(!LLFile::isdir(chatLogPath)) + if (!LLFile::isdir(chatLogPath)) { //mkdir success is defined as zero - if(LLFile::mkdir(chatLogPath) != 0) + if (LLFile::mkdir(chatLogPath) != 0) { return false; } @@ -1430,10 +1457,10 @@ bool LLFloaterPreference::moveTranscriptsAndLog() std::string originalConversationLogDir = LLConversationLog::instance().getFileName(); std::string targetConversationLogDir = gDirUtilp->add(chatLogPath, "conversation.log"); //Try to move the conversation log - if(!LLConversationLog::instance().moveLog(originalConversationLogDir, targetConversationLogDir)) + if (!LLConversationLog::instance().moveLog(originalConversationLogDir, targetConversationLogDir)) { //Couldn't move the log and created a new directory so remove the new directory - if(madeDirectory) + if (madeDirectory) { LLFile::rmdir(chatLogPath); } @@ -1446,7 +1473,7 @@ bool LLFloaterPreference::moveTranscriptsAndLog() LLLogChat::getListOfTranscriptFiles(listOfTranscripts); - if(!LLLogChat::moveTranscripts(gDirUtilp->getChatLogsDir(), + if (!LLLogChat::moveTranscripts(gDirUtilp->getChatLogsDir(), instantMessageLogPath, listOfTranscripts, listOfFilesMoved)) @@ -1459,7 +1486,7 @@ bool LLFloaterPreference::moveTranscriptsAndLog() //Move the conversation log back LLConversationLog::instance().moveLog(targetConversationLogDir, originalConversationLogDir); - if(madeDirectory) + if (madeDirectory) { LLFile::rmdir(chatLogPath); } @@ -1506,7 +1533,6 @@ void LLFloaterPreference::setPersonalInfo(const std::string& visibility) getChild<LLUICtrl>("voice_call_friends_only_check")->setValue(gSavedPerAccountSettings.getBOOL("VoiceCallsFriendsOnly")); } - void LLFloaterPreference::refreshUI() { refresh(); @@ -1790,8 +1816,7 @@ void LLFloaterPreference::onClickActionChange() void LLFloaterPreference::onAtmosShaderChange() { - LLCheckBoxCtrl* ctrl_alm = getChild<LLCheckBoxCtrl>("UseLightShaders"); - if(ctrl_alm) + if (LLCheckBoxCtrl* ctrl_alm = getChild<LLCheckBoxCtrl>("UseLightShaders")) { //Deferred/SSAO/Shadows bool bumpshiny = LLCubeMap::sUseCubeMaps && LLFeatureManager::getInstance()->isFeatureAvailable("RenderObjectBump") && gSavedSettings.getBOOL("RenderObjectBump"); @@ -1852,12 +1877,9 @@ void LLFloaterPreference::updateClickActionControls() // In such case we won't need to do this 'dynamic_cast' nightmare. // updateTable() can also be avoided LLTabContainer* tabcontainer = getChild<LLTabContainer>("pref core"); - for (child_list_t::const_iterator iter = tabcontainer->getChildList()->begin(); - iter != tabcontainer->getChildList()->end(); ++iter) + for (LLView* view : *tabcontainer->getChildList()) { - LLView* view = *iter; - LLPanelPreferenceControls* panel = dynamic_cast<LLPanelPreferenceControls*>(view); - if (panel) + if (LLPanelPreferenceControls* panel = dynamic_cast<LLPanelPreferenceControls*>(view)) { panel->setKeyBind("walk_to", EMouseClickType::CLICK_LEFT, @@ -1891,12 +1913,9 @@ void LLFloaterPreference::updateClickActionViews() // Todo: This is a very ugly way to get access to keybindings. // Reconsider possible options. LLTabContainer* tabcontainer = getChild<LLTabContainer>("pref core"); - for (child_list_t::const_iterator iter = tabcontainer->getChildList()->begin(); - iter != tabcontainer->getChildList()->end(); ++iter) + for (LLView* view : *tabcontainer->getChildList()) { - LLView* view = *iter; - LLPanelPreferenceControls* panel = dynamic_cast<LLPanelPreferenceControls*>(view); - if (panel) + if (LLPanelPreferenceControls* panel = dynamic_cast<LLPanelPreferenceControls*>(view)) { click_to_walk = panel->canKeyBindHandle("walk_to", EMouseClickType::CLICK_LEFT, @@ -1952,6 +1971,16 @@ void LLFloaterPreference::selectPanel(const LLSD& name) } } +void LLFloaterPreference::setPanelVisibility(const LLSD& name, bool visible) +{ + LLTabContainer * tab_containerp = getChild<LLTabContainer>("pref core"); + LLPanel * panel = tab_containerp->getPanelByName(name.asStringRef()); + if (NULL != panel) + { + tab_containerp->setTabVisibility(panel, visible); + } +} + void LLFloaterPreference::selectPrivacyPanel() { selectPanel("im"); @@ -1968,7 +1997,6 @@ void LLFloaterPreference::changed() // set 'enable' property for 'Delete transcripts...' button updateDeleteTranscriptsButton(); - } void LLFloaterPreference::saveGraphicsPreset(std::string& preset) @@ -2076,7 +2104,6 @@ bool LLPanelPreference::postBuild() if (hasChild("media_enabled", true)) { bool media_enabled = gSavedSettings.getBOOL("AudioStreamingMedia"); - getChild<LLCheckBoxCtrl>("media_enabled")->set(media_enabled); getChild<LLCheckBoxCtrl>("autoplay_enabled")->setEnabled(media_enabled); } @@ -2133,41 +2160,41 @@ LLPanelPreference::~LLPanelPreference() delete mBandWidthUpdater; } } + +// virtual void LLPanelPreference::apply() { // no-op } +// virtual void LLPanelPreference::saveSettings() { - LLFloater* advanced = LLFloaterReg::findTypedInstance<LLFloater>("prefs_graphics_advanced"); - // Save the value of all controls in the hierarchy mSavedValues.clear(); std::list<LLView*> view_stack; view_stack.push_back(this); - if (advanced) + // Search for 'Advanced' panel and add it if found + if (LLFloater* advanced = LLFloaterReg::findTypedInstance<LLFloater>("prefs_graphics_advanced")) { view_stack.push_back(advanced); } - while(!view_stack.empty()) + + while (!view_stack.empty()) { // Process view on top of the stack LLView* curview = view_stack.front(); view_stack.pop_front(); - LLColorSwatchCtrl* color_swatch = dynamic_cast<LLColorSwatchCtrl *>(curview); - if (color_swatch) + if (LLColorSwatchCtrl* color_swatch = dynamic_cast<LLColorSwatchCtrl*>(curview)) { mSavedColors[color_swatch->getName()] = color_swatch->get(); } else { - LLUICtrl* ctrl = dynamic_cast<LLUICtrl*>(curview); - if (ctrl) + if (LLUICtrl* ctrl = dynamic_cast<LLUICtrl*>(curview)) { - LLControlVariable* control = ctrl->getControlVariable(); - if (control) + if (LLControlVariable* control = ctrl->getControlVariable()) { mSavedValues[control] = control->getValue(); } @@ -2175,10 +2202,9 @@ void LLPanelPreference::saveSettings() } // Push children onto the end of the work stack - for (child_list_t::const_iterator iter = curview->getChildList()->begin(); - iter != curview->getChildList()->end(); ++iter) + for (LLView* view : *curview->getChildList()) { - view_stack.push_back(*iter); + view_stack.push_back(view); } } @@ -2320,7 +2346,7 @@ public: mAccountIndependentSettings.push_back("AutoDisengageMic"); } - /*virtual*/ void saveSettings() + void saveSettings() override { LLPanelPreference::saveSettings(); @@ -2335,7 +2361,7 @@ public: if (find(mAccountIndependentSettings.begin(), mAccountIndependentSettings.end(), setting) == mAccountIndependentSettings.end()) { - mSavedValues.erase(it++); + it = mSavedValues.erase(it); } else { @@ -2499,9 +2525,11 @@ void LLPanelPreferenceGraphics::cancel(const std::vector<std::string> settings_t { LLPanelPreference::cancel(settings_to_skip); } + void LLPanelPreferenceGraphics::saveSettings() { resetDirtyChilds(); + std::string preset_graphic_active = gSavedSettings.getString("PresetGraphicActive"); if (preset_graphic_active.empty()) { @@ -2512,8 +2540,10 @@ void LLPanelPreferenceGraphics::saveSettings() instance->saveGraphicsPreset(preset_graphic_active); } } + LLPanelPreference::saveSettings(); } + void LLPanelPreferenceGraphics::setHardwareDefaults() { resetDirtyChilds(); @@ -2538,6 +2568,12 @@ LLPanelPreferenceControls::~LLPanelPreferenceControls() { } +void LLPanelPreferenceControls::refresh() +{ + populateControlTable(); + LLPanelPreference::refresh(); +} + bool LLPanelPreferenceControls::postBuild() { // populate list of controls @@ -2609,12 +2645,9 @@ bool LLPanelPreferenceControls::addControlTableRows(const std::string &filename) cell_params.column = ""; cell_params.value = ""; - - for (LLInitParam::ParamIterator<LLScrollListItem::Params>::const_iterator row_it = contents.rows.begin(); - row_it != contents.rows.end(); - ++row_it) + for (LLScrollListItem::Params& row_params : contents.rows) { - std::string control = row_it->value.getValue().asString(); + std::string control = row_params.value.getValue().asString(); if (!control.empty() && control != "menu_separator") { bool show = true; @@ -2633,7 +2666,7 @@ bool LLPanelPreferenceControls::addControlTableRows(const std::string &filename) if (show) { // At the moment viewer is hardcoded to assume that columns are named as lst_ctrl%d - LLScrollListItem::Params item_params(*row_it); + LLScrollListItem::Params item_params(row_params); item_params.enabled.setValue(enabled); S32 num_columns = pControlsTable->getNumColumns(); @@ -2658,7 +2691,7 @@ bool LLPanelPreferenceControls::addControlTableRows(const std::string &filename) // value = "menu_separator" // column = "lst_action" / > //</rows> - pControlsTable->addRow(*row_it, EAddPosition::ADD_BOTTOM); + pControlsTable->addRow(row_params, EAddPosition::ADD_BOTTOM); } } return true; @@ -2718,6 +2751,11 @@ void LLPanelPreferenceControls::populateControlTable() addControlTableRows("control_table_contents_movement.xml"); addControlTableSeparator(); addControlTableRows("control_table_contents_media.xml"); + addControlTableSeparator(); + if (LLGameControl::isEnabled()) + { + addControlTableRows("control_table_contents_game_control.xml"); + } } // MODE_THIRD_PERSON; MODE_EDIT_AVATAR; MODE_SITTING else if (mEditingMode < LLKeyConflictHandler::MODE_SAVED_SETTINGS) @@ -2734,6 +2772,12 @@ void LLPanelPreferenceControls::populateControlTable() addControlTableSeparator(); addControlTableRows("control_table_contents_media.xml"); + addControlTableSeparator(); + + if (LLGameControl::isEnabled()) + { + addControlTableRows("control_table_contents_game_control.xml"); + } } else { @@ -3109,6 +3153,7 @@ void LLPanelPreferenceControls::onDefaultKeyBind(bool all_modes) mConflictHandler[mEditingMode].saveToSettings(true); } } + updateTable(); if (mEditingMode == LLKeyConflictHandler::MODE_THIRD_PERSON || all_modes) @@ -3127,6 +3172,923 @@ void LLPanelPreferenceControls::onCancelKeyBind() pControlsTable->deselectAllItems(); } +//------------------------LLPanelPreferenceGameControl-------------------------------- + +// LLPanelPreferenceGameControl is effectively a singleton, so we track its instance +static LLPanelPreferenceGameControl* gGameControlPanel { nullptr }; +static LLScrollListCtrl* gSelectedGrid { nullptr }; +static LLScrollListItem* gSelectedItem { nullptr }; +static LLScrollListCell* gSelectedCell { nullptr }; + +// static +void LLPanelPreferenceGameControl::updateDeviceList() +{ + if (gGameControlPanel) + { + gGameControlPanel->updateDeviceListInternal(); + } +} + +LLPanelPreferenceGameControl::LLPanelPreferenceGameControl() +{ + gGameControlPanel = this; +} + +LLPanelPreferenceGameControl::~LLPanelPreferenceGameControl() +{ + gGameControlPanel = nullptr; +} + +static LLPanelInjector<LLPanelPreferenceGameControl> t_pref_game_control("panel_preference_game_control"); + +// Collect all UI control values into mSavedValues +void LLPanelPreferenceGameControl::saveSettings() +{ + LLPanelPreference::saveSettings(); + + std::vector<LLScrollListItem*> items = mActionTable->getAllData(); + + // Find the channel visually associated with the specified action + LLGameControl::getChannel_t getChannel = + [&](const std::string& action) -> LLGameControl::InputChannel + { + for (LLScrollListItem* item : items) + { + if (action == item->getValue() && (item->getNumColumns() >= 2)) + { + return LLGameControl::getChannelByName(item->getColumn(1)->getValue()); + } + } + return LLGameControl::InputChannel(); + }; + + // Use string formatting functions provided by class LLGameControl: + if (LLControlVariable* analogMappings = gSavedSettings.getControl("AnalogChannelMappings")) + { + analogMappings->set(LLGameControl::stringifyAnalogMappings(getChannel)); + mSavedValues[analogMappings] = analogMappings->getValue(); + } + + if (LLControlVariable* binaryMappings = gSavedSettings.getControl("BinaryChannelMappings")) + { + binaryMappings->set(LLGameControl::stringifyBinaryMappings(getChannel)); + mSavedValues[binaryMappings] = binaryMappings->getValue(); + } + + if (LLControlVariable* flycamMappings = gSavedSettings.getControl("FlycamChannelMappings")) + { + flycamMappings->set(LLGameControl::stringifyFlycamMappings(getChannel)); + mSavedValues[flycamMappings] = flycamMappings->getValue(); + } + + if (LLControlVariable* knownControllers = gSavedSettings.getControl("KnownGameControllers")) + { + LLSD deviceOptions(LLSD::emptyMap()); + for (auto& pair : mDeviceOptions) + { + pair.second.settings = pair.second.options.saveToString(pair.second.name); + if (!pair.second.settings.empty()) + { + deviceOptions.insert(pair.first, pair.second.settings); + } + } + knownControllers->set(deviceOptions); + mSavedValues[knownControllers] = deviceOptions; + } +} + +void LLPanelPreferenceGameControl::onGridSelect(LLUICtrl* ctrl) +{ + clearSelectionState(); + + LLScrollListCtrl* table = dynamic_cast<LLScrollListCtrl*>(ctrl); + if (!table || !table->getEnabled()) + return; + + if (LLScrollListItem* item = table->getFirstSelected()) + { + if (initCombobox(item, table)) + return; + + table->deselectAllItems(); + } +} + +bool LLPanelPreferenceGameControl::initCombobox(LLScrollListItem* item, LLScrollListCtrl* grid) +{ + if (item->getSelectedCell() != 1) + return false; + + LLScrollListText* cell = dynamic_cast<LLScrollListText*>(item->getColumn(1)); + if (!cell) + return false; + + LLComboBox* combobox = nullptr; + if (grid == mActionTable) + { + std::string action = item->getValue(); + LLGameControl::ActionNameType actionNameType = LLGameControl::getActionNameType(action); + combobox = + actionNameType == LLGameControl::ACTION_NAME_ANALOG ? mAnalogChannelSelector : + actionNameType == LLGameControl::ACTION_NAME_BINARY ? mBinaryChannelSelector : + actionNameType == LLGameControl::ACTION_NAME_FLYCAM ? mAnalogChannelSelector : + nullptr; + } + else if (grid == mAxisMappings) + { + combobox = mAxisSelector; + } + else if (grid == mButtonMappings) + { + combobox = mBinaryChannelSelector; + } + if (!combobox) + return false; + + // compute new rect for combobox + S32 row_index = grid->getItemIndex(item); + fitInRect(combobox, grid, row_index, 1); + + std::string channel_name = "NONE"; + std::string cell_value = cell->getValue(); + std::vector<LLScrollListItem*> items = combobox->getAllData(); + for (const LLScrollListItem* item : items) + { + if (item->getColumn(0)->getValue().asString() == cell_value) + { + channel_name = item->getValue().asString(); + break; + } + } + + std::string value; + LLGameControl::InputChannel channel = LLGameControl::getChannelByName(channel_name); + if (!channel.isNone()) + { + std::string channel_name = channel.getLocalName(); + std::string channel_label = getChannelLabel(channel_name, combobox->getAllData()); + if (combobox->itemExists(channel_label)) + { + value = channel_name; + } + } + if (value.empty()) + { + // Assign the last element in the dropdown list which is "NONE" + value = combobox->getAllData().back()->getValue().asString(); + } + + combobox->setValue(value); + combobox->setVisible(true); + combobox->showList(); + + gSelectedGrid = grid; + gSelectedItem = item; + gSelectedCell = cell; + + return true; +} + +void LLPanelPreferenceGameControl::onCommitInputChannel(LLUICtrl* ctrl) +{ + if (!gSelectedGrid || !gSelectedItem || !gSelectedCell) + return; + + LLComboBox* combobox = dynamic_cast<LLComboBox*>(ctrl); + llassert(combobox); + if (!combobox) + return; + + if (gSelectedGrid == mActionTable) + { + std::string value = combobox->getValue(); + std::string label = (value == "NONE") ? + LLStringUtil::null : combobox->getSelectedItemLabel(); + gSelectedCell->setValue(label); + } + else + { + S32 chosen_index = combobox->getCurrentIndex(); + if (chosen_index >= 0) + { + int row_index = gSelectedGrid->getItemIndex(gSelectedItem); + llassert(row_index >= 0); + LLGameControl::Options& deviceOptions = getSelectedDeviceOptions(); + std::vector<U8>& map = gSelectedGrid == mAxisMappings ? + deviceOptions.getAxisMap() : deviceOptions.getButtonMap(); + if (chosen_index >= map.size()) + { + chosen_index = row_index; + } + std::string label = chosen_index == row_index ? + LLStringUtil::null : combobox->getSelectedItemLabel(); + gSelectedCell->setValue(label); + map[row_index] = chosen_index; + } + } + gSelectedGrid->deselectAllItems(); + clearSelectionState(); +} + +bool LLPanelPreferenceGameControl::isWaitingForInputChannel() +{ + return gSelectedCell != nullptr; +} + +// static +void LLPanelPreferenceGameControl::applyGameControlInput() +{ + if (!gGameControlPanel || !gSelectedGrid || !gSelectedCell) + return; + + LLComboBox* combobox; + LLGameControl::InputChannel::Type expectedType; + if (gGameControlPanel->mAnalogChannelSelector->getVisible()) + { + combobox = gGameControlPanel->mAnalogChannelSelector; + expectedType = LLGameControl::InputChannel::TYPE_AXIS; + } + else if (gGameControlPanel->mBinaryChannelSelector->getVisible()) + { + combobox = gGameControlPanel->mBinaryChannelSelector; + expectedType = LLGameControl::InputChannel::TYPE_BUTTON; + } + else + { + return; + } + + LLGameControl::InputChannel channel = LLGameControl::getActiveInputChannel(); + if (channel.mType == expectedType) + { + std::string channel_name = channel.getLocalName(); + std::string channel_label = LLPanelPreferenceGameControl::getChannelLabel(channel_name, combobox->getAllData()); + gSelectedCell->setValue(channel_label); + gSelectedGrid->deselectAllItems(); + gGameControlPanel->clearSelectionState(); + } +} + +void LLPanelPreferenceGameControl::onAxisOptionsSelect() +{ + clearSelectionState(); + + if (LLScrollListItem* row = mAxisOptions->getFirstSelected()) + { + LLGameControl::Options& options = getSelectedDeviceOptions(); + S32 row_index = mAxisOptions->getItemIndex(row); + + { + // always update invert checkbox value because even though it may have been clicked + // the row does not know its cell has been selected + constexpr S32 invert_checkbox_column = 1; + bool invert = row->getColumn(invert_checkbox_column)->getValue().asBoolean(); + options.getAxisOptions()[row_index].mMultiplier = invert ? -1 : 1; + } + + S32 column_index = row->getSelectedCell(); + if (column_index == 2 || column_index == 3) + { + fitInRect(mNumericValueEditor, mAxisOptions, row_index, column_index); + if (column_index == 2) + { + mNumericValueEditor->setMinValue(0); + mNumericValueEditor->setMaxValue(LLGameControl::MAX_AXIS_DEAD_ZONE); + mNumericValueEditor->setValue(options.getAxisOptions()[row_index].mDeadZone); + } + else // column_index == 3 + { + mNumericValueEditor->setMinValue(-LLGameControl::MAX_AXIS_OFFSET); + mNumericValueEditor->setMaxValue(LLGameControl::MAX_AXIS_OFFSET); + mNumericValueEditor->setValue(options.getAxisOptions()[row_index].mOffset); + } + mNumericValueEditor->setVisible(true); + } + + initCombobox(row, mAxisOptions); + + LLGameControl::setDeviceOptions(mSelectedDeviceGUID, options); + } +} + +void LLPanelPreferenceGameControl::onCommitNumericValue() +{ + if (LLScrollListItem* row = mAxisOptions->getFirstSelected()) + { + LLGameControl::Options& deviceOptions = getSelectedDeviceOptions(); + S32 value = mNumericValueEditor->getValue().asInteger(); + S32 row_index = mAxisOptions->getItemIndex(row); + S32 column_index = row->getSelectedCell(); + llassert(column_index == 2 || column_index == 3); + if (column_index < 2 || column_index > 3) + return; + + if (column_index == 2) + { + value = std::clamp<S32>(value, 0, LLGameControl::MAX_AXIS_DEAD_ZONE); + deviceOptions.getAxisOptions()[row_index].mDeadZone = (U16)value; + } + else // column_index == 3 + { + value = std::clamp<S32>(value, -LLGameControl::MAX_AXIS_OFFSET, LLGameControl::MAX_AXIS_OFFSET); + deviceOptions.getAxisOptions()[row_index].mOffset = (S16)value; + } + setNumericLabel(row->getColumn(column_index), value); + LLGameControl::setDeviceOptions(mSelectedDeviceGUID, deviceOptions); + } +} + +bool LLPanelPreferenceGameControl::postBuild() +{ + // Above the tab container + mCheckGameControlToServer = getChild<LLCheckBoxCtrl>("game_control_to_server"); + mCheckGameControlToAgent = getChild<LLCheckBoxCtrl>("game_control_to_agent"); + mCheckAgentToGameControl = getChild<LLCheckBoxCtrl>("agent_to_game_control"); + + mCheckGameControlToServer->setCommitCallback([this](LLUICtrl*, const LLSD&) + { + LLGameControl::setSendToServer(mCheckGameControlToServer->getValue()); + updateActionTableState(); + }); + mCheckGameControlToAgent->setCommitCallback([this](LLUICtrl*, const LLSD&) + { + LLGameControl::setControlAgent(mCheckGameControlToAgent->getValue()); + updateActionTableState(); + }); + mCheckAgentToGameControl->setCommitCallback([this](LLUICtrl*, const LLSD&) + { + LLGameControl::setTranslateAgentActions(mCheckAgentToGameControl->getValue()); + updateActionTableState(); + }); + + getChild<LLTabContainer>("game_control_tabs")->setCommitCallback([this](LLUICtrl*, const LLSD&) { clearSelectionState(); }); + getChild<LLTabContainer>("device_settings_tabs")->setCommitCallback([this](LLUICtrl*, const LLSD&) { clearSelectionState(); }); + + // 1st tab "Channel mappings" + mTabChannelMappings = getChild<LLPanel>("tab_channel_mappings"); + mActionTable = getChild<LLScrollListCtrl>("action_table"); + mActionTable->setCommitCallback([this](LLUICtrl* ctrl, const LLSD&) { onGridSelect(ctrl); }); + + // 2nd tab "Device settings" + mTabDeviceSettings = getChild<LLPanel>("tab_device_settings"); + mNoDeviceMessage = getChild<LLTextBox>("nodevice_message"); + mDevicePrompt = getChild<LLTextBox>("device_prompt"); + mSingleDevice = getChild<LLTextBox>("single_device"); + mDeviceList = getChild<LLComboBox>("device_list"); + mCheckShowAllDevices = getChild<LLCheckBoxCtrl>("show_all_known_devices"); + mPanelDeviceSettings = getChild<LLPanel>("device_settings"); + + mCheckShowAllDevices->setCommitCallback([this](LLUICtrl*, const LLSD&) { populateDeviceTitle(); }); + mDeviceList->setCommitCallback([this](LLUICtrl*, const LLSD& value) { populateDeviceSettings(value); }); + + mTabAxisOptions = getChild<LLPanel>("tab_axis_options"); + mAxisOptions = getChild<LLScrollListCtrl>("axis_options"); + mAxisOptions->setCommitCallback([this](LLUICtrl*, const LLSD&) { onAxisOptionsSelect(); }); + + mTabAxisMappings = getChild<LLPanel>("tab_axis_mappings"); + mAxisMappings = getChild<LLScrollListCtrl>("axis_mappings"); + mAxisMappings->setCommitCallback([this](LLUICtrl* ctrl, const LLSD&) { onGridSelect(ctrl); }); + + mTabButtonMappings = getChild<LLPanel>("tab_button_mappings"); + mButtonMappings = getChild<LLScrollListCtrl>("button_mappings"); + mButtonMappings->setCommitCallback([this](LLUICtrl* ctrl, const LLSD&) { onGridSelect(ctrl); }); + + mResetToDefaults = getChild<LLButton>("reset_to_defaults"); + mResetToDefaults->setCommitCallback([this](LLUICtrl* ctrl, const LLSD&) { onResetToDefaults(); }); + + // Numeric value editor + mNumericValueEditor = getChild<LLSpinCtrl>("numeric_value_editor"); + mNumericValueEditor->setCommitCallback([this](LLUICtrl*, const LLSD&) { onCommitNumericValue(); }); + + // Channel selectors + mAnalogChannelSelector = getChild<LLComboBox>("analog_channel_selector"); + mAnalogChannelSelector->setCommitCallback([this](LLUICtrl* ctrl, const LLSD&) { onCommitInputChannel(ctrl); }); + + mBinaryChannelSelector = getChild<LLComboBox>("binary_channel_selector"); + mBinaryChannelSelector->setCommitCallback([this](LLUICtrl* ctrl, const LLSD&) { onCommitInputChannel(ctrl); }); + + mAxisSelector = getChild<LLComboBox>("axis_selector"); + mAxisSelector->setCommitCallback([this](LLUICtrl* ctrl, const LLSD&) { onCommitInputChannel(ctrl); }); + + // Setup the 1st tab + populateActionTableRows("game_control_table_rows.xml"); + addActionTableSeparator(); + populateActionTableRows("game_control_table_camera_rows.xml"); + + // Setup the 2nd tab + populateOptionsTableRows(); + populateMappingTableRows(mAxisMappings, mAxisSelector, LLGameControl::NUM_AXES); + populateMappingTableRows(mButtonMappings, mBinaryChannelSelector, LLGameControl::NUM_BUTTONS); + + // Workaround for the common bug: + // LLScrollListCtrl with draw_heading="true" initially has incorrect mTop (17 px higher) + LLRect rect = mAxisOptions->getRect(); + rect.mTop = mAxisOptions->getParent()->getRect().getHeight() - 1; + mAxisOptions->setRect(rect); + mAxisOptions->updateLayout(); + + return true; +} + +// Update all UI control values from real objects +// This function is called before floater is shown +void LLPanelPreferenceGameControl::onOpen(const LLSD& key) +{ + mCheckGameControlToServer->setValue(LLGameControl::getSendToServer()); + mCheckGameControlToAgent->setValue(LLGameControl::getControlAgent()); + mCheckAgentToGameControl->setValue(LLGameControl::getTranslateAgentActions()); + + clearSelectionState(); + + // Setup the 1st tab + populateActionTableCells(); + updateActionTableState(); + + updateDeviceListInternal(); + updateEnable(); +} + +void LLPanelPreferenceGameControl::updateDeviceListInternal() +{ + // Setup the 2nd tab + mDeviceOptions.clear(); + for (const auto& pair : LLGameControl::getDeviceOptions()) + { + DeviceOptions deviceOptions = { LLStringUtil::null, pair.second, LLGameControl::Options() }; + deviceOptions.options.loadFromString(deviceOptions.name, deviceOptions.settings); + mDeviceOptions.emplace(pair.first, deviceOptions); + } + // Add missing device settings/options even if they are default + for (const auto& device : LLGameControl::getDevices()) + { + if (mDeviceOptions.find(device.getGUID()) == mDeviceOptions.end()) + { + mDeviceOptions[device.getGUID()] = { device.getName(), device.saveOptionsToString(true), device.getOptions() }; + } + } + mCheckShowAllDevices->setValue(false); + populateDeviceTitle(); +} + +void LLPanelPreferenceGameControl::populateActionTableRows(const std::string& filename) +{ + LLScrollListCtrl::Contents contents; + if (!parseXmlFile(contents, filename, "rows")) + return; + + // init basic cell params + LLScrollListCell::Params second_cell_params; + second_cell_params.font = LLFontGL::getFontSansSerif(); + second_cell_params.font_halign = LLFontGL::LEFT; + second_cell_params.column = mActionTable->getColumn(1)->mName; + second_cell_params.value = ""; // Actual value is assigned in populateActionTableCells + + for (const LLScrollListItem::Params& row_params : contents.rows) + { + std::string name = row_params.value.getValue().asString(); + if (!name.empty() && name != "menu_separator") + { + LLScrollListItem::Params new_params(row_params); + new_params.enabled.setValue(true); + // item_params should already have one column that was defined + // in XUI config file, and now we want to add one more + if (new_params.columns.size() == 1) + { + new_params.columns.add(second_cell_params); + } + mActionTable->addRow(new_params, EAddPosition::ADD_BOTTOM); + } + else + { + mActionTable->addRow(row_params, EAddPosition::ADD_BOTTOM); + } + } +} + +void LLPanelPreferenceGameControl::populateActionTableCells() +{ + std::vector<LLScrollListItem*> rows = mActionTable->getAllData(); + std::vector<LLScrollListItem*> axes = mAnalogChannelSelector->getAllData(); + std::vector<LLScrollListItem*> btns = mBinaryChannelSelector->getAllData(); + + for (LLScrollListItem* row : rows) + { + if (row->getNumColumns() >= 2) // Skip separators + { + std::string name = row->getValue().asString(); + if (!name.empty() && name != "menu_separator") + { + LLGameControl::InputChannel channel = LLGameControl::getChannelByAction(name); + std::string channel_name = channel.getLocalName(); + std::string channel_label = + channel.isAxis() ? getChannelLabel(channel_name, axes) : + channel.isButton() ? getChannelLabel(channel_name, btns) : + LLStringUtil::null; + row->getColumn(1)->setValue(channel_label); + } + } + } +} + +// static +bool LLPanelPreferenceGameControl::parseXmlFile(LLScrollListCtrl::Contents& contents, + const std::string& filename, const std::string& what) +{ + LLXMLNodePtr xmlNode; + if (!LLUICtrlFactory::getLayeredXMLNode(filename, xmlNode)) + { + LL_WARNS("Preferences") << "Failed to populate " << what << " from '" << filename << "'" << LL_ENDL; + return false; + } + + LLXUIParser parser; + parser.readXUI(xmlNode, contents, filename); + if (!contents.validateBlock()) + { + LL_WARNS("Preferences") << "Failed to parse " << what << " from '" << filename << "'" << LL_ENDL; + return false; + } + + return true; +} + +void LLPanelPreferenceGameControl::populateDeviceTitle() +{ + mSelectedDeviceGUID.clear(); + + bool showAllDevices = mCheckShowAllDevices->getValue().asBoolean(); + std::size_t deviceCount = showAllDevices ? mDeviceOptions.size() : LLGameControl::getDevices().size(); + + mNoDeviceMessage->setVisible(!deviceCount); + mDevicePrompt->setVisible(deviceCount); + mSingleDevice->setVisible(deviceCount == 1); + mDeviceList->setVisible(deviceCount > 1); + mPanelDeviceSettings->setVisible(deviceCount); + + auto makeTitle = [](const std::string& guid, const std::string& name) -> std::string + { + return guid + ", " + name; + }; + + if (deviceCount == 1) + { + if (showAllDevices) + { + const std::pair<std::string, DeviceOptions>& pair = *mDeviceOptions.begin(); + mSingleDevice->setValue(makeTitle(pair.first, pair.second.name)); + populateDeviceSettings(pair.first); + } + else + { + const LLGameControl::Device& device = LLGameControl::getDevices().front(); + mSingleDevice->setValue(makeTitle(device.getGUID(), device.getName())); + populateDeviceSettings(device.getGUID()); + } + } + else if (deviceCount) + { + mDeviceList->clear(); + mDeviceList->clearRows(); + + auto makeListItem = [](const std::string& guid, const std::string& title) + { + return LLSD().with("value", guid).with("columns", LLSD().with("label", title)); + }; + + if (showAllDevices) + { + for (const auto& pair : mDeviceOptions) + { + mDeviceList->addElement(makeListItem(pair.first, makeTitle(pair.first, pair.second.name))); + } + } + else + { + for (const LLGameControl::Device& device : LLGameControl::getDevices()) + { + mDeviceList->addElement(makeListItem(device.getGUID(), makeTitle(device.getGUID(), device.getName()))); + } + } + + mDeviceList->selectNthItem(0); + populateDeviceSettings(mDeviceList->getValue()); + } +} + +void LLPanelPreferenceGameControl::populateDeviceSettings(const std::string& guid) +{ + LL_INFOS() << "guid: '" << guid << "'" << LL_ENDL; + + mSelectedDeviceGUID = guid; + auto options_it = mDeviceOptions.find(guid); + llassert_always(options_it != mDeviceOptions.end()); + const DeviceOptions& deviceOptions = options_it->second; + + populateOptionsTableCells(); + populateMappingTableCells(mAxisMappings, deviceOptions.options.getAxisMap(), mAxisSelector); + populateMappingTableCells(mButtonMappings, deviceOptions.options.getButtonMap(), mBinaryChannelSelector); +} + +void LLPanelPreferenceGameControl::populateOptionsTableRows() +{ + mAxisOptions->clearRows(); + + std::vector<LLScrollListItem*> items = mAnalogChannelSelector->getAllData(); + + LLScrollListItem::Params row_params; + LLScrollListCell::Params cell_params; + cell_params.font = LLFontGL::getFontMonospace(); + for (size_t i = 0; i < mAxisOptions->getNumColumns(); ++i) + { + row_params.columns.add(cell_params); + } + + row_params.columns(1).type = "checkbox"; + row_params.columns(2).font_halign = "right"; + row_params.columns(3).font_halign = "right"; + + for (size_t i = 0; i < LLGameControl::NUM_AXES; ++i) + { + LLScrollListItem* row = mAxisOptions->addRow(row_params); + row->getColumn(0)->setValue(items[i]->getColumn(0)->getValue()); + } +} + +void LLPanelPreferenceGameControl::populateOptionsTableCells() +{ + std::vector<LLScrollListItem*> rows = mAxisOptions->getAllData(); + const auto& all_axis_options = getSelectedDeviceOptions().getAxisOptions(); + llassert(rows.size() == all_axis_options.size()); + + for (size_t i = 0; i < rows.size(); ++i) + { + LLScrollListItem* row = rows[i]; + const LLGameControl::Options::AxisOptions& axis_options = all_axis_options[i]; + row->getColumn(1)->setValue(axis_options.mMultiplier == -1 ? true : false); + setNumericLabel(row->getColumn(2), axis_options.mDeadZone); + setNumericLabel(row->getColumn(3), axis_options.mOffset); + } +} + +void LLPanelPreferenceGameControl::populateMappingTableRows(LLScrollListCtrl* target, + const LLComboBox* source, size_t row_count) +{ + target->clearRows(); + + std::vector<LLScrollListItem*> items = source->getAllData(); + + LLScrollListItem::Params row_params; + LLScrollListCell::Params cell_params; + cell_params.font = LLFontGL::getFontMonospace(); + for (size_t i = 0; i < target->getNumColumns(); ++i) + { + row_params.columns.add(cell_params); + } + + for (size_t i = 0; i < row_count; ++i) + { + LLScrollListItem* row = target->addRow(row_params); + row->getColumn(0)->setValue(items[i]->getColumn(0)->getValue()); + } +} + +void LLPanelPreferenceGameControl::populateMappingTableCells(LLScrollListCtrl* target, + const std::vector<U8>& mappings, const LLComboBox* source) +{ + std::vector<LLScrollListItem*> rows = target->getAllData(); + std::vector<LLScrollListItem*> items = source->getAllData(); + llassert(rows.size() == mappings.size()); + + for (size_t i = 0; i < rows.size(); ++i) + { + U8 mapping = mappings[i]; + llassert(mapping < items.size()); + // Default values should look as empty cells + rows[i]->getColumn(1)->setValue(mapping == i ? LLSD() : + items[mapping]->getColumn(0)->getValue()); + } +} + +LLGameControl::Options& LLPanelPreferenceGameControl::getSelectedDeviceOptions() +{ + auto options_it = mDeviceOptions.find(mSelectedDeviceGUID); + llassert_always(options_it != mDeviceOptions.end()); + return options_it->second.options; +} + +// static +std::string LLPanelPreferenceGameControl::getChannelLabel(const std::string& channel_name, + const std::vector<LLScrollListItem*>& items) +{ + if (!channel_name.empty() && channel_name != "NONE") + { + for (LLScrollListItem* item : items) + { + if (item->getValue().asString() == channel_name) + { + if (item->getNumColumns()) + { + return item->getColumn(0)->getValue().asString(); + } + break; + } + } + } + return LLStringUtil::null; +} + +// static +void LLPanelPreferenceGameControl::setNumericLabel(LLScrollListCell* cell, S32 value) +{ + // Default values should look as empty cells + cell->setValue(value ? llformat("%d ", value) : LLStringUtil::null); +} + +void LLPanelPreferenceGameControl::fitInRect(LLUICtrl* ctrl, LLScrollListCtrl* grid, S32 row_index, S32 col_index) +{ + LLRect rect(grid->getCellRect(row_index, col_index)); + LLView* parent = grid->getParent(); + while (parent && parent != ctrl->getParent()) + { + rect.translate(parent->getRect().mLeft, parent->getRect().mBottom); + parent = parent->getParent(); + } + + ctrl->setRect(rect); + rect.translate(-rect.mLeft, -rect.mBottom); + for (LLView* child : *ctrl->getChildList()) + { + LLRect childRect(child->getRect()); + childRect.intersectWith(rect); + if (childRect.mRight < rect.mRight && + childRect.mRight > (rect.mLeft + rect.mRight) / 2) + { + childRect.mRight = rect.mRight; + } + child->setRect(childRect); + } +} + +void LLPanelPreferenceGameControl::clearSelectionState() +{ + gSelectedGrid = nullptr; + gSelectedItem = nullptr; + gSelectedCell = nullptr; + mNumericValueEditor->setVisible(false); + mAnalogChannelSelector->setVisible(false); + mBinaryChannelSelector->setVisible(false); + mAxisSelector->setVisible(false); +} + +void LLPanelPreferenceGameControl::addActionTableSeparator() +{ + LLScrollListItem::Params separator_params; + separator_params.enabled(false); + LLScrollListCell::Params column_params; + column_params.type = "icon"; + column_params.value = "menu_separator"; + column_params.column = "action"; + column_params.color = LLColor4(0.f, 0.f, 0.f, 0.7f); + column_params.font_halign = LLFontGL::HCENTER; + separator_params.columns.add(column_params); + mActionTable->addRow(separator_params, EAddPosition::ADD_BOTTOM); +} + +void LLPanelPreferenceGameControl::updateEnable() +{ + bool enabled = LLGameControl::isEnabled(); + LLGameControl::setEnabled(enabled); + + mCheckGameControlToServer->setEnabled(enabled); + mCheckGameControlToAgent->setEnabled(enabled); + mCheckAgentToGameControl->setEnabled(enabled); + + mActionTable->setEnabled(enabled); + mAxisOptions->setEnabled(enabled); + mAxisMappings->setEnabled(enabled); + mButtonMappings->setEnabled(enabled); + mDeviceList->setEnabled(enabled); + + if (!enabled) + { + //mActionTable->deselectAllItems(); + mAnalogChannelSelector->setVisible(false); + mBinaryChannelSelector->setVisible(false); + clearSelectionState(); + } +} + +void LLPanelPreferenceGameControl::updateActionTableState() +{ + // Enable the table if at least one of the GameControl<-->Agent options is enabled + bool enable_table = LLGameControl::isEnabled() && (mCheckGameControlToAgent->get() || mCheckAgentToGameControl->get()); + + mActionTable->deselectAllItems(); + mActionTable->setEnabled(enable_table); + mAnalogChannelSelector->setVisible(false); + mBinaryChannelSelector->setVisible(false); +} + +void LLPanelPreferenceGameControl::onResetToDefaults() +{ + clearSelectionState(); + if (mTabChannelMappings->getVisible()) + { + resetChannelMappingsToDefaults(); + } + else if (mTabDeviceSettings->getVisible() && !mSelectedDeviceGUID.empty()) + { + if (mTabAxisOptions->getVisible()) + { + resetAxisOptionsToDefaults(); + } + else if (mTabAxisMappings->getVisible()) + { + resetAxisMappingsToDefaults(); + } + else if (mTabButtonMappings->getVisible()) + { + resetButtonMappingsToDefaults(); + } + } +} + +void LLPanelPreferenceGameControl::resetChannelMappingsToDefaults() +{ + std::vector<std::pair<std::string, LLGameControl::InputChannel>> mappings; + LLGameControl::getDefaultMappings(mappings); + std::vector<LLScrollListItem*> rows = mActionTable->getAllData(); + std::vector<LLScrollListItem*> axes = mAnalogChannelSelector->getAllData(); + std::vector<LLScrollListItem*> btns = mBinaryChannelSelector->getAllData(); + for (LLScrollListItem* row : rows) + { + if (row->getNumColumns() >= 2) // Skip separators + { + std::string action_name = row->getValue().asString(); + if (!action_name.empty() && action_name != "menu_separator") + { + std::string channel_label; + for (const auto& mapping : mappings) + { + if (mapping.first == action_name) + { + std::string channel_name = mapping.second.getLocalName(); + channel_label = + mapping.second.isAxis() ? getChannelLabel(channel_name, axes) : + mapping.second.isButton() ? getChannelLabel(channel_name, btns) : + LLStringUtil::null; + break; + } + } + row->getColumn(1)->setValue(channel_label); + } + } + } +} + +void LLPanelPreferenceGameControl::resetAxisOptionsToDefaults() +{ + std::vector<LLScrollListItem*> rows = mAxisOptions->getAllData(); + llassert(rows.size() == LLGameControl::NUM_AXES); + LLGameControl::Options& options = getSelectedDeviceOptions(); + llassert(options.getAxisOptions().size() == LLGameControl::NUM_AXES); + for (U8 i = 0; i < LLGameControl::NUM_AXES; ++i) + { + rows[i]->getColumn(1)->setValue(false); + rows[i]->getColumn(2)->setValue(LLStringUtil::null); + rows[i]->getColumn(3)->setValue(LLStringUtil::null); + options.getAxisOptions()[i].resetToDefaults(); + } +} + +void LLPanelPreferenceGameControl::resetAxisMappingsToDefaults() +{ + std::vector<LLScrollListItem*> rows = mAxisMappings->getAllData(); + llassert(rows.size() == LLGameControl::NUM_AXES); + LLGameControl::Options& options = getSelectedDeviceOptions(); + llassert(options.getAxisMap().size() == LLGameControl::NUM_AXES); + for (U8 i = 0; i < LLGameControl::NUM_AXES; ++i) + { + rows[i]->getColumn(1)->setValue(LLStringUtil::null); + options.getAxisMap()[i] = i; + } +} + +void LLPanelPreferenceGameControl::resetButtonMappingsToDefaults() +{ + std::vector<LLScrollListItem*> rows = mButtonMappings->getAllData(); + llassert(rows.size() == LLGameControl::NUM_BUTTONS); + LLGameControl::Options& options = getSelectedDeviceOptions(); + llassert(options.getButtonMap().size() == LLGameControl::NUM_BUTTONS); + for (U8 i = 0; i < LLGameControl::NUM_BUTTONS; ++i) + { + rows[i]->getColumn(1)->setValue(LLStringUtil::null); + options.getButtonMap()[i] = i; + } +} + +//------------------------LLFloaterPreferenceProxy-------------------------------- + LLFloaterPreferenceProxy::LLFloaterPreferenceProxy(const LLSD& key) : LLFloater(key), mSocksSettingsDirty(false) @@ -3170,7 +4132,7 @@ void LLFloaterPreferenceProxy::onOpen(const LLSD& key) void LLFloaterPreferenceProxy::onClose(bool app_quitting) { - if(app_quitting) + if (app_quitting) { cancel(); } @@ -3194,7 +4156,7 @@ void LLFloaterPreferenceProxy::saveSettings() mSavedValues.clear(); std::list<LLView*> view_stack; view_stack.push_back(this); - while(!view_stack.empty()) + while (!view_stack.empty()) { // Process view on top of the stack LLView* curview = view_stack.front(); @@ -3281,13 +4243,9 @@ void LLFloaterPreferenceProxy::onClickCloseBtn(bool app_quitting) void LLFloaterPreferenceProxy::cancel() { - - for (control_values_map_t::iterator iter = mSavedValues.begin(); - iter != mSavedValues.end(); ++iter) + for (const auto& iter : mSavedValues) { - LLControlVariable* control = iter->first; - LLSD ctrl_value = iter->second; - control->set(ctrl_value); + iter.first->set(iter.second); } mSocksSettingsDirty = false; closeFloater(); @@ -3312,21 +4270,20 @@ void LLFloaterPreferenceProxy::onChangeSocksSettings() // Check for invalid states for the other HTTP proxy radio LLRadioGroup* otherHttpProxy = getChild<LLRadioGroup>("other_http_proxy_type"); if ((otherHttpProxy->getSelectedValue().asString() == "Socks" && - !getChild<LLCheckBoxCtrl>("socks_proxy_enabled")->get())||( + getChild<LLCheckBoxCtrl>("socks_proxy_enabled")->get() == false )||( otherHttpProxy->getSelectedValue().asString() == "Web" && - !getChild<LLCheckBoxCtrl>("web_proxy_enabled")->get())) + getChild<LLCheckBoxCtrl>("web_proxy_enabled")->get() == false ) ) { otherHttpProxy->selectFirstItem(); } - } void LLFloaterPreference::onUpdateFilterTerm(bool force) { - LLWString seachValue = utf8str_to_wstring(mFilterEdit->getValue()); - LLWStringUtil::toLower(seachValue); + LLWString seachValue = utf8str_to_wstring( mFilterEdit->getValue() ); + LLWStringUtil::toLower( seachValue ); - if (!mSearchData || (mSearchData->mLastFilter == seachValue && !force)) + if( !mSearchData || (mSearchData->mLastFilter == seachValue && !force)) return; if (mSearchDataDirty) @@ -3337,7 +4294,7 @@ void LLFloaterPreference::onUpdateFilterTerm(bool force) mSearchData->mLastFilter = seachValue; - if (!mSearchData->mRootTab) + if( !mSearchData->mRootTab ) return; mSearchData->mRootTab->hightlightAndHide( seachValue ); @@ -3360,10 +4317,10 @@ void LLFloaterPreference::filterIgnorableNotifications() void collectChildren( LLView const *aView, ll::prefs::PanelDataPtr aParentPanel, ll::prefs::TabContainerDataPtr aParentTabContainer ) { - if (!aView) + if( !aView ) return; - llassert_always(aParentPanel || aParentTabContainer); + llassert_always( aParentPanel || aParentTabContainer ); for (LLView* pView : *aView->getChildList()) { @@ -3373,56 +4330,56 @@ void collectChildren( LLView const *aView, ll::prefs::PanelDataPtr aParentPanel, ll::prefs::PanelDataPtr pCurPanelData = aParentPanel; ll::prefs::TabContainerDataPtr pCurTabContainer = aParentTabContainer; - LLPanel const *pPanel = dynamic_cast<LLPanel const*>(pView); - LLTabContainer const *pTabContainer = dynamic_cast<LLTabContainer const*>(pView); - ll::ui::SearchableControl const *pSCtrl = dynamic_cast<ll::ui::SearchableControl const*>( pView ); + LLPanel const *pPanel = dynamic_cast< LLPanel const *>( pView ); + LLTabContainer const *pTabContainer = dynamic_cast< LLTabContainer const *>( pView ); + ll::ui::SearchableControl const *pSCtrl = dynamic_cast< ll::ui::SearchableControl const *>( pView ); - if (pTabContainer) + if( pTabContainer ) { pCurPanelData.reset(); - pCurTabContainer = ll::prefs::TabContainerDataPtr(new ll::prefs::TabContainerData); - pCurTabContainer->mTabContainer = const_cast< LLTabContainer *>(pTabContainer); + pCurTabContainer = ll::prefs::TabContainerDataPtr( new ll::prefs::TabContainerData ); + pCurTabContainer->mTabContainer = const_cast< LLTabContainer *>( pTabContainer ); pCurTabContainer->mLabel = pTabContainer->getLabel(); pCurTabContainer->mPanel = 0; - if (aParentPanel) - aParentPanel->mChildPanel.push_back(pCurTabContainer); - if (aParentTabContainer) - aParentTabContainer->mChildPanel.push_back(pCurTabContainer); + if( aParentPanel ) + aParentPanel->mChildPanel.push_back( pCurTabContainer ); + if( aParentTabContainer ) + aParentTabContainer->mChildPanel.push_back( pCurTabContainer ); } - else if (pPanel) + else if( pPanel ) { pCurTabContainer.reset(); - pCurPanelData = ll::prefs::PanelDataPtr(new ll::prefs::PanelData); + pCurPanelData = ll::prefs::PanelDataPtr( new ll::prefs::PanelData ); pCurPanelData->mPanel = pPanel; pCurPanelData->mLabel = pPanel->getLabel(); llassert_always( aParentPanel || aParentTabContainer ); - if (aParentTabContainer) - aParentTabContainer->mChildPanel.push_back(pCurPanelData); - else if (aParentPanel) - aParentPanel->mChildPanel.push_back(pCurPanelData); + if( aParentTabContainer ) + aParentTabContainer->mChildPanel.push_back( pCurPanelData ); + else if( aParentPanel ) + aParentPanel->mChildPanel.push_back( pCurPanelData ); } - else if (pSCtrl && pSCtrl->getSearchText().size()) + else if( pSCtrl && pSCtrl->getSearchText().size() ) { - ll::prefs::SearchableItemPtr item = ll::prefs::SearchableItemPtr(new ll::prefs::SearchableItem()); + ll::prefs::SearchableItemPtr item = ll::prefs::SearchableItemPtr( new ll::prefs::SearchableItem() ); item->mView = pView; item->mCtrl = pSCtrl; - item->mLabel = utf8str_to_wstring(pSCtrl->getSearchText()); - LLWStringUtil::toLower(item->mLabel); + item->mLabel = utf8str_to_wstring( pSCtrl->getSearchText() ); + LLWStringUtil::toLower( item->mLabel ); - llassert_always(aParentPanel || aParentTabContainer); + llassert_always( aParentPanel || aParentTabContainer ); - if (aParentPanel) - aParentPanel->mChildren.push_back(item); - if (aParentTabContainer) - aParentTabContainer->mChildren.push_back(item); + if( aParentPanel ) + aParentPanel->mChildren.push_back( item ); + if( aParentTabContainer ) + aParentTabContainer->mChildren.push_back( item ); } - collectChildren(pView, pCurPanelData, pCurTabContainer); + collectChildren( pView, pCurPanelData, pCurTabContainer ); } } diff --git a/indra/newview/llfloaterpreference.h b/indra/newview/llfloaterpreference.h index 40806c22fc..e06e758e3a 100644 --- a/indra/newview/llfloaterpreference.h +++ b/indra/newview/llfloaterpreference.h @@ -36,9 +36,13 @@ #include "llfloater.h" #include "llavatarpropertiesprocessor.h" #include "llconversationlog.h" +#include "llgamecontrol.h" +#include "llkeyconflict.h" +#include "llscrolllistcell.h" +#include "llscrolllistctrl.h" #include "llsearcheditor.h" #include "llsetkeybinddialog.h" -#include "llkeyconflict.h" +#include "llspinctrl.h" class LLConversationLogObserver; class LLPanelPreference; @@ -51,6 +55,7 @@ class LLScrollListCell; class LLSliderCtrl; class LLSD; class LLTextBox; +class LLPanelPreferenceGameControl; namespace ll { @@ -80,12 +85,14 @@ public: void apply(); void cancel(const std::vector<std::string> settings_to_skip = {}); - /*virtual*/ void draw(); - /*virtual*/ bool postBuild(); - /*virtual*/ void onOpen(const LLSD& key); - /*virtual*/ void onClose(bool app_quitting); - /*virtual*/ void changed(); - /*virtual*/ void changed(const LLUUID& session_id, U32 mask) {}; + virtual void draw() override; + virtual bool postBuild() override; + virtual void onOpen(const LLSD& key) override; + virtual void onClose(bool app_quitting) override; + virtual void changed() override; + virtual void changed(const LLUUID& session_id, U32 mask) override {}; + + static void refreshInstance(); // static data update, called from message handler static void updateUserInfo(const std::string& visibility); @@ -99,7 +106,7 @@ public: // update Show Favorites checkbox static void updateShowFavoritesCheckbox(bool val); - void processProperties( void* pData, EAvatarProcessorType type ); + void processProperties( void* pData, EAvatarProcessorType type ) override; void saveAvatarProperties( void ); static void saveAvatarPropertiesCoro(const std::string url, bool allow_publish); void selectPrivacyPanel(); @@ -167,7 +174,7 @@ public: void setPersonalInfo(const std::string& visibility); void refreshEnabledState(); void onCommitWindowedMode(); - void refresh(); // Refresh enable/disable + void refresh() override; // Refresh enable/disable // if the quality radio buttons are changed void onChangeQuality(const LLSD& data); @@ -196,6 +203,7 @@ public: void buildPopupLists(); static void refreshSkin(void* data); void selectPanel(const LLSD& name); + void setPanelVisibility(const LLSD& name, bool visible); void saveGraphicsPreset(std::string& preset); void setRecommendedSettings(); @@ -251,7 +259,7 @@ class LLPanelPreference : public LLPanel { public: LLPanelPreference(); - /*virtual*/ bool postBuild(); + virtual bool postBuild() override; virtual ~LLPanelPreference(); @@ -297,12 +305,12 @@ private: class LLPanelPreferenceGraphics : public LLPanelPreference { public: - bool postBuild(); - void draw(); - void cancel(const std::vector<std::string> settings_to_skip = {}); - void saveSettings(); + bool postBuild() override; + void draw() override; + void cancel(const std::vector<std::string> settings_to_skip = {}) override; + void saveSettings() override; void resetDirtyChilds(); - void setHardwareDefaults(); + void setHardwareDefaults() override; void setPresetText(); protected: @@ -320,11 +328,13 @@ public: LLPanelPreferenceControls(); virtual ~LLPanelPreferenceControls(); - bool postBuild(); + bool postBuild() override; - void apply(); - void cancel(const std::vector<std::string> settings_to_skip = {}); - void saveSettings(); + void refresh() override; + + void apply() override; + void cancel(const std::vector<std::string> settings_to_skip = {}) override; + void saveSettings() override; void resetDirtyChilds(); void onListCommit(); @@ -340,9 +350,12 @@ public: void updateAndApply(); // from interface - /*virtual*/ bool onSetKeyBind(EMouseClickType click, KEY key, MASK mask, bool all_modes); - /*virtual*/ void onDefaultKeyBind(bool all_modes); - /*virtual*/ void onCancelKeyBind(); + bool onSetKeyBind(EMouseClickType click, KEY key, MASK mask, bool all_modes) override; + void onDefaultKeyBind(bool all_modes) override; + void onCancelKeyBind() override; + + // Cleans content and then adds content from xml files according to current mEditingMode + void populateControlTable(); private: // reloads settings, discards current changes, updates table @@ -353,9 +366,6 @@ private: bool addControlTableRows(const std::string &filename); void addControlTableSeparator(); - // Cleans content and then adds content from xml files according to current mEditingMode - void populateControlTable(); - // Updates keybindings from storage to table void updateTable(); @@ -367,6 +377,118 @@ private: S32 mEditingMode; }; +class LLPanelPreferenceGameControl : public LLPanelPreference +{ + LOG_CLASS(LLPanelPreferenceGameControl); +public: + + enum InputType + { + TYPE_AXIS, + TYPE_BUTTON, + TYPE_NONE + }; + + static void updateDeviceList(); + + LLPanelPreferenceGameControl(); + ~LLPanelPreferenceGameControl(); + + void onOpen(const LLSD& key) override; + + // This function squirrels away the current values of the controls so that + // cancel() can restore them. + void saveSettings() override; + + void updateDeviceListInternal(); + + void onGridSelect(LLUICtrl* ctrl); + void onCommitInputChannel(LLUICtrl* ctrl); + + void onAxisOptionsSelect(); + void onCommitNumericValue(); + + static bool isWaitingForInputChannel(); + static void applyGameControlInput(); + +protected: + bool postBuild() override; + + void populateActionTableRows(const std::string& filename); + void populateActionTableCells(); + static bool parseXmlFile(LLScrollListCtrl::Contents& contents, + const std::string& filename, const std::string& what); + + void populateDeviceTitle(); + void populateDeviceSettings(const std::string& guid); + void populateOptionsTableRows(); + void populateOptionsTableCells(); + void populateMappingTableRows(LLScrollListCtrl* target, + const LLComboBox* source, size_t row_count); + void populateMappingTableCells(LLScrollListCtrl* target, + const std::vector<U8>& mappings, const LLComboBox* source); + LLGameControl::Options& getSelectedDeviceOptions(); + + static std::string getChannelLabel(const std::string& channelName, + const std::vector<LLScrollListItem*>& items); + static void setNumericLabel(LLScrollListCell* cell, S32 value); + static void fitInRect(LLUICtrl* ctrl, LLScrollListCtrl* grid, S32 row_index, S32 col_index); + +private: + bool initCombobox(LLScrollListItem* item, LLScrollListCtrl* grid); + void clearSelectionState(); + void addActionTableSeparator(); + void updateEnable(); + void updateActionTableState(); + void onResetToDefaults(); + void resetChannelMappingsToDefaults(); + void resetAxisOptionsToDefaults(); + void resetAxisMappingsToDefaults(); + void resetButtonMappingsToDefaults(); + + // Above the tab container + LLCheckBoxCtrl* mCheckGameControlToServer { nullptr }; // send game_control data to server + LLCheckBoxCtrl* mCheckGameControlToAgent { nullptr }; // use game_control data to move avatar + LLCheckBoxCtrl* mCheckAgentToGameControl { nullptr }; // translate external avatar actions to game_control data + + // 1st tab "Channel mappings" + LLPanel* mTabChannelMappings { nullptr }; + LLScrollListCtrl* mActionTable { nullptr }; + + // 2nd tab "Device settings" + LLPanel* mTabDeviceSettings { nullptr }; + LLTextBox* mNoDeviceMessage { nullptr }; + LLTextBox* mDevicePrompt { nullptr }; + LLTextBox* mSingleDevice { nullptr }; + LLComboBox* mDeviceList { nullptr }; + LLCheckBoxCtrl* mCheckShowAllDevices { nullptr }; + LLPanel* mPanelDeviceSettings { nullptr }; + LLPanel* mTabAxisOptions { nullptr }; + LLScrollListCtrl* mAxisOptions { nullptr }; + LLPanel* mTabAxisMappings { nullptr }; + LLScrollListCtrl* mAxisMappings { nullptr }; + LLPanel* mTabButtonMappings { nullptr }; + LLScrollListCtrl* mButtonMappings { nullptr }; + + LLButton* mResetToDefaults { nullptr }; + + // Numeric value editor + LLSpinCtrl* mNumericValueEditor { nullptr }; + + // Channel selectors + LLComboBox* mAnalogChannelSelector { nullptr }; + LLComboBox* mBinaryChannelSelector { nullptr }; + LLComboBox* mAxisSelector { nullptr }; + + struct DeviceOptions + { + std::string name, settings; + LLGameControl::Options options; + }; + std::map<std::string, DeviceOptions> mDeviceOptions; + std::string mSelectedDeviceGUID; +}; + class LLAvatarComplexityControls { public: @@ -391,13 +513,13 @@ public: void cancel(); protected: - bool postBuild(); - void onOpen(const LLSD& key); - void onClose(bool app_quitting); + bool postBuild() override; + void onOpen(const LLSD& key) override; + void onClose(bool app_quitting) override; void saveSettings(); void onBtnOk(); void onBtnCancel(); - void onClickCloseBtn(bool app_quitting = false); + void onClickCloseBtn(bool app_quitting = false) override; void onChangeSocksSettings(); diff --git a/indra/newview/llflycam.cpp b/indra/newview/llflycam.cpp new file mode 100644 index 0000000000..eb5bfecf73 --- /dev/null +++ b/indra/newview/llflycam.cpp @@ -0,0 +1,136 @@ +/** + * @file llflycam.cpp + * @brief LLFlycam class implementation + * + * $LicenseInfo:firstyear=2024&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2024, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llflycam.h" + +#include <algorithm> +#include "llcamera.h" +#include "llcoordframe.h" + +LLFlycam::LLFlycam() +{ +} + + +void LLFlycam::setTransform(const LLVector3& position, const LLQuaternion& rotation) +{ + mPosition = position; + mRotation = rotation; + mRotation.normalize(); +} + +void LLFlycam::getTransform(LLVector3& position_out, LLQuaternion& rotation_out) +{ + position_out = mPosition; + rotation_out = mRotation; +} + +// 'view' is expected to be in radians +void LLFlycam::setView(F32 view) +{ + mView = std::clamp(view, MIN_FIELD_OF_VIEW, MAX_FIELD_OF_VIEW); +} + + +void LLFlycam::setLinearVelocity(const LLVector3& velocity) +{ + // Note: this math expects velocity components to be in range [-1.0, 1.0] + mLinearVelocity = velocity; +} + + +void LLFlycam::setPitchRate(F32 pitch_rate) +{ + // Note: this math expects pitch_rate to be in range [-1.0, 1.0] + constexpr F32 PITCH_RATE_FACTOR = 0.75f; + mPitchRate = pitch_rate * PITCH_RATE_FACTOR; +} + + +void LLFlycam::setYawRate(F32 yaw_rate) +{ + // Note: this math expects yaw_rate to be in range [-1.0, 1.0] + constexpr F32 YAW_RATE_FACTOR = 0.90f; + mYawRate = yaw_rate * YAW_RATE_FACTOR; +} + + +void LLFlycam::setZoomRate(F32 zoom_rate) +{ + // Note: this math expects zoom_rate to be in range [-1.0, 1.0] + constexpr F32 FULL_ZOOM_PERIOD = 5.0f; // seconds + constexpr F32 ZOOM_RATE_FACTOR = (MAX_FIELD_OF_VIEW - MIN_FIELD_OF_VIEW) / FULL_ZOOM_PERIOD; + mZoomRate = zoom_rate * ZOOM_RATE_FACTOR; +} + + +void LLFlycam::integrate(F32 delta_time) +{ + // cap delta_time to slow camera motion when framerates are low + constexpr F32 MAX_DELTA_TIME = 0.2f; + if (delta_time > MAX_DELTA_TIME) + { + delta_time = MAX_DELTA_TIME; + } + + // Note: we modulate pitch and yaw rates by view ratio + // to make pitch and yaw work better when zoomed in close + F32 angle = delta_time * mPitchRate * (mView / DEFAULT_FIELD_OF_VIEW); + bool needs_renormalization = false; + if (fabsf(angle) > 0.0f) + { + LLQuaternion dQ; + dQ.setAngleAxis(angle, 0.0f, 1.0f, 0.0f); + mRotation = dQ * mRotation; + needs_renormalization = true; + } + + angle = delta_time * mYawRate * (mView / DEFAULT_FIELD_OF_VIEW); + if (fabsf(angle) > 0.0f) + { + LLQuaternion dQ; + dQ.setAngleAxis(angle, 0.0f, 0.0f, 1.0f); + mRotation = mRotation * dQ; + needs_renormalization = true; + } + + if (mLinearVelocity.lengthSquared() > 0.0f) + { + mPosition += (delta_time * mLinearVelocity) * mRotation; + } + + if (mZoomRate != 0.0f) + { + // Note: we subtract the delta because "positive" zoom (e.g. "zoom in") + // produces smaller view angle + mView = std::clamp(mView - delta_time * mZoomRate, MIN_FIELD_OF_VIEW, MAX_FIELD_OF_VIEW); + } + + if (needs_renormalization) + { + mRotation.normalize(); + } +} diff --git a/indra/newview/llflycam.h b/indra/newview/llflycam.h new file mode 100644 index 0000000000..c75b6e246e --- /dev/null +++ b/indra/newview/llflycam.h @@ -0,0 +1,60 @@ +/** + * @file llflycam.h + * @brief LLFlycam class header file + * + * $LicenseInfo:firstyear=2024&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2024, 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$ + */ + +#pragma once + +#include "llcamera.h" +#include "llquaternion.h" +#include "v3math.h" + +class LLFlycam +{ +public: + + LLFlycam(); + + void setTransform(const LLVector3& position, const LLQuaternion& rotation); + void getTransform(LLVector3& position_out, LLQuaternion& rotation_out); + + void setView(F32 view); + F32 getView() const { return mView; } + + void setLinearVelocity(const LLVector3& velocity); + void setPitchRate(F32 pitch_rate); + void setYawRate(F32 yaw_rate); + void setZoomRate(F32 zoom_rate); + + void integrate(F32 delta_time); + +protected: + LLVector3 mPosition; + LLVector3 mLinearVelocity; + LLQuaternion mRotation; + F32 mPitchRate { 0.0f }; + F32 mYawRate { 0.0f }; + F32 mZoomRate { 0.0f }; + F32 mView { DEFAULT_FIELD_OF_VIEW }; +}; diff --git a/indra/newview/llgltfmateriallist.cpp b/indra/newview/llgltfmateriallist.cpp index 25438eae5e..5e5e6425b8 100644 --- a/indra/newview/llgltfmateriallist.cpp +++ b/indra/newview/llgltfmateriallist.cpp @@ -45,7 +45,9 @@ #include "llworld.h" #include "tinygltf/tiny_gltf.h" -#include <strstream> + +#include <boost/iostreams/device/array.hpp> +#include <boost/iostreams/stream.hpp> #include <unordered_set> @@ -168,7 +170,7 @@ namespace void LLGLTFMaterialList::applyOverrideMessage(LLMessageSystem* msg, const std::string& data_in) { - std::istringstream str(data_in); + boost::iostreams::stream<boost::iostreams::array_source> str(data_in.data(), data_in.size()); LLSD data; @@ -539,8 +541,7 @@ void LLGLTFMaterialList::onAssetLoadComplete(const LLUUID& id, LLAssetType::ETyp LLSD asset; // read file into buffer - std::istrstream str(&buffer[0], static_cast<S32>(buffer.size())); - + boost::iostreams::stream<boost::iostreams::array_source> str(buffer.data(), buffer.size()); if (LLSDSerialize::deserialize(asset, str, buffer.size())) { if (asset.has("version") && LLGLTFMaterial::isAcceptedVersion(asset["version"].asString())) diff --git a/indra/newview/llhudrender.cpp b/indra/newview/llhudrender.cpp index aa440c6cf5..2255eb236f 100644 --- a/indra/newview/llhudrender.cpp +++ b/indra/newview/llhudrender.cpp @@ -109,7 +109,7 @@ void hud_render_text(const LLWString &wstr, const LLVector3 &pos_agent, LLRect world_view_rect = gViewerWindow->getWorldViewRectRaw(); glm::ivec4 viewport(world_view_rect.mLeft, world_view_rect.mBottom, world_view_rect.getWidth(), world_view_rect.getHeight()); - glm::vec3 win_coord = glm::project(glm::make_vec3(render_pos.mV), get_current_modelview(), get_current_projection(), viewport); + glm::vec3 win_coord = glm::project(glm::make_vec3(LLVector4(render_pos).mV), get_current_modelview(), get_current_projection(), viewport); //fonts all render orthographically, set up projection`` gGL.matrixMode(LLRender::MM_PROJECTION); diff --git a/indra/newview/llhudtext.cpp b/indra/newview/llhudtext.cpp index 92f09c34a0..818474a0cb 100644 --- a/indra/newview/llhudtext.cpp +++ b/indra/newview/llhudtext.cpp @@ -185,6 +185,15 @@ void LLHUDText::renderText() LLVector3 render_position = mPositionAgent + (x_pixel_vec * screen_offset.mV[VX]) + (y_pixel_vec * screen_offset.mV[VY]); + bool reset_buffers = false; + const F32 treshold = 0.000001f; + if (abs(mLastRenderPosition.mV[VX] - render_position.mV[VX]) > treshold + || abs(mLastRenderPosition.mV[VY] - render_position.mV[VY]) > treshold + || abs(mLastRenderPosition.mV[VZ] - render_position.mV[VZ]) > treshold) + { + reset_buffers = true; + mLastRenderPosition = render_position; + } F32 y_offset = (F32)mOffsetY; @@ -208,6 +217,11 @@ void LLHUDText::renderText() for (std::vector<LLHUDTextSegment>::iterator segment_iter = mTextSegments.begin() + start_segment; segment_iter != mTextSegments.end(); ++segment_iter ) { + if (reset_buffers) + { + segment_iter->mFontBufferText.reset(); + } + const LLFontGL* fontp = segment_iter->mFont; y_offset -= fontp->getLineHeight() - 1; // correction factor to match legacy font metrics @@ -231,7 +245,7 @@ void LLHUDText::renderText() } text_color.mV[VALPHA] *= alpha_factor; - hud_render_text(segment_iter->getText(), render_position, &mFontBuffer, *fontp, style, shadow, x_offset, y_offset, text_color, mOnHUDAttachment); + hud_render_text(segment_iter->getText(), render_position, &segment_iter->mFontBufferText, *fontp, style, shadow, x_offset, y_offset, text_color, mOnHUDAttachment); } } /// Reset the default color to white. The renderer expects this to be the default. diff --git a/indra/newview/llhudtext.h b/indra/newview/llhudtext.h index 224677736c..4c850e2d91 100644 --- a/indra/newview/llhudtext.h +++ b/indra/newview/llhudtext.h @@ -67,6 +67,8 @@ protected: LLColor4 mColor; LLFontGL::StyleFlags mStyle; const LLFontGL* mFont; + LLFontVertexBuffer mFontBuffer; + LLFontVertexBuffer mFontBufferText; private: LLWString mText; std::map<const LLFontGL*, F32> mFontWidthMap; @@ -152,6 +154,7 @@ private: const LLFontGL* mBoldFontp; LLRectf mSoftScreenRect; LLVector3 mPositionAgent; + LLVector3 mLastRenderPosition; LLVector2 mPositionOffset; LLVector2 mTargetPositionOffset; F32 mMass; @@ -162,7 +165,6 @@ private: ETextAlignment mTextAlignment; EVertAlignment mVertAlignment; bool mHidden; - LLFontVertexBuffer mFontBuffer; static bool sDisplayText ; static std::set<LLPointer<LLHUDText> > sTextObjects; diff --git a/indra/newview/llkeyconflict.cpp b/indra/newview/llkeyconflict.cpp index 666ab4f5d0..b9456349cd 100644 --- a/indra/newview/llkeyconflict.cpp +++ b/indra/newview/llkeyconflict.cpp @@ -99,29 +99,34 @@ LLKeyConflictHandler::~LLKeyConflictHandler() // Note: does not reset bindings if temporary file was used } -bool LLKeyConflictHandler::canHandleControl(const std::string &control_name, EMouseClickType mouse_ind, KEY key, MASK mask) +bool LLKeyConflictHandler::canHandleControl(const std::string &control_name, EMouseClickType mouse_ind, KEY key, MASK mask) const { - return mControlsMap[control_name].canHandle(mouse_ind, key, mask); + control_map_t::const_iterator iter = mControlsMap.find(control_name); + if (iter != mControlsMap.end()) + { + return iter->second.canHandle(mouse_ind, key, mask); + } + return false; } -bool LLKeyConflictHandler::canHandleKey(const std::string &control_name, KEY key, MASK mask) +bool LLKeyConflictHandler::canHandleKey(const std::string &control_name, KEY key, MASK mask) const { return canHandleControl(control_name, CLICK_NONE, key, mask); } -bool LLKeyConflictHandler::canHandleMouse(const std::string &control_name, EMouseClickType mouse_ind, MASK mask) +bool LLKeyConflictHandler::canHandleMouse(const std::string &control_name, EMouseClickType mouse_ind, MASK mask) const { return canHandleControl(control_name, mouse_ind, KEY_NONE, mask); } -bool LLKeyConflictHandler::canHandleMouse(const std::string &control_name, S32 mouse_ind, MASK mask) +bool LLKeyConflictHandler::canHandleMouse(const std::string &control_name, S32 mouse_ind, MASK mask) const { return canHandleControl(control_name, (EMouseClickType)mouse_ind, KEY_NONE, mask); } -bool LLKeyConflictHandler::canAssignControl(const std::string &control_name) +bool LLKeyConflictHandler::canAssignControl(const std::string &control_name) const { - control_map_t::iterator iter = mControlsMap.find(control_name); + control_map_t::const_iterator iter = mControlsMap.find(control_name); if (iter != mControlsMap.end()) { return iter->second.mAssignable; @@ -284,7 +289,7 @@ void LLKeyConflictHandler::loadFromSettings(const LLViewerInput::KeyMode& keymod LLKeyboard::keyFromString(it->key, &key); } LLKeyboard::maskFromString(it->mask, &mask); - // Note: it->command is also the name of UI element, howhever xml we are loading from + // Note: it->command is also the name of UI element, however xml we are loading from // might not know all the commands, so UI will have to know what to fill by its own // Assumes U32_MAX conflict mask, and is assignable by default, // but assignability might have been overriden by generatePlaceholders. diff --git a/indra/newview/llkeyconflict.h b/indra/newview/llkeyconflict.h index 6c01ddb7a7..21990688a2 100644 --- a/indra/newview/llkeyconflict.h +++ b/indra/newview/llkeyconflict.h @@ -44,7 +44,7 @@ public: LLKeyData getKeyData(U32 index) { return mKeyBind.getKeyData(index); } void setPrimaryKeyData(const LLKeyData& data) { mKeyBind.replaceKeyData(data, 0); } void setKeyData(const LLKeyData& data, U32 index) { mKeyBind.replaceKeyData(data, index); } - bool canHandle(EMouseClickType mouse, KEY key, MASK mask) { return mKeyBind.canHandle(mouse, key, mask); } + bool canHandle(EMouseClickType mouse, KEY key, MASK mask) const { return mKeyBind.canHandle(mouse, key, mask); } LLKeyBind mKeyBind; bool mAssignable; // whether user can change key or key simply acts as placeholder @@ -76,11 +76,11 @@ public: LLKeyConflictHandler(ESourceMode mode); ~LLKeyConflictHandler(); - bool canHandleControl(const std::string &control_name, EMouseClickType mouse_ind, KEY key, MASK mask); - bool canHandleKey(const std::string &control_name, KEY key, MASK mask); - bool canHandleMouse(const std::string &control_name, EMouseClickType mouse_ind, MASK mask); - bool canHandleMouse(const std::string &control_name, S32 mouse_ind, MASK mask); //Just for convinience - bool canAssignControl(const std::string &control_name); + bool canHandleControl(const std::string &control_name, EMouseClickType mouse_ind, KEY key, MASK mask) const; + bool canHandleKey(const std::string &control_name, KEY key, MASK mask) const; + bool canHandleMouse(const std::string &control_name, EMouseClickType mouse_ind, MASK mask) const; + bool canHandleMouse(const std::string &control_name, S32 mouse_ind, MASK mask) const; //Just for convenience + bool canAssignControl(const std::string &control_name) const; static bool isReservedByMenu(const KEY &key, const MASK &mask); static bool isReservedByMenu(const LLKeyData &data); diff --git a/indra/newview/llmaterialeditor.cpp b/indra/newview/llmaterialeditor.cpp index dde238eddb..b5e494379d 100644 --- a/indra/newview/llmaterialeditor.cpp +++ b/indra/newview/llmaterialeditor.cpp @@ -63,8 +63,9 @@ #include "tinygltf/tiny_gltf.h" #include "lltinygltfhelper.h" -#include <strstream> +#include <boost/iostreams/device/array.hpp> +#include <boost/iostreams/stream.hpp> const std::string MATERIAL_BASE_COLOR_DEFAULT_NAME = "Base Color"; const std::string MATERIAL_NORMAL_DEFAULT_NAME = "Normal"; @@ -1245,7 +1246,7 @@ bool LLMaterialEditor::decodeAsset(const std::vector<char>& buffer) { LLSD asset; - std::istrstream str(&buffer[0], buffer.size()); + boost::iostreams::stream<boost::iostreams::array_source> str(buffer.data(), buffer.size()); if (LLSDSerialize::deserialize(asset, str, buffer.size())) { if (asset.has("version") && LLGLTFMaterial::isAcceptedVersion(asset["version"].asString())) diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp index a8585c7f23..5fc49b32ea 100644 --- a/indra/newview/llmeshrepository.cpp +++ b/indra/newview/llmeshrepository.cpp @@ -864,7 +864,7 @@ LLMeshRepoThread::~LLMeshRepoThread() while (!mSkinInfoQ.empty()) { - delete mSkinInfoQ.front(); + llassert(mSkinInfoQ.front()->getNumRefs() == 1); mSkinInfoQ.pop_front(); } @@ -2058,13 +2058,15 @@ bool LLMeshRepoThread::skinInfoReceived(const LLUUID& mesh_id, U8* data, S32 dat LLSkinningUtil::initJointNums(info, gAgentAvatarp); } - // remember the skin info in the background thread so we can use it + // copy the skin info for the background thread so we can use it // to calculate per-joint bounding boxes when volumes are loaded - mSkinMap[mesh_id] = info; + mSkinMap[mesh_id] = new LLMeshSkinInfo(*info); { + // Move the LLPointer in to the skin info queue to avoid reference + // count modification after we leave the lock LLMutexLock lock(mMutex); - mSkinInfoQ.push_back(info); + mSkinInfoQ.emplace_back(std::move(info)); } } diff --git a/indra/newview/llpaneleditsky.cpp b/indra/newview/llpaneleditsky.cpp index ea2b2ba944..b4a0f0570e 100644 --- a/indra/newview/llpaneleditsky.cpp +++ b/indra/newview/llpaneleditsky.cpp @@ -35,7 +35,6 @@ #include "llvirtualtrackball.h" #include "llsettingssky.h" #include "llenvironment.h" -#include "llatmosphere.h" #include "llviewercontrol.h" namespace @@ -926,13 +925,6 @@ void LLPanelSettingsSkyDensityTab::updateProfile() mSkySettings->setAbsorptionConfigs(absorption_config); mSkySettings->update(); setIsDirty(); - - if (gAtmosphere) - { - AtmosphericModelSettings atmospheric_settings; - LLEnvironment::getAtmosphericModelSettings(atmospheric_settings, mSkySettings); - gAtmosphere->configureAtmosphericModel(atmospheric_settings); - } } void LLPanelSettingsSkyDensityTab::onRayleighExponentialChanged() diff --git a/indra/newview/llpanelenvironment.cpp b/indra/newview/llpanelenvironment.cpp index 423ca376d1..be61c44b7c 100644 --- a/indra/newview/llpanelenvironment.cpp +++ b/indra/newview/llpanelenvironment.cpp @@ -288,7 +288,7 @@ void LLPanelEnvironmentInfo::refresh() F32Hours dayoffset(mCurrentEnvironment->mDayOffset); if (dayoffset.value() > 12.0f) - dayoffset -= daylength; + dayoffset -= F32Hours(24.0); mSliderDayLength->setValue(daylength.value()); mSliderDayOffset->setValue(dayoffset.value()); @@ -717,11 +717,6 @@ void LLPanelEnvironmentInfo::onSldDayLengthChanged(F32 value) F32Hours daylength(value); mCurrentEnvironment->mDayLength = daylength; - F32 offset = (F32)mSliderDayOffset->getValue().asReal(); - if (offset <= 0.0f) - { - onSldDayOffsetChanged(offset); - } setDirtyFlag(DIRTY_FLAG_DAYLENGTH); udpateApparentTimeOfDay(); @@ -735,8 +730,7 @@ void LLPanelEnvironmentInfo::onSldDayOffsetChanged(F32 value) F32Hours dayoffset(value); if (dayoffset.value() <= 0.0f) - // if day cycle is 5 hours long, we want -1h offset to result in 4h - dayoffset += mCurrentEnvironment->mDayLength; + dayoffset += F32Hours(24.0); mCurrentEnvironment->mDayOffset = dayoffset; setDirtyFlag(DIRTY_FLAG_DAYOFFSET); @@ -928,7 +922,7 @@ void LLPanelEnvironmentInfo::udpateApparentTimeOfDay() { static const F32 SECONDSINDAY(24.0 * 60.0 * 60.0); - if ((!mCurrentEnvironment) || (mCurrentEnvironment->mDayLength.value() < 1.0)) + if ((!mCurrentEnvironment) || (mCurrentEnvironment->mDayLength.value() < 1.0) || (mCurrentEnvironment->mDayOffset.value() < 1.0)) { mLabelApparentTime->setVisible(false); return; diff --git a/indra/newview/llpanelprofileclassifieds.h b/indra/newview/llpanelprofileclassifieds.h index 9f0b27139a..1c58fa6cfa 100644 --- a/indra/newview/llpanelprofileclassifieds.h +++ b/indra/newview/llpanelprofileclassifieds.h @@ -157,17 +157,17 @@ public: void setParcelId(const LLUUID& id) { mParcelId = id; } - LLUUID getParcelId() { return mParcelId; } + LLUUID getParcelId() const { return mParcelId; } void setSimName(const std::string& sim_name) { mSimName = sim_name; } - std::string getSimName() { return mSimName; } + std::string getSimName() const { return mSimName; } void setFromSearch(bool val) { mFromSearch = val; } - bool fromSearch() { return mFromSearch; } + bool fromSearch() const { return mFromSearch; } - bool getInfoLoaded() { return mInfoLoaded; } + bool getInfoLoaded() const { return mInfoLoaded; } void setInfoLoaded(bool loaded) { mInfoLoaded = loaded; } @@ -175,9 +175,9 @@ public: void resetDirty() override; - bool isNew() { return mIsNew; } + bool isNew() const { return mIsNew; } - bool isNewWithErrors() { return mIsNewWithErrors; } + bool isNewWithErrors() const { return mIsNewWithErrors; } bool canClose(); @@ -191,10 +191,10 @@ public: bool getAutoRenew(); - S32 getPriceForListing() { return mPriceForListing; } + S32 getPriceForListing() const { return mPriceForListing; } void setEditMode(bool edit_mode); - bool getEditMode() {return mEditMode;} + bool getEditMode() const { return mEditMode; } static void setClickThrough( const LLUUID& classified_id, diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp index fa99432603..6292cc7810 100644 --- a/indra/newview/llpreviewscript.cpp +++ b/indra/newview/llpreviewscript.cpp @@ -703,9 +703,10 @@ void LLScriptEdCore::sync() } } -bool LLScriptEdCore::hasChanged() +bool LLScriptEdCore::hasChanged() const { - if (!mEditor) return false; + if (!mEditor) + return false; return ((!mEditor->isPristine() || mEnableSave) && mHasScriptData); } diff --git a/indra/newview/llpreviewscript.h b/indra/newview/llpreviewscript.h index 70ee1a4274..0bbe540207 100644 --- a/indra/newview/llpreviewscript.h +++ b/indra/newview/llpreviewscript.h @@ -143,7 +143,7 @@ public: void setItemRemoved(bool script_removed){mScriptRemoved = script_removed;}; void setAssetID( const LLUUID& asset_id){ mAssetID = asset_id; }; - LLUUID getAssetID() { return mAssetID; } + LLUUID getAssetID() const { return mAssetID; } bool isFontSizeChecked(const LLSD &userdata); void onChangeFontSize(const LLSD &size_name); @@ -155,7 +155,7 @@ public: void onBtnDynamicHelp(); void onBtnUndoChanges(); - bool hasChanged(); + bool hasChanged() const; void selectFirstError(); @@ -211,7 +211,6 @@ class LLScriptEdContainer : public LLPreview public: LLScriptEdContainer(const LLSD& key); - LLScriptEdContainer(const LLSD& key, const bool live); bool handleKeyHere(KEY key, MASK mask); diff --git a/indra/newview/llreflectionmap.cpp b/indra/newview/llreflectionmap.cpp index f77d37f821..07e2c39379 100644 --- a/indra/newview/llreflectionmap.cpp +++ b/indra/newview/llreflectionmap.cpp @@ -256,7 +256,7 @@ bool LLReflectionMap::getBox(LLMatrix4& box) glm::mat4 mv(get_current_modelview()); LLVector3 s = mViewerObject->getScale().scaledVec(LLVector3(0.5f, 0.5f, 0.5f)); mRadius = s.magVec(); - glm::mat4 scale = glm::scale(glm::make_vec3(s.mV)); + glm::mat4 scale = glm::scale(glm::make_vec3(LLVector4(s).mV)); if (mViewerObject->mDrawable != nullptr) { // object to agent space (no scale) diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp index 35057a910a..db3e6335ec 100644 --- a/indra/newview/lltexturectrl.cpp +++ b/indra/newview/lltexturectrl.cpp @@ -185,7 +185,8 @@ LLFloaterTexturePicker::LLFloaterTexturePicker( mSetImageAssetIDCallback(NULL), mOnUpdateImageStatsCallback(NULL), mBakeTextureEnabled(false), - mInventoryPickType(pick_type) + mInventoryPickType(pick_type), + mSelectionSource(PICKER_UNKNOWN) { mCanApplyImmediately = can_apply_immediately; buildFromFile("floater_texture_ctrl.xml"); @@ -203,6 +204,7 @@ void LLFloaterTexturePicker::setImageID(const LLUUID& image_id, bool set_selecti mNoCopyTextureSelected = false; mViewModel->setDirty(); // *TODO: shouldn't we be using setValue() here? mImageAssetID = image_id; + mSelectionSource = PICKER_UNKNOWN; if (LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::isBakedImageId(mImageAssetID)) { @@ -211,6 +213,7 @@ void LLFloaterTexturePicker::setImageID(const LLUUID& image_id, bool set_selecti mModeSelector->selectByValue(2); onModeSelect(0,this); } + mSelectionSource = PICKER_BAKE; } else { @@ -257,6 +260,7 @@ void LLFloaterTexturePicker::setImageID(const LLUUID& image_id, bool set_selecti getChild<LLUICtrl>("apply_immediate_check")->setValue(false); mNoCopyTextureSelected = true; } + mSelectionSource = PICKER_INVENTORY; } if (set_selection) @@ -276,6 +280,7 @@ void LLFloaterTexturePicker::setImageIDFromItem(const LLInventoryItem* itemp, bo asset_id = BLANK_MATERIAL_ASSET_ID; } setImageID(asset_id, set_selection); + mSelectionSource = PICKER_INVENTORY; } void LLFloaterTexturePicker::setActive( bool active ) @@ -890,10 +895,15 @@ void LLFloaterTexturePicker::commitCallback(LLTextureCtrl::ETexturePickOp op) { return; } + LLUUID asset_id = mImageAssetID; LLUUID inventory_id; LLUUID tracking_id; - LLPickerSource mode = (LLPickerSource)mModeSelector->getValue().asInteger(); + LLPickerSource mode = mSelectionSource; + if (mode == PICKER_UNKNOWN) + { + mode = (LLPickerSource)mModeSelector->getValue().asInteger(); + } switch (mode) { @@ -919,11 +929,13 @@ void LLFloaterTexturePicker::commitCallback(LLTextureCtrl::ETexturePickOp op) } else { + // Item's asset id changed? mode = PICKER_UNKNOWN; // source of id unknown } } else { + // Item could have been removed from inventory mode = PICKER_UNKNOWN; // source of id unknown } break; @@ -947,6 +959,7 @@ void LLFloaterTexturePicker::commitCallback(LLTextureCtrl::ETexturePickOp op) } else { + // List could have been emptied, with local image still selected asset_id = mImageAssetID; mode = PICKER_UNKNOWN; // source of id unknown } @@ -1000,18 +1013,6 @@ void LLFloaterTexturePicker::onBtnNone(void* userdata) self->commitIfImmediateSet(); } -/* -// static -void LLFloaterTexturePicker::onBtnRevert(void* userdata) -{ - LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata; - self->setImageID( self->mOriginalImageAssetID ); - // TODO: Change this to tell the owner to cancel. It needs to be - // smart enough to restore multi-texture selections. - self->mOwner->onFloaterCommit(); - self->mViewModel->resetDirty(); -}*/ - // static void LLFloaterTexturePicker::onBtnCancel(void* userdata) { @@ -1029,8 +1030,11 @@ void LLFloaterTexturePicker::onBtnCancel(void* userdata) void LLFloaterTexturePicker::onBtnSelect(void* userdata) { LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata; - if (self->mOnFloaterCommitCallback) + if (self->mViewModel->isDirty() && self->mOnFloaterCommitCallback) { + // If nothing changed, don't commit. + // ex: can overwrite multiple original textures with a single one. + // or resubmit something thus overriding some other source of change self->commitCallback(LLTextureCtrl::TEXTURE_SELECT); } self->closeFloater(); @@ -1067,8 +1071,18 @@ void LLFloaterTexturePicker::onSelectionChange(const std::deque<LLFolderViewItem { mNoCopyTextureSelected = true; } + bool was_dirty = mViewModel->isDirty(); setImageIDFromItem(itemp, false); - mViewModel->setDirty(); // *TODO: shouldn't we be using setValue() here? + if (user_action) + { + mViewModel->setDirty(); // *TODO: shouldn't we be using setValue() here? + setTentative( false ); + } + else if (!was_dirty) + { + // setImageIDFromItem could have dropped the flag + mViewModel->resetDirty(); + } if(!mPreviewSettingChanged) { @@ -1215,6 +1229,8 @@ void LLFloaterTexturePicker::onLocalScrollCommit(LLUICtrl* ctrl, void* userdata) inworld_id = LLLocalBitmapMgr::getInstance()->getWorldID(tracking_id); } + self->mSelectionSource = PICKER_LOCAL; + if (self->mSetImageAssetIDCallback) { self->mSetImageAssetIDCallback(inworld_id); @@ -1312,6 +1328,7 @@ void LLFloaterTexturePicker::onBakeTextureSelect(LLUICtrl* ctrl, void *user_data // only commit intentional selections, not implicit ones self->commitIfImmediateSet(); } + self->mSelectionSource = PICKER_BAKE; } void LLFloaterTexturePicker::setCanApply(bool can_preview, bool can_apply, bool inworld_image) @@ -1627,6 +1644,7 @@ void LLFloaterTexturePicker::onTextureSelect( const LLTextureEntry& te ) // no copy texture mNoCopyTextureSelected = true; } + mSelectionSource = PICKER_INVENTORY; commitIfImmediateSet(); } diff --git a/indra/newview/lltexturectrl.h b/indra/newview/lltexturectrl.h index df5e763139..e4d877e229 100644 --- a/indra/newview/lltexturectrl.h +++ b/indra/newview/lltexturectrl.h @@ -447,6 +447,7 @@ private: S32 mMaxDim; S32 mMinDim; EPickInventoryType mInventoryPickType; + LLPickerSource mSelectionSource; texture_selected_callback mTextureSelectedCallback; diff --git a/indra/newview/llviewerinput.cpp b/indra/newview/llviewerinput.cpp index ea3088613f..66042128f2 100644 --- a/indra/newview/llviewerinput.cpp +++ b/indra/newview/llviewerinput.cpp @@ -35,6 +35,7 @@ #include "llagentcamera.h" #include "llfloaterimnearbychat.h" #include "llfocusmgr.h" +#include "llgamecontrol.h" #include "llkeybind.h" // LLKeyData #include "llmorphview.h" #include "llmoveview.h" @@ -157,9 +158,6 @@ static void agent_handle_doubletap_run(EKeystate s, LLAgent::EDoubleTapRunMode m static void agent_push_forwardbackward( EKeystate s, S32 direction, LLAgent::EDoubleTapRunMode mode ) { - agent_handle_doubletap_run(s, mode); - if (KEYSTATE_UP == s) return; - F32 time = gKeyboard->getCurKeyElapsedTime(); S32 frame_count = ll_round(gKeyboard->getCurKeyElapsedFrameCount()); @@ -913,6 +911,20 @@ bool agent_control_lbutton_handle(EKeystate s) return true; } +template <U8 N> +bool game_control_button(EKeystate s) +{ + if (s == KEYSTATE_DOWN) + { + gAgent.pressGameControlButton(N); + } + else if ( s == KEYSTATE_UP) + { + gAgent.releaseGameControlButton(N); + } + return true; +} + // In-world keybindings, like walking or camera #define REGISTER_KEYBOARD_ACTION(KEY, ACTION) LLREGISTER_STATIC(LLKeyboardActionRegistry, KEY, LLKeybindFunctionData(ACTION, false)); // Global keybindings that should work even with floaters focused, like voice @@ -970,6 +982,38 @@ REGISTER_KEYBOARD_ACTION("walk_to", walk_to); REGISTER_KEYBOARD_GLOBAL_ACTION("toggle_voice", toggle_voice); REGISTER_KEYBOARD_GLOBAL_ACTION("voice_follow_key", voice_follow_key); REGISTER_KEYBOARD_ACTION(script_mouse_handler_name, script_trigger_lbutton); +REGISTER_KEYBOARD_ACTION("game_control_button_0", game_control_button<0>); +REGISTER_KEYBOARD_ACTION("game_control_button_1", game_control_button<1>); +REGISTER_KEYBOARD_ACTION("game_control_button_2", game_control_button<2>); +REGISTER_KEYBOARD_ACTION("game_control_button_3", game_control_button<3>); +REGISTER_KEYBOARD_ACTION("game_control_button_4", game_control_button<4>); +REGISTER_KEYBOARD_ACTION("game_control_button_5", game_control_button<5>); +REGISTER_KEYBOARD_ACTION("game_control_button_6", game_control_button<6>); +REGISTER_KEYBOARD_ACTION("game_control_button_7", game_control_button<7>); +REGISTER_KEYBOARD_ACTION("game_control_button_8", game_control_button<8>); +REGISTER_KEYBOARD_ACTION("game_control_button_9", game_control_button<9>); +REGISTER_KEYBOARD_ACTION("game_control_button_10", game_control_button<10>); +REGISTER_KEYBOARD_ACTION("game_control_button_11", game_control_button<11>); +REGISTER_KEYBOARD_ACTION("game_control_button_12", game_control_button<12>); +REGISTER_KEYBOARD_ACTION("game_control_button_13", game_control_button<13>); +REGISTER_KEYBOARD_ACTION("game_control_button_14", game_control_button<14>); +REGISTER_KEYBOARD_ACTION("game_control_button_15", game_control_button<15>); +REGISTER_KEYBOARD_ACTION("game_control_button_16", game_control_button<16>); +REGISTER_KEYBOARD_ACTION("game_control_button_17", game_control_button<17>); +REGISTER_KEYBOARD_ACTION("game_control_button_18", game_control_button<18>); +REGISTER_KEYBOARD_ACTION("game_control_button_19", game_control_button<19>); +REGISTER_KEYBOARD_ACTION("game_control_button_20", game_control_button<20>); +REGISTER_KEYBOARD_ACTION("game_control_button_21", game_control_button<21>); +REGISTER_KEYBOARD_ACTION("game_control_button_22", game_control_button<22>); +REGISTER_KEYBOARD_ACTION("game_control_button_23", game_control_button<23>); +REGISTER_KEYBOARD_ACTION("game_control_button_24", game_control_button<24>); +REGISTER_KEYBOARD_ACTION("game_control_button_25", game_control_button<25>); +REGISTER_KEYBOARD_ACTION("game_control_button_26", game_control_button<26>); +REGISTER_KEYBOARD_ACTION("game_control_button_27", game_control_button<27>); +REGISTER_KEYBOARD_ACTION("game_control_button_28", game_control_button<28>); +REGISTER_KEYBOARD_ACTION("game_control_button_29", game_control_button<29>); +REGISTER_KEYBOARD_ACTION("game_control_button_30", game_control_button<30>); +REGISTER_KEYBOARD_ACTION("game_control_button_31", game_control_button<31>); #undef REGISTER_KEYBOARD_ACTION LLViewerInput::LLViewerInput() diff --git a/indra/newview/llviewerjoystick.cpp b/indra/newview/llviewerjoystick.cpp index 7543fb3743..416f6a476a 100644 --- a/indra/newview/llviewerjoystick.cpp +++ b/indra/newview/llviewerjoystick.cpp @@ -41,6 +41,7 @@ #include "llagent.h" #include "llagentcamera.h" #include "llfocusmgr.h" +#include "llgamecontrol.h" #if LL_WINDOWS && !LL_MESA_HEADLESS // Require DirectInput version 8 @@ -289,6 +290,7 @@ NDOF_HotPlugResult LLViewerJoystick::HotPlugAddCallback(NDOF_Device *dev) ndof_dump(stderr, dev); joystick->mNdofDev = dev; joystick->mDriverState = JDS_INITIALIZED; + joystick->mDeviceIs3DConnexion = is3DConnexionDevice(joystick->mNdofDev->product); res = NDOF_KEEP_HOTPLUGGED; } joystick->updateEnabled(true); @@ -314,18 +316,11 @@ void LLViewerJoystick::HotPlugRemovalCallback(NDOF_Device *dev) // ----------------------------------------------------------------------------- LLViewerJoystick::LLViewerJoystick() -: mDriverState(JDS_UNINITIALIZED), - mNdofDev(NULL), - mResetFlag(false), - mCameraUpdated(true), - mOverrideCamera(false), - mJoystickRun(0) { for (int i = 0; i < 6; i++) { mAxes[i] = sDelta[i] = sLastDelta[i] = 0.0f; } - memset(mBtn, 0, sizeof(mBtn)); // factor in bandwidth? bandwidth = gViewerStats->mKBitStat @@ -404,6 +399,7 @@ void LLViewerJoystick::init(bool autoenable) else { mDriverState = JDS_INITIALIZED; + mDeviceIs3DConnexion = is3DConnexionDevice(mNdofDev->product); } } #endif @@ -500,6 +496,7 @@ void LLViewerJoystick::initDevice(LLSD &guid) else { mDriverState = JDS_INITIALIZED; + mDeviceIs3DConnexion = is3DConnexionDevice(mNdofDev->product); } } #endif @@ -584,6 +581,7 @@ bool LLViewerJoystick::initDevice(void * preffered_device /* LPDIRECTINPUTDEVICE else { mDriverState = JDS_INITIALIZED; + mDeviceIs3DConnexion = is3DConnexionDevice(mNdofDev->product); return true; } #endif @@ -599,6 +597,7 @@ void LLViewerJoystick::terminate() ndof_libcleanup(); // frees alocated memory in mNdofDev mDriverState = JDS_UNINITIALIZED; mNdofDev = NULL; + mDeviceIs3DConnexion = false; LL_INFOS("Joystick") << "Terminated connection with NDOF device." << LL_ENDL; } #endif @@ -1350,7 +1349,9 @@ bool LLViewerJoystick::toggleFlycam() void LLViewerJoystick::scanJoystick() { - if (mDriverState != JDS_INITIALIZED || !gSavedSettings.getBOOL("JoystickEnabled")) + if (mDriverState != JDS_INITIALIZED + || !gSavedSettings.getBOOL("JoystickEnabled") + || (!mDeviceIs3DConnexion && LLGameControl::isEnabled())) { return; } @@ -1513,14 +1514,23 @@ std::string LLViewerJoystick::getDescription() return res; } +// static +bool LLViewerJoystick::is3DConnexionDevice(const std::string& device_name) +{ + bool answer = device_name.find("Space") == 0 + && ( (device_name.find("SpaceNavigator") == 0) + || (device_name.find("SpaceExplorer") == 0) + || (device_name.find("SpaceTraveler") == 0) + || (device_name.find("SpacePilot") == 0) + || (device_name.find("SpaceMouse") == 0)); + return answer; +} + bool LLViewerJoystick::isLikeSpaceNavigator() const { #if LIB_NDOF return (isJoystickInitialized() - && (strncmp(mNdofDev->product, "SpaceNavigator", 14) == 0 - || strncmp(mNdofDev->product, "SpaceExplorer", 13) == 0 - || strncmp(mNdofDev->product, "SpaceTraveler", 13) == 0 - || strncmp(mNdofDev->product, "SpacePilot", 10) == 0)); + && is3DConnexionDevice(mNdofDev->product)); #else return false; #endif diff --git a/indra/newview/llviewerjoystick.h b/indra/newview/llviewerjoystick.h index c989615653..aaf9abb437 100644 --- a/indra/newview/llviewerjoystick.h +++ b/indra/newview/llviewerjoystick.h @@ -81,6 +81,8 @@ public: std::string getDescription(); void saveDeviceIdToSettings(); + static bool is3DConnexionDevice(const std::string& device_name); + protected: void updateEnabled(bool autoenable); void handleRun(F32 inc); @@ -100,19 +102,21 @@ protected: private: F32 mAxes[6]; long mBtn[16]; - EJoystickDriverState mDriverState; - NDOF_Device *mNdofDev; - bool mResetFlag; - F32 mPerfScale; - bool mCameraUpdated; - bool mOverrideCamera; - U32 mJoystickRun; + EJoystickDriverState mDriverState { JDS_UNINITIALIZED }; + NDOF_Device *mNdofDev { nullptr }; // Windows: _GUID as U8 binary map // MacOS: long as an U8 binary map // Else: integer 1 for no device/ndof's default device LLSD mLastDeviceUUID; + F32 mPerfScale; + U32 mJoystickRun { 0 }; + bool mResetFlag { false }; + bool mCameraUpdated { true }; + bool mOverrideCamera { false }; + bool mDeviceIs3DConnexion { false }; + static F32 sLastDelta[7]; static F32 sDelta[7]; }; diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 2f5a302b3f..39aa85beea 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -52,6 +52,7 @@ #include "llagentui.h" #include "llagentwearables.h" #include "llagentpilot.h" +#include "llavataractions.h" #include "llcompilequeue.h" #include "llconsole.h" #include "lldebugview.h" @@ -71,6 +72,7 @@ #include "llfloaterpathfindingcharacters.h" #include "llfloaterpathfindinglinksets.h" #include "llfloaterpay.h" +#include "llfloaterpreference.h" #include "llfloaterreporter.h" #include "llfloatersearch.h" #include "llfloaterscriptdebug.h" @@ -78,9 +80,10 @@ #include "llfloatertools.h" #include "llfloaterworldmap.h" #include "llfloaterbuildoptions.h" -#include "llavataractions.h" -#include "lllandmarkactions.h" +#include "fsyspath.h" +#include "llgamecontrol.h" #include "llgroupmgr.h" +#include "lllandmarkactions.h" #include "lltooltip.h" #include "lltoolface.h" #include "llhints.h" @@ -90,6 +93,7 @@ #include "llinventorybridge.h" #include "llinventorydefines.h" #include "llinventoryfunctions.h" +#include "llluamanager.h" #include "llpanellogin.h" #include "llpanelblockedlist.h" #include "llpanelmaininventory.h" @@ -941,17 +945,46 @@ class LLAdvancedToggleFeature : public view_listener_t class LLAdvancedCheckFeature : public view_listener_t { bool handleEvent(const LLSD& userdata) -{ - U32 feature = feature_from_string( userdata.asString() ); - bool new_value = false; + { + U32 feature = feature_from_string( userdata.asString() ); + bool new_value = false; - if ( feature != 0 ) + if ( feature != 0 ) + { + new_value = LLPipeline::toggleRenderDebugFeatureControl( feature ); + } + + return new_value; + } +}; + +class LLAdvancedToggleExperiment : public view_listener_t +{ + bool handleEvent(const LLSD& userdata) { - new_value = LLPipeline::toggleRenderDebugFeatureControl( feature ); + std::string feature = userdata.asString(); + if (feature == "GameControl") + { + LLGameControl::setEnabled(! LLGameControl::isEnabled()); + LLFloaterPreference::refreshInstance(); + return true; + } + return false; } +}; - return new_value; -} +class LLAdvancedCheckExperiment : public view_listener_t +{ + bool handleEvent(const LLSD& userdata) + { + bool value = false; + std::string feature = userdata.asString(); + if (feature == "GameControl") + { + value = LLGameControl::isEnabled(); + } + return value; + } }; class LLAdvancedCheckDisplayTextureDensity : public view_listener_t @@ -9461,6 +9494,18 @@ void LLUploadCostCalculator::calculateCost(const std::string& asset_type_str) mCostStr = std::to_string(upload_cost); } +void lua_run_script(const LLSD& userdata) +{ + std::string script_path = userdata.asString(); + if (script_path.empty()) + { + LL_WARNS() << "Script name is not specified" << LL_ENDL; + return; + } + + LLLUAmanager::runScriptFile(script_path); +} + void show_navbar_context_menu(LLView* ctrl, S32 x, S32 y) { static LLMenuGL* show_navbar_context_menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_hide_navbar.xml", @@ -9715,6 +9760,9 @@ void initialize_menus() view_listener_t::addMenu(new LLAdvancedToggleFeature(), "Advanced.ToggleFeature"); view_listener_t::addMenu(new LLAdvancedCheckFeature(), "Advanced.CheckFeature"); + view_listener_t::addMenu(new LLAdvancedToggleExperiment(), "Advanced.ToggleExperiment"); + view_listener_t::addMenu(new LLAdvancedCheckExperiment(), "Advanced.CheckExperiment"); + view_listener_t::addMenu(new LLAdvancedCheckDisplayTextureDensity(), "Advanced.CheckDisplayTextureDensity"); view_listener_t::addMenu(new LLAdvancedSetDisplayTextureDensity(), "Advanced.SetDisplayTextureDensity"); @@ -10062,4 +10110,6 @@ void initialize_menus() view_listener_t::addMenu(new LLEditableSelected(), "EditableSelected"); view_listener_t::addMenu(new LLEditableSelectedMono(), "EditableSelectedMono"); view_listener_t::addMenu(new LLToggleUIHints(), "ToggleUIHints"); + + registrar.add("Lua.RunScript", boost::bind(&lua_run_script, _2), cb_info::UNTRUSTED_BLOCK); } diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index a37e15f8da..da019d60d8 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -3153,8 +3153,8 @@ void process_crossed_region(LLMessageSystem* msg, void**) } -// sends an AgentUpdate message to the server... or not: -// only when force_send is 'true' OR +// sends an AgentUpdate message to the server... or not +// e.g. only when force_send is 'true' OR // something changed AND the update is not being throttled void send_agent_update(bool force_send, bool send_reliable) { @@ -3220,8 +3220,6 @@ void send_agent_update(bool force_send, bool send_reliable) return; } - bool send_update = force_send || sec_since_last_send > MAX_AGENT_UPDATE_PERIOD; - LLVector3 camera_pos_agent = gAgentCamera.getCameraPositionAgent(); // local to avatar's region LLVector3 camera_at = LLViewerCamera::getInstance()->getAtAxis(); LLQuaternion body_rotation = gAgent.getFrameAgent().getQuaternion(); @@ -3238,6 +3236,7 @@ void send_agent_update(bool force_send, bool send_reliable) flags |= AU_FLAGS_CLIENT_AUTOPILOT; } + bool send_update = force_send || sec_since_last_send > MAX_AGENT_UPDATE_PERIOD; if (!send_update) { // check to see if anything changed diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index 58b541b19b..a8fe221d98 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -37,7 +37,6 @@ #include "llrender.h" #include "llenvironment.h" #include "llerrorcontrol.h" -#include "llatmosphere.h" #include "llworld.h" #include "llsky.h" @@ -731,14 +730,6 @@ std::string LLViewerShaderMgr::loadBasicShaders() S32 sum_lights_class = 3; -#if LL_DARWIN - // Work around driver crashes on older Macs when using deferred rendering - // NORSPEC-59 - // - if (gGLManager.mIsMobileGF) - sum_lights_class = 3; -#endif - // Use the feature table to mask out the max light level to use. Also make sure it's at least 1. S32 max_light_class = gSavedSettings.getS32("RenderShaderLightingMaxLevel"); sum_lights_class = llclamp(sum_lights_class, 1, max_light_class); diff --git a/indra/newview/llviewerstats.cpp b/indra/newview/llviewerstats.cpp index ff86684499..9d4c072909 100644 --- a/indra/newview/llviewerstats.cpp +++ b/indra/newview/llviewerstats.cpp @@ -781,7 +781,7 @@ void send_viewer_stats(bool include_preferences) LL_INFOS("LogViewerStatsPacket") << "Sending viewer statistics: " << body << LL_ENDL; // <ND> Do those lines even do anything sane in regard of debug logging? - LL_DEBUGS("LogViewerStatsPacket"); + LL_DEBUGS("LogViewerStatsPacket") << " "; std::string filename("viewer_stats_packet.xml"); llofstream of(filename.c_str()); LLSDSerialize::toPrettyXML(body,of); diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index 9e1cb84bd1..0f9c65893d 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -2495,6 +2495,11 @@ bool LLViewerFetchedTexture::doLoadedCallbacks() } } + if (need_readback) + { + readbackRawImage(); + } + // // Run raw/auxiliary data callbacks // @@ -2744,10 +2749,22 @@ void LLViewerFetchedTexture::readbackRawImage() if (mGLTexturep.notNull() && mGLTexturep->getTexName() != 0 && (mRawImage.isNull() || mRawImage->getWidth() < mGLTexturep->getWidth() || mRawImage->getHeight() < mGLTexturep->getHeight() )) { + if (mRawImage.isNull()) + { + sRawCount++; + } mRawImage = new LLImageRaw(); if (!mGLTexturep->readBackRaw(-1, mRawImage, false)) { mRawImage = nullptr; + mIsRawImageValid = false; + mRawDiscardLevel = INVALID_DISCARD_LEVEL; + sRawCount--; + } + else + { + mIsRawImageValid = true; + mRawDiscardLevel = mGLTexturep->getDiscardLevel(); } } } diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 8178dade8b..c8a4e4c205 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -1940,10 +1940,10 @@ bool LLVOAvatar::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& if (linesegment_sphere(LLVector3(glm::value_ptr(p1)), LLVector3(glm::value_ptr(p2)), LLVector3(0,0,0), 1.f, position, norm)) { - glm::vec3 res_pos(glm::make_vec3(position.mV)); + glm::vec3 res_pos(glm::make_vec3(LLVector4(position).mV)); res_pos = mul_mat4_vec3(mat, res_pos); - glm::vec3 res_norm(glm::make_vec3(norm.mV)); + glm::vec3 res_norm(glm::make_vec3(LLVector4(norm).mV)); res_norm = glm::normalize(res_norm); res_norm = glm::mat3(norm_mat) * res_norm; diff --git a/indra/newview/llxmlrpctransaction.cpp b/indra/newview/llxmlrpctransaction.cpp index 07e2b118d3..0f956d8350 100644 --- a/indra/newview/llxmlrpctransaction.cpp +++ b/indra/newview/llxmlrpctransaction.cpp @@ -218,7 +218,7 @@ LLXMLRPCTransaction::Impl::Impl mCertStore = gSavedSettings.getString("CertStore"); httpOpts->setSSLVerifyPeer(vefifySSLCert); - httpOpts->setSSLVerifyHost(vefifySSLCert ? 2 : 0); + httpOpts->setSSLVerifyHost(vefifySSLCert); // LLRefCounted starts with a 1 ref, so don't add a ref in the smart pointer httpHeaders = LLCore::HttpHeaders::ptr_t(new LLCore::HttpHeaders()); diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index eb353beb11..84f026699e 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -35,6 +35,7 @@ #include "llviewercontrol.h" #include "llfasttimer.h" #include "llfontgl.h" +#include "llfontvertexbuffer.h" #include "llnamevalue.h" #include "llpointer.h" #include "llprimitive.h" @@ -138,7 +139,6 @@ bool gShiftFrame = false; //cached settings bool LLPipeline::WindLightUseAtmosShaders; bool LLPipeline::RenderDeferred; -F32 LLPipeline::RenderDeferredSunWash; U32 LLPipeline::RenderFSAAType; U32 LLPipeline::RenderResolutionDivisor; bool LLPipeline::RenderUIBuffer; @@ -179,7 +179,6 @@ F32 LLPipeline::CameraFocusTransitionTime; F32 LLPipeline::CameraFNumber; F32 LLPipeline::CameraFocalLength; F32 LLPipeline::CameraFieldOfView; -F32 LLPipeline::RenderShadowNoise; F32 LLPipeline::RenderShadowBlurSize; F32 LLPipeline::RenderSSAOScale; U32 LLPipeline::RenderSSAOMaxScale; @@ -192,8 +191,6 @@ F32 LLPipeline::RenderShadowBias; F32 LLPipeline::RenderSpotShadowOffset; F32 LLPipeline::RenderSpotShadowBias; LLDrawable* LLPipeline::RenderSpotLight = nullptr; -F32 LLPipeline::RenderEdgeDepthCutoff; -F32 LLPipeline::RenderEdgeNormCutoff; LLVector3 LLPipeline::RenderShadowGaussian; F32 LLPipeline::RenderShadowBlurDistFactor; bool LLPipeline::RenderDeferredAtmospheric; @@ -276,7 +273,6 @@ static LLTrace::BlockTimerStatHandle FTM_STATESORT_DRAWABLE("Sort Drawables"); static LLStaticHashedString sTint("tint"); static LLStaticHashedString sAmbiance("ambiance"); static LLStaticHashedString sAlphaScale("alpha_scale"); -static LLStaticHashedString sNormMat("norm_mat"); static LLStaticHashedString sOffset("offset"); static LLStaticHashedString sScreenRes("screenRes"); static LLStaticHashedString sDelta("delta"); @@ -501,7 +497,6 @@ void LLPipeline::init() connectRefreshCachedSettingsSafe("UseOcclusion"); // DEPRECATED -- connectRefreshCachedSettingsSafe("WindLightUseAtmosShaders"); // DEPRECATED -- connectRefreshCachedSettingsSafe("RenderDeferred"); - connectRefreshCachedSettingsSafe("RenderDeferredSunWash"); connectRefreshCachedSettingsSafe("RenderFSAAType"); connectRefreshCachedSettingsSafe("RenderResolutionDivisor"); connectRefreshCachedSettingsSafe("RenderUIBuffer"); @@ -542,7 +537,6 @@ void LLPipeline::init() connectRefreshCachedSettingsSafe("CameraFNumber"); connectRefreshCachedSettingsSafe("CameraFocalLength"); connectRefreshCachedSettingsSafe("CameraFieldOfView"); - connectRefreshCachedSettingsSafe("RenderShadowNoise"); connectRefreshCachedSettingsSafe("RenderShadowBlurSize"); connectRefreshCachedSettingsSafe("RenderSSAOScale"); connectRefreshCachedSettingsSafe("RenderSSAOMaxScale"); @@ -554,8 +548,6 @@ void LLPipeline::init() connectRefreshCachedSettingsSafe("RenderShadowBias"); connectRefreshCachedSettingsSafe("RenderSpotShadowOffset"); connectRefreshCachedSettingsSafe("RenderSpotShadowBias"); - connectRefreshCachedSettingsSafe("RenderEdgeDepthCutoff"); - connectRefreshCachedSettingsSafe("RenderEdgeNormCutoff"); connectRefreshCachedSettingsSafe("RenderShadowGaussian"); connectRefreshCachedSettingsSafe("RenderShadowBlurDistFactor"); connectRefreshCachedSettingsSafe("RenderDeferredAtmospheric"); @@ -580,7 +572,16 @@ void LLPipeline::init() connectRefreshCachedSettingsSafe("RenderMirrors"); connectRefreshCachedSettingsSafe("RenderHeroProbeUpdateRate"); connectRefreshCachedSettingsSafe("RenderHeroProbeConservativeUpdateMultiplier"); - gSavedSettings.getControl("RenderAutoHideSurfaceAreaLimit")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); + connectRefreshCachedSettingsSafe("RenderAutoHideSurfaceAreaLimit"); + + LLPointer<LLControlVariable> cntrl_ptr = gSavedSettings.getControl("CollectFontVertexBuffers"); + if (cntrl_ptr.notNull()) + { + cntrl_ptr->getCommitSignal()->connect([](LLControlVariable* control, const LLSD& value, const LLSD& previous) + { + LLFontVertexBuffer::enableBufferCollection(control->getValue().asBoolean()); + }); + } } LLPipeline::~LLPipeline() @@ -1010,7 +1011,6 @@ void LLPipeline::refreshCachedSettings() WindLightUseAtmosShaders = true; // DEPRECATED -- gSavedSettings.getBOOL("WindLightUseAtmosShaders"); RenderDeferred = true; // DEPRECATED -- gSavedSettings.getBOOL("RenderDeferred"); - RenderDeferredSunWash = gSavedSettings.getF32("RenderDeferredSunWash"); RenderFSAAType = gSavedSettings.getU32("RenderFSAAType"); RenderResolutionDivisor = gSavedSettings.getU32("RenderResolutionDivisor"); RenderUIBuffer = gSavedSettings.getBOOL("RenderUIBuffer"); @@ -1051,7 +1051,6 @@ void LLPipeline::refreshCachedSettings() CameraFNumber = gSavedSettings.getF32("CameraFNumber"); CameraFocalLength = gSavedSettings.getF32("CameraFocalLength"); CameraFieldOfView = gSavedSettings.getF32("CameraFieldOfView"); - RenderShadowNoise = gSavedSettings.getF32("RenderShadowNoise"); RenderShadowBlurSize = gSavedSettings.getF32("RenderShadowBlurSize"); RenderSSAOScale = gSavedSettings.getF32("RenderSSAOScale"); RenderSSAOMaxScale = gSavedSettings.getU32("RenderSSAOMaxScale"); @@ -1063,8 +1062,6 @@ void LLPipeline::refreshCachedSettings() RenderShadowBias = gSavedSettings.getF32("RenderShadowBias"); RenderSpotShadowOffset = gSavedSettings.getF32("RenderSpotShadowOffset"); RenderSpotShadowBias = gSavedSettings.getF32("RenderSpotShadowBias"); - RenderEdgeDepthCutoff = gSavedSettings.getF32("RenderEdgeDepthCutoff"); - RenderEdgeNormCutoff = gSavedSettings.getF32("RenderEdgeNormCutoff"); RenderShadowGaussian = gSavedSettings.getVector3("RenderShadowGaussian"); RenderShadowBlurDistFactor = gSavedSettings.getF32("RenderShadowBlurDistFactor"); RenderDeferredAtmospheric = gSavedSettings.getBOOL("RenderDeferredAtmospheric"); @@ -1098,6 +1095,8 @@ void LLPipeline::refreshCachedSettings() LLVOAvatar::sMaxNonImpostors = 1; LLVOAvatar::updateImpostorRendering(LLVOAvatar::sMaxNonImpostors); } + + LLFontVertexBuffer::enableBufferCollection(gSavedSettings.getBOOL("CollectFontVertexBuffers")); } void LLPipeline::releaseGLBuffers() @@ -3475,8 +3474,6 @@ void LLPipeline::postSort(LLCamera &camera) assertInitialized(); - LL_PUSH_CALLSTACKS(); - if (!gCubeSnapshot) { // rebuild drawable geometry @@ -3492,15 +3489,12 @@ void LLPipeline::postSort(LLCamera &camera) group->rebuildGeom(); } } - LL_PUSH_CALLSTACKS(); // rebuild groups sCull->assertDrawMapsEmpty(); rebuildPriorityGroups(); } - LL_PUSH_CALLSTACKS(); - // build render map for (LLCullResult::sg_iterator i = sCull->beginVisibleGroups(); i != sCull->endVisibleGroups(); ++i) { @@ -3621,7 +3615,6 @@ void LLPipeline::postSort(LLCamera &camera) std::sort(sCull->beginRiggedAlphaGroups(), sCull->endRiggedAlphaGroups(), LLSpatialGroup::CompareRenderOrder()); } - LL_PUSH_CALLSTACKS(); // only render if the flag is set. The flag is only set if we are in edit mode or the toggle is set in the menus if (LLFloaterReg::instanceVisible("beacons") && !sShadowRender && !gCubeSnapshot) { @@ -3674,7 +3667,7 @@ void LLPipeline::postSort(LLCamera &camera) forAllVisibleDrawables(renderSoundHighlights); } } - LL_PUSH_CALLSTACKS(); + // If managing your telehub, draw beacons at telehub and currently selected spawnpoint. if (LLFloaterTelehub::renderBeacons() && !sShadowRender && !gCubeSnapshot) { @@ -3735,7 +3728,6 @@ void LLPipeline::postSort(LLCamera &camera) LLVertexBuffer::flushBuffers(); // LLSpatialGroup::sNoDelete = false; - LL_PUSH_CALLSTACKS(); } @@ -7278,7 +7270,7 @@ void LLPipeline::generateGlow(LLRenderTarget* src) void LLPipeline::applyCAS(LLRenderTarget* src, LLRenderTarget* dst) { static LLCachedControl<F32> cas_sharpness(gSavedSettings, "RenderCASSharpness", 0.4f); - if (cas_sharpness == 0.0f) + if (cas_sharpness == 0.0f || !gCASProgram.isComplete()) { gPipeline.copyRenderTarget(src, dst); return; @@ -7752,8 +7744,6 @@ void LLPipeline::renderDoF(LLRenderTarget* src, LLRenderTarget* dst) gDeferredCoFProgram.bindTexture(LLShaderMgr::DEFERRED_DIFFUSE, src, LLTexUnit::TFO_POINT); gDeferredCoFProgram.bindTexture(LLShaderMgr::DEFERRED_DEPTH, &mRT->deferredScreen, true); - gDeferredCoFProgram.uniform1f(LLShaderMgr::DEFERRED_DEPTH_CUTOFF, RenderEdgeDepthCutoff); - gDeferredCoFProgram.uniform1f(LLShaderMgr::DEFERRED_NORM_CUTOFF, RenderEdgeNormCutoff); gDeferredCoFProgram.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, (GLfloat)dst->getWidth(), (GLfloat)dst->getHeight()); gDeferredCoFProgram.uniform1f(LLShaderMgr::DOF_FOCAL_DISTANCE, -subject_distance / 1000.f); gDeferredCoFProgram.uniform1f(LLShaderMgr::DOF_BLUR_CONSTANT, blur_constant); @@ -8065,32 +8055,11 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, LLRenderTarget* light_ stop_glerror(); } - channel = shader.enableTexture(LLShaderMgr::EXPOSURE_MAP); - if (channel > -1) - { - gGL.getTexUnit(channel)->bind(&mExposureMap); - } - - if (shader.getUniformLocation(LLShaderMgr::VIEWPORT) != -1) - { - shader.uniform4f(LLShaderMgr::VIEWPORT, (F32) gGLViewport[0], - (F32) gGLViewport[1], - (F32) gGLViewport[2], - (F32) gGLViewport[3]); - } - if (sReflectionRender && !shader.getUniformLocation(LLShaderMgr::MODELVIEW_MATRIX)) { shader.uniformMatrix4fv(LLShaderMgr::MODELVIEW_MATRIX, 1, false, glm::value_ptr(mReflectionModelView)); } - channel = shader.enableTexture(LLShaderMgr::DEFERRED_NOISE); - if (channel > -1) - { - gGL.getTexUnit(channel)->bindManual(LLTexUnit::TT_TEXTURE, mNoiseMap); - gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT); - } - bindLightFunc(shader); stop_glerror(); @@ -8154,34 +8123,6 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, LLRenderTarget* light_ bindReflectionProbes(shader); - if (gAtmosphere) - { - // bind precomputed textures necessary for calculating sun and sky luminance - channel = shader.enableTexture(LLShaderMgr::TRANSMITTANCE_TEX, LLTexUnit::TT_TEXTURE); - if (channel > -1) - { - shader.bindTexture(LLShaderMgr::TRANSMITTANCE_TEX, gAtmosphere->getTransmittance()); - } - - channel = shader.enableTexture(LLShaderMgr::SCATTER_TEX, LLTexUnit::TT_TEXTURE_3D); - if (channel > -1) - { - shader.bindTexture(LLShaderMgr::SCATTER_TEX, gAtmosphere->getScattering()); - } - - channel = shader.enableTexture(LLShaderMgr::SINGLE_MIE_SCATTER_TEX, LLTexUnit::TT_TEXTURE_3D); - if (channel > -1) - { - shader.bindTexture(LLShaderMgr::SINGLE_MIE_SCATTER_TEX, gAtmosphere->getMieScattering()); - } - - channel = shader.enableTexture(LLShaderMgr::ILLUMINANCE_TEX, LLTexUnit::TT_TEXTURE); - if (channel > -1) - { - shader.bindTexture(LLShaderMgr::ILLUMINANCE_TEX, gAtmosphere->getIlluminance()); - } - } - /*if (gCubeSnapshot) { // we only really care about the first two values, but the shader needs increasing separation between clip planes shader.uniform4f(LLShaderMgr::DEFERRED_SHADOW_CLIP, 1.f, 64.f, 128.f, 256.f); @@ -8190,26 +8131,6 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, LLRenderTarget* light_ { shader.uniform4fv(LLShaderMgr::DEFERRED_SHADOW_CLIP, 1, mSunClipPlanes.mV); } - shader.uniform1f(LLShaderMgr::DEFERRED_SUN_WASH, RenderDeferredSunWash); - shader.uniform1f(LLShaderMgr::DEFERRED_SHADOW_NOISE, RenderShadowNoise); - shader.uniform1f(LLShaderMgr::DEFERRED_BLUR_SIZE, RenderShadowBlurSize); - - shader.uniform1f(LLShaderMgr::DEFERRED_SSAO_RADIUS, RenderSSAOScale); - shader.uniform1f(LLShaderMgr::DEFERRED_SSAO_MAX_RADIUS, (GLfloat)RenderSSAOMaxScale); - - F32 ssao_factor = RenderSSAOFactor; - shader.uniform1f(LLShaderMgr::DEFERRED_SSAO_FACTOR, ssao_factor); - shader.uniform1f(LLShaderMgr::DEFERRED_SSAO_FACTOR_INV, 1.0f/ssao_factor); - - LLVector3 ssao_effect = RenderSSAOEffect; - F32 matrix_diag = (ssao_effect[0] + 2.0f*ssao_effect[1])/3.0f; - F32 matrix_nondiag = (ssao_effect[0] - ssao_effect[1])/3.0f; - // This matrix scales (proj of color onto <1/rt(3),1/rt(3),1/rt(3)>) by - // value factor, and scales remainder by saturation factor - F32 ssao_effect_mat[] = { matrix_diag, matrix_nondiag, matrix_nondiag, - matrix_nondiag, matrix_diag, matrix_nondiag, - matrix_nondiag, matrix_nondiag, matrix_diag}; - shader.uniformMatrix3fv(LLShaderMgr::DEFERRED_SSAO_EFFECT_MAT, 1, GL_FALSE, ssao_effect_mat); //F32 shadow_offset_error = 1.f + RenderShadowOffsetError * fabsf(LLViewerCamera::getInstance()->getOrigin().mV[2]); F32 shadow_bias_error = RenderShadowBiasError * fabsf(LLViewerCamera::getInstance()->getOrigin().mV[2])/3000.f; @@ -8226,20 +8147,12 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, LLRenderTarget* light_ shader.uniform3fv(LLShaderMgr::DEFERRED_MOON_DIR, 1, mTransformedMoonDir.mV); shader.uniform2f(LLShaderMgr::DEFERRED_SHADOW_RES, (GLfloat)mRT->shadow[0].getWidth(), (GLfloat)mRT->shadow[0].getHeight()); shader.uniform2f(LLShaderMgr::DEFERRED_PROJ_SHADOW_RES, (GLfloat)mSpotShadow[0].getWidth(), (GLfloat)mSpotShadow[0].getHeight()); - shader.uniform1f(LLShaderMgr::DEFERRED_DEPTH_CUTOFF, RenderEdgeDepthCutoff); - shader.uniform1f(LLShaderMgr::DEFERRED_NORM_CUTOFF, RenderEdgeNormCutoff); shader.uniformMatrix4fv(LLShaderMgr::MODELVIEW_DELTA_MATRIX, 1, GL_FALSE, glm::value_ptr(gGLDeltaModelView)); shader.uniformMatrix4fv(LLShaderMgr::INVERSE_MODELVIEW_DELTA_MATRIX, 1, GL_FALSE, glm::value_ptr(gGLInverseDeltaModelView)); shader.uniform1i(LLShaderMgr::CUBE_SNAPSHOT, gCubeSnapshot ? 1 : 0); - if (shader.getUniformLocation(LLShaderMgr::DEFERRED_NORM_MATRIX) >= 0) - { - glm::mat4 norm_mat = glm::transpose(glm::inverse(get_current_modelview())); - shader.uniformMatrix4fv(LLShaderMgr::DEFERRED_NORM_MATRIX, 1, false, glm::value_ptr(norm_mat)); - } - // auto adjust legacy sun color if needed static LLCachedControl<bool> should_auto_adjust(gSavedSettings, "RenderSkyAutoAdjustLegacy", true); static LLCachedControl<F32> auto_adjust_sun_color_scale(gSavedSettings, "RenderSkyAutoAdjustSunColorScale", 1.f); @@ -8339,12 +8252,31 @@ void LLPipeline::renderDeferredLighting() (GLfloat)deferred_light_target->getWidth(), (GLfloat)deferred_light_target->getHeight()); + if (RenderDeferredSSAO && !gCubeSnapshot) + { + sun_shader.uniform1f(LLShaderMgr::DEFERRED_SSAO_RADIUS, RenderSSAOScale); + sun_shader.uniform1f(LLShaderMgr::DEFERRED_SSAO_MAX_RADIUS, (GLfloat)RenderSSAOMaxScale); + + F32 ssao_factor = RenderSSAOFactor; + sun_shader.uniform1f(LLShaderMgr::DEFERRED_SSAO_FACTOR, ssao_factor); + sun_shader.uniform1f(LLShaderMgr::DEFERRED_SSAO_FACTOR_INV, 1.0f / ssao_factor); + + S32 channel = sun_shader.enableTexture(LLShaderMgr::DEFERRED_NOISE); + if (channel > -1) + { + gGL.getTexUnit(channel)->bindManual(LLTexUnit::TT_TEXTURE, mNoiseMap); + gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT); + } + } + { LLGLDisable blend(GL_BLEND); LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_ALWAYS); mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); } + sun_shader.disableTexture(LLShaderMgr::DEFERRED_NOISE); + unbindDeferredShader(sun_shader); } deferred_light_target->flush(); @@ -8410,7 +8342,9 @@ void LLPipeline::renderDeferredLighting() unbindDeferredShader(gDeferredBlurLightProgram); } screen_target->bindTarget(); - screen_target->invalidate(GL_COLOR_BUFFER_BIT); + // clear color buffer here - zeroing alpha (glow) is important or it will accumulate against sky + glClearColor(0, 0, 0, 0); + screen_target->clear(GL_COLOR_BUFFER_BIT); if (RenderDeferredAtmospheric) { // apply sunlight contribution @@ -8434,6 +8368,19 @@ void LLPipeline::renderDeferredLighting() soften_shader.uniform4fv(LLShaderMgr::WATER_WATERPLANE, 1, LLDrawPoolAlpha::sWaterPlane.mV); + if(RenderDeferredSSAO) + { + LLVector3 ssao_effect = RenderSSAOEffect; + F32 matrix_diag = (ssao_effect[0] + 2.0f * ssao_effect[1]) / 3.0f; + F32 matrix_nondiag = (ssao_effect[0] - ssao_effect[1]) / 3.0f; + // This matrix scales (proj of color onto <1/rt(3),1/rt(3),1/rt(3)>) by + // value factor, and scales remainder by saturation factor + F32 ssao_effect_mat[] = { matrix_diag, matrix_nondiag, matrix_nondiag, + matrix_nondiag, matrix_diag, matrix_nondiag, + matrix_nondiag, matrix_nondiag, matrix_diag }; + soften_shader.uniformMatrix3fv(LLShaderMgr::DEFERRED_SSAO_EFFECT_MAT, 1, GL_FALSE, ssao_effect_mat); + } + { LLGLDepthTest depth(GL_FALSE); LLGLDisable blend(GL_BLEND); @@ -8666,13 +8613,12 @@ void LLPipeline::renderDeferredLighting() LLDrawable* drawablep = *iter; LLVOVolume* volume = drawablep->getVOVolume(); LLVector3 center = drawablep->getPositionAgent(); - F32* c = center.mV; F32 light_size_final = volume->getLightRadius() * 1.5f; F32 light_falloff_final = volume->getLightFalloff(DEFERRED_LIGHT_FALLOFF); sVisibleLightCount++; - glm::vec3 tc(glm::make_vec3(c)); + glm::vec3 tc(glm::make_vec3(LLVector4(center).mV)); tc = mul_mat4_vec3(mat, tc); setupSpotLight(gDeferredMultiSpotLightProgram, drawablep); @@ -9056,7 +9002,6 @@ void LLPipeline::unbindDeferredShader(LLGLSLShader &shader) shader.disableTexture(LLShaderMgr::DEFERRED_DEPTH, deferred_target->getUsage()); shader.disableTexture(LLShaderMgr::DEFERRED_LIGHT, deferred_light_target->getUsage()); shader.disableTexture(LLShaderMgr::DIFFUSE_MAP); - shader.disableTexture(LLShaderMgr::DEFERRED_BLOOM); for (U32 i = 0; i < 4; i++) { @@ -9074,7 +9019,6 @@ void LLPipeline::unbindDeferredShader(LLGLSLShader &shader) } } - shader.disableTexture(LLShaderMgr::DEFERRED_NOISE); shader.disableTexture(LLShaderMgr::DEFERRED_LIGHTFUNC); if (!LLPipeline::sReflectionProbesEnabled) @@ -10214,7 +10158,7 @@ void LLPipeline::generateSunShadow(LLCamera& camera) view[j] = glm::inverse(view[j]); //llassert(origin.isFinite()); - glm::vec3 origin_agent(glm::make_vec3(origin.mV)); + glm::vec3 origin_agent(glm::make_vec3(LLVector4(origin).mV)); //translate view to origin origin_agent = mul_mat4_vec3(view[j], origin_agent); diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index 5c9b95ef4a..c69ca863e7 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -1000,7 +1000,6 @@ public: //cached settings static bool WindLightUseAtmosShaders; static bool RenderDeferred; - static F32 RenderDeferredSunWash; static U32 RenderFSAAType; static U32 RenderResolutionDivisor; static bool RenderUIBuffer; @@ -1042,7 +1041,6 @@ public: static F32 CameraFNumber; static F32 CameraFocalLength; static F32 CameraFieldOfView; - static F32 RenderShadowNoise; static F32 RenderShadowBlurSize; static F32 RenderSSAOScale; static U32 RenderSSAOMaxScale; @@ -1055,8 +1053,6 @@ public: static F32 RenderSpotShadowOffset; static F32 RenderSpotShadowBias; static LLDrawable* RenderSpotLight; - static F32 RenderEdgeDepthCutoff; - static F32 RenderEdgeNormCutoff; static LLVector3 RenderShadowGaussian; static F32 RenderShadowBlurDistFactor; static bool RenderDeferredAtmospheric; diff --git a/indra/newview/scripts/lua/test_top_menu.lua b/indra/newview/scripts/lua/test_top_menu.lua index 780a384c92..f877cda5eb 100644 --- a/indra/newview/scripts/lua/test_top_menu.lua +++ b/indra/newview/scripts/lua/test_top_menu.lua @@ -18,17 +18,35 @@ UI.addMenuItem{name="lua_scripts",label="Scripts", --Add menu separator to the 'LUA Menu' under added menu items UI.addMenuSeparator{parent_menu=MENU_NAME} ---Add two new menu branch 'About...' to the 'LUA Menu' -local BRANCH_NAME = "about_branch" -UI.addMenuBranch{name="about_branch",label="About...",parent_menu=MENU_NAME} +--Add 'Demo scripts...' branch to the 'LUA Menu' +local DEMO_BRANCH = "demo_scripts" +UI.addMenuBranch{name=DEMO_BRANCH,label="Demo scripts...",parent_menu=MENU_NAME} + +--Add menu items to the 'Demo scripts...' branch, which will invoke specified script on click +UI.addMenuItem{name="speedometer",label="Speedometer", + param="test_luafloater_speedometer.lua", + func="Lua.RunScript", + parent_menu=DEMO_BRANCH} + +UI.addMenuItem{name="gesture_list",label="Gesture list", + param="test_luafloater_gesture_list.lua", + func="Lua.RunScript", + parent_menu=DEMO_BRANCH} + +--Add one more menu separator +UI.addMenuSeparator{parent_menu=MENU_NAME} + +--Add 'About...' branch to the 'LUA Menu' +local ABOUT_BRANCH = "about_branch" +UI.addMenuBranch{name=ABOUT_BRANCH,label="About...",parent_menu=MENU_NAME} --Add two new menu items to the 'About...' branch UI.addMenuItem{name="lua_info",label="Lua...", param="https://www.lua.org/about.html", func="Advanced.ShowURL", - parent_menu=BRANCH_NAME} + parent_menu=ABOUT_BRANCH} UI.addMenuItem{name="lua_info",label="Luau...", param="https://luau-lang.org/", func="Advanced.ShowURL", - parent_menu=BRANCH_NAME} + parent_menu=ABOUT_BRANCH} diff --git a/indra/newview/skins/default/textures/bottomtray/Dpad.png b/indra/newview/skins/default/textures/bottomtray/Dpad.png Binary files differnew file mode 100644 index 0000000000..00fcb4beea --- /dev/null +++ b/indra/newview/skins/default/textures/bottomtray/Dpad.png diff --git a/indra/newview/skins/default/xui/da/notifications.xml b/indra/newview/skins/default/xui/da/notifications.xml index 4a4b7269dc..283a7b2a43 100644 --- a/indra/newview/skins/default/xui/da/notifications.xml +++ b/indra/newview/skins/default/xui/da/notifications.xml @@ -1574,6 +1574,10 @@ Klik på Acceptér for at deltage eller Afvis for at afvise invitationen. Klik p Den aktive stemme "morph" er udløbet og din normale stemme opsætning er genaktiveret. [[URL] Click here] for at forny dit abbonnement. </notification> + <notification name="VoiceEffectsWillExpire"> + En eller flere af dine stemme "morphs" vil udløbe om mindre end [INTERVAL] dage. +[[URL] Click here] for at forny dit abbonnement. + </notification> <notification name="VoiceEffectsNew"> Nye stemme "morphs" er tilgængelige! </notification> diff --git a/indra/newview/skins/default/xui/de/notifications.xml b/indra/newview/skins/default/xui/de/notifications.xml index 76bebedeec..6ad71e0ad1 100644 --- a/indra/newview/skins/default/xui/de/notifications.xml +++ b/indra/newview/skins/default/xui/de/notifications.xml @@ -2466,6 +2466,10 @@ Wenn Sie Premium-Mitglied sind, [[PREMIUM_URL] klicken Sie hier], um Ihren Voice [[URL] Klicken Sie hier], um Ihr Abo zu erneuern. Wenn Sie Premium-Mitglied sind, [[PREMIUM_URL] klicken Sie hier], um Ihren Voice-Morphing-Vorteil zu nutzen.</notification> + <notification name="VoiceEffectsWillExpire">Ein oder mehrere Ihrer Voice-Morph-Abos laufen in weniger als [INTERVAL] Tagen ab. +[[URL] Klicken Sie hier], um Ihr Abo zu erneuern. + +Wenn Sie Premium-Mitglied sind, [[PREMIUM_URL] klicken Sie hier], um Ihren Voice-Morphing-Vorteil zu nutzen.</notification> <notification name="VoiceEffectsNew">Neue Voice-Morph-Effekte sind erhältlich!</notification> <notification name="Cannot enter parcel: not a group member">Nur Mitglieder einer bestimmten Gruppe dürfen diesen Bereich betreten.</notification> <notification name="Cannot enter parcel: banned">Zugang zur Parzelle verweigert. Sie wurden verbannt.</notification> diff --git a/indra/newview/skins/default/xui/en/control_table_contents_game_control.xml b/indra/newview/skins/default/xui/en/control_table_contents_game_control.xml new file mode 100644 index 0000000000..a3a2d66e5e --- /dev/null +++ b/indra/newview/skins/default/xui/en/control_table_contents_game_control.xml @@ -0,0 +1,326 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<contents> + <rows + enabled="false" + name="game_control_buttons" + value=""> + <columns + type="icontext" + column="lst_action" + font="SansSerif" + halign="left" + label="Game Control Buttons" + name="lst_action" + value="Dpad" /> + </rows> + <rows + name="game_control_button_0" + value="game_control_button_0"> + <columns + column="lst_action" + font="SansSerif" + halign="left" + name="lst_action" + value="BUTTON_0" /> + </rows> + <rows + name="game_control_button_1" + value="game_control_button_1"> + <columns + column="lst_action" + font="SansSerif" + halign="left" + name="lst_action" + value="BUTTON_1" /> + </rows> + <rows + name="game_control_button_2" + value="game_control_button_2"> + <columns + column="lst_action" + font="SansSerif" + halign="left" + name="lst_action" + value="BUTTON_2" /> + </rows> + <rows + name="game_control_button_3" + value="game_control_button_3"> + <columns + column="lst_action" + font="SansSerif" + halign="left" + name="lst_action" + value="BUTTON_3" /> + </rows> + <rows + name="game_control_button_4" + value="game_control_button_4"> + <columns + column="lst_action" + font="SansSerif" + halign="left" + name="lst_action" + value="BUTTON_4" /> + </rows> + <rows + name="game_control_button_5" + value="game_control_button_5"> + <columns + column="lst_action" + font="SansSerif" + halign="left" + name="lst_action" + value="BUTTON_5" /> + </rows> + <rows + name="game_control_button_6" + value="game_control_button_6"> + <columns + column="lst_action" + font="SansSerif" + halign="left" + name="lst_action" + value="BUTTON_6" /> + </rows> + <rows + name="game_control_button_7" + value="game_control_button_7"> + <columns + column="lst_action" + font="SansSerif" + halign="left" + name="lst_action" + value="BUTTON_7" /> + </rows> + <rows + name="game_control_button_8" + value="game_control_button_8"> + <columns + column="lst_action" + font="SansSerif" + halign="left" + name="lst_action" + value="BUTTON_8" /> + </rows> + <rows + name="game_control_button_9" + value="game_control_button_9"> + <columns + column="lst_action" + font="SansSerif" + halign="left" + name="lst_action" + value="BUTTON_9" /> + </rows> + <rows + name="game_control_button_10" + value="game_control_button_10"> + <columns + column="lst_action" + font="SansSerif" + halign="left" + name="lst_action" + value="BUTTON_10" /> + </rows> + <rows + name="game_control_button_11" + value="game_control_button_11"> + <columns + column="lst_action" + font="SansSerif" + halign="left" + name="lst_action" + value="BUTTON_11" /> + </rows> + <rows + name="game_control_button_12" + value="game_control_button_12"> + <columns + column="lst_action" + font="SansSerif" + halign="left" + name="lst_action" + value="BUTTON_12" /> + </rows> + <rows + name="game_control_button_13" + value="game_control_button_13"> + <columns + column="lst_action" + font="SansSerif" + halign="left" + name="lst_action" + value="BUTTON_13" /> + </rows> + <rows + name="game_control_button_14" + value="game_control_button_14"> + <columns + column="lst_action" + font="SansSerif" + halign="left" + name="lst_action" + value="BUTTON_14" /> + </rows> + <rows + name="game_control_button_15" + value="game_control_button_15"> + <columns + column="lst_action" + font="SansSerif" + halign="left" + name="lst_action" + value="BUTTON_15" /> + </rows> + <rows + name="game_control_button_16" + value="game_control_button_16"> + <columns + column="lst_action" + font="SansSerif" + halign="left" + name="lst_action" + value="BUTTON_16" /> + </rows> + <rows + name="game_control_button_17" + value="game_control_button_17"> + <columns + column="lst_action" + font="SansSerif" + halign="left" + name="lst_action" + value="BUTTON_17" /> + </rows> + <rows + name="game_control_button_18" + value="game_control_button_18"> + <columns + column="lst_action" + font="SansSerif" + halign="left" + name="lst_action" + value="BUTTON_18" /> + </rows> + <rows + name="game_control_button_19" + value="game_control_button_19"> + <columns + column="lst_action" + font="SansSerif" + halign="left" + name="lst_action" + value="BUTTON_19" /> + </rows> + <rows + name="game_control_button_21" + value="game_control_button_21"> + <columns + column="lst_action" + font="SansSerif" + halign="left" + name="lst_action" + value="BUTTON_21" /> + </rows> + <rows + name="game_control_button_22" + value="game_control_button_22"> + <columns + column="lst_action" + font="SansSerif" + halign="left" + name="lst_action" + value="BUTTON_22" /> + </rows> + <rows + name="game_control_button_23" + value="game_control_button_23"> + <columns + column="lst_action" + font="SansSerif" + halign="left" + name="lst_action" + value="BUTTON_23" /> + </rows> + <rows + name="game_control_button_24" + value="game_control_button_24"> + <columns + column="lst_action" + font="SansSerif" + halign="left" + name="lst_action" + value="BUTTON_24" /> + </rows> + <rows + name="game_control_button_25" + value="game_control_button_25"> + <columns + column="lst_action" + font="SansSerif" + halign="left" + name="lst_action" + value="BUTTON_25" /> + </rows> + <rows + name="game_control_button_26" + value="game_control_button_26"> + <columns + column="lst_action" + font="SansSerif" + halign="left" + name="lst_action" + value="BUTTON_26" /> + </rows> + <rows + name="game_control_button_27" + value="game_control_button_27"> + <columns + column="lst_action" + font="SansSerif" + halign="left" + name="lst_action" + value="BUTTON_27" /> + </rows> + <rows + name="game_control_button_28" + value="game_control_button_28"> + <columns + column="lst_action" + font="SansSerif" + halign="left" + name="lst_action" + value="BUTTON_28" /> + </rows> + <rows + name="game_control_button_29" + value="game_control_button_29"> + <columns + column="lst_action" + font="SansSerif" + halign="left" + name="lst_action" + value="BUTTON_29" /> + </rows> + <rows + name="game_control_button_30" + value="game_control_button_30"> + <columns + column="lst_action" + font="SansSerif" + halign="left" + name="lst_action" + value="BUTTON_30" /> + </rows> + <rows + name="game_control_button_31" + value="game_control_button_31"> + <columns + column="lst_action" + font="SansSerif" + halign="left" + name="lst_action" + value="BUTTON_31" /> + </rows> +</contents> diff --git a/indra/newview/skins/default/xui/en/floater_joystick.xml b/indra/newview/skins/default/xui/en/floater_joystick.xml index e6f0420698..597744238c 100644 --- a/indra/newview/skins/default/xui/en/floater_joystick.xml +++ b/indra/newview/skins/default/xui/en/floater_joystick.xml @@ -3,9 +3,9 @@ legacy_header_height="18" height="500" layout="topleft" - name="Joystick" + name="3Dconnexion Device" help_topic="Viewerhelp:Joystick_Configuration" - title="JOYSTICK CONFIGURATION" + title="3DCONNEXION DEVICE CONFIGURATION" width="569"> <floater.string name="JoystickDisabled"> @@ -22,7 +22,7 @@ width="50" mouse_opaque="false" name="joystick_lbl"> - Joystick: + Device: </text> <combo_box allow_text_entry="false" @@ -35,7 +35,7 @@ <spinner bottom="56" height="10" - control_name="JoystickAxis1" + control_name="Axis1" decimal_digits="0" increment="1" label="X Axis Mapping" @@ -44,12 +44,12 @@ left="20" max_val="5" min_val="-1" - name="JoystickAxis1" + name="Axis1" width="140" /> <spinner bottom_delta="0" height="10" - control_name="JoystickAxis2" + control_name="Axis2" decimal_digits="0" increment="1" label="Y Axis Mapping" @@ -58,12 +58,12 @@ left="190" max_val="5" min_val="-1" - name="JoystickAxis2" + name="Axis2" width="140" /> <spinner bottom_delta="0" height="10" - control_name="JoystickAxis0" + control_name="Axis0" decimal_digits="0" increment="1" label="Z Axis Mapping" @@ -72,12 +72,12 @@ left="360" max_val="5" min_val="-1" - name="JoystickAxis0" + name="Axis0" width="140" /> <spinner bottom="76" height="10" - control_name="JoystickAxis4" + control_name="Axis4" decimal_digits="0" increment="1" label="Pitch Mapping" @@ -86,12 +86,12 @@ left="20" max_val="5" min_val="-1" - name="JoystickAxis4" + name="Axis4" width="140" /> <spinner bottom_delta="0" height="10" - control_name="JoystickAxis5" + control_name="Axis5" decimal_digits="0" increment="1" label="Yaw Mapping" @@ -100,12 +100,12 @@ left="190" max_val="5" min_val="-1" - name="JoystickAxis5" + name="Axis5" width="140" /> <spinner bottom_delta="0" height="10" - control_name="JoystickAxis3" + control_name="Axis3" decimal_digits="0" increment="1" label="Roll Mapping" @@ -114,12 +114,12 @@ left="360" max_val="5" min_val="-1" - name="JoystickAxis3" + name="Axis3" width="140" /> <spinner bottom="96" height="10" - control_name="JoystickAxis6" + control_name="Axis6" decimal_digits="0" increment="1" label="Zoom Mapping" @@ -128,7 +128,7 @@ left="20" max_val="5" min_val="-1" - name="JoystickAxis6" + name="Axis6" width="140" /> <check_box bottom_delta="18" @@ -203,7 +203,7 @@ width="60" /> <stat_view height="270" - label="Joystick Monitor" + label="Axis Monitor" layout="topleft" left="359" name="axis_view" diff --git a/indra/newview/skins/default/xui/en/floater_preferences.xml b/indra/newview/skins/default/xui/en/floater_preferences.xml index 4b0e0bb221..e7fa839001 100644 --- a/indra/newview/skins/default/xui/en/floater_preferences.xml +++ b/indra/newview/skins/default/xui/en/floater_preferences.xml @@ -87,49 +87,49 @@ top="40" width="658"> <panel - class="panel_preference" + class="panel_preference" filename="panel_preferences_general.xml" label="General" layout="topleft" help_topic="preferences_general_tab" name="general" /> <panel - class="panel_preference_graphics" + class="panel_preference_graphics" filename="panel_preferences_graphics1.xml" label="Graphics" layout="topleft" help_topic="preferences_display_tab" name="display" /> <panel - class="panel_preference" + class="panel_preference" filename="panel_preferences_sound.xml" label="Sound & Media" layout="topleft" help_topic="preferences_audio_tab" name="audio" /> <panel - class="panel_preference" + class="panel_preference" filename="panel_preferences_chat.xml" label="Chat" layout="topleft" help_topic="preferences_chat_tab" name="chat" /> <panel - class="panel_preference" + class="panel_preference" filename="panel_preferences_move.xml" label="Move & View" layout="topleft" help_topic="preferences_move_tab" name="move" /> <panel - class="panel_preference" + class="panel_preference" filename="panel_preferences_alerts.xml" label="Notifications" layout="topleft" help_topic="preferences_msgs_tab" name="msgs" /> <panel - class="panel_preference" + class="panel_preference" filename="panel_preferences_colors.xml" label="Colors" layout="topleft" @@ -143,14 +143,14 @@ help_topic="preferences_im_tab" name="im" /> <panel - class="panel_preference" + class="panel_preference" filename="panel_preferences_setup.xml" label="Setup" layout="topleft" help_topic="preferences_input_tab" name="input" /> <panel - class="panel_preference" + class="panel_preference" filename="panel_preferences_advanced.xml" label="Advanced" layout="topleft" @@ -170,6 +170,13 @@ layout="topleft" help_topic="preferences_controls_tab" name="controls" /> + <panel + class="panel_preference_game_control" + filename="panel_preferences_game_control.xml" + label="Game Control" + layout="topleft" + help_topic="preferences_game_control_tab" + name="game_control" /> </tab_container> </floater> diff --git a/indra/newview/skins/default/xui/en/game_control_table_camera_rows.xml b/indra/newview/skins/default/xui/en/game_control_table_camera_rows.xml new file mode 100644 index 0000000000..6074b72dc8 --- /dev/null +++ b/indra/newview/skins/default/xui/en/game_control_table_camera_rows.xml @@ -0,0 +1,106 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<contents> + <rows + enabled="false" + name="camera_actions" + value=""> + <columns + type="icontext" + column="action" + font="SansSerif" + halign="left" + label="Camera" + name="action" + value="Cam_FreeCam_Off" /> + </rows> + <rows + name="advance" + value="advance"> + <columns + column="action" + font="SansSerif" + halign="left" + name="action" + tool_tip="Camera move forward/backward" + value="Advance Forward" /> + </rows> + <rows + name="pan" + value="pan"> + <columns + column="action" + font="SansSerif" + halign="left" + name="action" + tool_tip="Camera pan left/right" + value="Pan Left" /> + </rows> + <rows + name="rise" + value="rise"> + <columns + column="action" + font="SansSerif" + halign="left" + name="action" + tool_tip="Camera rise/fall" + value="Rise Up" /> + </rows> + <rows + name="pitch" + value="pitch"> + <columns + column="action" + font="SansSerif" + halign="left" + name="action" + tool_tip="Camera adjust pitch" + value="Pitch Down" /> + </rows> + <rows + name="yaw" + value="yaw"> + <columns + column="action" + font="SansSerif" + halign="left" + name="action" + tool_tip="Camera turn left/right" + value="Yaw CCW" /> + </rows> + <rows + name="zoom" + value="zoom"> + <columns + column="action" + font="SansSerif" + halign="left" + name="action" + tool_tip="Camera zoom in/out" + value="Zoom In" /> + </rows> + <!-- + <rows + name="roll_ccw" + value="roll_ccw"> + <columns + column="action" + font="SansSerif" + halign="left" + name="action" + tool_tip="Camera roll counterclockwise" + value="Roll Counterclockwise" /> + </rows> + <rows + name="roll_cw" + value="roll_cw"> + <columns + column="action" + font="SansSerif" + halign="left" + name="action" + tool_tip="Camera roll clockwise" + value="Roll Clockwise" /> + </rows> + --> +</contents> diff --git a/indra/newview/skins/default/xui/en/game_control_table_rows.xml b/indra/newview/skins/default/xui/en/game_control_table_rows.xml new file mode 100644 index 0000000000..181bc8592c --- /dev/null +++ b/indra/newview/skins/default/xui/en/game_control_table_rows.xml @@ -0,0 +1,106 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<contents> + <rows + enabled="false" + name="move_actions" + value=""> + <columns + type="icontext" + column="action" + font="SansSerif" + halign="left" + label="Move Actions" + name="action" + value="Move_Walk_Off" /> + </rows> + <rows + name="push" + value="push"> + <columns + column="action" + font="SansSerif" + halign="left" + name="action" + value="Walk Forward" /> + </rows> + <rows + name="slide" + value="slide"> + <columns + column="action" + font="SansSerif" + halign="left" + name="action" + value="Strafe Left" /> + </rows> + <rows + name="jump" + value="jump"> + <columns + column="action" + font="SansSerif" + halign="left" + name="action" + value="Jump Up" /> + </rows> + <rows + name="turn" + value="turn"> + <columns + column="action" + font="SansSerif" + halign="left" + name="action" + value="Turn Left" /> + </rows> + <rows + name="look" + value="look"> + <columns + column="action" + font="SansSerif" + halign="left" + name="action" + value="Look Down" /> + </rows> + <rows + name="stop" + value="stop"> + <columns + column="action" + font="SansSerif" + halign="left" + name="action" + value="Stop" /> + </rows> + <rows + name="toggle_run" + value="toggle_run"> + <columns + column="action" + font="SansSerif" + halign="left" + name="action" + value="Run" /> + </rows> + <rows + name="toggle_fly" + value="toggle_fly"> + <columns + column="action" + font="SansSerif" + halign="left" + name="action" + value="Fly" /> + </rows> + <rows + name="toggle_flycam" + value="toggle_flycam"> + <columns + column="action" + font="SansSerif" + halign="left" + name="action" + value="Flycam" /> + </rows> +</contents> diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index a0d3a5e960..da9cc0c98d 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -19,7 +19,7 @@ label="Inventory..." name="Inventory" shortcut="control|I" - visible="true"> + visible="true"> <menu_item_check.on_check function="Floater.Visible" parameter="inventory" /> @@ -734,8 +734,7 @@ function="Floater.Show" parameter="snapshot" /> </menu_item_call> - -<menu_item_call + <menu_item_call label="360 snapshot" name="Capture 360" shortcut="control|alt|shift|s"> @@ -2344,7 +2343,7 @@ function="World.EnvPreset" function="Advanced.ToggleFeature" parameter="flexible" /> </menu_item_check> - </menu> + </menu> <menu_item_check label="Use Plugin Read Thread" name="Use Plugin Read Thread"> @@ -2492,6 +2491,22 @@ function="World.EnvPreset" visible="false"> <menu create_jump_keys="true" + label="Experimental Features" + name="Experimental Features" + tear_off="true"> + <menu_item_check + label="GameControl" + name="ToggleGameControl"> + <menu_item_check.on_check + function="Advanced.CheckExperiment" + parameter="GameControl" /> + <menu_item_check.on_click + function="Advanced.ToggleExperiment" + parameter="GameControl" /> + </menu_item_check> + </menu> + <menu + create_jump_keys="true" label="Consoles" name="Consoles" tear_off="true"> @@ -3467,6 +3482,16 @@ function="World.EnvPreset" function="Advanced.HandleAttachedLightParticles" parameter="RenderAttachedParticles" /> </menu_item_check> + <menu_item_check + label="Collect Font Vertex Buffers" + name="Collect Font Vertex Buffers"> + <menu_item_check.on_check + function="CheckControl" + parameter="CollectFontVertexBuffers" /> + <menu_item_check.on_click + function="ToggleControl" + parameter="CollectFontVertexBuffers" /> + </menu_item_check> <menu_item_separator /> <menu_item_check label="Enable Shader Cache" diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 848d9aca7c..071f6458c5 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -7556,7 +7556,7 @@ Message from [NAME]: type="notify"> <unique/> This land has damage enabled. -You can be hurt here. If you die, you will be teleported to your home location. +You can be hurt here. If you die, you might be teleported to your home location or to the spawn point. </notification> <notification @@ -8860,6 +8860,25 @@ If you are a Premium Member, [[PREMIUM_URL] click here] to receive your voice mo <notification icon="notify.tga" + name="VoiceEffectsWillExpire" + sound="UISndAlert" + persist="true" + type="notify"> + <unique/> +One or more of your Voice Morphs will expire in less than [INTERVAL] days. +[[URL] Click here] to renew your subscription. + +If you are a Premium Member, [[PREMIUM_URL] click here] to receive your voice morphing perk. + <tag>fail</tag> + <tag>voice</tag> + <usetemplate + ignoretext="Warn me about voice morph expiring" + name="okignore" + yestext="OK"/> + </notification> + + <notification + icon="notify.tga" name="VoiceEffectsNew" sound="UISndAlert" persist="true" diff --git a/indra/newview/skins/default/xui/en/panel_preferences_controls.xml b/indra/newview/skins/default/xui/en/panel_preferences_controls.xml index f8801f9c89..b02270dd9e 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_controls.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_controls.xml @@ -6,7 +6,7 @@ label="Controls" layout="topleft" left="102" - name="controls" + name="controls_panel" top="1" width="517"> <combo_box diff --git a/indra/newview/skins/default/xui/en/panel_preferences_game_control.xml b/indra/newview/skins/default/xui/en/panel_preferences_game_control.xml new file mode 100644 index 0000000000..bd92fe895d --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_preferences_game_control.xml @@ -0,0 +1,442 @@ +<?xml version="1.0" encoding="utf-8"?> +<panel + border="true" + follows="all" + height="408" + label="Game Controls" + layout="topleft" + left="102" + name="game_control_panel" + top="1" + width="517"> + <check_box + name="game_control_to_server" + control_name="GameControlToServer" + label="Send GameControl Data to server" + layout="topleft" + height="15" + left="10" + top="10"/> + <check_box + name="game_control_to_agent" + control_name="GameControlToAgent" + label="GameControl moves avatar and flycam" + layout="topleft" + height="15" + left="10" + top="30"/> + <check_box + name="agent_to_game_control" + control_name="AgentToGameControl" + label="Avatar actions interpreted as GameControl" + layout="topleft" + height="15" + left="10" + top="50"/> + <tab_container + name="game_control_tabs" + layout="topleft" + follows="all" + top="70" + left="2" + right="-2" + bottom="-32"> + <panel + name="tab_channel_mappings" + label="Channel mappings"> + <scroll_list + name="action_table" + layout="topleft" + follows="all" + top="1" + left="6" + right="-5" + bottom="-4" + can_sort="false" + column_padding="0" + multi_select="false" + selection_type="header" + fg_disable_color="ScrollUnselectedColor"> + <scroll_list.columns + name="action" + label="Action" + relative_width="0.25" /> + <scroll_list.columns + label="Channel" + relative_width="0.75" /> + </scroll_list> + </panel> + <panel + name="tab_device_settings" + label="Device settings"> + <text + type="string" + name="nodevice_message" + layout="topleft" + follows="all" + halign="center" + valign="center" + top="1" + left="1" + right="-1" + bottom="-1">No device</text> + <panel + layout="topleft" + follows="top|left|right" + top="1" + left="1" + right="-1" + height="60"> + <text + type="string" + name="device_prompt" + layout="topleft" + follows="top|left" + valign="center" + top="10" + left="2" + height="21" + width="200">Device to customize:</text> + <text + type="string" + name="single_device" + layout="topleft" + follows="top|left" + valign="center" + top="30" + left="2" + height="21" + width="500"/> + <combo_box + name="device_list" + layout="topleft" + follows="top|left" + top="30" + left="2" + width="500"/> + </panel> + <!-- This checkbox should be placed inside the above panel --> + <check_box + name="show_all_known_devices" + label="Show all known devices" + layout="topleft" + follows="top|left" + top_delta="10" + left="310"/> + <panel + name="device_settings" + layout="topleft" + follows="all" + top="61" + left="1" + right="-1" + bottom="-1"> + <tab_container + name="device_settings_tabs" + layout="topleft" + follows="all" + top="1" + left="1" + right="-1" + bottom="-1"> + <panel + name="tab_axis_options" + label="Axis Options"> + <scroll_list + name="axis_options" + follows="all" + top="41" + left="1" + right="-1" + bottom="-1" + can_sort="false" + column_padding="0" + draw_heading="true" + multi_select="false" + selection_type="header" + fg_disable_color="ScrollUnselectedColor"> + <scroll_list.columns + label="Axis" + relative_width="0.5"/> + <scroll_list.columns + label="Invert" + relative_width="0.1"/> + <scroll_list.columns + label="Dead Zone" + relative_width="0.2"/> + <scroll_list.columns + label="Offset" + relative_width="0.2"/> + </scroll_list> + </panel> + <panel + name="tab_axis_mappings" + label="Axis Mappings"> + <scroll_list + name="axis_mappings" + follows="all" + top="1" + left="1" + right="-1" + bottom="-1" + can_sort="false" + column_padding="0" + multi_select="false" + selection_type="header" + fg_disable_color="ScrollUnselectedColor"> + <scroll_list.columns relative_width="0.5"/> + <scroll_list.columns relative_width="0.5"/> + </scroll_list> + </panel> + <panel + name="tab_button_mappings" + label="Button Mappings"> + <scroll_list + name="button_mappings" + follows="all" + top="1" + left="1" + right="-1" + bottom="-1" + can_sort="false" + column_padding="0" + multi_select="false" + selection_type="header" + fg_disable_color="ScrollUnselectedColor"> + <scroll_list.columns relative_width="0.5"/> + <scroll_list.columns relative_width="0.5"/> + </scroll_list> + </panel> + </tab_container> + </panel> + </panel> + </tab_container> + <panel + layout="topleft" + follows="top|left" + top="405" + height="41" + left="1" + right="-1"> + <button + layout="topleft" + follows="top|left" + name="reset_to_defaults" + label="Reset to Defaults" + top="1" + left="8" + width="200"/> + </panel> + <spinner + name="numeric_value_editor" + decimal_digits="0" + increment="1" + width="100" + height="18"/> + <combo_box + name="axis_selector" + width="250" + height="18"> + <combo_box.item label="AXIS_0 (Left stick: tilt left/right)"/> + <combo_box.item label="AXIS_1 (Left stick: tilt forward/back)"/> + <combo_box.item label="AXIS_2 (Right stick: tilt left/right)"/> + <combo_box.item label="AXIS_3 (Right stick: tilt forward/back)"/> + <combo_box.item label="AXIS_4 (Left trigger: push/release)"/> + <combo_box.item label="AXIS_5 (Right trigger: push/release)"/> + <combo_box.item label="NONE (No mapping)"/> + </combo_box> + <combo_box + name="analog_channel_selector" + width="380" + height="18"> + <combo_box.item + label="AXIS_0- (Left stick: tilt right)" + name="AXIS_0-" + value="AXIS_0-"/> + <combo_box.item + label="AXIS_0+ (Left stick: tilt left)" + name="AXIS_0+" + value="AXIS_0+"/> + <combo_box.item + label="AXIS_1- (Left stick: tilt back)" + name="AXIS_1-" + value="AXIS_1-"/> + <combo_box.item + label="AXIS_1+ (Left stick: tilt forward)" + name="AXIS_1+" + value="AXIS_1+"/> + <combo_box.item + label="AXIS_2- (Right stick: tilt right)" + name="AXIS_2-" + value="AXIS_2-"/> + <combo_box.item + label="AXIS_2+ (Right stick: tilt left)" + name="AXIS_2+" + value="AXIS_2+"/> + <combo_box.item + label="AXIS_3- (Right stick: tilt back)" + name="AXIS_3-" + value="AXIS_3-"/> + <combo_box.item + label="AXIS_3+ (Right stick: tilt forward)" + name="AXIS_3+" + value="AXIS_3+"/> + <combo_box.item + label="AXIS_4- (Left trigger: release)" + name="AXIS_4-" + value="AXIS_4-"/> + <combo_box.item + label="AXIS_4+ (Left trigger: push)" + name="AXIS_4+" + value="AXIS_4+"/> + <combo_box.item + label="AXIS_5- (Right trigger: release)" + name="AXIS_5-" + value="AXIS_5-"/> + <combo_box.item + label="AXIS_5+ (Right trigger: push)" + name="AXIS_5+" + value="AXIS_5+"/> + <combo_box.item + label="NONE (No mapping)" + name="NONE" + value="NONE"/> + </combo_box> + <combo_box + name="binary_channel_selector" + width="380" + height="18"> + <combo_box.item + label="BUTTON_0 ('A' button)" + name="BUTTON_0" + value="BUTTON_0"/> + <combo_box.item + label="BUTTON_1 ('B' button)" + name="BUTTON_1" + value="BUTTON_1"/> + <combo_box.item + label="BUTTON_2 ('X' button)" + name="BUTTON_2" + value="BUTTON_2"/> + <combo_box.item + label="BUTTON_3 ('Y' button)" + name="BUTTON_3" + value="BUTTON_3"/> + <combo_box.item + label="BUTTON_4 (Back button)" + name="BUTTON_4" + value="BUTTON_4"/> + <combo_box.item + label="BUTTON_5 (Guide button)" + name="BUTTON_5" + value="BUTTON_5"/> + <combo_box.item + label="BUTTON_6 (Home button)" + name="BUTTON_6" + value="BUTTON_6"/> + <combo_box.item + label="BUTTON_7 (Left stick)" + name="BUTTON_7" + value="BUTTON_7"/> + <combo_box.item + label="BUTTON_8 (Right stick)" + name="BUTTON_8" + value="BUTTON_8"/> + <combo_box.item + label="BUTTON_9 (Left shoulder)" + name="BUTTON_9" + value="BUTTON_9"/> + <combo_box.item + label="BUTTON_10 (Right shoulder)" + name="BUTTON_10" + value="BUTTON_10"/> + <combo_box.item + label="BUTTON_11 (DPad up)" + name="BUTTON_11" + value="BUTTON_11"/> + <combo_box.item + label="BUTTON_12 (DPad down)" + name="BUTTON_12" + value="BUTTON_12"/> + <combo_box.item + label="BUTTON_13 (DPad left)" + name="BUTTON_13" + value="BUTTON_13"/> + <combo_box.item + label="BUTTON_14 (DPad right)" + name="BUTTON_14" + value="BUTTON_14"/> + <combo_box.item + label="BUTTON_15 (Miscellaneous 1)" + name="BUTTON_15" + value="BUTTON_15"/> + <combo_box.item + label="BUTTON_16 (Paddle 1)" + name="BUTTON_16" + value="BUTTON_16"/> + <combo_box.item + label="BUTTON_17 (Paddle 2)" + name="BUTTON_17" + value="BUTTON_17"/> + <combo_box.item + label="BUTTON_18 (Paddle 3)" + name="BUTTON_18" + value="BUTTON_18"/> + <combo_box.item + label="BUTTON_19 (Paddle 4)" + name="BUTTON_19" + value="BUTTON_19"/> + <combo_box.item + label="BUTTON_20 (Touchpad)" + name="BUTTON_20" + value="BUTTON_20"/> + <combo_box.item + label="BUTTON_21" + name="BUTTON_21" + value="BUTTON_21"/> + <combo_box.item + label="BUTTON_22" + name="BUTTON_22" + value="BUTTON_22"/> + <combo_box.item + label="BUTTON_23" + name="BUTTON_23" + value="BUTTON_23"/> + <combo_box.item + label="BUTTON_24" + name="BUTTON_24" + value="BUTTON_24"/> + <combo_box.item + label="BUTTON_25" + name="BUTTON_25" + value="BUTTON_25"/> + <combo_box.item + label="BUTTON_26" + name="BUTTON_26" + value="BUTTON_26"/> + <combo_box.item + label="BUTTON_27" + name="BUTTON_27" + value="BUTTON_27"/> + <combo_box.item + label="BUTTON_28" + name="BUTTON_28" + value="BUTTON_28"/> + <combo_box.item + label="BUTTON_29" + name="BUTTON_29" + value="BUTTON_29"/> + <combo_box.item + label="BUTTON_30" + name="BUTTON_30" + value="BUTTON_30"/> + <combo_box.item + label="BUTTON_31" + name="BUTTON_31" + value="BUTTON_31"/> + <combo_box.item + label="NONE (No mapping)" + name="NONE" + value="NONE"/> + </combo_box> +</panel> diff --git a/indra/newview/skins/default/xui/en/panel_preferences_move.xml b/indra/newview/skins/default/xui/en/panel_preferences_move.xml index 0412466b4f..8a372256dc 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_move.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_move.xml @@ -270,7 +270,7 @@ width="200" /> <button height="23" - label="Other Devices" + label="3Dconnexion devices" left="30" name="joystick_setup_button" top="30" diff --git a/indra/newview/skins/default/xui/es/notifications.xml b/indra/newview/skins/default/xui/es/notifications.xml index bf55e2c443..739391b965 100644 --- a/indra/newview/skins/default/xui/es/notifications.xml +++ b/indra/newview/skins/default/xui/es/notifications.xml @@ -2452,6 +2452,10 @@ Si eres un miembro Premium [[PREMIUM_URL] pulsa aquí] para recibir tu beneficio [[URL] Pulsa aquí] para renovar la suscripción. Si eres un miembro Premium [[PREMIUM_URL] pulsa aquí] para recibir tu beneficio de transformación de voz.</notification> + <notification name="VoiceEffectsWillExpire">Una o más de tus transformaciones de voz caducarán en menos de [INTERVAL] días. +[[URL] Pulsa aquí] para renovar la suscripción + +Si eres un miembro Premium [[PREMIUM_URL] pulsa aquí] para recibir tu beneficio de transformación de voz.</notification> <notification name="VoiceEffectsNew">Están disponibles nuevas transformaciones de voz.</notification> <notification name="Cannot enter parcel: not a group member">Sólo los miembros de un grupo determinado pueden visitar esta zona.</notification> <notification name="Cannot enter parcel: banned">No puedes entrar en esta parcela, se te ha prohibido el acceso.</notification> diff --git a/indra/newview/skins/default/xui/fr/notifications.xml b/indra/newview/skins/default/xui/fr/notifications.xml index 17cf18633f..587c88faad 100644 --- a/indra/newview/skins/default/xui/fr/notifications.xml +++ b/indra/newview/skins/default/xui/fr/notifications.xml @@ -2451,6 +2451,10 @@ Si vous êtes un membre Premium, [[PREMIUM_URL] cliquez ici] pour recevoir votr [[URL] Cliquez ici] pour renouveler votre abonnement. Si vous êtes un membre Premium, [[PREMIUM_URL] cliquez ici] pour recevoir votre effet de voix.</notification> + <notification name="VoiceEffectsWillExpire">Au moins l'un de vos effets de voix expirera dans moins de [INTERVAL] jours. +[[URL] Cliquez ici] pour renouveler votre abonnement. + +Si vous êtes un membre Premium, [[PREMIUM_URL] cliquez ici] pour recevoir votre effet de voix.</notification> <notification name="VoiceEffectsNew">De nouveaux effets de voix sont disponibles !</notification> <notification name="Cannot enter parcel: not a group member">Seuls les membres d'un certain groupe peuvent visiter cette zone.</notification> <notification name="Cannot enter parcel: banned">Vous ne pouvez pas pénétrer sur ce terrain car l'accès vous y est interdit.</notification> diff --git a/indra/newview/skins/default/xui/it/notifications.xml b/indra/newview/skins/default/xui/it/notifications.xml index 1c40e7304a..f79cc1515b 100644 --- a/indra/newview/skins/default/xui/it/notifications.xml +++ b/indra/newview/skins/default/xui/it/notifications.xml @@ -2454,6 +2454,10 @@ Se sei un membro Premium, [[PREMIUM_URL] fai clic qui] per ricevere in regalo la [[URL] Fai clic qui] per rinnovare l'abbonamento. Se sei un membro Premium, [[PREMIUM_URL] fai clic qui] per ricevere in regalo la manipolazione vocale.</notification> + <notification name="VoiceEffectsWillExpire">Almeno una delle tue manipolazioni vocali scadrà tra meno di [INTERVAL] giorni. +[[URL] Fai clic qui] per rinnovare l'abbonamento. + +Se sei un membro Premium, [[PREMIUM_URL] fai clic qui] per ricevere in regalo la manipolazione vocale.</notification> <notification name="VoiceEffectsNew">Sono disponibili nuove manipolazioni vocali.</notification> <notification name="Cannot enter parcel: not a group member">Soltanto i membri di un determinato gruppo possono visitare questa zona.</notification> <notification name="Cannot enter parcel: banned">Non puoi entrare nel terreno, sei stato bloccato.</notification> diff --git a/indra/newview/skins/default/xui/ja/notifications.xml b/indra/newview/skins/default/xui/ja/notifications.xml index fbd56e118c..123e95df04 100644 --- a/indra/newview/skins/default/xui/ja/notifications.xml +++ b/indra/newview/skins/default/xui/ja/notifications.xml @@ -4663,6 +4663,17 @@ Webページにリンクすると、他人がこの場所に簡単にアクセ voice </tag> </notification> + <notification name="VoiceEffectsWillExpire">ボイスモーフィング効果の1つ、または複数の有効期限が[INTERVAL]日以内に終了します。 +期限を延長・更新するには[[URL] ここ]をクリックしてください。 + +プレミアム会員の方は、[[PREMIUM_URL] ここ]をクリックしてボイスモーフィング特典をお受け取りください。 + <tag> + fail + </tag> + <tag> + voice + </tag> + </notification> <notification name="VoiceEffectsNew">新しいボイスモーフィング効果が登場! <tag> voice diff --git a/indra/newview/skins/default/xui/pl/notifications.xml b/indra/newview/skins/default/xui/pl/notifications.xml index 17c11bc75f..e668c6cc20 100644 --- a/indra/newview/skins/default/xui/pl/notifications.xml +++ b/indra/newview/skins/default/xui/pl/notifications.xml @@ -3118,6 +3118,11 @@ Jeśli jesteś użytkownikiem premium, to [[PREMIUM_URL] kliknij tutaj] aby otrz [[URL] Kliknij tutaj] aby odnowić subskrypcję. Jeśli jesteś użytkownikiem premium, to [[PREMIUM_URL] kliknij tutaj] aby otrzymać swój perk Przekształceń Głosu. </notification> + <notification name="VoiceEffectsWillExpire"> + Jedno lub więcej z Twoich Przekształceń Głosu wygaśnie za mniej niż [INTERVAL] dni. +[[URL] Kliknij tutaj] aby odnowić subskrypcję. +Jeśli jesteś użytkownikiem premium, to [[PREMIUM_URL] kliknij tutaj] aby otrzymać swój perk Przekształceń Głosu. + </notification> <notification name="VoiceEffectsNew"> Nowe Przekształcenia Głosu są dostępne! </notification> diff --git a/indra/newview/skins/default/xui/pt/notifications.xml b/indra/newview/skins/default/xui/pt/notifications.xml index 0390239669..a3220bca54 100644 --- a/indra/newview/skins/default/xui/pt/notifications.xml +++ b/indra/newview/skins/default/xui/pt/notifications.xml @@ -2441,6 +2441,10 @@ Se você é um Membro Premium, [[PREMIUM_URL] clique aqui] para receber o seu ap [[URL] Clique aqui] para renovar o serviço. Se você é um Membro Premium, [[PREMIUM_URL] clique aqui] para receber o seu app de distorção de voz.</notification> + <notification name="VoiceEffectsWillExpire">Uma ou mais das suas distorções de voz tem vencimento em menos de [INTERVAL] dias. +[[URL] Clique aqui] para renovar o serviço. + +Se você é um Membro Premium, [[PREMIUM_URL] clique aqui] para receber o seu app de distorção de voz.</notification> <notification name="VoiceEffectsNew">Novas Distorções de voz!</notification> <notification name="Cannot enter parcel: not a group member">Só membros de um grupo podem acessar esta área.</notification> <notification name="Cannot enter parcel: banned">Você não pode entrar nessa terra, você foi banido.</notification> diff --git a/indra/newview/skins/default/xui/ru/notifications.xml b/indra/newview/skins/default/xui/ru/notifications.xml index bde18edc23..e75fd1fd82 100644 --- a/indra/newview/skins/default/xui/ru/notifications.xml +++ b/indra/newview/skins/default/xui/ru/notifications.xml @@ -3232,6 +3232,12 @@ Если вы - владелец премиум-аккаунта, [[PREMIUM_URL] щелкните здесь], чтобы получить право на анимационное изменение голоса. </notification> + <notification name="VoiceEffectsWillExpire"> + Срок действия одного или нескольких ваших типов анимационного изменения голоса истекает через [INTERVAL] дней или раньше. +[[URL] Щелкните здесь], чтобы обновить подписку. + +Если вы - владелец премиум-аккаунта, [[PREMIUM_URL] щелкните здесь], чтобы получить право на анимационное изменение голоса. + </notification> <notification name="VoiceEffectsNew"> Появились новые типы изменения голоса! </notification> diff --git a/indra/newview/skins/default/xui/tr/notifications.xml b/indra/newview/skins/default/xui/tr/notifications.xml index 30aa0c0342..17d2969d19 100644 --- a/indra/newview/skins/default/xui/tr/notifications.xml +++ b/indra/newview/skins/default/xui/tr/notifications.xml @@ -3232,6 +3232,12 @@ Aboneliğinizi yenilemek için [[URL] buraya tıklayın]. Özel Üye iseniz, ses dönüştürme özelliğini almak için [[PREMIUM_URL] buraya tıklayın]. </notification> + <notification name="VoiceEffectsWillExpire"> + Ses Dönüşümlerinizden birinin ya da daha fazlasının süresi [INTERVAL] günden daha az bir zamanda dolacak. +Aboneliğinizi yenilemek için [[URL] buraya tıklayın]. + +Özel Üye iseniz, ses dönüştürme özelliğini almak için [[PREMIUM_URL] buraya tıklayın]. + </notification> <notification name="VoiceEffectsNew"> Yeni Ses Şekilleri kullanılabilir! </notification> diff --git a/indra/newview/skins/default/xui/zh/notifications.xml b/indra/newview/skins/default/xui/zh/notifications.xml index 3ebea7dc27..4d0f1cb85b 100644 --- a/indra/newview/skins/default/xui/zh/notifications.xml +++ b/indra/newview/skins/default/xui/zh/notifications.xml @@ -3216,6 +3216,12 @@ SHA1 指紋:[MD5_DIGEST] 付費用戶請[[PREMIUM_URL] 點按這裡]領取免費變聲工具。 </notification> + <notification name="VoiceEffectsWillExpire"> + 至少一個你訂用的變聲效果將在 [INTERVAL] 天後到期。 +[[URL] 點按這裡]繼續訂用。 + +付費用戶請[[PREMIUM_URL] 點按這裡]領取免費變聲工具。 + </notification> <notification name="VoiceEffectsNew"> 新的變聲效果上市了! </notification> diff --git a/indra/newview/tests/llgamecontrol_stub.cpp b/indra/newview/tests/llgamecontrol_stub.cpp new file mode 100644 index 0000000000..b06a7fd132 --- /dev/null +++ b/indra/newview/tests/llgamecontrol_stub.cpp @@ -0,0 +1,99 @@ +/** + * @file llgamecontrol_stub.h + * @brief Stubbery for LLGameControl + * + * $LicenseInfo:firstyear=2023&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2023, 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$ + */ + +#pragma once + +#include "llgamecontrol.h" + +#include "SDL2/SDL_events.h" + +LLGameControl::State g_state; + +// static +bool LLGameControl::isInitialized() +{ + return false; +} + +// static +void LLGameControl::init() +{ +} + +// static +void LLGameControl::terminate() +{ +} + +// static +bool LLGameControl::computeFinalStateAndCheckForChanges() +{ + return false; +} + +// static +void LLGameControl::clearAllState() +{ +} + +// static +void LLGameControl::processEvents(bool app_has_focus) +{ +} + +// static +const LLGameControl::State& LLGameControl::getState() +{ + return g_state; +} + +// static +void LLGameControl::setIncludeKeyboard(bool include) +{ +} + +// static +bool LLGameControl::getIncludeKeyboard() +{ + return false; +} + +// static +LLGameControl::InputChannel LLGameControl::getChannelByActionName(const std::string& name) +{ + return LLGameControl::InputChannel(); +} + +// static +void LLGameControl::addActionMapping(const std::string& name, LLGameControl::InputChannel channel) +{ +} + +// static +void LLGameControl::setActionFlags(U32 action_flags) +{ +} + diff --git a/indra/newview/tests/llversioninfo_test.cpp b/indra/newview/tests/llversioninfo_test.cpp index 8049e67fc5..b07800cdcd 100644 --- a/indra/newview/tests/llversioninfo_test.cpp +++ b/indra/newview/tests/llversioninfo_test.cpp @@ -29,7 +29,10 @@ #include "../llversioninfo.h" - #include <iostream> +#include <iostream> + +//#include "llgamecontrol_stub.cpp" + // LL_VIEWER_CHANNEL is a macro defined on the compiler command line. The // macro expands to the string name of the channel, but without quotes. We diff --git a/indra/newview/tests/llviewerhelputil_test.cpp b/indra/newview/tests/llviewerhelputil_test.cpp index 9ee6625bf1..9a7a5be09f 100644 --- a/indra/newview/tests/llviewerhelputil_test.cpp +++ b/indra/newview/tests/llviewerhelputil_test.cpp @@ -79,6 +79,8 @@ bool LLAgent::isGodlike() const { return false; } LLAgent gAgent; +LLFlycam::LLFlycam() { } + std::string LLWeb::expandURLSubstitutions(const std::string &url, const LLSD &default_subs) { diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index daa7e58211..efc90b8991 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -72,6 +72,7 @@ class ViewerManifest(LLManifest): self.exclude("logcontrol.xml") self.exclude("logcontrol-dev.xml") self.path("*.ini") + self.path("*.txt") self.path("*.xml") # include the entire shaders directory recursively @@ -584,6 +585,9 @@ class Windows_x86_64_Manifest(ViewerManifest): self.path("vivoxsdk_x64.dll") self.path("ortp_x64.dll") + # SDL2 + self.path("SDL2.dll") + # BugSplat if self.args.get('bugsplat'): self.path("BsSndRpt64.exe") @@ -928,6 +932,7 @@ class Darwin_x86_64_Manifest(ViewerManifest): with self.prefix(src=relpkgdir, dst=""): self.path("libndofdev.dylib") + self.path("libSDL2-*.dylib") with self.prefix(src_dst="cursors_mac"): self.path("*.tif") @@ -1406,7 +1411,7 @@ class Linux_x86_64_Manifest(LinuxManifest): pkgdir = self.args['package_dir'] relpkgdir = os.path.join(pkgdir, "lib", "release") - debpkgdir = os.path.join(pkgdir, "lib", "debug") + #debpkgdir = os.path.join(pkgdir, "lib", "debug") with self.prefix(src=relpkgdir, dst="lib"): self.path("libapr-1.so*") |