diff --git a/cmake/compiler.cmake b/cmake/compiler.cmake index bc35d2f2f8..3615b80cda 100644 --- a/cmake/compiler.cmake +++ b/cmake/compiler.cmake @@ -89,7 +89,7 @@ if (APPLE) string(REGEX MATCH "^[0-9]+\\.[0-9]+" OSX_VERSION ${OSX_VERSION}) message(STATUS "Detected OS X version = ${OSX_VERSION}") - set(OSX_SDK "${OSX_VERSION}" CACHE String "OS X SDK version to look for inside Xcode bundle or at OSX_SDK_PATH") + set(OSX_SDK "${OSX_VERSION}" CACHE STRING "OS X SDK version to look for inside Xcode bundle or at OSX_SDK_PATH") # set our OS X deployment target set(CMAKE_OSX_DEPLOYMENT_TARGET 10.9) diff --git a/cmake/externals/LibOVR/CMakeLists.txt b/cmake/externals/LibOVR/CMakeLists.txt index 481753f7e0..53c4c2976c 100644 --- a/cmake/externals/LibOVR/CMakeLists.txt +++ b/cmake/externals/LibOVR/CMakeLists.txt @@ -27,12 +27,12 @@ if (WIN32) ExternalProject_Get_Property(${EXTERNAL_NAME} SOURCE_DIR) ExternalProject_Get_Property(${EXTERNAL_NAME} INSTALL_DIR) set(LIBOVR_DIR ${INSTALL_DIR}) - set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${LIBOVR_DIR}/Include CACHE TYPE INTERNAL) - set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG ${LIBOVR_DIR}/Lib/LibOVRd.lib CACHE TYPE INTERNAL) - set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${LIBOVR_DIR}/Lib/LibOVR.lib CACHE TYPE INTERNAL) + set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${LIBOVR_DIR}/Include CACHE STRING INTERNAL) + set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG ${LIBOVR_DIR}/Lib/LibOVRd.lib CACHE STRING INTERNAL) + set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${LIBOVR_DIR}/Lib/LibOVR.lib CACHE STRING INTERNAL) include(SelectLibraryConfigurations) select_library_configurations(LIBOVR) - set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${${EXTERNAL_NAME_UPPER}_LIBRARIES} CACHE TYPE INTERNAL) + set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${${EXTERNAL_NAME_UPPER}_LIBRARIES} CACHE STRING INTERNAL) elseif(APPLE) @@ -50,11 +50,11 @@ elseif(APPLE) # In theory we should use the Headers path inside the framework, as seen here # but unfortunately Oculus doesn't seem to have figured out automated testing # so they released a framework with missing headers. - #set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${SOURCE_DIR}/LibOVR/Lib/Mac/Release/LibOVR.framework/Headers/ CACHE TYPE INTERNAL) + #set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${SOURCE_DIR}/LibOVR/Lib/Mac/Release/LibOVR.framework/Headers/ CACHE STRING INTERNAL) # Work around the broken framework by using a different path for the headers. - set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${SOURCE_DIR}/LibOVR/Include CACHE TYPE INTERNAL) - set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${SOURCE_DIR}/LibOVR/Lib/Mac/Release/LibOVR.framework/LibOVR CACHE TYPE INTERNAL) + set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${SOURCE_DIR}/LibOVR/Include CACHE STRING INTERNAL) + set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${SOURCE_DIR}/LibOVR/Lib/Mac/Release/LibOVR.framework/LibOVR CACHE STRING INTERNAL) @@ -74,8 +74,8 @@ elseif(NOT ANDROID) ExternalProject_Get_Property(${EXTERNAL_NAME} SOURCE_DIR) ExternalProject_Get_Property(${EXTERNAL_NAME} INSTALL_DIR) - set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${INSTALL_DIR}/lib/libovr.a CACHE TYPE INTERNAL) - set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG "" CACHE TYPE INTERNAL) + set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${INSTALL_DIR}/lib/libovr.a CACHE STRING INTERNAL) + set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG "" CACHE STRING INTERNAL) find_package(Threads REQUIRED) find_package(X11 REQUIRED) @@ -89,8 +89,8 @@ elseif(NOT ANDROID) select_library_configurations(${EXTERNAL_NAME_UPPER}) - set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${SOURCE_DIR}/LibOVR/Include ${SOURCE_DIR}/LibOVR/Src CACHE TYPE INTERNAL) - set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${${EXTERNAL_NAME_UPPER}_LIBRARY} ${${EXTERNAL_NAME_UPPER}_LIBRARY_EXTRAS} CACHE TYPE INTERNAL) + set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${SOURCE_DIR}/LibOVR/Include ${SOURCE_DIR}/LibOVR/Src CACHE STRING INTERNAL) + set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${${EXTERNAL_NAME_UPPER}_LIBRARY} ${${EXTERNAL_NAME_UPPER}_LIBRARY_EXTRAS} CACHE STRING INTERNAL) endif() # Hide this external target (for ide users) diff --git a/cmake/externals/LibOVRPlatform/CMakeLists.txt b/cmake/externals/LibOVRPlatform/CMakeLists.txt index 895efa9357..adf89823f2 100644 --- a/cmake/externals/LibOVRPlatform/CMakeLists.txt +++ b/cmake/externals/LibOVRPlatform/CMakeLists.txt @@ -20,12 +20,12 @@ if (WIN32) ExternalProject_Get_Property(${EXTERNAL_NAME} SOURCE_DIR) if ("${CMAKE_SIZEOF_VOID_P}" EQUAL "8") - set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${SOURCE_DIR}/Windows/LibOVRPlatform64_1.lib CACHE TYPE INTERNAL) + set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${SOURCE_DIR}/Windows/LibOVRPlatform64_1.lib CACHE STRING INTERNAL) else() - set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${SOURCE_DIR}/Windows/LibOVRPlatform32_1.lib CACHE TYPE INTERNAL) + set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${SOURCE_DIR}/Windows/LibOVRPlatform32_1.lib CACHE STRING INTERNAL) endif() - set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${SOURCE_DIR}/Include CACHE TYPE INTERNAL) + set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${SOURCE_DIR}/Include CACHE STRING INTERNAL) endif () # Hide this external target (for ide users) diff --git a/cmake/externals/hifiAudioCodec/CMakeLists.txt b/cmake/externals/hifiAudioCodec/CMakeLists.txt index 8a8e2573d5..5d439cd519 100644 --- a/cmake/externals/hifiAudioCodec/CMakeLists.txt +++ b/cmake/externals/hifiAudioCodec/CMakeLists.txt @@ -36,10 +36,10 @@ set_target_properties(${EXTERNAL_NAME} PROPERTIES FOLDER "hidden/externals") ExternalProject_Get_Property(${EXTERNAL_NAME} SOURCE_DIR) -set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${SOURCE_DIR}/include CACHE TYPE INTERNAL) +set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${SOURCE_DIR}/include CACHE STRING INTERNAL) if (WIN32) - set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${SOURCE_DIR}/Release/audio.lib CACHE TYPE INTERNAL) + set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${SOURCE_DIR}/Release/audio.lib CACHE STRING INTERNAL) else() - set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${SOURCE_DIR}/Release/libaudio.a CACHE TYPE INTERNAL) + set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${SOURCE_DIR}/Release/libaudio.a CACHE STRING INTERNAL) endif() diff --git a/cmake/externals/neuron/CMakeLists.txt b/cmake/externals/neuron/CMakeLists.txt index 5ac38bc442..049e175354 100644 --- a/cmake/externals/neuron/CMakeLists.txt +++ b/cmake/externals/neuron/CMakeLists.txt @@ -21,9 +21,9 @@ set_target_properties(${EXTERNAL_NAME} PROPERTIES FOLDER "hidden/externals") # set include dir if(WIN32) - set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS "${SOURCE_DIR}/NeuronDataReader_Windows/include" CACHE TYPE INTERNAL) + set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS "${SOURCE_DIR}/NeuronDataReader_Windows/include" CACHE STRING INTERNAL) elseif(APPLE) - set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS "${SOURCE_DIR}/NeuronDataReader_Mac/include" CACHE TYPE INTERNAL) + set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS "${SOURCE_DIR}/NeuronDataReader_Mac/include" CACHE STRING INTERNAL) else() # Unsupported endif() @@ -37,16 +37,16 @@ if(WIN32) endif() set(${EXTERNAL_NAME_UPPER}_LIB_PATH "${SOURCE_DIR}/NeuronDataReader_Windows/lib/${ARCH_DIR}") - set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE "${${EXTERNAL_NAME_UPPER}_LIB_PATH}/NeuronDataReader.lib" CACHE TYPE INTERNAL) - set(${EXTERNAL_NAME_UPPER}_LIBRARIES "${${EXTERNAL_NAME_UPPER}_LIB_PATH}/NeuronDataReader.lib" CACHE TYPE INTERNAL) + set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE "${${EXTERNAL_NAME_UPPER}_LIB_PATH}/NeuronDataReader.lib" CACHE STRING INTERNAL) + set(${EXTERNAL_NAME_UPPER}_LIBRARIES "${${EXTERNAL_NAME_UPPER}_LIB_PATH}/NeuronDataReader.lib" CACHE STRING INTERNAL) add_paths_to_fixup_libs("${${EXTERNAL_NAME_UPPER}_LIB_PATH}") elseif(APPLE) set(${EXTERNAL_NAME_UPPER}_LIB_PATH "${SOURCE_DIR}/NeuronDataReader_Mac/dylib") - set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE "${${EXTERNAL_NAME_UPPER}_LIB_PATH}/NeuronDataReader.dylib" CACHE TYPE INTERNAL) - set(${EXTERNAL_NAME_UPPER}_LIBRARIES "${${EXTERNAL_NAME_UPPER}_LIB_PATH}/NeuronDataReader.dylib" CACHE TYPE INTERNAL) + set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE "${${EXTERNAL_NAME_UPPER}_LIB_PATH}/NeuronDataReader.dylib" CACHE STRING INTERNAL) + set(${EXTERNAL_NAME_UPPER}_LIBRARIES "${${EXTERNAL_NAME_UPPER}_LIB_PATH}/NeuronDataReader.dylib" CACHE STRING INTERNAL) add_paths_to_fixup_libs("${${EXTERNAL_NAME_UPPER}_LIB_PATH}") diff --git a/cmake/externals/sixense/CMakeLists.txt b/cmake/externals/sixense/CMakeLists.txt index 17d2f98e2d..35f7758820 100644 --- a/cmake/externals/sixense/CMakeLists.txt +++ b/cmake/externals/sixense/CMakeLists.txt @@ -30,7 +30,7 @@ set_target_properties(${EXTERNAL_NAME} PROPERTIES FOLDER "hidden/externals") ExternalProject_Get_Property(${EXTERNAL_NAME} SOURCE_DIR) -set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${SOURCE_DIR}/include CACHE TYPE INTERNAL) +set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${SOURCE_DIR}/include CACHE STRING INTERNAL) if (WIN32) @@ -52,7 +52,7 @@ if (WIN32) set(${EXTERNAL_NAME_UPPER}_LIB_PATH "${SOURCE_DIR}/lib/${ARCH_DIR}/release_dll") endif() - set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE "${${EXTERNAL_NAME_UPPER}_LIB_PATH}/sixense${ARCH_SUFFIX}.lib" CACHE TYPE INTERNAL) + set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE "${${EXTERNAL_NAME_UPPER}_LIB_PATH}/sixense${ARCH_SUFFIX}.lib" CACHE STRING INTERNAL) add_paths_to_fixup_libs("${${EXTERNAL_NAME_UPPER}_DLL_PATH}") elseif(APPLE) @@ -62,7 +62,7 @@ elseif(APPLE) elseif(NOT ANDROID) # FIXME need to account for different architectures - set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${SOURCE_DIR}/lib/linux_x64/release/libsixense_x64.so CACHE TYPE INTERNAL) + set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${SOURCE_DIR}/lib/linux_x64/release/libsixense_x64.so CACHE STRING INTERNAL) endif() diff --git a/cmake/externals/steamworks/CMakeLists.txt b/cmake/externals/steamworks/CMakeLists.txt index 30b3926436..eb61d22f8b 100644 --- a/cmake/externals/steamworks/CMakeLists.txt +++ b/cmake/externals/steamworks/CMakeLists.txt @@ -21,7 +21,7 @@ set_target_properties(${EXTERNAL_NAME} PROPERTIES FOLDER "hidden/externals") ExternalProject_Get_Property(${EXTERNAL_NAME} SOURCE_DIR) -set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${SOURCE_DIR}/public CACHE TYPE INTERNAL) +set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${SOURCE_DIR}/public CACHE STRING INTERNAL) if (WIN32) @@ -36,12 +36,12 @@ if (WIN32) set(${EXTERNAL_NAME_UPPER}_DLL_PATH ${ARCH_DIR}) set(${EXTERNAL_NAME_UPPER}_LIB_PATH ${ARCH_DIR}) - set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE "${${EXTERNAL_NAME_UPPER}_LIB_PATH}/steam_api${ARCH_SUFFIX}.lib" CACHE TYPE INTERNAL) + set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE "${${EXTERNAL_NAME_UPPER}_LIB_PATH}/steam_api${ARCH_SUFFIX}.lib" CACHE STRING INTERNAL) add_paths_to_fixup_libs("${${EXTERNAL_NAME_UPPER}_DLL_PATH}") elseif(APPLE) - set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${SOURCE_DIR}/redistributable_bin/osx32/libsteam_api.dylib CACHE TYPE INTERNAL) + set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${SOURCE_DIR}/redistributable_bin/osx32/libsteam_api.dylib CACHE STRING INTERNAL) set(_STEAMWORKS_LIB_DIR "${SOURCE_DIR}/redistributable_bin/osx32") ExternalProject_Add_Step( @@ -57,6 +57,6 @@ elseif(APPLE) elseif(NOT ANDROID) # FIXME need to account for different architectures - set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${SOURCE_DIR}/redistributable_bin/linux64/libsteam_api.so CACHE TYPE INTERNAL) + set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${SOURCE_DIR}/redistributable_bin/linux64/libsteam_api.so CACHE STRING INTERNAL) endif() diff --git a/cmake/externals/tbb/CMakeLists.txt b/cmake/externals/tbb/CMakeLists.txt index 436cae79a1..1788922ef2 100644 --- a/cmake/externals/tbb/CMakeLists.txt +++ b/cmake/externals/tbb/CMakeLists.txt @@ -102,6 +102,6 @@ if (DEFINED _TBB_LIB_DIR) endif () if (DEFINED ${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE) - set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${SOURCE_DIR}/include CACHE TYPE "List of tbb include directories") + set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${SOURCE_DIR}/include CACHE STRING "List of tbb include directories") endif () diff --git a/cmake/macros/TargetBreakpad.cmake b/cmake/macros/TargetBreakpad.cmake index dac581d6c7..58626ad17b 100644 --- a/cmake/macros/TargetBreakpad.cmake +++ b/cmake/macros/TargetBreakpad.cmake @@ -8,7 +8,7 @@ macro(TARGET_BREAKPAD) if (ANDROID) set(INSTALL_DIR ${HIFI_ANDROID_PRECOMPILED}/breakpad) - set(BREAKPAD_INCLUDE_DIRS "${INSTALL_DIR}/include" CACHE TYPE INTERNAL) + set(BREAKPAD_INCLUDE_DIRS "${INSTALL_DIR}/include" CACHE STRING INTERNAL) set(LIB_DIR ${INSTALL_DIR}/lib) list(APPEND BREAKPAD_LIBRARIES ${LIB_DIR}/libbreakpad_client.a) target_include_directories(${TARGET_NAME} SYSTEM PRIVATE ${BREAKPAD_INCLUDE_DIRS}) diff --git a/cmake/macros/TargetBullet.cmake b/cmake/macros/TargetBullet.cmake index 1f4050dd42..843b03ac13 100644 --- a/cmake/macros/TargetBullet.cmake +++ b/cmake/macros/TargetBullet.cmake @@ -8,7 +8,7 @@ macro(TARGET_BULLET) if (ANDROID) set(INSTALL_DIR ${HIFI_ANDROID_PRECOMPILED}/bullet) - set(BULLET_INCLUDE_DIRS "${INSTALL_DIR}/include/bullet" CACHE TYPE INTERNAL) + set(BULLET_INCLUDE_DIRS "${INSTALL_DIR}/include/bullet" CACHE STRING INTERNAL) set(LIB_DIR ${INSTALL_DIR}/lib) list(APPEND BULLET_LIBRARIES ${LIB_DIR}/libBulletDynamics.a) diff --git a/cmake/macros/TargetDraco.cmake b/cmake/macros/TargetDraco.cmake index 9dbfa865b8..520786d4c3 100755 --- a/cmake/macros/TargetDraco.cmake +++ b/cmake/macros/TargetDraco.cmake @@ -3,7 +3,7 @@ macro(TARGET_DRACO) find_library(LIBPATH ${LIB} PATHS ) if (ANDROID) set(INSTALL_DIR ${HIFI_ANDROID_PRECOMPILED}/draco) - set(DRACO_INCLUDE_DIRS "${INSTALL_DIR}/include" CACHE TYPE INTERNAL) + set(DRACO_INCLUDE_DIRS "${INSTALL_DIR}/include" CACHE STRING INTERNAL) set(LIB_DIR ${INSTALL_DIR}/lib) list(APPEND DRACO_LIBRARIES ${LIB_DIR}/libdraco.a) list(APPEND DRACO_LIBRARIES ${LIB_DIR}/libdracodec.a) @@ -21,4 +21,4 @@ macro(TARGET_DRACO) select_library_configurations(DRACO) target_link_libraries(${TARGET_NAME} ${DRACO_LIBRARY}) endif() -endmacro() \ No newline at end of file +endmacro() diff --git a/cmake/macros/TargetHifiAudioCodec.cmake b/cmake/macros/TargetHifiAudioCodec.cmake index 98c24e684c..4eaccc4f25 100644 --- a/cmake/macros/TargetHifiAudioCodec.cmake +++ b/cmake/macros/TargetHifiAudioCodec.cmake @@ -9,9 +9,9 @@ macro(TARGET_HIFIAUDIOCODEC) if (ANDROID) set(HIFIAC_INSTALL_DIR ${HIFI_ANDROID_PRECOMPILED}/hifiAC/codecSDK) set(HIFIAC_LIB_DIR "${HIFIAC_INSTALL_DIR}/Release") - set(HIFIAC_INCLUDE_DIRS "${HIFIAC_INSTALL_DIR}/include" CACHE TYPE INTERNAL) + set(HIFIAC_INCLUDE_DIRS "${HIFIAC_INSTALL_DIR}/include" CACHE STRING INTERNAL) list(APPEND HIFIAC_LIBS "${HIFIAC_LIB_DIR}/libaudio.a") - set(HIFIAC_LIBRARIES ${HIFIAC_LIBS} CACHE TYPE INTERNAL) + set(HIFIAC_LIBRARIES ${HIFIAC_LIBS} CACHE STRING INTERNAL) else() add_dependency_external_projects(hifiAudioCodec) target_include_directories(${TARGET_NAME} PRIVATE ${HIFIAUDIOCODEC_INCLUDE_DIRS}) diff --git a/cmake/macros/TargetNvtt.cmake b/cmake/macros/TargetNvtt.cmake index 8227355cb9..c2f243563f 100644 --- a/cmake/macros/TargetNvtt.cmake +++ b/cmake/macros/TargetNvtt.cmake @@ -9,12 +9,12 @@ macro(TARGET_NVTT) if (ANDROID) set(NVTT_INSTALL_DIR ${HIFI_ANDROID_PRECOMPILED}/nvtt) set(NVTT_LIB_DIR "${NVTT_INSTALL_DIR}/lib") - set(NVTT_INCLUDE_DIRS "${NVTT_INSTALL_DIR}/include" CACHE TYPE INTERNAL) + set(NVTT_INCLUDE_DIRS "${NVTT_INSTALL_DIR}/include" CACHE STRING INTERNAL) list(APPEND NVTT_LIBS "${NVTT_LIB_DIR}/libnvcore.so") list(APPEND NVTT_LIBS "${NVTT_LIB_DIR}/libnvmath.so") list(APPEND NVTT_LIBS "${NVTT_LIB_DIR}/libnvimage.so") list(APPEND NVTT_LIBS "${NVTT_LIB_DIR}/libnvtt.so") - set(NVTT_LIBRARIES ${NVTT_LIBS} CACHE TYPE INTERNAL) + set(NVTT_LIBRARIES ${NVTT_LIBS} CACHE STRING INTERNAL) target_include_directories(${TARGET_NAME} PRIVATE ${NVTT_INCLUDE_DIRS}) else() find_library(NVTT_LIBRARY_RELEASE nvtt PATHS ${VCPKG_INSTALL_ROOT}/lib NO_DEFAULT_PATH) diff --git a/cmake/macros/TargetOpenSSL.cmake b/cmake/macros/TargetOpenSSL.cmake index 3faaab5801..f74015201d 100644 --- a/cmake/macros/TargetOpenSSL.cmake +++ b/cmake/macros/TargetOpenSSL.cmake @@ -8,8 +8,8 @@ macro(TARGET_OPENSSL) if (ANDROID) set(OPENSSL_INSTALL_DIR ${HIFI_ANDROID_PRECOMPILED}/openssl) - set(OPENSSL_INCLUDE_DIR "${OPENSSL_INSTALL_DIR}/include" CACHE TYPE INTERNAL) - set(OPENSSL_LIBRARIES "${OPENSSL_INSTALL_DIR}/lib/libcrypto.a;${OPENSSL_INSTALL_DIR}/lib/libssl.a" CACHE TYPE INTERNAL) + set(OPENSSL_INCLUDE_DIR "${OPENSSL_INSTALL_DIR}/include" CACHE STRING INTERNAL) + set(OPENSSL_LIBRARIES "${OPENSSL_INSTALL_DIR}/lib/libcrypto.a;${OPENSSL_INSTALL_DIR}/lib/libssl.a" CACHE STRING INTERNAL) else() # using VCPKG for OpenSSL find_package(OpenSSL REQUIRED) diff --git a/cmake/macros/TargetPolyvox.cmake b/cmake/macros/TargetPolyvox.cmake index 9db6b522c7..b2c4e30dd2 100644 --- a/cmake/macros/TargetPolyvox.cmake +++ b/cmake/macros/TargetPolyvox.cmake @@ -8,7 +8,7 @@ macro(TARGET_POLYVOX) if (ANDROID) set(INSTALL_DIR ${HIFI_ANDROID_PRECOMPILED}/polyvox) - set(POLYVOX_INCLUDE_DIRS "${INSTALL_DIR}/include" CACHE TYPE INTERNAL) + set(POLYVOX_INCLUDE_DIRS "${INSTALL_DIR}/include" CACHE STRING INTERNAL) set(LIB_DIR ${INSTALL_DIR}/lib) list(APPEND POLYVOX_LIBRARIES ${LIB_DIR}/libPolyVoxUtil.so) list(APPEND POLYVOX_LIBRARIES ${LIB_DIR}/Release/libPolyVoxCore.so) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 8f864cb88a..4fce236e31 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -9,6 +9,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // + #include "Application.h" #include @@ -50,6 +51,7 @@ #include #include + #include #include #include @@ -193,6 +195,8 @@ #include "scripting/KeyboardScriptingInterface.h" #include "scripting/RefreshRateScriptingInterface.h" + + #if defined(Q_OS_MAC) || defined(Q_OS_WIN) #include "SpeechRecognizer.h" #endif @@ -241,7 +245,7 @@ #include "webbrowser/WebBrowserSuggestionsEngine.h" #include -#include + #include "AboutUtil.h" #include @@ -263,7 +267,7 @@ // On Windows PC, NVidia Optimus laptop, we want to enable NVIDIA GPU // FIXME seems to be broken. extern "C" { -_declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001; + _declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001; } #endif @@ -276,8 +280,6 @@ _declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001; Q_LOGGING_CATEGORY(trace_app_input_mouse, "trace.app.input.mouse") -#define PLATFORM 1 - using namespace std; static QTimer locationUpdateTimer; @@ -334,9 +336,9 @@ static const float INITIAL_QUERY_RADIUS = 10.0f; // priority radius for entitie static const QString DESKTOP_LOCATION = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation); -Setting::Handle maxOctreePacketsPerSecond{ "maxOctreePPS", DEFAULT_MAX_OCTREE_PPS }; +Setting::Handle maxOctreePacketsPerSecond{"maxOctreePPS", DEFAULT_MAX_OCTREE_PPS}; -Setting::Handle loginDialogPoppedUp{ "loginDialogPoppedUp", false }; +Setting::Handle loginDialogPoppedUp{"loginDialogPoppedUp", false}; static const QUrl AVATAR_INPUTS_BAR_QML = PathUtils::qmlUrl("AvatarInputsBar.qml"); static const QUrl MIC_BAR_APPLICATION_QML = PathUtils::qmlUrl("hifi/audio/MicBarApplication.qml"); @@ -347,7 +349,7 @@ static const QString NO_MOVEMENT_MAPPING_NAME = "Standard to Action (No Movement static const QString NO_MOVEMENT_MAPPING_JSON = PathUtils::resourcesPath() + "/controllers/standard_nomovement.json"; static const QString MARKETPLACE_CDN_HOSTNAME = "mpassets.highfidelity.com"; -static const int INTERVAL_TO_CHECK_HMD_WORN_STATUS = 500; // milliseconds +static const int INTERVAL_TO_CHECK_HMD_WORN_STATUS = 500; // milliseconds static const QString DESKTOP_DISPLAY_PLUGIN_NAME = "Desktop"; static const QString ACTIVE_DISPLAY_PLUGIN_SETTING_NAME = "activeDisplayPlugin"; static const QString SYSTEM_TABLET = "com.highfidelity.interface.tablet.system"; @@ -358,25 +360,26 @@ static const float FOCUS_HIGHLIGHT_EXPANSION_FACTOR = 1.05f; #if defined(Q_OS_ANDROID) static const QString TESTER_FILE = "/sdcard/_hifi_test_device.txt"; #endif -const std::vector> - Application::_acceptedExtensions{ { SVO_EXTENSION, &Application::importSVOFromURL }, - { SVO_JSON_EXTENSION, &Application::importSVOFromURL }, - { AVA_JSON_EXTENSION, &Application::askToWearAvatarAttachmentUrl }, - { JSON_EXTENSION, &Application::importJSONFromURL }, - { JS_EXTENSION, &Application::askToLoadScript }, - { FST_EXTENSION, &Application::askToSetAvatarUrl }, - { JSON_GZ_EXTENSION, &Application::askToReplaceDomainContent }, - { CONTENT_ZIP_EXTENSION, &Application::askToReplaceDomainContent }, - { ZIP_EXTENSION, &Application::importFromZIP }, - { JPG_EXTENSION, &Application::importImage }, - { PNG_EXTENSION, &Application::importImage } }; +const std::vector> Application::_acceptedExtensions { + { SVO_EXTENSION, &Application::importSVOFromURL }, + { SVO_JSON_EXTENSION, &Application::importSVOFromURL }, + { AVA_JSON_EXTENSION, &Application::askToWearAvatarAttachmentUrl }, + { JSON_EXTENSION, &Application::importJSONFromURL }, + { JS_EXTENSION, &Application::askToLoadScript }, + { FST_EXTENSION, &Application::askToSetAvatarUrl }, + { JSON_GZ_EXTENSION, &Application::askToReplaceDomainContent }, + { CONTENT_ZIP_EXTENSION, &Application::askToReplaceDomainContent }, + { ZIP_EXTENSION, &Application::importFromZIP }, + { JPG_EXTENSION, &Application::importImage }, + { PNG_EXTENSION, &Application::importImage } +}; class DeadlockWatchdogThread : public QThread { public: static const unsigned long HEARTBEAT_UPDATE_INTERVAL_SECS = 1; - static const unsigned long MAX_HEARTBEAT_AGE_USECS = 120 * USECS_PER_SECOND; // 2 mins with no checkin probably a deadlock - static const int WARNING_ELAPSED_HEARTBEAT = 500 * USECS_PER_MSEC; // warn if elapsed heartbeat average is large - static const int HEARTBEAT_SAMPLES = 100000; // ~5 seconds worth of samples + static const unsigned long MAX_HEARTBEAT_AGE_USECS = 120 * USECS_PER_SECOND; // 2 mins with no checkin probably a deadlock + static const int WARNING_ELAPSED_HEARTBEAT = 500 * USECS_PER_MSEC; // warn if elapsed heartbeat average is large + static const int HEARTBEAT_SAMPLES = 100000; // ~5 seconds worth of samples // Set the heartbeat on launch DeadlockWatchdogThread() { @@ -384,10 +387,14 @@ public: // Give the heartbeat an initial value _heartbeat = usecTimestampNow(); _paused = false; - connect(qApp, &QCoreApplication::aboutToQuit, [this] { _quit = true; }); + connect(qApp, &QCoreApplication::aboutToQuit, [this] { + _quit = true; + }); } - void setMainThreadID(Qt::HANDLE threadID) { _mainThreadID = threadID; } + void setMainThreadID(Qt::HANDLE threadID) { + _mainThreadID = threadID; + } static void updateHeartbeat() { auto now = usecTimestampNow(); @@ -408,7 +415,9 @@ public: lambda(); resume(); } - static void pause() { _paused = true; } + static void pause() { + _paused = true; + } static void resume() { // Update the heartbeat BEFORE resuming the checks @@ -423,49 +432,55 @@ public: if (_paused) { continue; } - uint64_t lastHeartbeat = - _heartbeat; // sample atomic _heartbeat, because we could context switch away and have it updated on us + uint64_t lastHeartbeat = _heartbeat; // sample atomic _heartbeat, because we could context switch away and have it updated on us uint64_t now = usecTimestampNow(); auto lastHeartbeatAge = (now > lastHeartbeat) ? now - lastHeartbeat : 0; auto elapsedMovingAverage = _movingAverage.getAverage(); if (elapsedMovingAverage > _maxElapsedAverage) { - qCDebug(interfaceapp_deadlock) - << "DEADLOCK WATCHDOG WARNING:" - << "lastHeartbeatAge:" << lastHeartbeatAge << "elapsedMovingAverage:" << elapsedMovingAverage - << "maxElapsed:" << _maxElapsed << "PREVIOUS maxElapsedAverage:" << _maxElapsedAverage + qCDebug(interfaceapp_deadlock) << "DEADLOCK WATCHDOG WARNING:" + << "lastHeartbeatAge:" << lastHeartbeatAge + << "elapsedMovingAverage:" << elapsedMovingAverage + << "maxElapsed:" << _maxElapsed + << "PREVIOUS maxElapsedAverage:" << _maxElapsedAverage << "NEW maxElapsedAverage:" << elapsedMovingAverage << "** NEW MAX ELAPSED AVERAGE **" << "samples:" << _movingAverage.getSamples(); _maxElapsedAverage = elapsedMovingAverage; } if (lastHeartbeatAge > _maxElapsed) { - qCDebug(interfaceapp_deadlock) - << "DEADLOCK WATCHDOG WARNING:" - << "lastHeartbeatAge:" << lastHeartbeatAge << "elapsedMovingAverage:" << elapsedMovingAverage - << "PREVIOUS maxElapsed:" << _maxElapsed << "NEW maxElapsed:" << lastHeartbeatAge << "** NEW MAX ELAPSED **" - << "maxElapsedAverage:" << _maxElapsedAverage << "samples:" << _movingAverage.getSamples(); + qCDebug(interfaceapp_deadlock) << "DEADLOCK WATCHDOG WARNING:" + << "lastHeartbeatAge:" << lastHeartbeatAge + << "elapsedMovingAverage:" << elapsedMovingAverage + << "PREVIOUS maxElapsed:" << _maxElapsed + << "NEW maxElapsed:" << lastHeartbeatAge << "** NEW MAX ELAPSED **" + << "maxElapsedAverage:" << _maxElapsedAverage + << "samples:" << _movingAverage.getSamples(); _maxElapsed = lastHeartbeatAge; } if (elapsedMovingAverage > WARNING_ELAPSED_HEARTBEAT) { qCDebug(interfaceapp_deadlock) << "DEADLOCK WATCHDOG WARNING:" - << "lastHeartbeatAge:" << lastHeartbeatAge - << "elapsedMovingAverage:" << elapsedMovingAverage << "** OVER EXPECTED VALUE **" - << "maxElapsed:" << _maxElapsed << "maxElapsedAverage:" << _maxElapsedAverage - << "samples:" << _movingAverage.getSamples(); + << "lastHeartbeatAge:" << lastHeartbeatAge + << "elapsedMovingAverage:" << elapsedMovingAverage << "** OVER EXPECTED VALUE **" + << "maxElapsed:" << _maxElapsed + << "maxElapsedAverage:" << _maxElapsedAverage + << "samples:" << _movingAverage.getSamples(); } if (lastHeartbeatAge > MAX_HEARTBEAT_AGE_USECS) { - qCDebug(interfaceapp_deadlock) - << "DEADLOCK DETECTED -- " - << "lastHeartbeatAge:" << lastHeartbeatAge << "[ lastHeartbeat :" << lastHeartbeat << "now:" << now << " ]" - << "elapsedMovingAverage:" << elapsedMovingAverage << "maxElapsed:" << _maxElapsed - << "maxElapsedAverage:" << _maxElapsedAverage << "samples:" << _movingAverage.getSamples(); + qCDebug(interfaceapp_deadlock) << "DEADLOCK DETECTED -- " + << "lastHeartbeatAge:" << lastHeartbeatAge + << "[ lastHeartbeat :" << lastHeartbeat + << "now:" << now << " ]" + << "elapsedMovingAverage:" << elapsedMovingAverage + << "maxElapsed:" << _maxElapsed + << "maxElapsedAverage:" << _maxElapsedAverage + << "samples:" << _movingAverage.getSamples(); -// Don't actually crash in debug builds, in case this apparent deadlock is simply from -// the developer actively debugging code -#ifdef NDEBUG + // Don't actually crash in debug builds, in case this apparent deadlock is simply from + // the developer actively debugging code + #ifdef NDEBUG deadlockDetectionCrash(); -#endif + #endif } } } @@ -476,7 +491,7 @@ public: static std::atomic _maxElapsedAverage; static ThreadSafeMovingAverage _movingAverage; - bool _quit{ false }; + bool _quit { false }; Qt::HANDLE _mainThreadID = nullptr; }; @@ -501,7 +516,8 @@ bool isDomainURL(QUrl url) { // url.scheme() != HIFI_URL_SCHEME_HTTPS return false; } - if (url.path().endsWith(".json", Qt::CaseInsensitive) || url.path().endsWith(".json.gz", Qt::CaseInsensitive)) { + if (url.path().endsWith(".json", Qt::CaseInsensitive) || + url.path().endsWith(".json.gz", Qt::CaseInsensitive)) { return true; } return false; @@ -515,7 +531,7 @@ public: return staticInstance; } - bool nativeEventFilter(const QByteArray& eventType, void* msg, long* result) Q_DECL_OVERRIDE { + bool nativeEventFilter(const QByteArray &eventType, void* msg, long* result) Q_DECL_OVERRIDE { if (eventType == "windows_generic_MSG") { MSG* message = (MSG*)msg; @@ -543,12 +559,12 @@ public: } if (message->message == WM_DEVICECHANGE) { - const float MIN_DELTA_SECONDS = 2.0f; // de-bounce signal + const float MIN_DELTA_SECONDS = 2.0f; // de-bounce signal static float lastTriggerTime = 0.0f; const float deltaSeconds = secTimestampNow() - lastTriggerTime; lastTriggerTime = secTimestampNow(); if (deltaSeconds > MIN_DELTA_SECONDS) { - Midi::USBchanged(); // re-scan the MIDI bus + Midi::USBchanged(); // re-scan the MIDI bus } } } @@ -559,35 +575,38 @@ public: class LambdaEvent : public QEvent { std::function _fun; - public: - LambdaEvent(const std::function& fun) : QEvent(static_cast(ApplicationEvent::Lambda)), _fun(fun) {} - LambdaEvent(std::function&& fun) : QEvent(static_cast(ApplicationEvent::Lambda)), _fun(fun) {} + LambdaEvent(const std::function & fun) : + QEvent(static_cast(ApplicationEvent::Lambda)), _fun(fun) { + } + LambdaEvent(std::function && fun) : + QEvent(static_cast(ApplicationEvent::Lambda)), _fun(fun) { + } void call() const { _fun(); } }; void messageHandler(QtMsgType type, const QMessageLogContext& context, const QString& message) { - QString logMessage = LogHandler::getInstance().printMessage((LogMsgType)type, context, message); + QString logMessage = LogHandler::getInstance().printMessage((LogMsgType) type, context, message); if (!logMessage.isEmpty()) { #ifdef Q_OS_ANDROID - const char* local = logMessage.toStdString().c_str(); + const char * local=logMessage.toStdString().c_str(); switch (type) { case QtDebugMsg: - __android_log_write(ANDROID_LOG_DEBUG, "Interface", local); + __android_log_write(ANDROID_LOG_DEBUG,"Interface",local); break; case QtInfoMsg: - __android_log_write(ANDROID_LOG_INFO, "Interface", local); + __android_log_write(ANDROID_LOG_INFO,"Interface",local); break; case QtWarningMsg: - __android_log_write(ANDROID_LOG_WARN, "Interface", local); + __android_log_write(ANDROID_LOG_WARN,"Interface",local); break; case QtCriticalMsg: - __android_log_write(ANDROID_LOG_ERROR, "Interface", local); + __android_log_write(ANDROID_LOG_ERROR,"Interface",local); break; case QtFatalMsg: default: - __android_log_write(ANDROID_LOG_FATAL, "Interface", local); + __android_log_write(ANDROID_LOG_FATAL,"Interface",local); abort(); } #else @@ -596,21 +615,21 @@ void messageHandler(QtMsgType type, const QMessageLogContext& context, const QSt } } -class ApplicationMeshProvider : public scriptable::ModelProviderFactory { + +class ApplicationMeshProvider : public scriptable::ModelProviderFactory { public: virtual scriptable::ModelProviderPointer lookupModelProvider(const QUuid& uuid) override { bool success; if (auto nestable = DependencyManager::get()->find(uuid, success).lock()) { auto type = nestable->getNestableType(); #ifdef SCRIPTABLE_MESH_DEBUG - qCDebug(interfaceapp) << "ApplicationMeshProvider::lookupModelProvider" << uuid - << SpatiallyNestable::nestableTypeToString(type); + qCDebug(interfaceapp) << "ApplicationMeshProvider::lookupModelProvider" << uuid << SpatiallyNestable::nestableTypeToString(type); #endif switch (type) { - case NestableType::Entity: - return getEntityModelProvider(static_cast(uuid)); - case NestableType::Avatar: - return getAvatarModelProvider(uuid); + case NestableType::Entity: + return getEntityModelProvider(static_cast(uuid)); + case NestableType::Avatar: + return getAvatarModelProvider(uuid); } } return nullptr; @@ -645,9 +664,10 @@ private: /**jsdoc *

The Controller.Hardware.Application object has properties representing Interface's state. The property - * values are integer IDs, uniquely identifying each output. Read-only. These can be mapped to actions or functions or - * Controller.Standard items in a {@link RouteObject} mapping (e.g., using the {@link RouteObject#when} method). - * Each data value is either 1.0 for "true" or 0.0 for "false".

+ * values are integer IDs, uniquely identifying each output. Read-only.

+ *

These states can be mapped to actions or functions or Controller.Standard items in a {@link RouteObject} + * mapping (e.g., using the {@link RouteObject#when} method). Each data value is either 1.0 for "true" or + * 0.0 for "false".

* * * @@ -661,13 +681,17 @@ private: * * * - * + * + * * * * * * + * + * + * * *
PropertyTypeDataDescription
CameraIndependentnumbernumberThe camera is in independent mode.
CameraEntitynumbernumberThe camera is in entity mode.
InHMDnumbernumberThe user is in HMD mode.
AdvancedMovementnumbernumberAdvanced movement controls are enabled. - *
AdvancedMovementnumbernumberAdvanced movement (walking) controls are + * enabled.
StrafeEnablednumbernumberStrafing is enabled
LeftHandDominantnumbernumberDominant hand set to left.
RightHandDominantnumbernumberDominant hand set to right.
SnapTurnnumbernumberSnap turn is enabled.
GroundednumbernumberThe user's avatar is on the ground.
NavigationFocusednumbernumberNot used.
PlatformWindowsnumbernumberThe operating system is Windows.
PlatformMacnumbernumberThe operating system is Mac.
PlatformAndroidnumbernumberThe operating system is Android.
* @typedef {object} Controller.Hardware-Application @@ -707,7 +731,7 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) { // HRS: I could not figure out how to move these any earlier in startup, so when using this option, be sure to also supply // --allowMultipleInstances - auto reportAndQuit = [&](const char* commandSwitch, std::function report) { + auto reportAndQuit = [&](const char* commandSwitch, std::function report) { const char* reportfile = getCmdOption(argc, constArgv, commandSwitch); // Reports to the specified file, because stdout is set up to be captured for logging. if (reportfile) { @@ -715,9 +739,9 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) { if (fp) { report(fp); fclose(fp); - if (!runningMarkerExisted) { // don't leave ours around + if (!runningMarkerExisted) { // don't leave ours around RunningMarker runingMarker(RUNNING_MARKER_FILENAME); - runingMarker.deleteRunningMarkerFile(); // happens in deleter, but making the side-effect explicit. + runingMarker.deleteRunningMarkerFile(); // happens in deleter, but making the side-effect explicit. } _exit(0); } @@ -727,7 +751,9 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) { auto version = protocolVersionsSignatureBase64(); fputs(version.toLatin1().data(), fp); }); - reportAndQuit("--version", [&](FILE* fp) { fputs(BuildInfo::VERSION.toLatin1().data(), fp); }); + reportAndQuit("--version", [&](FILE* fp) { + fputs(BuildInfo::VERSION.toLatin1().data(), fp); + }); const char* portStr = getCmdOption(argc, constArgv, "--listenPort"); const int listenPort = portStr ? atoi(portStr) : INVALID_PORT; @@ -746,7 +772,7 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) { qApp->setProperty(hifi::properties::STANDALONE, isStandalone); // Ignore any previous crashes if running from command line with a test script. - bool inTestMode{ false }; + bool inTestMode { false }; for (int i = 0; i < argc; ++i) { QString parameter(argv[i]); if (parameter == TEST_SCRIPT_COMMAND) { @@ -755,7 +781,7 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) { } } - bool previousSessionCrashed{ false }; + bool previousSessionCrashed { false }; if (!inTestMode) { previousSessionCrashed = CrashRecoveryHandler::checkForResetSettings(runningMarkerExisted, suppressPrompt); } @@ -801,7 +827,7 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) { audioDLLPath += "/audioWin7"; } QCoreApplication::addLibraryPath(audioDLLPath); -#endif +#endif DependencyManager::registerInheritance(); DependencyManager::registerInheritance(); @@ -819,7 +845,7 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) { DependencyManager::set(); DependencyManager::set(); #if defined(Q_OS_ANDROID) - DependencyManager::set(); // use the default user agent getter + DependencyManager::set(); // use the default user agent getter #else DependencyManager::set(std::bind(&Application::getUserAgent, qApp)); #endif @@ -833,8 +859,7 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) { DependencyManager::set(NodeType::Agent, listenPort); DependencyManager::set(); DependencyManager::set(); - DependencyManager::set< - ModelFormatRegistry>(); // ModelFormatRegistry must be defined before ModelCache. See the ModelCache constructor. + DependencyManager::set(); // ModelFormatRegistry must be defined before ModelCache. See the ModelCache constructor. DependencyManager::set(); DependencyManager::set(); DependencyManager::set(); @@ -886,11 +911,10 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) { DependencyManager::set(); DependencyManager::set(); DependencyManager::set(); - controller::StateController::setStateVariables( - { { STATE_IN_HMD, STATE_CAMERA_FULL_SCREEN_MIRROR, STATE_CAMERA_FIRST_PERSON, STATE_CAMERA_THIRD_PERSON, - STATE_CAMERA_ENTITY, STATE_CAMERA_INDEPENDENT, STATE_SNAP_TURN, STATE_ADVANCED_MOVEMENT_CONTROLS, STATE_GROUNDED, - STATE_NAV_FOCUSED, STATE_PLATFORM_WINDOWS, STATE_PLATFORM_MAC, STATE_PLATFORM_ANDROID, STATE_LEFT_HAND_DOMINANT, - STATE_RIGHT_HAND_DOMINANT, STATE_STRAFE_ENABLED } }); + controller::StateController::setStateVariables({ { STATE_IN_HMD, STATE_CAMERA_FULL_SCREEN_MIRROR, + STATE_CAMERA_FIRST_PERSON, STATE_CAMERA_THIRD_PERSON, STATE_CAMERA_ENTITY, STATE_CAMERA_INDEPENDENT, + STATE_SNAP_TURN, STATE_ADVANCED_MOVEMENT_CONTROLS, STATE_GROUNDED, STATE_NAV_FOCUSED, + STATE_PLATFORM_WINDOWS, STATE_PLATFORM_MAC, STATE_PLATFORM_ANDROID, STATE_LEFT_HAND_DOMINANT, STATE_RIGHT_HAND_DOMINANT, STATE_STRAFE_ENABLED } }); DependencyManager::set(); DependencyManager::set(); DependencyManager::set(); @@ -928,7 +952,7 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) { // continuing to overburden Application.cpp QUuid _keyboardFocusHighlightID; -OffscreenGLCanvas* _qmlShareContext{ nullptr }; +OffscreenGLCanvas* _qmlShareContext { nullptr }; // FIXME hack access to the internal share context for the Chromium helper // Normally we'd want to use QWebEngine::initialize(), but we can't because @@ -938,11 +962,11 @@ OffscreenGLCanvas* _qmlShareContext{ nullptr }; // So instead we create a new offscreen context to share with the QGLWidget, // and manually set THAT to be the shared context for the Chromium helper #if !defined(DISABLE_QML) -OffscreenGLCanvas* _chromiumShareContext{ nullptr }; +OffscreenGLCanvas* _chromiumShareContext { nullptr }; #endif -Q_GUI_EXPORT void qt_gl_set_global_share_context(QOpenGLContext* context); -Q_GUI_EXPORT QOpenGLContext* qt_gl_global_share_context(); +Q_GUI_EXPORT void qt_gl_set_global_share_context(QOpenGLContext *context); +Q_GUI_EXPORT QOpenGLContext *qt_gl_global_share_context(); Setting::Handle sessionRunTime{ "sessionRunTime", 0 }; @@ -963,35 +987,41 @@ QSharedPointer getOffscreenUI() { #endif } -void Application::InitializePlatform() { - platform::create(); - - if (platform::enumerateProcessors()) { - std::string test = platform::getProcessor(0); - } -} - Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bool runningMarkerExisted) : - QApplication(argc, argv), _window(new MainWindow(desktop())), _sessionRunTimer(startupTimer), + QApplication(argc, argv), + _window(new MainWindow(desktop())), + _sessionRunTimer(startupTimer), #ifndef Q_OS_ANDROID _logger(new FileLogger(this)), #endif _previousSessionCrashed(setupEssentials(argc, argv, runningMarkerExisted)), - _entitySimulation(new PhysicalEntitySimulation()), _physicsEngine(new PhysicsEngine(Vectors::ZERO)), - _entityClipboard(new EntityTree()), _previousScriptLocation("LastScriptLocation", DESKTOP_LOCATION), + _entitySimulation(new PhysicalEntitySimulation()), + _physicsEngine(new PhysicsEngine(Vectors::ZERO)), + _entityClipboard(new EntityTree()), + _previousScriptLocation("LastScriptLocation", DESKTOP_LOCATION), _fieldOfView("fieldOfView", DEFAULT_FIELD_OF_VIEW_DEGREES), _hmdTabletScale("hmdTabletScale", DEFAULT_HMD_TABLET_SCALE_PERCENT), - _desktopTabletScale("desktopTabletScale", DEFAULT_DESKTOP_TABLET_SCALE_PERCENT), _firstRun(Settings::firstRun, true), + _desktopTabletScale("desktopTabletScale", DEFAULT_DESKTOP_TABLET_SCALE_PERCENT), + _firstRun(Settings::firstRun, true), _desktopTabletBecomesToolbarSetting("desktopTabletBecomesToolbar", DEFAULT_DESKTOP_TABLET_BECOMES_TOOLBAR), _hmdTabletBecomesToolbarSetting("hmdTabletBecomesToolbar", DEFAULT_HMD_TABLET_BECOMES_TOOLBAR), _preferStylusOverLaserSetting("preferStylusOverLaser", DEFAULT_PREFER_STYLUS_OVER_LASER), _preferAvatarFingerOverStylusSetting("preferAvatarFingerOverStylus", DEFAULT_PREFER_AVATAR_FINGER_OVER_STYLUS), _constrainToolbarPosition("toolbar/constrainToolbarToCenterX", true), _preferredCursor("preferredCursor", DEFAULT_CURSOR_NAME), - _miniTabletEnabledSetting("miniTabletEnabled", DEFAULT_MINI_TABLET_ENABLED), _scaleMirror(1.0f), _mirrorYawOffset(0.0f), - _raiseMirror(0.0f), _enableProcessOctreeThread(true), _lastNackTime(usecTimestampNow()), - _lastSendDownstreamAudioStats(usecTimestampNow()), _notifiedPacketVersionMismatchThisDomain(false), - _maxOctreePPS(maxOctreePacketsPerSecond.get()), _lastFaceTrackerUpdate(0), _snapshotSound(nullptr), _sampleSound(nullptr) { + _miniTabletEnabledSetting("miniTabletEnabled", DEFAULT_MINI_TABLET_ENABLED), + _scaleMirror(1.0f), + _mirrorYawOffset(0.0f), + _raiseMirror(0.0f), + _enableProcessOctreeThread(true), + _lastNackTime(usecTimestampNow()), + _lastSendDownstreamAudioStats(usecTimestampNow()), + _notifiedPacketVersionMismatchThisDomain(false), + _maxOctreePPS(maxOctreePacketsPerSecond.get()), + _lastFaceTrackerUpdate(0), + _snapshotSound(nullptr), + _sampleSound(nullptr) +{ auto steamClient = PluginManager::getInstance()->getSteamClientPlugin(); setProperty(hifi::properties::STEAM, (steamClient && steamClient->isRunning())); @@ -1008,6 +1038,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo // This is done so as not break previous command line scripts if (testScriptPath.left(HIFI_URL_SCHEME_HTTP.length()) == HIFI_URL_SCHEME_HTTP || testScriptPath.left(HIFI_URL_SCHEME_FTP.length()) == HIFI_URL_SCHEME_FTP) { + setProperty(hifi::properties::TEST, QUrl::fromUserInput(testScriptPath)); } else if (QFileInfo(testScriptPath).exists()) { setProperty(hifi::properties::TEST, QUrl::fromLocalFile(testScriptPath)); @@ -1032,7 +1063,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo // make sure the debug draw singleton is initialized on the main thread. DebugDraw::getInstance().removeMarker(""); - PluginContainer* pluginContainer = dynamic_cast(this); // set the container for any plugins that care + PluginContainer* pluginContainer = dynamic_cast(this); // set the container for any plugins that care PluginManager::getInstance()->setContainer(pluginContainer); QThreadPool::globalInstance()->setMaxThreadCount(MIN_PROCESSING_THREAD_POOL_SIZE); @@ -1043,10 +1074,12 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo auto controllerScriptingInterface = DependencyManager::get().data(); _controllerScriptingInterface = dynamic_cast(controllerScriptingInterface); - connect(PluginManager::getInstance().data(), &PluginManager::inputDeviceRunningChanged, controllerScriptingInterface, - &controller::ScriptingInterface::updateRunningInputDevices); + connect(PluginManager::getInstance().data(), &PluginManager::inputDeviceRunningChanged, + controllerScriptingInterface, &controller::ScriptingInterface::updateRunningInputDevices); - EntityTree::setEntityClicksCapturedOperator([this] { return _controllerScriptingInterface->areEntityClicksCaptured(); }); + EntityTree::setEntityClicksCapturedOperator([this] { + return _controllerScriptingInterface->areEntityClicksCaptured(); + }); _entityClipboard->createRootElement(); @@ -1054,11 +1087,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo installNativeEventFilter(&MyNativeEventFilter::getInstance()); #endif -#ifdef PLATFORM - InitializePlatform(); -#endif - - QFontDatabase::addApplicationFont(PathUtils::resourcesPath() + "styles/Inconsolata.otf"); QFontDatabase::addApplicationFont(PathUtils::resourcesPath() + "fonts/fontawesome-webfont.ttf"); QFontDatabase::addApplicationFont(PathUtils::resourcesPath() + "fonts/hifi-glyphs.ttf"); @@ -1073,7 +1101,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo QFontDatabase::addApplicationFont(PathUtils::resourcesPath() + "fonts/Cairo-SemiBold.ttf"); _window->setWindowTitle("High Fidelity Interface"); - Model::setAbstractViewStateInterface(this); // The model class will sometimes need to know view state details from us + Model::setAbstractViewStateInterface(this); // The model class will sometimes need to know view state details from us auto nodeList = DependencyManager::get(); nodeList->startThread(); @@ -1129,8 +1157,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo bool isStore = property(hifi::properties::OCULUS_STORE).toBool(); - DependencyManager::get()->setLimitedCommerce( - isStore); // Or we could make it a separate arg, or if either arg is set, etc. And should this instead by a hifi::properties? + DependencyManager::get()->setLimitedCommerce(isStore); // Or we could make it a separate arg, or if either arg is set, etc. And should this instead by a hifi::properties? updateHeartbeat(); @@ -1164,16 +1191,14 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo return myAvatar ? myAvatar->getOrientationForAudio() : Quaternions::IDENTITY; }); - recording::Frame::registerFrameHandler(AudioConstants::getAudioFrameName(), - [&audioIO](recording::Frame::ConstPointer frame) { - audioIO->handleRecordedAudioInput(frame->data); - }); + recording::Frame::registerFrameHandler(AudioConstants::getAudioFrameName(), [&audioIO](recording::Frame::ConstPointer frame) { + audioIO->handleRecordedAudioInput(frame->data); + }); connect(audioIO, &AudioClient::inputReceived, [](const QByteArray& audio) { static auto recorder = DependencyManager::get(); if (recorder->isRecording()) { - static const recording::FrameType AUDIO_FRAME_TYPE = - recording::Frame::registerFrameType(AudioConstants::getAudioFrameName()); + static const recording::FrameType AUDIO_FRAME_TYPE = recording::Frame::registerFrameType(AudioConstants::getAudioFrameName()); recorder->recordFrame(AUDIO_FRAME_TYPE, audio); } }); @@ -1190,8 +1215,9 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo connect(&domainHandler, SIGNAL(domainURLChanged(QUrl)), SLOT(domainURLChanged(QUrl))); connect(&domainHandler, SIGNAL(redirectToErrorDomainURL(QUrl)), SLOT(goToErrorDomainURL(QUrl))); - connect(&domainHandler, &DomainHandler::domainURLChanged, - [](QUrl domainURL) { setCrashAnnotation("domain", domainURL.toString().toStdString()); }); + connect(&domainHandler, &DomainHandler::domainURLChanged, [](QUrl domainURL){ + setCrashAnnotation("domain", domainURL.toString().toStdString()); + }); connect(&domainHandler, SIGNAL(resetting()), SLOT(resettingDomain())); connect(&domainHandler, SIGNAL(connectedToDomain(QUrl)), SLOT(updateWindowTitle())); connect(&domainHandler, SIGNAL(disconnectedFromDomain()), SLOT(updateWindowTitle())); @@ -1219,21 +1245,20 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo // We could clear ATP assets only when changing domains, but it's possible that the domain you are connected // to has gone down and switched to a new content set, so when you reconnect the cached ATP assets will no longer be valid. - connect(&domainHandler, &DomainHandler::disconnectedFromDomain, DependencyManager::get().data(), - &ScriptCache::clearATPScriptsFromCache); + connect(&domainHandler, &DomainHandler::disconnectedFromDomain, DependencyManager::get().data(), &ScriptCache::clearATPScriptsFromCache); // update our location every 5 seconds in the metaverse server, assuming that we are authenticated with one const qint64 DATA_SERVER_LOCATION_CHANGE_UPDATE_MSECS = 5 * MSECS_PER_SECOND; auto discoverabilityManager = DependencyManager::get(); connect(&locationUpdateTimer, &QTimer::timeout, discoverabilityManager.data(), &DiscoverabilityManager::updateLocation); - connect(&locationUpdateTimer, &QTimer::timeout, DependencyManager::get().data(), - &AddressManager::storeCurrentAddress); + connect(&locationUpdateTimer, &QTimer::timeout, + DependencyManager::get().data(), &AddressManager::storeCurrentAddress); locationUpdateTimer.start(DATA_SERVER_LOCATION_CHANGE_UPDATE_MSECS); // if we get a domain change, immediately attempt update location in metaverse server - connect(&nodeList->getDomainHandler(), &DomainHandler::connectedToDomain, discoverabilityManager.data(), - &DiscoverabilityManager::updateLocation); + connect(&nodeList->getDomainHandler(), &DomainHandler::connectedToDomain, + discoverabilityManager.data(), &DiscoverabilityManager::updateLocation); // send a location update immediately discoverabilityManager->updateLocation(); @@ -1246,7 +1271,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo connect(nodeList.data(), &NodeList::packetVersionMismatch, this, &Application::notifyPacketVersionMismatch); // you might think we could just do this in NodeList but we only want this connection for Interface - connect(&nodeList->getDomainHandler(), SIGNAL(limitOfSilentDomainCheckInsReached()), nodeList.data(), SLOT(reset())); + connect(&nodeList->getDomainHandler(), SIGNAL(limitOfSilentDomainCheckInsReached()), + nodeList.data(), SLOT(reset())); auto dialogsManager = DependencyManager::get(); #if defined(Q_OS_ANDROID) @@ -1264,21 +1290,21 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo accountManager->setAuthURL(NetworkingConstants::METAVERSE_SERVER_URL()); // use our MyAvatar position and quat for address manager path - addressManager->setPositionGetter([this] { return getMyAvatar()->getWorldFeetPosition(); }); - addressManager->setOrientationGetter([this] { return getMyAvatar()->getWorldOrientation(); }); + addressManager->setPositionGetter([this]{ return getMyAvatar()->getWorldFeetPosition(); }); + addressManager->setOrientationGetter([this]{ return getMyAvatar()->getWorldOrientation(); }); connect(addressManager.data(), &AddressManager::hostChanged, this, &Application::updateWindowTitle); connect(this, &QCoreApplication::aboutToQuit, addressManager.data(), &AddressManager::storeCurrentAddress); connect(this, &Application::activeDisplayPluginChanged, this, &Application::updateThreadPoolCount); - connect(this, &Application::activeDisplayPluginChanged, this, []() { + connect(this, &Application::activeDisplayPluginChanged, this, [](){ qApp->setProperty(hifi::properties::HMD, qApp->isHMDMode()); auto displayPlugin = qApp->getActiveDisplayPlugin(); setCrashAnnotation("display_plugin", displayPlugin->getName().toStdString()); setCrashAnnotation("hmd", displayPlugin->isHmd() ? "1" : "0"); }); connect(this, &Application::activeDisplayPluginChanged, this, &Application::updateSystemTabletMode); - connect(this, &Application::activeDisplayPluginChanged, this, [&]() { + connect(this, &Application::activeDisplayPluginChanged, this, [&](){ if (getLoginDialogPoppedUp()) { auto dialogsManager = DependencyManager::get(); auto keyboard = DependencyManager::get(); @@ -1301,10 +1327,10 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo }); // Save avatar location immediately after a teleport. - connect(myAvatar.get(), &MyAvatar::positionGoneTo, DependencyManager::get().data(), - &AddressManager::storeCurrentAddress); + connect(myAvatar.get(), &MyAvatar::positionGoneTo, + DependencyManager::get().data(), &AddressManager::storeCurrentAddress); - connect(myAvatar.get(), &MyAvatar::skeletonModelURLChanged, []() { + connect(myAvatar.get(), &MyAvatar::skeletonModelURLChanged, [](){ QUrl avatarURL = qApp->getMyAvatar()->getSkeletonModelURL(); setCrashAnnotation("avatar", avatarURL.toString().toStdString()); }); @@ -1314,30 +1340,26 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo { auto scriptEngines = DependencyManager::get().data(); - scriptEngines->registerScriptInitializer( - [this](ScriptEnginePointer engine) { registerScriptEngineWithApplicationServices(engine); }); + scriptEngines->registerScriptInitializer([this](ScriptEnginePointer engine) { + registerScriptEngineWithApplicationServices(engine); + }); - connect(scriptEngines, &ScriptEngines::scriptCountChanged, this, - [this] { - auto scriptEngines = DependencyManager::get(); - if (scriptEngines->getRunningScripts().isEmpty()) { - getMyAvatar()->clearScriptableSettings(); - } - }, - Qt::QueuedConnection); + connect(scriptEngines, &ScriptEngines::scriptCountChanged, this, [this] { + auto scriptEngines = DependencyManager::get(); + if (scriptEngines->getRunningScripts().isEmpty()) { + getMyAvatar()->clearScriptableSettings(); + } + }, Qt::QueuedConnection); - connect(scriptEngines, &ScriptEngines::scriptsReloading, this, - [this] { - getEntities()->reloadEntityScripts(); - loadAvatarScripts(getMyAvatar()->getScriptUrls()); - }, - Qt::QueuedConnection); + connect(scriptEngines, &ScriptEngines::scriptsReloading, this, [this] { + getEntities()->reloadEntityScripts(); + loadAvatarScripts(getMyAvatar()->getScriptUrls()); + }, Qt::QueuedConnection); - connect(scriptEngines, &ScriptEngines::scriptLoadError, this, - [](const QString& filename, const QString& error) { - OffscreenUi::asyncWarning(nullptr, "Error Loading Script", filename + " failed to load."); - }, - Qt::QueuedConnection); + connect(scriptEngines, &ScriptEngines::scriptLoadError, + this, [](const QString& filename, const QString& error) { + OffscreenUi::asyncWarning(nullptr, "Error Loading Script", filename + " failed to load."); + }, Qt::QueuedConnection); } #ifdef _WIN32 @@ -1347,13 +1369,11 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo // tell the NodeList instance who to tell the domain server we care about nodeList->addSetOfNodeTypesToNodeInterestSet(NodeSet() << NodeType::AudioMixer << NodeType::AvatarMixer - << NodeType::EntityServer << NodeType::AssetServer - << NodeType::MessagesMixer << NodeType::EntityScriptServer); + << NodeType::EntityServer << NodeType::AssetServer << NodeType::MessagesMixer << NodeType::EntityScriptServer); // connect to the packet sent signal of the _entityEditSender connect(&_entityEditSender, &EntityEditPacketSender::packetSent, this, &Application::packetSent); - connect(&_entityEditSender, &EntityEditPacketSender::addingEntityWithCertificate, this, - &Application::addingEntityWithCertificate); + connect(&_entityEditSender, &EntityEditPacketSender::addingEntityWithCertificate, this, &Application::addingEntityWithCertificate); QString concurrentDownloadsStr = getCmdOption(argc, constArgv, "--concurrent-downloads"); bool success; @@ -1415,8 +1435,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo auto audioScriptingInterface = DependencyManager::set(); auto audioIO = DependencyManager::get().data(); connect(audioIO, &AudioClient::mutedByMixer, audioScriptingInterface.data(), &AudioScriptingInterface::mutedByMixer); - connect(audioIO, &AudioClient::receivedFirstPacket, audioScriptingInterface.data(), - &AudioScriptingInterface::receivedFirstPacket); + connect(audioIO, &AudioClient::receivedFirstPacket, audioScriptingInterface.data(), &AudioScriptingInterface::receivedFirstPacket); connect(audioIO, &AudioClient::disconnected, audioScriptingInterface.data(), &AudioScriptingInterface::disconnected); connect(audioIO, &AudioClient::muteEnvironmentRequested, [](glm::vec3 position, float radius) { auto audioClient = DependencyManager::get(); @@ -1429,8 +1448,11 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo audioScriptingInterface->environmentMuted(); } }); - connect(this, &Application::activeDisplayPluginChanged, - reinterpret_cast(audioScriptingInterface.data()), &scripting::Audio::onContextChanged); + QSharedPointer scriptingAudioSharedPointer = qSharedPointerDynamicCast(DependencyManager::get()); + if (scriptingAudioSharedPointer) { + connect(this, &Application::activeDisplayPluginChanged, + scriptingAudioSharedPointer.data(), &scripting::Audio::onContextChanged); + } } // Create the rendering engine. This can be slow on some machines due to lots of @@ -1439,7 +1461,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo qCDebug(interfaceapp, "Initialized Render Engine."); // Overlays need to exist before we set the ContextOverlayInterface dependency - _overlays.init(); // do this before scripts load + _overlays.init(); // do this before scripts load DependencyManager::set(); auto offscreenUi = getOffscreenUI(); @@ -1491,8 +1513,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo updateHeartbeat(); static const QString TESTER = "HIFI_TESTER"; - bool isTester = false; -#if defined(Q_OS_ANDROID) + bool isTester = false; +#if defined (Q_OS_ANDROID) // Since we cannot set environment variables in Android we use a file presence // to denote that this is a testing device QFileInfo check_tester_file(TESTER_FILE); @@ -1501,7 +1523,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo constexpr auto INSTALLER_INI_NAME = "installer.ini"; auto iniPath = QDir(applicationDirPath()).filePath(INSTALLER_INI_NAME); - QFile installerFile{ iniPath }; + QFile installerFile { iniPath }; std::unordered_map installerKeyValues; if (installerFile.open(QIODevice::ReadOnly)) { while (!installerFile.atEnd()) { @@ -1548,27 +1570,29 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo static const QString TESTER = "HIFI_TESTER"; auto gpuIdent = GPUIdent::getInstance(); auto glContextData = getGLContextData(); - QJsonObject properties = { { "version", applicationVersion() }, - { "tester", QProcessEnvironment::systemEnvironment().contains(TESTER) || isTester }, - { "installer_campaign", installerCampaign }, - { "installer_type", installerType }, - { "build_type", BuildInfo::BUILD_TYPE_STRING }, - { "previousSessionCrashed", _previousSessionCrashed }, - { "previousSessionRuntime", sessionRunTime.get() }, - { "cpu_architecture", QSysInfo::currentCpuArchitecture() }, - { "kernel_type", QSysInfo::kernelType() }, - { "kernel_version", QSysInfo::kernelVersion() }, - { "os_type", QSysInfo::productType() }, - { "os_version", QSysInfo::productVersion() }, - { "gpu_name", gpuIdent->getName() }, - { "gpu_driver", gpuIdent->getDriver() }, - { "gpu_memory", static_cast(gpuIdent->getMemory()) }, - { "gl_version_int", glVersionToInteger(glContextData.value("version").toString()) }, - { "gl_version", glContextData["version"] }, - { "gl_vender", glContextData["vendor"] }, - { "gl_sl_version", glContextData["sl_version"] }, - { "gl_renderer", glContextData["renderer"] }, - { "ideal_thread_count", QThread::idealThreadCount() } }; + QJsonObject properties = { + { "version", applicationVersion() }, + { "tester", QProcessEnvironment::systemEnvironment().contains(TESTER) || isTester }, + { "installer_campaign", installerCampaign }, + { "installer_type", installerType }, + { "build_type", BuildInfo::BUILD_TYPE_STRING }, + { "previousSessionCrashed", _previousSessionCrashed }, + { "previousSessionRuntime", sessionRunTime.get() }, + { "cpu_architecture", QSysInfo::currentCpuArchitecture() }, + { "kernel_type", QSysInfo::kernelType() }, + { "kernel_version", QSysInfo::kernelVersion() }, + { "os_type", QSysInfo::productType() }, + { "os_version", QSysInfo::productVersion() }, + { "gpu_name", gpuIdent->getName() }, + { "gpu_driver", gpuIdent->getDriver() }, + { "gpu_memory", static_cast(gpuIdent->getMemory()) }, + { "gl_version_int", glVersionToInteger(glContextData.value("version").toString()) }, + { "gl_version", glContextData["version"] }, + { "gl_vender", glContextData["vendor"] }, + { "gl_sl_version", glContextData["sl_version"] }, + { "gl_renderer", glContextData["renderer"] }, + { "ideal_thread_count", QThread::idealThreadCount() } + }; auto macVersion = QSysInfo::macVersion(); if (macVersion != QSysInfo::MV_None) { properties["os_osx_version"] = QSysInfo::macVersion(); @@ -1605,7 +1629,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo // For now we're going to set the PPS for outbound packets to be super high, this is // probably not the right long term solution. But for now, we're going to do this to // allow you to move an entity around in your hand - _entityEditSender.setPacketsPerSecond(3000); // super high!! + _entityEditSender.setPacketsPerSecond(3000); // super high!! // Make sure we don't time out during slow operations at startup updateHeartbeat(); @@ -1613,16 +1637,15 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo connect(this, SIGNAL(aboutToQuit()), this, SLOT(onAboutToQuit())); // FIXME -- I'm a little concerned about this. - connect(myAvatar->getSkeletonModel().get(), &SkeletonModel::skeletonLoaded, this, &Application::checkSkeleton, - Qt::QueuedConnection); + connect(myAvatar->getSkeletonModel().get(), &SkeletonModel::skeletonLoaded, + this, &Application::checkSkeleton, Qt::QueuedConnection); // Setup the userInputMapper with the actions auto userInputMapper = DependencyManager::get(); connect(userInputMapper.data(), &UserInputMapper::actionEvent, [this](int action, float state) { using namespace controller; auto tabletScriptingInterface = DependencyManager::get(); - auto audioScriptingInterface = - reinterpret_cast(DependencyManager::get().data()); + QSharedPointer audioScriptingInterface = qSharedPointerDynamicCast(DependencyManager::get()); { auto actionEnum = static_cast(action); int key = Qt::Key_unknown; @@ -1630,10 +1653,12 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo bool navAxis = false; switch (actionEnum) { case Action::TOGGLE_PUSHTOTALK: - if (state > 0.0f) { - audioScriptingInterface->setPushingToTalk(true); - } else if (state <= 0.0f) { - audioScriptingInterface->setPushingToTalk(false); + if (audioScriptingInterface) { + if (state > 0.0f) { + audioScriptingInterface->setPushingToTalk(true); + } else if (state <= 0.0f) { + audioScriptingInterface->setPushingToTalk(false); + } } break; @@ -1704,7 +1729,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo if (action == controller::toInt(controller::Action::RETICLE_CLICK)) { auto reticlePos = getApplicationCompositor().getReticlePosition(); - QPoint localPos(reticlePos.x, reticlePos.y); // both hmd and desktop already handle this in our coordinates. + QPoint localPos(reticlePos.x, reticlePos.y); // both hmd and desktop already handle this in our coordinates. if (state) { QMouseEvent mousePress(QEvent::MouseButtonPress, localPos, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier); sendEvent(_glWidget, &mousePress); @@ -1714,7 +1739,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo sendEvent(_glWidget, &mouseRelease); _reticleClickPressed = false; } - return; // nothing else to do + return; // nothing else to do } if (state) { @@ -1739,7 +1764,9 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo _applicationStateDevice = userInputMapper->getStateDevice(); - _applicationStateDevice->setInputVariant(STATE_IN_HMD, []() -> float { return qApp->isHMDMode() ? 1 : 0; }); + _applicationStateDevice->setInputVariant(STATE_IN_HMD, []() -> float { + return qApp->isHMDMode() ? 1 : 0; + }); _applicationStateDevice->setInputVariant(STATE_CAMERA_FULL_SCREEN_MIRROR, []() -> float { return qApp->getCamera().getMode() == CAMERA_MODE_MIRROR ? 1 : 0; }); @@ -1755,8 +1782,9 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo _applicationStateDevice->setInputVariant(STATE_CAMERA_INDEPENDENT, []() -> float { return qApp->getCamera().getMode() == CAMERA_MODE_INDEPENDENT ? 1 : 0; }); - _applicationStateDevice->setInputVariant(STATE_SNAP_TURN, - []() -> float { return qApp->getMyAvatar()->getSnapTurn() ? 1 : 0; }); + _applicationStateDevice->setInputVariant(STATE_SNAP_TURN, []() -> float { + return qApp->getMyAvatar()->getSnapTurn() ? 1 : 0; + }); _applicationStateDevice->setInputVariant(STATE_ADVANCED_MOVEMENT_CONTROLS, []() -> float { return qApp->getMyAvatar()->useAdvancedMovementControls() ? 1 : 0; }); @@ -1766,8 +1794,9 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo _applicationStateDevice->setInputVariant(STATE_RIGHT_HAND_DOMINANT, []() -> float { return qApp->getMyAvatar()->getDominantHand() == "right" ? 1 : 0; }); - _applicationStateDevice->setInputVariant(STATE_STRAFE_ENABLED, - []() -> float { return qApp->getMyAvatar()->getStrafeEnabled() ? 1 : 0; }); + _applicationStateDevice->setInputVariant(STATE_STRAFE_ENABLED, []() -> float { + return qApp->getMyAvatar()->getStrafeEnabled() ? 1 : 0; + }); _applicationStateDevice->setInputVariant(STATE_GROUNDED, []() -> float { return qApp->getMyAvatar()->getCharacterController()->onGround() ? 1 : 0; @@ -1792,12 +1821,13 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo }); _applicationStateDevice->setInputVariant(STATE_PLATFORM_ANDROID, []() -> float { #if defined(Q_OS_ANDROID) - return 1; + return 1 ; #else return 0; #endif }); + getRefreshRateManager().setRefreshRateRegime(RefreshRateManager::RefreshRateRegime::STARTUP); // Setup the _keyboardMouseDevice, _touchscreenDevice, _touchscreenVirtualPadDevice and the user input mapper with the default bindings @@ -1823,30 +1853,28 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo // Make sure we don't time out during slow operations at startup updateHeartbeat(); QTimer* settingsTimer = new QTimer(); - moveToNewNamedThread(settingsTimer, "Settings Thread", - [this, settingsTimer] { - // This needs to run on the settings thread, so we need to pass the `settingsTimer` as the - // receiver object, otherwise it will run on the application thread and trigger a warning - // about trying to kill the timer on the main thread. - connect(qApp, &Application::beforeAboutToQuit, settingsTimer, [this, settingsTimer] { - // Disconnect the signal from the save settings - QObject::disconnect(settingsTimer, &QTimer::timeout, this, &Application::saveSettings); - // Stop the settings timer - settingsTimer->stop(); - // Delete it (this will trigger the thread destruction - settingsTimer->deleteLater(); - // Mark the settings thread as finished, so we know we can safely save in the main application - // shutdown code - _settingsGuard.trigger(); - }); + moveToNewNamedThread(settingsTimer, "Settings Thread", [this, settingsTimer]{ + // This needs to run on the settings thread, so we need to pass the `settingsTimer` as the + // receiver object, otherwise it will run on the application thread and trigger a warning + // about trying to kill the timer on the main thread. + connect(qApp, &Application::beforeAboutToQuit, settingsTimer, [this, settingsTimer]{ + // Disconnect the signal from the save settings + QObject::disconnect(settingsTimer, &QTimer::timeout, this, &Application::saveSettings); + // Stop the settings timer + settingsTimer->stop(); + // Delete it (this will trigger the thread destruction + settingsTimer->deleteLater(); + // Mark the settings thread as finished, so we know we can safely save in the main application + // shutdown code + _settingsGuard.trigger(); + }); - int SAVE_SETTINGS_INTERVAL = 10 * MSECS_PER_SECOND; // Let's save every seconds for now - settingsTimer->setSingleShot(false); - settingsTimer->setInterval(SAVE_SETTINGS_INTERVAL); // 10s, Qt::CoarseTimer acceptable - QObject::connect(settingsTimer, &QTimer::timeout, this, &Application::saveSettings); - settingsTimer->start(); - }, - QThread::LowestPriority); + int SAVE_SETTINGS_INTERVAL = 10 * MSECS_PER_SECOND; // Let's save every seconds for now + settingsTimer->setSingleShot(false); + settingsTimer->setInterval(SAVE_SETTINGS_INTERVAL); // 10s, Qt::CoarseTimer acceptable + QObject::connect(settingsTimer, &QTimer::timeout, this, &Application::saveSettings); + settingsTimer->start(); + }, QThread::LowestPriority); if (Menu::getInstance()->isOptionChecked(MenuOption::FirstPerson)) { getMyAvatar()->setBoomLength(MyAvatar::ZOOM_MIN); // So that camera doesn't auto-switch to third person. @@ -1858,15 +1886,15 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo AudioInjector::setLocalAudioInterface(audioIO); auto audioScriptingInterface = DependencyManager::get(); audioScriptingInterface->setLocalAudioInterface(audioIO); - connect(audioIO, &AudioClient::noiseGateOpened, audioScriptingInterface.data(), - &AudioScriptingInterface::noiseGateOpened); - connect(audioIO, &AudioClient::noiseGateClosed, audioScriptingInterface.data(), - &AudioScriptingInterface::noiseGateClosed); + connect(audioIO, &AudioClient::noiseGateOpened, audioScriptingInterface.data(), &AudioScriptingInterface::noiseGateOpened); + connect(audioIO, &AudioClient::noiseGateClosed, audioScriptingInterface.data(), &AudioScriptingInterface::noiseGateClosed); connect(audioIO, &AudioClient::inputReceived, audioScriptingInterface.data(), &AudioScriptingInterface::inputReceived); } this->installEventFilter(this); + + #ifdef HAVE_DDE auto ddeTracker = DependencyManager::get(); ddeTracker->init(); @@ -1882,20 +1910,19 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo // If launched from Steam, let it handle updates const QString HIFI_NO_UPDATER_COMMAND_LINE_KEY = "--no-updater"; bool noUpdater = arguments().indexOf(HIFI_NO_UPDATER_COMMAND_LINE_KEY) != -1; - bool buildCanUpdate = - BuildInfo::BUILD_TYPE == BuildInfo::BuildType::Stable || BuildInfo::BUILD_TYPE == BuildInfo::BuildType::Master; + bool buildCanUpdate = BuildInfo::BUILD_TYPE == BuildInfo::BuildType::Stable + || BuildInfo::BUILD_TYPE == BuildInfo::BuildType::Master; if (!noUpdater && buildCanUpdate) { constexpr auto INSTALLER_TYPE_CLIENT_ONLY = "client_only"; auto applicationUpdater = DependencyManager::set(); - AutoUpdater::InstallerType type = installerType == INSTALLER_TYPE_CLIENT_ONLY ? AutoUpdater::InstallerType::CLIENT_ONLY - : AutoUpdater::InstallerType::FULL; + AutoUpdater::InstallerType type = installerType == INSTALLER_TYPE_CLIENT_ONLY + ? AutoUpdater::InstallerType::CLIENT_ONLY : AutoUpdater::InstallerType::FULL; applicationUpdater->setInstallerType(type); applicationUpdater->setInstallerCampaign(installerCampaign); - connect(applicationUpdater.data(), &AutoUpdater::newVersionIsAvailable, dialogsManager.data(), - &DialogsManager::showUpdateDialog); + connect(applicationUpdater.data(), &AutoUpdater::newVersionIsAvailable, dialogsManager.data(), &DialogsManager::showUpdateDialog); applicationUpdater->checkForUpdate(); } @@ -1914,9 +1941,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo auto keyboard = DependencyManager::get(); if (getEntities()->wantsKeyboardFocus(id)) { setKeyboardFocusEntity(id); - } else if ( - !keyboard->containsID( - id)) { // FIXME: this is a hack to make the keyboard work for now, since the keys would otherwise steal focus + } else if (!keyboard->containsID(id)) { // FIXME: this is a hack to make the keyboard work for now, since the keys would otherwise steal focus setKeyboardFocusEntity(UNKNOWN_ENTITY_ID); } } @@ -1925,63 +1950,57 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo connect(pointerManager.data(), &PointerManager::triggerBeginOverlay, keyboardFocusOperator); auto entityScriptingInterface = DependencyManager::get(); - connect(entityScriptingInterface.data(), &EntityScriptingInterface::deletingEntity, this, - [this](const EntityItemID& entityItemID) { - if (entityItemID == _keyboardFocusedEntity.get()) { - setKeyboardFocusEntity(UNKNOWN_ENTITY_ID); - } - }, - Qt::QueuedConnection); - - EntityTreeRenderer::setAddMaterialToEntityOperator( - [this](const QUuid& entityID, graphics::MaterialLayer material, const std::string& parentMaterialName) { - if (_aboutToQuit) { - return false; - } - - auto renderable = getEntities()->renderableForEntityId(entityID); - if (renderable) { - renderable->addMaterial(material, parentMaterialName); - return true; - } + connect(entityScriptingInterface.data(), &EntityScriptingInterface::deletingEntity, this, [this](const EntityItemID& entityItemID) { + if (entityItemID == _keyboardFocusedEntity.get()) { + setKeyboardFocusEntity(UNKNOWN_ENTITY_ID); + } + }, Qt::QueuedConnection); + EntityTreeRenderer::setAddMaterialToEntityOperator([this](const QUuid& entityID, graphics::MaterialLayer material, const std::string& parentMaterialName) { + if (_aboutToQuit) { return false; - }); - EntityTreeRenderer::setRemoveMaterialFromEntityOperator( - [this](const QUuid& entityID, graphics::MaterialPointer material, const std::string& parentMaterialName) { - if (_aboutToQuit) { - return false; - } + } - auto renderable = getEntities()->renderableForEntityId(entityID); - if (renderable) { - renderable->removeMaterial(material, parentMaterialName); - return true; - } + auto renderable = getEntities()->renderableForEntityId(entityID); + if (renderable) { + renderable->addMaterial(material, parentMaterialName); + return true; + } + return false; + }); + EntityTreeRenderer::setRemoveMaterialFromEntityOperator([this](const QUuid& entityID, graphics::MaterialPointer material, const std::string& parentMaterialName) { + if (_aboutToQuit) { return false; - }); + } - EntityTreeRenderer::setAddMaterialToAvatarOperator( - [](const QUuid& avatarID, graphics::MaterialLayer material, const std::string& parentMaterialName) { - auto avatarManager = DependencyManager::get(); - auto avatar = avatarManager->getAvatarBySessionID(avatarID); - if (avatar) { - avatar->addMaterial(material, parentMaterialName); - return true; - } - return false; - }); - EntityTreeRenderer::setRemoveMaterialFromAvatarOperator( - [](const QUuid& avatarID, graphics::MaterialPointer material, const std::string& parentMaterialName) { - auto avatarManager = DependencyManager::get(); - auto avatar = avatarManager->getAvatarBySessionID(avatarID); - if (avatar) { - avatar->removeMaterial(material, parentMaterialName); - return true; - } - return false; - }); + auto renderable = getEntities()->renderableForEntityId(entityID); + if (renderable) { + renderable->removeMaterial(material, parentMaterialName); + return true; + } + + return false; + }); + + EntityTreeRenderer::setAddMaterialToAvatarOperator([](const QUuid& avatarID, graphics::MaterialLayer material, const std::string& parentMaterialName) { + auto avatarManager = DependencyManager::get(); + auto avatar = avatarManager->getAvatarBySessionID(avatarID); + if (avatar) { + avatar->addMaterial(material, parentMaterialName); + return true; + } + return false; + }); + EntityTreeRenderer::setRemoveMaterialFromAvatarOperator([](const QUuid& avatarID, graphics::MaterialPointer material, const std::string& parentMaterialName) { + auto avatarManager = DependencyManager::get(); + auto avatar = avatarManager->getAvatarBySessionID(avatarID); + if (avatar) { + avatar->removeMaterial(material, parentMaterialName); + return true; + } + return false; + }); EntityTree::setGetEntityObjectOperator([this](const QUuid& id) -> QObject* { auto entities = getEntities(); @@ -2008,7 +2027,9 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo return QSizeF(0.0f, 0.0f); }); - connect(this, &Application::aboutToQuit, [this]() { setKeyboardFocusEntity(UNKNOWN_ENTITY_ID); }); + connect(this, &Application::aboutToQuit, [this]() { + setKeyboardFocusEntity(UNKNOWN_ENTITY_ID); + }); // Add periodic checks to send user activity data static int CHECK_NEARBY_AVATARS_INTERVAL_MS = 10000; @@ -2027,6 +2048,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo QTimer* sendStatsTimer = new QTimer(this); sendStatsTimer->setInterval(SEND_STATS_INTERVAL_MS); // 10s, Qt::CoarseTimer acceptable connect(sendStatsTimer, &QTimer::timeout, this, [this]() { + QJsonObject properties = {}; MemoryInfo memInfo; if (getMemoryInfo(memInfo)) { @@ -2037,8 +2059,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo // content location and build info - useful for filtering stats auto addressManager = DependencyManager::get(); - auto currentDomain = addressManager->currentShareableAddress(true).toString(); // domain only - auto currentPath = addressManager->currentPath(true); // with orientation + auto currentDomain = addressManager->currentShareableAddress(true).toString(); // domain only + auto currentPath = addressManager->currentPath(true); // with orientation properties["current_domain"] = currentDomain; properties["current_path"] = currentPath; properties["build_version"] = BuildInfo::VERSION; @@ -2102,24 +2124,24 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo startedRequests["atp"] = statTracker->getStat(STAT_ATP_REQUEST_STARTED).toInt(); startedRequests["http"] = statTracker->getStat(STAT_HTTP_REQUEST_STARTED).toInt(); startedRequests["file"] = statTracker->getStat(STAT_FILE_REQUEST_STARTED).toInt(); - startedRequests["total"] = - startedRequests["atp"].toInt() + startedRequests["http"].toInt() + startedRequests["file"].toInt(); + startedRequests["total"] = startedRequests["atp"].toInt() + startedRequests["http"].toInt() + + startedRequests["file"].toInt(); properties["started_requests"] = startedRequests; QJsonObject successfulRequests; successfulRequests["atp"] = statTracker->getStat(STAT_ATP_REQUEST_SUCCESS).toInt(); successfulRequests["http"] = statTracker->getStat(STAT_HTTP_REQUEST_SUCCESS).toInt(); successfulRequests["file"] = statTracker->getStat(STAT_FILE_REQUEST_SUCCESS).toInt(); - successfulRequests["total"] = - successfulRequests["atp"].toInt() + successfulRequests["http"].toInt() + successfulRequests["file"].toInt(); + successfulRequests["total"] = successfulRequests["atp"].toInt() + successfulRequests["http"].toInt() + + successfulRequests["file"].toInt(); properties["successful_requests"] = successfulRequests; QJsonObject failedRequests; failedRequests["atp"] = statTracker->getStat(STAT_ATP_REQUEST_FAILED).toInt(); failedRequests["http"] = statTracker->getStat(STAT_HTTP_REQUEST_FAILED).toInt(); failedRequests["file"] = statTracker->getStat(STAT_FILE_REQUEST_FAILED).toInt(); - failedRequests["total"] = - failedRequests["atp"].toInt() + failedRequests["http"].toInt() + failedRequests["file"].toInt(); + failedRequests["total"] = failedRequests["atp"].toInt() + failedRequests["http"].toInt() + + failedRequests["file"].toInt(); properties["failed_requests"] = failedRequests; QJsonObject cacheRequests; @@ -2164,18 +2186,21 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo totalServerOctreeElements += i->second.getTotalElements(); } - properties["local_octree_elements"] = (qint64)OctreeElement::getInternalNodeCount(); - properties["server_octree_elements"] = (qint64)totalServerOctreeElements; + properties["local_octree_elements"] = (qint64) OctreeElement::getInternalNodeCount(); + properties["server_octree_elements"] = (qint64) totalServerOctreeElements; properties["active_display_plugin"] = getActiveDisplayPlugin()->getName(); properties["using_hmd"] = isHMDMode(); _autoSwitchDisplayModeSupportedHMDPlugin = nullptr; - foreach (DisplayPluginPointer displayPlugin, PluginManager::getInstance()->getDisplayPlugins()) { - if (displayPlugin->isHmd() && displayPlugin->getSupportsAutoSwitch()) { + foreach(DisplayPluginPointer displayPlugin, PluginManager::getInstance()->getDisplayPlugins()) { + if (displayPlugin->isHmd() && + displayPlugin->getSupportsAutoSwitch()) { _autoSwitchDisplayModeSupportedHMDPlugin = displayPlugin; - _autoSwitchDisplayModeSupportedHMDPluginName = _autoSwitchDisplayModeSupportedHMDPlugin->getName(); - _previousHMDWornStatus = _autoSwitchDisplayModeSupportedHMDPlugin->isDisplayVisible(); + _autoSwitchDisplayModeSupportedHMDPluginName = + _autoSwitchDisplayModeSupportedHMDPlugin->getName(); + _previousHMDWornStatus = + _autoSwitchDisplayModeSupportedHMDPlugin->isDisplayVisible(); break; } } @@ -2183,7 +2208,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo if (_autoSwitchDisplayModeSupportedHMDPlugin) { if (getActiveDisplayPlugin() != _autoSwitchDisplayModeSupportedHMDPlugin && !_autoSwitchDisplayModeSupportedHMDPlugin->isSessionActive()) { - startHMDStandBySession(); + startHMDStandBySession(); } // Poll periodically to check whether the user has worn HMD or not. Switch Display mode accordingly. // If the user wears HMD then switch to VR mode. If the user removes HMD then switch to Desktop mode. @@ -2209,8 +2234,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo // controller::Pose considers two poses to be different if either are invalid. In our case, we actually // want to consider the pose to be unchanged if it was invalid and still is invalid, so we check that first. properties["hand_pose_changed"] = - ((leftHandPose.valid || lastLeftHandPose.valid) && (leftHandPose != lastLeftHandPose)) || - ((rightHandPose.valid || lastRightHandPose.valid) && (rightHandPose != lastRightHandPose)); + ((leftHandPose.valid || lastLeftHandPose.valid) && (leftHandPose != lastLeftHandPose)) + || ((rightHandPose.valid || lastRightHandPose.valid) && (rightHandPose != lastRightHandPose)); lastLeftHandPose = leftHandPose; lastRightHandPose = rightHandPose; @@ -2221,12 +2246,11 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo // Periodically check for count of nearby avatars static int lastCountOfNearbyAvatars = -1; QTimer* checkNearbyAvatarsTimer = new QTimer(this); - checkNearbyAvatarsTimer->setInterval(CHECK_NEARBY_AVATARS_INTERVAL_MS); // 10 seconds, Qt::CoarseTimer ok + checkNearbyAvatarsTimer->setInterval(CHECK_NEARBY_AVATARS_INTERVAL_MS); // 10 seconds, Qt::CoarseTimer ok connect(checkNearbyAvatarsTimer, &QTimer::timeout, this, []() { auto avatarManager = DependencyManager::get(); int nearbyAvatars = avatarManager->numberOfAvatarsInRange(avatarManager->getMyAvatar()->getWorldPosition(), - NEARBY_AVATAR_RADIUS_METERS) - - 1; + NEARBY_AVATAR_RADIUS_METERS) - 1; if (nearbyAvatars != lastCountOfNearbyAvatars) { lastCountOfNearbyAvatars = nearbyAvatars; UserActivityLogger::getInstance().logAction("nearby_avatars", { { "count", nearbyAvatars } }); @@ -2235,7 +2259,9 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo checkNearbyAvatarsTimer->start(); // Track user activity event when we receive a mute packet - auto onMutedByMixer = []() { UserActivityLogger::getInstance().logAction("received_mute_packet"); }; + auto onMutedByMixer = []() { + UserActivityLogger::getInstance().logAction("received_mute_packet"); + }; connect(DependencyManager::get().data(), &AudioClient::mutedByMixer, this, onMutedByMixer); // Track when the address bar is opened @@ -2265,16 +2291,16 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo // Monitor model assets (e.g., from Clara.io) added to the world that may need resizing. static const int ADD_ASSET_TO_WORLD_TIMER_INTERVAL_MS = 1000; - _addAssetToWorldResizeTimer.setInterval(ADD_ASSET_TO_WORLD_TIMER_INTERVAL_MS); // 1s, Qt::CoarseTimer acceptable + _addAssetToWorldResizeTimer.setInterval(ADD_ASSET_TO_WORLD_TIMER_INTERVAL_MS); // 1s, Qt::CoarseTimer acceptable connect(&_addAssetToWorldResizeTimer, &QTimer::timeout, this, &Application::addAssetToWorldCheckModelSize); // Auto-update and close adding asset to world info message box. static const int ADD_ASSET_TO_WORLD_INFO_TIMEOUT_MS = 5000; - _addAssetToWorldInfoTimer.setInterval(ADD_ASSET_TO_WORLD_INFO_TIMEOUT_MS); // 5s, Qt::CoarseTimer acceptable + _addAssetToWorldInfoTimer.setInterval(ADD_ASSET_TO_WORLD_INFO_TIMEOUT_MS); // 5s, Qt::CoarseTimer acceptable _addAssetToWorldInfoTimer.setSingleShot(true); connect(&_addAssetToWorldInfoTimer, &QTimer::timeout, this, &Application::addAssetToWorldInfoTimeout); static const int ADD_ASSET_TO_WORLD_ERROR_TIMEOUT_MS = 8000; - _addAssetToWorldErrorTimer.setInterval(ADD_ASSET_TO_WORLD_ERROR_TIMEOUT_MS); // 8s, Qt::CoarseTimer acceptable + _addAssetToWorldErrorTimer.setInterval(ADD_ASSET_TO_WORLD_ERROR_TIMEOUT_MS); // 8s, Qt::CoarseTimer acceptable _addAssetToWorldErrorTimer.setSingleShot(true); connect(&_addAssetToWorldErrorTimer, &QTimer::timeout, this, &Application::addAssetToWorldErrorTimeout); @@ -2286,8 +2312,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo connect(&_myCamera, &Camera::modeUpdated, this, &Application::cameraModeChanged); - DependencyManager::get()->setShouldPickHUDOperator( - []() { return DependencyManager::get()->isHMDMode(); }); + DependencyManager::get()->setShouldPickHUDOperator([]() { return DependencyManager::get()->isHMDMode(); }); DependencyManager::get()->setCalculatePos2DFromHUDOperator([this](const glm::vec3& intersection) { const glm::vec2 MARGIN(25.0f); glm::vec2 maxPos = _controllerScriptingInterface->getViewportDimensions() - MARGIN; @@ -2297,10 +2322,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo // Setup the mouse ray pick and related operators { - auto mouseRayPick = std::make_shared(Vectors::ZERO, Vectors::UP, - PickFilter(PickScriptingInterface::PICK_ENTITIES() | - PickScriptingInterface::PICK_LOCAL_ENTITIES()), - 0.0f, true); + auto mouseRayPick = std::make_shared(Vectors::ZERO, Vectors::UP, PickFilter(PickScriptingInterface::PICK_ENTITIES() | PickScriptingInterface::PICK_LOCAL_ENTITIES()), 0.0f, true); mouseRayPick->parentTransform = std::make_shared(); mouseRayPick->setJointState(PickQuery::JOINT_STATE_MOUSE); auto mouseRayPickID = DependencyManager::get()->addPick(PickQuery::Ray, mouseRayPick); @@ -2326,8 +2348,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo DependencyManager::get()->setPrecisionPicking(rayPickID, value); }); - EntityItem::setBillboardRotationOperator([](const glm::vec3& position, const glm::quat& rotation, - BillboardMode billboardMode, const glm::vec3& frustumPos) { + EntityItem::setBillboardRotationOperator([](const glm::vec3& position, const glm::quat& rotation, BillboardMode billboardMode, const glm::vec3& frustumPos) { if (billboardMode == BillboardMode::YAW) { //rotate about vertical to face the camera glm::vec3 dPosition = frustumPos - position; @@ -2353,12 +2374,9 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo return viewFrustum.getPosition(); }); - DependencyManager::get()->setKickConfirmationOperator( - [this](const QUuid& nodeID) { userKickConfirmation(nodeID); }); + DependencyManager::get()->setKickConfirmationOperator([this] (const QUuid& nodeID) { userKickConfirmation(nodeID); }); - render::entities::WebEntityRenderer::setAcquireWebSurfaceOperator([=](const QString& url, bool htmlContent, - QSharedPointer& webSurface, - bool& cachedWebSurface) { + render::entities::WebEntityRenderer::setAcquireWebSurfaceOperator([=](const QString& url, bool htmlContent, QSharedPointer& webSurface, bool& cachedWebSurface) { bool isTablet = url == TabletScriptingInterface::QML; if (htmlContent) { webSurface = DependencyManager::get()->acquire(render::entities::WebEntityRenderer::QML); @@ -2372,8 +2390,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo QObject::connect(webSurface.data(), &hifi::qml::OffscreenSurface::rootContextCreated, rootItemLoadedFunctor); } auto surfaceContext = webSurface->getSurfaceContext(); - surfaceContext->setContextProperty("KeyboardScriptingInterface", - DependencyManager::get().data()); + surfaceContext->setContextProperty("KeyboardScriptingInterface", DependencyManager::get().data()); } else { // FIXME: the tablet should use the OffscreenQmlSurfaceCache webSurface = QSharedPointer(new OffscreenQmlSurface(), [](OffscreenQmlSurface* webSurface) { @@ -2384,9 +2401,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo }); }); auto rootItemLoadedFunctor = [webSurface, url, isTablet] { - Application::setupQmlSurface(webSurface->getSurfaceContext(), isTablet || url == LOGIN_DIALOG.toString() || - url == AVATAR_INPUTS_BAR_QML.toString() || - url == BUBBLE_ICON_QML.toString()); + Application::setupQmlSurface(webSurface->getSurfaceContext(), isTablet || url == LOGIN_DIALOG.toString() || url == AVATAR_INPUTS_BAR_QML.toString() || + url == BUBBLE_ICON_QML.toString()); }; if (webSurface->getRootItem()) { rootItemLoadedFunctor(); @@ -2400,9 +2416,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo const uint8_t TABLET_FPS = 90; webSurface->setMaxFps(isTablet ? TABLET_FPS : DEFAULT_MAX_FPS); }); - render::entities::WebEntityRenderer::setReleaseWebSurfaceOperator([=](QSharedPointer& webSurface, - bool& cachedWebSurface, - std::vector& connections) { + render::entities::WebEntityRenderer::setReleaseWebSurfaceOperator([=](QSharedPointer& webSurface, bool& cachedWebSurface, std::vector& connections) { QQuickItem* rootItem = webSurface->getRootItem(); // Fix for crash in QtWebEngineCore when rapidly switching domains @@ -2511,10 +2525,10 @@ QString Application::getUserAgent() { return userAgent; } - QString userAgent = "Mozilla/5.0 (HighFidelityInterface/" + BuildInfo::VERSION + "; " + QSysInfo::productType() + " " + - QSysInfo::productVersion() + ")"; + QString userAgent = "Mozilla/5.0 (HighFidelityInterface/" + BuildInfo::VERSION + "; " + + QSysInfo::productType() + " " + QSysInfo::productVersion() + ")"; - auto formatPluginName = [](QString name) -> QString { return name.trimmed().replace(" ", "-"); }; + auto formatPluginName = [](QString name) -> QString { return name.trimmed().replace(" ", "-"); }; // For each plugin, add to userAgent auto displayPlugins = PluginManager::getInstance()->getDisplayPlugins(); @@ -2523,7 +2537,7 @@ QString Application::getUserAgent() { userAgent += " " + formatPluginName(dp->getName()); } } - auto inputPlugins = PluginManager::getInstance()->getInputPlugins(); + auto inputPlugins= PluginManager::getInstance()->getInputPlugins(); for (auto& ip : inputPlugins) { if (ip->isActive()) { userAgent += " " + formatPluginName(ip->getName()); @@ -2557,7 +2571,7 @@ void Application::checkChangeCursor() { QMutexLocker locker(&_changeCursorLock); if (_cursorNeedsChanging) { #ifdef Q_OS_MAC - auto cursorTarget = _window; // OSX doesn't seem to provide for hiding the cursor only on the GL widget + auto cursorTarget = _window; // OSX doesn't seem to provide for hiding the cursor only on the GL widget #else // On windows and linux, hiding the top level cursor also means it's invisible when hovering over the // window menu, which is a pain, so only hide it for the GL surface @@ -2596,7 +2610,7 @@ void Application::onAboutToQuit() { _firstRun.set(false); } - foreach (auto inputPlugin, PluginManager::getInstance()->getInputPlugins()) { + foreach(auto inputPlugin, PluginManager::getInstance()->getInputPlugins()) { if (inputPlugin->isActive()) { inputPlugin->deactivate(); } @@ -2609,7 +2623,8 @@ void Application::onAboutToQuit() { loginDialogPoppedUp.set(false); getActiveDisplayPlugin()->deactivate(); - if (_autoSwitchDisplayModeSupportedHMDPlugin && _autoSwitchDisplayModeSupportedHMDPlugin->isSessionActive()) { + if (_autoSwitchDisplayModeSupportedHMDPlugin + && _autoSwitchDisplayModeSupportedHMDPlugin->isSessionActive()) { _autoSwitchDisplayModeSupportedHMDPlugin->endSession(); } // use the CloseEventSender via a QThread to send an event that says the user asked for the app to close @@ -2671,7 +2686,7 @@ void Application::cleanupBeforeQuit() { nodeList->getPacketReceiver().setShouldDropPackets(true); } - getEntities()->shutdown(); // tell the entities system we're shutting down, so it will stop running scripts + getEntities()->shutdown(); // tell the entities system we're shutting down, so it will stop running scripts // Clear any queued processing (I/O, FBX/OBJ/Texture parsing) QThreadPool::globalInstance()->clear(); @@ -2680,7 +2695,7 @@ void Application::cleanupBeforeQuit() { // FIXME: Something is still holding on to the ScriptEnginePointers contained in ScriptEngines, and they hold backpointers to ScriptEngines, // so this doesn't shut down properly - DependencyManager::get()->shutdownScripting(); // stop all currently running global scripts + DependencyManager::get()->shutdownScripting(); // stop all currently running global scripts // These classes hold ScriptEnginePointers, so they must be destroyed before ScriptEngines // Must be done after shutdownScripting in case any scripts try to access these things { @@ -2724,7 +2739,7 @@ void Application::cleanupBeforeQuit() { DependencyManager::destroy(); #endif - DependencyManager::destroy(); // Must be destroyed before TabletScriptingInterface + DependencyManager::destroy(); // Must be destroyed before TabletScriptingInterface // stop QML DependencyManager::destroy(); @@ -2765,14 +2780,14 @@ Application::~Application() { avatarManager->handleProcessedPhysicsTransaction(transaction); avatarManager->deleteAllAvatars(); - + auto myCharacterController = getMyAvatar()->getCharacterController(); myCharacterController->clearDetailedMotionStates(); - + myCharacterController->buildPhysicsTransaction(transaction); _physicsEngine->processTransaction(transaction); myCharacterController->handleProcessedPhysicsTransaction(transaction); - + _physicsEngine->setCharacterController(nullptr); // the _shapeManager should have zero references @@ -2802,7 +2817,7 @@ Application::~Application() { DependencyManager::destroy(); - DependencyManager::destroy(); // must be destroyed before the FramebufferCache + DependencyManager::destroy(); // must be destroyed before the FramebufferCache DependencyManager::destroy(); @@ -2876,7 +2891,7 @@ void Application::initializeGL() { if (!nsightActive()) { _chromiumShareContext = new OffscreenGLCanvas(); _chromiumShareContext->setObjectName("ChromiumShareContext"); - auto format = QSurfaceFormat::defaultFormat(); + auto format =QSurfaceFormat::defaultFormat(); #ifdef Q_OS_MAC // On mac, the primary shared OpenGL context must be a 3.2 core context, // or chromium flips out and spews error spam (but renders fine) @@ -2895,6 +2910,7 @@ void Application::initializeGL() { } #endif + _glWidget->createContext(globalShareContext); if (!_glWidget->makeCurrent()) { @@ -2903,7 +2919,7 @@ void Application::initializeGL() { #if !defined(DISABLE_QML) QStringList chromiumFlags; - // Bug 21993: disable microphone and camera input + // Bug 21993: disable microphone and camera input chromiumFlags << "--use-fake-device-for-media-stream"; // Disable signed distance field font rendering on ATI/AMD GPUs, due to // https://highfidelity.manuscript.com/f/cases/13677/Text-showing-up-white-on-Marketplace-app @@ -2940,6 +2956,7 @@ void Application::initializeGL() { } #endif + // Build an offscreen GL context for the main thread. _glWidget->makeCurrent(); glClearColor(0.2f, 0.2f, 0.2f, 1); @@ -2957,18 +2974,18 @@ void Application::initializeDisplayPlugins() { auto defaultDisplayPlugin = displayPlugins.at(0); // Once time initialization code DisplayPluginPointer targetDisplayPlugin; - foreach (auto displayPlugin, displayPlugins) { + foreach(auto displayPlugin, displayPlugins) { displayPlugin->setContext(_graphicsEngine.getGPUContext()); if (displayPlugin->getName() == lastActiveDisplayPluginName) { targetDisplayPlugin = displayPlugin; } QObject::connect(displayPlugin.get(), &DisplayPlugin::recommendedFramebufferSizeChanged, - [this](const QSize& size) { resizeGL(); }); + [this](const QSize& size) { resizeGL(); }); QObject::connect(displayPlugin.get(), &DisplayPlugin::resetSensorsRequested, this, &Application::requestReset); if (displayPlugin->isHmd()) { auto hmdDisplayPlugin = dynamic_cast(displayPlugin.get()); QObject::connect(hmdDisplayPlugin, &HmdDisplayPlugin::hmdMountedChanged, - DependencyManager::get().data(), &HMDScriptingInterface::mountedChanged); + DependencyManager::get().data(), &HMDScriptingInterface::mountedChanged); QObject::connect(hmdDisplayPlugin, &HmdDisplayPlugin::hmdVisibleChanged, this, &Application::hmdVisibleChanged); } } @@ -3005,8 +3022,7 @@ void Application::showLoginScreen() { auto dialogsManager = DependencyManager::get(); if (!accountManager->isLoggedIn()) { if (!isHMDMode()) { - auto toolbar = - DependencyManager::get()->getToolbar("com.highfidelity.interface.toolbar.system"); + auto toolbar = DependencyManager::get()->getToolbar("com.highfidelity.interface.toolbar.system"); toolbar->writeProperty("visible", false); } _loginDialogPoppedUp = true; @@ -3035,64 +3051,60 @@ void Application::initializeUi() { QmlContextCallback commerceCallback = [](QQmlContext* context) { context->setContextProperty("Commerce", DependencyManager::get().data()); }; - OffscreenQmlSurface::addWhitelistContextHandler( - { - QUrl{ "hifi/commerce/checkout/Checkout.qml" }, - QUrl{ "hifi/commerce/common/CommerceLightbox.qml" }, - QUrl{ "hifi/commerce/common/EmulatedMarketplaceHeader.qml" }, - QUrl{ "hifi/commerce/common/FirstUseTutorial.qml" }, - QUrl{ "hifi/commerce/common/sendAsset/SendAsset.qml" }, - QUrl{ "hifi/commerce/common/SortableListModel.qml" }, - QUrl{ "hifi/commerce/inspectionCertificate/InspectionCertificate.qml" }, - QUrl{ "hifi/commerce/marketplaceItemTester/MarketplaceItemTester.qml" }, - QUrl{ "hifi/commerce/purchases/PurchasedItem.qml" }, - QUrl{ "hifi/commerce/purchases/Purchases.qml" }, - QUrl{ "hifi/commerce/wallet/Help.qml" }, - QUrl{ "hifi/commerce/wallet/NeedsLogIn.qml" }, - QUrl{ "hifi/commerce/wallet/PassphraseChange.qml" }, - QUrl{ "hifi/commerce/wallet/PassphraseModal.qml" }, - QUrl{ "hifi/commerce/wallet/PassphraseSelection.qml" }, - QUrl{ "hifi/commerce/wallet/Wallet.qml" }, - QUrl{ "hifi/commerce/wallet/WalletHome.qml" }, - QUrl{ "hifi/commerce/wallet/WalletSetup.qml" }, - QUrl{ "hifi/dialogs/security/Security.qml" }, - QUrl{ "hifi/dialogs/security/SecurityImageChange.qml" }, - QUrl{ "hifi/dialogs/security/SecurityImageModel.qml" }, - QUrl{ "hifi/dialogs/security/SecurityImageSelection.qml" }, - QUrl{ "hifi/tablet/TabletMenu.qml" }, - QUrl{ "hifi/commerce/marketplace/Marketplace.qml" }, - }, - commerceCallback); + OffscreenQmlSurface::addWhitelistContextHandler({ + QUrl{ "hifi/commerce/checkout/Checkout.qml" }, + QUrl{ "hifi/commerce/common/CommerceLightbox.qml" }, + QUrl{ "hifi/commerce/common/EmulatedMarketplaceHeader.qml" }, + QUrl{ "hifi/commerce/common/FirstUseTutorial.qml" }, + QUrl{ "hifi/commerce/common/sendAsset/SendAsset.qml" }, + QUrl{ "hifi/commerce/common/SortableListModel.qml" }, + QUrl{ "hifi/commerce/inspectionCertificate/InspectionCertificate.qml" }, + QUrl{ "hifi/commerce/marketplaceItemTester/MarketplaceItemTester.qml"}, + QUrl{ "hifi/commerce/purchases/PurchasedItem.qml" }, + QUrl{ "hifi/commerce/purchases/Purchases.qml" }, + QUrl{ "hifi/commerce/wallet/Help.qml" }, + QUrl{ "hifi/commerce/wallet/NeedsLogIn.qml" }, + QUrl{ "hifi/commerce/wallet/PassphraseChange.qml" }, + QUrl{ "hifi/commerce/wallet/PassphraseModal.qml" }, + QUrl{ "hifi/commerce/wallet/PassphraseSelection.qml" }, + QUrl{ "hifi/commerce/wallet/Wallet.qml" }, + QUrl{ "hifi/commerce/wallet/WalletHome.qml" }, + QUrl{ "hifi/commerce/wallet/WalletSetup.qml" }, + QUrl{ "hifi/dialogs/security/Security.qml" }, + QUrl{ "hifi/dialogs/security/SecurityImageChange.qml" }, + QUrl{ "hifi/dialogs/security/SecurityImageModel.qml" }, + QUrl{ "hifi/dialogs/security/SecurityImageSelection.qml" }, + QUrl{ "hifi/tablet/TabletMenu.qml" }, + QUrl{ "hifi/commerce/marketplace/Marketplace.qml" }, + }, commerceCallback); QmlContextCallback marketplaceCallback = [](QQmlContext* context) { context->setContextProperty("MarketplaceScriptingInterface", new QmlMarketplace()); }; - OffscreenQmlSurface::addWhitelistContextHandler( - { - QUrl{ "hifi/commerce/marketplace/Marketplace.qml" }, - }, - marketplaceCallback); + OffscreenQmlSurface::addWhitelistContextHandler({ + QUrl{ "hifi/commerce/marketplace/Marketplace.qml" }, + }, marketplaceCallback); QmlContextCallback platformInfoCallback = [](QQmlContext* context) { context->setContextProperty("PlatformInfo", new PlatformInfoScriptingInterface()); }; - OffscreenQmlSurface::addWhitelistContextHandler( - { - QUrl{ "hifi/commerce/marketplace/Marketplace.qml" }, - QUrl{ "hifi/commerce/purchases/Purchases.qml" }, - QUrl{ "hifi/commerce/wallet/Wallet.qml" }, - QUrl{ "hifi/commerce/wallet/WalletHome.qml" }, - QUrl{ "hifi/tablet/TabletAddressDialog.qml" }, - QUrl{ "hifi/Card.qml" }, - QUrl{ "hifi/Pal.qml" }, - QUrl{ "hifi/NameCard.qml" }, - }, - platformInfoCallback); + OffscreenQmlSurface::addWhitelistContextHandler({ + QUrl{ "hifi/commerce/marketplace/Marketplace.qml" }, + QUrl{ "hifi/commerce/purchases/Purchases.qml" }, + QUrl{ "hifi/commerce/wallet/Wallet.qml" }, + QUrl{ "hifi/commerce/wallet/WalletHome.qml" }, + QUrl{ "hifi/tablet/TabletAddressDialog.qml" }, + QUrl{ "hifi/Card.qml" }, + QUrl{ "hifi/Pal.qml" }, + QUrl{ "hifi/NameCard.qml" }, + }, platformInfoCallback); QmlContextCallback ttsCallback = [](QQmlContext* context) { context->setContextProperty("TextToSpeech", DependencyManager::get().data()); }; - OffscreenQmlSurface::addWhitelistContextHandler({ QUrl{ "hifi/tts/TTS.qml" } }, ttsCallback); + OffscreenQmlSurface::addWhitelistContextHandler({ + QUrl{ "hifi/tts/TTS.qml" } + }, ttsCallback); qmlRegisterType("Hifi", 1, 0, "ResourceImageItem"); qmlRegisterType("Hifi", 1, 0, "Preference"); qmlRegisterType("HifiWeb", 1, 0, "WebBrowserSuggestionsEngine"); @@ -3103,15 +3115,18 @@ void Application::initializeUi() { } auto offscreenUi = getOffscreenUI(); - connect(offscreenUi.data(), &hifi::qml::OffscreenSurface::rootContextCreated, this, - &Application::onDesktopRootContextCreated); - connect(offscreenUi.data(), &hifi::qml::OffscreenSurface::rootItemCreated, this, &Application::onDesktopRootItemCreated); + connect(offscreenUi.data(), &hifi::qml::OffscreenSurface::rootContextCreated, + this, &Application::onDesktopRootContextCreated); + connect(offscreenUi.data(), &hifi::qml::OffscreenSurface::rootItemCreated, + this, &Application::onDesktopRootItemCreated); #if !defined(DISABLE_QML) offscreenUi->setProxyWindow(_window->windowHandle()); // OffscreenUi is a subclass of OffscreenQmlSurface specifically designed to // support the window management and scripting proxies for VR use - DeadlockWatchdogThread::withPause([&] { offscreenUi->createDesktop(PathUtils::qmlUrl("hifi/Desktop.qml")); }); + DeadlockWatchdogThread::withPause([&] { + offscreenUi->createDesktop(PathUtils::qmlUrl("hifi/Desktop.qml")); + }); // FIXME either expose so that dialogs can set this themselves or // do better detection in the offscreen UI of what has focus offscreenUi->setNavigationFocused(false); @@ -3135,7 +3150,7 @@ void Application::initializeUi() { }); offscreenUi->resume(); #endif - connect(_window, &MainWindow::windowGeometryChanged, [this](const QRect& r) { + connect(_window, &MainWindow::windowGeometryChanged, [this](const QRect& r){ resizeGL(); if (_touchscreenVirtualPadDevice) { _touchscreenVirtualPadDevice->resize(); @@ -3144,7 +3159,7 @@ void Application::initializeUi() { // This will set up the input plugins UI _activeInputPlugins.clear(); - foreach (auto inputPlugin, PluginManager::getInstance()->getInputPlugins()) { + foreach(auto inputPlugin, PluginManager::getInstance()->getInputPlugins()) { if (KeyboardMouseDevice::NAME == inputPlugin->getName()) { _keyboardMouseDevice = std::dynamic_pointer_cast(inputPlugin); } @@ -3155,8 +3170,10 @@ void Application::initializeUi() { _touchscreenVirtualPadDevice = std::dynamic_pointer_cast(inputPlugin); #if defined(ANDROID_APP_INTERFACE) auto& virtualPadManager = VirtualPad::Manager::instance(); - connect(&virtualPadManager, &VirtualPad::Manager::hapticFeedbackRequested, this, - [](int duration) { AndroidHelper::instance().performHapticFeedback(duration); }); + connect(&virtualPadManager, &VirtualPad::Manager::hapticFeedbackRequested, + this, [](int duration) { + AndroidHelper::instance().performHapticFeedback(duration); + }); #endif } } @@ -3164,9 +3181,10 @@ void Application::initializeUi() { auto compositorHelper = DependencyManager::get(); connect(compositorHelper.data(), &CompositorHelper::allowMouseCaptureChanged, this, [=] { if (isHMDMode()) { - auto compositorHelper = DependencyManager::get(); // don't capture outer smartpointer - showCursor(compositorHelper->getAllowMouseCapture() ? Cursor::Manager::lookupIcon(_preferredCursor.get()) - : Cursor::Icon::SYSTEM); + auto compositorHelper = DependencyManager::get(); // don't capture outer smartpointer + showCursor(compositorHelper->getAllowMouseCapture() ? + Cursor::Manager::lookupIcon(_preferredCursor.get()) : + Cursor::Icon::SYSTEM); } }); @@ -3177,10 +3195,8 @@ void Application::initializeUi() { if (rootObject == TabletScriptingInterface::QML) { // in Qt 5.10.0 there is already an "Audio" object in the QML context // though I failed to find it (from QtMultimedia??). So.. let it be "AudioScriptingInterface" - surfaceContext->setContextProperty("AudioScriptingInterface", - DependencyManager::get().data()); - surfaceContext->setContextProperty("Account", - AccountServicesScriptingInterface::getInstance()); // DEPRECATED - TO BE REMOVED + surfaceContext->setContextProperty("AudioScriptingInterface", DependencyManager::get().data()); + surfaceContext->setContextProperty("Account", AccountServicesScriptingInterface::getInstance()); // DEPRECATED - TO BE REMOVED } }); @@ -3196,12 +3212,10 @@ void Application::initializeUi() { auto displayPlugins = PluginManager::getInstance()->getDisplayPlugins(); // first sort the plugins into groupings: standard, advanced, developer std::stable_sort(displayPlugins.begin(), displayPlugins.end(), - [](const DisplayPluginPointer& a, const DisplayPluginPointer& b) -> bool { - return a->getGrouping() < b->getGrouping(); - }); + [](const DisplayPluginPointer& a, const DisplayPluginPointer& b) -> bool { return a->getGrouping() < b->getGrouping(); }); int dpIndex = 1; // concatenate the groupings into a single list in the order: standard, advanced, developer - for (const auto& displayPlugin : displayPlugins) { + for(const auto& displayPlugin : displayPlugins) { addDisplayPluginToMenu(displayPlugin, dpIndex, _displayPlugin == displayPlugin); dpIndex++; } @@ -3212,15 +3226,18 @@ void Application::initializeUi() { } #endif + // The display plugins are created before the menu now, so we need to do this here to hide the menu bar // now that it exists if (_window && _window->isFullScreen()) { setFullscreen(nullptr, true); } + setIsInterstitialMode(true); } + void Application::onDesktopRootContextCreated(QQmlContext* surfaceContext) { auto engine = surfaceContext->engine(); // in Qt 5.10.0 there is already an "Audio" object in the QML context @@ -3255,8 +3272,7 @@ void Application::onDesktopRootContextCreated(QQmlContext* surfaceContext) { surfaceContext->setContextProperty("AvatarList", DependencyManager::get().data()); surfaceContext->setContextProperty("Users", DependencyManager::get().data()); - surfaceContext->setContextProperty("UserActivityLogger", - DependencyManager::get().data()); + surfaceContext->setContextProperty("UserActivityLogger", DependencyManager::get().data()); surfaceContext->setContextProperty("Camera", &_myCamera); @@ -3281,10 +3297,8 @@ void Application::onDesktopRootContextCreated(QQmlContext* surfaceContext) { surfaceContext->setContextProperty("InputConfiguration", DependencyManager::get().data()); - surfaceContext->setContextProperty("Account", - AccountServicesScriptingInterface::getInstance()); // DEPRECATED - TO BE REMOVED - surfaceContext->setContextProperty("GlobalServices", - AccountServicesScriptingInterface::getInstance()); // DEPRECATED - TO BE REMOVED + surfaceContext->setContextProperty("Account", AccountServicesScriptingInterface::getInstance()); // DEPRECATED - TO BE REMOVED + surfaceContext->setContextProperty("GlobalServices", AccountServicesScriptingInterface::getInstance()); // DEPRECATED - TO BE REMOVED surfaceContext->setContextProperty("AccountServices", AccountServicesScriptingInterface::getInstance()); surfaceContext->setContextProperty("DialogsManager", _dialogsManagerScriptingInterface); @@ -3342,10 +3356,12 @@ void Application::userKickConfirmation(const QUuid& nodeID) { } QString kickMessage = "Do you wish to kick " + userName + " from your domain"; - ModalDialogListener* dlg = OffscreenUi::asyncQuestion("Kick User", kickMessage, QMessageBox::Yes | QMessageBox::No); + ModalDialogListener* dlg = OffscreenUi::asyncQuestion("Kick User", kickMessage, + QMessageBox::Yes | QMessageBox::No); if (dlg->getDialogItem()) { - QObject::connect(dlg, &ModalDialogListener::response, this, [=](QVariant answer) { + + QObject::connect(dlg, &ModalDialogListener::response, this, [=] (QVariant answer) { QObject::disconnect(dlg, &ModalDialogListener::response, this, nullptr); bool yes = (static_cast(answer.toInt()) == QMessageBox::Yes); @@ -3364,16 +3380,14 @@ void Application::userKickConfirmation(const QUuid& nodeID) { void Application::setupQmlSurface(QQmlContext* surfaceContext, bool setAdditionalContextProperties) { surfaceContext->setContextProperty("Users", DependencyManager::get().data()); surfaceContext->setContextProperty("HMD", DependencyManager::get().data()); - surfaceContext->setContextProperty("UserActivityLogger", - DependencyManager::get().data()); + surfaceContext->setContextProperty("UserActivityLogger", DependencyManager::get().data()); surfaceContext->setContextProperty("Preferences", DependencyManager::get().data()); surfaceContext->setContextProperty("Vec3", new Vec3()); surfaceContext->setContextProperty("Quat", new Quat()); surfaceContext->setContextProperty("MyAvatar", DependencyManager::get()->getMyAvatar().get()); surfaceContext->setContextProperty("Entities", DependencyManager::get().data()); surfaceContext->setContextProperty("Snapshot", DependencyManager::get().data()); - surfaceContext->setContextProperty("KeyboardScriptingInterface", - DependencyManager::get().data()); + surfaceContext->setContextProperty("KeyboardScriptingInterface", DependencyManager::get().data()); if (setAdditionalContextProperties) { auto tabletScriptingInterface = DependencyManager::get(); @@ -3386,10 +3400,8 @@ void Application::setupQmlSurface(QQmlContext* surfaceContext, bool setAdditiona surfaceContext->setContextProperty("MenuInterface", MenuScriptingInterface::getInstance()); surfaceContext->setContextProperty("RefreshRate", new RefreshRateScriptingInterface()); - surfaceContext->setContextProperty("Account", - AccountServicesScriptingInterface::getInstance()); // DEPRECATED - TO BE REMOVED - surfaceContext->setContextProperty("GlobalServices", - AccountServicesScriptingInterface::getInstance()); // DEPRECATED - TO BE REMOVED + surfaceContext->setContextProperty("Account", AccountServicesScriptingInterface::getInstance()); // DEPRECATED - TO BE REMOVED + surfaceContext->setContextProperty("GlobalServices", AccountServicesScriptingInterface::getInstance()); // DEPRECATED - TO BE REMOVED surfaceContext->setContextProperty("AccountServices", AccountServicesScriptingInterface::getInstance()); // in Qt 5.10.0 there is already an "Audio" object in the QML context @@ -3409,16 +3421,14 @@ void Application::setupQmlSurface(QQmlContext* surfaceContext, bool setAdditiona surfaceContext->setContextProperty("InputConfiguration", DependencyManager::get().data()); surfaceContext->setContextProperty("SoundCache", DependencyManager::get().data()); surfaceContext->setContextProperty("AvatarBookmarks", DependencyManager::get().data()); - surfaceContext->setContextProperty("Render", - AbstractViewStateInterface::instance()->getRenderEngine()->getConfiguration().get()); + surfaceContext->setContextProperty("Render", AbstractViewStateInterface::instance()->getRenderEngine()->getConfiguration().get()); surfaceContext->setContextProperty("Workload", qApp->getGameWorkload()._engine->getConfiguration().get()); surfaceContext->setContextProperty("Controller", DependencyManager::get().data()); surfaceContext->setContextProperty("Pointers", DependencyManager::get().data()); surfaceContext->setContextProperty("Window", DependencyManager::get().data()); surfaceContext->setContextProperty("Reticle", qApp->getApplicationCompositor().getReticleInterface()); surfaceContext->setContextProperty("HiFiAbout", AboutUtil::getInstance()); - surfaceContext->setContextProperty("WalletScriptingInterface", - DependencyManager::get().data()); + surfaceContext->setContextProperty("WalletScriptingInterface", DependencyManager::get().data()); surfaceContext->setContextProperty("ResourceRequestObserver", DependencyManager::get().data()); } } @@ -3438,17 +3448,20 @@ void Application::updateCamera(RenderArgs& renderArgs, float deltaTime) { // Using the latter will cause the camera to wobble with idle animations, // or with changes from the face tracker if (_myCamera.getMode() == CAMERA_MODE_FIRST_PERSON) { - _thirdPersonHMDCameraBoomValid = false; + _thirdPersonHMDCameraBoomValid= false; if (isHMDMode()) { mat4 camMat = myAvatar->getSensorToWorldMatrix() * myAvatar->getHMDSensorMatrix(); _myCamera.setPosition(extractTranslation(camMat)); _myCamera.setOrientation(glmExtractRotation(camMat)); - } else { + } + else { _myCamera.setPosition(myAvatar->getDefaultEyePosition()); _myCamera.setOrientation(myAvatar->getMyHead()->getHeadOrientation()); } - } else if (_myCamera.getMode() == CAMERA_MODE_THIRD_PERSON) { + } + else if (_myCamera.getMode() == CAMERA_MODE_THIRD_PERSON) { if (isHMDMode()) { + if (!_thirdPersonHMDCameraBoomValid) { const glm::vec3 CAMERA_OFFSET = glm::vec3(0.0f, 0.0f, 0.7f); _thirdPersonHMDCameraBoom = cancelOutRollAndPitch(myAvatar->getHMDSensorOrientation()) * CAMERA_OFFSET; @@ -3457,29 +3470,32 @@ void Application::updateCamera(RenderArgs& renderArgs, float deltaTime) { glm::mat4 thirdPersonCameraSensorToWorldMatrix = myAvatar->getSensorToWorldMatrix(); - const glm::vec3 cameraPos = - myAvatar->getHMDSensorPosition() + _thirdPersonHMDCameraBoom * myAvatar->getBoomLength(); + const glm::vec3 cameraPos = myAvatar->getHMDSensorPosition() + _thirdPersonHMDCameraBoom * myAvatar->getBoomLength(); glm::mat4 sensorCameraMat = createMatFromQuatAndPos(myAvatar->getHMDSensorOrientation(), cameraPos); glm::mat4 worldCameraMat = thirdPersonCameraSensorToWorldMatrix * sensorCameraMat; _myCamera.setOrientation(glm::normalize(glmExtractRotation(worldCameraMat))); _myCamera.setPosition(extractTranslation(worldCameraMat)); - } else { + } + else { _thirdPersonHMDCameraBoomValid = false; _myCamera.setOrientation(myAvatar->getHead()->getOrientation()); if (isOptionChecked(MenuOption::CenterPlayerInView)) { - _myCamera.setPosition(myAvatar->getDefaultEyePosition() + _myCamera.getOrientation() * boomOffset); - } else { - _myCamera.setPosition(myAvatar->getDefaultEyePosition() + myAvatar->getWorldOrientation() * boomOffset); + _myCamera.setPosition(myAvatar->getDefaultEyePosition() + + _myCamera.getOrientation() * boomOffset); + } + else { + _myCamera.setPosition(myAvatar->getDefaultEyePosition() + + myAvatar->getWorldOrientation() * boomOffset); } } - } else if (_myCamera.getMode() == CAMERA_MODE_MIRROR) { - _thirdPersonHMDCameraBoomValid = false; + } + else if (_myCamera.getMode() == CAMERA_MODE_MIRROR) { + _thirdPersonHMDCameraBoomValid= false; if (isHMDMode()) { - auto mirrorBodyOrientation = - myAvatar->getWorldOrientation() * glm::quat(glm::vec3(0.0f, PI + _mirrorYawOffset, 0.0f)); + auto mirrorBodyOrientation = myAvatar->getWorldOrientation() * glm::quat(glm::vec3(0.0f, PI + _mirrorYawOffset, 0.0f)); glm::quat hmdRotation = extractRotation(myAvatar->getHMDSensorMatrix()); // Mirror HMD yaw and roll @@ -3496,24 +3512,26 @@ void Application::updateCamera(RenderArgs& renderArgs, float deltaTime) { // Mirror HMD lateral offsets hmdOffset.x = -hmdOffset.x; - _myCamera.setPosition( - myAvatar->getDefaultEyePosition() + glm::vec3(0, _raiseMirror * myAvatar->getModelScale(), 0) + - mirrorBodyOrientation * glm::vec3(0.0f, 0.0f, 1.0f) * MIRROR_FULLSCREEN_DISTANCE * _scaleMirror + - mirrorBodyOrientation * hmdOffset); - } else { + _myCamera.setPosition(myAvatar->getDefaultEyePosition() + + glm::vec3(0, _raiseMirror * myAvatar->getModelScale(), 0) + + mirrorBodyOrientation * glm::vec3(0.0f, 0.0f, 1.0f) * MIRROR_FULLSCREEN_DISTANCE * _scaleMirror + + mirrorBodyOrientation * hmdOffset); + } + else { auto userInputMapper = DependencyManager::get(); const float YAW_SPEED = TWO_PI / 5.0f; float deltaYaw = userInputMapper->getActionState(controller::Action::YAW) * YAW_SPEED * deltaTime; _mirrorYawOffset += deltaYaw; _myCamera.setOrientation(myAvatar->getWorldOrientation() * glm::quat(glm::vec3(0.0f, PI + _mirrorYawOffset, 0.0f))); - _myCamera.setPosition(myAvatar->getDefaultEyePosition() + - glm::vec3(0, _raiseMirror * myAvatar->getModelScale(), 0) + - (myAvatar->getWorldOrientation() * glm::quat(glm::vec3(0.0f, _mirrorYawOffset, 0.0f))) * - glm::vec3(0.0f, 0.0f, -1.0f) * myAvatar->getBoomLength() * _scaleMirror); + _myCamera.setPosition(myAvatar->getDefaultEyePosition() + + glm::vec3(0, _raiseMirror * myAvatar->getModelScale(), 0) + + (myAvatar->getWorldOrientation() * glm::quat(glm::vec3(0.0f, _mirrorYawOffset, 0.0f))) * + glm::vec3(0.0f, 0.0f, -1.0f) * myAvatar->getBoomLength() * _scaleMirror); } renderArgs._renderMode = RenderArgs::MIRROR_RENDER_MODE; - } else if (_myCamera.getMode() == CAMERA_MODE_ENTITY) { - _thirdPersonHMDCameraBoomValid = false; + } + else if (_myCamera.getMode() == CAMERA_MODE_ENTITY) { + _thirdPersonHMDCameraBoomValid= false; EntityItemPointer cameraEntity = _myCamera.getCameraEntityPointer(); if (cameraEntity != nullptr) { if (isHMDMode()) { @@ -3521,7 +3539,8 @@ void Application::updateCamera(RenderArgs& renderArgs, float deltaTime) { _myCamera.setOrientation(cameraEntity->getWorldOrientation() * hmdRotation); glm::vec3 hmdOffset = extractTranslation(myAvatar->getHMDSensorMatrix()); _myCamera.setPosition(cameraEntity->getWorldPosition() + (hmdRotation * hmdOffset)); - } else { + } + else { _myCamera.setOrientation(cameraEntity->getWorldOrientation()); _myCamera.setPosition(cameraEntity->getWorldPosition()); } @@ -3541,6 +3560,7 @@ void Application::runTests() { } void Application::faceTrackerMuteToggled() { + QAction* muteAction = Menu::getInstance()->getActionForOption(MenuOption::MuteFaceTracking); Q_CHECK_PTR(muteAction); bool isMuted = getSelectedFaceTracker()->isMuted(); @@ -3587,8 +3607,9 @@ void Application::setPreferredCursor(const QString& cursorName) { if (_displayPlugin && _displayPlugin->isHmd()) { _preferredCursor.set(cursorName.isEmpty() ? DEFAULT_CURSOR_NAME : cursorName); - } else { - _preferredCursor.set(cursorName.isEmpty() ? Cursor::Manager::getIconName(Cursor::Icon::SYSTEM) : cursorName); + } + else { + _preferredCursor.set(cursorName.isEmpty() ? Cursor::Manager::getIconName(Cursor::Icon::SYSTEM) : cursorName); } showCursor(Cursor::Manager::lookupIcon(_preferredCursor.get())); @@ -3644,8 +3665,7 @@ void Application::showHelp() { QUrlQuery queryString; queryString.addQueryItem("handControllerName", handControllerName); queryString.addQueryItem("defaultTab", defaultTab); - TabletProxy* tablet = - dynamic_cast(DependencyManager::get()->getTablet(SYSTEM_TABLET)); + TabletProxy* tablet = dynamic_cast(DependencyManager::get()->getTablet(SYSTEM_TABLET)); tablet->gotoWebScreen(PathUtils::resourcesUrl() + INFO_HELP_PATH + "?" + queryString.toString()); DependencyManager::get()->openTablet(); //InfoView::show(INFO_HELP_PATH, false, queryString.toString()); @@ -3685,8 +3705,8 @@ void Application::resizeGL() { // FIXME the aspect ratio for stereo displays is incorrect based on this. float aspectRatio = displayPlugin->getRecommendedAspectRatio(); - _myCamera.setProjection( - glm::perspective(glm::radians(_fieldOfView.get()), aspectRatio, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP)); + _myCamera.setProjection(glm::perspective(glm::radians(_fieldOfView.get()), aspectRatio, + DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP)); // Possible change in aspect ratio { QMutexLocker viewLocker(&_viewMutex); @@ -3703,12 +3723,14 @@ void Application::handleSandboxStatus(QNetworkReply* reply) { bool sandboxIsRunning = SandboxUtils::readStatus(reply->readAll()); - enum HandControllerType - { + enum HandControllerType { Vive, Oculus }; - static const std::map MIN_CONTENT_VERSION = { { Vive, 1 }, { Oculus, 27 } }; + static const std::map MIN_CONTENT_VERSION = { + { Vive, 1 }, + { Oculus, 27 } + }; // Get sandbox content set version auto acDirPath = PathUtils::getAppDataPath() + "../../" + BuildInfo::MODIFIED_ORGANIZATION + "/assignment-client/"; @@ -3718,7 +3740,7 @@ void Application::handleSandboxStatus(QNetworkReply* reply) { QFile contentVersionFile(contentVersionPath); if (contentVersionFile.open(QIODevice::ReadOnly | QIODevice::Text)) { QString line = contentVersionFile.readAll(); - contentVersion = line.toInt(); // returns 0 if conversion fails + contentVersion = line.toInt(); // returns 0 if conversion fails } // Get controller availability @@ -3736,8 +3758,7 @@ void Application::handleSandboxStatus(QNetworkReply* reply) { bool isUsingHMD = _displayPlugin->isHmd(); bool isUsingHMDAndHandControllers = hasHMD && hasHandControllers && isUsingHMD; - qCDebug(interfaceapp) << "HMD:" << hasHMD << ", Hand Controllers: " << hasHandControllers - << ", Using HMD: " << isUsingHMDAndHandControllers; + qCDebug(interfaceapp) << "HMD:" << hasHMD << ", Hand Controllers: " << hasHandControllers << ", Using HMD: " << isUsingHMDAndHandControllers; // when --url in command line, teleport to location const QString HIFI_URL_COMMAND_LINE_KEY = "--url"; @@ -3759,8 +3780,8 @@ void Application::handleSandboxStatus(QNetworkReply* reply) { // If this is a first run we short-circuit the address passed in if (_firstRun.get()) { - DependencyManager::get()->goToEntry(); - sentTo = SENT_TO_ENTRY; + DependencyManager::get()->goToEntry(); + sentTo = SENT_TO_ENTRY; _firstRun.set(false); } else { @@ -3779,21 +3800,22 @@ void Application::handleSandboxStatus(QNetworkReply* reply) { sentTo = SENT_TO_PREVIOUS_LOCATION; } - UserActivityLogger::getInstance().logAction("startup_sent_to", - { { "sent_to", sentTo }, - { "sandbox_is_running", sandboxIsRunning }, - { "has_hmd", hasHMD }, - { "has_hand_controllers", hasHandControllers }, - { "is_using_hmd", isUsingHMD }, - { "is_using_hmd_and_hand_controllers", isUsingHMDAndHandControllers }, - { "content_version", contentVersion } }); + UserActivityLogger::getInstance().logAction("startup_sent_to", { + { "sent_to", sentTo }, + { "sandbox_is_running", sandboxIsRunning }, + { "has_hmd", hasHMD }, + { "has_hand_controllers", hasHandControllers }, + { "is_using_hmd", isUsingHMD }, + { "is_using_hmd_and_hand_controllers", isUsingHMDAndHandControllers }, + { "content_version", contentVersion } + }); _connectionMonitor.init(); } bool Application::importJSONFromURL(const QString& urlString) { // we only load files that terminate in just .json (not .svo.json and not .ava.json) - QUrl jsonURL{ urlString }; + QUrl jsonURL { urlString }; emit svoImportRequested(urlString); return true; @@ -3939,18 +3961,19 @@ bool Application::handleKeyEventForFocusedEntity(QEvent* event) { if (_keyboardFocusedEntity.get() != UNKNOWN_ENTITY_ID) { switch (event->type()) { case QEvent::KeyPress: - case QEvent::KeyRelease: { - auto eventHandler = getEntities()->getEventHandler(_keyboardFocusedEntity.get()); - if (eventHandler) { - event->setAccepted(false); - QCoreApplication::sendEvent(eventHandler, event); - if (event->isAccepted()) { - _lastAcceptedKeyPress = usecTimestampNow(); - return true; + case QEvent::KeyRelease: + { + auto eventHandler = getEntities()->getEventHandler(_keyboardFocusedEntity.get()); + if (eventHandler) { + event->setAccepted(false); + QCoreApplication::sendEvent(eventHandler, event); + if (event->isAccepted()) { + _lastAcceptedKeyPress = usecTimestampNow(); + return true; + } } + break; } - break; - } default: break; } @@ -3986,18 +4009,19 @@ static void dumpEventQueue(QThread* thread) { qDebug() << " " << type; } } -#endif // DEBUG_EVENT_QUEUE +#endif // DEBUG_EVENT_QUEUE -bool Application::notify(QObject* object, QEvent* event) { +bool Application::notify(QObject * object, QEvent * event) { if (thread() == QThread::currentThread()) { PROFILE_RANGE_IF_LONGER(app, "notify", 2) return QApplication::notify(object, event); - } - + } + return QApplication::notify(object, event); } bool Application::event(QEvent* event) { + if (_aboutToQuit) { return false; } @@ -4029,7 +4053,7 @@ bool Application::event(QEvent* event) { dumpEventQueue(QThread::currentThread()); } } -#endif // DEBUG_EVENT_QUEUE +#endif // DEBUG_EVENT_QUEUE _pendingIdleEvent.store(false); @@ -4053,9 +4077,6 @@ bool Application::event(QEvent* event) { case QEvent::KeyRelease: keyReleaseEvent(static_cast(event)); return true; - case QEvent::FocusIn: - focusInEvent(static_cast(event)); - return true; case QEvent::FocusOut: focusOutEvent(static_cast(event)); return true; @@ -4093,10 +4114,16 @@ bool Application::event(QEvent* event) { } bool Application::eventFilter(QObject* object, QEvent* event) { + if (_aboutToQuit && event->type() != QEvent::DeferredDelete && event->type() != QEvent::Destroy) { return true; } + auto eventType = event->type(); + if (eventType == QEvent::KeyPress || eventType == QEvent::KeyRelease || eventType == QEvent::MouseMove) { + getRefreshRateManager().resetInactiveTimer(); + } + if (event->type() == QEvent::Leave) { getApplicationCompositor().handleLeaveEvent(); } @@ -4134,7 +4161,7 @@ void Application::keyPressEvent(QKeyEvent* event) { _keysPressed.insert(event->key(), *event); } - _controllerScriptingInterface->emitKeyPressEvent(event); // send events to any registered scripts + _controllerScriptingInterface->emitKeyPressEvent(event); // send events to any registered scripts // if one of our scripts have asked to capture this event, then stop processing it if (_controllerScriptingInterface->isKeyCaptured(event) || isInterstitialMode()) { return; @@ -4224,10 +4251,9 @@ void Application::keyPressEvent(QKeyEvent* event) { case Qt::Key_G: if (isShifted && isMeta && Menu::getInstance() && Menu::getInstance()->getMenu("Developer")->isVisible()) { static const QString HIFI_FRAMES_FOLDER_VAR = "HIFI_FRAMES_FOLDER"; - static const QString GPU_FRAME_FOLDER = - QProcessEnvironment::systemEnvironment().contains(HIFI_FRAMES_FOLDER_VAR) - ? QProcessEnvironment::systemEnvironment().value(HIFI_FRAMES_FOLDER_VAR) - : "hifiFrames"; + static const QString GPU_FRAME_FOLDER = QProcessEnvironment::systemEnvironment().contains(HIFI_FRAMES_FOLDER_VAR) + ? QProcessEnvironment::systemEnvironment().value(HIFI_FRAMES_FOLDER_VAR) + : "hifiFrames"; static QString GPU_FRAME_TEMPLATE = GPU_FRAME_FOLDER + "/{DATE}_{TIME}"; QString fullPath = FileUtils::computeDocumentPath(FileUtils::replaceDateTimeTokens(GPU_FRAME_TEMPLATE)); if (FileUtils::canCreateFile(fullPath)) { @@ -4287,6 +4313,10 @@ void Application::keyPressEvent(QKeyEvent* event) { if (isMeta) { auto audioClient = DependencyManager::get(); audioClient->setMuted(!audioClient->isMuted()); + QSharedPointer audioScriptingInterface = qSharedPointerDynamicCast(DependencyManager::get()); + if (audioScriptingInterface && audioScriptingInterface->getPTT()) { + audioScriptingInterface->setPushingToTalk(!audioClient->isMuted()); + } } break; @@ -4306,18 +4336,16 @@ void Application::keyPressEvent(QKeyEvent* event) { if (!isShifted && !isMeta && !isOption && !event->isAutoRepeat()) { AudioInjectorOptions options; options.localOnly = true; - options.positionSet = false; // system sound + options.positionSet = false; // system sound options.stereo = true; Setting::Handle notificationSounds{ MenuOption::NotificationSounds, true }; Setting::Handle notificationSoundSnapshot{ MenuOption::NotificationSoundsSnapshot, true }; if (notificationSounds.get() && notificationSoundSnapshot.get()) { if (_snapshotSoundInjector) { - DependencyManager::get()->setOptionsAndRestart(_snapshotSoundInjector, - options); + DependencyManager::get()->setOptionsAndRestart(_snapshotSoundInjector, options); } else { - _snapshotSoundInjector = - DependencyManager::get()->playSound(_snapshotSound, options); + _snapshotSoundInjector = DependencyManager::get()->playSound(_snapshotSound, options); } } takeSnapshot(true); @@ -4338,7 +4366,7 @@ void Application::keyPressEvent(QKeyEvent* event) { } else { showCursor(Cursor::Icon::DEFAULT); } - } else if (!event->isAutoRepeat()) { + } else if (!event->isAutoRepeat()){ resetSensors(true); } break; @@ -4398,7 +4426,7 @@ void Application::keyReleaseEvent(QKeyEvent* event) { AndroidHelper::instance().requestActivity("Home", false); } #endif - _controllerScriptingInterface->emitKeyReleaseEvent(event); // send events to any registered scripts + _controllerScriptingInterface->emitKeyReleaseEvent(event); // send events to any registered scripts // if one of our scripts have asked to capture this event, then stop processing it if (_controllerScriptingInterface->isKeyCaptured(event)) { @@ -4408,25 +4436,16 @@ void Application::keyReleaseEvent(QKeyEvent* event) { if (_keyboardMouseDevice->isActive()) { _keyboardMouseDevice->keyReleaseEvent(event); } -} -void Application::focusInEvent(QFocusEvent* event) { - if (!_aboutToQuit && _startUpFinished) { - getRefreshRateManager().setRefreshRateRegime(RefreshRateManager::RefreshRateRegime::RUNNING); - } } void Application::focusOutEvent(QFocusEvent* event) { auto inputPlugins = PluginManager::getInstance()->getInputPlugins(); - foreach (auto inputPlugin, inputPlugins) { + foreach(auto inputPlugin, inputPlugins) { if (inputPlugin->isActive()) { inputPlugin->pluginFocusOutEvent(); } } - - if (!_aboutToQuit && _startUpFinished) { - getRefreshRateManager().setRefreshRateRegime(RefreshRateManager::RefreshRateRegime::UNFOCUS); - } // FIXME spacemouse code still needs cleanup #if 0 //SpacemouseDevice::getInstance().focusOutEvent(); @@ -4444,7 +4463,7 @@ void Application::synthesizeKeyReleasEvents() { QHash keysPressed; std::swap(keysPressed, _keysPressed); for (auto& ev : keysPressed) { - QKeyEvent synthesizedEvent{ QKeyEvent::KeyRelease, ev.key(), Qt::NoModifier, ev.text() }; + QKeyEvent synthesizedEvent { QKeyEvent::KeyRelease, ev.key(), Qt::NoModifier, ev.text() }; keyReleaseEvent(&synthesizedEvent); } } @@ -4461,7 +4480,7 @@ void Application::maybeToggleMenuVisible(QMouseEvent* event) const { if (event->pos().y() <= MENU_TOGGLE_AREA) { menuBar->setVisible(true); } - } else { + } else { if (event->pos().y() > MENU_TOGGLE_AREA) { menuBar->setVisible(false); } @@ -4481,7 +4500,7 @@ void Application::mouseMoveEvent(QMouseEvent* event) { // compositor reticle // handleRealMouseMoveEvent() will return true, if we shouldn't process the event further if (!compositor.fakeEventActive() && compositor.handleRealMouseMoveEvent()) { - return; // bail + return; // bail } #if !defined(DISABLE_QML) @@ -4501,14 +4520,17 @@ void Application::mouseMoveEvent(QMouseEvent* event) { buttons |= Qt::LeftButton; } - QMouseEvent mappedEvent(event->type(), transformedPos, event->screenPos(), button, buttons, event->modifiers()); + QMouseEvent mappedEvent(event->type(), + transformedPos, + event->screenPos(), button, + buttons, event->modifiers()); if (compositor.getReticleVisible() || !isHMDMode() || !compositor.getReticleOverDesktop() || getOverlays().getOverlayAtPoint(glm::vec2(transformedPos.x(), transformedPos.y())) != UNKNOWN_ENTITY_ID) { getEntities()->mouseMoveEvent(&mappedEvent); } - _controllerScriptingInterface->emitMouseMoveEvent(&mappedEvent); // send events to any registered scripts + _controllerScriptingInterface->emitMouseMoveEvent(&mappedEvent); // send events to any registered scripts // if one of our scripts have asked to capture this event, then stop processing it if (_controllerScriptingInterface->isMouseCaptured()) { @@ -4538,12 +4560,11 @@ void Application::mousePressEvent(QMouseEvent* event) { QPointF transformedPos; #endif - QMouseEvent mappedEvent(event->type(), transformedPos, event->screenPos(), event->button(), event->buttons(), - event->modifiers()); + QMouseEvent mappedEvent(event->type(), transformedPos, event->screenPos(), event->button(), event->buttons(), event->modifiers()); QUuid result = getEntities()->mousePressEvent(&mappedEvent); setKeyboardFocusEntity(getEntities()->wantsKeyboardFocus(result) ? result : UNKNOWN_ENTITY_ID); - _controllerScriptingInterface->emitMousePressEvent(&mappedEvent); // send events to any registered scripts + _controllerScriptingInterface->emitMousePressEvent(&mappedEvent); // send events to any registered scripts // if one of our scripts have asked to capture this event, then stop processing it if (_controllerScriptingInterface->isMouseCaptured()) { @@ -4576,8 +4597,10 @@ void Application::mouseDoublePressEvent(QMouseEvent* event) { #else QPointF transformedPos; #endif - QMouseEvent mappedEvent(event->type(), transformedPos, event->screenPos(), event->button(), event->buttons(), - event->modifiers()); + QMouseEvent mappedEvent(event->type(), + transformedPos, + event->screenPos(), event->button(), + event->buttons(), event->modifiers()); getEntities()->mouseDoublePressEvent(&mappedEvent); // if one of our scripts have asked to capture this event, then stop processing it @@ -4589,6 +4612,7 @@ void Application::mouseDoublePressEvent(QMouseEvent* event) { } void Application::mouseReleaseEvent(QMouseEvent* event) { + #if !defined(DISABLE_QML) auto offscreenUi = getOffscreenUI(); auto eventPosition = getApplicationCompositor().getMouseEventPosition(event); @@ -4596,12 +4620,14 @@ void Application::mouseReleaseEvent(QMouseEvent* event) { #else QPointF transformedPos; #endif - QMouseEvent mappedEvent(event->type(), transformedPos, event->screenPos(), event->button(), event->buttons(), - event->modifiers()); + QMouseEvent mappedEvent(event->type(), + transformedPos, + event->screenPos(), event->button(), + event->buttons(), event->modifiers()); getEntities()->mouseReleaseEvent(&mappedEvent); - _controllerScriptingInterface->emitMouseReleaseEvent(&mappedEvent); // send events to any registered scripts + _controllerScriptingInterface->emitMouseReleaseEvent(&mappedEvent); // send events to any registered scripts // if one of our scripts have asked to capture this event, then stop processing it if (_controllerScriptingInterface->isMouseCaptured()) { @@ -4620,7 +4646,7 @@ void Application::touchUpdateEvent(QTouchEvent* event) { if (event->type() == QEvent::TouchUpdate) { TouchEvent thisEvent(*event, _lastTouchEvent); - _controllerScriptingInterface->emitTouchUpdateEvent(thisEvent); // send events to any registered scripts + _controllerScriptingInterface->emitTouchUpdateEvent(thisEvent); // send events to any registered scripts _lastTouchEvent = thisEvent; } @@ -4642,10 +4668,10 @@ void Application::touchUpdateEvent(QTouchEvent* event) { void Application::touchBeginEvent(QTouchEvent* event) { _altPressed = false; - TouchEvent thisEvent(*event); // on touch begin, we don't compare to last event - _controllerScriptingInterface->emitTouchBeginEvent(thisEvent); // send events to any registered scripts + TouchEvent thisEvent(*event); // on touch begin, we don't compare to last event + _controllerScriptingInterface->emitTouchBeginEvent(thisEvent); // send events to any registered scripts - _lastTouchEvent = thisEvent; // and we reset our last event to this event before we call our update + _lastTouchEvent = thisEvent; // and we reset our last event to this event before we call our update touchUpdateEvent(event); // if one of our scripts have asked to capture this event, then stop processing it @@ -4662,12 +4688,13 @@ void Application::touchBeginEvent(QTouchEvent* event) { if (_touchscreenVirtualPadDevice && _touchscreenVirtualPadDevice->isActive()) { _touchscreenVirtualPadDevice->touchBeginEvent(event); } + } void Application::touchEndEvent(QTouchEvent* event) { _altPressed = false; TouchEvent thisEvent(*event, _lastTouchEvent); - _controllerScriptingInterface->emitTouchEndEvent(thisEvent); // send events to any registered scripts + _controllerScriptingInterface->emitTouchEndEvent(thisEvent); // send events to any registered scripts _lastTouchEvent = thisEvent; // if one of our scripts have asked to capture this event, then stop processing it @@ -4698,7 +4725,7 @@ void Application::touchGestureEvent(QGestureEvent* event) { void Application::wheelEvent(QWheelEvent* event) const { _altPressed = false; - _controllerScriptingInterface->emitWheelEvent(event); // send events to any registered scripts + _controllerScriptingInterface->emitWheelEvent(event); // send events to any registered scripts // if one of our scripts have asked to capture this event, then stop processing it if (_controllerScriptingInterface->isWheelCaptured() || getLoginDialogPoppedUp()) { @@ -4710,7 +4737,7 @@ void Application::wheelEvent(QWheelEvent* event) const { } } -void Application::dropEvent(QDropEvent* event) { +void Application::dropEvent(QDropEvent *event) { const QMimeData* mimeData = event->mimeData(); for (auto& url : mimeData->urls()) { QString urlString = url.toString(); @@ -4736,8 +4763,8 @@ bool Application::acceptSnapshot(const QString& urlString) { DependencyManager::get()->handleLookupString(snapshotData->getURL().toString()); } } else { - OffscreenUi::asyncWarning("", "No location details were found in the file\n" + snapshotPath + - "\nTry dragging in an authentic Hifi snapshot."); + OffscreenUi::asyncWarning("", "No location details were found in the file\n" + + snapshotPath + "\nTry dragging in an authentic Hifi snapshot."); } return true; } @@ -4750,39 +4777,41 @@ bool Application::acceptSnapshot(const QString& urlString) { #pragma comment(lib, "ntdll.lib") extern "C" { -enum SYSTEM_INFORMATION_CLASS -{ - SystemBasicInformation = 0, - SystemProcessorPerformanceInformation = 8, -}; + enum SYSTEM_INFORMATION_CLASS { + SystemBasicInformation = 0, + SystemProcessorPerformanceInformation = 8, + }; -struct SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION { - LARGE_INTEGER IdleTime; - LARGE_INTEGER KernelTime; - LARGE_INTEGER UserTime; - LARGE_INTEGER DpcTime; - LARGE_INTEGER InterruptTime; - ULONG InterruptCount; -}; + struct SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION { + LARGE_INTEGER IdleTime; + LARGE_INTEGER KernelTime; + LARGE_INTEGER UserTime; + LARGE_INTEGER DpcTime; + LARGE_INTEGER InterruptTime; + ULONG InterruptCount; + }; -struct SYSTEM_BASIC_INFORMATION { - ULONG Reserved; - ULONG TimerResolution; - ULONG PageSize; - ULONG NumberOfPhysicalPages; - ULONG LowestPhysicalPageNumber; - ULONG HighestPhysicalPageNumber; - ULONG AllocationGranularity; - ULONG_PTR MinimumUserModeAddress; - ULONG_PTR MaximumUserModeAddress; - ULONG_PTR ActiveProcessorsAffinityMask; - CCHAR NumberOfProcessors; -}; + struct SYSTEM_BASIC_INFORMATION { + ULONG Reserved; + ULONG TimerResolution; + ULONG PageSize; + ULONG NumberOfPhysicalPages; + ULONG LowestPhysicalPageNumber; + ULONG HighestPhysicalPageNumber; + ULONG AllocationGranularity; + ULONG_PTR MinimumUserModeAddress; + ULONG_PTR MaximumUserModeAddress; + ULONG_PTR ActiveProcessorsAffinityMask; + CCHAR NumberOfProcessors; + }; + + NTSYSCALLAPI NTSTATUS NTAPI NtQuerySystemInformation( + _In_ SYSTEM_INFORMATION_CLASS SystemInformationClass, + _Out_writes_bytes_opt_(SystemInformationLength) PVOID SystemInformation, + _In_ ULONG SystemInformationLength, + _Out_opt_ PULONG ReturnLength + ); -NTSYSCALLAPI NTSTATUS NTAPI NtQuerySystemInformation(_In_ SYSTEM_INFORMATION_CLASS SystemInformationClass, - _Out_writes_bytes_opt_(SystemInformationLength) PVOID SystemInformation, - _In_ ULONG SystemInformationLength, - _Out_opt_ PULONG ReturnLength); } template NTSTATUS NtQuerySystemInformation(SYSTEM_INFORMATION_CLASS SystemInformationClass, T& t) { @@ -4794,6 +4823,7 @@ NTSTATUS NtQuerySystemInformation(SYSTEM_INFORMATION_CLASS SystemInformationClas return NtQuerySystemInformation(SystemInformationClass, t.data(), (ULONG)(sizeof(T) * t.size()), nullptr); } + template void updateValueAndDelta(std::pair& pair, T newValue) { auto& value = pair.first; @@ -4805,11 +4835,11 @@ void updateValueAndDelta(std::pair& pair, T newValue) { struct MyCpuInfo { using ValueAndDelta = std::pair; std::string name; - ValueAndDelta kernel{ 0, 0 }; - ValueAndDelta user{ 0, 0 }; - ValueAndDelta idle{ 0, 0 }; - float kernelUsage{ 0.0f }; - float userUsage{ 0.0f }; + ValueAndDelta kernel { 0, 0 }; + ValueAndDelta user { 0, 0 }; + ValueAndDelta idle { 0, 0 }; + float kernelUsage { 0.0f }; + float userUsage { 0.0f }; void update(const SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION& cpuInfo) { updateValueAndDelta(kernel, cpuInfo.KernelTime.QuadPart); @@ -4827,13 +4857,13 @@ struct MyCpuInfo { void updateCpuInformation() { static std::once_flag once; - static SYSTEM_BASIC_INFORMATION systemInfo{}; + static SYSTEM_BASIC_INFORMATION systemInfo {}; static SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION cpuTotals; static std::vector cpuInfos; static std::vector myCpuInfos; static MyCpuInfo myCpuTotals; std::call_once(once, [&] { - NtQuerySystemInformation(SystemBasicInformation, systemInfo); + NtQuerySystemInformation( SystemBasicInformation, systemInfo); cpuInfos.resize(systemInfo.NumberOfProcessors); myCpuInfos.resize(systemInfo.NumberOfProcessors); for (size_t i = 0; i < systemInfo.NumberOfProcessors; ++i) { @@ -4858,14 +4888,20 @@ void updateCpuInformation() { // Update friendly structure auto& myCpuInfo = myCpuInfos[i]; myCpuInfo.update(cpuInfo); - PROFILE_COUNTER(app, myCpuInfo.name.c_str(), { { "kernel", myCpuInfo.kernelUsage }, { "user", myCpuInfo.userUsage } }); + PROFILE_COUNTER(app, myCpuInfo.name.c_str(), { + { "kernel", myCpuInfo.kernelUsage }, + { "user", myCpuInfo.userUsage } + }); } myCpuTotals.update(cpuTotals); - PROFILE_COUNTER(app, myCpuTotals.name.c_str(), - { { "kernel", myCpuTotals.kernelUsage }, { "user", myCpuTotals.userUsage } }); + PROFILE_COUNTER(app, myCpuTotals.name.c_str(), { + { "kernel", myCpuTotals.kernelUsage }, + { "user", myCpuTotals.userUsage } + }); } + static ULARGE_INTEGER lastCPU, lastSysCPU, lastUserCPU; static int numProcessors; static HANDLE self; @@ -4989,10 +5025,8 @@ void Application::idle() { PROFILE_COUNTER_IF_CHANGED(app, "renderLoopRate", float, getRenderLoopRate()); PROFILE_COUNTER_IF_CHANGED(app, "currentDownloads", uint32_t, ResourceCache::getLoadingRequests().length()); PROFILE_COUNTER_IF_CHANGED(app, "pendingDownloads", uint32_t, ResourceCache::getPendingRequestCount()); - PROFILE_COUNTER_IF_CHANGED(app, "currentProcessing", int, - DependencyManager::get()->getStat("Processing").toInt()); - PROFILE_COUNTER_IF_CHANGED(app, "pendingProcessing", int, - DependencyManager::get()->getStat("PendingProcessing").toInt()); + PROFILE_COUNTER_IF_CHANGED(app, "currentProcessing", int, DependencyManager::get()->getStat("Processing").toInt()); + PROFILE_COUNTER_IF_CHANGED(app, "pendingProcessing", int, DependencyManager::get()->getStat("PendingProcessing").toInt()); auto renderConfig = _graphicsEngine.getRenderEngine()->getConfiguration(); PROFILE_COUNTER_IF_CHANGED(render, "gpuTime", float, (float)_graphicsEngine.getGPUContext()->getFrameTimerGPUAverage()); @@ -5022,7 +5056,7 @@ void Application::idle() { } } #endif - + checkChangeCursor(); #if !defined(DISABLE_QML) @@ -5057,9 +5091,9 @@ void Application::idle() { update(glm::clamp(secondsSinceLastUpdate, 0.0f, BIGGEST_DELTA_TIME_SECS)); } - { // Update keyboard focus highlight + { // Update keyboard focus highlight if (!_keyboardFocusedEntity.get().isInvalidID()) { - const quint64 LOSE_FOCUS_AFTER_ELAPSED_TIME = 30 * USECS_PER_SECOND; // if idle for 30 seconds, drop focus + const quint64 LOSE_FOCUS_AFTER_ELAPSED_TIME = 30 * USECS_PER_SECOND; // if idle for 30 seconds, drop focus quint64 elapsedSinceAcceptedKeyPress = usecTimestampNow() - _lastAcceptedKeyPress; if (elapsedSinceAcceptedKeyPress > LOSE_FOCUS_AFTER_ELAPSED_TIME) { setKeyboardFocusEntity(UNKNOWN_ENTITY_ID); @@ -5089,7 +5123,7 @@ void Application::idle() { PerformanceWarning warn(showWarnings, "Application::idle()... pluginIdle()"); getActiveDisplayPlugin()->idle(); auto inputPlugins = PluginManager::getInstance()->getInputPlugins(); - foreach (auto inputPlugin, inputPlugins) { + foreach(auto inputPlugin, inputPlugins) { if (inputPlugin->isActive()) { inputPlugin->idle(); } @@ -5177,7 +5211,9 @@ void Application::calibrateEyeTracker5Points() { } #endif -bool Application::exportEntities(const QString& filename, const QVector& entityIDs, const glm::vec3* givenOffset) { +bool Application::exportEntities(const QString& filename, + const QVector& entityIDs, + const glm::vec3* givenOffset) { QHash entities; auto nodeList = DependencyManager::get(); @@ -5190,7 +5226,7 @@ bool Application::exportEntities(const QString& filename, const QVector& glm::vec3 root(TREE_SCALE, TREE_SCALE, TREE_SCALE); bool success = true; entityTree->withReadLock([entityIDs, entityTree, givenOffset, myAvatarID, &root, &entities, &success, &exportTree] { - for (auto entityID : entityIDs) { // Gather entities and properties. + for (auto entityID : entityIDs) { // Gather entities and properties. auto entityItem = entityTree->findEntityByEntityItemID(entityID); if (!entityItem) { qCWarning(interfaceapp) << "Skipping export of" << entityID << "that is not in scene."; @@ -5200,7 +5236,8 @@ bool Application::exportEntities(const QString& filename, const QVector& if (!givenOffset) { EntityItemID parentID = entityItem->getParentID(); bool parentIsAvatar = (parentID == AVATAR_SELF_ID || parentID == myAvatarID); - if (!parentIsAvatar && (parentID.isInvalidID() || !entityIDs.contains(parentID) || + if (!parentIsAvatar && (parentID.isInvalidID() || + !entityIDs.contains(parentID) || !entityTree->findEntityByEntityItemID(parentID))) { // If parent wasn't selected, we want absolute position, which isn't in properties. auto position = entityItem->getWorldPosition(); @@ -5231,7 +5268,7 @@ bool Application::exportEntities(const QString& filename, const QVector& properties.setPosition(properties.getPosition() - root); } else if (!entities.contains(parentID)) { entityDatum->globalizeProperties(properties, "Parent %3 of %2 %1 is not selected for export.", -root); - } // else valid parent -- don't offset + } // else valid parent -- don't offset } exportTree->addEntity(entityDatum->getEntityItemID(), properties); } @@ -5252,12 +5289,15 @@ bool Application::exportEntities(const QString& filename, float x, float y, floa AACube boundingCube(minCorner, cubeSize); QVector entities; auto entityTree = getEntities()->getTree(); - entityTree->withReadLock([&] { entityTree->evalEntitiesInCube(boundingCube, PickFilter(), entities); }); + entityTree->withReadLock([&] { + entityTree->evalEntitiesInCube(boundingCube, PickFilter(), entities); + }); return exportEntities(filename, entities, ¢er); } void Application::loadSettings() { - sessionRunTime.set(0); // Just clean living. We're about to saveSettings, which will update value. + + sessionRunTime.set(0); // Just clean living. We're about to saveSettings, which will update value. DependencyManager::get()->loadSettings(); DependencyManager::get()->loadSettings(); @@ -5327,9 +5367,10 @@ void Application::loadSettings() { } } - auto audioScriptingInterface = - reinterpret_cast(DependencyManager::get().data()); - audioScriptingInterface->loadData(); + QSharedPointer audioScriptingInterface = qSharedPointerDynamicCast(DependencyManager::get()); + if (audioScriptingInterface) { + audioScriptingInterface->loadData(); + } getMyAvatar()->loadData(); _settingsLoaded = true; @@ -5340,9 +5381,10 @@ void Application::saveSettings() const { DependencyManager::get()->saveSettings(); DependencyManager::get()->saveSettings(); - auto audioScriptingInterface = - reinterpret_cast(DependencyManager::get().data()); - audioScriptingInterface->saveData(); + QSharedPointer audioScriptingInterface = qSharedPointerDynamicCast(DependencyManager::get()); + if (audioScriptingInterface) { + audioScriptingInterface->saveData(); + } Menu::getInstance()->saveSettings(); getMyAvatar()->saveData(); @@ -5386,6 +5428,7 @@ void Application::init() { } } + qCDebug(interfaceapp) << "Loaded settings"; // fire off an immediate domain-server check in now that settings are loaded @@ -5420,27 +5463,23 @@ void Application::init() { auto entityScriptingInterface = DependencyManager::get(); // connect the _entityCollisionSystem to our EntityTreeRenderer since that's what handles running entity scripts - connect(_entitySimulation.get(), &PhysicalEntitySimulation::entityCollisionWithEntity, getEntities().data(), - &EntityTreeRenderer::entityCollisionWithEntity); + connect(_entitySimulation.get(), &PhysicalEntitySimulation::entityCollisionWithEntity, + getEntities().data(), &EntityTreeRenderer::entityCollisionWithEntity); // connect the _entities (EntityTreeRenderer) to our script engine's EntityScriptingInterface for firing // of events related clicking, hovering over, and entering entities getEntities()->connectSignalsToSlots(entityScriptingInterface.data()); // Make sure any new sounds are loaded as soon as know about them. - connect(tree.get(), &EntityTree::newCollisionSoundURL, this, - [this](QUrl newURL, EntityItemID id) { - getEntities()->setCollisionSound(id, DependencyManager::get()->getSound(newURL)); - }, - Qt::QueuedConnection); - connect(getMyAvatar().get(), &MyAvatar::newCollisionSoundURL, this, - [this](QUrl newURL) { - if (auto avatar = getMyAvatar()) { - auto sound = DependencyManager::get()->getSound(newURL); - avatar->setCollisionSound(sound); - } - }, - Qt::QueuedConnection); + connect(tree.get(), &EntityTree::newCollisionSoundURL, this, [this](QUrl newURL, EntityItemID id) { + getEntities()->setCollisionSound(id, DependencyManager::get()->getSound(newURL)); + }, Qt::QueuedConnection); + connect(getMyAvatar().get(), &MyAvatar::newCollisionSoundURL, this, [this](QUrl newURL) { + if (auto avatar = getMyAvatar()) { + auto sound = DependencyManager::get()->getSound(newURL); + avatar->setCollisionSound(sound); + } + }, Qt::QueuedConnection); _gameWorkload.startup(getEntities()->getWorkloadSpace(), _graphicsEngine.getRenderScene(), _entitySimulation); _entitySimulation->setWorkloadSpace(getEntities()->getWorkloadSpace()); @@ -5511,8 +5550,7 @@ void Application::resumeAfterLoginDialogActionTaken() { } if (!isHMDMode() && getDesktopTabletBecomesToolbarSetting()) { - auto toolbar = - DependencyManager::get()->getToolbar("com.highfidelity.interface.toolbar.system"); + auto toolbar = DependencyManager::get()->getToolbar("com.highfidelity.interface.toolbar.system"); toolbar->writeProperty("visible", true); } else { getApplicationCompositor().getReticleInterface()->setAllowMouseCapture(true); @@ -5580,7 +5618,7 @@ void Application::resumeAfterLoginDialogActionTaken() { _myCamera.setMode(_previousCameraMode); cameraModeChanged(); _startUpFinished = true; - getRefreshRateManager().setRefreshRateRegime(RefreshRateManager::RefreshRateRegime::RUNNING); + getRefreshRateManager().setRefreshRateRegime(RefreshRateManager::RefreshRateRegime::FOCUS_ACTIVE); } void Application::loadAvatarScripts(const QVector& urls) { @@ -5658,8 +5696,8 @@ void Application::updateMyAvatarLookAtPosition() { glm::quat hmdRotation = glm::quat_cast(headPose); lookAtSpot = _myCamera.getPosition() + myAvatar->getWorldOrientation() * (hmdRotation * lookAtPosition); } else { - lookAtSpot = myAvatar->getHead()->getEyePosition() + - (myAvatar->getHead()->getFinalOrientationInWorldFrame() * lookAtPosition); + lookAtSpot = myAvatar->getHead()->getEyePosition() + + (myAvatar->getHead()->getFinalOrientationInWorldFrame() * lookAtPosition); } } else { AvatarSharedPointer lookingAt = myAvatar->getLookAtTargetAvatar().lock(); @@ -5673,14 +5711,14 @@ void Application::updateMyAvatarLookAtPosition() { const float MAXIMUM_FACE_ANGLE = 65.0f * RADIANS_PER_DEGREE; glm::vec3 lookingAtFaceOrientation = lookingAtHead->getFinalOrientationInWorldFrame() * IDENTITY_FORWARD; - glm::vec3 fromLookingAtToMe = - glm::normalize(myAvatar->getHead()->getEyePosition() - lookingAtHead->getEyePosition()); + glm::vec3 fromLookingAtToMe = glm::normalize(myAvatar->getHead()->getEyePosition() + - lookingAtHead->getEyePosition()); float faceAngle = glm::angle(lookingAtFaceOrientation, fromLookingAtToMe); if (faceAngle < MAXIMUM_FACE_ANGLE) { // Randomly look back and forth between look targets - eyeContactTarget target = - Menu::getInstance()->isOptionChecked(MenuOption::FixGaze) ? LEFT_EYE : myAvatar->getEyeContactTarget(); + eyeContactTarget target = Menu::getInstance()->isOptionChecked(MenuOption::FixGaze) ? + LEFT_EYE : myAvatar->getEyeContactTarget(); switch (target) { case LEFT_EYE: lookAtSpot = lookingAtHead->getLeftEyePosition(); @@ -5703,7 +5741,7 @@ void Application::updateMyAvatarLookAtPosition() { lookAtSpot = transformPoint(headPose.getMatrix(), glm::vec3(0.0f, 0.0f, TREE_SCALE)); } else { lookAtSpot = myAvatar->getHead()->getEyePosition() + - (myAvatar->getHead()->getFinalOrientationInWorldFrame() * glm::vec3(0.0f, 0.0f, -TREE_SCALE)); + (myAvatar->getHead()->getFinalOrientationInWorldFrame() * glm::vec3(0.0f, 0.0f, -TREE_SCALE)); } } @@ -5717,9 +5755,9 @@ void Application::updateMyAvatarLookAtPosition() { if (isLookingAtSomeone) { deflection *= GAZE_DEFLECTION_REDUCTION_DURING_EYE_CONTACT; } - lookAtSpot = origin + _myCamera.getOrientation() * - glm::quat(glm::radians(glm::vec3(eyePitch * deflection, eyeYaw * deflection, 0.0f))) * - glm::inverse(_myCamera.getOrientation()) * (lookAtSpot - origin); + lookAtSpot = origin + _myCamera.getOrientation() * glm::quat(glm::radians(glm::vec3( + eyePitch * deflection, eyeYaw * deflection, 0.0f))) * + glm::inverse(_myCamera.getOrientation()) * (lookAtSpot - origin); } } @@ -5755,18 +5793,22 @@ void Application::centerUI() { void Application::cycleCamera() { auto menu = Menu::getInstance(); if (menu->isOptionChecked(MenuOption::FullscreenMirror)) { + menu->setIsOptionChecked(MenuOption::FullscreenMirror, false); menu->setIsOptionChecked(MenuOption::FirstPerson, true); } else if (menu->isOptionChecked(MenuOption::FirstPerson)) { + menu->setIsOptionChecked(MenuOption::FirstPerson, false); menu->setIsOptionChecked(MenuOption::ThirdPerson, true); } else if (menu->isOptionChecked(MenuOption::ThirdPerson)) { + menu->setIsOptionChecked(MenuOption::ThirdPerson, false); menu->setIsOptionChecked(MenuOption::FullscreenMirror, true); + } - cameraMenuChanged(); // handle the menu change + cameraMenuChanged(); // handle the menu change } void Application::cameraModeChanged() { @@ -5808,7 +5850,7 @@ void Application::cameraMenuChanged() { if (!isHMDMode() && _myCamera.getMode() != CAMERA_MODE_MIRROR) { _mirrorYawOffset = 0.0f; _myCamera.setMode(CAMERA_MODE_MIRROR); - getMyAvatar()->reset(false, false, false); // to reset any active MyAvatar::FollowHelpers + getMyAvatar()->reset(false, false, false); // to reset any active MyAvatar::FollowHelpers getMyAvatar()->setBoomLength(MyAvatar::ZOOM_DEFAULT); } } else if (menu->isOptionChecked(MenuOption::FirstPerson)) { @@ -5837,6 +5879,7 @@ void Application::resetPhysicsReadyInformation() { _octreeProcessor.startEntitySequence(); } + void Application::reloadResourceCaches() { resetPhysicsReadyInformation(); @@ -5946,7 +5989,7 @@ void Application::setKeyboardFocusEntity(const QUuid& id) { if (properties.getShowKeyboardFocusHighlight()) { if (auto entity = entities->getEntity(entityId)) { setKeyboardFocusHighlight(entity->getWorldPosition(), entity->getWorldOrientation(), - entity->getScaledDimensions() * FOCUS_HIGHLIGHT_EXPANSION_FACTOR); + entity->getScaledDimensions() * FOCUS_HIGHLIGHT_EXPANSION_FACTOR); return; } } @@ -6010,8 +6053,8 @@ void Application::updateSecondaryCameraViewFrustum() { glm::vec3 mainCameraPositionWorld = getCamera().getPosition(); glm::vec3 mainCameraPositionPortalEntrance = vec3(portalEntranceFromWorld * vec4(mainCameraPositionWorld, 1.0f)); - mainCameraPositionPortalEntrance = - vec3(-mainCameraPositionPortalEntrance.x, mainCameraPositionPortalEntrance.y, -mainCameraPositionPortalEntrance.z); + mainCameraPositionPortalEntrance = vec3(-mainCameraPositionPortalEntrance.x, mainCameraPositionPortalEntrance.y, + -mainCameraPositionPortalEntrance.z); glm::vec3 portalExitCameraPositionWorld = vec3(worldFromPortalExit * vec4(mainCameraPositionPortalEntrance, 1.0f)); secondaryViewFrustum.setPosition(portalExitCameraPositionWorld); @@ -6022,8 +6065,7 @@ void Application::updateSecondaryCameraViewFrustum() { // but the values are the same. glm::vec3 upperRight = halfPortalExitPropertiesDimensions - mainCameraPositionPortalEntrance; glm::vec3 bottomLeft = -halfPortalExitPropertiesDimensions - mainCameraPositionPortalEntrance; - glm::mat4 frustum = - glm::frustum(bottomLeft.x, upperRight.x, bottomLeft.y, upperRight.y, nearClip, camera->farClipPlaneDistance); + glm::mat4 frustum = glm::frustum(bottomLeft.x, upperRight.x, bottomLeft.y, upperRight.y, nearClip, camera->farClipPlaneDistance); secondaryViewFrustum.setProjection(frustum); } else if (camera->mirrorProjection && !camera->attachedEntityId.isNull()) { auto entityScriptingInterface = DependencyManager::get(); @@ -6043,8 +6085,8 @@ void Application::updateSecondaryCameraViewFrustum() { // get mirror camera position by reflecting main camera position's z coordinate in mirror space glm::vec3 mainCameraPositionWorld = getCamera().getPosition(); glm::vec3 mainCameraPositionMirror = vec3(mirrorFromWorld * vec4(mainCameraPositionWorld, 1.0f)); - glm::vec3 mirrorCameraPositionMirror = - vec3(mainCameraPositionMirror.x, mainCameraPositionMirror.y, -mainCameraPositionMirror.z); + glm::vec3 mirrorCameraPositionMirror = vec3(mainCameraPositionMirror.x, mainCameraPositionMirror.y, + -mainCameraPositionMirror.z); glm::vec3 mirrorCameraPositionWorld = vec3(worldFromMirror * vec4(mirrorCameraPositionMirror, 1.0f)); // set frustum position to be mirrored camera and set orientation to mirror's adjusted rotation @@ -6056,8 +6098,7 @@ void Application::updateSecondaryCameraViewFrustum() { float nearClip = mirrorCameraPositionMirror.z + mirrorPropertiesDimensions.z * 2.0f; glm::vec3 upperRight = halfMirrorPropertiesDimensions - mirrorCameraPositionMirror; glm::vec3 bottomLeft = -halfMirrorPropertiesDimensions - mirrorCameraPositionMirror; - glm::mat4 frustum = - glm::frustum(bottomLeft.x, upperRight.x, bottomLeft.y, upperRight.y, nearClip, camera->farClipPlaneDistance); + glm::mat4 frustum = glm::frustum(bottomLeft.x, upperRight.x, bottomLeft.y, upperRight.y, nearClip, camera->farClipPlaneDistance); secondaryViewFrustum.setProjection(frustum); } else { if (!camera->attachedEntityId.isNull()) { @@ -6071,8 +6112,10 @@ void Application::updateSecondaryCameraViewFrustum() { } float aspectRatio = (float)camera->textureWidth / (float)camera->textureHeight; - secondaryViewFrustum.setProjection(camera->vFoV, aspectRatio, camera->nearClipPlaneDistance, - camera->farClipPlaneDistance); + secondaryViewFrustum.setProjection(camera->vFoV, + aspectRatio, + camera->nearClipPlaneDistance, + camera->farClipPlaneDistance); } // Without calculating the bound planes, the secondary camera will use the same culling frustum as the main camera, // which is not what we want here. @@ -6090,6 +6133,7 @@ void Application::update(float deltaTime) { return; } + if (!_physicsEnabled) { if (!domainLoadingInProgress) { PROFILE_ASYNC_BEGIN(app, "Scene Loading", ""); @@ -6144,8 +6188,8 @@ void Application::update(float deltaTime) { Menu* menu = Menu::getInstance(); auto audioClient = DependencyManager::get(); if (menu->isOptionChecked(MenuOption::AutoMuteAudio) && !audioClient->isMuted()) { - if (_lastFaceTrackerUpdate > 0 && - ((usecTimestampNow() - _lastFaceTrackerUpdate) > MUTE_MICROPHONE_AFTER_USECS)) { + if (_lastFaceTrackerUpdate > 0 + && ((usecTimestampNow() - _lastFaceTrackerUpdate) > MUTE_MICROPHONE_AFTER_USECS)) { audioClient->setMuted(true); _lastFaceTrackerUpdate = 0; } @@ -6166,21 +6210,22 @@ void Application::update(float deltaTime) { hmdAvatarAlignmentType = controller::HmdAvatarAlignmentType::Head; } - controller::InputCalibrationData calibrationData = - { myAvatar->getSensorToWorldMatrix(), - createMatFromQuatAndPos(myAvatar->getWorldOrientation(), myAvatar->getWorldPosition()), - myAvatar->getHMDSensorMatrix(), - myAvatar->getCenterEyeCalibrationMat(), - myAvatar->getHeadCalibrationMat(), - myAvatar->getSpine2CalibrationMat(), - myAvatar->getHipsCalibrationMat(), - myAvatar->getLeftFootCalibrationMat(), - myAvatar->getRightFootCalibrationMat(), - myAvatar->getRightArmCalibrationMat(), - myAvatar->getLeftArmCalibrationMat(), - myAvatar->getRightHandCalibrationMat(), - myAvatar->getLeftHandCalibrationMat(), - hmdAvatarAlignmentType }; + controller::InputCalibrationData calibrationData = { + myAvatar->getSensorToWorldMatrix(), + createMatFromQuatAndPos(myAvatar->getWorldOrientation(), myAvatar->getWorldPosition()), + myAvatar->getHMDSensorMatrix(), + myAvatar->getCenterEyeCalibrationMat(), + myAvatar->getHeadCalibrationMat(), + myAvatar->getSpine2CalibrationMat(), + myAvatar->getHipsCalibrationMat(), + myAvatar->getLeftFootCalibrationMat(), + myAvatar->getRightFootCalibrationMat(), + myAvatar->getRightArmCalibrationMat(), + myAvatar->getLeftArmCalibrationMat(), + myAvatar->getRightHandCalibrationMat(), + myAvatar->getLeftHandCalibrationMat(), + hmdAvatarAlignmentType + }; InputPluginPointer keyboardMousePlugin; for (auto inputPlugin : PluginManager::getInstance()->getInputPlugins()) { @@ -6202,84 +6247,82 @@ void Application::update(float deltaTime) { myAvatar->clearDriveKeys(); if (_myCamera.getMode() != CAMERA_MODE_INDEPENDENT && !isInterstitialMode()) { if (!_controllerScriptingInterface->areActionsCaptured() && _myCamera.getMode() != CAMERA_MODE_MIRROR) { - myAvatar->setDriveKey(MyAvatar::TRANSLATE_Z, - -1.0f * userInputMapper->getActionState(controller::Action::TRANSLATE_Z)); + myAvatar->setDriveKey(MyAvatar::TRANSLATE_Z, -1.0f * userInputMapper->getActionState(controller::Action::TRANSLATE_Z)); myAvatar->setDriveKey(MyAvatar::TRANSLATE_Y, userInputMapper->getActionState(controller::Action::TRANSLATE_Y)); myAvatar->setDriveKey(MyAvatar::TRANSLATE_X, userInputMapper->getActionState(controller::Action::TRANSLATE_X)); if (deltaTime > FLT_EPSILON) { myAvatar->setDriveKey(MyAvatar::PITCH, -1.0f * userInputMapper->getActionState(controller::Action::PITCH)); myAvatar->setDriveKey(MyAvatar::YAW, -1.0f * userInputMapper->getActionState(controller::Action::YAW)); - myAvatar->setDriveKey(MyAvatar::DELTA_PITCH, - -1.0f * userInputMapper->getActionState(controller::Action::DELTA_PITCH)); - myAvatar->setDriveKey(MyAvatar::DELTA_YAW, - -1.0f * userInputMapper->getActionState(controller::Action::DELTA_YAW)); - myAvatar->setDriveKey(MyAvatar::STEP_YAW, - -1.0f * userInputMapper->getActionState(controller::Action::STEP_YAW)); + myAvatar->setDriveKey(MyAvatar::DELTA_PITCH, -1.0f * userInputMapper->getActionState(controller::Action::DELTA_PITCH)); + myAvatar->setDriveKey(MyAvatar::DELTA_YAW, -1.0f * userInputMapper->getActionState(controller::Action::DELTA_YAW)); + myAvatar->setDriveKey(MyAvatar::STEP_YAW, -1.0f * userInputMapper->getActionState(controller::Action::STEP_YAW)); } } myAvatar->setDriveKey(MyAvatar::ZOOM, userInputMapper->getActionState(controller::Action::TRANSLATE_CAMERA_Z)); } myAvatar->setSprintMode((bool)userInputMapper->getActionState(controller::Action::SPRINT)); - static const std::vector avatarControllerActions = { controller::Action::LEFT_HAND, - controller::Action::RIGHT_HAND, - controller::Action::LEFT_FOOT, - controller::Action::RIGHT_FOOT, - controller::Action::HIPS, - controller::Action::SPINE2, - controller::Action::HEAD, - controller::Action::LEFT_HAND_THUMB1, - controller::Action::LEFT_HAND_THUMB2, - controller::Action::LEFT_HAND_THUMB3, - controller::Action::LEFT_HAND_THUMB4, - controller::Action::LEFT_HAND_INDEX1, - controller::Action::LEFT_HAND_INDEX2, - controller::Action::LEFT_HAND_INDEX3, - controller::Action::LEFT_HAND_INDEX4, - controller::Action::LEFT_HAND_MIDDLE1, - controller::Action::LEFT_HAND_MIDDLE2, - controller::Action::LEFT_HAND_MIDDLE3, - controller::Action::LEFT_HAND_MIDDLE4, - controller::Action::LEFT_HAND_RING1, - controller::Action::LEFT_HAND_RING2, - controller::Action::LEFT_HAND_RING3, - controller::Action::LEFT_HAND_RING4, - controller::Action::LEFT_HAND_PINKY1, - controller::Action::LEFT_HAND_PINKY2, - controller::Action::LEFT_HAND_PINKY3, - controller::Action::LEFT_HAND_PINKY4, - controller::Action::RIGHT_HAND_THUMB1, - controller::Action::RIGHT_HAND_THUMB2, - controller::Action::RIGHT_HAND_THUMB3, - controller::Action::RIGHT_HAND_THUMB4, - controller::Action::RIGHT_HAND_INDEX1, - controller::Action::RIGHT_HAND_INDEX2, - controller::Action::RIGHT_HAND_INDEX3, - controller::Action::RIGHT_HAND_INDEX4, - controller::Action::RIGHT_HAND_MIDDLE1, - controller::Action::RIGHT_HAND_MIDDLE2, - controller::Action::RIGHT_HAND_MIDDLE3, - controller::Action::RIGHT_HAND_MIDDLE4, - controller::Action::RIGHT_HAND_RING1, - controller::Action::RIGHT_HAND_RING2, - controller::Action::RIGHT_HAND_RING3, - controller::Action::RIGHT_HAND_RING4, - controller::Action::RIGHT_HAND_PINKY1, - controller::Action::RIGHT_HAND_PINKY2, - controller::Action::RIGHT_HAND_PINKY3, - controller::Action::RIGHT_HAND_PINKY4, - controller::Action::LEFT_ARM, - controller::Action::RIGHT_ARM, - controller::Action::LEFT_SHOULDER, - controller::Action::RIGHT_SHOULDER, - controller::Action::LEFT_FORE_ARM, - controller::Action::RIGHT_FORE_ARM, - controller::Action::LEFT_LEG, - controller::Action::RIGHT_LEG, - controller::Action::LEFT_UP_LEG, - controller::Action::RIGHT_UP_LEG, - controller::Action::LEFT_TOE_BASE, - controller::Action::RIGHT_TOE_BASE }; + static const std::vector avatarControllerActions = { + controller::Action::LEFT_HAND, + controller::Action::RIGHT_HAND, + controller::Action::LEFT_FOOT, + controller::Action::RIGHT_FOOT, + controller::Action::HIPS, + controller::Action::SPINE2, + controller::Action::HEAD, + controller::Action::LEFT_HAND_THUMB1, + controller::Action::LEFT_HAND_THUMB2, + controller::Action::LEFT_HAND_THUMB3, + controller::Action::LEFT_HAND_THUMB4, + controller::Action::LEFT_HAND_INDEX1, + controller::Action::LEFT_HAND_INDEX2, + controller::Action::LEFT_HAND_INDEX3, + controller::Action::LEFT_HAND_INDEX4, + controller::Action::LEFT_HAND_MIDDLE1, + controller::Action::LEFT_HAND_MIDDLE2, + controller::Action::LEFT_HAND_MIDDLE3, + controller::Action::LEFT_HAND_MIDDLE4, + controller::Action::LEFT_HAND_RING1, + controller::Action::LEFT_HAND_RING2, + controller::Action::LEFT_HAND_RING3, + controller::Action::LEFT_HAND_RING4, + controller::Action::LEFT_HAND_PINKY1, + controller::Action::LEFT_HAND_PINKY2, + controller::Action::LEFT_HAND_PINKY3, + controller::Action::LEFT_HAND_PINKY4, + controller::Action::RIGHT_HAND_THUMB1, + controller::Action::RIGHT_HAND_THUMB2, + controller::Action::RIGHT_HAND_THUMB3, + controller::Action::RIGHT_HAND_THUMB4, + controller::Action::RIGHT_HAND_INDEX1, + controller::Action::RIGHT_HAND_INDEX2, + controller::Action::RIGHT_HAND_INDEX3, + controller::Action::RIGHT_HAND_INDEX4, + controller::Action::RIGHT_HAND_MIDDLE1, + controller::Action::RIGHT_HAND_MIDDLE2, + controller::Action::RIGHT_HAND_MIDDLE3, + controller::Action::RIGHT_HAND_MIDDLE4, + controller::Action::RIGHT_HAND_RING1, + controller::Action::RIGHT_HAND_RING2, + controller::Action::RIGHT_HAND_RING3, + controller::Action::RIGHT_HAND_RING4, + controller::Action::RIGHT_HAND_PINKY1, + controller::Action::RIGHT_HAND_PINKY2, + controller::Action::RIGHT_HAND_PINKY3, + controller::Action::RIGHT_HAND_PINKY4, + controller::Action::LEFT_ARM, + controller::Action::RIGHT_ARM, + controller::Action::LEFT_SHOULDER, + controller::Action::RIGHT_SHOULDER, + controller::Action::LEFT_FORE_ARM, + controller::Action::RIGHT_FORE_ARM, + controller::Action::LEFT_LEG, + controller::Action::RIGHT_LEG, + controller::Action::LEFT_UP_LEG, + controller::Action::RIGHT_UP_LEG, + controller::Action::LEFT_TOE_BASE, + controller::Action::RIGHT_TOE_BASE + }; // copy controller poses from userInputMapper to myAvatar. glm::mat4 myAvatarMatrix = createMatFromQuatAndPos(myAvatar->getWorldOrientation(), myAvatar->getWorldPosition()); @@ -6290,25 +6333,21 @@ void Application::update(float deltaTime) { myAvatar->setControllerPoseInSensorFrame(action, pose.transform(avatarToSensorMatrix)); } - static const std::vector trackedObjectStringLiterals = - { QStringLiteral("_TrackedObject00"), QStringLiteral("_TrackedObject01"), QStringLiteral("_TrackedObject02"), - QStringLiteral("_TrackedObject03"), QStringLiteral("_TrackedObject04"), QStringLiteral("_TrackedObject05"), - QStringLiteral("_TrackedObject06"), QStringLiteral("_TrackedObject07"), QStringLiteral("_TrackedObject08"), - QStringLiteral("_TrackedObject09"), QStringLiteral("_TrackedObject10"), QStringLiteral("_TrackedObject11"), - QStringLiteral("_TrackedObject12"), QStringLiteral("_TrackedObject13"), QStringLiteral("_TrackedObject14"), - QStringLiteral("_TrackedObject15") }; + static const std::vector trackedObjectStringLiterals = { + QStringLiteral("_TrackedObject00"), QStringLiteral("_TrackedObject01"), QStringLiteral("_TrackedObject02"), QStringLiteral("_TrackedObject03"), + QStringLiteral("_TrackedObject04"), QStringLiteral("_TrackedObject05"), QStringLiteral("_TrackedObject06"), QStringLiteral("_TrackedObject07"), + QStringLiteral("_TrackedObject08"), QStringLiteral("_TrackedObject09"), QStringLiteral("_TrackedObject10"), QStringLiteral("_TrackedObject11"), + QStringLiteral("_TrackedObject12"), QStringLiteral("_TrackedObject13"), QStringLiteral("_TrackedObject14"), QStringLiteral("_TrackedObject15") + }; // Controlled by the Developer > Avatar > Show Tracked Objects menu. if (_showTrackedObjects) { - static const std::vector trackedObjectActions = - { controller::Action::TRACKED_OBJECT_00, controller::Action::TRACKED_OBJECT_01, - controller::Action::TRACKED_OBJECT_02, controller::Action::TRACKED_OBJECT_03, - controller::Action::TRACKED_OBJECT_04, controller::Action::TRACKED_OBJECT_05, - controller::Action::TRACKED_OBJECT_06, controller::Action::TRACKED_OBJECT_07, - controller::Action::TRACKED_OBJECT_08, controller::Action::TRACKED_OBJECT_09, - controller::Action::TRACKED_OBJECT_10, controller::Action::TRACKED_OBJECT_11, - controller::Action::TRACKED_OBJECT_12, controller::Action::TRACKED_OBJECT_13, - controller::Action::TRACKED_OBJECT_14, controller::Action::TRACKED_OBJECT_15 }; + static const std::vector trackedObjectActions = { + controller::Action::TRACKED_OBJECT_00, controller::Action::TRACKED_OBJECT_01, controller::Action::TRACKED_OBJECT_02, controller::Action::TRACKED_OBJECT_03, + controller::Action::TRACKED_OBJECT_04, controller::Action::TRACKED_OBJECT_05, controller::Action::TRACKED_OBJECT_06, controller::Action::TRACKED_OBJECT_07, + controller::Action::TRACKED_OBJECT_08, controller::Action::TRACKED_OBJECT_09, controller::Action::TRACKED_OBJECT_10, controller::Action::TRACKED_OBJECT_11, + controller::Action::TRACKED_OBJECT_12, controller::Action::TRACKED_OBJECT_13, controller::Action::TRACKED_OBJECT_14, controller::Action::TRACKED_OBJECT_15 + }; int i = 0; glm::vec4 BLUE(0.0f, 0.0f, 1.0f, 1.0f); @@ -6331,8 +6370,8 @@ void Application::update(float deltaTime) { _prevShowTrackedObjects = _showTrackedObjects; } - updateThreads(deltaTime); // If running non-threaded, then give the threads some time to process... - updateDialogs(deltaTime); // update various stats dialogs if present + updateThreads(deltaTime); // If running non-threaded, then give the threads some time to process... + updateDialogs(deltaTime); // update various stats dialogs if present auto grabManager = DependencyManager::get(); grabManager->simulateGrabs(); @@ -6410,15 +6449,18 @@ void Application::update(float deltaTime) { { PROFILE_RANGE(simulation_physics, "PrepareActions"); - _physicsEngine->forEachDynamic( - [&](EntityDynamicPointer dynamic) { dynamic->prepareForPhysicsSimulation(); }); + _physicsEngine->forEachDynamic([&](EntityDynamicPointer dynamic) { + dynamic->prepareForPhysicsSimulation(); + }); } } auto t2 = std::chrono::high_resolution_clock::now(); { PROFILE_RANGE(simulation_physics, "StepPhysics"); PerformanceTimer perfTimer("stepPhysics"); - getEntities()->getTree()->withWriteLock([&] { _physicsEngine->stepSimulation(); }); + getEntities()->getTree()->withWriteLock([&] { + _physicsEngine->stepSimulation(); + }); } auto t3 = std::chrono::high_resolution_clock::now(); { @@ -6457,8 +6499,8 @@ void Application::update(float deltaTime) { } if (PerformanceTimer::isActive() && - Menu::getInstance()->isOptionChecked(MenuOption::DisplayDebugTimingDetails) && - Menu::getInstance()->isOptionChecked(MenuOption::ExpandPhysicsTiming)) { + Menu::getInstance()->isOptionChecked(MenuOption::DisplayDebugTimingDetails) && + Menu::getInstance()->isOptionChecked(MenuOption::ExpandPhysicsTiming)) { _physicsEngine->harvestPerformanceStats(); } // NOTE: the PhysicsEngine stats are written to stdout NOT to Qt log framework @@ -6468,17 +6510,17 @@ void Application::update(float deltaTime) { // NOTE: the getEntities()->update() call below will wait for lock // and will provide non-physical entity motion - getEntities()->update(true); // update the models... + getEntities()->update(true); // update the models... auto t5 = std::chrono::high_resolution_clock::now(); workload::Timings timings(6); - timings[0] = t1 - t0; // prePhysics entities - timings[1] = t2 - t1; // prePhysics avatars - timings[2] = t3 - t2; // stepPhysics - timings[3] = t4 - t3; // postPhysics - timings[4] = t5 - t4; // non-physical kinematics - timings[5] = workload::Timing_ns((int32_t)(NSECS_PER_SECOND * deltaTime)); // game loop duration + timings[0] = t1 - t0; // prePhysics entities + timings[1] = t2 - t1; // prePhysics avatars + timings[2] = t3 - t2; // stepPhysics + timings[3] = t4 - t3; // postPhysics + timings[4] = t5 - t4; // non-physical kinematics + timings[5] = workload::Timing_ns((int32_t)(NSECS_PER_SECOND * deltaTime)); // game loop duration _gameWorkload.updateSimulationTimings(timings); } } @@ -6562,8 +6604,9 @@ void Application::update(float deltaTime) { viewIsDifferentEnough = true; } + // if it's been a while since our last query or the view has significantly changed then send a query, otherwise suppress it - static const std::chrono::seconds MIN_PERIOD_BETWEEN_QUERIES{ 3 }; + static const std::chrono::seconds MIN_PERIOD_BETWEEN_QUERIES { 3 }; auto now = SteadyClock::now(); if (now > _queryExpiry || viewIsDifferentEnough) { if (DependencyManager::get()->shouldRenderEntities()) { @@ -6592,8 +6635,7 @@ void Application::update(float deltaTime) { if (sinceLastNack > TOO_LONG_SINCE_LAST_SEND_DOWNSTREAM_AUDIO_STATS && !isInterstitialMode()) { _lastSendDownstreamAudioStats = now; - QMetaObject::invokeMethod(DependencyManager::get().data(), "sendDownstreamAudioStatsPacket", - Qt::QueuedConnection); + QMetaObject::invokeMethod(DependencyManager::get().data(), "sendDownstreamAudioStatsPacket", Qt::QueuedConnection); } } @@ -6612,6 +6654,7 @@ void Application::update(float deltaTime) { _postUpdateLambdas.clear(); } + updateRenderArgs(deltaTime); { @@ -6619,7 +6662,8 @@ void Application::update(float deltaTime) { AnimDebugDraw::getInstance().update(); } - { // Game loop is done, mark the end of the frame for the scene transactions and the render loop to take over + + { // Game loop is done, mark the end of the frame for the scene transactions and the render loop to take over PerformanceTimer perfTimer("enqueueFrame"); getMain3DScene()->enqueueFrame(); } @@ -6653,16 +6697,16 @@ void Application::updateRenderArgs(float deltaTime) { { QMutexLocker viewLocker(&_viewMutex); // adjust near clip plane to account for sensor scaling. - auto adjustedProjection = - glm::perspective(glm::radians(_fieldOfView.get()), getActiveDisplayPlugin()->getRecommendedAspectRatio(), - DEFAULT_NEAR_CLIP * sensorToWorldScale, DEFAULT_FAR_CLIP); + auto adjustedProjection = glm::perspective(glm::radians(_fieldOfView.get()), + getActiveDisplayPlugin()->getRecommendedAspectRatio(), + DEFAULT_NEAR_CLIP * sensorToWorldScale, + DEFAULT_FAR_CLIP); _viewFrustum.setProjection(adjustedProjection); _viewFrustum.calculate(); } - appRenderArgs._renderArgs = - RenderArgs(_graphicsEngine.getGPUContext(), lodManager->getOctreeSizeScale(), - lodManager->getBoundaryLevelAdjust(), lodManager->getLODAngleHalfTan(), - RenderArgs::DEFAULT_RENDER_MODE, RenderArgs::MONO, RenderArgs::RENDER_DEBUG_NONE); + appRenderArgs._renderArgs = RenderArgs(_graphicsEngine.getGPUContext(), lodManager->getOctreeSizeScale(), + lodManager->getBoundaryLevelAdjust(), lodManager->getLODAngleHalfTan(), RenderArgs::DEFAULT_RENDER_MODE, + RenderArgs::MONO, RenderArgs::RENDER_DEBUG_NONE); appRenderArgs._renderArgs._scene = getMain3DScene(); { @@ -6751,6 +6795,7 @@ void Application::updateRenderArgs(float deltaTime) { appRenderArgs._renderArgs.setViewFrustum(_displayViewFrustum); } + // HACK // load the view frustum // FIXME: This preDisplayRender call is temporary until we create a separate render::scene for the mirror rendering. @@ -6779,14 +6824,18 @@ void Application::queryAvatars() { } } + int Application::sendNackPackets() { + // iterates through all nodes in NodeList auto nodeList = DependencyManager::get(); int packetsSent = 0; - nodeList->eachNode([&](const SharedNodePointer& node) { + nodeList->eachNode([&](const SharedNodePointer& node){ + if (node->getActiveSocket() && node->getType() == NodeType::EntityServer) { + auto nackPacketList = NLPacketList::create(PacketType::OctreeDataNack); QUuid nodeUUID = node->getUUID(); @@ -6804,8 +6853,7 @@ int Application::sendNackPackets() { return; } // get sequence number stats of node, prune its missing set, and make a copy of the missing set - SequenceNumberStats& sequenceNumberStats = - _octreeServerSceneStats[nodeUUID].getIncomingOctreeSequenceNumberStats(); + SequenceNumberStats& sequenceNumberStats = _octreeServerSceneStats[nodeUUID].getIncomingOctreeSequenceNumberStats(); sequenceNumberStats.pruneMissingSet(); missingSequenceNumbers = sequenceNumberStats.getMissingSet(); }); @@ -6813,7 +6861,7 @@ int Application::sendNackPackets() { _isMissingSequenceNumbers = (missingSequenceNumbers.size() != 0); // construct nack packet(s) for this node - foreach (const OCTREE_PACKET_SEQUENCE& missingNumber, missingSequenceNumbers) { + foreach(const OCTREE_PACKET_SEQUENCE& missingNumber, missingSequenceNumbers) { nackPacketList->writePrimitive(missingNumber); } @@ -6830,8 +6878,9 @@ int Application::sendNackPackets() { } void Application::queryOctree(NodeType_t serverType, PacketType packetType) { + if (!_settingsLoaded) { - return; // bail early if settings are not loaded + return; // bail early if settings are not loaded } const bool isModifiedQuery = !_physicsEnabled; @@ -6861,6 +6910,7 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType) { } _octreeQuery.setReportInitialCompletion(isModifiedQuery); + auto nodeList = DependencyManager::get(); auto node = nodeList->soloNodeOfType(serverType); @@ -6879,6 +6929,7 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType) { } } + bool Application::isHMDMode() const { return getActiveDisplayPlugin()->isHmd(); } @@ -6887,9 +6938,7 @@ float Application::getNumCollisionObjects() const { return _physicsEngine ? _physicsEngine->getNumCollisionObjects() : 0; } -float Application::getTargetRenderFrameRate() const { - return getActiveDisplayPlugin()->getTargetFrameRate(); -} +float Application::getTargetRenderFrameRate() const { return getActiveDisplayPlugin()->getTargetFrameRate(); } QRect Application::getDesirableApplicationGeometry() const { QRect applicationGeometry = getWindow()->geometry(); @@ -6915,7 +6964,7 @@ QRect Application::getDesirableApplicationGeometry() const { } PickRay Application::computePickRay(float x, float y) const { - vec2 pickPoint{ x, y }; + vec2 pickPoint { x, y }; PickRay result; if (isHMDMode()) { getApplicationCompositor().computeHmdPickRay(pickPoint, result.origin, result.direction); @@ -6975,18 +7024,19 @@ void Application::hmdVisibleChanged(bool visible) { } void Application::updateWindowTitle() const { + auto nodeList = DependencyManager::get(); auto accountManager = DependencyManager::get(); auto isInErrorState = nodeList->getDomainHandler().isInErrorState(); - QString buildVersion = " - " + - (BuildInfo::BUILD_TYPE == BuildInfo::BuildType::Stable ? QString("Version") : QString("Build")) + - " " + applicationVersion(); + QString buildVersion = " - " + + (BuildInfo::BUILD_TYPE == BuildInfo::BuildType::Stable ? QString("Version") : QString("Build")) + + " " + applicationVersion(); QString loginStatus = accountManager->isLoggedIn() ? "" : " (NOT LOGGED IN)"; - QString connectionStatus = - isInErrorState ? " (ERROR CONNECTING)" : nodeList->getDomainHandler().isConnected() ? "" : " (NOT CONNECTED)"; + QString connectionStatus = isInErrorState ? " (ERROR CONNECTING)" : + nodeList->getDomainHandler().isConnected() ? "" : " (NOT CONNECTED)"; QString username = accountManager->getAccountInfo().getUsername(); setCrashAnnotation("username", username.toStdString()); @@ -7005,8 +7055,8 @@ void Application::updateWindowTitle() const { } } - QString title = QString() + (!username.isEmpty() ? username + " @ " : QString()) + currentPlaceName + connectionStatus + - loginStatus + buildVersion; + QString title = QString() + (!username.isEmpty() ? username + " @ " : QString()) + + currentPlaceName + connectionStatus + loginStatus + buildVersion; #ifndef WIN32 // crashes with vs2013/win32 @@ -7016,7 +7066,7 @@ void Application::updateWindowTitle() const { // updateTitleWindow gets called whenever there's a change regarding the domain, so rather // than placing this within domainURLChanged, it's placed here to cover the other potential cases. - DependencyManager::get()->sendLocalMessage("Toolbar-DomainChanged", ""); + DependencyManager::get< MessagesClient >()->sendLocalMessage("Toolbar-DomainChanged", ""); } void Application::clearDomainOctreeDetails(bool clearAll) { @@ -7030,7 +7080,9 @@ void Application::clearDomainOctreeDetails(bool clearAll) { resetPhysicsReadyInformation(); setIsInterstitialMode(true); - _octreeServerSceneStats.withWriteLock([&] { _octreeServerSceneStats.clear(); }); + _octreeServerSceneStats.withWriteLock([&] { + _octreeServerSceneStats.clear(); + }); // reset the model renderer clearAll ? getEntities()->clear() : getEntities()->clearDomainAndNonOwnedEntities(); @@ -7114,7 +7166,7 @@ void Application::nodeActivated(SharedNodePointer node) { _queryExpiry = SteadyClock::now(); _octreeQuery.incrementConnectionID(); - if (!_failedToConnectToEntityServer) { + if (!_failedToConnectToEntityServer) { _entityServerConnectionTimer.stop(); } } @@ -7240,6 +7292,7 @@ void Application::addingEntityWithCertificate(const QString& certificateID, cons } void Application::registerScriptEngineWithApplicationServices(ScriptEnginePointer scriptEngine) { + scriptEngine->setEmitScriptUpdatesFunction([this]() { SharedNodePointer entityServerNode = DependencyManager::get()->soloNodeOfType(NodeType::EntityServer); return !entityServerNode || isPhysicsEnabled(); @@ -7283,13 +7336,13 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEnginePointe #endif qScriptRegisterMetaType(scriptEngine.data(), wrapperToScriptValue, wrapperFromScriptValue); - qScriptRegisterMetaType(scriptEngine.data(), wrapperToScriptValue, - wrapperFromScriptValue); + qScriptRegisterMetaType(scriptEngine.data(), + wrapperToScriptValue, wrapperFromScriptValue); scriptEngine->registerGlobalObject("Toolbars", DependencyManager::get().data()); qScriptRegisterMetaType(scriptEngine.data(), wrapperToScriptValue, wrapperFromScriptValue); - qScriptRegisterMetaType(scriptEngine.data(), wrapperToScriptValue, - wrapperFromScriptValue); + qScriptRegisterMetaType(scriptEngine.data(), + wrapperToScriptValue, wrapperFromScriptValue); scriptEngine->registerGlobalObject("Tablet", DependencyManager::get().data()); // FIXME remove these deprecated names for the tablet scripting interface scriptEngine->registerGlobalObject("tabletInterface", DependencyManager::get().data()); @@ -7299,20 +7352,17 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEnginePointe scriptEngine->registerGlobalObject("Window", DependencyManager::get().data()); scriptEngine->registerGetterSetter("location", LocationScriptingInterface::locationGetter, - LocationScriptingInterface::locationSetter, "Window"); + LocationScriptingInterface::locationSetter, "Window"); // register `location` on the global object. scriptEngine->registerGetterSetter("location", LocationScriptingInterface::locationGetter, LocationScriptingInterface::locationSetter); bool clientScript = scriptEngine->isClientScript(); - scriptEngine->registerFunction("OverlayWindow", - clientScript ? QmlWindowClass::constructor : QmlWindowClass::restricted_constructor); + scriptEngine->registerFunction("OverlayWindow", clientScript ? QmlWindowClass::constructor : QmlWindowClass::restricted_constructor); #if !defined(Q_OS_ANDROID) && !defined(DISABLE_QML) - scriptEngine->registerFunction("OverlayWebWindow", - clientScript ? QmlWebWindowClass::constructor : QmlWebWindowClass::restricted_constructor); + scriptEngine->registerFunction("OverlayWebWindow", clientScript ? QmlWebWindowClass::constructor : QmlWebWindowClass::restricted_constructor); #endif - scriptEngine->registerFunction("QmlFragment", - clientScript ? QmlFragmentClass::constructor : QmlFragmentClass::restricted_constructor); + scriptEngine->registerFunction("QmlFragment", clientScript ? QmlFragmentClass::constructor : QmlFragmentClass::restricted_constructor); scriptEngine->registerGlobalObject("Menu", MenuScriptingInterface::getInstance()); scriptEngine->registerGlobalObject("DesktopPreviewProvider", DependencyManager::get().data()); @@ -7339,10 +7389,8 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEnginePointe scriptEngine->registerGlobalObject("DialogsManager", _dialogsManagerScriptingInterface); - scriptEngine->registerGlobalObject("Account", - AccountServicesScriptingInterface::getInstance()); // DEPRECATED - TO BE REMOVED - scriptEngine->registerGlobalObject("GlobalServices", - AccountServicesScriptingInterface::getInstance()); // DEPRECATED - TO BE REMOVED + scriptEngine->registerGlobalObject("Account", AccountServicesScriptingInterface::getInstance()); // DEPRECATED - TO BE REMOVED + scriptEngine->registerGlobalObject("GlobalServices", AccountServicesScriptingInterface::getInstance()); // DEPRECATED - TO BE REMOVED scriptEngine->registerGlobalObject("AccountServices", AccountServicesScriptingInterface::getInstance()); qScriptRegisterMetaType(scriptEngine.data(), DownloadInfoResultToScriptValue, DownloadInfoResultFromScriptValue); @@ -7371,8 +7419,7 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEnginePointe scriptEngine->registerGlobalObject("ScriptDiscoveryService", DependencyManager::get().data()); scriptEngine->registerGlobalObject("Reticle", getApplicationCompositor().getReticleInterface()); - scriptEngine->registerGlobalObject("UserActivityLogger", - DependencyManager::get().data()); + scriptEngine->registerGlobalObject("UserActivityLogger", DependencyManager::get().data()); scriptEngine->registerGlobalObject("Users", DependencyManager::get().data()); scriptEngine->registerGlobalObject("GooglePoly", DependencyManager::get().data()); @@ -7409,6 +7456,7 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEnginePointe connect(scriptEngine.data(), &ScriptEngine::warningMessage, scriptEngines, &ScriptEngines::onWarningMessage); connect(scriptEngine.data(), &ScriptEngine::infoMessage, scriptEngines, &ScriptEngines::onInfoMessage); connect(scriptEngine.data(), &ScriptEngine::clearDebugWindow, scriptEngines, &ScriptEngines::onClearDebugWindow); + } bool Application::canAcceptURL(const QString& urlString) const { @@ -7432,8 +7480,8 @@ bool Application::acceptURL(const QString& urlString, bool defaultUpload) { if (url.scheme() == URL_SCHEME_HIFI) { // this is a hifi URL - have the AddressManager handle it - QMetaObject::invokeMethod(DependencyManager::get().data(), "handleLookupString", Qt::AutoConnection, - Q_ARG(const QString&, urlString)); + QMetaObject::invokeMethod(DependencyManager::get().data(), "handleLookupString", + Qt::AutoConnection, Q_ARG(const QString&, urlString)); return true; } @@ -7470,13 +7518,13 @@ bool Application::askToSetAvatarUrl(const QString& url) { QString modelName = fstMapping["name"].toString(); QString modelLicense = fstMapping["license"].toString(); - bool agreeToLicense = true; // assume true + bool agreeToLicense = true; // assume true //create set avatar callback - auto setAvatar = [=](QString url, QString modelName) { - ModalDialogListener* dlg = - OffscreenUi::asyncQuestion("Set Avatar", "Would you like to use '" + modelName + "' for your avatar?", - QMessageBox::Ok | QMessageBox::Cancel, QMessageBox::Ok); - QObject::connect(dlg, &ModalDialogListener::response, this, [=](QVariant answer) { + auto setAvatar = [=] (QString url, QString modelName) { + ModalDialogListener* dlg = OffscreenUi::asyncQuestion("Set Avatar", + "Would you like to use '" + modelName + "' for your avatar?", + QMessageBox::Ok | QMessageBox::Cancel, QMessageBox::Ok); + QObject::connect(dlg, &ModalDialogListener::response, this, [=] (QVariant answer) { QObject::disconnect(dlg, &ModalDialogListener::response, this, nullptr); bool ok = (QMessageBox::Ok == static_cast(answer.toInt())); @@ -7494,22 +7542,22 @@ bool Application::askToSetAvatarUrl(const QString& url) { const int MAX_CHARACTERS_PER_LINE = 90; modelLicense = simpleWordWrap(modelLicense, MAX_CHARACTERS_PER_LINE); - ModalDialogListener* dlg = - OffscreenUi::asyncQuestion("Avatar Usage License", modelLicense + "\nDo you agree to these terms?", - QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes); - QObject::connect(dlg, &ModalDialogListener::response, this, [=, &agreeToLicense](QVariant answer) { + ModalDialogListener* dlg = OffscreenUi::asyncQuestion("Avatar Usage License", + modelLicense + "\nDo you agree to these terms?", + QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes); + QObject::connect(dlg, &ModalDialogListener::response, this, [=, &agreeToLicense] (QVariant answer) { QObject::disconnect(dlg, &ModalDialogListener::response, this, nullptr); agreeToLicense = (static_cast(answer.toInt()) == QMessageBox::Yes); if (agreeToLicense) { switch (modelType) { case FSTReader::HEAD_AND_BODY_MODEL: { - setAvatar(url, modelName); - break; - } - default: - OffscreenUi::asyncWarning("", modelName + "Does not support a head and body as required."); - break; + setAvatar(url, modelName); + break; + } + default: + OffscreenUi::asyncWarning("", modelName + "Does not support a head and body as required."); + break; } } else { qCDebug(interfaceapp) << "Declined to agree to avatar license"; @@ -7524,10 +7572,11 @@ bool Application::askToSetAvatarUrl(const QString& url) { return true; } + bool Application::askToLoadScript(const QString& scriptFilenameOrURL) { QString shortName = scriptFilenameOrURL; - QUrl scriptURL{ scriptFilenameOrURL }; + QUrl scriptURL { scriptFilenameOrURL }; if (scriptURL.host().endsWith(MARKETPLACE_CDN_HOSTNAME)) { int startIndex = shortName.lastIndexOf('/') + 1; @@ -7539,10 +7588,10 @@ bool Application::askToLoadScript(const QString& scriptFilenameOrURL) { DependencyManager::get()->loadScript(scriptFilenameOrURL); #else QString message = "Would you like to run this script:\n" + shortName; - ModalDialogListener* dlg = - OffscreenUi::asyncQuestion(getWindow(), "Run Script", message, QMessageBox::Yes | QMessageBox::No); + ModalDialogListener* dlg = OffscreenUi::asyncQuestion(getWindow(), "Run Script", message, + QMessageBox::Yes | QMessageBox::No); - QObject::connect(dlg, &ModalDialogListener::response, this, [=](QVariant answer) { + QObject::connect(dlg, &ModalDialogListener::response, this, [=] (QVariant answer) { const QString& fileName = scriptFilenameOrURL; if (static_cast(answer.toInt()) == QMessageBox::Yes) { qCDebug(interfaceapp) << "Chose to run the script: " << fileName; @@ -7564,6 +7613,7 @@ bool Application::askToWearAvatarAttachmentUrl(const QString& url) { QNetworkReply* reply = networkAccessManager.get(networkRequest); int requestNumber = ++_avatarAttachmentRequest; connect(reply, &QNetworkReply::finished, [this, reply, url, requestNumber]() { + if (requestNumber != _avatarAttachmentRequest) { // this request has been superseded by another more recent request reply->deleteLater(); @@ -7578,6 +7628,7 @@ bool Application::askToWearAvatarAttachmentUrl(const QString& url) { QJsonParseError jsonError; auto doc = QJsonDocument::fromJson(contents, &jsonError); if (jsonError.error == QJsonParseError::NoError) { + auto jsonObject = doc.object(); // retrieve optional name field from JSON @@ -7589,10 +7640,10 @@ bool Application::askToWearAvatarAttachmentUrl(const QString& url) { auto avatarAttachmentConfirmationTitle = tr("Avatar Attachment Confirmation"); auto avatarAttachmentConfirmationMessage = tr("Would you like to wear '%1' on your avatar?").arg(name); - ModalDialogListener* dlg = - OffscreenUi::asyncQuestion(avatarAttachmentConfirmationTitle, avatarAttachmentConfirmationMessage, - QMessageBox::Ok | QMessageBox::Cancel); - QObject::connect(dlg, &ModalDialogListener::response, this, [=](QVariant answer) { + ModalDialogListener* dlg = OffscreenUi::asyncQuestion(avatarAttachmentConfirmationTitle, + avatarAttachmentConfirmationMessage, + QMessageBox::Ok | QMessageBox::Cancel); + QObject::connect(dlg, &ModalDialogListener::response, this, [=] (QVariant answer) { QObject::disconnect(dlg, &ModalDialogListener::response, this, nullptr); if (static_cast(answer.toInt()) == QMessageBox::Yes) { // add attachment to avatar @@ -7643,23 +7694,18 @@ bool Application::askToReplaceDomainContent(const QString& url) { QString methodDetails; const int MAX_CHARACTERS_PER_LINE = 90; if (DependencyManager::get()->getThisNodeCanReplaceContent()) { - QUrl originURL{ url }; + QUrl originURL { url }; if (originURL.host().endsWith(MARKETPLACE_CDN_HOSTNAME)) { // Create a confirmation dialog when this call is made - static const QString infoText = - simpleWordWrap( - "Your domain's content will be replaced with a new content set. " - "If you want to save what you have now, create a backup before proceeding. For more information about " - "backing up " - "and restoring content, visit the documentation page at: ", - MAX_CHARACTERS_PER_LINE) + + static const QString infoText = simpleWordWrap("Your domain's content will be replaced with a new content set. " + "If you want to save what you have now, create a backup before proceeding. For more information about backing up " + "and restoring content, visit the documentation page at: ", MAX_CHARACTERS_PER_LINE) + "\nhttps://docs.highfidelity.com/create-and-explore/start-working-in-your-sandbox/restoring-sandbox-content"; - ModalDialogListener* dig = - OffscreenUi::asyncQuestion("Are you sure you want to replace this domain's content set?", infoText, - QMessageBox::Yes | QMessageBox::No, QMessageBox::No); + ModalDialogListener* dig = OffscreenUi::asyncQuestion("Are you sure you want to replace this domain's content set?", + infoText, QMessageBox::Yes | QMessageBox::No, QMessageBox::No); - QObject::connect(dig, &ModalDialogListener::response, this, [=](QVariant answer) { + QObject::connect(dig, &ModalDialogListener::response, this, [=] (QVariant answer) { QString details; if (static_cast(answer.toInt()) == QMessageBox::Yes) { // Given confirmation, send request to domain server to replace content @@ -7668,26 +7714,33 @@ bool Application::askToReplaceDomainContent(const QString& url) { } else { details = "UserDeclinedToReplaceContent"; } - QJsonObject messageProperties = { { "status", details }, { "content_set_url", url } }; + QJsonObject messageProperties = { + { "status", details }, + { "content_set_url", url } + }; UserActivityLogger::getInstance().logAction("replace_domain_content", messageProperties); QObject::disconnect(dig, &ModalDialogListener::response, this, nullptr); }); } else { methodDetails = "ContentSetDidNotOriginateFromMarketplace"; - QJsonObject messageProperties = { { "status", methodDetails }, { "content_set_url", url } }; + QJsonObject messageProperties = { + { "status", methodDetails }, + { "content_set_url", url } + }; UserActivityLogger::getInstance().logAction("replace_domain_content", messageProperties); } } else { - methodDetails = "UserDoesNotHavePermissionToReplaceContent"; - static const QString warningMessage = simpleWordWrap( - "The domain owner must enable 'Replace Content' " - "permissions for you in this domain's server settings before you can continue.", - MAX_CHARACTERS_PER_LINE); - OffscreenUi::asyncWarning("You do not have permissions to replace domain content", warningMessage, QMessageBox::Ok, - QMessageBox::Ok); + methodDetails = "UserDoesNotHavePermissionToReplaceContent"; + static const QString warningMessage = simpleWordWrap("The domain owner must enable 'Replace Content' " + "permissions for you in this domain's server settings before you can continue.", MAX_CHARACTERS_PER_LINE); + OffscreenUi::asyncWarning("You do not have permissions to replace domain content", warningMessage, + QMessageBox::Ok, QMessageBox::Ok); - QJsonObject messageProperties = { { "status", methodDetails }, { "content_set_url", url } }; - UserActivityLogger::getInstance().logAction("replace_domain_content", messageProperties); + QJsonObject messageProperties = { + { "status", methodDetails }, + { "content_set_url", url } + }; + UserActivityLogger::getInstance().logAction("replace_domain_content", messageProperties); } return true; } @@ -7724,9 +7777,9 @@ void Application::showAssetServerWidget(QString filePath) { if (!DependencyManager::get()->getThisNodeCanWriteAssets() || getLoginDialogPoppedUp()) { return; } - static const QUrl url{ "hifi/AssetServer.qml" }; + static const QUrl url { "hifi/AssetServer.qml" }; - auto startUpload = [=](QQmlContext* context, QObject* newObject) { + auto startUpload = [=](QQmlContext* context, QObject* newObject){ if (!filePath.isEmpty()) { emit uploadRequest(filePath); } @@ -7751,6 +7804,7 @@ void Application::showAssetServerWidget(QString filePath) { } void Application::addAssetToWorldFromURL(QString url) { + QString filename; if (url.contains("filename")) { filename = url.section("filename=", 1, 1); // Filename is in "?filename=" parameter at end of URL. @@ -7762,6 +7816,7 @@ void Application::addAssetToWorldFromURL(QString url) { } else { filename.remove(".zip"); } + } if (!DependencyManager::get()->getThisNodeCanWriteAssets()) { @@ -7773,8 +7828,8 @@ void Application::addAssetToWorldFromURL(QString url) { addAssetToWorldInfo(filename, "Downloading model file " + filename + "."); - auto request = DependencyManager::get()->createResourceRequest(nullptr, QUrl(url), true, -1, - "Application::addAssetToWorldFromURL"); + auto request = DependencyManager::get()->createResourceRequest( + nullptr, QUrl(url), true, -1, "Application::addAssetToWorldFromURL"); connect(request, &ResourceRequest::finished, this, &Application::addAssetToWorldFromURLRequestFinished); request->send(); } @@ -7831,6 +7886,7 @@ void Application::addAssetToWorldFromURLRequestFinished() { request->deleteLater(); } + QString filenameFromPath(QString filePath) { return filePath.right(filePath.length() - filePath.lastIndexOf("/") - 1); } @@ -7875,8 +7931,8 @@ void Application::addAssetToWorldWithNewMapping(QString filePath, QString mappin if (result == GetMappingRequest::NotFound) { addAssetToWorldUpload(filePath, mapping, isZip, isBlocks); } else if (result != GetMappingRequest::NoError) { - QString errorInfo = - "Could not map asset name: " + mapping.left(mapping.length() - QString::number(copy).length() - 1); + QString errorInfo = "Could not map asset name: " + + mapping.left(mapping.length() - QString::number(copy).length() - 1); qWarning(interfaceapp) << "Error downloading model: " + errorInfo; addAssetToWorldError(filenameFromPath(filePath), errorInfo); } else if (copy < MAX_COPY_COUNT - 1) { @@ -7887,8 +7943,8 @@ void Application::addAssetToWorldWithNewMapping(QString filePath, QString mappin mapping = mapping.insert(mapping.lastIndexOf("."), "-" + QString::number(copy)); addAssetToWorldWithNewMapping(filePath, mapping, copy, isZip, isBlocks); } else { - QString errorInfo = - "Too many copies of asset name: " + mapping.left(mapping.length() - QString::number(copy).length() - 1); + QString errorInfo = "Too many copies of asset name: " + + mapping.left(mapping.length() - QString::number(copy).length() - 1); qWarning(interfaceapp) << "Error downloading model: " + errorInfo; addAssetToWorldError(filenameFromPath(filePath), errorInfo); } @@ -7935,7 +7991,7 @@ void Application::addAssetToWorldSetMapping(QString filePath, QString mapping, Q // to prevent files that aren't models or texture files from being loaded into world automatically if ((filePath.toLower().endsWith(OBJ_EXTENSION) || filePath.toLower().endsWith(FBX_EXTENSION)) || ((filePath.toLower().endsWith(JPG_EXTENSION) || filePath.toLower().endsWith(PNG_EXTENSION)) && - ((!isBlocks) && (!isZip)))) { + ((!isBlocks) && (!isZip)))) { addAssetToWorldAddEntity(filePath, mapping); } else { qCDebug(interfaceapp) << "Zipped contents are not supported entity files"; @@ -7961,11 +8017,10 @@ void Application::addAssetToWorldAddEntity(QString filePath, QString mapping) { properties.setShapeType(SHAPE_TYPE_SIMPLE_COMPOUND); } properties.setCollisionless(true); // Temporarily set so that doesn't collide with avatar. - properties.setVisible(false); // Temporarily set so that don't see at large unresized dimensions. + properties.setVisible(false); // Temporarily set so that don't see at large unresized dimensions. bool grabbable = (Menu::getInstance()->isOptionChecked(MenuOption::CreateEntitiesGrabbable)); properties.setUserData(grabbable ? GRABBABLE_USER_DATA : NOT_GRABBABLE_USER_DATA); - glm::vec3 positionOffset = - getMyAvatar()->getWorldOrientation() * (getMyAvatar()->getSensorToWorldScale() * glm::vec3(0.0f, 0.0f, -2.0f)); + glm::vec3 positionOffset = getMyAvatar()->getWorldOrientation() * (getMyAvatar()->getSensorToWorldScale() * glm::vec3(0.0f, 0.0f, -2.0f)); properties.setPosition(getMyAvatar()->getWorldPosition() + positionOffset); properties.setRotation(getMyAvatar()->getWorldOrientation()); properties.setGravity(glm::vec3(0.0f, 0.0f, 0.0f)); @@ -8011,11 +8066,12 @@ void Application::addAssetToWorldCheckModelSize() { const glm::vec3 DEFAULT_DIMENSIONS = glm::vec3(0.1f, 0.1f, 0.1f); if (dimensions != DEFAULT_DIMENSIONS) { + // Scale model so that its maximum is exactly specific size. const float MAXIMUM_DIMENSION = getMyAvatar()->getSensorToWorldScale(); auto previousDimensions = dimensions; - auto scale = std::min(MAXIMUM_DIMENSION / dimensions.x, - std::min(MAXIMUM_DIMENSION / dimensions.y, MAXIMUM_DIMENSION / dimensions.z)); + auto scale = std::min(MAXIMUM_DIMENSION / dimensions.x, std::min(MAXIMUM_DIMENSION / dimensions.y, + MAXIMUM_DIMENSION / dimensions.z)); dimensions *= scale; qInfo(interfaceapp) << "Model" << name << "auto-resized from" << previousDimensions << " to " << dimensions; doResize = true; @@ -8062,6 +8118,7 @@ void Application::addAssetToWorldCheckModelSize() { } } + void Application::addAssetToWorldInfo(QString modelName, QString infoText) { // Displays the most recent info message, subject to being overridden by error messages. @@ -8086,8 +8143,8 @@ void Application::addAssetToWorldInfo(QString modelName, QString infoText) { if (!_addAssetToWorldErrorTimer.isActive()) { if (!_addAssetToWorldMessageBox) { - _addAssetToWorldMessageBox = getOffscreenUI()->createMessageBox(OffscreenUi::ICON_INFORMATION, "Downloading Model", - "", QMessageBox::NoButton, QMessageBox::NoButton); + _addAssetToWorldMessageBox = getOffscreenUI()->createMessageBox(OffscreenUi::ICON_INFORMATION, + "Downloading Model", "", QMessageBox::NoButton, QMessageBox::NoButton); connect(_addAssetToWorldMessageBox, SIGNAL(destroyed()), this, SLOT(onAssetToWorldMessageBoxClosed())); } @@ -8169,8 +8226,8 @@ void Application::addAssetToWorldError(QString modelName, QString errorText) { addAssetToWorldInfoClear(modelName); if (!_addAssetToWorldMessageBox) { - _addAssetToWorldMessageBox = getOffscreenUI()->createMessageBox(OffscreenUi::ICON_INFORMATION, "Downloading Model", "", - QMessageBox::NoButton, QMessageBox::NoButton); + _addAssetToWorldMessageBox = getOffscreenUI()->createMessageBox(OffscreenUi::ICON_INFORMATION, + "Downloading Model", "", QMessageBox::NoButton, QMessageBox::NoButton); connect(_addAssetToWorldMessageBox, SIGNAL(destroyed()), this, SLOT(onAssetToWorldMessageBoxClosed())); } @@ -8202,6 +8259,7 @@ void Application::addAssetToWorldErrorTimeout() { } } + void Application::addAssetToWorldMessageClose() { // Clear messages, e.g., if Interface is being closed or domain changes. @@ -8239,6 +8297,7 @@ void Application::onAssetToWorldMessageBoxClosed() { } } + void Application::handleUnzip(QString zipFile, QStringList unzipFile, bool autoAdd, bool isZip, bool isBlocks) { if (autoAdd) { if (!unzipFile.isEmpty()) { @@ -8261,9 +8320,10 @@ void Application::packageModel() { } void Application::loadDialog() { - ModalDialogListener* dlg = OffscreenUi::getOpenFileNameAsync(_glWidget, tr("Open Script"), getPreviousScriptLocation(), + ModalDialogListener* dlg = OffscreenUi::getOpenFileNameAsync(_glWidget, tr("Open Script"), + getPreviousScriptLocation(), tr("JavaScript Files (*.js)")); - connect(dlg, &ModalDialogListener::response, this, [=](QVariant answer) { + connect(dlg, &ModalDialogListener::response, this, [=] (QVariant answer) { disconnect(dlg, &ModalDialogListener::response, this, nullptr); const QString& response = answer.toString(); if (!response.isEmpty() && QFile(response).exists()) { @@ -8284,7 +8344,7 @@ void Application::setPreviousScriptLocation(const QString& location) { void Application::loadScriptURLDialog() const { ModalDialogListener* dlg = OffscreenUi::getTextAsync(OffscreenUi::ICON_NONE, "Open and Run Script", "Script URL"); - connect(dlg, &ModalDialogListener::response, this, [=](QVariant response) { + connect(dlg, &ModalDialogListener::response, this, [=] (QVariant response) { disconnect(dlg, &ModalDialogListener::response, this, nullptr); const QString& newScript = response.toString(); if (QUrl(newScript).scheme() == "atp") { @@ -8337,8 +8397,9 @@ void Application::toggleLogDialog() { if (getLoginDialogPoppedUp()) { return; } - if (!_logDialog) { - bool keepOnTop = _keepLogWindowOnTop.get(); + if (! _logDialog) { + + bool keepOnTop =_keepLogWindowOnTop.get(); #ifdef Q_OS_WIN _logDialog = new LogDialog(keepOnTop ? qApp->getWindow() : nullptr, getLogger()); #elif !defined(Q_OS_ANDROID) @@ -8359,21 +8420,21 @@ void Application::toggleLogDialog() { #endif } -void Application::recreateLogWindow(int keepOnTop) { - _keepLogWindowOnTop.set(keepOnTop != 0); - if (_logDialog) { - bool toggle = _logDialog->isVisible(); - _logDialog->close(); - _logDialog = nullptr; + void Application::recreateLogWindow(int keepOnTop) { + _keepLogWindowOnTop.set(keepOnTop != 0); + if (_logDialog) { + bool toggle = _logDialog->isVisible(); + _logDialog->close(); + _logDialog = nullptr; - if (toggle) { - toggleLogDialog(); - } - } -} + if (toggle) { + toggleLogDialog(); + } + } + } void Application::toggleEntityScriptServerLogDialog() { - if (!_entityScriptServerLogDialog) { + if (! _entityScriptServerLogDialog) { _entityScriptServerLogDialog = new EntityScriptServerLogDialog(nullptr); } @@ -8389,13 +8450,11 @@ void Application::loadAddAvatarBookmarkDialog() const { } void Application::loadAvatarBrowser() const { - auto tablet = dynamic_cast( - DependencyManager::get()->getTablet("com.highfidelity.interface.tablet.system")); + auto tablet = dynamic_cast(DependencyManager::get()->getTablet("com.highfidelity.interface.tablet.system")); // construct the url to the marketplace item QString url = NetworkingConstants::METAVERSE_SERVER_URL().toString() + "/marketplace?category=avatars"; - QString MARKETPLACES_INJECT_SCRIPT_PATH = - "file:///" + qApp->applicationDirPath() + "/scripts/system/html/js/marketplacesInject.js"; + QString MARKETPLACES_INJECT_SCRIPT_PATH = "file:///" + qApp->applicationDirPath() + "/scripts/system/html/js/marketplacesInject.js"; tablet->gotoWebScreen(url, MARKETPLACES_INJECT_SCRIPT_PATH); DependencyManager::get()->openTablet(); } @@ -8415,11 +8474,9 @@ bool Application::takeSnapshotOperators(std::queue& snapshotOp } void Application::takeSnapshot(bool notify, bool includeAnimated, float aspectRatio, const QString& filename) { - addSnapshotOperator(std::make_tuple( - [notify, includeAnimated, aspectRatio, filename](const QImage& snapshot) { - QString path = - DependencyManager::get() - ->saveSnapshot(snapshot, filename, TestScriptingInterface::getInstance()->getTestResultsLocation()); + addSnapshotOperator(std::make_tuple([notify, includeAnimated, aspectRatio, filename](const QImage& snapshot) { + qApp->postLambdaEvent([snapshot, notify, includeAnimated, aspectRatio, filename] { + QString path = DependencyManager::get()->saveSnapshot(snapshot, filename, TestScriptingInterface::getInstance()->getTestResultsLocation()); // If we're not doing an animated snapshot as well... if (!includeAnimated) { @@ -8428,32 +8485,24 @@ void Application::takeSnapshot(bool notify, bool includeAnimated, float aspectRa emit DependencyManager::get()->stillSnapshotTaken(path, notify); } } else if (!SnapshotAnimated::isAlreadyTakingSnapshotAnimated()) { - qApp->postLambdaEvent([path, aspectRatio] { - // Get an animated GIF snapshot and save it - SnapshotAnimated::saveSnapshotAnimated(path, aspectRatio, - DependencyManager::get()); - }); + // Get an animated GIF snapshot and save it + SnapshotAnimated::saveSnapshotAnimated(path, aspectRatio, DependencyManager::get()); } - }, - aspectRatio, true)); + }); + }, aspectRatio, true)); } void Application::takeSecondaryCameraSnapshot(const bool& notify, const QString& filename) { - addSnapshotOperator(std::make_tuple( - [notify, filename](const QImage& snapshot) { - QString snapshotPath = - DependencyManager::get() - ->saveSnapshot(snapshot, filename, TestScriptingInterface::getInstance()->getTestResultsLocation()); + addSnapshotOperator(std::make_tuple([notify, filename](const QImage& snapshot) { + qApp->postLambdaEvent([snapshot, notify, filename] { + QString snapshotPath = DependencyManager::get()->saveSnapshot(snapshot, filename, TestScriptingInterface::getInstance()->getTestResultsLocation()); emit DependencyManager::get()->stillSnapshotTaken(snapshotPath, notify); - }, - 0.0f, false)); + }); + }, 0.0f, false)); } -void Application::takeSecondaryCamera360Snapshot(const glm::vec3& cameraPosition, - const bool& cubemapOutputFormat, - const bool& notify, - const QString& filename) { +void Application::takeSecondaryCamera360Snapshot(const glm::vec3& cameraPosition, const bool& cubemapOutputFormat, const bool& notify, const QString& filename) { postLambdaEvent([notify, filename, cubemapOutputFormat, cameraPosition] { DependencyManager::get()->save360Snapshot(cameraPosition, cubemapOutputFormat, notify, filename); }); @@ -8514,11 +8563,20 @@ void Application::activeChanged(Qt::ApplicationState state) { switch (state) { case Qt::ApplicationActive: _isForeground = true; + if (!_aboutToQuit && _startUpFinished) { + getRefreshRateManager().setRefreshRateRegime(RefreshRateManager::RefreshRateRegime::FOCUS_ACTIVE); + } break; case Qt::ApplicationSuspended: + break; case Qt::ApplicationHidden: + break; case Qt::ApplicationInactive: + if (!_aboutToQuit && _startUpFinished) { + getRefreshRateManager().setRefreshRateRegime(RefreshRateManager::RefreshRateRegime::UNFOCUS); + } + break; default: _isForeground = false; break; @@ -8530,8 +8588,7 @@ void Application::windowMinimizedChanged(bool minimized) { static std::once_flag once; std::call_once(once, [&] { connect(&_minimizedWindowTimer, &QTimer::timeout, this, [] { - QCoreApplication::postEvent(QCoreApplication::instance(), new QEvent(static_cast(Idle)), - Qt::HighEventPriority); + QCoreApplication::postEvent(QCoreApplication::instance(), new QEvent(static_cast(Idle)), Qt::HighEventPriority); }); }); @@ -8582,7 +8639,7 @@ void Application::initPlugins(const QStringList& arguments) { if (parser.isSet(disableDisplays)) { auto disabledDisplays = parser.value(disableDisplays).split(',', QString::SkipEmptyParts); - qInfo() << "Disabling following display plugins:" << disabledDisplays; + qInfo() << "Disabling following display plugins:" << disabledDisplays; PluginManager::getInstance()->disableDisplays(disabledDisplays); } @@ -8702,6 +8759,7 @@ DisplayPluginPointer Application::getActiveDisplayPlugin() const { return _displayPlugin; } + #if !defined(DISABLE_QML) static const char* EXCLUSION_GROUP_KEY = "exclusionGroup"; @@ -8709,7 +8767,7 @@ static void addDisplayPluginToMenu(const DisplayPluginPointer& displayPlugin, in auto menu = Menu::getInstance(); QString name = displayPlugin->getName(); auto grouping = displayPlugin->getGrouping(); - QString groupingMenu{ "" }; + QString groupingMenu { "" }; Q_ASSERT(!menu->menuItemExists(MenuOption::OutputMenu, name)); // assign the meny grouping based on plugin grouping @@ -8731,9 +8789,10 @@ static void addDisplayPluginToMenu(const DisplayPluginPointer& displayPlugin, in displayPluginGroup->setExclusive(true); } auto parent = menu->getMenu(MenuOption::OutputMenu); - auto action = menu->addActionToQMenuAndActionHash(parent, name, QKeySequence(Qt::CTRL + (Qt::Key_0 + index)), qApp, - SLOT(updateDisplayMode()), QAction::NoRole, Menu::UNSPECIFIED_POSITION, - groupingMenu); + auto action = menu->addActionToQMenuAndActionHash(parent, + name, QKeySequence(Qt::CTRL + (Qt::Key_0 + index)), qApp, + SLOT(updateDisplayMode()), + QAction::NoRole, Menu::UNSPECIFIED_POSITION, groupingMenu); action->setCheckable(true); action->setChecked(active); @@ -8758,7 +8817,7 @@ void Application::updateDisplayMode() { DisplayPluginPointer newDisplayPlugin = displayPlugins.at(0); auto menu = getPrimaryMenu(); if (menu) { - foreach (DisplayPluginPointer displayPlugin, PluginManager::getInstance()->getDisplayPlugins()) { + foreach(DisplayPluginPointer displayPlugin, PluginManager::getInstance()->getDisplayPlugins()) { QString name = displayPlugin->getName(); QAction* action = menu->getActionForOption(name); // Menu might have been removed if the display plugin lost @@ -8848,7 +8907,8 @@ void Application::setDisplayPlugin(DisplayPluginPointer newDisplayPlugin) { RefreshRateManager& refreshRateManager = getRefreshRateManager(); refreshRateManager.setRefreshRateOperator(OpenGLDisplayPlugin::getRefreshRateOperator()); bool isHmd = newDisplayPlugin->isHmd(); - RefreshRateManager::UXMode uxMode = isHmd ? RefreshRateManager::UXMode::HMD : RefreshRateManager::UXMode::DESKTOP; + RefreshRateManager::UXMode uxMode = isHmd ? RefreshRateManager::UXMode::VR : + RefreshRateManager::UXMode::DESKTOP; refreshRateManager.setUXMode(uxMode); } @@ -8857,10 +8917,11 @@ void Application::setDisplayPlugin(DisplayPluginPointer newDisplayPlugin) { qCDebug(interfaceapp) << "Entering into" << (isHmd ? "HMD" : "Desktop") << "Mode"; // Only log/emit after a successful change - UserActivityLogger::getInstance().logAction("changed_display_mode", - { { "previous_display_mode", _displayPlugin ? _displayPlugin->getName() : "" }, - { "display_mode", newDisplayPlugin ? newDisplayPlugin->getName() : "" }, - { "hmd", isHmd } }); + UserActivityLogger::getInstance().logAction("changed_display_mode", { + { "previous_display_mode", _displayPlugin ? _displayPlugin->getName() : "" }, + { "display_mode", newDisplayPlugin ? newDisplayPlugin->getName() : "" }, + { "hmd", isHmd } + }); emit activeDisplayPluginChanged(); // reset the avatar, to set head and hand palms back to a reasonable default pose. @@ -8927,7 +8988,7 @@ void Application::setShowBulletConstraintLimits(bool value) { } void Application::createLoginDialog() { - const glm::vec3 LOGIN_DIMENSIONS{ 0.89f, 0.5f, 0.01f }; + const glm::vec3 LOGIN_DIMENSIONS { 0.89f, 0.5f, 0.01f }; const auto OFFSET = glm::vec2(0.7f, -0.1f); auto cameraPosition = _myCamera.getPosition(); auto cameraOrientation = _myCamera.getOrientation(); @@ -9004,8 +9065,7 @@ void Application::updateLoginDialogPosition() { } { - glm::vec3 keyboardLocalOffset = - cameraOrientation * glm::vec3(-0.4f * getMyAvatar()->getSensorToWorldScale(), -0.3f, 0.2f); + glm::vec3 keyboardLocalOffset = cameraOrientation * glm::vec3(-0.4f * getMyAvatar()->getSensorToWorldScale(), -0.3f, 0.2f); glm::quat keyboardOrientation = cameraOrientation * glm::quat(glm::radians(glm::vec3(-30.0f, 180.0f, 0.0f))); EntityItemProperties properties; @@ -9017,7 +9077,7 @@ void Application::updateLoginDialogPosition() { } void Application::createAvatarInputsBar() { - const glm::vec3 LOCAL_POSITION{ 0.0, 0.0, -1.0 }; + const glm::vec3 LOCAL_POSITION { 0.0, 0.0, -1.0 }; // DEFAULT_DPI / tablet scale percentage const float DPI = 31.0f / (75.0f / 100.0f); @@ -9171,6 +9231,7 @@ CompositorHelper& Application::getApplicationCompositor() const { return *DependencyManager::get(); } + // virtual functions required for PluginContainer ui::Menu* Application::getPrimaryMenu() { auto appMenu = _window->menuBar(); @@ -9302,9 +9363,7 @@ void Application::showUrlHandler(const QUrl& url) { return; } - ModalDialogListener* dlg = - OffscreenUi::asyncQuestion("Confirm openUrl", "Do you recognize this path or code and want to open or execute it: " + - url.toDisplayString()); + ModalDialogListener* dlg = OffscreenUi::asyncQuestion("Confirm openUrl", "Do you recognize this path or code and want to open or execute it: " + url.toDisplayString()); QObject::connect(dlg, &ModalDialogListener::response, this, [=](QVariant answer) { QObject::disconnect(dlg, &ModalDialogListener::response, this, nullptr); if (QMessageBox::Yes == static_cast(answer.toInt())) { @@ -9324,8 +9383,11 @@ void Application::beforeEnterBackground() { clearDomainOctreeDetails(); } + + void Application::enterBackground() { - QMetaObject::invokeMethod(DependencyManager::get().data(), "stop", Qt::BlockingQueuedConnection); + QMetaObject::invokeMethod(DependencyManager::get().data(), + "stop", Qt::BlockingQueuedConnection); // Quest only supports one plugin which can't be deactivated currently #if !defined(ANDROID_APP_QUEST_INTERFACE) if (getActiveDisplayPlugin()->isActive()) { @@ -9335,7 +9397,8 @@ void Application::enterBackground() { } void Application::enterForeground() { - QMetaObject::invokeMethod(DependencyManager::get().data(), "start", Qt::BlockingQueuedConnection); + QMetaObject::invokeMethod(DependencyManager::get().data(), + "start", Qt::BlockingQueuedConnection); // Quest only supports one plugin which can't be deactivated currently #if !defined(ANDROID_APP_QUEST_INTERFACE) if (!getActiveDisplayPlugin() || getActiveDisplayPlugin()->isActive() || !getActiveDisplayPlugin()->activate()) { @@ -9346,9 +9409,11 @@ void Application::enterForeground() { nodeList->setSendDomainServerCheckInEnabled(true); } -void Application::toggleAwayMode() { - QKeyEvent event = QKeyEvent(QEvent::KeyPress, Qt::Key_Escape, Qt::NoModifier); - QCoreApplication::sendEvent(this, &event); + +void Application::toggleAwayMode(){ + QKeyEvent event = QKeyEvent (QEvent::KeyPress, Qt::Key_Escape, Qt::NoModifier); + QCoreApplication::sendEvent (this, &event); } + #endif diff --git a/interface/src/RefreshRateManager.cpp b/interface/src/RefreshRateManager.cpp index c4a35da1f6..0c5bcd405e 100644 --- a/interface/src/RefreshRateManager.cpp +++ b/interface/src/RefreshRateManager.cpp @@ -20,37 +20,40 @@ #include -static const int HMD_TARGET_RATE = 90; +static const int VR_TARGET_RATE = 90; static const std::array REFRESH_RATE_PROFILE_TO_STRING = { { "Eco", "Interactive", "Realtime" } }; static const std::array REFRESH_RATE_REGIME_TO_STRING = - { { "Running", "Unfocus", "Minimized", "StartUp", "ShutDown" } }; + { { "FocusActive", "FocusInactive", "Unfocus", "Minimized", "StartUp", "ShutDown" } }; static const std::array UX_MODE_TO_STRING = - { { "Desktop", "HMD" } }; + { { "Desktop", "VR" } }; static const std::map REFRESH_RATE_PROFILE_FROM_STRING = { { "Eco", RefreshRateManager::RefreshRateProfile::ECO }, { "Interactive", RefreshRateManager::RefreshRateProfile::INTERACTIVE }, { "Realtime", RefreshRateManager::RefreshRateProfile::REALTIME } }; -static const std::array RUNNING_REGIME_PROFILES = - { { 5, 20, 60 } }; -static const std::array UNFOCUS_REGIME_PROFILES = - { { 5, 5, 10 } }; +// Porfile regimes are: +// { { "FocusActive", "FocusInactive", "Unfocus", "Minimized", "StartUp", "ShutDown" } } -static const std::array MINIMIZED_REGIME_PROFILE = - { { 2, 2, 2 } }; +static const std::array ECO_PROFILE = + { { 20, 10, 5, 2, 30, 30 } }; -static const std::array START_AND_SHUTDOWN_REGIME_PROFILES = - { { 30, 30, 30 } }; +static const std::array INTERACTIVE_PROFILE = + { { 30, 20, 10, 2, 30, 30 } }; -static const std::array, RefreshRateManager::RefreshRateRegime::REGIME_NUM> REFRESH_RATE_REGIMES = - { { RUNNING_REGIME_PROFILES, UNFOCUS_REGIME_PROFILES, MINIMIZED_REGIME_PROFILE, - START_AND_SHUTDOWN_REGIME_PROFILES, START_AND_SHUTDOWN_REGIME_PROFILES } }; +static const std::array REALTIME_PROFILE = + { { 60, 60, 10, 2, 30, 30} }; + +static const std::array, RefreshRateManager::RefreshRateProfile::PROFILE_NUM> REFRESH_RATE_PROFILES = + { { ECO_PROFILE, INTERACTIVE_PROFILE, REALTIME_PROFILE } }; + + +static const int INACTIVE_TIMER_LIMIT = 3000; std::string RefreshRateManager::refreshRateProfileToString(RefreshRateManager::RefreshRateProfile refreshRateProfile) { @@ -70,14 +73,36 @@ std::string RefreshRateManager::uxModeToString(RefreshRateManager::RefreshRateMa } RefreshRateManager::RefreshRateManager() { - _refreshRateProfile = (RefreshRateManager::RefreshRateProfile) _refreshRateMode.get(); + _refreshRateProfile = (RefreshRateManager::RefreshRateProfile) _refreshRateProfileSetting.get(); + _inactiveTimer->setInterval(INACTIVE_TIMER_LIMIT); + _inactiveTimer->setSingleShot(true); + QObject::connect(_inactiveTimer.get(), &QTimer::timeout, [&] { + toggleInactive(); + }); +} + +void RefreshRateManager::resetInactiveTimer() { + if (_uxMode == RefreshRateManager::UXMode::DESKTOP) { + auto regime = getRefreshRateRegime(); + if (regime == RefreshRateRegime::FOCUS_ACTIVE || regime == RefreshRateRegime::FOCUS_INACTIVE) { + _inactiveTimer->start(); + setRefreshRateRegime(RefreshRateManager::RefreshRateRegime::FOCUS_ACTIVE); + } + } +} + +void RefreshRateManager::toggleInactive() { + if (_uxMode == RefreshRateManager::UXMode::DESKTOP && + getRefreshRateRegime() == RefreshRateManager::RefreshRateRegime::FOCUS_ACTIVE) { + setRefreshRateRegime(RefreshRateManager::RefreshRateRegime::FOCUS_INACTIVE); + } } void RefreshRateManager::setRefreshRateProfile(RefreshRateManager::RefreshRateProfile refreshRateProfile) { if (_refreshRateProfile != refreshRateProfile) { - _refreshRateModeLock.withWriteLock([&] { + _refreshRateProfileSettingLock.withWriteLock([&] { _refreshRateProfile = refreshRateProfile; - _refreshRateMode.set((int) refreshRateProfile); + _refreshRateProfileSetting.set((int) refreshRateProfile); }); updateRefreshRateController(); } @@ -86,9 +111,9 @@ void RefreshRateManager::setRefreshRateProfile(RefreshRateManager::RefreshRatePr RefreshRateManager::RefreshRateProfile RefreshRateManager::getRefreshRateProfile() const { RefreshRateManager::RefreshRateProfile profile = RefreshRateManager::RefreshRateProfile::REALTIME; - if (getUXMode() != RefreshRateManager::UXMode::HMD) { - profile =(RefreshRateManager::RefreshRateProfile) _refreshRateModeLock.resultWithReadLock([&] { - return _refreshRateMode.get(); + if (getUXMode() != RefreshRateManager::UXMode::VR) { + profile =(RefreshRateManager::RefreshRateProfile) _refreshRateProfileSettingLock.resultWithReadLock([&] { + return _refreshRateProfileSetting.get(); }); } @@ -96,8 +121,11 @@ RefreshRateManager::RefreshRateProfile RefreshRateManager::getRefreshRateProfile } RefreshRateManager::RefreshRateRegime RefreshRateManager::getRefreshRateRegime() const { - return getUXMode() == RefreshRateManager::UXMode::HMD ? RefreshRateManager::RefreshRateRegime::RUNNING : - _refreshRateRegime; + if (getUXMode() == RefreshRateManager::UXMode::VR) { + return RefreshRateManager::RefreshRateRegime::FOCUS_ACTIVE; + } else { + return _refreshRateRegime; + } } void RefreshRateManager::setRefreshRateRegime(RefreshRateManager::RefreshRateRegime refreshRateRegime) { @@ -119,31 +147,12 @@ void RefreshRateManager::updateRefreshRateController() const { if (_refreshRateOperator) { int targetRefreshRate; if (_uxMode == RefreshRateManager::UXMode::DESKTOP) { - if (_refreshRateRegime == RefreshRateManager::RefreshRateRegime::RUNNING && - _refreshRateProfile == RefreshRateManager::RefreshRateProfile::INTERACTIVE) { - targetRefreshRate = getInteractiveRefreshRate(); - } else { - targetRefreshRate = REFRESH_RATE_REGIMES[_refreshRateRegime][_refreshRateProfile]; - } + targetRefreshRate = REFRESH_RATE_PROFILES[_refreshRateProfile][_refreshRateRegime]; } else { - targetRefreshRate = HMD_TARGET_RATE; + targetRefreshRate = VR_TARGET_RATE; } _refreshRateOperator(targetRefreshRate); _activeRefreshRate = targetRefreshRate; } } - -void RefreshRateManager::setInteractiveRefreshRate(int refreshRate) { - _refreshRateLock.withWriteLock([&] { - _interactiveRefreshRate.set(refreshRate); - }); - updateRefreshRateController(); -} - - -int RefreshRateManager::getInteractiveRefreshRate() const { - return _refreshRateLock.resultWithReadLock([&] { - return _interactiveRefreshRate.get(); - }); -} diff --git a/interface/src/RefreshRateManager.h b/interface/src/RefreshRateManager.h index ee7debe3ef..6ded8c8869 100644 --- a/interface/src/RefreshRateManager.h +++ b/interface/src/RefreshRateManager.h @@ -15,6 +15,8 @@ #include #include +#include + #include #include @@ -28,7 +30,8 @@ public: }; enum RefreshRateRegime { - RUNNING = 0, + FOCUS_ACTIVE = 0, + FOCUS_INACTIVE, UNFOCUS, MINIMIZED, STARTUP, @@ -38,7 +41,7 @@ public: enum UXMode { DESKTOP = 0, - HMD, + VR, UX_NUM }; @@ -57,8 +60,9 @@ public: void setRefreshRateOperator(std::function refreshRateOperator) { _refreshRateOperator = refreshRateOperator; } int getActiveRefreshRate() const { return _activeRefreshRate; } void updateRefreshRateController() const; - void setInteractiveRefreshRate(int refreshRate); - int getInteractiveRefreshRate() const; + + void resetInactiveTimer(); + void toggleInactive(); static std::string refreshRateProfileToString(RefreshRateProfile refreshRateProfile); static RefreshRateProfile refreshRateProfileFromString(std::string refreshRateProfile); @@ -66,18 +70,17 @@ public: static std::string refreshRateRegimeToString(RefreshRateRegime refreshRateRegime); private: - mutable ReadWriteLockable _refreshRateLock; - mutable ReadWriteLockable _refreshRateModeLock; - mutable int _activeRefreshRate { 20 }; RefreshRateProfile _refreshRateProfile { RefreshRateProfile::INTERACTIVE}; RefreshRateRegime _refreshRateRegime { RefreshRateRegime::STARTUP }; UXMode _uxMode; - Setting::Handle _interactiveRefreshRate { "interactiveRefreshRate", 20}; - Setting::Handle _refreshRateMode { "refreshRateProfile", INTERACTIVE }; + mutable ReadWriteLockable _refreshRateProfileSettingLock; + Setting::Handle _refreshRateProfileSetting { "refreshRateProfile", RefreshRateProfile::INTERACTIVE }; std::function _refreshRateOperator { nullptr }; + + std::shared_ptr _inactiveTimer { std::make_shared() }; }; #endif diff --git a/interface/src/scripting/ClipboardScriptingInterface.h b/interface/src/scripting/ClipboardScriptingInterface.h index 42f2205861..9e72d9ea15 100644 --- a/interface/src/scripting/ClipboardScriptingInterface.h +++ b/interface/src/scripting/ClipboardScriptingInterface.h @@ -18,7 +18,7 @@ #include /**jsdoc - * The Clipboard API enables you to export and import entities to and from JSON files. + * The Clipboard API enables you to export and import entities to and from JSON files. * * @namespace Clipboard * @@ -33,56 +33,92 @@ public: public: /**jsdoc - * Compute the extents of the contents held in the clipboard. + * Gets the extents of the entities held in the clipboard. * @function Clipboard.getContentsDimensions - * @returns {Vec3} The extents of the contents held in the clipboard. + * @returns {Vec3} The extents of the content held in the clipboard. + * @example Import entities to the clipboard and report their overall dimensions. + * var filename = Window.browse("Import entities to clipboard", "", "*.json"); + * if (filename) { + * if (Clipboard.importEntities(filename)) { + * print("Clipboard dimensions: " + JSON.stringify(Clipboard.getContentsDimensions())); + * } + * } */ Q_INVOKABLE glm::vec3 getContentsDimensions(); /**jsdoc - * Compute the largest dimension of the extents of the contents held in the clipboard. + * Gets the largest dimension of the extents of the entities held in the clipboard. * @function Clipboard.getClipboardContentsLargestDimension - * @returns {number} The largest dimension computed. + * @returns {number} The largest dimension of the extents of the content held in the clipboard. */ Q_INVOKABLE float getClipboardContentsLargestDimension(); /**jsdoc - * Import entities from a JSON file containing entity data into the clipboard. - * You can generate a JSON file using {@link Clipboard.exportEntities}. + * Imports entities from a JSON file into the clipboard. * @function Clipboard.importEntities - * @param {string} filename Path and name of file to import. - * @param {boolean} does the ResourceRequestObserver observe this request? - * @param {number} optional internal id of object causing this import. + * @param {string} filename - The path and name of the JSON file to import. + * @param {boolean} [isObservable=true] - true if the {@link ResourceRequestObserver} can observe this + * request, false if it can't. + * @param {number} [callerID=-1] - An integer ID that is passed through to the {@link ResourceRequestObserver}. * @returns {boolean} true if the import was successful, otherwise false. + * @example Import entities and paste into the domain. + * var filename = Window.browse("Import entities to clipboard", "", "*.json"); + * if (filename) { + * if (Clipboard.importEntities(filename)) { + * pastedEntities = Clipboard.pasteEntities(Vec3.sum(MyAvatar.position, + * Vec3.multiplyQbyV(MyAvatar.orientation, { x: 0, y: 0, z: -3 }))); + * print("Entities pasted: " + JSON.stringify(pastedEntities)); + * } + * } */ Q_INVOKABLE bool importEntities(const QString& filename, const bool isObservable = true, const qint64 callerId = -1); /**jsdoc - * Export the entities specified to a JSON file. + * Exports specified entities to a JSON file. * @function Clipboard.exportEntities - * @param {string} filename Path and name of the file to export the entities to. Should have the extension ".json". - * @param {Uuid[]} entityIDs Array of IDs of the entities to export. - * @returns {boolean} true if the export was successful, otherwise false. + * @param {string} filename - Path and name of the file to export the entities to. Should have the extension ".json". + * @param {Uuid[]} entityIDs - The IDs of the entities to export. + * @returns {boolean} true if entities were found and the file was written, otherwise false. + * @example Create and export a cube and a sphere. + * // Create entities. + * var box = Entities.addEntity({ + * type: "Box", + * position: Vec3.sum(MyAvatar.position, Vec3.multiplyQbyV(MyAvatar.orientation, { x: -0.2, y: 0, z: -3 })), + * lifetime: 300 // Delete after 5 minutes. + * }); + * var sphere = Entities.addEntity({ + * type: "Sphere", + * position: Vec3.sum(MyAvatar.position, Vec3.multiplyQbyV(MyAvatar.orientation, { x: 0.2, y: 0, z: -3 })), + * lifetime: 300 // Delete after 5 minutes. + * }); + * + * // Export entities. + * var filename = Window.save("Export entities to JSON file", Paths.resources, "*.json"); + * if (filename) { + * Clipboard.exportEntities(filename, [box, sphere]); + * } */ Q_INVOKABLE bool exportEntities(const QString& filename, const QVector& entityIDs); /**jsdoc - * Export the entities with centers within a cube to a JSON file. + * Exports all entities that have centers within a cube to a JSON file. * @function Clipboard.exportEntities - * @param {string} filename Path and name of the file to export the entities to. Should have the extension ".json". - * @param {number} x X-coordinate of the cube center. - * @param {number} y Y-coordinate of the cube center. - * @param {number} z Z-coordinate of the cube center. - * @param {number} scale Half dimension of the cube. - * @returns {boolean} true if the export was successful, otherwise false. + * @variation 0 + * @param {string} filename - Path and name of the file to export the entities to. Should have the extension ".json". + * @param {number} x - X-coordinate of the cube center. + * @param {number} y - Y-coordinate of the cube center. + * @param {number} z - Z-coordinate of the cube center. + * @param {number} scale - Half dimension of the cube. + * @returns {boolean} true if entities were found and the file was written, otherwise false. */ Q_INVOKABLE bool exportEntities(const QString& filename, float x, float y, float z, float scale); /**jsdoc - * Paste the contents of the clipboard into the world. + * Pastes the contents of the clipboard into the domain. * @function Clipboard.pasteEntities - * @param {Vec3} position Position to paste the clipboard contents at. - * @returns {Uuid[]} Array of entity IDs for the new entities that were created as a result of the paste operation. + * @param {Vec3} position - The position to paste the clipboard contents at. + * @returns {Uuid[]} The IDs of the new entities that were created as a result of the paste operation. If entities couldn't + * be created then an empty array is returned. */ Q_INVOKABLE QVector pasteEntities(glm::vec3 position); }; diff --git a/interface/src/scripting/ControllerScriptingInterface.h b/interface/src/scripting/ControllerScriptingInterface.h index 9701c911b8..4fb631463e 100644 --- a/interface/src/scripting/ControllerScriptingInterface.h +++ b/interface/src/scripting/ControllerScriptingInterface.h @@ -26,18 +26,20 @@ class ScriptEngine; /**jsdoc - * The Controller API provides facilities to interact with computer and controller hardware. + * The Controller API provides facilities to interact with computer and controller hardware. * - *
Functions
+ *

Facilities

* - *

Properties

+ *

Properties

+ *

Get Controller property trees.

*
    *
  • {@link Controller.getActions|getActions}
  • *
  • {@link Controller.getHardware|getHardware}
  • *
  • {@link Controller.getStandard|getStandard}
  • *
* - *

Mappings

+ *

Mappings

+ *

Create and enable or disable Controller mappings.

*
    *
  • {@link Controller.disableMapping|disableMapping}
  • *
  • {@link Controller.enableMapping|enableMapping}
  • @@ -46,7 +48,8 @@ class ScriptEngine; *
  • {@link Controller.parseMapping|parseMapping}
  • *
* - *

Input, Hardware, and Action Reflection

+ *

Input, Hardware, and Action Reflection

+ *

Information on the devices and actions available.

*
    *
  • {@link Controller.findAction|findAction}
  • *
  • {@link Controller.findDevice|findDevice}
  • @@ -55,16 +58,20 @@ class ScriptEngine; *
  • {@link Controller.getAvailableInputs|getAvailableInputs}
  • *
  • {@link Controller.getDeviceName|getDeviceName}
  • *
  • {@link Controller.getDeviceNames|getDeviceNames}
  • + *
  • {@link Controller.getRunningInputDevices|getRunningInputDevices}
  • *
* - *

Input, Hardware, and Action Events

+ *

Input, Hardware, and Action Signals

+ *

Notifications of device and action events.

*
    *
  • {@link Controller.actionEvent|actionEvent}
  • *
  • {@link Controller.hardwareChanged|hardwareChanged}
  • + *
  • {@link Controller.inputDeviceRunningChanged|inputDeviceRunningChanged}
  • *
  • {@link Controller.inputEvent|inputEvent}
  • *
* - *

Mouse, Keyboard, and Touch Events

+ *

Mouse, Keyboard, and Touch Signals

+ *

Notifications of mouse, keyboard, and touch events.

*
    *
  • {@link Controller.keyPressEvent|keyPressEvent}
  • *
  • {@link Controller.keyReleaseEvent|keyReleaseEvent}
  • @@ -78,29 +85,32 @@ class ScriptEngine; *
  • {@link Controller.wheelEvent|wheelEvent}
  • *
* - *

Control Capturing

+ *

Control Capturing

+ *

Disable and enable the processing of mouse and touch events.

*
    *
  • {@link Controller.captureMouseEvents|captureMouseEvents}
  • - *
  • {@link Controller.captureTouchEvents|captureTouchEvents}
  • *
  • {@link Controller.captureWheelEvents|captureWheelEvents}
  • + *
  • {@link Controller.captureTouchEvents|captureTouchEvents}
  • *
  • {@link Controller.releaseMouseEvents|releaseMouseEvents}
  • - *
  • {@link Controller.releaseTouchEvents|releaseTouchEvents}
  • *
  • {@link Controller.releaseWheelEvents|releaseWheelEvents}
  • + *
  • {@link Controller.releaseTouchEvents|releaseTouchEvents}
  • *
* - *

Action Capturing

+ *

Action Capturing

+ *

Disable and enable controller actions.

*
    *
  • {@link Controller.captureActionEvents|captureActionEvents}
  • - *
  • {@link Controller.captureEntityClickEvents|captureEntityClickEvents}
  • - *
  • {@link Controller.captureJoystick|captureJoystick}
  • *
  • {@link Controller.captureKeyEvents|captureKeyEvents}
  • + *
  • {@link Controller.captureJoystick|captureJoystick}
  • + *
  • {@link Controller.captureEntityClickEvents|captureEntityClickEvents}
  • *
  • {@link Controller.releaseActionEvents|releaseActionEvents}
  • - *
  • {@link Controller.releaseEntityClickEvents|releaseEntityClickEvents}
  • - *
  • {@link Controller.releaseJoystick|releaseJoystick}
  • *
  • {@link Controller.releaseKeyEvents|releaseKeyEvents}
  • + *
  • {@link Controller.releaseJoystick|releaseJoystick}
  • + *
  • {@link Controller.releaseEntityClickEvents|releaseEntityClickEvents}
  • *
* - *

Controller and Action Values

+ *

Controller and Action Values

+ *

Get the current value of controller outputs and actions.

*
    *
  • {@link Controller.getValue|getValue}
  • *
  • {@link Controller.getAxisValue|getAxisValue}
  • @@ -108,7 +118,8 @@ class ScriptEngine; *
  • {@link Controller.getActionValue|getActionValue}
  • *
* - *

Haptics

+ *

Haptics

+ *

Trigger haptic pulses.

*
    *
  • {@link Controller.triggerHapticPulse|triggerHapticPulse}
  • *
  • {@link Controller.triggerHapticPulseOnDevice|triggerHapticPulseOnDevice}
  • @@ -116,20 +127,23 @@ class ScriptEngine; *
  • {@link Controller.triggerShortHapticPulseOnDevice|triggerShortHapticPulseOnDevice}
  • *
* - *

Display Information

+ *

Display Information

+ *

Get information on the display.

*
    *
  • {@link Controller.getViewportDimensions|getViewportDimensions}
  • *
  • {@link Controller.getRecommendedHUDRect|getRecommendedHUDRect}
  • *
* - *

Virtual Game Pad

+ *

Virtual Game Pad

+ *

Use the virtual game pad which is available on some devices.

*
    *
  • {@link Controller.setVPadEnabled|setVPadEnabled}
  • *
  • {@link Controller.setVPadHidden|setVPadHidden}
  • *
  • {@link Controller.setVPadExtraBottomMargin|setVPadExtraBottomMargin}
  • *
* - *

Input Recordings

+ *

Input Recordings

+ *

Create and play input recordings.

*
    *
  • {@link Controller.startInputRecording|startInputRecording}
  • *
  • {@link Controller.stopInputRecording|stopInputRecording}
  • @@ -140,10 +154,10 @@ class ScriptEngine; *
  • {@link Controller.stopInputPlayback|stopInputPlayback}
  • *
* - *
Entity Methods:
+ *

Entity Methods

* *

The default scripts implement hand controller actions that use {@link Entities.callEntityMethod} to call entity script - * methods, if present in the entity being interacted with.

+ * methods, if present, in the entity being interacted with.

* * * @@ -203,7 +217,7 @@ class ScriptEngine; * * @property {Controller.Actions} Actions - Predefined actions on Interface and the user's avatar. These can be used as end * points in a {@link RouteObject} mapping. A synonym for Controller.Hardware.Actions. - * Read-only.
+ * Read-only.

* Default mappings are provided from the Controller.Hardware.Keyboard and Controller.Standard to * actions in * @@ -217,7 +231,7 @@ class ScriptEngine; * controller outputs. Read-only. * * @property {Controller.Standard} Standard - Standard controller outputs that can be mapped to Actions or - * functions in a {@link RouteObject} mapping. Read-only.
+ * functions in a {@link RouteObject} mapping. Read-only.

* Each hardware device has a mapping from its outputs to Controller.Standard items, specified in a JSON file. * For example,
* leapmotion.json and @@ -253,7 +267,7 @@ public: public slots: /**jsdoc - * Disable default Interface actions for a particular key event. + * Disables default Interface actions for a particular key event. * @function Controller.captureKeyEvents * @param {KeyEvent} event - Details of the key event to be captured. The key property must be specified. The * text property is ignored. The other properties default to false. @@ -272,7 +286,7 @@ public slots: virtual void captureKeyEvents(const KeyEvent& event); /**jsdoc - * Re-enable default Interface actions for a particular key event that has been disabled using + * Re-enables default Interface actions for a particular key event that has been disabled using * {@link Controller.captureKeyEvents|captureKeyEvents}. * @function Controller.releaseKeyEvents * @param {KeyEvent} event - Details of the key event to release from capture. The key property must be @@ -281,7 +295,7 @@ public slots: virtual void releaseKeyEvents(const KeyEvent& event); /**jsdoc - * Disable default Interface actions for a joystick. + * Disables default Interface actions for a joystick. * @function Controller.captureJoystick * @param {number} joystickID - The integer ID of the joystick. * @deprecated This function is deprecated and will be removed. It no longer has any effect. @@ -289,7 +303,7 @@ public slots: virtual void captureJoystick(int joystickIndex); /**jsdoc - * Re-enable default Interface actions for a joystick that has been disabled using + * Re-enables default Interface actions for a joystick that has been disabled using * {@link Controller.captureJoystick|captureJoystick}. * @function Controller.releaseJoystick * @param {number} joystickID - The integer ID of the joystick. @@ -298,7 +312,7 @@ public slots: virtual void releaseJoystick(int joystickIndex); /**jsdoc - * Disable {@link Entities.mousePressOnEntity} and {@link Entities.mouseDoublePressOnEntity} events on entities. + * Disables {@link Entities.mousePressOnEntity} and {@link Entities.mouseDoublePressOnEntity} events on entities. * @function Controller.captureEntityClickEvents * @example * Entities.mousePressOnEntity.connect(function (entityID, event) { @@ -316,7 +330,7 @@ public slots: virtual void captureEntityClickEvents(); /**jsdoc - * Re-enable {@link Entities.mousePressOnEntity} and {@link Entities.mouseDoublePressOnEntity} events on entities that were + * Re-enables {@link Entities.mousePressOnEntity} and {@link Entities.mouseDoublePressOnEntity} events on entities that were * disabled using {@link Controller.captureEntityClickEvents|captureEntityClickEvents}. * @function Controller.releaseEntityClickEvents */ @@ -324,14 +338,14 @@ public slots: /**jsdoc - * Get the dimensions of the Interface window's interior if in desktop mode or the HUD surface if in HMD mode. + * Gets the dimensions of the Interface window's interior if in desktop mode or the HUD surface if in HMD mode. * @function Controller.getViewportDimensions * @returns {Vec2} The dimensions of the Interface window interior if in desktop mode or HUD surface if in HMD mode. */ virtual glm::vec2 getViewportDimensions() const; /**jsdoc - * Get the recommended area to position UI on the HUD surface if in HMD mode or Interface's window interior if in desktop + * Gets the recommended area to position UI on the HUD surface if in HMD mode or Interface's window interior if in desktop * mode. * @function Controller.getRecommendedHUDRect * @returns {Rect} The recommended area in which to position UI. diff --git a/libraries/controllers/src/controllers/Actions.cpp b/libraries/controllers/src/controllers/Actions.cpp index e34ce277e2..9f9d92fed7 100644 --- a/libraries/controllers/src/controllers/Actions.cpp +++ b/libraries/controllers/src/controllers/Actions.cpp @@ -35,9 +35,9 @@ namespace controller { /**jsdoc *

The Controller.Actions object has properties representing predefined actions on the user's avatar and - * Interface. The property values are integer IDs, uniquely identifying each action. Read-only. These can be used - * as end points in the routes of a {@link MappingObject}. The data routed to each action is either a number or a - * {@link Pose}.

+ * Interface. The property values are integer IDs, uniquely identifying each action. Read-only.

+ *

These actions can be used as end points in the routes of a {@link MappingObject}. The data item routed to each action + * is either a number or a {@link Pose}.

* *
Disable entity click events for a short period.
* @@ -178,7 +178,7 @@ namespace controller { * person view. * - * + * * * * @@ -238,71 +238,49 @@ namespace controller { * * + * action is deprecated and will be removed. Use RightHand instead. * + * action is deprecated and will be removed. Use BoomIn instead. * + * action is deprecated and will be removed. Use BoomOut instead. * + * action is deprecated and will be removed. Use ContextMenu instead. * + * action is deprecated and will be removed. Use ToggleMute instead. * + * action is deprecated and will be removed. Use TogglePushToTalk instead. * + * action is deprecated and will be removed. Use Sprint instead. * + * action is deprecated and will be removed. Use Backward instead. * + * action is deprecated and will be removed. Use Forward instead. * + * action is deprecated and will be removed. Use StrafeLeft instead. * + * action is deprecated and will be removed. Use StrafeRight instead. * + * action is deprecated and will be removed. Use Up instead. * + * action is deprecated and will be removed. Use Down instead. * + * action is deprecated and will be removed. Use PitchDown instead. * + * action is deprecated and will be removed. Use PitchUp instead. * + * action is deprecated and will be removed. Use YawLeft instead. * + * action is deprecated and will be removed. Use YawRight instead. * + * action is deprecated and will be removed. Use LeftHandClick instead. * + * action is deprecated and will be removed. Use RightHandClick instead. * + * action is deprecated and will be removed. Use Shift instead. * + * action is deprecated and will be removed. Use PrimaryAction instead. * + * action is deprecated and will be removed. Use SecondaryAction instead. * * * @@ -143,7 +143,7 @@ namespace controller { Q_INVOKABLE QVector getDeviceNames(); /**jsdoc - * Find the ID of an action from its name. + * Finds the ID of an action from its name. * @function Controller.findAction * @param {string} actionName - The name of the action: one of the {@link Controller.Actions} property names. * @returns {number} The integer ID of the action if found, otherwise 4095. Note that this value is not @@ -156,7 +156,7 @@ namespace controller { Q_INVOKABLE int findAction(QString actionName); /**jsdoc - * Get the names of all actions available as properties of {@link Controller.Actions}. + * Gets the names of all actions available as properties of {@link Controller.Actions}. * @function Controller.getActionNames * @returns {string[]} An array of action names. * @example @@ -167,7 +167,7 @@ namespace controller { Q_INVOKABLE QVector getActionNames() const; /**jsdoc - * Get the value of a controller button or axis output. Note: Also gets the value of a controller axis output. + * Gets the value of a controller button or axis output. Note: Also gets the value of a controller axis output. * @function Controller.getValue * @param {number} source - The {@link Controller.Standard} or {@link Controller.Hardware} item. * @returns {number} The current value of the controller item output if source is valid, otherwise @@ -186,7 +186,7 @@ namespace controller { Q_INVOKABLE float getValue(const int& source) const; /**jsdoc - * Get the value of a controller axis output. Note: Also gets the value of a controller button output. + * Gets the value of a controller axis output. Note: Also gets the value of a controller button output. * @function Controller.getAxisValue * @param {number} source - The {@link Controller.Standard} or {@link Controller.Hardware} item. * @returns {number} The current value of the controller item output if source is valid, otherwise @@ -196,7 +196,7 @@ namespace controller { Q_INVOKABLE float getAxisValue(int source) const; /**jsdoc - * Get the value of a controller pose output. + * Gets the value of a controller pose output. * @function Controller.getPoseValue * @param {number} source - The {@link Controller.Standard} or {@link Controller.Hardware} pose output. * @returns {Pose} The current value of the controller pose output if source is a pose output, otherwise @@ -210,9 +210,9 @@ namespace controller { /**jsdoc * Triggers a haptic pulse on connected and enabled devices that have the capability. * @function Controller.triggerHapticPulse - * @param {number} strength - The strength of the haptic pulse, 0.01.0. + * @param {number} strength - The strength of the haptic pulse, range 0.01.0. * @param {number} duration - The duration of the haptic pulse, in milliseconds. - * @param {Controller.Hand} hand=2 - The hand or hands to trigger the haptic pulse on. + * @param {Controller.Hand} [hand=2] - The hand or hands to trigger the haptic pulse on. * @example * var HAPTIC_STRENGTH = 0.5; * var HAPTIC_DURATION = 10; @@ -224,8 +224,8 @@ namespace controller { /**jsdoc * Triggers a 250ms haptic pulse on connected and enabled devices that have the capability. * @function Controller.triggerShortHapticPulse - * @param {number} strength - The strength of the haptic pulse, 0.01.0. - * @param {Controller.Hand} hand=2 - The hand or hands to trigger the haptic pulse on. + * @param {number} strength - The strength of the haptic pulse, range 0.01.0. + * @param {Controller.Hand} [hand=2] - The hand or hands to trigger the haptic pulse on. */ Q_INVOKABLE bool triggerShortHapticPulse(float strength, controller::Hand hand = BOTH) const; @@ -233,9 +233,9 @@ namespace controller { * Triggers a haptic pulse on a particular device if connected and enabled and it has the capability. * @function Controller.triggerHapticPulseOnDevice * @param {number} deviceID - The ID of the device to trigger the haptic pulse on. - * @param {number} strength - The strength of the haptic pulse, 0.01.0. + * @param {number} strength - The strength of the haptic pulse, range 0.01.0. * @param {number} duration - The duration of the haptic pulse, in milliseconds. - * @param {Controller.Hand} hand=2 - The hand or hands to trigger the haptic pulse on. + * @param {Controller.Hand} [hand=2] - The hand or hands to trigger the haptic pulse on. * @example * var HAPTIC_STRENGTH = 0.5; * var deviceID = Controller.findDevice("OculusTouch"); @@ -250,19 +250,19 @@ namespace controller { * Triggers a 250ms haptic pulse on a particular device if connected and enabled and it has the capability. * @function Controller.triggerShortHapticPulseOnDevice * @param {number} deviceID - The ID of the device to trigger the haptic pulse on. - * @param {number} strength - The strength of the haptic pulse, 0.01.0. - * @param {Controller.Hand} hand=2 - The hand or hands to trigger the haptic pulse on. + * @param {number} strength - The strength of the haptic pulse, range 0.01.0. + * @param {Controller.Hand} [hand=2] - The hand or hands to trigger the haptic pulse on. */ Q_INVOKABLE bool triggerShortHapticPulseOnDevice(unsigned int device, float strength, controller::Hand hand = BOTH) const; /**jsdoc - * Create a new controller mapping. Routes can then be added to the mapping using {@link MappingObject} methods and + * Creates a new controller mapping. Routes can then be added to the mapping using {@link MappingObject} methods and * routed to Standard controls, Actions, or script functions using {@link RouteObject} * methods. The mapping can then be enabled using {@link Controller.enableMapping|enableMapping} for it to take effect. * @function Controller.newMapping - * @param {string} mappingName=Uuid.generate() - A unique name for the mapping. If not specified a new UUID generated + * @param {string} [mappingName=Uuid.generate()] - A unique name for the mapping. If not specified a new UUID generated * by {@link Uuid.generate} is used. * @returns {MappingObject} A controller mapping object. * @example @@ -279,22 +279,22 @@ namespace controller { Q_INVOKABLE QObject* newMapping(const QString& mappingName = QUuid::createUuid().toString()); /**jsdoc - * Enable or disable a controller mapping. When enabled, the routes in the mapping have effect. + * Enables or disables a controller mapping. When enabled, the routes in the mapping have effect. * @function Controller.enableMapping * @param {string} mappingName - The name of the mapping. - * @param {boolean} enable=true - If true then the mapping is enabled, otherwise it is disabled. + * @param {boolean} [[enable=true] - If true then the mapping is enabled, otherwise it is disabled. */ Q_INVOKABLE void enableMapping(const QString& mappingName, bool enable = true); /**jsdoc - * Disable a controller mapping. When disabled, the routes in the mapping have no effect. + * Disables a controller mapping. When disabled, the routes in the mapping have no effect. * @function Controller.disableMapping * @param {string} mappingName - The name of the mapping. */ Q_INVOKABLE void disableMapping(const QString& mappingName) { enableMapping(mappingName, false); } /**jsdoc - * Create a new controller mapping from a {@link Controller.MappingJSON|MappingJSON} string. Use + * Creates a new controller mapping from a {@link Controller.MappingJSON|MappingJSON} string. Use * {@link Controller.enableMapping|enableMapping} to enable the mapping for it to take effect. * @function Controller.parseMapping * @param {string} jsonString - A JSON string of the {@link Controller.MappingJSON|MappingJSON}. @@ -317,19 +317,19 @@ namespace controller { Q_INVOKABLE QObject* parseMapping(const QString& json); /**jsdoc - * Create a new controller mapping from a {@link Controller.MappingJSON|MappingJSON} JSON file at a URL. Use + * Creates a new controller mapping from a {@link Controller.MappingJSON|MappingJSON} JSON file at a URL. Use * {@link Controller.enableMapping|enableMapping} to enable the mapping for it to take effect. + *

Warning: This function is not yet implemented; it doesn't load a mapping and just returns + * null. * @function Controller.loadMapping * @param {string} jsonURL - The URL the {@link Controller.MappingJSON|MappingJSON} JSON file. * @returns {MappingObject} A controller mapping object. - * @todo Implement this function. It currently does not load the mapping from the file; it just returns - * null. */ Q_INVOKABLE QObject* loadMapping(const QString& jsonUrl); /**jsdoc - * Get the {@link Controller.Hardware} property tree. Calling this function is the same as using the {@link Controller} + * Gets the {@link Controller.Hardware} property tree. Calling this function is the same as using the {@link Controller} * property, Controller.Hardware. * @function Controller.getHardware * @returns {Controller.Hardware} The {@link Controller.Hardware} property tree. @@ -337,7 +337,7 @@ namespace controller { Q_INVOKABLE const QVariantMap getHardware() { return _hardware; } /**jsdoc - * Get the {@link Controller.Actions} property tree. Calling this function is the same as using the {@link Controller} + * Gets the {@link Controller.Actions} property tree. Calling this function is the same as using the {@link Controller} * property, Controller.Actions. * @function Controller.getActions * @returns {Controller.Actions} The {@link Controller.Actions} property tree. @@ -345,7 +345,7 @@ namespace controller { Q_INVOKABLE const QVariantMap getActions() { return _actions; } //undefined /**jsdoc - * Get the {@link Controller.Standard} property tree. Calling this function is the same as using the {@link Controller} + * Gets the {@link Controller.Standard} property tree. Calling this function is the same as using the {@link Controller} * property, Controller.Standard. * @function Controller.getStandard * @returns {Controller.Standard} The {@link Controller.Standard} property tree. @@ -354,7 +354,7 @@ namespace controller { /**jsdoc - * Start making a recording of currently active controllers. + * Starts making a recording of currently active controllers. * @function Controller.startInputRecording * @example

* // Delay start of recording for 2s. @@ -374,13 +374,13 @@ namespace controller { Q_INVOKABLE void startInputRecording(); /**jsdoc - * Stop making a recording started by {@link Controller.startInputRecording|startInputRecording}. + * Stops making a recording started by {@link Controller.startInputRecording|startInputRecording}. * @function Controller.stopInputRecording */ Q_INVOKABLE void stopInputRecording(); /**jsdoc - * Play back the current recording from the beginning. The current recording may have been recorded by + * Plays back the current recording from the beginning. The current recording may have been recorded by * {@link Controller.startInputRecording|startInputRecording} and * {@link Controller.stopInputRecording|stopInputRecording}, or loaded by * {@link Controller.loadInputRecording|loadInputRecording}. Playback repeats in a loop until @@ -403,13 +403,13 @@ namespace controller { Q_INVOKABLE void startInputPlayback(); /**jsdoc - * Stop play back of a recording started by {@link Controller.startInputPlayback|startInputPlayback}. + * Stops play back of a recording started by {@link Controller.startInputPlayback|startInputPlayback}. * @function Controller.stopInputPlayback */ Q_INVOKABLE void stopInputPlayback(); /**jsdoc - * Save the current recording to a file. The current recording may have been recorded by + * Saves the current recording to a file. The current recording may have been recorded by * {@link Controller.startInputRecording|startInputRecording} and * {@link Controller.stopInputRecording|stopInputRecording}, or loaded by * {@link Controller.loadInputRecording|loadInputRecording}. It is saved in the directory returned by @@ -419,24 +419,26 @@ namespace controller { Q_INVOKABLE void saveInputRecording(); /**jsdoc - * Load an input recording, ready for play back. + * Loads an input recording, ready for play back. * @function Controller.loadInputRecording * @param {string} file - The path to the recording file, prefixed by "file:///". */ Q_INVOKABLE void loadInputRecording(const QString& file); /**jsdoc - * Get the directory in which input recordings are saved. + * Gets the directory in which input recordings are saved. * @function Controller.getInputRecorderSaveDirectory * @returns {string} The directory in which input recordings are saved. */ Q_INVOKABLE QString getInputRecorderSaveDirectory(); /**jsdoc - * Get all the active and enabled (running) input devices - * @function Controller.getRunningInputDevices - * @returns {string[]} An array of strings with the names - */ + * Gets the names of all the active and running (enabled) input devices. + * @function Controller.getRunningInputDevices + * @returns {string[]} The list of current active and running input devices. + * @example + * print("Running devices: " + JSON.stringify(Controller.getRunningInputDeviceNames())); + */ Q_INVOKABLE QStringList getRunningInputDeviceNames(); bool isMouseCaptured() const { return _mouseCaptured; } @@ -447,7 +449,7 @@ namespace controller { public slots: /**jsdoc - * Disable processing of mouse "move", "press", "double-press", and "release" events into + * Disables processing of mouse "move", "press", "double-press", and "release" events into * {@link Controller.Hardware|Controller.Hardware.Keyboard} outputs. * @function Controller.captureMouseEvents * @example @@ -475,7 +477,7 @@ namespace controller { virtual void captureMouseEvents() { _mouseCaptured = true; } /**jsdoc - * Enable processing of mouse "move", "press", "double-press", and "release" events into + * Enables processing of mouse "move", "press", "double-press", and "release" events into * {@link Controller.Hardware-Keyboard|Controller.Hardware.Keyboard} outputs that were disabled using * {@link Controller.captureMouseEvents|captureMouseEvents}. * @function Controller.releaseMouseEvents @@ -484,7 +486,7 @@ namespace controller { /**jsdoc - * Disable processing of touch "begin", "update", and "end" events into + * Disables processing of touch "begin", "update", and "end" events into * {@link Controller.Hardware|Controller.Hardware.Keyboard}, * {@link Controller.Hardware|Controller.Hardware.Touchscreen}, and * {@link Controller.Hardware|Controller.Hardware.TouchscreenVirtualPad} outputs. @@ -493,7 +495,7 @@ namespace controller { virtual void captureTouchEvents() { _touchCaptured = true; } /**jsdoc - * Enable processing of touch "begin", "update", and "end" events into + * Enables processing of touch "begin", "update", and "end" events into * {@link Controller.Hardware|Controller.Hardware.Keyboard}, * {@link Controller.Hardware|Controller.Hardware.Touchscreen}, and * {@link Controller.Hardware|Controller.Hardware.TouchscreenVirtualPad} outputs that were disabled using @@ -504,14 +506,14 @@ namespace controller { /**jsdoc - * Disable processing of mouse wheel rotation events into {@link Controller.Hardware|Controller.Hardware.Keyboard} + * Disables processing of mouse wheel rotation events into {@link Controller.Hardware|Controller.Hardware.Keyboard} * outputs. * @function Controller.captureWheelEvents */ virtual void captureWheelEvents() { _wheelCaptured = true; } /**jsdoc - * Enable processing of mouse wheel rotation events into {@link Controller.Hardware|Controller.Hardware.Keyboard} + * Enables processing of mouse wheel rotation events into {@link Controller.Hardware|Controller.Hardware.Keyboard} * outputs that wer disabled using {@link Controller.captureWheelEvents|captureWheelEvents}. * @function Controller.releaseWheelEvents */ @@ -519,7 +521,7 @@ namespace controller { /**jsdoc - * Disable translating and rotating the user's avatar in response to keyboard and controller controls. + * Disables translating and rotating the user's avatar in response to keyboard and controller controls. * @function Controller.captureActionEvents * @example * Script.setTimeout(function () { @@ -533,12 +535,19 @@ namespace controller { virtual void captureActionEvents() { _actionsCaptured = true; } /**jsdoc - * Enable translating and rotating the user's avatar in response to keyboard and controller controls that were disabled + * Enables translating and rotating the user's avatar in response to keyboard and controller controls that were disabled * using {@link Controller.captureActionEvents|captureActionEvents}. * @function Controller.releaseActionEvents */ virtual void releaseActionEvents() { _actionsCaptured = false; } + /**jsdoc + * @function Controller.updateRunningInputDevices + * @param {string} deviceName - Device name. + * @param {boolean} isRunning - Is running. + * @param {string[]} runningDevices - Running devices. + * @deprecated This function is deprecated and will be removed. + */ void updateRunningInputDevices(const QString& deviceName, bool isRunning, const QStringList& runningDevices); signals: @@ -593,7 +602,7 @@ namespace controller { /**jsdoc * Triggered when a device is registered or unregistered by a plugin. Not all plugins generate - * hardwareChanged events: for example connecting or disconnecting a mouse will not generate an event but + * hardwareChanged events: for example, connecting or disconnecting a mouse will not generate an event but * connecting or disconnecting an Xbox controller will. * @function Controller.hardwareChanged * @returns {Signal} @@ -601,13 +610,13 @@ namespace controller { void hardwareChanged(); /**jsdoc - * Triggered when a device is enabled/disabled - * Enabling/Disabling Leapmotion on settings/controls will trigger this signal. - * @function Controller.deviceRunningChanged - * @param {string} deviceName - The name of the device that is getting enabled/disabled - * @param {boolean} isEnabled - Return if the device is enabled. - * @returns {Signal} - */ + * Triggered when an input device starts or stops being active and running (enabled). For example, enabling or + * disabling the LeapMotion in Settings > Controls > Calibration will trigger this signal. + * @function Controller.inputDeviceRunningChanged + * @param {string} deviceName - The name of the device. + * @param {boolean} isRunning - true if the device is active and running, false if it isn't. + * @returns {Signal} + */ void inputDeviceRunningChanged(QString deviceName, bool isRunning); diff --git a/libraries/controllers/src/controllers/StandardController.cpp b/libraries/controllers/src/controllers/StandardController.cpp index e1733d2524..ece10ecca3 100644 --- a/libraries/controllers/src/controllers/StandardController.cpp +++ b/libraries/controllers/src/controllers/StandardController.cpp @@ -30,17 +30,16 @@ void StandardController::focusOutEvent() { /**jsdoc *

The Controller.Standard object has properties representing standard controller outputs. Those for physical * controllers are based on the XBox controller, with aliases for PlayStation. The property values are integer IDs, uniquely - * identifying each output. Read-only. These can be mapped to actions or functions in a {@link RouteObject} - * mapping.

- * - *

The data value provided by each control is either a number or a {@link Pose}. Numbers are typically normalized to - * 0.0 or 1.0 for button states, the range 0.0 – 1.0 for unidirectional scales, - * and the range -1.0 – 1.0 for bidirectional scales.

- * - *

Each hardware device has a mapping from its outputs to Controller.Standard items, specified in a JSON file. - * For example, - * leapmotion.json and - * vive.json.

+ * identifying each output. Read-only.

+ *

These outputs can be mapped to actions or functions in a {@link RouteObject} mapping. The data value provided by each + * control is either a number or a {@link Pose}. Numbers are typically normalized to 0.0 or 1.0 for + * button states, the range 0.0 – 1.0 for unidirectional scales, and the range + * -1.01.0 for bidirectional scales.

+ *

Each hardware device has a mapping from its outputs to a subset of Controller.Standard items, specified in a + * JSON file. For example, + * vive.json + * and + * leapmotion.json.

* *
CycleCameranumbernumberCycle the camera view from first person, to * third person, to full screen mirror, then back to first person and repeat.
ContextMenunumbernumberShow / hide the tablet.
ContextMenunumbernumberShow/hide the tablet.
ToggleMutenumbernumberToggle the microphone mute.
TogglePushToTalknumbernumberToggle push to talk.
ToggleOverlaynumbernumberToggle the display of overlays.
LEFT_HANDnumber{@link Pose}Deprecated: This * action is deprecated and will be removed. Use LeftHand instead.
RIGHT_HANDnumber{@link Pose}Deprecated: This - * action is deprecated and will be removed. Use - * RightHand instead.
BOOM_INnumbernumberDeprecated: This - * action is deprecated and will be removed. Use - * BoomIn instead.
BOOM_OUTnumbernumberDeprecated: This - * action is deprecated and will be removed. Use - * BoomOut instead.
CONTEXT_MENUnumbernumberDeprecated: This - * action is deprecated and will be removed. Use - * ContextMenu instead.
TOGGLE_MUTEnumbernumberDeprecated: This - * action is deprecated and will be removed. Use - * ToggleMute instead.
TOGGLE_PUSHTOTALKnumbernumberDeprecated: This - * action is deprecated and will be removed. Use - * TogglePushToTalk instead.
SPRINTnumbernumberDeprecated: This - * action is deprecated and will be removed. Use - * Sprint instead.
LONGITUDINAL_BACKWARDnumbernumberDeprecated: This - * action is deprecated and will be removed. Use - * Backward instead.
LONGITUDINAL_FORWARDnumbernumberDeprecated: This - * action is deprecated and will be removed. Use - * Forward instead.
LATERAL_LEFTnumbernumberDeprecated: This - * action is deprecated and will be removed. Use - * StrafeLeft instead.
LATERAL_RIGHTnumbernumberDeprecated: This - * action is deprecated and will be removed. Use - * StrafeRight instead.
VERTICAL_UPnumbernumberDeprecated: This - * action is deprecated and will be removed. Use - * Up instead.
VERTICAL_DOWNnumbernumberDeprecated: This - * action is deprecated and will be removed. Use - * Down instead.
PITCH_DOWNnumbernumberDeprecated: This - * action is deprecated and will be removed. Use - * PitchDown instead.
PITCH_UPnumbernumberDeprecated: This - * action is deprecated and will be removed. Use - * PitchUp instead.
YAW_LEFTnumbernumberDeprecated: This - * action is deprecated and will be removed. Use - * YawLeft instead.
YAW_RIGHTnumbernumberDeprecated: This - * action is deprecated and will be removed. Use - * YawRight instead.
LEFT_HAND_CLICKnumbernumberDeprecated: This - * action is deprecated and will be removed. Use - * LeftHandClick instead.
RIGHT_HAND_CLICKnumbernumberDeprecated: This - * action is deprecated and will be removed. Use - * RightHandClick instead.
SHIFTnumbernumberDeprecated: This - * action is deprecated and will be removed. Use - * Shift instead.
ACTION1numbernumberDeprecated: This - * action is deprecated and will be removed. Use - * PrimaryAction instead.
ACTION2numbernumberDeprecated: This - * action is deprecated and will be removed. Use - * SecondaryAction instead.
Deprecated Trackers
TrackedObject00number{@link Pose}Deprecated: diff --git a/libraries/controllers/src/controllers/InputDevice.h b/libraries/controllers/src/controllers/InputDevice.h index 7c3c31cb38..95d0524a4a 100644 --- a/libraries/controllers/src/controllers/InputDevice.h +++ b/libraries/controllers/src/controllers/InputDevice.h @@ -54,10 +54,9 @@ enum Hand { /**jsdoc *

The Controller.Hardware object has properties representing standard and hardware-specific controller and - * computer outputs, plus predefined actions on Interface and the user's avatar. Read-only. The outputs can be mapped - * to actions or functions in a {@link RouteObject} mapping. Additionally, hardware-specific controller outputs can be mapped - * to standard controller outputs. - * + * computer outputs, plus predefined actions on Interface and the user's avatar. Read-only.

+ *

The outputs can be mapped to actions or functions in a {@link RouteObject} mapping. Additionally, hardware-specific + * controller outputs can be mapped to standard controller outputs. *

Controllers typically implement a subset of the {@link Controller.Standard} controls, plus they may implement some extras. * Some common controllers are included in the table. You can see the outputs provided by these and others by * viewing their {@link Controller.MappingJSON|MappingJSON} files at diff --git a/libraries/controllers/src/controllers/ScriptingInterface.cpp b/libraries/controllers/src/controllers/ScriptingInterface.cpp index 07c59e1aaa..fd32b2eb43 100644 --- a/libraries/controllers/src/controllers/ScriptingInterface.cpp +++ b/libraries/controllers/src/controllers/ScriptingInterface.cpp @@ -227,6 +227,7 @@ namespace controller { } QObject* ScriptingInterface::loadMapping(const QString& jsonUrl) { + // FIXME: Implement. https://highfidelity.manuscript.com/f/cases/14188/Implement-Controller-loadMappping return nullptr; } diff --git a/libraries/controllers/src/controllers/ScriptingInterface.h b/libraries/controllers/src/controllers/ScriptingInterface.h index 156fc1af7c..84396fc8be 100644 --- a/libraries/controllers/src/controllers/ScriptingInterface.h +++ b/libraries/controllers/src/controllers/ScriptingInterface.h @@ -73,7 +73,7 @@ namespace controller { virtual ~ScriptingInterface() {}; /**jsdoc - * Get a list of all available actions. + * Gets a list of all available actions. * @function Controller.getAllActions * @returns {Action[]} All available actions. * @deprecated This function is deprecated and will be removed. It no longer works. @@ -82,7 +82,7 @@ namespace controller { Q_INVOKABLE QVector getAllActions(); /**jsdoc - * Get a list of all available inputs for a hardware device. + * Gets a list of all available inputs for a hardware device. * @function Controller.getAvailableInputs * @param {number} deviceID - Integer ID of the hardware device. * @returns {NamedPair[]} All available inputs for the device. @@ -92,7 +92,7 @@ namespace controller { Q_INVOKABLE QVector getAvailableInputs(unsigned int device); /**jsdoc - * Find the name of a particular controller from its device ID. + * Finds the name of a particular controller from its device ID. * @function Controller.getDeviceName * @param {number} deviceID - The integer ID of the device. * @returns {string} The name of the device if found, otherwise "unknown". @@ -106,7 +106,7 @@ namespace controller { Q_INVOKABLE QString getDeviceName(unsigned int device); /**jsdoc - * Get the current value of an action. + * Gets the current value of an action. * @function Controller.getActionValue * @param {number} actionID - The integer ID of the action. * @returns {number} The current value of the action. @@ -121,7 +121,7 @@ namespace controller { Q_INVOKABLE float getActionValue(int action); /**jsdoc - * Find the ID of a specific controller from its device name. + * Finds the ID of a specific controller from its device name. * @function Controller.findDevice * @param {string} deviceName - The name of the device to find. * @returns {number} The integer ID of the device if available, otherwise 65535. @@ -132,7 +132,7 @@ namespace controller { Q_INVOKABLE int findDevice(QString name); /**jsdoc - * Get the names of all currently available controller devices plus "Actions", "Application", and "Standard". + * Gets the names of all currently available controller devices plus "Actions", "Application", and "Standard". * @function Controller.getDeviceNames * @returns {string[]} An array of device names. * @example

Get the names of all currently available controller devices.Get the names of all actions.Trigger a haptic pulse on the right hand.Trigger a haptic pulse on an Oculus Touch controller.Create a simple mapping that makes the right trigger move your avatar up.Make a controller recording.List all active and running input devices.Disable Controller.Hardware.Keyboard mouse events for a short period.Disable avatar translation and rotation for a short period.
* @@ -119,12 +118,12 @@ void StandardController::focusOutEvent() { * button. * - * + * * * + * * * * var MAPPING_NAME = "com.highfidelity.controllers.example.newMapping"; @@ -193,7 +195,7 @@ class RouteBuilderProxy : public QObject { Q_INVOKABLE QObject* when(const QScriptValue& expression); /**jsdoc - * Filter numeric route values to lie between two values; values outside this range are not passed on through the + * Filters numeric route values to lie between two values; values outside this range are not passed on through the * route. * @function RouteObject#clamp * @param {number} min - The minimum value to pass through. @@ -214,7 +216,7 @@ class RouteBuilderProxy : public QObject { Q_INVOKABLE QObject* clamp(float min, float max); /**jsdoc - * Filter numeric route values such that they are rounded to 0 or 1 without output values + * Filters numeric route values such that they are rounded to 0 or 1 without output values * flickering when the input value hovers around 0.5. For example, this enables you to use an analog input * as if it were a toggle. * @function RouteObject#hysteresis @@ -239,7 +241,7 @@ class RouteBuilderProxy : public QObject { Q_INVOKABLE QObject* hysteresis(float min, float max); /**jsdoc - * Filter numeric route values to send at a specified interval. + * Filters numeric route values to send at a specified interval. * @function RouteObject#pulse * @param {number} interval - The interval between sending values, in seconds. * @returns {RouteObject} The RouteObject with the filter applied. @@ -258,7 +260,7 @@ class RouteBuilderProxy : public QObject { Q_INVOKABLE QObject* pulse(float interval); /**jsdoc - * Filter numeric and {@link Pose} route values to be scaled by a constant amount. + * Filters numeric and {@link Pose} route values to be scaled by a constant amount. * @function RouteObject#scale * @param {number} multiplier - The scale to multiply the value by. * @returns {RouteObject} The RouteObject with the filter applied. @@ -280,7 +282,7 @@ class RouteBuilderProxy : public QObject { Q_INVOKABLE QObject* scale(float multiplier); /**jsdoc - * Filter numeric and {@link Pose} route values to have the opposite sign, e.g., 0.5 is changed to + * Filters numeric and {@link Pose} route values to have the opposite sign, e.g., 0.5 is changed to * -0.5. * @function RouteObject#invert * @returns {RouteObject} The RouteObject with the filter applied. @@ -302,7 +304,7 @@ class RouteBuilderProxy : public QObject { Q_INVOKABLE QObject* invert(); /**jsdoc - * Filter numeric route values such that they're sent only when the input value is outside a dead-zone. When the input + * Filters numeric route values such that they're sent only when the input value is outside a dead-zone. When the input * passes the dead-zone value, output is sent starting at 0.0 and catching up with the input value. As the * input returns toward the dead-zone value, output values reduce to 0.0 at the dead-zone value. * @function RouteObject#deadZone @@ -324,7 +326,7 @@ class RouteBuilderProxy : public QObject { Q_INVOKABLE QObject* deadZone(float min); /**jsdoc - * Filter numeric route values such that they are rounded to -1, 0, or 1. + * Filters numeric route values such that they are rounded to -1, 0, or 1. * For example, this enables you to use an analog input as if it were a toggle or, in the case of a bidirectional axis, * a tri-state switch. * @function RouteObject#constrainToInteger @@ -345,7 +347,7 @@ class RouteBuilderProxy : public QObject { Q_INVOKABLE QObject* constrainToInteger(); /**jsdoc - * Filter numeric route values such that they are rounded to 0 or 1. For example, this + * Filters numeric route values such that they are rounded to 0 or 1. For example, this * enables you to use an analog input as if it were a toggle. * @function RouteObject#constrainToPositiveInteger * @returns {RouteObject} The RouteObject with the filter applied. @@ -364,7 +366,7 @@ class RouteBuilderProxy : public QObject { Q_INVOKABLE QObject* constrainToPositiveInteger(); /**jsdoc - * Filter {@link Pose} route values to have a pre-translation applied. + * Filters {@link Pose} route values to have a pre-translation applied. * @function RouteObject#translate * @param {Vec3} translate - The pre-translation to add to the pose. * @returns {RouteObject} The RouteObject with the pre-translation applied. @@ -373,7 +375,7 @@ class RouteBuilderProxy : public QObject { Q_INVOKABLE QObject* translate(glm::vec3 translate); /**jsdoc - * Filter {@link Pose} route values to have a pre-transform applied. + * Filters {@link Pose} route values to have a pre-transform applied. * @function RouteObject#transform * @param {Mat4} transform - The pre-transform to apply. * @returns {RouteObject} The RouteObject with the pre-transform applied. @@ -382,7 +384,7 @@ class RouteBuilderProxy : public QObject { Q_INVOKABLE QObject* transform(glm::mat4 transform); /**jsdoc - * Filter {@link Pose} route values to have a post-transform applied. + * Filters {@link Pose} route values to have a post-transform applied. * @function RouteObject#postTransform * @param {Mat4} transform - The post-transform to apply. * @returns {RouteObject} The RouteObject with the post-transform applied. @@ -391,7 +393,7 @@ class RouteBuilderProxy : public QObject { Q_INVOKABLE QObject* postTransform(glm::mat4 transform); /**jsdoc - * Filter {@link Pose} route values to have a pre-rotation applied. + * Filters {@link Pose} route values to have a pre-rotation applied. * @function RouteObject#rotate * @param {Quat} rotation - The pre-rotation to add to the pose. * @returns {RouteObject} The RouteObject with the pre-rotation applied. @@ -400,7 +402,7 @@ class RouteBuilderProxy : public QObject { Q_INVOKABLE QObject* rotate(glm::quat rotation); /**jsdoc - * Filter {@link Pose} route values to be smoothed by a low velocity filter. The filter's rotation and translation + * Filters {@link Pose} route values to be smoothed by a low velocity filter. The filter's rotation and translation * values are calculated as: (1 - f) * currentValue + f * previousValue where * f = currentVelocity / filterConstant. At low velocities, the filter value is largely the previous * value; at high velocities the value is wholly the current controller value. @@ -415,7 +417,7 @@ class RouteBuilderProxy : public QObject { Q_INVOKABLE QObject* lowVelocity(float rotationConstant, float translationConstant); /**jsdoc - * Filter {@link Pose} route values to be smoothed by an exponential decay filter. The filter's rotation and + * Filters {@link Pose} route values to be smoothed by an exponential decay filter. The filter's rotation and * translation values are calculated as: filterConstant * currentValue + (1 - filterConstant) * * previousValue. Values near 1 are less smooth with lower latency; values near 0 are more smooth with higher * latency. @@ -428,7 +430,7 @@ class RouteBuilderProxy : public QObject { Q_INVOKABLE QObject* exponentialSmoothing(float rotationConstant, float translationConstant); /**jsdoc - * Filter numeric route values such that a value of 0.0 is changed to 1.0, and other values + * Filters numeric route values such that a value of 0.0 is changed to 1.0, and other values * are changed to 0.0. * @function RouteObject#logicalNot * @returns {RouteObject} The RouteObject with the filter applied. diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index 6cfff7bc41..7d130125b3 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -205,8 +205,11 @@ void EntityTreeRenderer::stopDomainAndNonOwnedEntities() { foreach (const EntityItemID& entityID, entitiesWithEntityScripts) { EntityItemPointer entityItem = getTree()->findEntityByEntityItemID(entityID); - if (entityItem) { + if (entityItem && !entityItem->getScript().isEmpty()) { if (!(entityItem->isLocalEntity() || (entityItem->isAvatarEntity() && entityItem->getOwningAvatarID() == getTree()->getMyAvatarSessionUUID()))) { + if (entityItem->contains(_avatarPosition)) { + _entitiesScriptEngine->callEntityScriptMethod(entityID, "leaveEntity"); + } _entitiesScriptEngine->unloadEntityScript(entityID, true); } } @@ -534,7 +537,7 @@ void EntityTreeRenderer::handleSpaceUpdate(std::pair proxyUp _spaceUpdates.emplace_back(proxyUpdate.first, proxyUpdate.second); } -bool EntityTreeRenderer::findBestZoneAndMaybeContainingEntities(QVector* entitiesContainingAvatar) { +bool EntityTreeRenderer::findBestZoneAndMaybeContainingEntities(QSet& entitiesContainingAvatar) { bool didUpdate = false; float radius = 0.01f; // for now, assume 0.01 meter radius, because we actually check the point inside later QVector entityIDs; @@ -580,9 +583,7 @@ bool EntityTreeRenderer::findBestZoneAndMaybeContainingEntities(QVectorgetEntityItemID(); - } + entitiesContainingAvatar << entity->getEntityItemID(); } } } @@ -616,36 +617,36 @@ bool EntityTreeRenderer::checkEnterLeaveEntities() { auto movedEnough = glm::distance(avatarPosition, _avatarPosition) > ZONE_CHECK_DISTANCE; auto enoughTimeElapsed = (now - _lastZoneCheck) > ZONE_CHECK_INTERVAL; - if (movedEnough || enoughTimeElapsed) { + if (_forceRecheckEntities || movedEnough || enoughTimeElapsed) { _avatarPosition = avatarPosition; _lastZoneCheck = now; - QVector entitiesContainingAvatar; - didUpdate = findBestZoneAndMaybeContainingEntities(&entitiesContainingAvatar); - + _forceRecheckEntities = false; + + QSet entitiesContainingAvatar; + didUpdate = findBestZoneAndMaybeContainingEntities(entitiesContainingAvatar); + // Note: at this point we don't need to worry about the tree being locked, because we only deal with // EntityItemIDs from here. The callEntityScriptMethod() method is robust against attempting to call scripts // for entity IDs that no longer exist. - // for all of our previous containing entities, if they are no longer containing then send them a leave event - foreach(const EntityItemID& entityID, _currentEntitiesInside) { - if (!entitiesContainingAvatar.contains(entityID)) { - emit leaveEntity(entityID); - if (_entitiesScriptEngine) { + if (_entitiesScriptEngine) { + // for all of our previous containing entities, if they are no longer containing then send them a leave event + foreach(const EntityItemID& entityID, _currentEntitiesInside) { + if (!entitiesContainingAvatar.contains(entityID)) { + emit leaveEntity(entityID); _entitiesScriptEngine->callEntityScriptMethod(entityID, "leaveEntity"); } } - } - // for all of our new containing entities, if they weren't previously containing then send them an enter event - foreach(const EntityItemID& entityID, entitiesContainingAvatar) { - if (!_currentEntitiesInside.contains(entityID)) { - emit enterEntity(entityID); - if (_entitiesScriptEngine) { + // for all of our new containing entities, if they weren't previously containing then send them an enter event + foreach(const EntityItemID& entityID, entitiesContainingAvatar) { + if (!_currentEntitiesInside.contains(entityID)) { + emit enterEntity(entityID); _entitiesScriptEngine->callEntityScriptMethod(entityID, "enterEntity"); } } + _currentEntitiesInside = entitiesContainingAvatar; } - _currentEntitiesInside = entitiesContainingAvatar; } } return didUpdate; @@ -653,7 +654,7 @@ bool EntityTreeRenderer::checkEnterLeaveEntities() { void EntityTreeRenderer::leaveDomainAndNonOwnedEntities() { if (_tree && !_shuttingDown) { - QVector currentEntitiesInsideToSave; + QSet currentEntitiesInsideToSave; foreach (const EntityItemID& entityID, _currentEntitiesInside) { EntityItemPointer entityItem = getTree()->findEntityByEntityItemID(entityID); if (!(entityItem->isLocalEntity() || (entityItem->isAvatarEntity() && entityItem->getOwningAvatarID() == getTree()->getMyAvatarSessionUUID()))) { @@ -662,7 +663,7 @@ void EntityTreeRenderer::leaveDomainAndNonOwnedEntities() { _entitiesScriptEngine->callEntityScriptMethod(entityID, "leaveEntity"); } } else { - currentEntitiesInsideToSave.push_back(entityID); + currentEntitiesInsideToSave.insert(entityID); } } @@ -687,9 +688,7 @@ void EntityTreeRenderer::leaveAllEntities() { } void EntityTreeRenderer::forceRecheckEntities() { - // make sure our "last avatar position" is something other than our current position, - // so that on our next chance, we'll check for enter/leave entity events. - _avatarPosition = _viewState->getAvatarPosition() + glm::vec3((float)TREE_SCALE); + _forceRecheckEntities = true; } bool EntityTreeRenderer::applyLayeredZones() { @@ -992,7 +991,10 @@ void EntityTreeRenderer::deletingEntity(const EntityItemID& entityID) { return; } - if (_tree && !_shuttingDown && _entitiesScriptEngine) { + if (_tree && !_shuttingDown && _entitiesScriptEngine && !itr->second->getEntity()->getScript().isEmpty()) { + if (itr->second->getEntity()->contains(_avatarPosition)) { + _entitiesScriptEngine->callEntityScriptMethod(entityID, "leaveEntity"); + } _entitiesScriptEngine->unloadEntityScript(entityID, true); } @@ -1038,6 +1040,9 @@ void EntityTreeRenderer::checkAndCallPreload(const EntityItemID& entityID, bool QString scriptUrl = entity->getScript(); if ((shouldLoad && unloadFirst) || scriptUrl.isEmpty()) { if (_entitiesScriptEngine) { + if (entity->contains(_avatarPosition)) { + _entitiesScriptEngine->callEntityScriptMethod(entityID, "leaveEntity"); + } _entitiesScriptEngine->unloadEntityScript(entityID); } entity->scriptHasUnloaded(); diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.h b/libraries/entities-renderer/src/EntityTreeRenderer.h index cee91ad1c7..05105a2c7f 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.h +++ b/libraries/entities-renderer/src/EntityTreeRenderer.h @@ -169,7 +169,7 @@ private: void resetEntitiesScriptEngine(); - bool findBestZoneAndMaybeContainingEntities(QVector* entitiesContainingAvatar = nullptr); + bool findBestZoneAndMaybeContainingEntities(QSet& entitiesContainingAvatar); bool applyLayeredZones(); void stopDomainAndNonOwnedEntities(); @@ -186,7 +186,8 @@ private: void forceRecheckEntities(); glm::vec3 _avatarPosition { 0.0f }; - QVector _currentEntitiesInside; + bool _forceRecheckEntities { true }; + QSet _currentEntitiesInside; bool _wantScripts; ScriptEnginePointer _entitiesScriptEngine; diff --git a/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.cpp b/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.cpp index 3383d71a52..0a6c76e456 100755 --- a/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.cpp +++ b/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.cpp @@ -219,9 +219,10 @@ controller::Input KeyboardMouseDevice::InputDevice::makeInput(KeyboardMouseDevic /**jsdoc *

The Controller.Hardware.Keyboard object has properties representing keyboard, mouse, and display touch - * events. The property values are integer IDs, uniquely identifying each output. Read-only. These can be mapped to - * actions or functions or Controller.Standard items in a {@link RouteObject} mapping. For presses, each data - * value is either 1.0 for "true" or 0.0 for "false".

+ * events. The property values are integer IDs, uniquely identifying each output. Read-only.

+ *

These events can be mapped to actions or functions or Controller.Standard items in a {@link RouteObject} + * mapping. For presses, each data value is either 1.0 for "true" or 0.0 for "false".

+ * *
RightThumbUpnumbernumberRight thumb not touching primary or secondary * thumb buttons.
LeftPrimaryIndexnumbernumberLeft primary index control pressed. - * To Do: Implement this for current controllers.
LeftPrimaryIndexnumbernumberLeft primary index control + * pressed.
LeftSecondaryIndexnumbernumberLeft secondary index control pressed. *
RightPrimaryIndexnumbernumberRight primary index control pressed. - * To Do: Implement this for current controllers.
RightSecondaryIndexnumbernumberRight secondary index control pressed. *
LeftPrimaryIndexTouchnumbernumberLeft index finger is touching primary diff --git a/libraries/controllers/src/controllers/impl/MappingBuilderProxy.h b/libraries/controllers/src/controllers/impl/MappingBuilderProxy.h index 845e19f6c3..f0a823a3de 100644 --- a/libraries/controllers/src/controllers/impl/MappingBuilderProxy.h +++ b/libraries/controllers/src/controllers/impl/MappingBuilderProxy.h @@ -84,12 +84,12 @@ class UserInputMapper; /**jsdoc * A route in a {@link Controller.MappingJSON}. * @typedef {object} Controller.MappingJSONRoute - * @property {string|Controller.MappingJSONAxis} from - The name of a {@link Controller.Hardware} property name or an axis - * made from them. If a property name, the leading "Controller.Hardware." can be omitted. - * @property {boolean} [peek=false] - If true then peeking is enabled per {@link RouteObject#peek}. - * @property {boolean} [debug=false] - If true then debug is enabled per {@link RouteObject#debug}. + * @property {string|Controller.MappingJSONAxis} from - The name of a {@link Controller.Hardware} property or an axis made from + * them. If a property name, the leading "Controller.Hardware." can be omitted. + * @property {boolean} [peek=false] - If true, then peeking is enabled per {@link RouteObject#peek}. + * @property {boolean} [debug=false] - If true, then debug is enabled per {@link RouteObject#debug}. * @property {string|string[]} [when=[]] - One or more numeric {@link Controller.Hardware} property names which are evaluated - * as booleans and ANDed together. Prepend with a ! to use the logical NOT of the property value. The leading + * as booleans and ANDed together. Prepend a property name with a ! to do a logical NOT. The leading * "Controller.Hardware." can be omitted from the property names. * @property {Controller.MappingJSONFilter|Controller.MappingJSONFilter[]} [filters=[]] - One or more filters in the route. * @property {string} to - The name of a {@link Controller.Actions} or {@link Controller.Standard} property. The leading @@ -134,7 +134,7 @@ public: : _parent(parent), _mapping(mapping) { } /**jsdoc - * Create a new {@link RouteObject} from a controller output, ready to be mapped to a standard control, action, or + * Creates a new {@link RouteObject} from a controller output, ready to be mapped to a standard control, action, or * function.
* This is a QML-specific version of {@link MappingObject#from|from}: use this version in QML files. * @function MappingObject#fromQml @@ -145,7 +145,7 @@ public: Q_INVOKABLE QObject* fromQml(const QJSValue& source); /**jsdoc - * Create a new {@link RouteObject} from two numeric {@link Controller.Hardware} outputs, one applied in the negative + * Creates a new {@link RouteObject} from two numeric {@link Controller.Hardware} outputs, one applied in the negative * direction and the other in the positive direction, ready to be mapped to a standard control, action, or function.
* This is a QML-specific version of {@link MappingObject#makeAxis|makeAxis}: use this version in QML files. * @function MappingObject#makeAxisQml @@ -157,7 +157,7 @@ public: Q_INVOKABLE QObject* makeAxisQml(const QJSValue& source1, const QJSValue& source2); /**jsdoc - * Create a new {@link RouteObject} from a controller output, ready to be mapped to a standard control, action, or + * Creates a new {@link RouteObject} from a controller output, ready to be mapped to a standard control, action, or * function. * @function MappingObject#from * @param {Controller.Standard|Controller.Hardware|function} source - The controller output or function that is the source @@ -167,7 +167,7 @@ public: Q_INVOKABLE QObject* from(const QScriptValue& source); /**jsdoc - * Create a new {@link RouteObject} from two numeric {@link Controller.Hardware} outputs, one applied in the negative + * Creates a new {@link RouteObject} from two numeric {@link Controller.Hardware} outputs, one applied in the negative * direction and the other in the positive direction, ready to be mapped to a standard control, action, or function. * @function MappingObject#makeAxis * @param {Controller.Hardware} source1 - The first, negative-direction controller output. @@ -189,7 +189,7 @@ public: Q_INVOKABLE QObject* makeAxis(const QScriptValue& source1, const QScriptValue& source2); /**jsdoc - * Enable or disable the mapping. When enabled, the routes in the mapping take effect.
+ * Enables or disables the mapping. When enabled, the routes in the mapping take effect.
* Synonymous with {@link Controller.enableMapping}. * @function MappingObject#enable * @param {boolean} enable=true - If true then the mapping is enabled, otherwise it is disabled. @@ -198,7 +198,7 @@ public: Q_INVOKABLE QObject* enable(bool enable = true); /**jsdoc - * Disable the mapping. When disabled, the routes in the mapping have no effect.
+ * Disables the mapping. When disabled, the routes in the mapping have no effect.
* Synonymous with {@link Controller.disableMapping}. * @function MappingObject#disable * @returns {MappingObject} The mapping object, so that further routes can be added. diff --git a/libraries/controllers/src/controllers/impl/RouteBuilderProxy.cpp b/libraries/controllers/src/controllers/impl/RouteBuilderProxy.cpp index 048e23be1c..56ace23335 100644 --- a/libraries/controllers/src/controllers/impl/RouteBuilderProxy.cpp +++ b/libraries/controllers/src/controllers/impl/RouteBuilderProxy.cpp @@ -66,6 +66,8 @@ QObject* RouteBuilderProxy::peek(bool enable) { } QObject* RouteBuilderProxy::when(const QScriptValue& expression) { + // FIXME: Support "!" conditional in simple expression and array expression. + // Note that "!" is supported when parsing a JSON file, in UserInputMapper::parseConditional(). auto newConditional = _parent.conditionalFor(expression); if (_route->conditional) { _route->conditional = ConditionalPointer(new AndConditional(_route->conditional, newConditional)); diff --git a/libraries/controllers/src/controllers/impl/RouteBuilderProxy.h b/libraries/controllers/src/controllers/impl/RouteBuilderProxy.h index eb610af78a..e7ff04d72c 100644 --- a/libraries/controllers/src/controllers/impl/RouteBuilderProxy.h +++ b/libraries/controllers/src/controllers/impl/RouteBuilderProxy.h @@ -51,7 +51,7 @@ class RouteBuilderProxy : public QObject { : _parent(parent), _mapping(mapping), _route(route) { } /**jsdoc - * Terminate the route with a standard control, an action, or a script function. The output value from the route is + * Terminates the route with a standard control, an action, or a script function. The output value from the route is * sent to the specified destination.
* This is a QML-specific version of {@link MappingObject#to|to}: use this version in QML files. * @function RouteObject#toQml @@ -62,7 +62,7 @@ class RouteBuilderProxy : public QObject { Q_INVOKABLE void toQml(const QJSValue& destination); /**jsdoc - * Process the route only if a condition is satisfied. The condition is evaluated before the route input is read, and + * Processes the route only if a condition is satisfied. The condition is evaluated before the route input is read, and * the input is read only if the condition is true. Thus, if the condition is not met then subsequent * routes using the same input are processed.
* This is a QML-specific version of {@link MappingObject#to|to}: use this version in QML files. @@ -81,7 +81,7 @@ class RouteBuilderProxy : public QObject { Q_INVOKABLE QObject* whenQml(const QJSValue& expression); /**jsdoc - * Terminate the route with a standard control, an action, or a script function. The output value from the route is + * Terminates the route with a standard control, an action, or a script function. The output value from the route is * sent to the specified destination. * @function RouteObject#to * @param {Controller.Standard|Controller.Actions|function} destination - The standard control, action, or JavaScript @@ -117,7 +117,7 @@ class RouteBuilderProxy : public QObject { Q_INVOKABLE void to(const QScriptValue& destination); /**jsdoc - * Enable and disabling writing debug information for a route to the program log. + * Enables or disables writing debug information for a route to the program log. * @function RouteObject#debug * @param {boolean} [enable=true] - If true then writing debug information is enabled for the route, * otherwise it is disabled. @@ -147,7 +147,7 @@ class RouteBuilderProxy : public QObject { Q_INVOKABLE QObject* debug(bool enable = true); /**jsdoc - * Process the route without marking the controller output as having been read, so that other routes from the same + * Processes the route without marking the controller output as having been read, so that other routes from the same * controller output can also process. * @function RouteObject#peek * @param {boolean} [enable=true] - If true then the route is processed without marking the route's @@ -157,7 +157,7 @@ class RouteBuilderProxy : public QObject { Q_INVOKABLE QObject* peek(bool enable = true); /**jsdoc - * Process the route only if a condition is satisfied. The condition is evaluated before the route input is read, and + * Processes the route only if a condition is satisfied. The condition is evaluated before the route input is read, and * the input is read only if the condition is true. Thus, if the condition is not met then subsequent * routes using the same input are processed. * @function RouteObject#when @@ -170,6 +170,8 @@ class RouteBuilderProxy : public QObject { * definition. * *

If an array of conditions is provided, their values are ANDed together.

+ *

Warning: The use of ! is not currently supported in JavaScript .when() + * calls.

* @returns {RouteObject} The RouteObject with the condition added. * @example
Process the right trigger differently in HMD and desktop modes.
* * @@ -269,14 +270,18 @@ controller::Input KeyboardMouseDevice::InputDevice::makeInput(KeyboardMouseDevic * new x-coordinate value. * - * * * + * is the number of units rotated (typically 1.0).
+ * Warning: The mouse wheel in an ordinary mouse generates left/right wheel events instead of + * up/down. * + * is the number of units rotated (typically 1.0).
+ * Warning: The mouse wheel in an ordinary mouse generates left/right wheel events instead of + * up/down. * *
PropertyTypeDataDescription
MouseYnumbernumberThe mouse y-coordinate changed. The data value is its * new y-coordinate value.
MouseWheelRightnumbernumberThe mouse wheel rotated left. The data value + *
MouseWheelRightnumbernumberThe mouse wheel rotated right. The data value * is the number of units rotated (typically 1.0).
MouseWheelLeftnumbernumberThe mouse wheel rotated left. The data value * is the number of units rotated (typically 1.0).
MouseWheelUpnumbernumberThe mouse wheel rotated up. The data value - * is the number of units rotated (typically 1.0).
MouseWheelDownnumbernumberThe mouse wheel rotated down. The data value - * is the number of units rotated (typically 1.0).
TouchpadRightnumbernumberThe average touch on a touch-enabled device * moved right. The data value is how far the average position of all touch points moved.
TouchpadLeftnumbernumberThe average touch on a touch-enabled device @@ -288,7 +293,6 @@ controller::Input KeyboardMouseDevice::InputDevice::makeInput(KeyboardMouseDevic * *
* @typedef {object} Controller.Hardware-Keyboard - * @todo Currently, the mouse wheel in an ordinary mouse generates left/right wheel events instead of up/down. */ controller::Input::NamedVector KeyboardMouseDevice::InputDevice::getAvailableInputs() const { using namespace controller; diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 8b79ca2572..b24c1a01cc 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -776,11 +776,14 @@ scriptable::ScriptableModelBase Model::getScriptableModel() { auto& materialName = _modelMeshMaterialNames[shapeID]; result.appendMaterial(graphics::MaterialLayer(getGeometry()->getShapeMaterial(shapeID), 0), shapeID, materialName); - auto mappedMaterialIter = _materialMapping.find(shapeID); - if (mappedMaterialIter != _materialMapping.end()) { - auto mappedMaterials = mappedMaterialIter->second; - for (auto& mappedMaterial : mappedMaterials) { - result.appendMaterial(mappedMaterial, shapeID, materialName); + { + std::unique_lock lock(_materialMappingMutex); + auto mappedMaterialIter = _materialMapping.find(shapeID); + if (mappedMaterialIter != _materialMapping.end()) { + auto mappedMaterials = mappedMaterialIter->second; + for (auto& mappedMaterial : mappedMaterials) { + result.appendMaterial(mappedMaterial, shapeID, materialName); + } } } shapeID++; @@ -1558,6 +1561,13 @@ void Model::applyMaterialMapping() { auto renderItemsKey = _renderItemKeyGlobalFlags; PrimitiveMode primitiveMode = getPrimitiveMode(); bool useDualQuaternionSkinning = _useDualQuaternionSkinning; + auto modelMeshRenderItemIDs = _modelMeshRenderItemIDs; + auto modelMeshRenderItemShapes = _modelMeshRenderItemShapes; + std::unordered_map shouldInvalidatePayloadShapeKeyMap; + + for (auto& shape : _modelMeshRenderItemShapes) { + shouldInvalidatePayloadShapeKeyMap[shape.meshIndex] = shouldInvalidatePayloadShapeKey(shape.meshIndex); + } auto& materialMapping = getMaterialMapping(); for (auto& mapping : materialMapping) { @@ -1577,7 +1587,8 @@ void Model::applyMaterialMapping() { priorityMapPerResource[shapeID] = ++_priorityMap[shapeID]; } - auto materialLoaded = [this, networkMaterialResource, shapeIDs, priorityMapPerResource, renderItemsKey, primitiveMode, useDualQuaternionSkinning]() { + auto materialLoaded = [this, networkMaterialResource, shapeIDs, priorityMapPerResource, renderItemsKey, primitiveMode, useDualQuaternionSkinning, + modelMeshRenderItemIDs, modelMeshRenderItemShapes, shouldInvalidatePayloadShapeKeyMap]() { if (networkMaterialResource->isFailed() || networkMaterialResource->parsedMaterials.names.size() == 0) { return; } @@ -1600,12 +1611,15 @@ void Model::applyMaterialMapping() { } } for (auto shapeID : shapeIDs) { - if (shapeID < _modelMeshRenderItemIDs.size()) { - auto itemID = _modelMeshRenderItemIDs[shapeID]; - auto meshIndex = _modelMeshRenderItemShapes[shapeID].meshIndex; - bool invalidatePayloadShapeKey = shouldInvalidatePayloadShapeKey(meshIndex); + if (shapeID < modelMeshRenderItemIDs.size()) { + auto itemID = modelMeshRenderItemIDs[shapeID]; + auto meshIndex = modelMeshRenderItemShapes[shapeID].meshIndex; + bool invalidatePayloadShapeKey = shouldInvalidatePayloadShapeKeyMap.at(meshIndex); graphics::MaterialLayer material = graphics::MaterialLayer(networkMaterial, priorityMapPerResource.at(shapeID)); - _materialMapping[shapeID].push_back(material); + { + std::unique_lock lock(_materialMappingMutex); + _materialMapping[shapeID].push_back(material); + } transaction.updateItem(itemID, [material, renderItemsKey, invalidatePayloadShapeKey, primitiveMode, useDualQuaternionSkinning](ModelMeshPartPayload& data) { data.addMaterial(material); diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index 34b8a90f87..7844e9bc41 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -379,6 +379,7 @@ protected: std::unordered_map _priorityMap; // only used for materialMapping std::unordered_map> _materialMapping; // generated during applyMaterialMapping + std::mutex _materialMappingMutex; void applyMaterialMapping(); void setBlendshapeCoefficients(const QVector& coefficients) { _blendshapeCoefficients = coefficients; } diff --git a/libraries/shared/src/ResourceRequestObserver.cpp b/libraries/shared/src/ResourceRequestObserver.cpp index 608d6905c5..21f4d56173 100644 --- a/libraries/shared/src/ResourceRequestObserver.cpp +++ b/libraries/shared/src/ResourceRequestObserver.cpp @@ -16,6 +16,13 @@ #include #include +/**jsdoc + * Information about a resource request. + * @typedef {object} ResourceRequestObserver.ResourceRequest + * @property {string} url - The URL of the resource request. + * @property {number} callerId - An ID identifying the request. + * @property {string} extra - Extra information about the request. + */ void ResourceRequestObserver::update(const QUrl& requestUrl, const qint64 callerId, const QString& extra) { diff --git a/libraries/shared/src/ResourceRequestObserver.h b/libraries/shared/src/ResourceRequestObserver.h index edf3c617cb..352f01c3a5 100644 --- a/libraries/shared/src/ResourceRequestObserver.h +++ b/libraries/shared/src/ResourceRequestObserver.h @@ -16,7 +16,15 @@ #include "DependencyManager.h" - +/**jsdoc + * The ResourceRequestObserver API provides notifications when an observable resource request is made. + * + * @namespace ResourceRequestObserver + * + * @hifi-interface + * @hifi-client-entity + * @hifi-avatar + */ class ResourceRequestObserver : public QObject, public Dependency { Q_OBJECT SINGLETON_DEPENDENCY @@ -25,5 +33,29 @@ public: void update(const QUrl& requestUrl, const qint64 callerId = -1, const QString& extra = ""); signals: + /**jsdoc + * Triggered when an observable resource request is made. + * @function ResourceRequestObserver.resourceRequestEvent + * @param {ResourceRequestObserver.ResourceRequest} request - Information about the resource request. + * @returns {Signal} + * @example Report when a particular Clipboard.importEntities() resource request is made. + * ResourceRequestObserver.resourceRequestEvent.connect(function (request) { + * if (request.callerId === 100) { + * print("Resource request: " + JSON.stringify(request)); + * } + * }); + * + * function importEntities() { + * var filename = Window.browse("Import entities to clipboard", "", "*.json"); + * if (filename) { + * Clipboard.importEntities(filename, true, 100); + * pastedEntities = Clipboard.pasteEntities(Vec3.sum(MyAvatar.position, + * Vec3.multiplyQbyV(MyAvatar.orientation, { x: 0, y: 0, z: -3 }))); + * print("Entities pasted: " + JSON.stringify(pastedEntities)); + * } + * } + * + * Script.setTimeout(importEntities, 2000); + */ void resourceRequestEvent(QVariantMap result); }; diff --git a/plugins/oculus/src/OculusControllerManager.cpp b/plugins/oculus/src/OculusControllerManager.cpp index 8d97ff78af..14830f3f04 100644 --- a/plugins/oculus/src/OculusControllerManager.cpp +++ b/plugins/oculus/src/OculusControllerManager.cpp @@ -409,9 +409,10 @@ void OculusControllerManager::TouchDevice::stopHapticPulse(bool leftHand) { } /**jsdoc - *

The Controller.Hardware.OculusTouch object has properties representing Oculus Rift. The property values are - * integer IDs, uniquely identifying each output. Read-only. These can be mapped to actions or functions or - * Controller.Standard items in a {@link RouteObject} mapping.

+ *

The Controller.Hardware.OculusTouch object has properties representing the Oculus Rift. The property values + * are integer IDs, uniquely identifying each output. Read-only.

+ *

These outputs can be mapped to actions or functions or Controller.Standard items in a {@link RouteObject} + * mapping.

* * * diff --git a/plugins/openvr/src/ViveControllerManager.cpp b/plugins/openvr/src/ViveControllerManager.cpp index 34ebb73fda..c21a9ae4df 100644 --- a/plugins/openvr/src/ViveControllerManager.cpp +++ b/plugins/openvr/src/ViveControllerManager.cpp @@ -1299,14 +1299,20 @@ void ViveControllerManager::InputDevice::setConfigFromString(const QString& valu } /**jsdoc - *

The Controller.Hardware.Vive object has properties representing Vive. The property values are integer IDs, - * uniquely identifying each output. Read-only. These can be mapped to actions or functions or - * Controller.Standard items in a {@link RouteObject} mapping.

+ *

The Controller.Hardware.Vive object has properties representing the Vive. The property values are integer + * IDs, uniquely identifying each output. Read-only.

+ *

These outputs can be mapped to actions or functions or Controller.Standard items in a {@link RouteObject} + * mapping.

*
PropertyTypeDataDescription
* * * * + * + * + * * * * diff --git a/prebuild.py b/prebuild.py index 5325ca34bc..b401c94e7f 100644 --- a/prebuild.py +++ b/prebuild.py @@ -94,7 +94,7 @@ def parse_args(): parser.add_argument('--vcpkg-root', type=str, help='The location of the vcpkg distribution') parser.add_argument('--build-root', required=True, type=str, help='The location of the cmake build') parser.add_argument('--ports-path', type=str, default=defaultPortsPath) - parser.add_argument('--ci-build', action='store_true') + parser.add_argument('--ci-build', action='store_true', default=os.getenv('CI_BUILD') is not None) if True: args = parser.parse_args() else:
PropertyTypeDataDescription
Buttons
LeftApplicationMenunumbernumberLeft application menu button pressed. + *
RightApplicationMenunumbernumberRight application menu button pressed. + *
Touch Pad (Sticks)
LXnumbernumberLeft touch pad x-axis scale.
LYnumbernumberLeft touch pad y-axis scale.