diff --git a/.github/stale.yml b/.github/stale.yml index d5c79b8504..08c174b5ef 100644 --- a/.github/stale.yml +++ b/.github/stale.yml @@ -1,17 +1,11 @@ # Number of days of inactivity before an issue becomes stale -daysUntilStale: 120 +daysUntilStale: 180 # Number of days of inactivity before a stale issue is closed -daysUntilClose: 60 -# Issues with these labels will never be considered stale -exemptLabels: - - pinned - - security +daysUntilClose: false # Label to use when marking an issue as stale staleLabel: stale # Comment to post when marking an issue as stale. Set to `false` to disable markComment: > - This issue has been automatically marked as stale because it has not had recent activity. - It will be closed if no further activity occurs. - Thank you for your contributions. + Hello! Is this still an issue? # Comment to post when closing a stale issue. Set to `false` to disable closeComment: false diff --git a/.github/workflows/master_build.yml b/.github/workflows/master_build.yml index 685c5c9524..f1e7578c02 100644 --- a/.github/workflows/master_build.yml +++ b/.github/workflows/master_build.yml @@ -101,8 +101,8 @@ jobs: working-directory: ${{runner.workspace}} run: rm -rf ./* - uses: actions/checkout@v1 - with: - submodules: true + with: + submodules: false fetch-depth: 1 - name: Install dependencies if: startsWith(matrix.os, 'ubuntu') diff --git a/.github/workflows/pr_build.yml b/.github/workflows/pr_build.yml index 8b4201f068..219daa0c4b 100644 --- a/.github/workflows/pr_build.yml +++ b/.github/workflows/pr_build.yml @@ -25,6 +25,8 @@ env: # WIN32 specific variables PreferredToolArchitecture: X64 + # Ensure XZ always runs with muticore support + XZ_OPT: -T0 jobs: build: @@ -118,8 +120,8 @@ jobs: working-directory: ${{runner.workspace}} run: rm -rf ./* - uses: actions/checkout@v1 - with: - submodules: true + with: + submodules: false fetch-depth: 1 - name: Install dependencies shell: bash @@ -140,6 +142,24 @@ jobs: working-directory: ${{runner.workspace}}/build shell: bash run: cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DVCPKG_BUILD_TYPE=release $CMAKE_EXTRA + - name: Compress cmake logs + if: always() + shell: bash + run: | + if [ "${{ matrix.os }}" == "macOS-latest" ]; then + TAR=gtar + else + TAR=tar + fi + + find "$HOME/vircadia-files/vcpkg" -name '*log' -type f -print0 | $TAR --null --force-local -T - -c --xz -v -f "${{ runner.workspace }}/cmake-logs-${{ matrix.os }}-${{ github.event.number }}.tar.xz" + - name: Archive cmake logs + if: always() + uses: actions/upload-artifact@v2 + with: + name: cmake-logs-${{ matrix.os }}-${{ github.event.number }}.tar.xz + path: ${{ runner.workspace }}/cmake-logs-${{ matrix.os }}-${{ github.event.number }}.tar.xz + if-no-files-found: error - name: Build Application if: matrix.build_type == 'full' || matrix.build_type == 'client' working-directory: ${{runner.workspace}}/build @@ -231,4 +251,4 @@ jobs: if [[ "${{ matrix.build_type }}" == "android" ]]; then cd $GITHUB_WORKSPACE/android fi - $PYTHON_EXEC "$GITHUB_WORKSPACE/tools/ci-scripts/upload_to_publish_server.py" \ No newline at end of file + $PYTHON_EXEC "$GITHUB_WORKSPACE/tools/ci-scripts/upload_to_publish_server.py" diff --git a/BUILD_LINUX.md b/BUILD_LINUX.md index e9c5047e38..1996360fed 100644 --- a/BUILD_LINUX.md +++ b/BUILD_LINUX.md @@ -93,13 +93,16 @@ git checkout master ### Using a custom Qt build -Qt binaries are only provided for Ubuntu. In order to build on other distributions, a Qt5 install needs to be provided as follows: +Qt binaries are only provided for Ubuntu. In order to build on other distributions, a Qt5 install +needs to be provided by setting the `VIRCADIA_QT_PATH` environment variable to a directory containing +a Qt install. -* Set `VIRCADIA_USE_PREBUILT_QT=1` -* Set `VIRCADIA_USE_QT_VERSION` to the Qt version (defaults to `5.12.3`) -* Set `HIFI_QT_BASE=/path/to/qt` +### Using the system's Qt -Qt must be installed in `$HIFI_QT_BASE/$VIRCADIA_USE_QT_VERSION/qt5-install`. +The system's Qt can be used, if the development packages are installed, by setting the +`VIRCADIA_USE_SYSTEM_QT` environment variable. The minimum recommended version is Qt 5.15.2, which is +also the last version available in the Qt 5 branch. It is expected that Linux distributions will have +Qt 5.15.2 available for a long time. ### Compiling diff --git a/CMakeLists.txt b/CMakeLists.txt index 77d0413690..7293e9f825 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -57,7 +57,7 @@ MESSAGE(STATUS "GLES_OPTION: ${GLES_OPTION}") include("${CMAKE_CURRENT_SOURCE_DIR}/cmake/macros/TargetPython.cmake") target_python() -if (WIN32 AND NOT HIFI_ANDROID) +if (WIN32 AND NOT HIFI_ANDROID AND NOT (CMAKE_GENERATOR STREQUAL "Ninja")) # Force x64 toolset set(CMAKE_GENERATOR_TOOLSET "host=x64" CACHE STRING "64-bit toolset" FORCE) endif() @@ -77,7 +77,7 @@ endif() if (HIFI_ANDROID) execute_process( COMMAND ${HIFI_PYTHON_EXEC} ${CMAKE_CURRENT_SOURCE_DIR}/prebuild.py --release-type ${RELEASE_TYPE} --android ${HIFI_ANDROID_APP} --build-root ${CMAKE_BINARY_DIR} - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} RESULTS_VARIABLE PREBUILD_RET ) else() set(VCPKG_BUILD_TYPE_PARAM "") @@ -86,7 +86,7 @@ else() endif() execute_process( COMMAND ${HIFI_PYTHON_EXEC} ${CMAKE_CURRENT_SOURCE_DIR}/prebuild.py --release-type ${RELEASE_TYPE} --build-root ${CMAKE_BINARY_DIR} ${VCPKG_BUILD_TYPE_PARAM} - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} RESULTS_VARIABLE PREBUILD_RET ) # squelch the Policy CMP0074 warning without requiring an update to cmake 3.12. if (CMAKE_VERSION VERSION_GREATER_EQUAL 3.12) @@ -94,6 +94,9 @@ else() endif() endif() +if (PREBUILD_RET GREATER 0) + message(FATAL_ERROR "prebuild.py failed with error ${PREBUILD_RET}") +endif() if(NOT EXISTS "${CMAKE_BINARY_DIR}/vcpkg.cmake") message(FATAL_ERROR "vcpkg configuration missing.") endif() @@ -101,11 +104,16 @@ include("${CMAKE_BINARY_DIR}/vcpkg.cmake") if (HIFI_ANDROID) set(QT_CMAKE_PREFIX_PATH "$ENV{HIFI_ANDROID_PRECOMPILED}/qt/lib/cmake") -else() - if(NOT EXISTS "${CMAKE_BINARY_DIR}/qt.cmake") - message(FATAL_ERROR "qt configuration missing.") +else() + if ("$ENV{VIRCADIA_USE_SYSTEM_QT}" STREQUAL "") + if(NOT EXISTS "${CMAKE_BINARY_DIR}/qt.cmake") + message(FATAL_ERROR "qt configuration missing.") + endif() + include("${CMAKE_BINARY_DIR}/qt.cmake") + message(STATUS "${CMAKE_BINARY_DIR}/qt.cmake included!") + else() + message(STATUS "System Qt in use, not including qt.cmake!") endif() - include("${CMAKE_BINARY_DIR}/qt.cmake") endif() option(VCPKG_APPLOCAL_DEPS OFF) @@ -290,7 +298,10 @@ set_packaging_parameters() # Locate the required Qt build on the filesystem setup_qt() -list(APPEND CMAKE_PREFIX_PATH "${QT_CMAKE_PREFIX_PATH}") + +if ("$ENV{VIRCADIA_USE_SYSTEM_QT}" STREQUAL "") + list(APPEND CMAKE_PREFIX_PATH "${QT_CMAKE_PREFIX_PATH}") +endif() find_package( Threads ) diff --git a/README.md b/README.md index 58e3a501d4..b84849b205 100644 --- a/README.md +++ b/README.md @@ -72,3 +72,9 @@ Vircadia consists of many projects and codebases with its unifying structure's g ### Contribution There are many contributors to Vircadia. Code writers, reviewers, testers, documentation writers, modelers, and general supporters of the project are all integral to its development and success towards its goals. Find out how you can [contribute](CONTRIBUTING.md)! + +### [Supporters](https://github.com/sponsors/digisomni/) + +| [Karol Suprynowicz - 74hc595](https://github.com/ksuprynowicz) | +| --- | +|

[![ksuprynowicz](https://avatars.githubusercontent.com/u/11568651?s=64&v=4)](https://github.com/ksuprynowicz)

diff --git a/android/apps/interface/src/main/cpp/native.cpp b/android/apps/interface/src/main/cpp/native.cpp index a466245eda..42118d89db 100644 --- a/android/apps/interface/src/main/cpp/native.cpp +++ b/android/apps/interface/src/main/cpp/native.cpp @@ -142,7 +142,7 @@ void unpackAndroidAssets() { if (!file.open(QIODevice::ReadWrite | QIODevice::Truncate)) { throw std::runtime_error("Can't write date stamp"); } - QTextStream(&file) << "touch" << endl; + QTextStream(&file) << "touch" << Qt::endl; file.close(); } } diff --git a/assignment-client/src/AssignmentClient.cpp b/assignment-client/src/AssignmentClient.cpp index 3eb3c83b83..1f18709a91 100644 --- a/assignment-client/src/AssignmentClient.cpp +++ b/assignment-client/src/AssignmentClient.cpp @@ -4,6 +4,7 @@ // // Created by Stephen Birarda on 11/25/2013. // Copyright 2013 High Fidelity, Inc. +// Copyright 2021 Vircadia contributors. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -83,7 +84,7 @@ AssignmentClient::AssignmentClient(Assignment::Type requestAssignmentType, QStri _assignmentServerHostname = assignmentServerHostname; } - _assignmentServerSocket = HifiSockAddr(_assignmentServerHostname, assignmentServerPort, true); + _assignmentServerSocket = SockAddr(_assignmentServerHostname, assignmentServerPort, true); if (_assignmentServerSocket.isNull()) { qCCritical(assignment_client) << "PAGE: Couldn't resolve domain server address" << _assignmentServerHostname; } @@ -118,7 +119,7 @@ AssignmentClient::AssignmentClient(Assignment::Type requestAssignmentType, QStri // did we get an assignment-client monitor port? if (assignmentMonitorPort > 0) { - _assignmentClientMonitorSocket = HifiSockAddr(DEFAULT_ASSIGNMENT_CLIENT_MONITOR_HOSTNAME, assignmentMonitorPort); + _assignmentClientMonitorSocket = SockAddr(DEFAULT_ASSIGNMENT_CLIENT_MONITOR_HOSTNAME, assignmentMonitorPort); _assignmentClientMonitorSocket.setObjectName("AssignmentClientMonitor"); qCDebug(assignment_client) << "Assignment-client monitor socket is" << _assignmentClientMonitorSocket; @@ -277,7 +278,7 @@ void AssignmentClient::handleCreateAssignmentPacket(QSharedPointer message) { - const HifiSockAddr& senderSockAddr = message->getSenderSockAddr(); + const SockAddr& senderSockAddr = message->getSenderSockAddr(); if (senderSockAddr.getAddress() == QHostAddress::LocalHost || senderSockAddr.getAddress() == QHostAddress::LocalHostIPv6) { diff --git a/assignment-client/src/AssignmentClient.h b/assignment-client/src/AssignmentClient.h index d40f0964d1..ecee81e337 100644 --- a/assignment-client/src/AssignmentClient.h +++ b/assignment-client/src/AssignmentClient.h @@ -4,6 +4,7 @@ // // Created by Stephen Birarda on 11/25/2013. // Copyright 2013 High Fidelity, Inc. +// Copyright 2021 Vircadia contributors. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -49,14 +50,14 @@ private: QPointer _currentAssignment; bool _isAssigned { false }; QString _assignmentServerHostname; - HifiSockAddr _assignmentServerSocket; + SockAddr _assignmentServerSocket; QTimer _requestTimer; // timer for requesting and assignment QTimer _statsTimerACM; // timer for sending stats to assignment client monitor QUuid _childAssignmentUUID = QUuid::createUuid(); bool _disableDomainPortAutoDiscovery { false }; protected: - HifiSockAddr _assignmentClientMonitorSocket; + SockAddr _assignmentClientMonitorSocket; }; #endif // hifi_AssignmentClient_h diff --git a/assignment-client/src/AssignmentClientMonitor.cpp b/assignment-client/src/AssignmentClientMonitor.cpp index 43d788f5d1..30d63470e5 100644 --- a/assignment-client/src/AssignmentClientMonitor.cpp +++ b/assignment-client/src/AssignmentClientMonitor.cpp @@ -337,7 +337,7 @@ void AssignmentClientMonitor::handleChildStatusPacket(QSharedPointer(); SharedNodePointer matchingNode = nodeList->nodeWithUUID(senderID); - const HifiSockAddr& senderSockAddr = message->getSenderSockAddr(); + const SockAddr& senderSockAddr = message->getSenderSockAddr(); AssignmentClientChildData* childData = nullptr; diff --git a/assignment-client/src/avatars/AvatarMixer.cpp b/assignment-client/src/avatars/AvatarMixer.cpp index 27b7d0d302..55decb90fb 100644 --- a/assignment-client/src/avatars/AvatarMixer.cpp +++ b/assignment-client/src/avatars/AvatarMixer.cpp @@ -4,6 +4,7 @@ // // Created by Stephen Birarda on 9/5/13. // Copyright 2013 High Fidelity, Inc. +// Copyright 2021 Vircadia contributors. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -113,7 +114,7 @@ AvatarMixer::AvatarMixer(ReceivedMessage& message) : }); } -SharedNodePointer addOrUpdateReplicatedNode(const QUuid& nodeID, const HifiSockAddr& senderSockAddr) { +SharedNodePointer addOrUpdateReplicatedNode(const QUuid& nodeID, const SockAddr& senderSockAddr) { auto replicatedNode = DependencyManager::get()->addOrUpdateNode(nodeID, NodeType::Agent, senderSockAddr, senderSockAddr, @@ -976,7 +977,7 @@ void AvatarMixer::domainSettingsRequestComplete() { start(); } -void AvatarMixer::handlePacketVersionMismatch(PacketType type, const HifiSockAddr& senderSockAddr, const QUuid& senderUUID) { +void AvatarMixer::handlePacketVersionMismatch(PacketType type, const SockAddr& senderSockAddr, const QUuid& senderUUID) { // if this client is using packet versions we don't expect. if ((type == PacketTypeEnum::Value::AvatarIdentity || type == PacketTypeEnum::Value::AvatarData) && !senderUUID.isNull()) { // Echo an empty AvatarData packet back to that client. diff --git a/assignment-client/src/avatars/AvatarMixer.h b/assignment-client/src/avatars/AvatarMixer.h index 10dff5e8a4..1a19a61bd2 100644 --- a/assignment-client/src/avatars/AvatarMixer.h +++ b/assignment-client/src/avatars/AvatarMixer.h @@ -4,6 +4,7 @@ // // Created by Stephen Birarda on 9/5/13. // Copyright 2013 High Fidelity, Inc. +// Copyright 2021 Vircadia contributors. // // The avatar mixer receives head, hand and positional data from all connected // nodes, and broadcasts that data back to them, every BROADCAST_INTERVAL ms. @@ -63,7 +64,7 @@ private slots: void handleReplicatedPacket(QSharedPointer message); void handleReplicatedBulkAvatarPacket(QSharedPointer message); void domainSettingsRequestComplete(); - void handlePacketVersionMismatch(PacketType type, const HifiSockAddr& senderSockAddr, const QUuid& senderUUID); + void handlePacketVersionMismatch(PacketType type, const SockAddr& senderSockAddr, const QUuid& senderUUID); void handleOctreePacket(QSharedPointer message, SharedNodePointer senderNode); void start(); diff --git a/cmake/externals/crashpad/CMakeLists.txt b/cmake/externals/crashpad/CMakeLists.txt index e519ead0ee..ae6972cab1 100644 --- a/cmake/externals/crashpad/CMakeLists.txt +++ b/cmake/externals/crashpad/CMakeLists.txt @@ -35,6 +35,25 @@ elseif (APPLE) ExternalProject_Get_Property(${EXTERNAL_NAME} SOURCE_DIR) + set(BIN_RELEASE_PATH "${SOURCE_DIR}/out/Release") + set(BIN_EXT "") + set(LIB_RELEASE_PATH "${SOURCE_DIR}/out/Release/lib") + set(LIB_DEBUG_PATH "${SOURCE_DIR}/out/Debug/lib") + set(LIB_PREFIX "lib") + set(LIB_EXT "a") +elseif (UNIX) + ExternalProject_Add( + ${EXTERNAL_NAME} + URL "${EXTERNAL_BUILD_ASSETS}/dependencies/crashpad_linux_f1943fcb.tar.bz2" + URL_MD5 e0949e5988905471c63c399833879482 + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + INSTALL_COMMAND "" + LOG_DOWNLOAD 1 + ) + + ExternalProject_Get_Property(${EXTERNAL_NAME} SOURCE_DIR) + set(BIN_RELEASE_PATH "${SOURCE_DIR}/out/Release") set(BIN_EXT "") set(LIB_RELEASE_PATH "${SOURCE_DIR}/out/Release/lib") @@ -43,8 +62,7 @@ elseif (APPLE) set(LIB_EXT "a") endif () -if (WIN32 OR APPLE) - +if (WIN32 OR APPLE OR UNIX) set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${SOURCE_DIR}/include CACHE PATH "List of Crashpad include directories") set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${LIB_RELEASE_PATH}/${LIB_PREFIX}crashpad_client.${LIB_EXT} CACHE FILEPATH "Path to Crashpad release library") diff --git a/cmake/macros/AddCrashpad.cmake b/cmake/macros/AddCrashpad.cmake index bc070e057b..684c842ea2 100644 --- a/cmake/macros/AddCrashpad.cmake +++ b/cmake/macros/AddCrashpad.cmake @@ -11,24 +11,29 @@ macro(add_crashpad) set (USE_CRASHPAD TRUE) + message(STATUS "Checking crashpad config") + if ("$ENV{CMAKE_BACKTRACE_URL}" STREQUAL "") + message(STATUS "Checking crashpad config - CMAKE_BACKTRACE_URL is not set, disabled.") set(USE_CRASHPAD FALSE) else() set(CMAKE_BACKTRACE_URL $ENV{CMAKE_BACKTRACE_URL}) endif() if ("$ENV{CMAKE_BACKTRACE_TOKEN}" STREQUAL "") + message(STATUS "Checking crashpad config - CMAKE_BACKTRACE_TOKEN is not set, disabled.") set(USE_CRASHPAD FALSE) else() set(CMAKE_BACKTRACE_TOKEN $ENV{CMAKE_BACKTRACE_TOKEN}) endif() - if ((WIN32 OR APPLE) AND USE_CRASHPAD) + if (USE_CRASHPAD) + message(STATUS "Checking crashpad config - enabled.") get_property(CRASHPAD_CHECKED GLOBAL PROPERTY CHECKED_FOR_CRASHPAD_ONCE) if (NOT CRASHPAD_CHECKED) add_dependency_external_projects(crashpad) - find_package(crashpad REQUIRED) + find_package(Crashpad REQUIRED) set_property(GLOBAL PROPERTY CHECKED_FOR_CRASHPAD_ONCE TRUE) endif() @@ -38,7 +43,7 @@ macro(add_crashpad) add_definitions(-DCMAKE_BACKTRACE_TOKEN=\"${CMAKE_BACKTRACE_TOKEN}\") target_include_directories(${TARGET_NAME} PRIVATE ${CRASHPAD_INCLUDE_DIRS}) - target_link_libraries(${TARGET_NAME} ${CRASHPAD_LIBRARY} ${CRASHPAD_BASE_LIBRARY} ${CRASHPAD_UTIL_LIBRARY}) + target_link_libraries(${TARGET_NAME} ${CRASHPAD_LIBRARY} ${CRASHPAD_UTIL_LIBRARY} ${CRASHPAD_BASE_LIBRARY}) if (WIN32) set_target_properties(${TARGET_NAME} PROPERTIES LINK_FLAGS "/ignore:4099") diff --git a/cmake/macros/SetupQt.cmake b/cmake/macros/SetupQt.cmake index 6f31a3994c..743ac934c4 100644 --- a/cmake/macros/SetupQt.cmake +++ b/cmake/macros/SetupQt.cmake @@ -5,6 +5,9 @@ # See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html # +# For understanding the execution flow followed by the Qt setup, +# please look at the comment on top of hifi_qt.py + function(get_sub_directories result curdir) file(GLOB children RELATIVE ${curdir} ${curdir}/*) set(dirlist "") @@ -25,6 +28,9 @@ function(calculate_qt5_version result _QT_DIR) set(_QT_CORE_DIR "${_QT_DIR}/lib/QtCore.framework/Versions/5/Headers") else() set(_QT_CORE_DIR "${_QT_DIR}/include/QtCore") + if(NOT EXISTS "${_QT_CORE_DIR}") + set(_QT_CORE_DIR "${_QT_DIR}/include/qt5/QtCore") + endif() endif() if(NOT EXISTS "${_QT_CORE_DIR}") message(FATAL_ERROR "Could not find 'include/QtCore' in '${_QT_DIR}'") @@ -45,49 +51,64 @@ endfunction() # Sets the QT_CMAKE_PREFIX_PATH and QT_DIR variables # Also enables CMAKE_AUTOMOC and CMAKE_AUTORCC macro(setup_qt) - # if we are in a development build and QT_CMAKE_PREFIX_PATH is specified - # then use it, - # otherwise, use the vcpkg'ed version - if(NOT DEFINED QT_CMAKE_PREFIX_PATH) - message(FATAL_ERROR "QT_CMAKE_PREFIX_PATH should have been set by hifi_qt.py") - endif() - if (DEV_BUILD) - if (DEFINED ENV{QT_CMAKE_PREFIX_PATH}) - set(QT_CMAKE_PREFIX_PATH $ENV{QT_CMAKE_PREFIX_PATH}) - endif() - endif() + if ($ENV{VIRCADIA_USE_SYSTEM_QT}) + message(STATUS "Using system Qt") + else() + # if we are in a development build and QT_CMAKE_PREFIX_PATH is specified + # then use it, + # otherwise, use the vcpkg'ed version + if(NOT DEFINED QT_CMAKE_PREFIX_PATH) + # Note: This comes from qt.cmake generated by hifi_qt.py + # See the comment on top of hifi_qt.py for details. + message(FATAL_ERROR "QT_CMAKE_PREFIX_PATH should have been set by hifi_qt.py through qt.cmake") + endif() + if (DEV_BUILD) + if (DEFINED ENV{QT_CMAKE_PREFIX_PATH}) + set(QT_CMAKE_PREFIX_PATH $ENV{QT_CMAKE_PREFIX_PATH}) + endif() + endif() - message("QT_CMAKE_PREFIX_PATH = " ${QT_CMAKE_PREFIX_PATH}) + # figure out where the qt dir is + get_filename_component(QT_DIR "${QT_CMAKE_PREFIX_PATH}/../../" ABSOLUTE) + set(QT_VERSION "unknown") + calculate_qt5_version(QT_VERSION "${QT_DIR}") + if (QT_VERSION STREQUAL "unknown") + message(FATAL_ERROR "Could not determine QT_VERSION") + endif() + + if(WIN32) + # windows shell does not like backslashes expanded on the command line, + # so convert all backslashes in the QT path to forward slashes + string(REPLACE \\ / QT_CMAKE_PREFIX_PATH ${QT_CMAKE_PREFIX_PATH}) + string(REPLACE \\ / QT_DIR ${QT_DIR}) + endif() + + if(NOT EXISTS "${QT_CMAKE_PREFIX_PATH}/Qt5Core/Qt5CoreConfig.cmake") + message(FATAL_ERROR "Unable to locate Qt5CoreConfig.cmake in '${QT_CMAKE_PREFIX_PATH}'") + endif() + + set(RCC_BINARY "${QT_DIR}/bin/rcc${CMAKE_EXECUTABLE_SUFFIX}") + + if(NOT EXISTS "${RCC_BINARY}") + set(RCC_BINARY "${QT_DIR}/bin/rcc-qt5${CMAKE_EXECUTABLE_SUFFIX}") + endif() + + if(NOT EXISTS "${RCC_BINARY}") + message(FATAL_ERROR "Unable to locate rcc. Last looked in '${RCC_BINARY}'") + endif() + + + message(STATUS "Using Qt build in : '${QT_DIR}' with version ${QT_VERSION}") + if (WIN32) + add_paths_to_fixup_libs("${QT_DIR}/bin") + endif () - # figure out where the qt dir is - get_filename_component(QT_DIR "${QT_CMAKE_PREFIX_PATH}/../../" ABSOLUTE) - set(QT_VERSION "unknown") - calculate_qt5_version(QT_VERSION "${QT_DIR}") - if (QT_VERSION STREQUAL "unknown") - message(FATAL_ERROR "Could not determine QT_VERSION") endif() - if(WIN32) - # windows shell does not like backslashes expanded on the command line, - # so convert all backslashes in the QT path to forward slashes - string(REPLACE \\ / QT_CMAKE_PREFIX_PATH ${QT_CMAKE_PREFIX_PATH}) - string(REPLACE \\ / QT_DIR ${QT_DIR}) - endif() - - if(NOT EXISTS "${QT_CMAKE_PREFIX_PATH}/Qt5Core/Qt5CoreConfig.cmake") - message(FATAL_ERROR "Unable to locate Qt5CoreConfig.cmake in '${QT_CMAKE_PREFIX_PATH}'") - endif() - - message(STATUS "Using Qt build in : '${QT_DIR}' with version ${QT_VERSION}") - # Instruct CMake to run moc automatically when needed. set(CMAKE_AUTOMOC ON) # Instruct CMake to run rcc automatically when needed set(CMAKE_AUTORCC ON) - if (WIN32) - add_paths_to_fixup_libs("${QT_DIR}/bin") - endif () - endmacro() diff --git a/cmake/modules/FindCrashpad.cmake b/cmake/modules/FindCrashpad.cmake index 283058336d..c93ab9a0be 100644 --- a/cmake/modules/FindCrashpad.cmake +++ b/cmake/modules/FindCrashpad.cmake @@ -38,4 +38,4 @@ select_library_configurations(CRASHPAD_BASE) select_library_configurations(CRASHPAD_UTIL) include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(CRASHPAD DEFAULT_MSG CRASHPAD_INCLUDE_DIRS CRASHPAD_LIBRARY CRASHPAD_BASE_LIBRARY CRASHPAD_UTIL_LIBRARY) +find_package_handle_standard_args(Crashpad DEFAULT_MSG CRASHPAD_INCLUDE_DIRS CRASHPAD_LIBRARY CRASHPAD_BASE_LIBRARY CRASHPAD_UTIL_LIBRARY) diff --git a/cmake/modules/FindGifCreator.cmake b/cmake/modules/FindGifCreator.cmake index def9f1d131..04f2af684c 100644 --- a/cmake/modules/FindGifCreator.cmake +++ b/cmake/modules/FindGifCreator.cmake @@ -21,6 +21,6 @@ hifi_library_search_hints("GIFCREATOR") find_path(GIFCREATOR_INCLUDE_DIRS "GifCreator/GifCreator.h" HINTS ${GIFCREATOR_SEARCH_DIRS}) include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(GIFCREATOR DEFAULT_MSG GIFCREATOR_INCLUDE_DIRS) +find_package_handle_standard_args(GifCreator DEFAULT_MSG GIFCREATOR_INCLUDE_DIRS) mark_as_advanced(GIFCREATOR_INCLUDE_DIRS GIFCREATOR_SEARCH_DIRS) \ No newline at end of file diff --git a/cmake/ports/nvtt/0001-Build-on-aarch64.patch b/cmake/ports/nvtt/0001-Build-on-aarch64.patch deleted file mode 100644 index 4f737f78c4..0000000000 --- a/cmake/ports/nvtt/0001-Build-on-aarch64.patch +++ /dev/null @@ -1,37 +0,0 @@ -commit 8909ba06ea1893a6e028836fbade28fd115ee1cc -Author: Julian Groß -Date: Wed Feb 17 04:51:49 2021 +0100 - - Enable building on aarch64 according to https://github.com/castano/nvidia-texture-tools/pull/309 and https://github.com/castano/nvidia-texture-tools/pull/322 - -diff --git a/src/nvcore/Debug.cpp b/src/nvcore/Debug.cpp -index 9ab4525..e335f97 100644 ---- a/src/nvcore/Debug.cpp -+++ b/src/nvcore/Debug.cpp -@@ -1008,6 +1008,13 @@ void debug::dumpInfo() - #endif - } - -+static va_list getEmptyVAList(va_list list, ...) -+{ -+ va_start(list, list); -+ va_end(list); -+ return list; -+} -+ - /// Dump callstack using the specified handler. - void debug::dumpCallstack(MessageHandler *messageHandler, int callstackLevelsToSkip /*= 0*/) - { -@@ -1020,8 +1027,11 @@ void debug::dumpCallstack(MessageHandler *messageHandler, int callstackLevelsToS - Array lines; - writeStackTrace(trace, size, callstackLevelsToSkip + 1, lines); // + 1 to skip the call to dumpCallstack - -+ va_list empty; -+ empty = getEmptyVAList(empty); -+ - for (uint i = 0; i < lines.count(); i++) { -- messageHandler->log(lines[i], NULL); -+ messageHandler->log(lines[i], empty); - delete lines[i]; - } - } diff --git a/cmake/ports/nvtt/0002-Hack-remove-include-sysctl.h-to-build-on-linux-a.patch b/cmake/ports/nvtt/0002-Hack-remove-include-sysctl.h-to-build-on-linux-a.patch deleted file mode 100644 index 78e92d38b8..0000000000 --- a/cmake/ports/nvtt/0002-Hack-remove-include-sysctl.h-to-build-on-linux-a.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 84dc6af45b1176a2b82d089239665cb3dc1584de Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Julian=20Gro=C3=9F?= -Date: Wed, 23 Dec 2020 07:33:39 +0100 -Subject: [PATCH] Hack: remove #include to build on - linux-aarch64 - ---- - src/nvthread/nvthread.cpp | 1 - - 1 file changed, 1 deletion(-) - -diff --git a/src/nvthread/nvthread.cpp b/src/nvthread/nvthread.cpp -index 2b3abe6..cec9f4f 100644 ---- a/src/nvthread/nvthread.cpp -+++ b/src/nvthread/nvthread.cpp -@@ -11,7 +11,6 @@ - #include - #elif NV_OS_UNIX - #include --#include - #include - #elif NV_OS_DARWIN - #import --- -2.17.1 - diff --git a/cmake/ports/nvtt/portfile.cmake b/cmake/ports/nvtt/portfile.cmake index 9088b62046..cf068a6db1 100644 --- a/cmake/ports/nvtt/portfile.cmake +++ b/cmake/ports/nvtt/portfile.cmake @@ -10,18 +10,11 @@ include(vcpkg_common_functions) vcpkg_from_github( OUT_SOURCE_PATH SOURCE_PATH REPO vircadia/nvidia-texture-tools - REF 330c4d56274a0f602a5c70596e2eb670a4ed56c2 - SHA512 4c0bc2f369120d696cc27710b6d33086b27eef55f537ec66b9a5c8b1839bc2426c0413670b0f65be52c5d353468f0126dfe024be1f0690611d4d7e33ac530127 + REF d8b7a98aeb177b5eddb76571183bbd2f95d54e6c + SHA512 ea15ffd19eb1e14c8ebd62f8d7de3df1ecf6c18a339025f4a0e13419717d510903fc126ec6d1bdfbb5a2f4525a922412b72318bc8dd55dd000481a3924fbfcd4 HEAD_REF master ) -if(VCPKG_TARGET_ARCHITECTURE STREQUAL arm64) - vcpkg_apply_patches( - SOURCE_PATH ${SOURCE_PATH} - PATCHES "${CMAKE_CURRENT_LIST_DIR}/0001-Build-on-aarch64.patch" "${CMAKE_CURRENT_LIST_DIR}/0002-Hack-remove-include-sysctl.h-to-build-on-linux-a.patch" - ) -endif() - vcpkg_configure_cmake( SOURCE_PATH ${SOURCE_PATH} OPTIONS diff --git a/cmake/ports/quazip/portfile.cmake b/cmake/ports/quazip/portfile.cmake index 0789062892..3f5703dcf4 100644 --- a/cmake/ports/quazip/portfile.cmake +++ b/cmake/ports/quazip/portfile.cmake @@ -1,6 +1,15 @@ include(vcpkg_common_functions) -file(READ "${VCPKG_ROOT_DIR}/_env/QT_CMAKE_PREFIX_PATH.txt" QT_CMAKE_PREFIX_PATH) +if(EXISTS "${VCPKG_ROOT_DIR}/_env/QT_CMAKE_PREFIX_PATH.txt") + # This environment var file only exists if we're overridding the default Qt location, + # which happens when using Qt from vcpkg, or using Qt from custom location + file(READ "${VCPKG_ROOT_DIR}/_env/QT_CMAKE_PREFIX_PATH.txt" QT_CMAKE_PREFIX_PATH) + set(QUAZIP_EXTRA_OPTS "-DCMAKE_PREFIX_PATH=${QT_CMAKE_PREFIX_PATH}") +else() + # In the case of using system Qt, don't pass anything. + set(QUAZIP_EXTRA_OPTS "") +endif() + file(READ "${VCPKG_ROOT_DIR}/_env/EXTERNAL_BUILD_ASSETS.txt" EXTERNAL_BUILD_ASSETS) vcpkg_download_distfile( @@ -19,7 +28,7 @@ vcpkg_extract_source_archive_ex( vcpkg_configure_cmake( SOURCE_PATH ${SOURCE_PATH} PREFER_NINJA - OPTIONS -DCMAKE_POSITION_INDEPENDENT_CODE=ON -DCMAKE_PREFIX_PATH=${QT_CMAKE_PREFIX_PATH} -DBUILD_WITH_QT4=OFF + OPTIONS -DCMAKE_POSITION_INDEPENDENT_CODE=ON ${QUAZIP_EXTRA_OPTS} -DBUILD_WITH_QT4=OFF ) vcpkg_install_cmake() diff --git a/domain-server/resources/web/wizard/index.shtml b/domain-server/resources/web/wizard/index.shtml index 6d56a99682..f140ba8686 100644 --- a/domain-server/resources/web/wizard/index.shtml +++ b/domain-server/resources/web/wizard/index.shtml @@ -24,7 +24,7 @@
- Place names are similar to web addresses. Users who want to visit your domain can + Place names are similar to web addresses. Users who want to visit your domain can enter its Place Name in Vircadia's Interface. You can choose a Place Name for your domain.
Your domain may also be reachable by IP address.
@@ -196,8 +196,8 @@
- Would you like use automatic threading for your server's avatars and audio? - If you are hosting this server on your local computer and it is not very powerful, then consider leaving this off because the server will use more resources if it is being utilized extensively, thereby slowing down your computer. + Would you like use automatic threading for your server's avatars and audio? + If you are hosting this server on your local computer and it is not very powerful, then consider leaving this off because the server will use more resources if it is being utilized extensively, thereby slowing down your computer. If you are running this server on a powerful system and intend to have a large audience, then turn this setting on.
diff --git a/domain-server/src/DomainGatekeeper.cpp b/domain-server/src/DomainGatekeeper.cpp index 035caaa328..d55a00dcf1 100644 --- a/domain-server/src/DomainGatekeeper.cpp +++ b/domain-server/src/DomainGatekeeper.cpp @@ -357,7 +357,7 @@ void DomainGatekeeper::updateNodePermissions() { } else { // at this point we don't have a sending socket for packets from this node - assume it is the active socket // or the public socket if we haven't activated a socket for the node yet - HifiSockAddr connectingAddr = node->getActiveSocket() ? *node->getActiveSocket() : node->getPublicSocket(); + SockAddr connectingAddr = node->getActiveSocket() ? *node->getActiveSocket() : node->getPublicSocket(); QString hardwareAddress; QUuid machineFingerprint; @@ -651,7 +651,7 @@ SharedNodePointer DomainGatekeeper::processAgentConnectRequest(const NodeConnect } SharedNodePointer DomainGatekeeper::addVerifiedNodeFromConnectRequest(const NodeConnectionData& nodeConnection) { - HifiSockAddr discoveredSocket = nodeConnection.senderSockAddr; + SockAddr discoveredSocket = nodeConnection.senderSockAddr; SharedNetworkPeer connectedPeer = _icePeers.value(nodeConnection.connectUUID); if (connectedPeer && connectedPeer->getActiveSocket()) { @@ -690,7 +690,7 @@ void DomainGatekeeper::cleanupICEPeerForNode(const QUuid& nodeID) { bool DomainGatekeeper::verifyUserSignature(const QString& username, const QByteArray& usernameSignature, - const HifiSockAddr& senderSockAddr) { + const SockAddr& senderSockAddr) { // it's possible this user can be allowed to connect, but we need to check their username signature auto lowerUsername = username.toLower(); KeyFlagPair publicKeyPair = _userPublicKeys.value(lowerUsername); @@ -773,7 +773,7 @@ bool DomainGatekeeper::needToVerifyDomainUserIdentity(const QString& username, c } bool DomainGatekeeper::verifyDomainUserIdentity(const QString& username, const QString& accessToken, - const QString& refreshToken, const HifiSockAddr& senderSockAddr) { + const QString& refreshToken, const SockAddr& senderSockAddr) { if (_verifiedDomainUserIdentities.contains(username) && _verifiedDomainUserIdentities.value(username) == QPair(accessToken, refreshToken)) { return true; @@ -871,7 +871,7 @@ void DomainGatekeeper::publicKeyJSONErrorCallback(QNetworkReply* requestReply) { _inFlightPublicKeyRequests.remove(username); } -void DomainGatekeeper::sendProtocolMismatchConnectionDenial(const HifiSockAddr& senderSockAddr) { +void DomainGatekeeper::sendProtocolMismatchConnectionDenial(const SockAddr& senderSockAddr) { QString protocolVersionError = "Protocol version mismatch - Domain version: " + QCoreApplication::applicationVersion(); qDebug() << "Protocol Version mismatch - denying connection."; @@ -880,7 +880,7 @@ void DomainGatekeeper::sendProtocolMismatchConnectionDenial(const HifiSockAddr& DomainHandler::ConnectionRefusedReason::ProtocolMismatch); } -void DomainGatekeeper::sendConnectionDeniedPacket(const QString& reason, const HifiSockAddr& senderSockAddr, +void DomainGatekeeper::sendConnectionDeniedPacket(const QString& reason, const SockAddr& senderSockAddr, DomainHandler::ConnectionRefusedReason reasonCode, QString extraInfo) { // this is an agent and we've decided we won't let them connect - send them a packet to deny connection @@ -910,7 +910,7 @@ void DomainGatekeeper::sendConnectionDeniedPacket(const QString& reason, const H DependencyManager::get()->sendPacket(std::move(connectionDeniedPacket), senderSockAddr); } -void DomainGatekeeper::sendConnectionTokenPacket(const QString& username, const HifiSockAddr& senderSockAddr) { +void DomainGatekeeper::sendConnectionTokenPacket(const QString& username, const SockAddr& senderSockAddr) { // get the existing connection token or create a new one QUuid& connectionToken = _connectionTokenHash[username.toLower()]; diff --git a/domain-server/src/DomainGatekeeper.h b/domain-server/src/DomainGatekeeper.h index cb42baa7e3..94f760d42e 100644 --- a/domain-server/src/DomainGatekeeper.h +++ b/domain-server/src/DomainGatekeeper.h @@ -47,7 +47,7 @@ public: Node::LocalID findOrCreateLocalID(const QUuid& uuid); - static void sendProtocolMismatchConnectionDenial(const HifiSockAddr& senderSockAddr); + static void sendProtocolMismatchConnectionDenial(const SockAddr& senderSockAddr); public slots: void processConnectRequestPacket(QSharedPointer message); void processICEPingPacket(QSharedPointer message); @@ -90,19 +90,19 @@ private: SharedNodePointer addVerifiedNodeFromConnectRequest(const NodeConnectionData& nodeConnection); bool verifyUserSignature(const QString& username, const QByteArray& usernameSignature, - const HifiSockAddr& senderSockAddr); + const SockAddr& senderSockAddr); bool needToVerifyDomainUserIdentity(const QString& username, const QString& accessToken, const QString& refreshToken); bool verifyDomainUserIdentity(const QString& username, const QString& accessToken, const QString& refreshToken, - const HifiSockAddr& senderSockAddr); + const SockAddr& senderSockAddr); bool isWithinMaxCapacity(); bool shouldAllowConnectionFromNode(const QString& username, const QByteArray& usernameSignature, - const HifiSockAddr& senderSockAddr); + const SockAddr& senderSockAddr); - void sendConnectionTokenPacket(const QString& username, const HifiSockAddr& senderSockAddr); - static void sendConnectionDeniedPacket(const QString& reason, const HifiSockAddr& senderSockAddr, + void sendConnectionTokenPacket(const QString& username, const SockAddr& senderSockAddr); + static void sendConnectionDeniedPacket(const QString& reason, const SockAddr& senderSockAddr, DomainHandler::ConnectionRefusedReason reasonCode = DomainHandler::ConnectionRefusedReason::Unknown, QString extraInfo = QString()); diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 3acd17f6af..b221c88f6e 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -777,7 +777,7 @@ void DomainServer::setupNodeListAndAssignments() { connect(nodeList.data(), &LimitedNodeList::nodeAdded, this, &DomainServer::nodeAdded); connect(nodeList.data(), &LimitedNodeList::nodeKilled, this, &DomainServer::nodeKilled); connect(nodeList.data(), &LimitedNodeList::localSockAddrChanged, this, - [this](const HifiSockAddr& localSockAddr) { + [this](const SockAddr& localSockAddr) { DependencyManager::get()->putLocalPortIntoSharedMemory(DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY, this, localSockAddr.getPort()); }); @@ -1225,7 +1225,7 @@ void DomainServer::handleConnectedNode(SharedNodePointer newNode, quint64 reques broadcastNewNode(newNode); } -void DomainServer::sendDomainListToNode(const SharedNodePointer& node, quint64 requestPacketReceiveTime, const HifiSockAddr &senderSockAddr, bool newConnection) { +void DomainServer::sendDomainListToNode(const SharedNodePointer& node, quint64 requestPacketReceiveTime, const SockAddr &senderSockAddr, bool newConnection) { const int NUM_DOMAIN_LIST_EXTENDED_HEADER_BYTES = NUM_BYTES_RFC4122_UUID + NLPacket::NUM_BYTES_LOCALID + NUM_BYTES_RFC4122_UUID + NLPacket::NUM_BYTES_LOCALID + 4; @@ -1501,7 +1501,7 @@ void DomainServer::transactionJSONCallback(const QJsonObject& data) { } } -QJsonObject jsonForDomainSocketUpdate(const HifiSockAddr& socket) { +QJsonObject jsonForDomainSocketUpdate(const SockAddr& socket) { const QString SOCKET_NETWORK_ADDRESS_KEY = "network_address"; const QString SOCKET_PORT_KEY = "port"; @@ -1512,7 +1512,7 @@ QJsonObject jsonForDomainSocketUpdate(const HifiSockAddr& socket) { return socketObject; } -void DomainServer::performIPAddressPortUpdate(const HifiSockAddr& newPublicSockAddr) { +void DomainServer::performIPAddressPortUpdate(const SockAddr& newPublicSockAddr) { const QString& DOMAIN_SERVER_SETTINGS_KEY = "domain_server"; const QString& publicSocketAddress = newPublicSockAddr.getAddress().toString(); const int publicSocketPort = newPublicSockAddr.getPort(); @@ -1770,7 +1770,7 @@ void DomainServer::sendHeartbeatToIceServer() { QDataStream heartbeatStream(_iceServerHeartbeatPacket.get()); QUuid senderUUID; - HifiSockAddr publicSocket, localSocket; + SockAddr publicSocket, localSocket; heartbeatStream >> senderUUID >> publicSocket >> localSocket; if (senderUUID != limitedNodeList->getSessionUUID() @@ -1928,7 +1928,7 @@ void DomainServer::processNodeJSONStatsPacket(QSharedPointer pa } } -QJsonObject DomainServer::jsonForSocket(const HifiSockAddr& socket) { +QJsonObject DomainServer::jsonForSocket(const SockAddr& socket) { QJsonObject socketJSON; socketJSON["ip"] = socket.getAddress().toString(); @@ -3017,7 +3017,7 @@ static const QString BROADCASTING_SETTINGS_KEY = "broadcasting"; struct ReplicationServerInfo { NodeType_t nodeType; - HifiSockAddr sockAddr; + SockAddr sockAddr; }; ReplicationServerInfo serverInformationFromSettings(QVariantMap serverMap, ReplicationServerDirection direction) { @@ -3038,7 +3038,7 @@ ReplicationServerInfo serverInformationFromSettings(QVariantMap serverMap, Repli serverInfo.nodeType = NodeType::downstreamType(nodeType); } - // read the address and port and construct a HifiSockAddr from them + // read the address and port and construct a SockAddr from them serverInfo.sockAddr = { serverMap[REPLICATION_SERVER_ADDRESS].toString(), (quint16) serverMap[REPLICATION_SERVER_PORT].toString().toInt() @@ -3047,7 +3047,7 @@ ReplicationServerInfo serverInformationFromSettings(QVariantMap serverMap, Repli return serverInfo; } - return { NodeType::Unassigned, HifiSockAddr() }; + return { NodeType::Unassigned, SockAddr() }; } void DomainServer::updateReplicationNodes(ReplicationServerDirection direction) { @@ -3056,7 +3056,7 @@ void DomainServer::updateReplicationNodes(ReplicationServerDirection direction) if (broadcastSettingsVariant.isValid()) { auto nodeList = DependencyManager::get(); - std::vector replicationNodesInSettings; + std::vector replicationNodesInSettings; auto replicationSettings = broadcastSettingsVariant.toMap(); @@ -3066,7 +3066,7 @@ void DomainServer::updateReplicationNodes(ReplicationServerDirection direction) if (replicationSettings.contains(serversKey)) { auto serversSettings = replicationSettings.value(serversKey).toList(); - std::vector knownReplicationNodes; + std::vector knownReplicationNodes; nodeList->eachNode([direction, &knownReplicationNodes](const SharedNodePointer& otherNode) { if ((direction == Upstream && NodeType::isUpstream(otherNode->getType())) || (direction == Downstream && NodeType::isDownstream(otherNode->getType()))) { @@ -3620,7 +3620,7 @@ void DomainServer::randomizeICEServerAddress(bool shouldTriggerHostLookup) { indexToTry = distribution(generator); } - _iceServerSocket = HifiSockAddr { candidateICEAddresses[indexToTry], ICE_SERVER_DEFAULT_PORT }; + _iceServerSocket = SockAddr { candidateICEAddresses[indexToTry], ICE_SERVER_DEFAULT_PORT }; qCInfo(domain_server_ice) << "Set candidate ice-server socket to" << _iceServerSocket; // clear our number of hearbeat denials, this should be re-set on ice-server change diff --git a/domain-server/src/DomainServer.h b/domain-server/src/DomainServer.h index 11d04cb255..deb204de1c 100644 --- a/domain-server/src/DomainServer.h +++ b/domain-server/src/DomainServer.h @@ -113,7 +113,7 @@ private slots: void setupPendingAssignmentCredits(); void sendPendingTransactionsToServer(); - void performIPAddressPortUpdate(const HifiSockAddr& newPublicSockAddr); + void performIPAddressPortUpdate(const SockAddr& newPublicSockAddr); void sendHeartbeatToMetaverse() { sendHeartbeatToMetaverse(QString(), int()); } void sendHeartbeatToIceServer(); void nodePingMonitor(); @@ -186,7 +186,7 @@ private: void handleKillNode(SharedNodePointer nodeToKill); void broadcastNodeDisconnect(const SharedNodePointer& disconnnectedNode); - void sendDomainListToNode(const SharedNodePointer& node, quint64 requestPacketReceiveTime, const HifiSockAddr& senderSockAddr, bool newConnection); + void sendDomainListToNode(const SharedNodePointer& node, quint64 requestPacketReceiveTime, const SockAddr& senderSockAddr, bool newConnection); bool isInInterestSet(const SharedNodePointer& nodeA, const SharedNodePointer& nodeB); @@ -212,7 +212,7 @@ private: QNetworkReply* profileRequestGivenTokenReply(QNetworkReply* tokenReply); Headers setupCookieHeadersFromProfileReply(QNetworkReply* profileReply); - QJsonObject jsonForSocket(const HifiSockAddr& socket); + QJsonObject jsonForSocket(const SockAddr& socket); QJsonObject jsonObjectForNode(const SharedNodePointer& node); bool shouldReplicateNode(const Node& node); @@ -270,7 +270,7 @@ private: DomainServerSettingsManager _settingsManager; - HifiSockAddr _iceServerSocket; + SockAddr _iceServerSocket; std::unique_ptr _iceServerHeartbeatPacket; // These will be parented to this, they are not dangling diff --git a/domain-server/src/DomainServerNodeData.h b/domain-server/src/DomainServerNodeData.h index 370886cbce..0a2e2775e2 100644 --- a/domain-server/src/DomainServerNodeData.h +++ b/domain-server/src/DomainServerNodeData.h @@ -4,6 +4,7 @@ // // Created by Stephen Birarda on 2/6/2014. // Copyright 2014 High Fidelity, Inc. +// Copyright 2021 Vircadia contributors. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -17,7 +18,7 @@ #include #include -#include +#include #include #include #include @@ -41,8 +42,8 @@ public: QElapsedTimer& getPaymentIntervalTimer() { return _paymentIntervalTimer; } - void setSendingSockAddr(const HifiSockAddr& sendingSockAddr) { _sendingSockAddr = sendingSockAddr; } - const HifiSockAddr& getSendingSockAddr() { return _sendingSockAddr; } + void setSendingSockAddr(const SockAddr& sendingSockAddr) { _sendingSockAddr = sendingSockAddr; } + const SockAddr& getSendingSockAddr() { return _sendingSockAddr; } void setIsAuthenticated(bool isAuthenticated) { _isAuthenticated = isAuthenticated; } bool isAuthenticated() const { return _isAuthenticated; } @@ -90,7 +91,7 @@ private: QJsonObject _statsJSONObject; static StringPairHash _overrideHash; - HifiSockAddr _sendingSockAddr; + SockAddr _sendingSockAddr; bool _isAuthenticated = true; NodeSet _nodeInterestSet; QString _nodeVersion; diff --git a/domain-server/src/NodeConnectionData.cpp b/domain-server/src/NodeConnectionData.cpp index 5419014622..1ef8ebf6a9 100644 --- a/domain-server/src/NodeConnectionData.cpp +++ b/domain-server/src/NodeConnectionData.cpp @@ -4,6 +4,7 @@ // // Created by Stephen Birarda on 2015-08-24. // Copyright 2015 High Fidelity, Inc. +// Copyright 2021 Vircadia contributors. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -13,7 +14,7 @@ #include -NodeConnectionData NodeConnectionData::fromDataStream(QDataStream& dataStream, const HifiSockAddr& senderSockAddr, +NodeConnectionData NodeConnectionData::fromDataStream(QDataStream& dataStream, const SockAddr& senderSockAddr, bool isConnectRequest) { NodeConnectionData newHeader; diff --git a/domain-server/src/NodeConnectionData.h b/domain-server/src/NodeConnectionData.h index 3833f5afd3..5976f07787 100644 --- a/domain-server/src/NodeConnectionData.h +++ b/domain-server/src/NodeConnectionData.h @@ -4,6 +4,7 @@ // // Created by Stephen Birarda on 2015-08-24. // Copyright 2015 High Fidelity, Inc. +// Copyright 2021 Vircadia contributors. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -18,15 +19,15 @@ class NodeConnectionData { public: - static NodeConnectionData fromDataStream(QDataStream& dataStream, const HifiSockAddr& senderSockAddr, + static NodeConnectionData fromDataStream(QDataStream& dataStream, const SockAddr& senderSockAddr, bool isConnectRequest = true); QUuid connectUUID; quint64 lastPingTimestamp{ 0 }; // client-side send time of last connect/domain list request NodeType_t nodeType; - HifiSockAddr publicSockAddr; - HifiSockAddr localSockAddr; - HifiSockAddr senderSockAddr; + SockAddr publicSockAddr; + SockAddr localSockAddr; + SockAddr senderSockAddr; QList interestList; QString placeName; QString hardwareAddress; diff --git a/hifi_qt.py b/hifi_qt.py index 7ee8a787b5..078f80c38d 100644 --- a/hifi_qt.py +++ b/hifi_qt.py @@ -10,6 +10,31 @@ import json import xml.etree.ElementTree as ET import functools +# The way Qt is handled is a bit complicated, so I'm documenting it here. +# +# 1. User runs cmake +# 2. cmake calls prebuild.py, which is referenced in /CMakeLists.txt +# 3. prebuild.py calls this code. +# 4. hifi_qt.py determines how to handle cmake: do we need to download a package, and which? +# 4.a - Using system Qt +# No download, most special paths are turned off. +# We build in the same way a normal Qt program would. +# 4.b - Using an user-provided Qt build in a custom directory. +# We just need to set the cmakePath to the right dir (qt5-install/lib/cmake) +# 4.c - Using a premade package. +# We check the OS and distro and set qtUrl to the URL to download. +# After this, it works on the same pathway as 4.b. +# 5. We write /qt.cmake, which contains paths that are passed down to SetupQt.cmake +# The template for this file is in CMAKE_TEMPLATE just below this comment +# and it sets the QT_CMAKE_PREFIX_PATH variable used by SetupQt.cmake. +# 6. cmake includes /qt.cmake receiving our information +# In the case of system Qt, this step is skipped. +# 7. cmake runs SetupQt.cmake which takes care of the cmake parts of the Qt configuration. +# In the case of system Qt, SetupQt.cmake is a no-op. It runs but exits immediately. +# +# The format for a prebuilt qt is a package containing a top-level directory named +# 'qt5-install', which contains the result of a "make install" from a build of the Qt source. + print = functools.partial(print, flush=True) # Encapsulates the vcpkg system @@ -28,32 +53,85 @@ endif() self.args = args self.configFilePath = os.path.join(args.build_root, 'qt.cmake') self.version = os.getenv('VIRCADIA_USE_QT_VERSION', '5.15.2') - self.assets_url = hifi_utils.readEnviromentVariableFromFile(args.build_root, 'EXTERNAL_BUILD_ASSETS') - defaultBasePath = os.path.expanduser('~/hifi/qt') - self.basePath = os.getenv('HIFI_QT_BASE', defaultBasePath) - if (not os.path.isdir(self.basePath)): - os.makedirs(self.basePath) - self.path = os.path.join(self.basePath, self.version) - self.fullPath = os.path.join(self.path, 'qt5-install') - self.cmakePath = os.path.join(self.fullPath, 'lib/cmake') - - print("Using qt path {}".format(self.path)) - lockDir, lockName = os.path.split(self.path) - lockName += '.lock' - if not os.path.isdir(lockDir): - os.makedirs(lockDir) - - self.lockFile = os.path.join(lockDir, lockName) - - if (os.getenv('VIRCADIA_USE_PREBUILT_QT')): - print("Using pre-built Qt5") - return - # OS dependent information system = platform.system() - cpu_architecture = platform.machine() + + qt_found = False + system_qt = False + + # Here we handle the 3 possible cases of dealing with Qt: + if os.getenv('VIRCADIA_USE_SYSTEM_QT', "") != "": + # 1. Using the system provided Qt. This is only recommended for Qt 5.15.0 and above, + # as it includes a required fix on Linux. + # + # This path only works on Linux as neither Windows nor OSX ship Qt. + + if system != "Linux": + raise Exception("Using the system Qt is only supported on Linux") + + self.path = None + self.cmakePath = None + + qt_found = True + system_qt = True + print("Using system Qt") + + elif os.getenv('VIRCADIA_QT_PATH', "") != "": + # 2. Using an user-provided directory. + # VIRCADIA_QT_PATH must point to a directory with a Qt install in it. + + self.path = os.getenv('VIRCADIA_QT_PATH') + self.fullPath = self.path + self.cmakePath = os.path.join(self.fullPath, 'lib', 'cmake') + + qt_found = True + print("Using Qt from " + self.fullPath) + + else: + # 3. Using a pre-built Qt. + # + # This works somewhat differently from above, notice how path and fullPath are + # used differently in this case. + # + # In the case of an user-provided directory, we just use the user-supplied directory. + # + # For a pre-built qt, however, we have to unpack it. The archive is required to contain + # a qt5-install directory in it. + + self.path = os.path.expanduser("~/vircadia-files/qt") + self.fullPath = os.path.join(self.path, 'qt5-install') + self.cmakePath = os.path.join(self.fullPath, 'lib', 'cmake') + + if (not os.path.isdir(self.path)): + os.makedirs(self.path) + + qt_found = os.path.isdir(self.fullPath) + print("Using a packaged Qt") + + + if not system_qt: + if qt_found: + # Sanity check, ensure we have a good cmake directory + qt5_dir = os.path.join(self.cmakePath, "Qt5") + if not os.path.isdir(qt5_dir): + raise Exception("Failed to find Qt5 directory under " + self.cmakePath + ". There should be a " + qt5_dir) + else: + print("Qt5 check passed, found " + qt5_dir) + + # I'm not sure why this is needed. It's used by hifi_singleton. + # Perhaps it stops multiple build processes from interferring? + lockDir, lockName = os.path.split(self.path) + lockName += '.lock' + if not os.path.isdir(lockDir): + os.makedirs(lockDir) + + self.lockFile = os.path.join(lockDir, lockName) + + if qt_found: + print("Found pre-built Qt5") + return if 'Windows' == system: self.qtUrl = self.assets_url + '/dependencies/vcpkg/qt5-install-5.15.2-windows.tar.gz' @@ -61,7 +139,7 @@ endif() self.qtUrl = self.assets_url + '/dependencies/vcpkg/qt5-install-5.15.2-macos.tar.gz' elif 'Linux' == system: import distro - dist = distro.linux_distribution() + cpu_architecture = platform.machine() if 'x86_64' == cpu_architecture: if distro.id() == 'ubuntu': @@ -71,16 +149,12 @@ endif() if u_major == 18: self.qtUrl = self.assets_url + '/dependencies/vcpkg/qt5-install-5.15.2-ubuntu-18.04-amd64.tar.xz' elif u_major > 19: - print("We don't support " + distro.name(pretty=True) + " yet. Perhaps consider helping us out?") - raise Exception('LINUX DISTRO IS NOT SUPPORTED YET!!!') + self.__no_qt_package_error() else: - print("Sorry, " + distro.name(pretty=True) + " is old and won't be officially supported. Please consider upgrading."); - raise Exception('UNKNOWN LINUX DISTRO VERSION!!!') + self.__unsupported_error() else: - print("Sorry, " + distro.name(pretty=True) + " is not supported on x86_64. Please consider helping us out.") - print("It's also possible to build Qt for your distribution, please see the documentation at:") - print("https://github.com/vircadia/vircadia/tree/master/tools/qt-builder") - raise Exception('UNKNOWN LINUX VERSION!!!') + self.__no_qt_package_error() + elif 'aarch64' == cpu_architecture: if distro.id() == 'ubuntu': u_major = int( distro.major_version() ) @@ -89,11 +163,9 @@ endif() if u_major == 18: self.qtUrl = 'http://motofckr9k.ddns.net/vircadia_packages/qt5-install-5.15.2-ubuntu-18.04-aarch64_test.tar.xz' elif u_major > 19: - print("We don't support " + distro.name(pretty=True) + " on aarch64 yet. Perhaps consider helping us out?") - raise Exception('LINUX DISTRO IS NOT SUPPORTED YET!!!') + self.__no_qt_package_error() else: - print("Sorry, " + distro.name(pretty=True) + " is old and won't be officially supported. Please consider upgrading."); - raise Exception('UNKNOWN LINUX DISTRO VERSION!!!') + self.__unsupported_error() elif distro.id() == 'debian': u_major = int( distro.major_version() ) @@ -101,20 +173,14 @@ endif() if u_major == 10: #self.qtUrl = self.assets_url + '/dependencies/vcpkg/qt5-install-5.12.3-ubuntu-16.04-with-symbols.tar.gz' - print("We don't support " + distro.name(pretty=True) + " on aarch64 yet. Perhaps consider helping us out?") - raise Exception('LINUX DISTRO IS NOT SUPPORTED YET!!!') + self.__no_qt_package_error() elif u_major > 10: - print("We don't support " + distro.name(pretty=True) + " on aarch64 yet. Perhaps consider helping us out?") - raise Exception('LINUX DISTRO IS NOT SUPPORTED YET!!!') + self.__no_qt_package_error() else: - print("Sorry, " + distro.name(pretty=True) + " is old and won't be officially supported. Please consider upgrading."); - raise Exception('UNKNOWN LINUX DISTRO VERSION!!!') + self.__unsupported_error() else: - print("Sorry, " + distro.name(pretty=True) + " is not supported on aarch64. Please consider helping us out.") - print("It's also possible to build Qt for your distribution, please see the documentation at:") - print("https://github.com/vircadia/vircadia/tree/master/tools/qt-builder") - raise Exception('UNKNOWN LINUX VERSION!!!') + self.__no_qt_package_error() else: raise Exception('UNKNOWN CPU ARCHITECTURE!!!') @@ -124,6 +190,14 @@ endif() print("Machine : " + platform.machine()) raise Exception('UNKNOWN OPERATING SYSTEM!!!') + def showQtBuildInfo(self): + print("") + print("It's also possible to build Qt for your distribution, please see the documentation at:") + print("https://github.com/vircadia/vircadia/tree/master/tools/qt-builder") + print("") + print("Alternatively, you can try building against the system Qt by setting the VIRCADIA_USE_SYSTEM_QT environment variable.") + print("You'll need to install the development packages, and to have Qt 5.15.0 or newer. ") + def writeConfig(self): print("Writing cmake config to {}".format(self.configFilePath)) # Write out the configuration for use by CMake @@ -138,3 +212,40 @@ endif() hifi_utils.downloadAndExtract(self.qtUrl, self.path) else: print ('Qt has already been downloaded') + + + def __unsupported_error(self): + import distro + cpu_architecture = platform.machine() + + print('') + hifi_utils.color('red') + print("Sorry, " + distro.name(pretty=True) + " on " + cpu_architecture + " is too old and won't be officially supported.") + hifi_utils.color('white') + print("Please upgrade to a more recent Linux distribution.") + hifi_utils.color('clear') + print('') + raise hifi_utils.SilentFatalError(3) + + def __no_qt_package_error(self): + import distro + cpu_architecture = platform.machine() + + print('') + hifi_utils.color('red') + print("Sorry, we don't have a prebuilt Qt package for " + distro.name(pretty=True) + " on " + cpu_architecture + ".") + hifi_utils.color('white') + print('') + print("If this is a recent distribution, dating from 2021 or so, you can try building") + print("against the system Qt by running this command, and trying again:") + print(" export VIRCADIA_USE_SYSTEM_QT=1") + print("") + hifi_utils.color('clear') + print("If you'd like to try to build Qt from source either for building Vircadia, or") + print("to contribute a prebuilt package for your distribution, please see the") + print("documentation at: ", end='') + hifi_utils.color('blue') + print("https://github.com/vircadia/vircadia/tree/master/tools/qt-builder") + hifi_utils.color('clear') + print('') + raise hifi_utils.SilentFatalError(2) diff --git a/hifi_utils.py b/hifi_utils.py index 157e5858a8..19290dbc42 100644 --- a/hifi_utils.py +++ b/hifi_utils.py @@ -16,6 +16,18 @@ import functools print = functools.partial(print, flush=True) +ansi_colors = { + 'black' : 30, + 'red': 31, + 'green': 32, + 'yellow': 33, + 'blue': 34, + 'magenta': 35, + 'cyan': 36, + 'white': 37, + 'clear': 0 +} + def scriptRelative(*paths): scriptdir = os.path.dirname(os.path.realpath(sys.argv[0])) result = os.path.join(scriptdir, *paths) @@ -125,3 +137,17 @@ def downloadAndExtract(url, destPath, hash=None, hasher=hashlib.sha512(), isZip= def readEnviromentVariableFromFile(buildRootDir, var): with open(os.path.join(buildRootDir, '_env', var + ".txt")) as fp: return fp.read() + +class SilentFatalError(Exception): + """Thrown when some sort of fatal condition happened, and we already reported it to the user. + This excecption exists to give a chance to run any cleanup needed before exiting. + + It should be handled at the bottom of the call stack, where the only action is to call + sys.exit(ex.exit_code) + """ + def __init__(self, exit_code): + self.exit_code = exit_code + +def color(color_name): + # Ideally we'd use the termcolor module, but this avoids adding it as a dependency. + print("\033[1;{}m".format(ansi_colors[color_name]), end='') \ No newline at end of file diff --git a/hifi_vcpkg.py b/hifi_vcpkg.py index fb77fd2507..642ed1253e 100644 --- a/hifi_vcpkg.py +++ b/hifi_vcpkg.py @@ -60,7 +60,7 @@ endif() self.path = args.vcpkg_root self.noClean = True else: - defaultBasePath = os.path.expanduser('~/hifi/vcpkg') + defaultBasePath = os.path.expanduser('~/vircadia-files/vcpkg') self.basePath = os.getenv('HIFI_VCPKG_BASE', defaultBasePath) if self.args.android: self.basePath = os.path.join(self.basePath, 'android') diff --git a/ice-server/src/IceServer.cpp b/ice-server/src/IceServer.cpp index a8e50d31a9..d42c0a4e2a 100644 --- a/ice-server/src/IceServer.cpp +++ b/ice-server/src/IceServer.cpp @@ -4,6 +4,7 @@ // // Created by Stephen Birarda on 2014-10-01. // Copyright 2014 High Fidelity, Inc. +// Copyright 2021 Vircadia contributors. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -97,7 +98,7 @@ void IceServer::processPacket(std::unique_ptr packet) { heartbeatStream >> senderUUID; // pull the public and private sock addrs for this peer - HifiSockAddr publicSocket, localSocket; + SockAddr publicSocket, localSocket; heartbeatStream >> publicSocket >> localSocket; // check if this node also included a UUID that they would like to connect to @@ -129,7 +130,7 @@ SharedNetworkPeer IceServer::addOrUpdateHeartbeatingPeer(NLPacket& packet) { // pull the UUID, public and private sock addrs for this peer QUuid senderUUID; - HifiSockAddr publicSocket, localSocket; + SockAddr publicSocket, localSocket; QByteArray signature; QDataStream heartbeatStream(&packet); @@ -288,7 +289,7 @@ void IceServer::publicKeyReplyFinished(QNetworkReply* reply) { reply->deleteLater(); } -void IceServer::sendPeerInformationPacket(const NetworkPeer& peer, const HifiSockAddr* destinationSockAddr) { +void IceServer::sendPeerInformationPacket(const NetworkPeer& peer, const SockAddr* destinationSockAddr) { auto peerPacket = NLPacket::create(PacketType::ICEServerPeerInformation); // get the byte array for this peer diff --git a/ice-server/src/IceServer.h b/ice-server/src/IceServer.h index 2aa9a875a7..e68115f7ef 100644 --- a/ice-server/src/IceServer.h +++ b/ice-server/src/IceServer.h @@ -4,6 +4,7 @@ // // Created by Stephen Birarda on 2014-10-01. // Copyright 2014 High Fidelity, Inc. +// Copyright 2021 Vircadia contributors. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -40,7 +41,7 @@ private: void processPacket(std::unique_ptr packet); SharedNetworkPeer addOrUpdateHeartbeatingPeer(NLPacket& incomingPacket); - void sendPeerInformationPacket(const NetworkPeer& peer, const HifiSockAddr* destinationSockAddr); + void sendPeerInformationPacket(const NetworkPeer& peer, const SockAddr* destinationSockAddr); bool isVerifiedHeartbeat(const QUuid& domainID, const QByteArray& plaintext, const QByteArray& signature); void requestDomainPublicKey(const QUuid& domainID); diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index c307c63142..a2a29ed4ba 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -34,14 +34,14 @@ if (ANDROID) add_custom_command( OUTPUT ${RESOURCES_RCC} DEPENDS ${RESOURCES_QRC} ${GENERATE_QRC_DEPENDS} - COMMAND "${QT_DIR}/bin/rcc" + COMMAND "${RCC_BINARY}" ARGS ${RESOURCES_QRC} -no-compress -binary -o ${RESOURCES_RCC} ) else () add_custom_command( OUTPUT ${RESOURCES_RCC} DEPENDS ${RESOURCES_QRC} ${GENERATE_QRC_DEPENDS} - COMMAND "${QT_DIR}/bin/rcc" + COMMAND "${RCC_BINARY}" ARGS ${RESOURCES_QRC} -binary -o ${RESOURCES_RCC} ) endif() @@ -435,18 +435,20 @@ else() endif() endif() -if (DEV_BUILD AND (APPLE OR UNIX)) - # create a qt.conf file to override hard-coded search paths in Qt libs - set(QT_LIB_PATH "${QT_CMAKE_PREFIX_PATH}/../..") - if (APPLE) - set(QT_CONF_FILE "${RESOURCES_DEV_DIR}/../Resources/qt.conf") - else () - set(QT_CONF_FILE "${INTERFACE_EXEC_DIR}/qt.conf") - endif () - file(GENERATE - OUTPUT "${QT_CONF_FILE}" - CONTENT "[Paths]\nPrefix=${QT_LIB_PATH}\n" - ) +if ("$ENV{VIRCADIA_USE_SYSTEM_QT}" STREQUAL "") + if (DEV_BUILD AND (APPLE OR UNIX)) + # create a qt.conf file to override hard-coded search paths in Qt libs + set(QT_LIB_PATH "${QT_CMAKE_PREFIX_PATH}/../..") + if (APPLE) + set(QT_CONF_FILE "${RESOURCES_DEV_DIR}/../Resources/qt.conf") + else () + set(QT_CONF_FILE "${INTERFACE_EXEC_DIR}/qt.conf") + endif () + file(GENERATE + OUTPUT "${QT_CONF_FILE}" + CONTENT "[Paths]\nPrefix=${QT_LIB_PATH}\n" + ) + endif() endif() if (SCRIPTS_INSTALL_DIR) diff --git a/interface/resources/html/tabletHelp.html b/interface/resources/html/tabletHelp.html index 17b41a1979..f9dc7034f5 100644 --- a/interface/resources/html/tabletHelp.html +++ b/interface/resources/html/tabletHelp.html @@ -53,7 +53,7 @@ position: absolute; top: 0; left: 0; bottom: 0; right: 0; } - + #image_button { position: absolute; width: 463; @@ -77,13 +77,13 @@ var handControllerImageURL = null; var index = 0; var count = 3; - var handControllerRefURL = "https://docs.vircadia.dev/explore/get-started/vr-controls.html#vr-controls"; - var keyboardRefURL = "https://docs.vircadia.dev/explore/get-started/desktop.html#movement-controls"; - var gamepadRefURL = "https://docs.vircadia.dev/explore/get-started/vr-controls.html#gamepad"; + var handControllerRefURL = "https://docs.vircadia.com/explore/get-started/vr-controls.html#vr-controls"; + var keyboardRefURL = "https://docs.vircadia.com/explore/get-started/desktop.html#movement-controls"; + var gamepadRefURL = "https://docs.vircadia.com/explore/get-started/vr-controls.html#gamepad"; function showKbm() { document.getElementById("main_image").setAttribute("src", "img/tablet-help-keyboard.jpg"); - document.getElementById("image_button").setAttribute("href", keyboardRefURL); + document.getElementById("image_button").setAttribute("href", keyboardRefURL); } function showHandControllers() { @@ -107,7 +107,7 @@ } function chooseIcon() { - switch (index) + switch (index) { case 0: showGamepad(); diff --git a/interface/resources/qml/hifi/avatarPackager/AvatarPackagerApp.qml b/interface/resources/qml/hifi/avatarPackager/AvatarPackagerApp.qml index 00d8a29561..3c82fdb32b 100644 --- a/interface/resources/qml/hifi/avatarPackager/AvatarPackagerApp.qml +++ b/interface/resources/qml/hifi/avatarPackager/AvatarPackagerApp.qml @@ -229,7 +229,7 @@ Item { } function openDocs() { - Qt.openUrlExternally("https://docs.vircadia.dev/create/avatars/package-avatar.html"); + Qt.openUrlExternally("https://docs.vircadia.com/create/avatars/package-avatar.html"); } function openVideo() { diff --git a/interface/resources/qml/hifi/avatarPackager/AvatarProject.qml b/interface/resources/qml/hifi/avatarPackager/AvatarProject.qml index 9b59303a7e..62540d34d7 100644 --- a/interface/resources/qml/hifi/avatarPackager/AvatarProject.qml +++ b/interface/resources/qml/hifi/avatarPackager/AvatarProject.qml @@ -150,7 +150,7 @@ Item { id: uploadingItemFooter anchors.fill: parent - anchors.topMargin: 1 + anchors.topMargin: 1 visible: !!root.uploader && !root.finished && root.uploader.state === 4 color: "#00B4EF" @@ -205,7 +205,7 @@ Item { function showConfirmUploadPopup() { popup.titleText = 'Overwrite Avatar'; - popup.bodyText = 'You have previously uploaded the avatar file from this project.' + + popup.bodyText = 'You have previously uploaded the avatar file from this project.' + ' This will overwrite that avatar and you won’t be able to access the older version.'; popup.button1text = 'CREATE NEW'; @@ -318,7 +318,7 @@ Item { text: "This item is not for sale yet, learn more." onLinkActivated: { - Qt.openUrlExternally("https://docs.vircadia.dev/sell/add-item/upload-avatar.html"); + Qt.openUrlExternally("https://docs.vircadia.com/sell/add-item/upload-avatar.html"); } } diff --git a/interface/resources/qml/hifi/avatarapp/MessageBoxes.qml b/interface/resources/qml/hifi/avatarapp/MessageBoxes.qml index ccc28174a1..290bf14877 100644 --- a/interface/resources/qml/hifi/avatarapp/MessageBoxes.qml +++ b/interface/resources/qml/hifi/avatarapp/MessageBoxes.qml @@ -7,7 +7,7 @@ MessageBox { popup.onButton2Clicked = callback; popup.titleText = 'Specify Avatar URL' popup.bodyText = 'This will not overwrite your existing favorite if you are wearing one.
' + - '' + + '' + 'Learn to make a custom avatar by opening this link on your desktop.' + '' popup.inputText.visible = true; diff --git a/interface/resources/qml/hifi/commerce/checkout/Checkout.qml b/interface/resources/qml/hifi/commerce/checkout/Checkout.qml index 424b4d616d..2a88cf8c17 100644 --- a/interface/resources/qml/hifi/commerce/checkout/Checkout.qml +++ b/interface/resources/qml/hifi/commerce/checkout/Checkout.qml @@ -6,6 +6,7 @@ // // Created by Zach Fox on 2017-08-25 // Copyright 2017 High Fidelity, Inc. +// Copyright 2021 Vircadia contributors. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -196,7 +197,7 @@ Rectangle { root.availableUpdatesReceived = false; root.currentUpdatesPage = 1; Commerce.getAvailableUpdates(root.itemId); - + var MARKETPLACE_API_URL = Account.metaverseServerURL + "/api/v1/marketplace/items/"; http.request({uri: MARKETPLACE_API_URL + root.itemId}, updateCheckoutQMLFromHTTP); } @@ -327,7 +328,7 @@ Rectangle { } } } - } + } HifiCommerceCommon.FirstUseTutorial { id: firstUseTutorial; @@ -374,7 +375,7 @@ Rectangle { hoverEnabled: true; propagateComposedEvents: false; } - + AnimatedImage { id: loadingImage; source: "../common/images/loader-blue.gif" @@ -397,7 +398,7 @@ Rectangle { color: hifi.colors.black; size: 28; } - + HifiControlsUit.Separator { id: separator; colorScheme: 1; @@ -475,7 +476,7 @@ Rectangle { } FiraSansSemiBold { id: itemPriceText; - text: isTradingIn ? "FREE\nUPDATE" : + text: isTradingIn ? "FREE\nUPDATE" : (isStocking ? "Free for creator" : ((root.itemPrice === -1) ? "--" : ((root.itemPrice > 0) ? root.itemPrice : "FREE"))); // Text size @@ -491,7 +492,7 @@ Rectangle { } } } - + HifiControlsUit.Separator { id: separator2; colorScheme: 1; @@ -728,7 +729,7 @@ Rectangle { sendToScript({method: 'checkout_itemLinkClicked', itemId: itemId}); } } - + Rectangle { id: rezzedNotifContainer; z: 997; @@ -778,7 +779,7 @@ Rectangle { lightboxPopup.bodyText = "Rezzing this content set will replace the existing environment and all of the items in this domain. " + "If you want to save the state of the content in this domain, create a backup before proceeding.

" + "For more information about backing up and restoring content, " + - "" + + "" + "click here to open info on your desktop browser."; lightboxPopup.button1text = "CANCEL"; lightboxPopup.button1method = function() { @@ -1069,7 +1070,7 @@ Rectangle { buyButton.color = hifi.buttons.red; root.shouldBuyWithControlledFailure = true; } else { - buyButton.text = (root.isCertified ? + buyButton.text = (root.isCertified ? (dataReady ? (root.alreadyOwned ? "Buy Another" : "Buy") : "--") : @@ -1079,7 +1080,7 @@ Rectangle { } } } - + HifiCommon.RootHttpRequest { id: http; @@ -1211,7 +1212,7 @@ Rectangle { // Else if the user HAS NOT selected a specific edition to update... } else { handleBuyAgainLogic(); - } + } // If the user IS NOT on the checkout page for the updated verison of an owned item... // (i.e. they are checking out an item "normally") } else { diff --git a/interface/resources/qml/hifi/commerce/purchases/Purchases.qml b/interface/resources/qml/hifi/commerce/purchases/Purchases.qml index 8ccfceb03c..2d886ce38e 100644 --- a/interface/resources/qml/hifi/commerce/purchases/Purchases.qml +++ b/interface/resources/qml/hifi/commerce/purchases/Purchases.qml @@ -6,6 +6,7 @@ // // Created by Zach Fox on 2017-08-25 // Copyright 2017 High Fidelity, Inc. +// Copyright 2021 Vircadia contributors. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -115,7 +116,7 @@ Rectangle { Component.onCompleted: { isStandalone = PlatformInfo.isStandalone(); } - + HifiCommerceCommon.CommerceLightbox { id: lightboxPopup; z: 999; @@ -174,7 +175,7 @@ Rectangle { Commerce.getWalletStatus(); } } - + Item { id: installedAppsContainer; z: 998; @@ -210,7 +211,7 @@ Rectangle { delegate: Item { width: parent.width; height: 40; - + RalewayRegular { text: model.appUrl; // Text size @@ -251,7 +252,7 @@ Rectangle { Commerce.openApp(model.appUrl); } } - + HiFiGlyphs { id: uninstallGlyph; text: hifi.glyphs.close; @@ -292,7 +293,7 @@ Rectangle { height: 40; text: "SIDELOAD APP FROM LOCAL DISK"; onClicked: { - Window.browseChanged.connect(onFileOpenChanged); + Window.browseChanged.connect(onFileOpenChanged); Window.browseAsync("Locate your app's .app.json file", "", "*.app.json"); } } @@ -602,7 +603,7 @@ Rectangle { lightboxPopup.bodyText = "Rezzing this content set will replace the existing environment and all of the items in this domain. " + "If you want to save the state of the content in this domain, create a backup before proceeding.

" + "For more information about backing up and restoring content, " + - "
" + + "" + "click here to open info on your desktop browser."; lightboxPopup.button1text = "CANCEL"; lightboxPopup.button1method = function() { @@ -823,7 +824,7 @@ Rectangle { anchors.right: parent.right; height: 75; color: "#B5EAFF"; - + Rectangle { id: updatesAvailableGlyph; anchors.verticalCenter: parent.verticalCenter; @@ -991,7 +992,7 @@ Rectangle { // // FUNCTION DEFINITIONS START // - + function updateCurrentlyWornWearables(wearables) { for (var i = 0; i < purchasesModel.count; i++) { for (var j = 0; j < wearables.length; j++) { diff --git a/interface/resources/qml/hifi/commerce/wallet/Help.qml b/interface/resources/qml/hifi/commerce/wallet/Help.qml index dbdefc4c79..168a295ada 100644 --- a/interface/resources/qml/hifi/commerce/wallet/Help.qml +++ b/interface/resources/qml/hifi/commerce/wallet/Help.qml @@ -6,6 +6,7 @@ // // Created by Zach Fox on 2017-08-18 // Copyright 2017 High Fidelity, Inc. +// Copyright 2021 Vircadia contributors. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -207,7 +208,7 @@ At the moment, there is currently no way to convert HFC to other currencies. Sta if (link === "#privateKeyPath") { Qt.openUrlExternally("file:///" + root.keyFilePath.substring(0, root.keyFilePath.lastIndexOf('/'))); } else if (link === "#blockchain") { - Qt.openUrlExternally("https://docs.vircadia.dev/explore/shop.html"); + Qt.openUrlExternally("https://docs.vircadia.com/explore/shop.html"); } else if (link === "#bank") { if ((Account.metaverseServerURL).toString().indexOf("staging") >= 0) { Qt.openUrlExternally("hifi://hifiqa-master-metaverse-staging"); // So that we can test in staging. diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 807b5e55a5..759a96388d 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -164,6 +164,7 @@ #include #include #include +#include #include "recording/ClipCache.h" #include "AudioClient.h" @@ -1972,7 +1973,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo loadSettings(); updateVerboseLogging(); - + setCachebustRequire(); // Make sure we don't time out during slow operations at startup @@ -2158,6 +2159,32 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo return QSizeF(0.0f, 0.0f); }); + Texture::setUnboundTextureForUUIDOperator([this](const QUuid& entityID) -> gpu::TexturePointer { + if (_aboutToQuit) { + return nullptr; + } + + auto renderable = getEntities()->renderableForEntityId(entityID); + if (renderable) { + return renderable->getTexture(); + } + + return nullptr; + }); + + ReferenceMaterial::setMaterialForUUIDOperator([this](const QUuid& entityID) -> graphics::MaterialPointer { + if (_aboutToQuit) { + return nullptr; + } + + auto renderable = getEntities()->renderableForEntityId(entityID); + if (renderable) { + return renderable->getTopMaterial(); + } + + return nullptr; + }); + connect(this, &Application::aboutToQuit, [this]() { setKeyboardFocusEntity(UNKNOWN_ENTITY_ID); }); @@ -2624,7 +2651,7 @@ void Application::setCachebustRequire() { return; } bool enable = menu->isOptionChecked(MenuOption::CachebustRequire); - + Setting::Handle{ CACHEBUST_SCRIPT_REQUIRE_SETTING_NAME, false }.set(enable); } @@ -3246,7 +3273,7 @@ void Application::initializeUi() { safeURLS += settingsSafeURLS; // END PULL SAFEURLS FROM INTERFACE.JSON Settings - + if (AUTHORIZED_EXTERNAL_QML_SOURCE.isParentOf(url)) { return true; } else { @@ -4004,7 +4031,7 @@ void Application::handleSandboxStatus(QNetworkReply* reply) { parser.parse(arguments()); if (parser.isSet(urlOption)) { QUrl url = QUrl(parser.value(urlOption)); - if (url.scheme() == URL_SCHEME_HIFIAPP) { + if (url.scheme() == URL_SCHEME_VIRCADIAAPP) { Setting::Handle("startUpApp").set(url.path()); } else { addressLookupString = url.toString(); @@ -4022,7 +4049,7 @@ void Application::handleSandboxStatus(QNetworkReply* reply) { DependencyManager::get()->setHomeLocationToAddress(NetworkingConstants::DEFAULT_VIRCADIA_ADDRESS); Menu::getInstance()->triggerOption(MenuOption::HomeLocation); } - + if (!_overrideEntry) { DependencyManager::get()->goToEntry(); sentTo = SENT_TO_ENTRY; @@ -7198,7 +7225,7 @@ void Application::updateWindowTitle() const { QString buildVersion = " - Vircadia - " + (BuildInfo::BUILD_TYPE == BuildInfo::BuildType::Stable ? QString("Version") : QString("Build")) + " " + applicationVersion(); - + if (BuildInfo::RELEASE_NAME != "") { buildVersion += " - " + BuildInfo::RELEASE_NAME; } @@ -7285,7 +7312,7 @@ void Application::clearDomainOctreeDetails(bool clearAll) { void Application::domainURLChanged(QUrl domainURL) { // disable physics until we have enough information about our new location to not cause craziness. - setIsServerlessMode(domainURL.scheme() != URL_SCHEME_HIFI); + setIsServerlessMode(domainURL.scheme() != URL_SCHEME_VIRCADIA); if (isServerlessMode()) { loadServerlessDomain(domainURL); } @@ -7294,7 +7321,7 @@ void Application::domainURLChanged(QUrl domainURL) { void Application::goToErrorDomainURL(QUrl errorDomainURL) { // disable physics until we have enough information about our new location to not cause craziness. - setIsServerlessMode(errorDomainURL.scheme() != URL_SCHEME_HIFI); + setIsServerlessMode(errorDomainURL.scheme() != URL_SCHEME_VIRCADIA); if (isServerlessMode()) { loadErrorDomain(errorDomainURL); } @@ -7658,7 +7685,7 @@ bool Application::canAcceptURL(const QString& urlString) const { QUrl url(urlString); if (url.query().contains(WEB_VIEW_TAG)) { return false; - } else if (urlString.startsWith(URL_SCHEME_HIFI)) { + } else if (urlString.startsWith(URL_SCHEME_VIRCADIA)) { return true; } QString lowerPath = url.path().toLower(); @@ -7673,7 +7700,7 @@ bool Application::canAcceptURL(const QString& urlString) const { bool Application::acceptURL(const QString& urlString, bool defaultUpload) { QUrl url(urlString); - if (url.scheme() == URL_SCHEME_HIFI) { + if (url.scheme() == URL_SCHEME_VIRCADIA) { // this is a hifi URL - have the AddressManager handle it QMetaObject::invokeMethod(DependencyManager::get().data(), "handleLookupString", Qt::AutoConnection, Q_ARG(const QString&, urlString)); @@ -7901,7 +7928,7 @@ bool Application::askToReplaceDomainContent(const QString& url) { 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.vircadia.dev/host/maintain-domain/backup-domain.html"; + "\nhttps://docs.vircadia.com/host/maintain-domain/backup-domain.html"; ModalDialogListener* dig = OffscreenUi::asyncQuestion("Are you sure you want to replace this domain's content set?", infoText, QMessageBox::Yes | QMessageBox::No, QMessageBox::No); diff --git a/interface/src/CrashHandler.h b/interface/src/CrashHandler.h index 5b7e3b4438..27c5d76e1c 100644 --- a/interface/src/CrashHandler.h +++ b/interface/src/CrashHandler.h @@ -13,7 +13,10 @@ #define hifi_CrashHandler_h #include -class QCoreApplication; +#include +#include + +Q_DECLARE_LOGGING_CATEGORY(crash_handler) bool startCrashHandler(std::string appPath); void setCrashAnnotation(std::string name, std::string value); diff --git a/interface/src/CrashHandler_Crashpad.cpp b/interface/src/CrashHandler_Crashpad.cpp index a8195ce6e8..8c8ceed4b3 100644 --- a/interface/src/CrashHandler_Crashpad.cpp +++ b/interface/src/CrashHandler_Crashpad.cpp @@ -13,6 +13,8 @@ #include "CrashHandler.h" +Q_LOGGING_CATEGORY(crash_handler, "vircadia.crash_handler") + #include #include @@ -141,6 +143,10 @@ static const QString CRASHPAD_HANDLER_NAME{ "crashpad_handler.exe" }; static const QString CRASHPAD_HANDLER_NAME{ "crashpad_handler" }; #endif +#ifdef Q_OS_LINUX +#include +#endif + #ifdef Q_OS_WIN // ------------------------------------------------------------------------------------------------ // The area within this #ifdef is specific to the Microsoft C++ compiler @@ -311,8 +317,38 @@ void checkUnhandledExceptionHook() { // ------------------------------------------------------------------------------------------------ #endif // Q_OS_WIN +// Locate the full path to the binary's directory +static QString findBinaryDir() { + // Normally we'd just use QCoreApplication::applicationDirPath(), but we can't. + // That function needs the QApplication to be created first, and Crashpad is initialized as early as possible, + // which is well before QApplication, so that function throws out a warning and returns ".". + // + // So we must do things the hard way here. In particular this is needed to correctly handle things in AppImage + // on Linux. On Windows and MacOS falling back to argv[0] should be fine. + +#ifdef Q_OS_LINUX + // Find outselves by looking at /proc//exe + pid_t ourPid = getpid(); + QString exeLink = QString("/proc/%1/exe").arg(ourPid); + qCDebug(crash_handler) << "Looking at" << exeLink; + + QFileInfo exeLinkInfo(exeLink); + if (exeLinkInfo.isSymLink()) { + QFileInfo exeInfo(exeLinkInfo.symLinkTarget()); + qCDebug(crash_handler) << "exe symlink points at" << exeInfo; + return exeInfo.absoluteDir().absolutePath(); + } else { + qCWarning(crash_handler) << exeLink << "isn't a symlink. /proc not mounted?"; + } + +#endif + + return QString(); +} + bool startCrashHandler(std::string appPath) { if (BACKTRACE_URL.empty() || BACKTRACE_TOKEN.empty()) { + qCCritical(crash_handler) << "Backtrace URL or token not set, crash handler disabled."; return false; } @@ -338,11 +374,29 @@ bool startCrashHandler(std::string appPath) { const auto crashpadDbPath = crashpadDbDir.toStdString() + "/" + crashpadDbName; // Locate Crashpad handler - const QFileInfo interfaceBinary{ QString::fromStdString(appPath) }; - const QDir interfaceDir = interfaceBinary.dir(); - assert(interfaceDir.exists(CRASHPAD_HANDLER_NAME)); + QString binaryDir = findBinaryDir(); + QDir interfaceDir; + + if (!binaryDir.isEmpty()) { + // Locating ourselves by argv[0] fails in the case of AppImage on Linux, as we get the AppImage + // itself in there. If we have a platform-specific method, and it succeeds, we use that instead + // of argv. + qCDebug(crash_handler) << "Locating own directory by platform-specific method"; + interfaceDir.setPath(binaryDir); + } else { + qCDebug(crash_handler) << "Locating own directory by argv[0]"; + interfaceDir.setPath(QString::fromStdString(appPath)); + } + + if (!interfaceDir.exists(CRASHPAD_HANDLER_NAME)) { + qCCritical(crash_handler) << "Failed to find" << CRASHPAD_HANDLER_NAME << "in" << interfaceDir << ", can't start crash handler"; + return false; + } + const std::string CRASHPAD_HANDLER_PATH = interfaceDir.filePath(CRASHPAD_HANDLER_NAME).toStdString(); + qCDebug(crash_handler) << "Crashpad handler found at" << QString::fromStdString(CRASHPAD_HANDLER_PATH); + // Setup different file paths base::FilePath::StringType dbPath; base::FilePath::StringType handlerPath; @@ -352,8 +406,10 @@ bool startCrashHandler(std::string appPath) { base::FilePath db(dbPath); base::FilePath handler(handlerPath); + qCDebug(crash_handler) << "Opening crashpad database" << QString::fromStdString(crashpadDbPath); auto database = crashpad::CrashReportDatabase::Initialize(db); if (database == nullptr || database->GetSettings() == nullptr) { + qCCritical(crash_handler) << "Failed to open crashpad database" << QString::fromStdString(crashpadDbPath); return false; } @@ -361,6 +417,7 @@ bool startCrashHandler(std::string appPath) { database->GetSettings()->SetUploadsEnabled(true); if (!client->StartHandler(handler, db, db, BACKTRACE_URL, annotations, arguments, true, true)) { + qCCritical(crash_handler) << "Failed to start crashpad handler"; return false; } @@ -369,6 +426,7 @@ bool startCrashHandler(std::string appPath) { gl_crashpadUnhandledExceptionFilter = SetUnhandledExceptionFilter(unhandledExceptionHandler); #endif + qCInfo(crash_handler) << "Crashpad initialized"; return true; } diff --git a/interface/src/CrashHandler_None.cpp b/interface/src/CrashHandler_None.cpp index 4fe56cd042..2e86472705 100644 --- a/interface/src/CrashHandler_None.cpp +++ b/interface/src/CrashHandler_None.cpp @@ -17,8 +17,11 @@ #include + +Q_LOGGING_CATEGORY(crash_handler, "vircadia.crash_handler") + bool startCrashHandler(std::string appPath) { - qDebug() << "No crash handler available."; + qCWarning(crash_handler) << "No crash handler available."; return false; } diff --git a/interface/src/avatar/AvatarDoctor.cpp b/interface/src/avatar/AvatarDoctor.cpp index d84383cf4f..e3a5a68621 100644 --- a/interface/src/avatar/AvatarDoctor.cpp +++ b/interface/src/avatar/AvatarDoctor.cpp @@ -1,9 +1,9 @@ // // AvatarDoctor.cpp // -// // Created by Thijs Wenker on 2/12/2019. // Copyright 2019 High Fidelity, Inc. +// Copyright 2021 Vircadia contributors. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -55,7 +55,7 @@ static QStringList HAND_MAPPING_SUFFIXES = { "HandThumb1", }; -const QUrl PACKAGE_AVATAR_DOCS_BASE_URL = QUrl("https://docs.vircadia.dev/create/avatars/package-avatar.html"); +const QUrl PACKAGE_AVATAR_DOCS_BASE_URL = QUrl("https://docs.vircadia.com/create/avatars/package-avatar.html"); AvatarDoctor::AvatarDoctor(const QUrl& avatarFSTFileUrl) : _avatarFSTFileUrl(avatarFSTFileUrl) { @@ -71,7 +71,7 @@ void AvatarDoctor::startDiagnosing() { return; } _isDiagnosing = true; - + _errors.clear(); _externalTextureCount = 0; @@ -107,7 +107,7 @@ void AvatarDoctor::startDiagnosing() { if (avatarModel.joints.length() > NETWORKED_JOINTS_LIMIT) { addError(tr( "Avatar has over %n bones.", "", NETWORKED_JOINTS_LIMIT), "maximum-bone-limit"); } - // Avatar does not have Hips bone mapped + // Avatar does not have Hips bone mapped if (!jointNames.contains("Hips")) { addError("Hips are not mapped.", "hips-not-mapped"); } @@ -236,7 +236,7 @@ void AvatarDoctor::startDiagnosing() { for (const auto& jointVariant: jointNameMappings.values()) { jointValues << jointVariant.toString(); } - + const auto& uniqueJointValues = jointValues.toSet(); for (const auto& jointName: uniqueJointValues) { if (jointValues.count(jointName) > 1) { @@ -279,7 +279,7 @@ void AvatarDoctor::startDiagnosing() { } else { connect(materialMappingResource.data(), &NetworkTexture::finished, this, [materialMappingHandled](bool success) mutable { - + materialMappingHandled(); }); } @@ -302,7 +302,7 @@ void AvatarDoctor::startDiagnosing() { } else { addError("Model file cannot be opened", "missing-file"); emit complete(getErrors()); - } + } } void AvatarDoctor::diagnoseTextures() { diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index cd9f929a62..3fceae534f 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -4,6 +4,7 @@ // // Created by Mark Peng on 8/16/13. // Copyright 2012 High Fidelity, Inc. +// Copyright 2021 Vircadia contributors. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -47,11 +48,11 @@ class DetailedMotionState; * ValueNameDescription * * - * 0DefaultYour walking speed is constant; it doesn't change depending on how far + * 0DefaultYour walking speed is constant; it doesn't change depending on how far * forward you push your controller's joystick. Fully pushing your joystick forward makes your avatar run. - * 1AnalogYour walking speed changes in steps based on how far forward you push your + * 1AnalogYour walking speed changes in steps based on how far forward you push your * controller's joystick. Fully pushing your joystick forward makes your avatar run. - * 2AnalogPlusYour walking speed changes proportionally to how far forward you push + * 2AnalogPlusYour walking speed changes proportionally to how far forward you push * your controller's joystick. Fully pushing your joystick forward makes your avatar run. * * @@ -154,11 +155,11 @@ class MyAvatar : public Avatar { *

Note: This property will automatically be set to true if the controller system has * valid facial blend shape actions.

* @property {boolean} hasProceduralBlinkFaceMovement=true - true if avatars blink automatically by animating - * facial blend shapes, false if automatic blinking is disabled. Set to false to fully control + * facial blend shapes, false if automatic blinking is disabled. Set to false to fully control * the blink facial blend shapes via the {@link MyAvatar.setBlendshape} method. * @property {boolean} hasProceduralEyeFaceMovement=true - true if the facial blend shapes for an avatar's eyes * adjust automatically as the eyes move, false if this automatic movement is disabled. Set this property - * to true to prevent the iris from being obscured by the upper or lower lids. Set to false to + * to true to prevent the iris from being obscured by the upper or lower lids. Set to false to * fully control the eye blend shapes via the {@link MyAvatar.setBlendshape} method. * @property {boolean} hasAudioEnabledFaceMovement=true - true if the avatar's mouth blend shapes animate * automatically based on detected microphone input, false if this automatic movement is disabled. Set @@ -175,16 +176,16 @@ class MyAvatar : public Avatar { * @property {boolean} shouldRenderLocally=true - If true then your avatar is rendered for you in Interface, * otherwise it is not rendered for you (but it is still rendered for other users). * @property {Vec3} motorVelocity=Vec3.ZERO - The target velocity of your avatar to be achieved by a scripted motor. - * @property {number} motorTimescale=1000000 - The timescale for the scripted motor to achieve the target + * @property {number} motorTimescale=1000000 - The timescale for the scripted motor to achieve the target * motorVelocity avatar velocity. Smaller values result in higher acceleration. - * @property {string} motorReferenceFrame="camera" - Reference frame of the motorVelocity. Must be one of the + * @property {string} motorReferenceFrame="camera" - Reference frame of the motorVelocity. Must be one of the * following: "camera", "avatar", and "world". - * @property {string} motorMode="simple" - The Type of scripted motor behavior: "simple" to use the + * @property {string} motorMode="simple" - The Type of scripted motor behavior: "simple" to use the * motorTimescale time scale; "dynamic" to use character controller timescales. - * @property {string} collisionSoundURL="Body_Hits_Impact.wav" - The sound that's played when the avatar experiences a - * collision. It can be a mono or stereo 16-bit WAV file running at either 24kHz or 48kHz. The latter is down-sampled + * @property {string} collisionSoundURL="Body_Hits_Impact.wav" - The sound that's played when the avatar experiences a + * collision. It can be a mono or stereo 16-bit WAV file running at either 24kHz or 48kHz. The latter is down-sampled * by the audio mixer, so all audio effectively plays back at a 24khz. 48kHz RAW files are also supported. - * @property {number} audioListenerMode=0 - Specifies the listening position when hearing spatialized audio. Must be one + * @property {number} audioListenerMode=0 - Specifies the listening position when hearing spatialized audio. Must be one * of the following property values: *
    *
  • MyAvatar.audioListenerModeHead
  • @@ -193,93 +194,93 @@ class MyAvatar : public Avatar { *
* @property {number} audioListenerModeHead=0 - The audio listening position is at the avatar's head. Read-only. * @property {number} audioListenerModeCamera=1 - The audio listening position is at the camera. Read-only. - * @property {number} audioListenerModeCustom=2 - The audio listening position is at a the position specified by set by the + * @property {number} audioListenerModeCustom=2 - The audio listening position is at a the position specified by set by the * customListenPosition and customListenOrientation property values. Read-only. * @property {Vec3} customListenPosition=Vec3.ZERO - The listening position used when the audioListenerMode * property value is audioListenerModeCustom. * @property {Quat} customListenOrientation=Quat.IDENTITY - The listening orientation used when the * audioListenerMode property value is audioListenerModeCustom. - * @property {number} rotationRecenterFilterLength - Configures how quickly the avatar root rotates to recenter its facing - * direction to match that of the user's torso based on head and hands orientation. A smaller value makes the + * @property {number} rotationRecenterFilterLength - Configures how quickly the avatar root rotates to recenter its facing + * direction to match that of the user's torso based on head and hands orientation. A smaller value makes the * recentering happen more quickly. The minimum value is 0.01. - * @property {number} rotationThreshold - The angle in radians that the user's torso facing direction (based on head and + * @property {number} rotationThreshold - The angle in radians that the user's torso facing direction (based on head and * hands orientation) can differ from that of the avatar before the avatar's root is rotated to match the user's torso. - * @property {boolean} enableStepResetRotation - If true then after the user's avatar takes a step, the - * avatar's root immediately rotates to recenter its facing direction to match that of the user's torso based on head + * @property {boolean} enableStepResetRotation - If true then after the user's avatar takes a step, the + * avatar's root immediately rotates to recenter its facing direction to match that of the user's torso based on head * and hands orientation. - * @property {boolean} enableDrawAverageFacing - If true, debug graphics are drawn that show the average - * facing direction of the user's torso (based on head and hands orientation). This can be useful if you want to try + * @property {boolean} enableDrawAverageFacing - If true, debug graphics are drawn that show the average + * facing direction of the user's torso (based on head and hands orientation). This can be useful if you want to try * out different filter lengths and thresholds. * - * @property {Vec3} leftHandPosition - The position of the left hand in avatar coordinates if it's being positioned by + * @property {Vec3} leftHandPosition - The position of the left hand in avatar coordinates if it's being positioned by * controllers, otherwise {@link Vec3(0)|Vec3.ZERO}. Read-only. * @property {Vec3} rightHandPosition - The position of the right hand in avatar coordinates if it's being positioned by * controllers, otherwise {@link Vec3(0)|Vec3.ZERO}. Read-only. - * @property {Vec3} leftHandTipPosition - The position 0.3m in front of the left hand's position, in the direction along the - * palm, in avatar coordinates. If the hand isn't being positioned by a controller, the value is + * @property {Vec3} leftHandTipPosition - The position 0.3m in front of the left hand's position, in the direction along the + * palm, in avatar coordinates. If the hand isn't being positioned by a controller, the value is * {@link Vec3(0)|Vec3.ZERO}. Read-only. - * @property {Vec3} rightHandTipPosition - The position 0.3m in front of the right hand's position, in the direction along - * the palm, in avatar coordinates. If the hand isn't being positioned by a controller, the value is + * @property {Vec3} rightHandTipPosition - The position 0.3m in front of the right hand's position, in the direction along + * the palm, in avatar coordinates. If the hand isn't being positioned by a controller, the value is * {@link Vec3(0)|Vec3.ZERO}. Read-only. * - * @property {Pose} leftHandPose - The left hand's pose as determined by the hand controllers, relative to the avatar. + * @property {Pose} leftHandPose - The left hand's pose as determined by the hand controllers, relative to the avatar. * Read-only. * @property {Pose} rightHandPose - The right hand's pose as determined by the hand controllers, relative to the avatar. * Read-only. - * @property {Pose} leftHandTipPose - The left hand's pose as determined by the hand controllers, relative to the avatar, + * @property {Pose} leftHandTipPose - The left hand's pose as determined by the hand controllers, relative to the avatar, * with the position adjusted by 0.3m along the direction of the palm. Read-only. - * @property {Pose} rightHandTipPose - The right hand's pose as determined by the hand controllers, relative to the avatar, + * @property {Pose} rightHandTipPose - The right hand's pose as determined by the hand controllers, relative to the avatar, * with the position adjusted by 0.3m along the direction of the palm. Read-only. * * @property {number} energy - Deprecated: This property will be removed. - * @property {boolean} isAway - true if your avatar is away (i.e., inactive), false if it is + * @property {boolean} isAway - true if your avatar is away (i.e., inactive), false if it is * active. * * @property {boolean} centerOfGravityModelEnabled=true - true if the avatar hips are placed according to * the center of gravity model that balances the center of gravity over the base of support of the feet. Set the * value to false for default behavior where the hips are positioned under the head. - * @property {boolean} hmdLeanRecenterEnabled=true - true IF the avatar is re-centered to be under the - * head's position. In room-scale VR, this behavior is what causes your avatar to follow your HMD as you walk around + * @property {boolean} hmdLeanRecenterEnabled=true - true IF the avatar is re-centered to be under the + * head's position. In room-scale VR, this behavior is what causes your avatar to follow your HMD as you walk around * the room. Setting the value false is useful if you want to pin the avatar to a fixed position. - * @property {boolean} collisionsEnabled - Set to true to enable the avatar to collide with the environment, - * false to disable collisions with the environment. May return true even though the value + * @property {boolean} collisionsEnabled - Set to true to enable the avatar to collide with the environment, + * false to disable collisions with the environment. May return true even though the value * was set false because the zone may disallow collisionless avatars. - * @property {boolean} otherAvatarsCollisionsEnabled - Set to true to enable the avatar to collide with other + * @property {boolean} otherAvatarsCollisionsEnabled - Set to true to enable the avatar to collide with other * avatars, false to disable collisions with other avatars. * @property {boolean} characterControllerEnabled - Synonym of collisionsEnabled. - *

Deprecated: This property is deprecated and will be removed. Use collisionsEnabled + *

Deprecated: This property is deprecated and will be removed. Use collisionsEnabled * instead.

- * @property {boolean} useAdvancedMovementControls - Returns and sets the value of the Interface setting, Settings > + * @property {boolean} useAdvancedMovementControls - Returns and sets the value of the Interface setting, Settings > * Controls > Walking. Note: Setting the value has no effect unless Interface is restarted. - * @property {boolean} showPlayArea - Returns and sets the value of the Interface setting, Settings > Controls > Show room + * @property {boolean} showPlayArea - Returns and sets the value of the Interface setting, Settings > Controls > Show room * boundaries while teleporting. *

Note: Setting the value has no effect unless Interface is restarted.

* * @property {number} yawSpeed=75 - The mouse X sensitivity value in Settings > General. Read-only. * @property {number} pitchSpeed=50 - The mouse Y sensitivity value in Settings > General. Read-only. * - * @property {boolean} hmdRollControlEnabled=true - If true, the roll angle of your HMD turns your avatar + * @property {boolean} hmdRollControlEnabled=true - If true, the roll angle of your HMD turns your avatar * while flying. - * @property {number} hmdRollControlDeadZone=8 - The amount of HMD roll, in degrees, required before your avatar turns if + * @property {number} hmdRollControlDeadZone=8 - The amount of HMD roll, in degrees, required before your avatar turns if * hmdRollControlEnabled is enabled. - * @property {number} hmdRollControlRate If MyAvatar.hmdRollControlEnabled is true, this value determines the + * @property {number} hmdRollControlRate If MyAvatar.hmdRollControlEnabled is true, this value determines the * maximum turn rate of your avatar when rolling your HMD in degrees per second. * * @property {number} userHeight=1.75 - The height of the user in sensor space. * @property {number} userEyeHeight=1.65 - The estimated height of the user's eyes in sensor space. Read-only. * - * @property {Uuid} SELF_ID - UUID representing "my avatar". Only use for local-only entities in situations - * where MyAvatar.sessionUUID is not available (e.g., if not connected to a domain). Note: Likely to be deprecated. + * @property {Uuid} SELF_ID - UUID representing "my avatar". Only use for local-only entities in situations + * where MyAvatar.sessionUUID is not available (e.g., if not connected to a domain). Note: Likely to be deprecated. * Read-only. * - * @property {number} walkSpeed - The walk speed of your avatar for the current control scheme (see + * @property {number} walkSpeed - The walk speed of your avatar for the current control scheme (see * {@link MyAvatar.getControlScheme|getControlScheme}). - * @property {number} walkBackwardSpeed - The walk backward speed of your avatar for the current control scheme (see + * @property {number} walkBackwardSpeed - The walk backward speed of your avatar for the current control scheme (see * {@link MyAvatar.getControlScheme|getControlScheme}). - * @property {number} sprintSpeed - The sprint (run) speed of your avatar for the current control scheme (see + * @property {number} sprintSpeed - The sprint (run) speed of your avatar for the current control scheme (see * {@link MyAvatar.getControlScheme|getControlScheme}). * @property {number} analogPlusWalkSpeed - The walk speed of your avatar for the "AnalogPlus" control scheme. - *

Warning: Setting this value also sets the value of analogPlusSprintSpeed to twice + *

Warning: Setting this value also sets the value of analogPlusSprintSpeed to twice * the value.

* @property {number} analogPlusSprintSpeed - The sprint (run) speed of your avatar for the "AnalogPlus" control scheme. * @property {MyAvatar.SitStandModelType} userRecenterModel - Controls avatar leaning and recentering behavior. @@ -289,11 +290,11 @@ class MyAvatar : public Avatar { * is allowed to stand, lean or recenter its footing, depending on user preferences. * The property value automatically updates as the user sits or stands. Setting the property value overrides the current * sitting / standing state, which is updated when the user next sits or stands. - * @property {boolean} isSitStandStateLocked - true to lock the avatar sitting/standing state, i.e., use this + * @property {boolean} isSitStandStateLocked - true to lock the avatar sitting/standing state, i.e., use this * to disable automatically changing state. - *

Deprecated: This property is deprecated and will be removed. + *

Deprecated: This property is deprecated and will be removed. * See also: getUserRecenterModel and setUserRecenterModel.

- * @property {boolean} allowTeleporting - true if teleporting is enabled in the Interface settings, + * @property {boolean} allowTeleporting - true if teleporting is enabled in the Interface settings, * false if it isn't. Read-only. * * @borrows Avatar.getDomainMinScale as getDomainMinScale @@ -435,7 +436,7 @@ class MyAvatar : public Avatar { public: /*@jsdoc - * The DriveKeys API provides constant numeric values that represent different logical keys that drive your + * The DriveKeys API provides constant numeric values that represent different logical keys that drive your * avatar and camera. * * @namespace DriveKeys @@ -444,27 +445,27 @@ public: * @hifi-client-entity * @hifi-avatar * - * @property {number} TRANSLATE_X - Move the user's avatar in the direction of its x-axis, if the camera isn't in + * @property {number} TRANSLATE_X - Move the user's avatar in the direction of its x-axis, if the camera isn't in * independent or mirror modes. - * @property {number} TRANSLATE_Y - Move the user's avatar in the direction of its y-axis, if the camera isn't in + * @property {number} TRANSLATE_Y - Move the user's avatar in the direction of its y-axis, if the camera isn't in * independent or mirror modes. - * @property {number} TRANSLATE_Z - Move the user's avatar in the direction of its z-axis, if the camera isn't in + * @property {number} TRANSLATE_Z - Move the user's avatar in the direction of its z-axis, if the camera isn't in * independent or mirror modes. - * @property {number} YAW - Rotate the user's avatar about its y-axis at a rate proportional to the control value, if the + * @property {number} YAW - Rotate the user's avatar about its y-axis at a rate proportional to the control value, if the * camera isn't in independent or mirror modes. * @property {number} STEP_TRANSLATE_X - No action. * @property {number} STEP_TRANSLATE_Y - No action. * @property {number} STEP_TRANSLATE_Z - No action. - * @property {number} STEP_YAW - Rotate the user's avatar about its y-axis in a step increment, if the camera isn't in + * @property {number} STEP_YAW - Rotate the user's avatar about its y-axis in a step increment, if the camera isn't in * independent or mirror modes. - * @property {number} PITCH - Rotate the user's avatar head and attached camera about its negative x-axis (i.e., positive - * values pitch down) at a rate proportional to the control value, if the camera isn't in HMD, independent, or mirror + * @property {number} PITCH - Rotate the user's avatar head and attached camera about its negative x-axis (i.e., positive + * values pitch down) at a rate proportional to the control value, if the camera isn't in HMD, independent, or mirror * modes. * @property {number} ZOOM - Zoom the camera in or out. - * @property {number} DELTA_YAW - Rotate the user's avatar about its y-axis by an amount proportional to the control value, + * @property {number} DELTA_YAW - Rotate the user's avatar about its y-axis by an amount proportional to the control value, * if the camera isn't in independent or mirror modes. - * @property {number} DELTA_PITCH - Rotate the user's avatar head and attached camera about its negative x-axis (i.e., - * positive values pitch down) by an amount proportional to the control value, if the camera isn't in HMD, independent, + * @property {number} DELTA_PITCH - Rotate the user's avatar head and attached camera about its negative x-axis (i.e., + * positive values pitch down) by an amount proportional to the control value, if the camera isn't in HMD, independent, * or mirror modes. */ @@ -475,27 +476,27 @@ public: * ValueDescription * * - * {@link DriveKeys|DriveKeys.TRANSLATE_X}Move the user's avatar in the direction of its + * {@link DriveKeys|DriveKeys.TRANSLATE_X}Move the user's avatar in the direction of its * x-axis, if the camera isn't in independent or mirror modes. - * {@link DriveKeys|DriveKeys.TRANSLATE_Y}Move the user's avatar in the direction of its + * {@link DriveKeys|DriveKeys.TRANSLATE_Y}Move the user's avatar in the direction of its * -axis, if the camera isn't in independent or mirror modes. - * {@link DriveKeys|DriveKeys.TRANSLATE_Z}Move the user's avatar in the direction of its + * {@link DriveKeys|DriveKeys.TRANSLATE_Z}Move the user's avatar in the direction of its * z-axis, if the camera isn't in independent or mirror modes. - * {@link DriveKeys|DriveKeys.YAW}Rotate the user's avatar about its y-axis at a rate + * {@link DriveKeys|DriveKeys.YAW}Rotate the user's avatar about its y-axis at a rate * proportional to the control value, if the camera isn't in independent or mirror modes. * {@link DriveKeys|DriveKeys.STEP_TRANSLATE_X}No action. * {@link DriveKeys|DriveKeys.STEP_TRANSLATE_Y}No action. * {@link DriveKeys|DriveKeys.STEP_TRANSLATE_Z}No action. - * {@link DriveKeys|DriveKeys.STEP_YAW}Rotate the user's avatar about its y-axis in a + * {@link DriveKeys|DriveKeys.STEP_YAW}Rotate the user's avatar about its y-axis in a * step increment, if the camera isn't in independent or mirror modes. - * {@link DriveKeys|DriveKeys.PITCH}Rotate the user's avatar head and attached camera - * about its negative x-axis (i.e., positive values pitch down) at a rate proportional to the control value, if the + * {@link DriveKeys|DriveKeys.PITCH}Rotate the user's avatar head and attached camera + * about its negative x-axis (i.e., positive values pitch down) at a rate proportional to the control value, if the * camera isn't in HMD, independent, or mirror modes. * {@link DriveKeys|DriveKeys.ZOOM}Zoom the camera in or out. - * {@link DriveKeys|DriveKeys.DELTA_YAW}Rotate the user's avatar about its y-axis by an + * {@link DriveKeys|DriveKeys.DELTA_YAW}Rotate the user's avatar about its y-axis by an * amount proportional to the control value, if the camera isn't in independent or mirror modes. - * {@link DriveKeys|DriveKeys.DELTA_PITCH}Rotate the user's avatar head and attached - * camera about its negative x-axis (i.e., positive values pitch down) by an amount proportional to the control + * {@link DriveKeys|DriveKeys.DELTA_PITCH}Rotate the user's avatar head and attached + * camera about its negative x-axis (i.e., positive values pitch down) by an amount proportional to the control * value, if the camera isn't in HMD, independent, or mirror modes. * * @@ -526,16 +527,16 @@ public: * ValueNameDescription * * - * 0ForceSitAssumes the user is seated in the real world. Disables avatar + * 0ForceSitAssumes the user is seated in the real world. Disables avatar * leaning regardless of what the avatar is doing in the virtual world (i.e., avatar always recenters). - * 1ForceStandAssumes the user is standing in the real world. Enables avatar - * leaning regardless of what the avatar is doing in the virtual world (i.e., avatar leans, then if leans too far it + * 1ForceStandAssumes the user is standing in the real world. Enables avatar + * leaning regardless of what the avatar is doing in the virtual world (i.e., avatar leans, then if leans too far it * recenters). - * 2AutoInterface detects when the user is standing or seated in the real world. - * Avatar leaning is disabled when the user is sitting (i.e., avatar always recenters), and avatar leaning is enabled + * 2AutoInterface detects when the user is standing or seated in the real world. + * Avatar leaning is disabled when the user is sitting (i.e., avatar always recenters), and avatar leaning is enabled * when the user is standing (i.e., avatar leans, then if leans too far it recenters). - * 3DisableHMDLean

Both avatar leaning and recentering are disabled regardless of - * what the user is doing in the real world and no matter what their avatar is doing in the virtual world. Enables + * 3DisableHMDLean

Both avatar leaning and recentering are disabled regardless of + * what the user is doing in the real world and no matter what their avatar is doing in the virtual world. Enables * the avatar to sit on the floor when the user sits on the floor.

*

Note: Experimental.

* @@ -597,7 +598,7 @@ public: Q_INVOKABLE void resetSensorsAndBody(); /*@jsdoc - * Moves and orients the avatar, such that it is directly underneath the HMD, with toes pointed forward in the direction of + * Moves and orients the avatar, such that it is directly underneath the HMD, with toes pointed forward in the direction of * the HMD. * @function MyAvatar.centerBody */ @@ -606,7 +607,7 @@ public: /*@jsdoc * Clears inverse kinematics joint limit history. - *

The internal inverse-kinematics system maintains a record of which joints are "locked". Sometimes it is useful to + *

The internal inverse-kinematics system maintains a record of which joints are "locked". Sometimes it is useful to * forget this history to prevent contorted joints, e.g., after finishing with an override animation.

* @function MyAvatar.clearIKJointLimitHistory */ @@ -657,7 +658,7 @@ public: /*@jsdoc * Gets the position in world coordinates of the point directly between your avatar's eyes assuming your avatar was in its - * default pose. This is a reference position; it does not change as your avatar's head moves relative to the avatar + * default pose. This is a reference position; it does not change as your avatar's head moves relative to the avatar * position. * @function MyAvatar.getDefaultEyePosition * @returns {Vec3} Default position between your avatar's eyes in world coordinates. @@ -672,17 +673,17 @@ public: /*@jsdoc * Overrides the default avatar animations. *

The avatar animation system includes a set of default animations along with rules for how those animations are blended - * together with procedural data (such as look at vectors, hand sensors etc.). overrideAnimation() is used to - * completely override all motion from the default animation system (including inverse kinematics for hand and head - * controllers) and play a set of specified animations. To end these animations and restore the default animations, use + * together with procedural data (such as look at vectors, hand sensors etc.). overrideAnimation() is used to + * completely override all motion from the default animation system (including inverse kinematics for hand and head + * controllers) and play a set of specified animations. To end these animations and restore the default animations, use * {@link MyAvatar.restoreAnimation}.

- *

Note: When using pre-built animation data, it's critical that the joint orientation of the source animation and target - * rig are equivalent, since the animation data applies absolute values onto the joints. If the orientations are different, - * the avatar will move in unpredictable ways. For more information about avatar joint orientation standards, see - * Avatar Standards.

+ *

Note: When using pre-built animation data, it's critical that the joint orientation of the source animation and target + * rig are equivalent, since the animation data applies absolute values onto the joints. If the orientations are different, + * the avatar will move in unpredictable ways. For more information about avatar joint orientation standards, see + * Avatar Standards.

* @function MyAvatar.overrideAnimation - * @param {string} url - The URL to the animation file. Animation files may be in glTF or FBX format, but only need to - * contain the avatar skeleton and animation data. glTF models may be in JSON or binary format (".gltf" or ".glb" URLs + * @param {string} url - The URL to the animation file. Animation files may be in glTF or FBX format, but only need to + * contain the avatar skeleton and animation data. glTF models may be in JSON or binary format (".gltf" or ".glb" URLs * respectively). *

Warning: glTF animations currently do not always animate correctly.

* @param {number} fps - The frames per second (FPS) rate for the animation playback. 30 FPS is normal speed. @@ -704,8 +705,8 @@ public: * Use {@link MyAvatar.restoreHandAnimation} to restore the default poses. * @function MyAvatar.overrideHandAnimation * @param isLeft {boolean} true to override the left hand, false to override the right hand. - * @param {string} url - The URL of the animation file. Animation files need to be in glTF or FBX format, but only need to - * contain the avatar skeleton and animation data. glTF models may be in JSON or binary format (".gltf" or ".glb" URLs + * @param {string} url - The URL of the animation file. Animation files need to be in glTF or FBX format, but only need to + * contain the avatar skeleton and animation data. glTF models may be in JSON or binary format (".gltf" or ".glb" URLs * respectively). *

Warning: glTF animations currently do not always animate correctly.

* @param {number} fps - The frames per second (FPS) rate for the animation playback. 30 FPS is normal speed. @@ -723,10 +724,10 @@ public: /*@jsdoc * Restores the default animations. - *

The avatar animation system includes a set of default animations along with rules for how those animations are blended - * together with procedural data (such as look at vectors, hand sensors etc.). Playing your own custom animations will - * override the default animations. restoreAnimation() is used to restore all motion from the default - * animation system including inverse kinematics for hand and head controllers. If you aren't currently playing an override + *

The avatar animation system includes a set of default animations along with rules for how those animations are blended + * together with procedural data (such as look at vectors, hand sensors etc.). Playing your own custom animations will + * override the default animations. restoreAnimation() is used to restore all motion from the default + * animation system including inverse kinematics for hand and head controllers. If you aren't currently playing an override * animation, this function has no effect.

* @function MyAvatar.restoreAnimation * @example Play a clapping animation on your avatar for three seconds. @@ -757,10 +758,10 @@ public: /*@jsdoc * Gets the current animation roles. - *

Each avatar has an avatar-animation.json file that defines which animations are used and how they are blended together - * with procedural data (such as look at vectors, hand sensors etc.). Each animation specified in the avatar-animation.json - * file is known as an animation role. Animation roles map to easily understandable actions that the avatar can perform, - * such as "idleStand", "idleTalk", or "walkFwd". getAnimationRoles() + *

Each avatar has an avatar-animation.json file that defines which animations are used and how they are blended together + * with procedural data (such as look at vectors, hand sensors etc.). Each animation specified in the avatar-animation.json + * file is known as an animation role. Animation roles map to easily understandable actions that the avatar can perform, + * such as "idleStand", "idleTalk", or "walkFwd". getAnimationRoles() * is used get the list of animation roles defined in the avatar-animation.json.

* @function MyAvatar.getAnimationRoles * @returns {string[]} Array of role strings. @@ -775,23 +776,23 @@ public: /*@jsdoc * Overrides a specific animation role. - *

Each avatar has an avatar-animation.json file that defines a set of animation roles. Animation roles map to easily - * understandable actions that the avatar can perform, such as "idleStand", "idleTalk", or + *

Each avatar has an avatar-animation.json file that defines a set of animation roles. Animation roles map to easily + * understandable actions that the avatar can perform, such as "idleStand", "idleTalk", or * "walkFwd". To get the full list of roles, use {@ link MyAvatar.getAnimationRoles}. - * For each role, the avatar-animation.json defines when the animation is used, the animation clip (glTF or FBX) used, and + * For each role, the avatar-animation.json defines when the animation is used, the animation clip (glTF or FBX) used, and * how animations are blended together with procedural data (such as look at vectors, hand sensors etc.). - * overrideRoleAnimation() is used to change the animation clip (glTF or FBX) associated with a specified + * overrideRoleAnimation() is used to change the animation clip (glTF or FBX) associated with a specified * animation role. To end the role animation and restore the default, use {@link MyAvatar.restoreRoleAnimation}.

- *

Note: Hand roles only affect the hand. Other "main" roles, like "idleStand", "idleTalk", and "takeoffStand", are full + *

Note: Hand roles only affect the hand. Other "main" roles, like "idleStand", "idleTalk", and "takeoffStand", are full * body.

*

Note: When using pre-built animation data, it's critical that the joint orientation of the source animation and target * rig are equivalent, since the animation data applies absolute values onto the joints. If the orientations are different, - * the avatar will move in unpredictable ways. For more information about avatar joint orientation standards, see - * Avatar Standards. + * the avatar will move in unpredictable ways. For more information about avatar joint orientation standards, see + * Avatar Standards. * @function MyAvatar.overrideRoleAnimation * @param {string} role - The animation role to override - * @param {string} url - The URL to the animation file. Animation files need to be in glTF or FBX format, but only need to - * contain the avatar skeleton and animation data. glTF models may be in JSON or binary format (".gltf" or ".glb" URLs + * @param {string} url - The URL to the animation file. Animation files need to be in glTF or FBX format, but only need to + * contain the avatar skeleton and animation data. glTF models may be in JSON or binary format (".gltf" or ".glb" URLs * respectively). *

Warning: glTF animations currently do not always animate correctly.

* @param {number} fps - The frames per second (FPS) rate for the animation playback. 30 FPS is normal speed. @@ -815,13 +816,13 @@ public: /*@jsdoc * Restores a default role animation. - *

Each avatar has an avatar-animation.json file that defines a set of animation roles. Animation roles map to easily - * understandable actions that the avatar can perform, such as "idleStand", "idleTalk", or + *

Each avatar has an avatar-animation.json file that defines a set of animation roles. Animation roles map to easily + * understandable actions that the avatar can perform, such as "idleStand", "idleTalk", or * "walkFwd". To get the full list of roles, use {@link MyAvatar.getAnimationRoles}. For each role, - * the avatar-animation.json defines when the animation is used, the animation clip (glTF or FBX) used, and how animations - * are blended together with procedural data (such as look-at vectors, hand sensors etc.). You can change the animation + * the avatar-animation.json defines when the animation is used, the animation clip (glTF or FBX) used, and how animations + * are blended together with procedural data (such as look-at vectors, hand sensors etc.). You can change the animation * clip (glTF or FBX) associated with a specified animation role using {@link MyAvatar.overrideRoleAnimation}. - * restoreRoleAnimation() is used to restore a specified animation role's default animation clip. If you have + * restoreRoleAnimation() is used to restore a specified animation role's default animation clip. If you have * not specified an override animation for the specified role, this function has no effect. * @function MyAvatar.restoreRoleAnimation * @param role {string} The animation role clip to restore. @@ -838,31 +839,31 @@ public: // a handler must not remove properties from animStateDictionaryIn, nor change property values that it does not intend to change. // It is not specified in what order multiple handlers are called. /*@jsdoc - * Adds an animation state handler function that is invoked just before each animation graph update. More than one - * animation state handler function may be added by calling addAnimationStateHandler multiple times. It is not + * Adds an animation state handler function that is invoked just before each animation graph update. More than one + * animation state handler function may be added by calling addAnimationStateHandler multiple times. It is not * specified in what order multiple handlers are called. *

The animation state handler function is called with an {@link MyAvatar.AnimStateDictionary|AnimStateDictionary} - * "animStateDictionaryIn" parameter and is expected to return an - * {@link MyAvatar.AnimStateDictionary|AnimStateDictionary} "animStateDictionaryOut" object. The - * animStateDictionaryOut object can be the same object as animStateDictionaryIn, or it can be a - * different object. The animStateDictionaryIn may be shared among multiple handlers and thus may contain + * "animStateDictionaryIn" parameter and is expected to return an + * {@link MyAvatar.AnimStateDictionary|AnimStateDictionary} "animStateDictionaryOut" object. The + * animStateDictionaryOut object can be the same object as animStateDictionaryIn, or it can be a + * different object. The animStateDictionaryIn may be shared among multiple handlers and thus may contain * additional properties specified when adding the different handlers.

- *

A handler may change a value from animStateDictionaryIn or add different values in the - * animStateDictionaryOut returned. Any property values set in animStateDictionaryOut will + *

A handler may change a value from animStateDictionaryIn or add different values in the + * animStateDictionaryOut returned. Any property values set in animStateDictionaryOut will * override those of the internal animation machinery.

* @function MyAvatar.addAnimationStateHandler * @param {function} handler - The animation state handler function to add. - * @param {Array|null} propertiesList - The list of {@link MyAvatar.AnimStateDictionary|AnimStateDictionary} - * properties that should be included in the parameter that the handler function is called with. If null + * @param {Array|null} propertiesList - The list of {@link MyAvatar.AnimStateDictionary|AnimStateDictionary} + * properties that should be included in the parameter that the handler function is called with. If null * then all properties are included in the call parameter. * @returns {number} The ID of the animation state handler function if successfully added, undefined if not. * @example Log all the animation state dictionary parameters for a short while. * function animStateHandler(dictionary) { * print("Anim state dictionary: " + JSON.stringify(dictionary)); * } - * + * * var handler = MyAvatar.addAnimationStateHandler(animStateHandler, null); - * + * * Script.setTimeout(function () { * MyAvatar.removeAnimationStateHandler(handler); * }, 100); @@ -881,7 +882,7 @@ public: /*@jsdoc * Gets whether you do snap turns in HMD mode. * @function MyAvatar.getSnapTurn - * @returns {boolean} true if you do snap turns in HMD mode; false if you do smooth turns in HMD + * @returns {boolean} true if you do snap turns in HMD mode; false if you do smooth turns in HMD * mode. */ Q_INVOKABLE bool getSnapTurn() const { return _useSnapTurn; } @@ -906,11 +907,11 @@ public: * @param {MyAvatar.LocomotionControlsMode} controlScheme - The control scheme to use. */ Q_INVOKABLE void setControlScheme(int index) { _controlSchemeIndex = (index >= 0 && index <= 2) ? index : 0; } - + /*@jsdoc * Gets whether your avatar hovers when its feet are not on the ground. * @function MyAvatar.hoverWhenUnsupported - * @returns {boolean} true if your avatar hovers when its feet are not on the ground, false if it + * @returns {boolean} true if your avatar hovers when its feet are not on the ground, false if it * falls. */ // FIXME: Should be named, getHoverWhenUnsupported(). @@ -919,7 +920,7 @@ public: /*@jsdoc * Sets whether your avatar hovers when its feet are not on the ground. * @function MyAvatar.setHoverWhenUnsupported - * @param {boolean} hover - true if your avatar hovers when its feet are not on the ground, false + * @param {boolean} hover - true if your avatar hovers when its feet are not on the ground, false * if it falls. */ Q_INVOKABLE void setHoverWhenUnsupported(bool on) { _hoverWhenUnsupported = on; } @@ -927,7 +928,7 @@ public: /*@jsdoc * Sets the avatar's dominant hand. * @function MyAvatar.setDominantHand - * @param {string} hand - The dominant hand: "left" for the left hand or "right" for the right + * @param {string} hand - The dominant hand: "left" for the left hand or "right" for the right * hand. Any other value has no effect. */ Q_INVOKABLE void setDominantHand(const QString& hand); @@ -956,7 +957,7 @@ public: /*@jsdoc * Sets the HMD alignment relative to your avatar. * @function MyAvatar.setHmdAvatarAlignmentType - * @param {string} type - "head" to align your head and your avatar's head, "eyes" to align your + * @param {string} type - "head" to align your head and your avatar's head, "eyes" to align your * eyes and your avatar's eyes. */ Q_INVOKABLE void setHmdAvatarAlignmentType(const QString& type); @@ -964,7 +965,7 @@ public: /*@jsdoc * Gets the HMD alignment relative to your avatar. * @function MyAvatar.getHmdAvatarAlignmentType - * @returns {string} "head" if aligning your head and your avatar's head, "eyes" if aligning your + * @returns {string} "head" if aligning your head and your avatar's head, "eyes" if aligning your * eyes and your avatar's eyes. */ Q_INVOKABLE QString getHmdAvatarAlignmentType() const; @@ -972,7 +973,7 @@ public: /*@jsdoc * Sets whether the avatar's hips are balanced over the feet or positioned under the head. * @function MyAvatar.setCenterOfGravityModelEnabled - * @param {boolean} enabled - true to balance the hips over the feet, false to position the hips + * @param {boolean} enabled - true to balance the hips over the feet, false to position the hips * under the head. */ Q_INVOKABLE void setCenterOfGravityModelEnabled(bool value) { _centerOfGravityModelEnabled = value; } @@ -980,17 +981,17 @@ public: /*@jsdoc * Gets whether the avatar hips are being balanced over the feet or placed under the head. * @function MyAvatar.getCenterOfGravityModelEnabled - * @returns {boolean} true if the hips are being balanced over the feet, false if the hips are + * @returns {boolean} true if the hips are being balanced over the feet, false if the hips are * being positioned under the head. */ Q_INVOKABLE bool getCenterOfGravityModelEnabled() const { return _centerOfGravityModelEnabled; } /*@jsdoc - * Sets whether the avatar's position updates to recenter the avatar under the head. In room-scale VR, recentering - * causes your avatar to follow your HMD as you walk around the room. Disabling recentering is useful if you want to pin + * Sets whether the avatar's position updates to recenter the avatar under the head. In room-scale VR, recentering + * causes your avatar to follow your HMD as you walk around the room. Disabling recentering is useful if you want to pin * the avatar to a fixed position. * @function MyAvatar.setHMDLeanRecenterEnabled - * @param {boolean} enabled - true to recenter the avatar under the head as it moves, false to + * @param {boolean} enabled - true to recenter the avatar under the head as it moves, false to * disable recentering. */ Q_INVOKABLE void setHMDLeanRecenterEnabled(bool value) { _hmdLeanRecenterEnabled = value; } @@ -1004,9 +1005,9 @@ public: Q_INVOKABLE bool getHMDLeanRecenterEnabled() const { return _hmdLeanRecenterEnabled; } /*@jsdoc - * Requests that the hand touch effect is disabled for your avatar. Any resulting change in the status of the hand touch + * Requests that the hand touch effect is disabled for your avatar. Any resulting change in the status of the hand touch * effect will be signaled by {@link MyAvatar.shouldDisableHandTouchChanged}. - *

The hand touch effect makes the avatar's fingers adapt to the shape of any object grabbed, creating the effect that + *

The hand touch effect makes the avatar's fingers adapt to the shape of any object grabbed, creating the effect that * it is really touching that object.

* @function MyAvatar.requestEnableHandTouch */ @@ -1081,7 +1082,7 @@ public: Q_INVOKABLE float getRawDriveKey(DriveKeys key) const; void relayDriveKeysToCharacterController(); - + /*@jsdoc * Disables the action associated with a drive key. * @function MyAvatar.disableDriveKey @@ -1097,7 +1098,7 @@ public: Q_INVOKABLE void disableDriveKey(DriveKeys key); /*@jsdoc - * Enables the action associated with a drive key. The action may have been disabled with + * Enables the action associated with a drive key. The action may have been disabled with * {@link MyAvatar.disableDriveKey|disableDriveKey}. * @function MyAvatar.enableDriveKey * @param {DriveKey} key - The drive key to enable. @@ -1114,14 +1115,14 @@ public: /*@jsdoc - * Recenter the avatar in the vertical direction, if {@link MyAvatar|MyAvatar.hmdLeanRecenterEnabled} is + * Recenter the avatar in the vertical direction, if {@link MyAvatar|MyAvatar.hmdLeanRecenterEnabled} is * false. * @function MyAvatar.triggerVerticalRecenter */ Q_INVOKABLE void triggerVerticalRecenter(); /*@jsdoc - * Recenter the avatar in the horizontal direction, if {@link MyAvatar|MyAvatar.hmdLeanRecenterEnabled} is + * Recenter the avatar in the horizontal direction, if {@link MyAvatar|MyAvatar.hmdLeanRecenterEnabled} is * false. * @function MyAvatar.triggerHorizontalRecenter */ @@ -1136,7 +1137,7 @@ public: /*@jsdoc * Gets whether the avatar is configured to keep its center of gravity under its head. * @function MyAvatar.isRecenteringHorizontally - * @returns {boolean} true if the avatar is keeping its center of gravity under its head position, + * @returns {boolean} true if the avatar is keeping its center of gravity under its head position, * false if not. */ Q_INVOKABLE bool isRecenteringHorizontally() const; @@ -1176,7 +1177,7 @@ public: Q_INVOKABLE float getHeadFinalPitch() const { return getHead()->getFinalPitch(); } /*@jsdoc - * If a face tracker is connected and being used, gets the estimated pitch of the user's head scaled. This is scale such + * If a face tracker is connected and being used, gets the estimated pitch of the user's head scaled. This is scale such * that the avatar looks at the edge of the view frustum when the user looks at the edge of their screen. * @function MyAvatar.getHeadDeltaPitch * @returns {number} The pitch that the avatar's head should be if a face tracker is connected and being used, otherwise @@ -1201,7 +1202,7 @@ public: * @example Report the position of the avatar you're currently looking at. * print(JSON.stringify(MyAvatar.getTargetAvatarPosition())); */ - // FIXME: If not looking at an avatar, the most recently looked-at position is returned. This should be fixed to return + // FIXME: If not looking at an avatar, the most recently looked-at position is returned. This should be fixed to return // undefined or {NaN, NaN, NaN} or similar. Q_INVOKABLE glm::vec3 getTargetAvatarPosition() const { return _targetAvatarPosition; } @@ -1210,18 +1211,18 @@ public: * @function MyAvatar.getTargetAvatar * @returns {ScriptAvatar} Information on the avatar being looked at, null if no avatar is being looked at. */ - // FIXME: The return type doesn't have a conversion to a script value so the function always returns undefined in + // FIXME: The return type doesn't have a conversion to a script value so the function always returns undefined in // JavaScript. Note: When fixed, JSDoc is needed for the return type. Q_INVOKABLE ScriptAvatarData* getTargetAvatar() const; /*@jsdoc - * Gets the position of the avatar's left hand, relative to the avatar, as positioned by a hand controller (e.g., Oculus + * Gets the position of the avatar's left hand, relative to the avatar, as positioned by a hand controller (e.g., Oculus * Touch or Vive). - *

Note: The Leap Motion isn't part of the hand controller input system. (Instead, it manipulates the avatar's joints + *

Note: The Leap Motion isn't part of the hand controller input system. (Instead, it manipulates the avatar's joints * for hand animation.)

* @function MyAvatar.getLeftHandPosition - * @returns {Vec3} The position of the left hand in avatar coordinates if positioned by a hand controller, otherwise + * @returns {Vec3} The position of the left hand in avatar coordinates if positioned by a hand controller, otherwise * {@link Vec3(0)|Vec3.ZERO}. * @example Report the position of your left hand relative to your avatar. * print(JSON.stringify(MyAvatar.getLeftHandPosition())); @@ -1229,12 +1230,12 @@ public: Q_INVOKABLE glm::vec3 getLeftHandPosition() const; /*@jsdoc - * Gets the position of the avatar's right hand, relative to the avatar, as positioned by a hand controller (e.g., Oculus + * Gets the position of the avatar's right hand, relative to the avatar, as positioned by a hand controller (e.g., Oculus * Touch or Vive). - *

Note: The Leap Motion isn't part of the hand controller input system. (Instead, it manipulates the avatar's joints + *

Note: The Leap Motion isn't part of the hand controller input system. (Instead, it manipulates the avatar's joints * for hand animation.)

* @function MyAvatar.getRightHandPosition - * @returns {Vec3} The position of the right hand in avatar coordinates if positioned by a hand controller, otherwise + * @returns {Vec3} The position of the right hand in avatar coordinates if positioned by a hand controller, otherwise * {@link Vec3(0)|Vec3.ZERO}. * @example Report the position of your right hand relative to your avatar. * print(JSON.stringify(MyAvatar.getLeftHandPosition())); @@ -1242,10 +1243,10 @@ public: Q_INVOKABLE glm::vec3 getRightHandPosition() const; /*@jsdoc - * Gets the position 0.3m in front of the left hand's position in the direction along the palm, in avatar coordinates, as + * Gets the position 0.3m in front of the left hand's position in the direction along the palm, in avatar coordinates, as * positioned by a hand controller. * @function MyAvatar.getLeftHandTipPosition - * @returns {Vec3} The position 0.3m in front of the left hand's position in the direction along the palm, in avatar + * @returns {Vec3} The position 0.3m in front of the left hand's position in the direction along the palm, in avatar * coordinates. If the hand isn't being positioned by a controller, {@link Vec3(0)|Vec3.ZERO} is returned. */ Q_INVOKABLE glm::vec3 getLeftHandTipPosition() const; @@ -1254,17 +1255,17 @@ public: * Gets the position 0.3m in front of the right hand's position in the direction along the palm, in avatar coordinates, as * positioned by a hand controller. * @function MyAvatar.getRightHandTipPosition - * @returns {Vec3} The position 0.3m in front of the right hand's position in the direction along the palm, in avatar + * @returns {Vec3} The position 0.3m in front of the right hand's position in the direction along the palm, in avatar * coordinates. If the hand isn't being positioned by a controller, {@link Vec3(0)|Vec3.ZERO} is returned. */ Q_INVOKABLE glm::vec3 getRightHandTipPosition() const; /*@jsdoc - * Gets the pose (position, rotation, velocity, and angular velocity) of the avatar's left hand as positioned by a + * Gets the pose (position, rotation, velocity, and angular velocity) of the avatar's left hand as positioned by a * hand controller (e.g., Oculus Touch or Vive). - *

Note: The Leap Motion isn't part of the hand controller input system. (Instead, it manipulates the avatar's joints - * for hand animation.) If you are using the Leap Motion, the return value's valid property will be + *

Note: The Leap Motion isn't part of the hand controller input system. (Instead, it manipulates the avatar's joints + * for hand animation.) If you are using the Leap Motion, the return value's valid property will be * false and any pose values returned will not be meaningful.

* @function MyAvatar.getLeftHandPose * @returns {Pose} The pose of the avatar's left hand, relative to the avatar, as positioned by a hand controller. @@ -1274,26 +1275,26 @@ public: Q_INVOKABLE controller::Pose getLeftHandPose() const; /*@jsdoc - * Gets the pose (position, rotation, velocity, and angular velocity) of the avatar's left hand as positioned by a + * Gets the pose (position, rotation, velocity, and angular velocity) of the avatar's left hand as positioned by a * hand controller (e.g., Oculus Touch or Vive). - *

Note: The Leap Motion isn't part of the hand controller input system. (Instead, it manipulates the avatar's joints - * for hand animation.) If you are using the Leap Motion, the return value's valid property will be + *

Note: The Leap Motion isn't part of the hand controller input system. (Instead, it manipulates the avatar's joints + * for hand animation.) If you are using the Leap Motion, the return value's valid property will be * false and any pose values returned will not be meaningful.

* @function MyAvatar.getRightHandPose - * @returns {Pose} The pose of the avatar's right hand, relative to the avatar, as positioned by a hand controller. + * @returns {Pose} The pose of the avatar's right hand, relative to the avatar, as positioned by a hand controller. * @example Report the pose of your avatar's right hand. * print(JSON.stringify(MyAvatar.getRightHandPose())); */ Q_INVOKABLE controller::Pose getRightHandPose() const; /*@jsdoc - * Gets the pose (position, rotation, velocity, and angular velocity) of the avatar's left hand, relative to the avatar, as + * Gets the pose (position, rotation, velocity, and angular velocity) of the avatar's left hand, relative to the avatar, as * positioned by a hand controller (e.g., Oculus Touch or Vive), and translated 0.3m along the palm. *

Note: Leap Motion isn't part of the hand controller input system. (Instead, it manipulates the avatar's joints * for hand animation.) If you are using Leap Motion, the return value's valid property will be * false and any pose values returned will not be meaningful.

* @function MyAvatar.getLeftHandTipPose - * @returns {Pose} The pose of the avatar's left hand, relative to the avatar, as positioned by a hand controller, and + * @returns {Pose} The pose of the avatar's left hand, relative to the avatar, as positioned by a hand controller, and * translated 0.3m along the palm. */ Q_INVOKABLE controller::Pose getLeftHandTipPose() const; @@ -1466,34 +1467,34 @@ public: /*@jsdoc * Checks whether your avatar is in the air. * @function MyAvatar.isInAir - * @returns {boolean} true if your avatar is taking off, flying, or falling, otherwise false + * @returns {boolean} true if your avatar is taking off, flying, or falling, otherwise false * because your avatar is on the ground. */ Q_INVOKABLE bool isInAir(); /*@jsdoc - * Sets your preference for flying in your current desktop or HMD display mode. Note that your ability to fly also depends + * Sets your preference for flying in your current desktop or HMD display mode. Note that your ability to fly also depends * on whether the domain you're in allows you to fly. * @function MyAvatar.setFlyingEnabled - * @param {boolean} enabled - Set true if you want to enable flying in your current desktop or HMD display + * @param {boolean} enabled - Set true if you want to enable flying in your current desktop or HMD display * mode, otherwise set false. */ Q_INVOKABLE void setFlyingEnabled(bool enabled); /*@jsdoc - * Gets your preference for flying in your current desktop or HMD display mode. Note that your ability to fly also depends + * Gets your preference for flying in your current desktop or HMD display mode. Note that your ability to fly also depends * on whether the domain you're in allows you to fly. * @function MyAvatar.getFlyingEnabled - * @returns {boolean} true if your preference is to enable flying in your current desktop or HMD display mode, + * @returns {boolean} true if your preference is to enable flying in your current desktop or HMD display mode, * otherwise false. */ Q_INVOKABLE bool getFlyingEnabled(); /*@jsdoc - * Sets your preference for flying in desktop display mode. Note that your ability to fly also depends on whether the domain + * Sets your preference for flying in desktop display mode. Note that your ability to fly also depends on whether the domain * you're in allows you to fly. * @function MyAvatar.setFlyingDesktopPref - * @param {boolean} enabled - Set true if you want to enable flying in desktop display mode, otherwise set + * @param {boolean} enabled - Set true if you want to enable flying in desktop display mode, otherwise set * false. */ Q_INVOKABLE void setFlyingDesktopPref(bool enabled); @@ -1502,7 +1503,7 @@ public: * Gets your preference for flying in desktop display mode. Note that your ability to fly also depends on whether the domain * you're in allows you to fly. * @function MyAvatar.getFlyingDesktopPref - * @returns {boolean} true if your preference is to enable flying in desktop display mode, otherwise + * @returns {boolean} true if your preference is to enable flying in desktop display mode, otherwise * false. */ Q_INVOKABLE bool getFlyingDesktopPref(); @@ -1624,8 +1625,8 @@ public: Q_INVOKABLE float getAvatarScale() const; /*@jsdoc - * Sets the target scale of the avatar. The target scale is the desired scale of the avatar without any restrictions on - * permissible scale values imposed by the domain. + * Sets the target scale of the avatar. The target scale is the desired scale of the avatar without any restrictions on + * permissible scale values imposed by the domain. * @function MyAvatar.setAvatarScale * @param {number} scale - The target scale for the avatar, range 0.0051000.0. */ @@ -1633,11 +1634,11 @@ public: /*@jsdoc * Sets whether the avatar should collide with entities. - *

Note: A false value won't disable collisions if the avatar is in a zone that disallows - * collisionless avatars. However, the false value will be set so that collisions are disabled as soon as the + *

Note: A false value won't disable collisions if the avatar is in a zone that disallows + * collisionless avatars. However, the false value will be set so that collisions are disabled as soon as the * avatar moves to a position where collisionless avatars are allowed. * @function MyAvatar.setCollisionsEnabled - * @param {boolean} enabled - true to enable the avatar to collide with entities, false to + * @param {boolean} enabled - true to enable the avatar to collide with entities, false to * disable. */ Q_INVOKABLE void setCollisionsEnabled(bool enabled); @@ -1653,7 +1654,7 @@ public: /*@jsdoc * Sets whether the avatar should collide with other avatars. * @function MyAvatar.setOtherAvatarsCollisionsEnabled - * @param {boolean} enabled - true to enable the avatar to collide with other avatars, false + * @param {boolean} enabled - true to enable the avatar to collide with other avatars, false * to disable. */ Q_INVOKABLE void setOtherAvatarsCollisionsEnabled(bool enabled); @@ -1667,7 +1668,7 @@ public: /*@jsdoc * Gets the avatar's collision capsule: a cylinder with hemispherical ends that approximates the extents or the avatar. - *

Warning: The values returned are in world coordinates but aren't necessarily up to date with the + *

Warning: The values returned are in world coordinates but aren't necessarily up to date with the * avatar's current position.

* @function MyAvatar.getCollisionCapsule * @returns {MyAvatar.CollisionCapsule} The avatar's collision capsule. @@ -1746,21 +1747,21 @@ public: glm::mat4 deriveBodyUsingCgModel(); /*@jsdoc - * Tests whether a vector is pointing in the general direction of the avatar's "up" direction (i.e., dot product of vectors + * Tests whether a vector is pointing in the general direction of the avatar's "up" direction (i.e., dot product of vectors * is > 0). * @function MyAvatar.isUp * @param {Vec3} direction - The vector to test. - * @returns {boolean} true if the direction vector is pointing generally in the direction of the avatar's "up" + * @returns {boolean} true if the direction vector is pointing generally in the direction of the avatar's "up" * direction. */ Q_INVOKABLE bool isUp(const glm::vec3& direction) { return glm::dot(direction, _worldUpDirection) > 0.0f; }; // true iff direction points up wrt avatar's definition of up. /*@jsdoc - * Tests whether a vector is pointing in the general direction of the avatar's "down" direction (i.e., dot product of + * Tests whether a vector is pointing in the general direction of the avatar's "down" direction (i.e., dot product of * vectors is < 0). * @function MyAvatar.isDown * @param {Vec3} direction - The vector to test. - * @returns {boolean} true if the direction vector is pointing generally in the direction of the avatar's + * @returns {boolean} true if the direction vector is pointing generally in the direction of the avatar's * "down" direction. */ Q_INVOKABLE bool isDown(const glm::vec3& direction) { return glm::dot(direction, _worldUpDirection) < 0.0f; }; @@ -1844,7 +1845,7 @@ public: /*@jsdoc * Forces the avatar's eyes to look at a specified location. Once this method is called, API calls - * full control of the eyes for a limited time. If this method is not called for 2 seconds, + * full control of the eyes for a limited time. If this method is not called for 2 seconds, * the engine regains control of the eyes. * @function MyAvatar.setEyesLookAt * @param {Vec3} lookAtTarget - The target point in world coordinates. @@ -1865,7 +1866,7 @@ public: Q_INVOKABLE void releaseEyesLookAtControl(); /*@jsdoc - * Sets the point-at target for the "point" reaction that may be started with {@link MyAvatar.beginReaction}. + * Sets the point-at target for the "point" reaction that may be started with {@link MyAvatar.beginReaction}. * The point-at target is set only if it is in front of the avatar. *

Note: The "point" reaction should be started before calling this method.

* @function MyAvatar.setPointAt @@ -1946,20 +1947,20 @@ public: * @comment Uses the base class's JSDoc. */ int sendAvatarDataPacket(bool sendAll = false) override; - + void addAvatarHandsToFlow(const std::shared_ptr& otherAvatar); /*@jsdoc - * Enables and disables flow simulation of physics on the avatar's hair, clothes, and body parts. See - * {@link https://docs.vircadia.dev/create/avatars/add-flow.html|Add Flow to Your Avatar} for more + * Enables and disables flow simulation of physics on the avatar's hair, clothes, and body parts. See + * {@link https://docs.vircadia.com/create/avatars/add-flow.html|Add Flow to Your Avatar} for more * information. * @function MyAvatar.useFlow * @param {boolean} isActive - true if flow simulation is enabled on the joint, false if it isn't. - * @param {boolean} isCollidable - true to enable collisions in the flow simulation, false to + * @param {boolean} isCollidable - true to enable collisions in the flow simulation, false to * disable. - * @param {Object} [physicsConfig] - Physics configurations for particular entity + * @param {Object} [physicsConfig] - Physics configurations for particular entity * and avatar joints. - * @param {Object} [collisionsConfig] - Collision configurations for particular + * @param {Object} [collisionsConfig] - Collision configurations for particular * entity and avatar joints. */ Q_INVOKABLE void useFlow(bool isActive, bool isCollidable, const QVariantMap& physicsConfig = QVariantMap(), const QVariantMap& collisionsConfig = QVariantMap()); @@ -2078,7 +2079,7 @@ public slots: void setGravity(float gravity); /*@jsdoc - * Sets the amount of gravity applied to the avatar in the y-axis direction. (Negative values are downward.) The default + * Sets the amount of gravity applied to the avatar in the y-axis direction. (Negative values are downward.) The default * value is -5 m/s2. * @function MyAvatar.getGravity * @returns {number} The amount of gravity currently applied to the avatar, in m/s2. @@ -2086,7 +2087,7 @@ public slots: float getGravity(); /*@jsdoc - * Moves the avatar to a new position and/or orientation in the domain, with safe landing, while taking into account avatar + * Moves the avatar to a new position and/or orientation in the domain, with safe landing, while taking into account avatar * leg length. * @function MyAvatar.goToFeetLocation * @param {Vec3} position - The new position for the avatar, in world coordinates. @@ -2095,7 +2096,7 @@ public slots: * @param {boolean} [shouldFaceLocation=false] - Set to true to position the avatar a short distance away from * the new position and orientate the avatar to face the position. */ - void goToFeetLocation(const glm::vec3& newPosition, bool hasOrientation = false, + void goToFeetLocation(const glm::vec3& newPosition, bool hasOrientation = false, const glm::quat& newOrientation = glm::quat(), bool shouldFaceLocation = false); /*@jsdoc @@ -2104,7 +2105,7 @@ public slots: * @param {Vec3} position - The new position for the avatar, in world coordinates. * @param {boolean} [hasOrientation=false] - Set to true to set the orientation of the avatar. * @param {Quat} [orientation=Quat.IDENTITY] - The new orientation for the avatar. - * @param {boolean} [shouldFaceLocation=false] - Set to true to position the avatar a short distance away from + * @param {boolean} [shouldFaceLocation=false] - Set to true to position the avatar a short distance away from * the new position and orientate the avatar to face the position. * @param {boolean} [withSafeLanding=true] - Set to false to disable safe landing when teleporting. */ @@ -2152,7 +2153,7 @@ public slots: * Adds a thrust to your avatar's current thrust to be applied for a short while. * @function MyAvatar.addThrust * @param {Vec3} thrust - The thrust direction and magnitude. - * @deprecated This function is deprecated and will be removed. Use {@link MyAvatar|MyAvatar.motorVelocity} and related + * @deprecated This function is deprecated and will be removed. Use {@link MyAvatar|MyAvatar.motorVelocity} and related * properties instead. */ // Set/Get update the thrust that will move the avatar around @@ -2162,7 +2163,7 @@ public slots: * Gets the thrust currently being applied to your avatar. * @function MyAvatar.getThrust * @returns {Vec3} The thrust currently being applied to your avatar. - * @deprecated This function is deprecated and will be removed. Use {@link MyAvatar|MyAvatar.motorVelocity} and related + * @deprecated This function is deprecated and will be removed. Use {@link MyAvatar|MyAvatar.motorVelocity} and related * properties instead. */ glm::vec3 getThrust() { return _thrust; }; @@ -2171,14 +2172,14 @@ public slots: * Sets the thrust to be applied to your avatar for a short while. * @function MyAvatar.setThrust * @param {Vec3} thrust - The thrust direction and magnitude. - * @deprecated This function is deprecated and will be removed. Use {@link MyAvatar|MyAvatar.motorVelocity} and related + * @deprecated This function is deprecated and will be removed. Use {@link MyAvatar|MyAvatar.motorVelocity} and related * properties instead. */ void setThrust(glm::vec3 newThrust) { _thrust = newThrust; } /*@jsdoc - * Updates avatar motion behavior from the Developer > Avatar > Enable Default Motor Control and Enable Scripted + * Updates avatar motion behavior from the Developer > Avatar > Enable Default Motor Control and Enable Scripted * Motor Control menu items. * @function MyAvatar.updateMotionBehaviorFromMenu */ @@ -2192,8 +2193,8 @@ public slots: void setToggleHips(bool followHead); /*@jsdoc - * Displays the base of support area debug graphics if in HMD mode. If your head goes outside this area your avatar's hips - * are moved to counterbalance your avatar, and if your head moves too far then your avatar's position is moved (i.e., a + * Displays the base of support area debug graphics if in HMD mode. If your head goes outside this area your avatar's hips + * are moved to counterbalance your avatar, and if your head moves too far then your avatar's position is moved (i.e., a * step happens). * @function MyAvatar.setEnableDebugDrawBaseOfSupport * @param {boolean} enabled - true to show the debug graphics, false to hide. @@ -2208,7 +2209,7 @@ public slots: void setEnableDebugDrawDefaultPose(bool isEnabled); /*@jsdoc - * Displays animation debug graphics. By default, the animation poses used for rendering are displayed. However, + * Displays animation debug graphics. By default, the animation poses used for rendering are displayed. However, * {@link MyAvatar.setDebugDrawAnimPoseName} can be used to set a specific animation node to display. * @function MyAvatar.setEnableDebugDrawAnimPose * @param {boolean} enabled - true to show the debug graphics, false to hide. @@ -2216,10 +2217,10 @@ public slots: void setEnableDebugDrawAnimPose(bool isEnabled); /*@jsdoc - * Sets the animation node to display when animation debug graphics are enabled with + * Sets the animation node to display when animation debug graphics are enabled with * {@link MyAvatar.setEnableDebugDrawAnimPose}. * @function MyAvatar.setDebugDrawAnimPoseName - * @param {string} poseName - The name of the animation node to display debug graphics for. Use "" to reset to + * @param {string} poseName - The name of the animation node to display debug graphics for. Use "" to reset to * default. */ void setDebugDrawAnimPoseName(QString poseName); @@ -2314,17 +2315,17 @@ public slots: /*@jsdoc * Gets the URL of the override animation graph. - *

See {@link https://docs.vircadia.dev/create/avatars/custom-animations.html|Custom Avatar Animations} for + *

See {@link https://docs.vircadia.com/create/avatars/custom-animations.html|Custom Avatar Animations} for * information on animation graphs.

* @function MyAvatar.getAnimGraphOverrideUrl - * @returns {string} The URL of the override animation graph JSON file. "" if there is no override animation + * @returns {string} The URL of the override animation graph JSON file. "" if there is no override animation * graph. */ QUrl getAnimGraphOverrideUrl() const; // thread-safe /*@jsdoc * Sets the animation graph to use in preference to the default animation graph. - *

See {@link https://docs.vircadia.dev/create/avatars/custom-animations.html|Custom Avatar Animations} for + *

See {@link https://docs.vircadia.com/create/avatars/custom-animations.html|Custom Avatar Animations} for * information on animation graphs.

* @function MyAvatar.setAnimGraphOverrideUrl * @param {string} url - The URL of the animation graph JSON file to use. Set to "" to clear an override. @@ -2333,7 +2334,7 @@ public slots: /*@jsdoc * Gets the URL of animation graph (i.e., the avatar animation JSON) that's currently being used for avatar animations. - *

See {@link https://docs.vircadia.dev/create/avatars/custom-animations.html|Custom Avatar Animations} for + *

See {@link https://docs.vircadia.com/create/avatars/custom-animations.html|Custom Avatar Animations} for * information on animation graphs.

* @function MyAvatar.getAnimGraphUrl * @returns {string} The URL of the current animation graph JSON file. @@ -2344,7 +2345,7 @@ public slots: /*@jsdoc * Sets the current animation graph (i.e., the avatar animation JSON) to use for avatar animations and makes it the default. - *

See {@link https://docs.vircadia.dev/create/avatars/custom-animations.html|Custom Avatar Animations} for + *

See {@link https://docs.vircadia.com/create/avatars/custom-animations.html|Custom Avatar Animations} for * information on animation graphs.

* @function MyAvatar.setAnimGraphUrl * @param {string} url - The URL of the animation graph JSON file to use. @@ -2360,7 +2361,7 @@ public slots: glm::vec3 getPositionForAudio(); /*@jsdoc - * Gets the orientation of your listening position for spatialized audio. The orientation depends on the value of the + * Gets the orientation of your listening position for spatialized audio. The orientation depends on the value of the * {@link Myavatar|audioListenerMode} property. * @function MyAvatar.getOrientationForAudio * @returns {Quat} The orientation of your listening position. @@ -2386,7 +2387,7 @@ public slots: /*@jsdoc - * Gets the list of reactions names that can be enabled using {@link MyAvatar.beginReaction} and + * Gets the list of reactions names that can be enabled using {@link MyAvatar.beginReaction} and * {@link MyAvatar.endReaction}. *

See also: {@link MyAvatar.getTriggerReactions}. * @function MyAvatar.getBeginEndReactions @@ -2407,7 +2408,7 @@ public slots: bool triggerReaction(QString reactionName); /*@jsdoc - * Starts playing a reaction on the avatar. The reaction will continue to play until stopped using + * Starts playing a reaction on the avatar. The reaction will continue to play until stopped using * {@link MyAvatar.endReaction} or superseded by another reaction. *

Only reactions returned by {@link MyAvatar.getBeginEndReactions} are available.

* @function MyAvatar.beginReaction @@ -2429,7 +2430,7 @@ signals: /*@jsdoc * Triggered when the {@link MyAvatar|audioListenerMode} property value changes. * @function MyAvatar.audioListenerModeChanged - * @returns {Signal} + * @returns {Signal} */ void audioListenerModeChanged(); @@ -2437,7 +2438,7 @@ signals: * Triggered when the walk speed set for the "AnalogPlus" control scheme changes. * @function MyAvatar.analogPlusWalkSpeedChanged * @param {number} speed - The new walk speed set for the "AnalogPlus" control scheme. - * @returns {Signal} + * @returns {Signal} */ void analogPlusWalkSpeedChanged(float value); @@ -2445,31 +2446,31 @@ signals: * Triggered when the sprint (run) speed set for the "AnalogPlus" control scheme changes. * @function MyAvatar.analogPlusSprintSpeedChanged * @param {number} speed - The new sprint speed set for the "AnalogPlus" control scheme. - * @returns {Signal} + * @returns {Signal} */ void analogPlusSprintSpeedChanged(float value); /*@jsdoc - * Triggered when the sprint (run) speed set for the current control scheme (see + * Triggered when the sprint (run) speed set for the current control scheme (see * {@link MyAvatar.getControlScheme|getControlScheme}) changes. * @function MyAvatar.sprintSpeedChanged * @param {number} speed -The new sprint speed set for the current control scheme. - * @returns {Signal} + * @returns {Signal} */ void sprintSpeedChanged(float value); /*@jsdoc - * Triggered when the walk backward speed set for the current control scheme (see + * Triggered when the walk backward speed set for the current control scheme (see * {@link MyAvatar.getControlScheme|getControlScheme}) changes. * @function MyAvatar.walkBackwardSpeedChanged * @param {number} speed - The new walk backward speed set for the current control scheme. - * @returns {Signal} + * @returns {Signal} */ void walkBackwardSpeedChanged(float value); /*@jsdoc * @function MyAvatar.transformChanged - * @returns {Signal} + * @returns {Signal} * @deprecated This signal is deprecated and will be removed. */ void transformChanged(); @@ -2478,7 +2479,7 @@ signals: * Triggered when the {@link MyAvatar|collisionSoundURL} property value changes. * @function MyAvatar.newCollisionSoundURL * @param {string} url - The URL of the new collision sound. - * @returns {Signal} + * @returns {Signal} */ void newCollisionSoundURL(const QUrl& url); @@ -2497,7 +2498,7 @@ signals: /*@jsdoc * Triggered when collisions with the environment are enabled or disabled. * @function MyAvatar.collisionsEnabledChanged - * @param {boolean} enabled - true if collisions with the environment are enabled, false if + * @param {boolean} enabled - true if collisions with the environment are enabled, false if * they're not. * @returns {Signal} */ @@ -2506,7 +2507,7 @@ signals: /*@jsdoc * Triggered when collisions with other avatars are enabled or disabled. * @function MyAvatar.otherAvatarsCollisionsEnabledChanged - * @param {boolean} enabled - true if collisions with other avatars are enabled, false if they're + * @param {boolean} enabled - true if collisions with other avatars are enabled, false if they're * not. * @returns {Signal} */ @@ -2526,7 +2527,7 @@ signals: /*@jsdoc * @function MyAvatar.energyChanged * @param {number} energy - Avatar energy. - * @returns {Signal} + * @returns {Signal} * @deprecated This signal is deprecated and will be removed. */ void energyChanged(float newEnergy); @@ -2534,7 +2535,7 @@ signals: /*@jsdoc * Triggered when the avatar has been moved to a new position by one of the MyAvatar "goTo" functions. * @function MyAvatar.positionGoneTo - * @returns {Signal} + * @returns {Signal} */ // FIXME: Better name would be goneToLocation(). void positionGoneTo(); @@ -2556,7 +2557,7 @@ signals: /*@jsdoc * Triggered when your avatar changes from being active to being away. * @function MyAvatar.wentAway - * @returns {Signal} + * @returns {Signal} * @example Report when your avatar goes away. * MyAvatar.wentAway.connect(function () { * print("My avatar went away"); @@ -2568,7 +2569,7 @@ signals: /*@jsdoc * Triggered when your avatar changes from being away to being active. * @function MyAvatar.wentActive - * @returns {Signal} + * @returns {Signal} */ void wentActive(); @@ -2576,7 +2577,7 @@ signals: * Triggered when the avatar's model (i.e., {@link MyAvatar|skeletonModelURL} property value) is changed. *

Synonym of {@link MyAvatar.skeletonModelURLChanged|skeletonModelURLChanged}.

* @function MyAvatar.skeletonChanged - * @returns {Signal} + * @returns {Signal} */ void skeletonChanged(); @@ -2584,14 +2585,14 @@ signals: * Triggered when the avatar's dominant hand changes. * @function MyAvatar.dominantHandChanged * @param {string} hand - The dominant hand: "left" for the left hand, "right" for the right hand. - * @returns {Signal} + * @returns {Signal} */ void dominantHandChanged(const QString& hand); /*@jsdoc * Triggered when the HMD alignment for your avatar changes. * @function MyAvatar.hmdAvatarAlignmentTypeChanged - * @param {string} type - "head" if aligning your head and your avatar's head, "eyes" if aligning + * @param {string} type - "head" if aligning your head and your avatar's head, "eyes" if aligning * your eyes and your avatar's eyes. * @returns {Signal} */ @@ -2600,27 +2601,27 @@ signals: /*@jsdoc * Triggered when the avatar's sensorToWorldScale property value changes. * @function MyAvatar.sensorToWorldScaleChanged - * @param {number} scale - The scale that transforms dimensions in the user's real world to the avatar's size in the virtual + * @param {number} scale - The scale that transforms dimensions in the user's real world to the avatar's size in the virtual * world. - * @returns {Signal} + * @returns {Signal} */ void sensorToWorldScaleChanged(float sensorToWorldScale); /*@jsdoc - * Triggered when the a model is attached to or detached from one of the avatar's joints using one of - * {@link MyAvatar.attach|attach}, {@link MyAvatar.detachOne|detachOne}, {@link MyAvatar.detachAll|detachAll}, or + * Triggered when the a model is attached to or detached from one of the avatar's joints using one of + * {@link MyAvatar.attach|attach}, {@link MyAvatar.detachOne|detachOne}, {@link MyAvatar.detachAll|detachAll}, or * {@link MyAvatar.setAttachmentData|setAttachmentData}. * @function MyAvatar.attachmentsChanged - * @returns {Signal} + * @returns {Signal} * @deprecated This signal is deprecated and will be removed. Use avatar entities instead. */ void attachmentsChanged(); /*@jsdoc - * Triggered when the avatar's size changes. This can be due to the user changing the size of their avatar or the domain + * Triggered when the avatar's size changes. This can be due to the user changing the size of their avatar or the domain * limiting the size of their avatar. * @function MyAvatar.scaleChanged - * @returns {Signal} + * @returns {Signal} */ void scaleChanged(); @@ -2629,7 +2630,7 @@ signals: *

The hand touch effect makes the avatar's fingers adapt to the shape of any object grabbed, creating the effect that * it is really touching that object.

* @function MyAvatar.shouldDisableHandTouchChanged - * @param {boolean} disabled - true if the hand touch effect is disabled for the avatar, + * @param {boolean} disabled - true if the hand touch effect is disabled for the avatar, * false if it isn't disabled. * @returns {Signal} */ @@ -2703,7 +2704,7 @@ private: virtual void detachOne(const QString& modelURL, const QString& jointName = QString()) override; virtual void detachAll(const QString& modelURL, const QString& jointName = QString()) override; - + // Attachments/Avatar Entity void attachmentDataToEntityProperties(const AttachmentData& data, EntityItemProperties& properties); AttachmentData entityPropertiesToAttachmentData(const EntityItemProperties& properties) const; diff --git a/interface/src/main.cpp b/interface/src/main.cpp index d190e3f3da..4e338a629b 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -265,7 +265,7 @@ int main(int argc, const char* argv[]) { if (socket.waitForConnected(LOCAL_SERVER_TIMEOUT_MS)) { if (parser.isSet(urlOption)) { QUrl url = QUrl(parser.value(urlOption)); - if (url.isValid() && (url.scheme() == URL_SCHEME_HIFI || url.scheme() == URL_SCHEME_HIFIAPP + if (url.isValid() && (url.scheme() == URL_SCHEME_VIRCADIA || url.scheme() == URL_SCHEME_VIRCADIAAPP || url.scheme() == HIFI_URL_SCHEME_HTTP || url.scheme() == HIFI_URL_SCHEME_HTTPS || url.scheme() == HIFI_URL_SCHEME_FILE)) { qDebug() << "Writing URL to local socket"; diff --git a/interface/src/scripting/WindowScriptingInterface.cpp b/interface/src/scripting/WindowScriptingInterface.cpp index c8714e2a8f..e594ecd536 100644 --- a/interface/src/scripting/WindowScriptingInterface.cpp +++ b/interface/src/scripting/WindowScriptingInterface.cpp @@ -139,9 +139,9 @@ void WindowScriptingInterface::disconnectedFromDomain() { void WindowScriptingInterface::openUrl(const QUrl& url) { if (!url.isEmpty()) { auto scheme = url.scheme(); - if (scheme == URL_SCHEME_HIFI) { + if (scheme == URL_SCHEME_VIRCADIA) { DependencyManager::get()->handleLookupString(url.toString()); - } else if (scheme == URL_SCHEME_HIFIAPP) { + } else if (scheme == URL_SCHEME_VIRCADIAAPP) { DependencyManager::get()->openSystemApp(url.path()); } else { #if defined(Q_OS_ANDROID) diff --git a/libraries/audio-client/src/AudioClient.h b/libraries/audio-client/src/AudioClient.h index a5de9bd4ca..5e753fbef8 100644 --- a/libraries/audio-client/src/AudioClient.h +++ b/libraries/audio-client/src/AudioClient.h @@ -4,6 +4,7 @@ // // Created by Stephen Birarda on 1/22/13. // Copyright 2013 High Fidelity, Inc. +// Copyright 2021 Vircadia contributors. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -33,7 +34,7 @@ #include #include -#include +#include #include #include #include diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h index 3f5faccb3b..fa5a5cff67 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h @@ -3,6 +3,7 @@ // interface/src/avatar // // Copyright 2012 High Fidelity, Inc. +// Copyright 2021 Vircadia contributors. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -207,7 +208,7 @@ public: /*@jsdoc * Gets the default rotation of a joint (in the current avatar) relative to its parent. *

For information on the joint hierarchy used, see - * Avatar Standards.

+ * Avatar Standards.

* @function MyAvatar.getDefaultJointRotation * @param {number} index - The joint index. * @returns {Quat} The default rotation of the joint if the joint index is valid, otherwise {@link Quat(0)|Quat.IDENTITY}. @@ -218,10 +219,10 @@ public: * Gets the default translation of a joint (in the current avatar) relative to its parent, in model coordinates. *

Warning: These coordinates are not necessarily in meters.

*

For information on the joint hierarchy used, see - * Avatar Standards.

+ * Avatar Standards.

* @function MyAvatar.getDefaultJointTranslation * @param {number} index - The joint index. - * @returns {Vec3} The default translation of the joint (in model coordinates) if the joint index is valid, otherwise + * @returns {Vec3} The default translation of the joint (in model coordinates) if the joint index is valid, otherwise * {@link Vec3(0)|Vec3.ZERO}. */ Q_INVOKABLE virtual glm::vec3 getDefaultJointTranslation(int index) const; @@ -283,7 +284,7 @@ public: // world-space to avatar-space rigconversion functions /*@jsdoc - * Transforms a position in world coordinates to a position in a joint's coordinates, or avatar coordinates if no joint is + * Transforms a position in world coordinates to a position in a joint's coordinates, or avatar coordinates if no joint is * specified. * @function MyAvatar.worldToJointPoint * @param {Vec3} position - The position in world coordinates. @@ -293,7 +294,7 @@ public: Q_INVOKABLE glm::vec3 worldToJointPoint(const glm::vec3& position, const int jointIndex = -1) const; /*@jsdoc - * Transforms a direction in world coordinates to a direction in a joint's coordinates, or avatar coordinates if no joint + * Transforms a direction in world coordinates to a direction in a joint's coordinates, or avatar coordinates if no joint * is specified. * @function MyAvatar.worldToJointDirection * @param {Vec3} direction - The direction in world coordinates. @@ -303,7 +304,7 @@ public: Q_INVOKABLE glm::vec3 worldToJointDirection(const glm::vec3& direction, const int jointIndex = -1) const; /*@jsdoc - * Transforms a rotation in world coordinates to a rotation in a joint's coordinates, or avatar coordinates if no joint is + * Transforms a rotation in world coordinates to a rotation in a joint's coordinates, or avatar coordinates if no joint is * specified. * @function MyAvatar.worldToJointRotation * @param {Quat} rotation - The rotation in world coordinates. @@ -313,7 +314,7 @@ public: Q_INVOKABLE glm::quat worldToJointRotation(const glm::quat& rotation, const int jointIndex = -1) const; /*@jsdoc - * Transforms a position in a joint's coordinates, or avatar coordinates if no joint is specified, to a position in world + * Transforms a position in a joint's coordinates, or avatar coordinates if no joint is specified, to a position in world * coordinates. * @function MyAvatar.jointToWorldPoint * @param {Vec3} position - The position in joint coordinates, or avatar coordinates if no joint is specified. @@ -323,7 +324,7 @@ public: Q_INVOKABLE glm::vec3 jointToWorldPoint(const glm::vec3& position, const int jointIndex = -1) const; /*@jsdoc - * Transforms a direction in a joint's coordinates, or avatar coordinates if no joint is specified, to a direction in world + * Transforms a direction in a joint's coordinates, or avatar coordinates if no joint is specified, to a direction in world * coordinates. * @function MyAvatar.jointToWorldDirection * @param {Vec3} direction - The direction in joint coordinates, or avatar coordinates if no joint is specified. @@ -333,7 +334,7 @@ public: Q_INVOKABLE glm::vec3 jointToWorldDirection(const glm::vec3& direction, const int jointIndex = -1) const; /*@jsdoc - * Transforms a rotation in a joint's coordinates, or avatar coordinates if no joint is specified, to a rotation in world + * Transforms a rotation in a joint's coordinates, or avatar coordinates if no joint is specified, to a rotation in world * coordinates. * @function MyAvatar.jointToWorldRotation * @param {Quat} rotation - The rotation in joint coordinates, or avatar coordinates if no joint is specified. @@ -351,7 +352,7 @@ public: virtual int parseDataFromBuffer(const QByteArray& buffer) override; /*@jsdoc - * Sets the offset applied to the current avatar. The offset adjusts the position that the avatar is rendered. For example, + * Sets the offset applied to the current avatar. The offset adjusts the position that the avatar is rendered. For example, * with an offset of { x: 0, y: 0.1, z: 0 }, your avatar will appear to be raised off the ground slightly. * @function MyAvatar.setSkeletonOffset * @param {Vec3} offset - The skeleton offset to set. @@ -367,7 +368,7 @@ public: Q_INVOKABLE void setSkeletonOffset(const glm::vec3& offset); /*@jsdoc - * Gets the offset applied to the current avatar. The offset adjusts the position that the avatar is rendered. For example, + * Gets the offset applied to the current avatar. The offset adjusts the position that the avatar is rendered. For example, * with an offset of { x: 0, y: 0.1, z: 0 }, your avatar will appear to be raised off the ground slightly. * @function MyAvatar.getSkeletonOffset * @returns {Vec3} The current skeleton offset. @@ -452,7 +453,7 @@ public: /*@jsdoc * Sets the ID of the entity or avatar that the avatar is parented to. * @function MyAvatar.setParentID - * @param {Uuid} parentID - The ID of the entity or avatar that the avatar should be parented to. Set to + * @param {Uuid} parentID - The ID of the entity or avatar that the avatar should be parented to. Set to * {@link Uuid(0)|Uuid.NULL} to unparent. */ // This calls through to the SpatiallyNestable versions, but is here to expose these to JavaScript. @@ -461,17 +462,17 @@ public: /*@jsdoc * Gets the joint of the entity or avatar that the avatar is parented to. * @function MyAvatar.getParentJointIndex - * @returns {number} The joint of the entity or avatar that the avatar is parented to. 65535 or + * @returns {number} The joint of the entity or avatar that the avatar is parented to. 65535 or * -1 if parented to the entity or avatar's position and orientation rather than a joint. */ // This calls through to the SpatiallyNestable versions, but is here to expose these to JavaScript. Q_INVOKABLE virtual quint16 getParentJointIndex() const override { return SpatiallyNestable::getParentJointIndex(); } /*@jsdoc - * Sets the joint of the entity or avatar that the avatar is parented to. + * Sets the joint of the entity or avatar that the avatar is parented to. * @function MyAvatar.setParentJointIndex * @param {number} parentJointIndex - The joint of the entity or avatar that the avatar should be parented to. Use - * 65535 or -1 to parent to the entity or avatar's position and orientation rather than a + * 65535 or -1 to parent to the entity or avatar's position and orientation rather than a * joint. */ // This calls through to the SpatiallyNestable versions, but is here to expose these to JavaScript. @@ -557,7 +558,7 @@ public: signals: /*@jsdoc - * Triggered when the avatar's target scale is changed. The target scale is the desired scale of the avatar without any + * Triggered when the avatar's target scale is changed. The target scale is the desired scale of the avatar without any * restrictions on permissible scale values imposed by the domain. * @function MyAvatar.targetScaleChanged * @param {number} targetScale - The avatar's target scale. @@ -758,7 +759,7 @@ protected: static void metaBlendshapeOperator(render::ItemID renderItemID, int blendshapeNumber, const QVector& blendshapeOffsets, const QVector& blendedMeshSizes, const render::ItemIDs& subItemIDs); - + std::vector _multiSphereShapes; AABox _fitBoundingBox; void clearAvatarGrabData(const QUuid& grabID) override; diff --git a/libraries/avatars-renderer/src/avatars-renderer/ScriptAvatar.h b/libraries/avatars-renderer/src/avatars-renderer/ScriptAvatar.h index f434498204..aac8236eda 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/ScriptAvatar.h +++ b/libraries/avatars-renderer/src/avatars-renderer/ScriptAvatar.h @@ -4,6 +4,7 @@ // // Created by Stephen Birarda on 4/10/17. // Copyright 2017 High Fidelity, Inc. +// Copyright 2021 Vircadia contributors. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -87,10 +88,10 @@ public slots: /*@jsdoc * Gets the default rotation of a joint in the avatar relative to its parent. *

For information on the joint hierarchy used, see - * Avatar Standards.

+ * Avatar Standards.

* @function ScriptAvatar.getDefaultJointRotation * @param {number} index - The joint index. - * @returns {Quat} The default rotation of the joint if avatar data are available and the joint index is valid, otherwise + * @returns {Quat} The default rotation of the joint if avatar data are available and the joint index is valid, otherwise * {@link Quat(0)|Quat.IDENTITY}. */ glm::quat getDefaultJointRotation(int index) const; @@ -99,10 +100,10 @@ public slots: * Gets the default translation of a joint in the avatar relative to its parent, in model coordinates. *

Warning: These coordinates are not necessarily in meters.

*

For information on the joint hierarchy used, see - * Avatar Standards.

+ * Avatar Standards.

* @function ScriptAvatar.getDefaultJointTranslation * @param {number} index - The joint index. - * @returns {Vec3} The default translation of the joint (in model coordinates) if avatar data are available and the joint + * @returns {Vec3} The default translation of the joint (in model coordinates) if avatar data are available and the joint * index is valid, otherwise {@link Vec3(0)|Vec3.ZERO}. */ glm::vec3 getDefaultJointTranslation(int index) const; @@ -120,7 +121,7 @@ public slots: * Gets the position of a joint in the avatar. * @function ScriptAvatar.getJointPosition * @param {number} index - The index of the joint. - * @returns {Vec3} The position of the joint in world coordinates, or {@link Vec3(0)|Vec3.ZERO} if avatar data aren't + * @returns {Vec3} The position of the joint in world coordinates, or {@link Vec3(0)|Vec3.ZERO} if avatar data aren't * available. */ glm::vec3 getJointPosition(int index) const; @@ -154,7 +155,7 @@ public slots: /*@jsdoc * Gets the ID of the entity or avatar that the avatar is parented to. * @function ScriptAvatar.getParentID - * @returns {Uuid} The ID of the entity or avatar that the avatar is parented to. {@link Uuid(0)|Uuid.NULL} if not parented + * @returns {Uuid} The ID of the entity or avatar that the avatar is parented to. {@link Uuid(0)|Uuid.NULL} if not parented * or avatar data aren't available. */ QUuid getParentID() const; @@ -163,7 +164,7 @@ public slots: * Gets the joint of the entity or avatar that the avatar is parented to. * @function ScriptAvatar.getParentJointIndex * @returns {number} The joint of the entity or avatar that the avatar is parented to. 65535 or - * -1 if parented to the entity or avatar's position and orientation rather than a joint, or avatar data + * -1 if parented to the entity or avatar's position and orientation rather than a joint, or avatar data * aren't available. */ quint16 getParentJointIndex() const; @@ -189,7 +190,7 @@ public slots: /*@jsdoc * Gets the position of the left palm in world coordinates. * @function ScriptAvatar.getLeftPalmPosition - * @returns {Vec3} The position of the left palm in world coordinates, or {@link Vec3(0)|Vec3.ZERO} if avatar data aren't + * @returns {Vec3} The position of the left palm in world coordinates, or {@link Vec3(0)|Vec3.ZERO} if avatar data aren't * available. */ glm::vec3 getLeftPalmPosition() const; @@ -197,7 +198,7 @@ public slots: /*@jsdoc * Gets the rotation of the left palm in world coordinates. * @function ScriptAvatar.getLeftPalmRotation - * @returns {Quat} The rotation of the left palm in world coordinates, or {@link Quat(0)|Quat.IDENTITY} if the avatar data + * @returns {Quat} The rotation of the left palm in world coordinates, or {@link Quat(0)|Quat.IDENTITY} if the avatar data * aren't available. */ glm::quat getLeftPalmRotation() const; diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index ff00f9d68b..e17ba8f09d 100755 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -4,6 +4,7 @@ // // Created by Stephen Birarda on 4/9/13. // Copyright 2013 High Fidelity, Inc. +// Copyright 2021 Vircadia contributors. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -530,23 +531,23 @@ class AvatarData : public QObject, public SpatiallyNestable { * avatar. Read-only. * @property {number} sensorToWorldScale - The scale that transforms dimensions in the user's real world to the avatar's * size in the virtual world. Read-only. - * @property {boolean} hasPriority - true if the avatar is in a "hero" zone, false if it isn't. + * @property {boolean} hasPriority - true if the avatar is in a "hero" zone, false if it isn't. * Read-only. - * @property {boolean} hasScriptedBlendshapes=false - true if blend shapes are controlled by scripted actions, - * otherwise false. Set this to true before using the {@link Avatar.setBlendshape} method, + * @property {boolean} hasScriptedBlendshapes=false - true if blend shapes are controlled by scripted actions, + * otherwise false. Set this to true before using the {@link Avatar.setBlendshape} method, * and set back to false after you no longer want scripted control over the blend shapes. - *

Note: This property will automatically be set to true if the controller system has + *

Note: This property will automatically be set to true if the controller system has * valid facial blend shape actions.

- * @property {boolean} hasProceduralBlinkFaceMovement=true - true if avatars blink automatically by animating - * facial blend shapes, false if automatic blinking is disabled. Set to false to fully control + * @property {boolean} hasProceduralBlinkFaceMovement=true - true if avatars blink automatically by animating + * facial blend shapes, false if automatic blinking is disabled. Set to false to fully control * the blink facial blend shapes via the {@link Avatar.setBlendshape} method. - * @property {boolean} hasProceduralEyeFaceMovement=true - true if the facial blend shapes for an avatar's eyes - * adjust automatically as the eyes move, false if this automatic movement is disabled. Set this property + * @property {boolean} hasProceduralEyeFaceMovement=true - true if the facial blend shapes for an avatar's eyes + * adjust automatically as the eyes move, false if this automatic movement is disabled. Set this property * to true to prevent the iris from being obscured by the upper or lower lids. Set to false to * fully control the eye blend shapes via the {@link Avatar.setBlendshape} method. - * @property {boolean} hasAudioEnabledFaceMovement=true - true if the avatar's mouth blend shapes animate - * automatically based on detected microphone input, false if this automatic movement is disabled. Set - * this property to false to fully control the mouth facial blend shapes via the + * @property {boolean} hasAudioEnabledFaceMovement=true - true if the avatar's mouth blend shapes animate + * automatically based on detected microphone input, false if this automatic movement is disabled. Set + * this property to false to fully control the mouth facial blend shapes via the * {@link Avatar.setBlendshape} method. */ Q_PROPERTY(glm::vec3 position READ getWorldPosition WRITE setPositionViaScript) @@ -758,7 +759,7 @@ public: void setDomainMaximumHeight(float domainMaximumHeight); /*@jsdoc - * Sets the pointing state of the hands to control where the laser emanates from. If the right index finger is pointing, the + * Sets the pointing state of the hands to control where the laser emanates from. If the right index finger is pointing, the * laser emanates from the tip of that finger, otherwise it emanates from the palm. * @function Avatar.setHandState * @param {HandState} state - The pointing state of the hand. @@ -787,9 +788,9 @@ public: * Sets a specific joint's rotation and position relative to its parent, in model coordinates. *

Warning: These coordinates are not necessarily in meters.

*

Setting joint data completely overrides/replaces all motion from the default animation system including inverse - * kinematics, but just for the specified joint. So for example, if you were to procedurally manipulate the finger joints, - * the avatar's hand and head would still do inverse kinematics properly. However, as soon as you start to manipulate - * joints in the inverse kinematics chain, the inverse kinematics might not function as you expect. For example, if you set + * kinematics, but just for the specified joint. So for example, if you were to procedurally manipulate the finger joints, + * the avatar's hand and head would still do inverse kinematics properly. However, as soon as you start to manipulate + * joints in the inverse kinematics chain, the inverse kinematics might not function as you expect. For example, if you set * the rotation of the elbow, the hand inverse kinematics position won't end up in the right place.

* @function Avatar.setJointData * @param {number} index - The index of the joint. @@ -816,10 +817,10 @@ public: /*@jsdoc * Sets a specific joint's rotation relative to its parent. - *

Setting joint data completely overrides/replaces all motion from the default animation system including inverse - * kinematics, but just for the specified joint. So for example, if you were to procedurally manipulate the finger joints, - * the avatar's hand and head would still do inverse kinematics properly. However, as soon as you start to manipulate - * joints in the inverse kinematics chain, the inverse kinematics might not function as you expect. For example, if you set + *

Setting joint data completely overrides/replaces all motion from the default animation system including inverse + * kinematics, but just for the specified joint. So for example, if you were to procedurally manipulate the finger joints, + * the avatar's hand and head would still do inverse kinematics properly. However, as soon as you start to manipulate + * joints in the inverse kinematics chain, the inverse kinematics might not function as you expect. For example, if you set * the rotation of the elbow, the hand inverse kinematics position won't end up in the right place.

* @function Avatar.setJointRotation * @param {number} index - The index of the joint. @@ -831,9 +832,9 @@ public: * Sets a specific joint's translation relative to its parent, in model coordinates. *

Warning: These coordinates are not necessarily in meters.

*

Setting joint data completely overrides/replaces all motion from the default animation system including inverse - * kinematics, but just for the specified joint. So for example, if you were to procedurally manipulate the finger joints, - * the avatar's hand and head would still do inverse kinematics properly. However, as soon as you start to manipulate - * joints in the inverse kinematics chain, the inverse kinematics might not function as you expect. For example, if you set + * kinematics, but just for the specified joint. So for example, if you were to procedurally manipulate the finger joints, + * the avatar's hand and head would still do inverse kinematics properly. However, as soon as you start to manipulate + * joints in the inverse kinematics chain, the inverse kinematics might not function as you expect. For example, if you set * the rotation of the elbow, the hand inverse kinematics position won't end up in the right place.

* @function Avatar.setJointTranslation * @param {number} index - The index of the joint. @@ -842,7 +843,7 @@ public: Q_INVOKABLE virtual void setJointTranslation(int index, const glm::vec3& translation); /*@jsdoc - * Clears joint translations and rotations set by script for a specific joint. This restores all motion from the default + * Clears joint translations and rotations set by script for a specific joint. This restores all motion from the default * animation system including inverse kinematics for that joint. *

Note: This is slightly faster than the function variation that specifies the joint name.

* @function Avatar.clearJointData @@ -859,8 +860,8 @@ public: Q_INVOKABLE bool isJointDataValid(int index) const; /*@jsdoc - * Gets the rotation of a joint relative to its parent. For information on the joint hierarchy used, see - * Avatar Standards. + * Gets the rotation of a joint relative to its parent. For information on the joint hierarchy used, see + * Avatar Standards. * @function Avatar.getJointRotation * @param {number} index - The index of the joint. * @returns {Quat} The rotation of the joint relative to its parent. @@ -870,8 +871,8 @@ public: /*@jsdoc * Gets the translation of a joint relative to its parent, in model coordinates. *

Warning: These coordinates are not necessarily in meters.

- *

For information on the joint hierarchy used, see - * Avatar Standards.

+ *

For information on the joint hierarchy used, see + * Avatar Standards.

* @function Avatar.getJointTranslation * @param {number} index - The index of the joint. * @returns {Vec3} The translation of the joint relative to its parent, in model coordinates. @@ -882,9 +883,9 @@ public: * Sets a specific joint's rotation and position relative to its parent, in model coordinates. *

Warning: These coordinates are not necessarily in meters.

*

Setting joint data completely overrides/replaces all motion from the default animation system including inverse - * kinematics, but just for the specified joint. So for example, if you were to procedurally manipulate the finger joints, - * the avatar's hand and head would still do inverse kinematics properly. However, as soon as you start to manipulate - * joints in the inverse kinematics chain, the inverse kinematics might not function as you expect. For example, if you set + * kinematics, but just for the specified joint. So for example, if you were to procedurally manipulate the finger joints, + * the avatar's hand and head would still do inverse kinematics properly. However, as soon as you start to manipulate + * joints in the inverse kinematics chain, the inverse kinematics might not function as you expect. For example, if you set * the rotation of the elbow, the hand inverse kinematics position won't end up in the right place.

* @function Avatar.setJointData * @param {string} name - The name of the joint. @@ -895,10 +896,10 @@ public: /*@jsdoc * Sets a specific joint's rotation relative to its parent. - *

Setting joint data completely overrides/replaces all motion from the default animation system including inverse - * kinematics, but just for the specified joint. So for example, if you were to procedurally manipulate the finger joints, - * the avatar's hand and head would still do inverse kinematics properly. However, as soon as you start to manipulate - * joints in the inverse kinematics chain, the inverse kinematics might not function as you expect. For example, if you set + *

Setting joint data completely overrides/replaces all motion from the default animation system including inverse + * kinematics, but just for the specified joint. So for example, if you were to procedurally manipulate the finger joints, + * the avatar's hand and head would still do inverse kinematics properly. However, as soon as you start to manipulate + * joints in the inverse kinematics chain, the inverse kinematics might not function as you expect. For example, if you set * the rotation of the elbow, the hand inverse kinematics position won't end up in the right place.

* @function Avatar.setJointRotation * @param {string} name - The name of the joint. @@ -930,19 +931,19 @@ public: * Sets a specific joint's translation relative to its parent, in model coordinates. *

Warning: These coordinates are not necessarily in meters.

*

Setting joint data completely overrides/replaces all motion from the default animation system including inverse - * kinematics, but just for the specified joint. So for example, if you were to procedurally manipulate the finger joints, - * the avatar's hand and head would still do inverse kinematics properly. However, as soon as you start to manipulate - * joints in the inverse kinematics chain, the inverse kinematics might not function as you expect. For example, if you set + * kinematics, but just for the specified joint. So for example, if you were to procedurally manipulate the finger joints, + * the avatar's hand and head would still do inverse kinematics properly. However, as soon as you start to manipulate + * joints in the inverse kinematics chain, the inverse kinematics might not function as you expect. For example, if you set * the rotation of the elbow, the hand inverse kinematics position won't end up in the right place.

* @function Avatar.setJointTranslation * @param {string} name - The name of the joint. * @param {Vec3} translation - The translation of the joint relative to its parent, in model coordinates. - * @example Stretch your avatar's neck. Depending on the avatar you are using, you will either see a gap between + * @example Stretch your avatar's neck. Depending on the avatar you are using, you will either see a gap between * the head and body or you will see the neck stretched.
* Avatar with neck stretched * // Stretch your avatar's neck. * MyAvatar.setJointTranslation("Neck", Vec3.multiply(2, MyAvatar.getJointTranslation("Neck"))); - * + * * // Restore your avatar's neck after 5s. * Script.setTimeout(function () { * MyAvatar.clearJointData("Neck"); @@ -953,7 +954,7 @@ public: Q_INVOKABLE virtual void setJointTranslation(const QString& name, const glm::vec3& translation); /*@jsdoc - * Clears joint translations and rotations set by script for a specific joint. This restores all motion from the default + * Clears joint translations and rotations set by script for a specific joint. This restores all motion from the default * animation system including inverse kinematics for that joint. *

Note: This is slightly slower than the function variation that specifies the joint index.

* @function Avatar.clearJointData @@ -980,8 +981,8 @@ public: Q_INVOKABLE virtual bool isJointDataValid(const QString& name) const; /*@jsdoc - * Gets the rotation of a joint relative to its parent. For information on the joint hierarchy used, see - * Avatar Standards. + * Gets the rotation of a joint relative to its parent. For information on the joint hierarchy used, see + * Avatar Standards. * @function Avatar.getJointRotation * @param {string} name - The name of the joint. * @returns {Quat} The rotation of the joint relative to its parent. @@ -996,7 +997,7 @@ public: * Gets the translation of a joint relative to its parent, in model coordinates. *

Warning: These coordinates are not necessarily in meters.

*

For information on the joint hierarchy used, see - * Avatar Standards.

+ * Avatar Standards.

* @function Avatar.getJointTranslation * @param {number} name - The name of the joint. * @returns {Vec3} The translation of the joint relative to its parent, in model coordinates. @@ -1010,7 +1011,7 @@ public: /*@jsdoc * Gets the rotations of all joints in the current avatar. Each joint's rotation is relative to its parent joint. * @function Avatar.getJointRotations - * @returns {Quat[]} The rotations of all joints relative to each's parent. The values are in the same order as the array + * @returns {Quat[]} The rotations of all joints relative to each's parent. The values are in the same order as the array * returned by {@link MyAvatar.getJointNames}, or {@link Avatar.getJointNames} if using the Avatar API. * @example Report the rotations of all your avatar's joints. * print(JSON.stringify(MyAvatar.getJointRotations())); @@ -1024,8 +1025,8 @@ public: * model coordinates. *

Warning: These coordinates are not necessarily in meters.

* @function Avatar.getJointTranslations - * @returns {Vec3[]} The translations of all joints relative to each's parent, in model coordinates. The values are in the - * same order as the array returned by {@link MyAvatar.getJointNames}, or {@link Avatar.getJointNames} if using the + * @returns {Vec3[]} The translations of all joints relative to each's parent, in model coordinates. The values are in the + * same order as the array returned by {@link MyAvatar.getJointNames}, or {@link Avatar.getJointNames} if using the * Avatar API. */ Q_INVOKABLE virtual QVector getJointTranslations() const; @@ -1038,7 +1039,7 @@ public: * joints in the inverse kinematics chain, the inverse kinematics might not function as you expect. For example, if you set * the rotation of the elbow, the hand inverse kinematics position won't end up in the right place.

* @function Avatar.setJointRotations - * @param {Quat[]} jointRotations - The rotations for all joints in the avatar. The values are in the same order as the + * @param {Quat[]} jointRotations - The rotations for all joints in the avatar. The values are in the same order as the * array returned by {@link MyAvatar.getJointNames}, or {@link Avatar.getJointNames} if using the Avatar API. * @example Set your avatar to its default T-pose then rotate its right arm.
* Avatar in T-pose @@ -1051,7 +1052,7 @@ public: * } * * // Get all join rotations. - * var jointRotations = MyAvatar.getJointRotations(); + * var jointRotations = MyAvatar.getJointRotations(); * * // Update the rotation of the right arm in the array. * jointRotations[MyAvatar.getJointIndex("RightArm")] = { x: 0.47, y: 0.22, z: -0.02, w: 0.87 }; @@ -1067,9 +1068,9 @@ public: * // Note: If using from the Avatar API, replace all occurrences of "MyAvatar" with "Avatar". */ Q_INVOKABLE virtual void setJointRotations(const QVector& jointRotations); - + /*@jsdoc - * Sets the translations of all joints in the current avatar. Each joint's translation is relative to its parent joint, in + * Sets the translations of all joints in the current avatar. Each joint's translation is relative to its parent joint, in * model coordinates. *

Warning: These coordinates are not necessarily in meters.

*

Setting joint data completely overrides/replaces all motion from the default animation system including inverse @@ -1078,14 +1079,14 @@ public: * joints in the inverse kinematics chain, the inverse kinematics might not function as you expect. For example, if you set * the rotation of the elbow, the hand inverse kinematics position won't end up in the right place.

* @function Avatar.setJointTranslations - * @param {Vec3[]} translations - The translations for all joints in the avatar, in model coordinates. The values are in - * the same order as the array returned by {@link MyAvatar.getJointNames}, or {@link Avatar.getJointNames} if using the + * @param {Vec3[]} translations - The translations for all joints in the avatar, in model coordinates. The values are in + * the same order as the array returned by {@link MyAvatar.getJointNames}, or {@link Avatar.getJointNames} if using the * Avatar API. */ Q_INVOKABLE virtual void setJointTranslations(const QVector& jointTranslations); /*@jsdoc - * Clears all joint translations and rotations that have been set by script. This restores all motion from the default + * Clears all joint translations and rotations that have been set by script. This restores all motion from the default * animation system including inverse kinematics for all joints. * @function Avatar.clearJointsData * @example Set your avatar to it's default T-pose for a while. @@ -1107,7 +1108,7 @@ public: Q_INVOKABLE virtual void clearJointsData(); /*@jsdoc - * Gets the joint index for a named joint. The joint index value is the position of the joint in the array returned by + * Gets the joint index for a named joint. The joint index value is the position of the joint in the array returned by * {@link MyAvatar.getJointNames}, or {@link Avatar.getJointNames} if using the Avatar API. * @function Avatar.getJointIndex * @param {string} name - The name of the joint. @@ -1133,12 +1134,12 @@ public: /*@jsdoc - * Sets the value of a blend shape to animate your avatar's face. In order for other users to see the resulting animations - * on your avatar's face, set hasScriptedBlendshapes to true. When you are done using this API, - * set hasScriptedBlendshapes back to false when the animation is complete. + * Sets the value of a blend shape to animate your avatar's face. In order for other users to see the resulting animations + * on your avatar's face, set hasScriptedBlendshapes to true. When you are done using this API, + * set hasScriptedBlendshapes back to false when the animation is complete. * @function Avatar.setBlendshape - * @param {string} name - The name of the blendshape, per the - * {@link https://docs.vircadia.dev/create/avatars/avatar-standards.html#blendshapes Avatar Standards}. + * @param {string} name - The name of the blendshape, per the + * {@link https://docs.vircadia.com/create/avatars/avatar-standards.html#blendshapes Avatar Standards}. * @param {number} value - A value between 0.0 and 1.0. * @example Open your avatar's mouth wide. * MyAvatar.hasScriptedBlendshapes = true; @@ -1160,7 +1161,7 @@ public: /*@jsdoc * Sets all models currently attached to your avatar. For example, if you retrieve attachment data using - * {@link MyAvatar.getAttachmentsVariant} or {@link Avatar.getAttachmentsVariant}, make changes to it, and then want to + * {@link MyAvatar.getAttachmentsVariant} or {@link Avatar.getAttachmentsVariant}, make changes to it, and then want to * update your avatar's attachments per the changed data. * @function Avatar.setAttachmentsVariant * @param {AttachmentData[]} variant - The attachment data defining the models to have attached to your avatar. @@ -1186,7 +1187,7 @@ public: * @deprecated This function is deprecated and will be removed. */ Q_INVOKABLE virtual void clearAvatarEntity(const QUuid& entityID, bool requiresRemovalFromTree = true); - + // FIXME: Rename to clearAvatarEntity() once the API call is removed. virtual void clearAvatarEntityInternal(const QUuid& entityID); @@ -1195,12 +1196,12 @@ public: QList getAvatarEntityIDs() const; /*@jsdoc - * Enables blend shapes set using {@link Avatar.setBlendshape} or {@link MyAvatar.setBlendshape} to be transmitted to other + * Enables blend shapes set using {@link Avatar.setBlendshape} or {@link MyAvatar.setBlendshape} to be transmitted to other * users so that they can see the animation of your avatar's face. - *

Deprecated: This method is deprecated and will be removed. Use the + *

Deprecated: This method is deprecated and will be removed. Use the * Avatar.hasScriptedBlendshapes or MyAvatar.hasScriptedBlendshapes property instead.

* @function Avatar.setForceFaceTrackerConnected - * @param {boolean} connected - true to enable blend shape changes to be transmitted to other users, + * @param {boolean} connected - true to enable blend shape changes to be transmitted to other users, * false to disable. */ Q_INVOKABLE void setForceFaceTrackerConnected(bool connected) { setHasScriptedBlendshapes(connected); } @@ -1274,7 +1275,7 @@ public: /*@jsdoc * Sets all models currently attached to your avatar. For example, if you retrieve attachment data using - * {@link MyAvatar.getAttachmentData} or {@link Avatar.getAttachmentData}, make changes to it, and then want to update your avatar's attachments per the + * {@link MyAvatar.getAttachmentData} or {@link Avatar.getAttachmentData}, make changes to it, and then want to update your avatar's attachments per the * changed data. You can also remove all attachments by using setting attachmentData to null. * @function Avatar.setAttachmentData * @param {AttachmentData[]} attachmentData - The attachment data defining the models to have attached to your avatar. Use @@ -1300,19 +1301,19 @@ public: * Attaches a model to your avatar. For example, you can give your avatar a hat to wear, a guitar to hold, or a surfboard to * stand on. * @function Avatar.attach - * @param {string} modelURL - The URL of the glTF, FBX, or OBJ model to attach. glTF models may be in JSON or binary format + * @param {string} modelURL - The URL of the glTF, FBX, or OBJ model to attach. glTF models may be in JSON or binary format * (".gltf" or ".glb" URLs respectively). - * @param {string} [jointName=""] - The name of the avatar joint (see {@link MyAvatar.getJointNames} or + * @param {string} [jointName=""] - The name of the avatar joint (see {@link MyAvatar.getJointNames} or * {@link Avatar.getJointNames}) to attach the model to. * @param {Vec3} [translation=Vec3.ZERO] - The offset to apply to the model relative to the joint position. * @param {Quat} [rotation=Quat.IDENTITY] - The rotation to apply to the model relative to the joint orientation. * @param {number} [scale=1.0] - The scale to apply to the model. - * @param {boolean} [isSoft=false] - If the model has a skeleton, set this to true so that the bones of the - * attached model's skeleton are rotated to fit the avatar's current pose. isSoft is used, for example, + * @param {boolean} [isSoft=false] - If the model has a skeleton, set this to true so that the bones of the + * attached model's skeleton are rotated to fit the avatar's current pose. isSoft is used, for example, * to have clothing that moves with the avatar. - *

If true, the translation, rotation, and scale parameters are + *

If true, the translation, rotation, and scale parameters are * ignored.

- * @param {boolean} [allowDuplicates=false] - If true then more than one copy of any particular model may be + * @param {boolean} [allowDuplicates=false] - If true then more than one copy of any particular model may be * attached to the same joint; if false then the same model cannot be attached to the same joint. * @param {boolean} [useSaved=true] - Not used. * @deprecated This function is deprecated and will be removed. Use avatar entities instead. @@ -1344,7 +1345,7 @@ public: * Detaches the most recently attached instance of a particular model from either a specific joint or any joint. * @function Avatar.detachOne * @param {string} modelURL - The URL of the model to detach. - * @param {string} [jointName=""] - The name of the joint to detach the model from. If "", then the most + * @param {string} [jointName=""] - The name of the joint to detach the model from. If "", then the most * recently attached model is removed from which ever joint it was attached to. * @deprecated This function is deprecated and will be removed. Use avatar entities instead. */ @@ -1354,7 +1355,7 @@ public: * Detaches all instances of a particular model from either a specific joint or all joints. * @function Avatar.detachAll * @param {string} modelURL - The URL of the model to detach. - * @param {string} [jointName=""] - The name of the joint to detach the model from. If "", then the model is + * @param {string} [jointName=""] - The name of the joint to detach the model from. If "", then the model is * detached from all joints. * @deprecated This function is deprecated and will be removed. Use avatar entities instead. */ @@ -1414,7 +1415,7 @@ public: /*@jsdoc * Gets the transform from the user's real world to the avatar's size, orientation, and position in the virtual world. * @function Avatar.getSensorToWorldMatrix - * @returns {Mat4} The scale, rotation, and translation transform from the user's real world to the avatar's size, + * @returns {Mat4} The scale, rotation, and translation transform from the user's real world to the avatar's size, * orientation, and position in the virtual world. * @example Report the sensor to world matrix. * var sensorToWorldMatrix = MyAvatar.getSensorToWorldMatrix(); @@ -1431,7 +1432,7 @@ public: /*@jsdoc * Gets the scale that transforms dimensions in the user's real world to the avatar's size in the virtual world. * @function Avatar.getSensorToWorldScale - * @returns {number} The scale that transforms dimensions in the user's real world to the avatar's size in the virtual + * @returns {number} The scale that transforms dimensions in the user's real world to the avatar's size in the virtual * world. */ // thread safe @@ -1661,7 +1662,7 @@ public slots: virtual bool setAbsoluteJointTranslationInObjectFrame(int index, const glm::vec3& translation) override { return false; } /*@jsdoc - * Gets the target scale of the avatar without any restrictions on permissible values imposed by the domain. In contrast, the + * Gets the target scale of the avatar without any restrictions on permissible values imposed by the domain. In contrast, the * scale property's value may be limited by the domain's settings. * @function Avatar.getTargetScale * @returns {number} The target scale of the avatar. @@ -1703,7 +1704,7 @@ protected: void unpackSkeletonModelURL(const QByteArray& data); void unpackSkeletonData(const QByteArray& data); - + // isReplicated will be true on downstream Avatar Mixers and their clients, but false on the upstream "master" // Audio Mixer that the replicated avatar is connected to. bool _isReplicated{ false }; diff --git a/libraries/avatars/src/ScriptAvatarData.h b/libraries/avatars/src/ScriptAvatarData.h index a9deb81a27..3982c32b29 100644 --- a/libraries/avatars/src/ScriptAvatarData.h +++ b/libraries/avatars/src/ScriptAvatarData.h @@ -4,6 +4,7 @@ // // Created by Zach Fox on 2017-04-10. // Copyright 2017 High Fidelity, Inc. +// Copyright 2021 Vircadia contributors. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -117,10 +118,10 @@ public: /*@jsdoc * Gets the rotation of a joint relative to its parent. For information on the joint hierarchy used, see - * Avatar Standards. + * Avatar Standards. * @function ScriptAvatar.getJointRotation * @param {number} index - The index of the joint. - * @returns {Quat} The rotation of the joint relative to its parent, or {@link Quat(0)|Quat.IDENTITY} if the avatar data + * @returns {Quat} The rotation of the joint relative to its parent, or {@link Quat(0)|Quat.IDENTITY} if the avatar data * aren't available. */ Q_INVOKABLE glm::quat getJointRotation(int index) const; @@ -129,20 +130,20 @@ public: * Gets the translation of a joint relative to its parent, in model coordinates. *

Warning: These coordinates are not necessarily in meters.

*

For information on the joint hierarchy used, see - * Avatar Standards.

+ * Avatar Standards.

* @function ScriptAvatar.getJointTranslation * @param {number} index - The index of the joint. - * @returns {Vec3} The translation of the joint relative to its parent, in model coordinates, or {@link Vec3(0)|Vec3.ZERO} + * @returns {Vec3} The translation of the joint relative to its parent, in model coordinates, or {@link Vec3(0)|Vec3.ZERO} * if the avatar data aren't available. */ Q_INVOKABLE glm::vec3 getJointTranslation(int index) const; /*@jsdoc * Gets the rotation of a joint relative to its parent. For information on the joint hierarchy used, see - * Avatar Standards. + * Avatar Standards. * @function ScriptAvatar.getJointRotation * @param {string} name - The name of the joint. - * @returns {Quat} The rotation of the joint relative to its parent, or {@link Quat(0)|Quat.IDENTITY} if the avatar data + * @returns {Quat} The rotation of the joint relative to its parent, or {@link Quat(0)|Quat.IDENTITY} if the avatar data * aren't available. */ Q_INVOKABLE glm::quat getJointRotation(const QString& name) const; @@ -151,10 +152,10 @@ public: * Gets the translation of a joint relative to its parent, in model coordinates. *

Warning: These coordinates are not necessarily in meters.

*

For information on the joint hierarchy used, see - * Avatar Standards.

+ * Avatar Standards.

* @function ScriptAvatar.getJointTranslation * @param {number} name - The name of the joint. - * @returns {Vec3} The translation of the joint relative to its parent, in model coordinates, or {@link Vec3(0)|Vec3.ZERO} + * @returns {Vec3} The translation of the joint relative to its parent, in model coordinates, or {@link Vec3(0)|Vec3.ZERO} * if the avatar data aren't available. */ Q_INVOKABLE glm::vec3 getJointTranslation(const QString& name) const; @@ -162,7 +163,7 @@ public: /*@jsdoc * Gets the rotations of all joints in the avatar. Each joint's rotation is relative to its parent joint. * @function ScriptAvatar.getJointRotations - * @returns {Quat[]} The rotations of all joints relative to each's parent, or [] if the avatar data aren't + * @returns {Quat[]} The rotations of all joints relative to each's parent, or [] if the avatar data aren't * available. The values are in the same order as the array returned by {@link ScriptAvatar.getJointNames}. */ Q_INVOKABLE QVector getJointRotations() const; @@ -172,8 +173,8 @@ public: * model coordinates. *

Warning: These coordinates are not necessarily in meters.

* @function ScriptAvatar.getJointTranslations - * @returns {Vec3[]} The translations of all joints relative to each's parent, in model coordinates, or [] if - * the avatar data aren't available. The values are in the same order as the array returned by + * @returns {Vec3[]} The translations of all joints relative to each's parent, in model coordinates, or [] if + * the avatar data aren't available. The values are in the same order as the array returned by * {@link ScriptAvatar.getJointNames}. */ Q_INVOKABLE QVector getJointTranslations() const; @@ -182,7 +183,7 @@ public: * Checks that the data for a joint are valid. * @function ScriptAvatar.isJointDataValid * @param {number} index - The index of the joint. - * @returns {boolean} true if the joint data are valid, false if not or the avatar data aren't + * @returns {boolean} true if the joint data are valid, false if not or the avatar data aren't * available. */ Q_INVOKABLE bool isJointDataValid(const QString& name) const; @@ -206,7 +207,7 @@ public: /*@jsdoc * Gets information about the models currently attached to the avatar. * @function ScriptAvatar.getAttachmentData - * @returns {AttachmentData[]} Information about all models attached to the avatar, or [] if the avatar data + * @returns {AttachmentData[]} Information about all models attached to the avatar, or [] if the avatar data * aren't available. * @deprecated This function is deprecated and will be removed. Use avatar entities instead. */ @@ -228,7 +229,7 @@ public: glm::mat4 getSensorToWorldMatrix() const; glm::mat4 getControllerLeftHandMatrix() const; glm::mat4 getControllerRightHandMatrix() const; - + bool getHasPriority() const; signals: @@ -268,7 +269,7 @@ public slots: * Gets the rotation of a joint relative to the avatar. * @function ScriptAvatar.getAbsoluteJointRotationInObjectFrame * @param {number} index - The index of the joint. - * @returns {Quat} The rotation of the joint relative to the avatar, or {@link Quat(0)|Quat.IDENTITY} if the avatar data + * @returns {Quat} The rotation of the joint relative to the avatar, or {@link Quat(0)|Quat.IDENTITY} if the avatar data * aren't available. */ glm::quat getAbsoluteJointRotationInObjectFrame(int index) const; @@ -277,7 +278,7 @@ public slots: * Gets the translation of a joint relative to the avatar. * @function ScriptAvatar.getAbsoluteJointTranslationInObjectFrame * @param {number} index - The index of the joint. - * @returns {Vec3} The translation of the joint relative to the avatar, or {@link Vec3(0)|Vec3.ZERO} if the avatar data + * @returns {Vec3} The translation of the joint relative to the avatar, or {@link Vec3(0)|Vec3.ZERO} if the avatar data * aren't available. */ glm::vec3 getAbsoluteJointTranslationInObjectFrame(int index) const; diff --git a/libraries/controllers/src/controllers/UserInputMapper.cpp b/libraries/controllers/src/controllers/UserInputMapper.cpp index 6333792b3f..6a46dea7d9 100755 --- a/libraries/controllers/src/controllers/UserInputMapper.cpp +++ b/libraries/controllers/src/controllers/UserInputMapper.cpp @@ -738,7 +738,7 @@ Mapping::Pointer UserInputMapper::newMapping(const QString& mappingName) { // if (request->getResult() == ResourceRequest::Success) { // result = parseMapping(QString(request->getData())); // } else { -// qCWarning(controllers) << "Failed to load mapping url <" << jsonUrl << ">" << endl; +// qCWarning(controllers) << "Failed to load mapping url <" << jsonUrl << ">" << Qt::endl; // } // request->deleteLater(); // } @@ -1177,13 +1177,13 @@ Mapping::Pointer UserInputMapper::parseMapping(const QString& json) { if (doc.isNull()) { qCDebug(controllers) << "Invalid JSON...\n"; qCDebug(controllers) << error.errorString(); - qCDebug(controllers) << "JSON was:\n" << json << endl; + qCDebug(controllers) << "JSON was:\n" << json << Qt::endl; return Mapping::Pointer(); } if (!doc.isObject()) { - qWarning() << "Mapping json Document is not an object" << endl; - qCDebug(controllers) << "JSON was:\n" << json << endl; + qWarning() << "Mapping json Document is not an object" << Qt::endl; + qCDebug(controllers) << "JSON was:\n" << json << Qt::endl; return Mapping::Pointer(); } return parseMapping(doc.object()); diff --git a/libraries/entities-renderer/src/RenderableEntityItem.cpp b/libraries/entities-renderer/src/RenderableEntityItem.cpp index b7cfcde224..212baa6634 100644 --- a/libraries/entities-renderer/src/RenderableEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableEntityItem.cpp @@ -495,6 +495,15 @@ void EntityRenderer::removeMaterial(graphics::MaterialPointer material, const st emit requestRenderUpdate(); } +graphics::MaterialPointer EntityRenderer::getTopMaterial() { + std::lock_guard lock(_materialsLock); + auto materials = _materials.find("0"); + if (materials != _materials.end()) { + return materials->second.top().material; + } + return nullptr; +} + EntityRenderer::Pipeline EntityRenderer::getPipelineType(const graphics::MultiMaterial& materials) { if (materials.top().material && materials.top().material->isProcedural() && materials.top().material->isReady()) { return Pipeline::PROCEDURAL; @@ -626,6 +635,7 @@ void EntityRenderer::updateShapeKeyBuilderFromMaterials(ShapeKey::Builder& build { std::lock_guard lock(_materialsLock); materials = _materials.find("0"); + if (materials != _materials.end()) { if (materials->second.shouldUpdate()) { RenderPipelines::updateMultiMaterial(materials->second); @@ -653,7 +663,6 @@ void EntityRenderer::updateShapeKeyBuilderFromMaterials(ShapeKey::Builder& build auto pipelineType = getPipelineType(materials->second); if (pipelineType == Pipeline::MATERIAL) { builder.withMaterial(); - if (drawMaterialKey.isNormalMap()) { builder.withTangents(); } diff --git a/libraries/entities-renderer/src/RenderableEntityItem.h b/libraries/entities-renderer/src/RenderableEntityItem.h index 2731fe6a50..3caeef0713 100644 --- a/libraries/entities-renderer/src/RenderableEntityItem.h +++ b/libraries/entities-renderer/src/RenderableEntityItem.h @@ -62,7 +62,9 @@ public: }; virtual void addMaterial(graphics::MaterialLayer material, const std::string& parentMaterialName); virtual void removeMaterial(graphics::MaterialPointer material, const std::string& parentMaterialName); + virtual graphics::MaterialPointer getTopMaterial(); static Pipeline getPipelineType(const graphics::MultiMaterial& materials); + virtual gpu::TexturePointer getTexture() { return nullptr; } virtual scriptable::ScriptableModelBase getScriptableModel() override { return scriptable::ScriptableModelBase(); } diff --git a/libraries/entities-renderer/src/RenderableImageEntityItem.cpp b/libraries/entities-renderer/src/RenderableImageEntityItem.cpp index 3fa2174114..9592a3e57f 100644 --- a/libraries/entities-renderer/src/RenderableImageEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableImageEntityItem.cpp @@ -198,10 +198,8 @@ void ImageEntityRenderer::doRender(RenderArgs* args) { procedural->prepare(*batch, transform.getTranslation(), transform.getScale(), transform.getRotation(), _created, ProceduralProgramKey(transparent)); } else if (pipelineType == Pipeline::SIMPLE) { batch->setResourceTexture(0, _texture->getGPUTexture()); - } else { - if (RenderPipelines::bindMaterials(materials, *batch, args->_renderMode, args->_enableTexturing)) { - args->_details._materialSwitches++; - } + } else if (RenderPipelines::bindMaterials(materials, *batch, args->_renderMode, args->_enableTexturing)) { + args->_details._materialSwitches++; } DependencyManager::get()->renderQuad( diff --git a/libraries/entities-renderer/src/RenderableImageEntityItem.h b/libraries/entities-renderer/src/RenderableImageEntityItem.h index ff82dc157a..cc923daf4b 100644 --- a/libraries/entities-renderer/src/RenderableImageEntityItem.h +++ b/libraries/entities-renderer/src/RenderableImageEntityItem.h @@ -24,6 +24,8 @@ public: ImageEntityRenderer(const EntityItemPointer& entity); ~ImageEntityRenderer(); + gpu::TexturePointer getTexture() override { return _texture ? _texture->getGPUTexture() : nullptr; } + protected: Item::Bound getBound(RenderArgs* args) override; ShapeKey getShapeKey() override; diff --git a/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp b/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp index 8f8a2076f8..b8f829f4ba 100644 --- a/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp @@ -79,26 +79,42 @@ void MaterialEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPo } } + bool usingMaterialData = _materialURL.startsWith("materialData"); + bool usingEntityID = _materialURL.startsWith("{"); + bool materialDataChanged = false; bool urlChanged = false; std::string newCurrentMaterialName = _currentMaterialName; + QString targetEntityID = _materialURL; { QString materialURL = entity->getMaterialURL(); if (materialURL != _materialURL) { _materialURL = materialURL; + usingMaterialData = _materialURL.startsWith("materialData"); + usingEntityID = _materialURL.startsWith("{"); + targetEntityID = _materialURL; if (_materialURL.contains("#")) { auto split = _materialURL.split("#"); newCurrentMaterialName = split.last().toStdString(); + if (usingEntityID) { + targetEntityID = split.first(); + } } else if (_materialURL.contains("?")) { qDebug() << "DEPRECATED: Use # instead of ? for material URLS:" << _materialURL; auto split = _materialURL.split("?"); newCurrentMaterialName = split.last().toStdString(); + if (usingEntityID) { + targetEntityID = split.first(); + } + } + + if (usingMaterialData) { + materialDataChanged = true; + } else { + urlChanged = true; } - urlChanged = true; } } - bool usingMaterialData = _materialURL.startsWith("materialData"); - bool materialDataChanged = false; QUuid oldParentID = _parentID; QString oldParentMaterialName = _parentMaterialName; { @@ -135,7 +151,7 @@ void MaterialEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPo } } - if (urlChanged && !usingMaterialData) { + if (urlChanged && !usingMaterialData && !usingEntityID) { _networkMaterial = DependencyManager::get()->getMaterial(_materialURL); auto onMaterialRequestFinished = [this, entity, oldParentID, oldParentMaterialName, newCurrentMaterialName](bool success) { deleteMaterial(oldParentID, oldParentMaterialName); @@ -159,6 +175,13 @@ void MaterialEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPo }); } } + } else if (urlChanged && usingEntityID) { + deleteMaterial(oldParentID, oldParentMaterialName); + _texturesLoaded = true; + _parsedMaterials = NetworkMaterialResource::parseMaterialForUUID(QJsonValue(targetEntityID)); + // Since our material changed, the current name might not be valid anymore, so we need to update + setCurrentMaterialName(newCurrentMaterialName); + applyMaterial(entity); } else if (materialDataChanged && usingMaterialData) { deleteMaterial(oldParentID, oldParentMaterialName); _texturesLoaded = false; @@ -167,6 +190,10 @@ void MaterialEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPo setCurrentMaterialName(newCurrentMaterialName); applyMaterial(entity); } else { + if (newCurrentMaterialName != _currentMaterialName) { + setCurrentMaterialName(newCurrentMaterialName); + } + if (deleteNeeded) { deleteMaterial(oldParentID, oldParentMaterialName); } diff --git a/libraries/entities-renderer/src/RenderableMaterialEntityItem.h b/libraries/entities-renderer/src/RenderableMaterialEntityItem.h index 340d169f29..25403e8a2b 100644 --- a/libraries/entities-renderer/src/RenderableMaterialEntityItem.h +++ b/libraries/entities-renderer/src/RenderableMaterialEntityItem.h @@ -26,6 +26,8 @@ public: MaterialEntityRenderer(const EntityItemPointer& entity) : Parent(entity) {} ~MaterialEntityRenderer() { deleteMaterial(_parentID, _parentMaterialName); } + graphics::MaterialPointer getTopMaterial() override { return getMaterial(); } + private: virtual void doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) override; virtual void doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) override; diff --git a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp index 7932a19110..6e436a0dcd 100644 --- a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp @@ -274,6 +274,7 @@ void WebEntityRenderer::doRender(RenderArgs* args) { // Try to update the texture OffscreenQmlSurface::TextureAndFence newTextureAndFence; + QSize windowSize; bool newTextureAvailable = false; if (!resultWithReadLock([&] { if (!_webSurface) { @@ -281,6 +282,7 @@ void WebEntityRenderer::doRender(RenderArgs* args) { } newTextureAvailable = _webSurface->fetchTexture(newTextureAndFence); + windowSize = _webSurface->size(); return true; })) { return; @@ -288,6 +290,8 @@ void WebEntityRenderer::doRender(RenderArgs* args) { if (newTextureAvailable) { _texture->setExternalTexture(newTextureAndFence.first, newTextureAndFence.second); + _texture->setSize(windowSize.width(), windowSize.height()); + _texture->setOriginalSize(windowSize.width(), windowSize.height()); } static const glm::vec2 texMin(0.0f), texMax(1.0f), topLeft(-0.5f), bottomRight(0.5f); diff --git a/libraries/entities-renderer/src/RenderableWebEntityItem.h b/libraries/entities-renderer/src/RenderableWebEntityItem.h index 1ac415e5e5..fb04e08ec7 100644 --- a/libraries/entities-renderer/src/RenderableWebEntityItem.h +++ b/libraries/entities-renderer/src/RenderableWebEntityItem.h @@ -55,6 +55,8 @@ public: virtual void setProxyWindow(QWindow* proxyWindow) override; virtual QObject* getEventHandler() override; + gpu::TexturePointer getTexture() override { return _texture; } + protected: virtual bool needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const override; virtual void doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) override; diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 425cfe9439..945804a0fc 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -951,10 +951,11 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { * * @typedef {object} Entities.EntityProperties-Material * @property {Vec3} dimensions=0.1,0.1,0.1 - Used when materialMappingMode == "projected". - * @property {string} materialURL="" - URL to a {@link Entities.MaterialResource|MaterialResource}. If you append - * "#name" to the URL, the material with that name in the {@link Entities.MaterialResource|MaterialResource} - * will be applied to the entity. Alternatively, set the property value to "materialData" to use the - * materialData property for the {@link Entities.MaterialResource|MaterialResource} values. + * @property {string} materialURL="" - URL to a {@link Entities.MaterialResource|MaterialResource}. Alternatively, set the + * property value to "materialData" to use the materialData property for the + * {@link Entities.MaterialResource|MaterialResource} values. If you append "#name" to the URL, the material + * with that name will be applied to the entity. You can also use the ID of another Material entity as the URL, in which + * case this material will act as a copy of that material, with its own unique material transform, priority, etc. * @property {string} materialData="" - Used to store {@link Entities.MaterialResource|MaterialResource} data as a JSON string. * You can use JSON.parse() to parse the string into a JavaScript object which you can manipulate the * properties of, and use JSON.stringify() to convert the object into a string to put in the property. @@ -1379,7 +1380,8 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { /*@jsdoc * The "Web" {@link Entities.EntityType|EntityType} displays a browsable web page. Each user views their own copy * of the web page: if one user navigates to another page on the entity, other users do not see the change; if a video is being - * played, users don't see it in sync. It has properties in addition to the common + * played, users don't see it in sync. Internally, a Web entity is rendered as a non-repeating, upside down texture, so additional + * transformations may be necessary if you reference a Web entity texture by UUID. It has properties in addition to the common * {@link Entities.EntityProperties|EntityProperties}. * * @typedef {object} Entities.EntityProperties-Web diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index eeb42626c2..63d8842a91 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -2751,6 +2751,47 @@ QVector EntityTree::sendEntities(EntityEditPacketSender* packetSen return map.values().toVector(); } +QJsonValue replaceEntityIDsInJSONHelper(const QJsonValue& jsonValue, std::function getMapped) { + if (jsonValue.isString()) { + QString stringValue = jsonValue.toString(); + QUuid oldID = stringValue; + if (!oldID.isNull()) { + return QJsonValue(getMapped(oldID).toString()); + } + return stringValue; + } else if (jsonValue.isArray()) { + QJsonArray jsonArray = jsonValue.toArray(); + for (int i = 0; i < jsonArray.count(); i++) { + jsonArray[i] = replaceEntityIDsInJSONHelper(jsonArray[i], getMapped); + } + return jsonArray; + } else if (jsonValue.isObject()) { + QJsonObject jsonObject = jsonValue.toObject(); + auto keys = jsonObject.keys(); + for (auto& key : keys) { + auto value = jsonObject.value(key); + jsonObject[key] = replaceEntityIDsInJSONHelper(value, getMapped); + } + return jsonObject; + } else { + return jsonValue; + } +} + +QString replaceEntityIDsInJSON(const QString& json, std::function getMapped) { + QJsonDocument document = QJsonDocument::fromJson(json.toUtf8()); + if (!document.isNull() && document.isObject()) { + QJsonObject jsonObject = document.object(); + auto keys = jsonObject.keys(); + for (auto& key : keys) { + auto value = jsonObject.value(key); + jsonObject[key] = replaceEntityIDsInJSONHelper(value, getMapped); + } + document = QJsonDocument(jsonObject); + } + return document.toJson(); +} + bool EntityTree::sendEntitiesOperation(const OctreeElementPointer& element, void* extraData) { SendEntitiesOperationArgs* args = static_cast(extraData); EntityTreeElementPointer entityTreeElement = std::static_pointer_cast(element); @@ -2819,6 +2860,61 @@ bool EntityTree::sendEntitiesOperation(const OctreeElementPointer& element, void QByteArray actionData = properties.getActionData(); properties.setActionData(remapActionDataIDs(actionData, *args->map)); + { + QString materialURL = properties.getMaterialURL(); + QString uuidString = materialURL; + QString materialName = ""; + + if (materialURL.contains("?")) { + QStringList split = materialURL.split("?"); + uuidString = split[0]; + if (split.length() > 1) { + materialName = split[1]; + } + } else if (materialURL.contains("#")) { + QStringList split = materialURL.split("#"); + uuidString = split[0]; + if (split.length() > 1) { + materialName = split[1]; + } + } + + QUuid oldID = uuidString; + if (!oldID.isNull()) { + uuidString = getMapped(oldID).toString(); + } + QUuid oldMaterialName = materialName; + if (!oldMaterialName.isNull()) { + materialName = getMapped(oldMaterialName).toString(); + } + + if (!materialName.isEmpty()) { + properties.setMaterialURL(uuidString + "?" + materialName); + } else { + properties.setMaterialURL(uuidString); + } + } + + QString imageURL = properties.getImageURL(); + if (imageURL.startsWith("{")) { + QUuid oldID = imageURL; + if (!oldID.isNull()) { + properties.setImageURL(getMapped(oldID).toString()); + } + } + + QString materialData = properties.getMaterialData(); + if (!materialData.isEmpty()) { + materialData = replaceEntityIDsInJSON(materialData, getMapped); + properties.setMaterialData(materialData); + } + + QString userData = properties.getUserData(); + if (!userData.isEmpty()) { + userData = replaceEntityIDsInJSON(userData, getMapped); + properties.setUserData(userData); + } + // set creation time to "now" for imported entities properties.setCreated(usecTimestampNow()); diff --git a/libraries/gpu/src/gpu/Texture.cpp b/libraries/gpu/src/gpu/Texture.cpp index 1edd7d33cf..48159c5da5 100755 --- a/libraries/gpu/src/gpu/Texture.cpp +++ b/libraries/gpu/src/gpu/Texture.cpp @@ -322,6 +322,16 @@ bool Texture::isDepthStencilRenderTarget() const { return (_texelFormat.getSemantic() == gpu::DEPTH) || (_texelFormat.getSemantic() == gpu::DEPTH_STENCIL); } +void Texture::setSize(int width, int height) { + _width = width; + _height = height; +} + +void Texture::setOriginalSize(int width, int height) { + _originalWidth = width; + _originalHeight = height; +} + uint16 Texture::evalDimMaxNumMips(uint16 size) { double largerDim = size; double val = log(largerDim)/log(2.0); @@ -887,16 +897,34 @@ void SphericalHarmonics::evalFromTexture(const Texture& texture, gpu::BackendTar // TextureSource -void TextureSource::resetTexture(gpu::TexturePointer texture) { +const gpu::TexturePointer TextureSource::getGPUTexture() const { + if (_gpuTextureOperator && !_locked) { + _locked = true; + auto gpuTexture = _gpuTextureOperator(); + _locked = false; + return gpuTexture; + } + return _gpuTexture; +} + +void TextureSource::resetTexture(const gpu::TexturePointer& texture) { _gpuTexture = texture; + _gpuTextureOperator = nullptr; +} + +void TextureSource::resetTextureOperator(const std::function& textureOperator) { + _gpuTexture = nullptr; + _gpuTextureOperator = textureOperator; } bool TextureSource::isDefined() const { - if (_gpuTexture) { - return _gpuTexture->isDefined(); - } else { - return false; + if (_gpuTextureOperator && !_locked) { + _locked = true; + auto gpuTexture = _gpuTextureOperator(); + _locked = false; + return gpuTexture && gpuTexture->isDefined(); } + return _gpuTexture && _gpuTexture->isDefined(); } bool Texture::setMinMip(uint16 newMinMip) { @@ -930,6 +958,7 @@ void Texture::setExternalTexture(uint32 externalId, void* externalFence) { Lock lock(_externalMutex); assert(_externalRecycler); _externalUpdates.push_back({ externalId, externalFence }); + _defined = true; } Texture::ExternalUpdates Texture::getUpdates() const { diff --git a/libraries/gpu/src/gpu/Texture.h b/libraries/gpu/src/gpu/Texture.h index a525cda1ab..a0cfc60b6e 100755 --- a/libraries/gpu/src/gpu/Texture.h +++ b/libraries/gpu/src/gpu/Texture.h @@ -417,11 +417,16 @@ public: Element getTexelFormat() const { return _texelFormat; } + void setSize(int width, int height); Vec3u getDimensions() const { return Vec3u(_width, _height, _depth); } uint16 getWidth() const { return _width; } uint16 getHeight() const { return _height; } uint16 getDepth() const { return _depth; } + void setOriginalSize(int width, int height); + int getOriginalWidth() const { return _originalWidth; } + int getOriginalHeight() const { return _originalHeight; } + // The number of faces is mostly used for cube map, and maybe for stereo ? otherwise it's 1 // For cube maps, this means the pixels of the different faces are supposed to be packed back to back in a mip // as if the height was NUM_FACES time bigger. @@ -615,6 +620,8 @@ protected: uint16 _width { 1 }; uint16 _height { 1 }; uint16 _depth { 1 }; + int _originalWidth { 0 }; + int _originalHeight { 0 }; uint16 _numSamples { 1 }; @@ -676,9 +683,10 @@ public: _element(element) {}; - TextureView(const TexturePointer& texture, uint16 subresource) : + TextureView(const TexturePointer& texture, uint16 subresource, std::function textureOperator = nullptr) : _texture(texture), - _subresource(subresource) + _subresource(subresource), + _textureOperator(textureOperator) {}; ~TextureView() {} @@ -689,6 +697,12 @@ public: bool operator !() const { return (!_texture); } bool isValid() const { return bool(_texture); } + + bool isReference() const { return (bool)_textureOperator; } + std::function getTextureOperator() const { return _textureOperator; } + +private: + std::function _textureOperator { nullptr }; }; typedef std::vector TextureViews; @@ -700,16 +714,20 @@ public: void setUrl(const QUrl& url) { _imageUrl = url; } const QUrl& getUrl() const { return _imageUrl; } - const gpu::TexturePointer getGPUTexture() const { return _gpuTexture; } + const gpu::TexturePointer getGPUTexture() const; void setType(int type) { _type = type; } int getType() const { return _type; } - void resetTexture(gpu::TexturePointer texture); + void resetTexture(const gpu::TexturePointer& texture); + void resetTextureOperator(const std::function& textureOperator); bool isDefined() const; + std::function getTextureOperator() const { return _gpuTextureOperator; } protected: gpu::TexturePointer _gpuTexture; + std::function _gpuTextureOperator { nullptr }; + mutable bool _locked { false }; QUrl _imageUrl; int _type { 0 }; }; diff --git a/libraries/graphics/src/graphics/Material.cpp b/libraries/graphics/src/graphics/Material.cpp index 41cd319595..836487de14 100755 --- a/libraries/graphics/src/graphics/Material.cpp +++ b/libraries/graphics/src/graphics/Material.cpp @@ -281,4 +281,33 @@ void MultiMaterial::calculateMaterialInfo() const { } _hasCalculatedTextureInfo = allTextures; } -} \ No newline at end of file +} + +void MultiMaterial::resetReferenceTexturesAndMaterials() { + _referenceTextures.clear(); + _referenceMaterials.clear(); +} + +void MultiMaterial::addReferenceTexture(const std::function& textureOperator) { + _referenceTextures.emplace_back(textureOperator, textureOperator()); +} + +void MultiMaterial::addReferenceMaterial(const std::function& materialOperator) { + _referenceMaterials.emplace_back(materialOperator, materialOperator()); +} + +bool MultiMaterial::anyReferenceMaterialsOrTexturesChanged() const { + for (auto textureOperatorPair : _referenceTextures) { + if (textureOperatorPair.first() != textureOperatorPair.second) { + return true; + } + } + + for (auto materialOperatorPair : _referenceMaterials) { + if (materialOperatorPair.first() != materialOperatorPair.second) { + return true; + } + } + + return false; +} diff --git a/libraries/graphics/src/graphics/Material.h b/libraries/graphics/src/graphics/Material.h index 7a411e5b2c..2eb4e0cbe1 100755 --- a/libraries/graphics/src/graphics/Material.h +++ b/libraries/graphics/src/graphics/Material.h @@ -341,57 +341,57 @@ public: virtual ~Material() = default; Material& operator= (const Material& material); - const MaterialKey& getKey() const { return _key; } + virtual MaterialKey getKey() const { return _key; } static const float DEFAULT_EMISSIVE; void setEmissive(const glm::vec3& emissive, bool isSRGB = true); - glm::vec3 getEmissive(bool SRGB = true) const { return (SRGB ? ColorUtils::tosRGBVec3(_emissive) : _emissive); } + virtual glm::vec3 getEmissive(bool SRGB = true) const { return (SRGB ? ColorUtils::tosRGBVec3(_emissive) : _emissive); } static const float DEFAULT_OPACITY; void setOpacity(float opacity); - float getOpacity() const { return _opacity; } + virtual float getOpacity() const { return _opacity; } static const MaterialKey::OpacityMapMode DEFAULT_OPACITY_MAP_MODE; void setOpacityMapMode(MaterialKey::OpacityMapMode opacityMapMode); - MaterialKey::OpacityMapMode getOpacityMapMode() const; + virtual MaterialKey::OpacityMapMode getOpacityMapMode() const; static const float DEFAULT_OPACITY_CUTOFF; void setOpacityCutoff(float opacityCutoff); - float getOpacityCutoff() const { return _opacityCutoff; } + virtual float getOpacityCutoff() const { return _opacityCutoff; } static const MaterialKey::CullFaceMode DEFAULT_CULL_FACE_MODE; void setCullFaceMode(MaterialKey::CullFaceMode cullFaceMode) { _cullFaceMode = cullFaceMode; } - MaterialKey::CullFaceMode getCullFaceMode() const { return _cullFaceMode; } + virtual MaterialKey::CullFaceMode getCullFaceMode() const { return _cullFaceMode; } void setUnlit(bool value); - bool isUnlit() const { return _key.isUnlit(); } + virtual bool isUnlit() const { return _key.isUnlit(); } static const float DEFAULT_ALBEDO; void setAlbedo(const glm::vec3& albedo, bool isSRGB = true); - glm::vec3 getAlbedo(bool SRGB = true) const { return (SRGB ? ColorUtils::tosRGBVec3(_albedo) : _albedo); } + virtual glm::vec3 getAlbedo(bool SRGB = true) const { return (SRGB ? ColorUtils::tosRGBVec3(_albedo) : _albedo); } static const float DEFAULT_METALLIC; void setMetallic(float metallic); - float getMetallic() const { return _metallic; } + virtual float getMetallic() const { return _metallic; } static const float DEFAULT_ROUGHNESS; void setRoughness(float roughness); - float getRoughness() const { return _roughness; } + virtual float getRoughness() const { return _roughness; } static const float DEFAULT_SCATTERING; void setScattering(float scattering); - float getScattering() const { return _scattering; } + virtual float getScattering() const { return _scattering; } // The texture map to channel association static const int NUM_TEXCOORD_TRANSFORMS { 2 }; void setTextureMap(MapChannel channel, const TextureMapPointer& textureMap); - const TextureMaps& getTextureMaps() const { return _textureMaps; } // FIXME - not thread safe... + virtual TextureMaps getTextureMaps() const { return _textureMaps; } // FIXME - not thread safe... const TextureMapPointer getTextureMap(MapChannel channel) const; // Albedo maps cannot have opacity detected until they are loaded // This method allows const changing of the key/schemaBuffer without touching the map // return true if the opacity changed, flase otherwise - bool resetOpacityMap() const; + virtual bool resetOpacityMap() const; // conversion from legacy material properties to PBR equivalent static float shininessToRoughness(float shininess) { return 1.0f - shininess / 100.0f; } @@ -404,12 +404,12 @@ public: const std::string& getModel() const { return _model; } void setModel(const std::string& model) { _model = model; } - glm::mat4 getTexCoordTransform(uint i) const { return _texcoordTransforms[i]; } + virtual glm::mat4 getTexCoordTransform(uint i) const { return _texcoordTransforms[i]; } void setTexCoordTransform(uint i, const glm::mat4& mat4) { _texcoordTransforms[i] = mat4; } - glm::vec2 getLightmapParams() const { return _lightmapParams; } - glm::vec2 getMaterialParams() const { return _materialParams; } + virtual glm::vec2 getLightmapParams() const { return _lightmapParams; } + virtual glm::vec2 getMaterialParams() const { return _materialParams; } - bool getDefaultFallthrough() const { return _defaultFallthrough; } + virtual bool getDefaultFallthrough() const { return _defaultFallthrough; } void setDefaultFallthrough(bool defaultFallthrough) { _defaultFallthrough = defaultFallthrough; } enum ExtraFlagBit { @@ -430,6 +430,8 @@ public: virtual bool isReady() const { return true; } virtual QString getProceduralString() const { return QString(); } + virtual bool isReference() const { return false; } + static const std::string HIFI_PBR; static const std::string HIFI_SHADER_SIMPLE; @@ -547,12 +549,16 @@ public: void setTexturesLoading(bool value) { _texturesLoading = value; } void setInitialized() { _initialized = true; } - bool shouldUpdate() const { return !_initialized || _needsUpdate || _texturesLoading; } + bool shouldUpdate() const { return !_initialized || _needsUpdate || _texturesLoading || anyReferenceMaterialsOrTexturesChanged(); } int getTextureCount() const { calculateMaterialInfo(); return _textureCount; } size_t getTextureSize() const { calculateMaterialInfo(); return _textureSize; } bool hasTextureInfo() const { return _hasCalculatedTextureInfo; } + void resetReferenceTexturesAndMaterials(); + void addReferenceTexture(const std::function& textureOperator); + void addReferenceMaterial(const std::function& materialOperator); + private: gpu::BufferView _schemaBuffer; graphics::MaterialKey::CullFaceMode _cullFaceMode { graphics::Material::DEFAULT_CULL_FACE_MODE }; @@ -565,6 +571,11 @@ private: mutable int _textureCount { 0 }; mutable bool _hasCalculatedTextureInfo { false }; void calculateMaterialInfo() const; + + bool anyReferenceMaterialsOrTexturesChanged() const; + + std::vector, gpu::TexturePointer>> _referenceTextures; + std::vector, graphics::MaterialPointer>> _referenceMaterials; }; }; diff --git a/libraries/graphics/src/graphics/TextureMap.cpp b/libraries/graphics/src/graphics/TextureMap.cpp index e2f24d68ff..0590203907 100755 --- a/libraries/graphics/src/graphics/TextureMap.cpp +++ b/libraries/graphics/src/graphics/TextureMap.cpp @@ -18,16 +18,12 @@ void TextureMap::setTextureSource(TextureSourcePointer& textureSource) { } bool TextureMap::isDefined() const { - if (_textureSource) { - return _textureSource->isDefined(); - } else { - return false; - } + return _textureSource && _textureSource->isDefined(); } gpu::TextureView TextureMap::getTextureView() const { if (_textureSource) { - return gpu::TextureView(_textureSource->getGPUTexture(), 0); + return gpu::TextureView(_textureSource->getGPUTexture(), 0, _textureSource->getTextureOperator()); } else { return gpu::TextureView(); } diff --git a/libraries/image/src/image/TextureProcessing.h b/libraries/image/src/image/TextureProcessing.h index ff81e98a77..7bf249ebda 100644 --- a/libraries/image/src/image/TextureProcessing.h +++ b/libraries/image/src/image/TextureProcessing.h @@ -4,6 +4,7 @@ // // Created by Clement Brisset on 4/5/2017. // Copyright 2017 High Fidelity, Inc. +// Copyright 2021 Vircadia contributors. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -23,7 +24,7 @@ namespace image { std::function getHDRPackingFunction(); std::function getHDRUnpackingFunction(); - void convertToFloatFromPacked(const unsigned char* source, int width, int height, size_t srcLineByteStride, gpu::Element sourceFormat, + void convertToFloatFromPacked(const unsigned char* source, int width, int height, size_t srcLineByteStride, gpu::Element sourceFormat, glm::vec4* output, size_t outputLinePixelStride); void convertToPackedFromFloat(unsigned char* output, int width, int height, size_t outputLineByteStride, gpu::Element outputFormat, const glm::vec4* source, size_t srcLinePixelStride); @@ -32,8 +33,8 @@ namespace TextureUsage { /*@jsdoc *

Describes the type of texture.

- *

See also: {@link Material} and - * {@link https://docs.vircadia.dev/create/3d-models/pbr-materials-guide.html|PBR Materials Guide}.

+ *

See also: {@link Material} and + * {@link https://docs.vircadia.com/create/3d-models/pbr-materials-guide.html|PBR Materials Guide}.

* * * @@ -102,7 +103,7 @@ gpu::TexturePointer createCubeTextureFromImage(Image&& image, const std::string& gpu::TexturePointer createAmbientCubeTextureAndIrradianceFromImage(Image&& image, const std::string& srcImageName, bool compress, gpu::BackendTarget target, const std::atomic& abortProcessing); gpu::TexturePointer createLightmapTextureFromImage(Image&& image, const std::string& srcImageName, - bool compress, gpu::BackendTarget target, const std::atomic& abortProcessing); + bool compress, gpu::BackendTarget target, const std::atomic& abortProcessing); gpu::TexturePointer process2DTextureColorFromImage(Image&& srcImage, const std::string& srcImageName, bool compress, gpu::BackendTarget target, bool isStrict, const std::atomic& abortProcessing); gpu::TexturePointer process2DTextureNormalMapFromImage(Image&& srcImage, const std::string& srcImageName, bool compress, diff --git a/libraries/material-networking/src/material-networking/TextureCache.cpp b/libraries/material-networking/src/material-networking/TextureCache.cpp index 92e5e0873c..0307e38cc9 100644 --- a/libraries/material-networking/src/material-networking/TextureCache.cpp +++ b/libraries/material-networking/src/material-networking/TextureCache.cpp @@ -98,6 +98,8 @@ static const QUrl HMD_PREVIEW_FRAME_URL("resource://hmdPreviewFrame"); static const float SKYBOX_LOAD_PRIORITY { 10.0f }; // Make sure skybox loads first static const float HIGH_MIPS_LOAD_PRIORITY { 9.0f }; // Make sure high mips loads after skybox but before models +std::function Texture::_unboundTextureForUUIDOperator { nullptr }; + TextureCache::TextureCache() { _ktxCache->initialize(); #if defined(DISABLE_KTX_CACHE) @@ -252,6 +254,10 @@ NetworkTexturePointer TextureCache::getTexture(const QUrl& url, image::TextureUs if (url.scheme() == RESOURCE_SCHEME) { return getResourceTexture(url); } + QString decodedURL = QUrl::fromPercentEncoding(url.toEncoded()); + if (decodedURL.startsWith("{")) { + return getTextureByUUID(decodedURL); + } auto modifiedUrl = url; if (type == image::TextureUsage::SKY_TEXTURE) { QUrlQuery query { url.query() }; @@ -385,8 +391,6 @@ NetworkTexture::NetworkTexture(const NetworkTexture& other) : _type(other._type), _sourceChannel(other._sourceChannel), _currentlyLoadingResourceType(other._currentlyLoadingResourceType), - _originalWidth(other._originalWidth), - _originalHeight(other._originalHeight), _width(other._width), _height(other._height), _maxNumPixels(other._maxNumPixels), @@ -462,13 +466,12 @@ void NetworkTexture::setExtra(void* extra) { void NetworkTexture::setImage(gpu::TexturePointer texture, int originalWidth, int originalHeight) { - _originalWidth = originalWidth; - _originalHeight = originalHeight; // Passing ownership _textureSource->resetTexture(texture); if (texture) { + texture->setOriginalSize(originalWidth, originalHeight); _width = texture->getWidth(); _height = texture->getHeight(); setSize(texture->getStoredSize()); @@ -481,6 +484,12 @@ void NetworkTexture::setImage(gpu::TexturePointer texture, int originalWidth, emit networkTextureCreated(qWeakPointerCast (_self)); } +void NetworkTexture::setImageOperator(std::function textureOperator) { + _textureSource->resetTextureOperator(textureOperator); + finishedLoading((bool)textureOperator); + emit networkTextureCreated(qWeakPointerCast (_self)); +} + gpu::TexturePointer NetworkTexture::getFallbackTexture() const { return getFallbackTextureForType(_type); } @@ -1312,7 +1321,6 @@ void ImageReader::read() { } NetworkTexturePointer TextureCache::getResourceTexture(const QUrl& resourceTextureUrl) { - gpu::TexturePointer texture; if (resourceTextureUrl == SPECTATOR_CAMERA_FRAME_URL) { if (!_spectatorCameraNetworkTexture) { _spectatorCameraNetworkTexture.reset(new NetworkTexture(resourceTextureUrl, true)); @@ -1329,6 +1337,7 @@ NetworkTexturePointer TextureCache::getResourceTexture(const QUrl& resourceTextu _hmdPreviewNetworkTexture.reset(new NetworkTexture(resourceTextureUrl, true)); } if (_hmdPreviewFramebuffer) { + gpu::TexturePointer texture; texture = _hmdPreviewFramebuffer->getRenderBuffer(0); if (texture) { texture->setSource(HMD_PREVIEW_FRAME_URL.toString().toStdString()); @@ -1375,3 +1384,27 @@ void TextureCache::updateSpectatorCameraNetworkTexture() { } } } + +NetworkTexturePointer TextureCache::getTextureByUUID(const QString& uuid) { + QUuid quuid = QUuid(uuid); + if (!quuid.isNull()) { + // We mark this as a resource texture because it's just a reference to another texture. The source + // texture will be marked properly + NetworkTexturePointer toReturn = NetworkTexturePointer(new NetworkTexture(uuid, true)); + toReturn->setImageOperator(Texture::getTextureForUUIDOperator(uuid)); + return toReturn; + } + return NetworkTexturePointer(); +} + +std::function Texture::getTextureForUUIDOperator(const QUuid& uuid) { + if (_unboundTextureForUUIDOperator) { + return std::bind(_unboundTextureForUUIDOperator, uuid); + } + return nullptr; +} + + +void Texture::setUnboundTextureForUUIDOperator(std::function textureForUUIDOperator) { + _unboundTextureForUUIDOperator = textureForUUIDOperator; +} diff --git a/libraries/material-networking/src/material-networking/TextureCache.h b/libraries/material-networking/src/material-networking/TextureCache.h index aab458e184..c0633c2f9b 100644 --- a/libraries/material-networking/src/material-networking/TextureCache.h +++ b/libraries/material-networking/src/material-networking/TextureCache.h @@ -39,6 +39,12 @@ class Texture { public: gpu::TexturePointer getGPUTexture() const { return _textureSource->getGPUTexture(); } gpu::TextureSourcePointer _textureSource; + + static std::function getTextureForUUIDOperator(const QUuid& uuid); + static void setUnboundTextureForUUIDOperator(std::function textureForUUIDOperator); + +private: + static std::function _unboundTextureForUUIDOperator; }; /// A texture loaded from the network. @@ -52,10 +58,10 @@ public: QString getType() const override { return "NetworkTexture"; } - int getOriginalWidth() const { return _originalWidth; } - int getOriginalHeight() const { return _originalHeight; } - int getWidth() const { return _width; } - int getHeight() const { return _height; } + int getOriginalWidth() const { return _textureSource->getGPUTexture() ? _textureSource->getGPUTexture()->getOriginalWidth() : 0; } + int getOriginalHeight() const { return _textureSource->getGPUTexture() ? _textureSource->getGPUTexture()->getOriginalHeight() : 0; } + int getWidth() const { return _textureSource->getGPUTexture() ? _textureSource->getGPUTexture()->getWidth() : 0; } + int getHeight() const { return _textureSource->getGPUTexture() ? _textureSource->getGPUTexture()->getHeight() : 0; } image::TextureUsage::Type getTextureType() const { return _type; } gpu::TexturePointer getFallbackTexture() const; @@ -86,6 +92,7 @@ protected: Q_INVOKABLE void loadTextureContent(const QByteArray& content); Q_INVOKABLE void setImage(gpu::TexturePointer texture, int originalWidth, int originalHeight); + void setImageOperator(std::function textureOperator); Q_INVOKABLE void startRequestForNextMipLevel(); @@ -136,8 +143,6 @@ private: // mip offsets to change. ktx::KTXDescriptorPointer _originalKtxDescriptor; - int _originalWidth { 0 }; - int _originalHeight { 0 }; int _width { 0 }; int _height { 0 }; int _maxNumPixels { ABSOLUTE_MAX_TEXTURE_NUM_PIXELS }; @@ -192,6 +197,8 @@ public: const gpu::FramebufferPointer& getSpectatorCameraFramebuffer(int width, int height); void updateSpectatorCameraNetworkTexture(); + NetworkTexturePointer getTextureByUUID(const QString& uuid); + static const int DEFAULT_SPECTATOR_CAM_WIDTH { 2048 }; static const int DEFAULT_SPECTATOR_CAM_HEIGHT { 1024 }; diff --git a/libraries/midi/src/Midi.h b/libraries/midi/src/Midi.h index c81aa4f04b..aca573f5ce 100644 --- a/libraries/midi/src/Midi.h +++ b/libraries/midi/src/Midi.h @@ -5,6 +5,7 @@ // Created by Burt Sloane // Modified by Bruce Brown // Copyright 2015 High Fidelity, Inc. +// Copyright 2021 Vircadia contributors. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -21,9 +22,9 @@ #include /*@jsdoc - * The Midi API provides the ability to connect Interface with musical instruments and other external or virtual - * devices via the MIDI protocol. For further information and examples, see the tutorial: - * Use MIDI to Control Your Environment. + * The Midi API provides the ability to connect Interface with musical instruments and other external or virtual + * devices via the MIDI protocol. For further information and examples, see the tutorial: + * Use MIDI to Control Your Environment. * *

Note: Only works on Windows.

* @@ -43,7 +44,7 @@ public: void midiHardwareChange(); // relay hardware change to Javascript void sendRawMessage(int device, int raw); // relay midi message to MIDI outputs void sendNote(int status, int note, int velocity); // relay a note to MIDI outputs - void sendMessage(int device, int channel, int type, int note, int velocity); // relay a message to MIDI outputs + void sendMessage(int device, int channel, int type, int note, int velocity); // relay a message to MIDI outputs static void USBchanged(); private: @@ -150,7 +151,7 @@ public slots: /*@jsdoc * Enables or disables repeating all incoming notes to all outputs. (Default is disabled.) * @function Midi.thruModeEnable - * @param {boolean} enable - true to enable repeating all incoming notes to all output, false to + * @param {boolean} enable - true to enable repeating all incoming notes to all output, false to * disable. */ Q_INVOKABLE void thruModeEnable(bool enable); @@ -159,11 +160,11 @@ public slots: /*@jsdoc * Enables or disables broadcasts to all unblocked devices. * @function Midi.broadcastEnable - * @param {boolean} enable - true to have "send" functions broadcast to all devices, false to + * @param {boolean} enable - true to have "send" functions broadcast to all devices, false to * have them send to specific output devices. */ Q_INVOKABLE void broadcastEnable(bool enable); - + /// filter by event types diff --git a/libraries/networking/src/AddressManager.cpp b/libraries/networking/src/AddressManager.cpp index f0fa1365c4..96d72cabaf 100644 --- a/libraries/networking/src/AddressManager.cpp +++ b/libraries/networking/src/AddressManager.cpp @@ -39,7 +39,7 @@ const QString SETTINGS_CURRENT_ADDRESS_KEY = "address"; const QString DEFAULT_VIRCADIA_ADDRESS = (!BuildInfo::PRELOADED_STARTUP_LOCATION.isEmpty()) ? BuildInfo::PRELOADED_STARTUP_LOCATION : NetworkingConstants::DEFAULT_VIRCADIA_ADDRESS; -const QString DEFAULT_HOME_ADDRESS = (!BuildInfo::PRELOADED_STARTUP_LOCATION.isEmpty()) +const QString DEFAULT_HOME_ADDRESS = (!BuildInfo::PRELOADED_STARTUP_LOCATION.isEmpty()) ? BuildInfo::PRELOADED_STARTUP_LOCATION : NetworkingConstants::DEFAULT_VIRCADIA_ADDRESS; @@ -56,7 +56,7 @@ QString AddressManager::getProtocol() const { QUrl AddressManager::currentAddress(bool domainOnly) const { QUrl hifiURL = _domainURL; - if (!domainOnly && hifiURL.scheme() == URL_SCHEME_HIFI) { + if (!domainOnly && hifiURL.scheme() == URL_SCHEME_VIRCADIA) { hifiURL.setPath(currentPath()); } @@ -65,7 +65,7 @@ QUrl AddressManager::currentAddress(bool domainOnly) const { QUrl AddressManager::currentFacingAddress() const { auto hifiURL = currentAddress(); - if (hifiURL.scheme() == URL_SCHEME_HIFI) { + if (hifiURL.scheme() == URL_SCHEME_VIRCADIA) { hifiURL.setPath(currentFacingPath()); } @@ -77,7 +77,7 @@ QUrl AddressManager::currentShareableAddress(bool domainOnly) const { // if we have a shareable place name use that instead of whatever the current host is QUrl hifiURL; - hifiURL.setScheme(URL_SCHEME_HIFI); + hifiURL.setScheme(URL_SCHEME_VIRCADIA); hifiURL.setHost(_shareablePlaceName); if (!domainOnly) { @@ -94,7 +94,7 @@ QUrl AddressManager::currentPublicAddress(bool domainOnly) const { // return an address that can be used by others to visit this client's current location. If // in a serverless domain (which can't be visited) return an empty URL. QUrl shareableAddress = currentShareableAddress(domainOnly); - if (shareableAddress.scheme() != URL_SCHEME_HIFI) { + if (shareableAddress.scheme() != URL_SCHEME_VIRCADIA) { return QUrl(); // file: urls aren't public } return shareableAddress; @@ -103,7 +103,7 @@ QUrl AddressManager::currentPublicAddress(bool domainOnly) const { QUrl AddressManager::currentFacingShareableAddress() const { auto hifiURL = currentShareableAddress(); - if (hifiURL.scheme() == URL_SCHEME_HIFI) { + if (hifiURL.scheme() == URL_SCHEME_VIRCADIA) { hifiURL.setPath(currentFacingPath()); } @@ -114,7 +114,7 @@ QUrl AddressManager::currentFacingPublicAddress() const { // return an address that can be used by others to visit this client's current location. If // in a serverless domain (which can't be visited) return an empty URL. QUrl shareableAddress = currentFacingShareableAddress(); - if (shareableAddress.scheme() != URL_SCHEME_HIFI) { + if (shareableAddress.scheme() != URL_SCHEME_VIRCADIA) { return QUrl(); // file: urls aren't public } return shareableAddress; @@ -165,7 +165,7 @@ void AddressManager::storeCurrentAddress() { if (url.scheme() == HIFI_URL_SCHEME_FILE || url.scheme() == HIFI_URL_SCHEME_HTTP || url.scheme() == HIFI_URL_SCHEME_HTTPS || - (url.scheme() == URL_SCHEME_HIFI && !url.host().isEmpty())) { + (url.scheme() == URL_SCHEME_VIRCADIA && !url.host().isEmpty())) { // TODO -- once Octree::readFromURL no-longer takes over the main event-loop, serverless-domain urls can // be loaded over http(s) // url.scheme() == HIFI_URL_SCHEME_HTTP || @@ -242,7 +242,7 @@ const JSONCallbackParameters& AddressManager::apiCallbackParameters() { return callbackParams; } -bool AddressManager::handleUrl(const QUrl& lookupUrlIn, LookupTrigger trigger) { +bool AddressManager::handleUrl(const QUrl& lookupUrlIn, LookupTrigger trigger, const QString& lookupUrlInString) { static QString URL_TYPE_USER = "user"; static QString URL_TYPE_DOMAIN_ID = "domain_id"; static QString URL_TYPE_PLACE = "place"; @@ -258,24 +258,32 @@ bool AddressManager::handleUrl(const QUrl& lookupUrlIn, LookupTrigger trigger) { if (lookupUrl.scheme().isEmpty() && !lookupUrl.path().startsWith("/")) { // 'urls' without schemes are taken as domain names, as opposed to // simply a path portion of a url, so we need to set the scheme - lookupUrl.setScheme(URL_SCHEME_HIFI); + lookupUrl.setScheme(URL_SCHEME_VIRCADIA); } static const QRegExp PORT_REGEX = QRegExp("\\d{1,5}(\\/.*)?"); if(!lookupUrl.scheme().isEmpty() && lookupUrl.host().isEmpty() && PORT_REGEX.exactMatch(lookupUrl.path())) { // this is in the form somewhere:, convert it to hifi://somewhere: - lookupUrl = QUrl(URL_SCHEME_HIFI + "://" + lookupUrl.toString()); + lookupUrl = QUrl(URL_SCHEME_VIRCADIA + "://" + lookupUrl.toString()); } // it should be noted that url's in the form // somewhere: are not valid, as that // would indicate that the scheme is 'somewhere' // use hifi://somewhere: instead - if (lookupUrl.scheme() == URL_SCHEME_HIFI) { + if (lookupUrl.scheme() == URL_SCHEME_VIRCADIA || lookupUrlInString.startsWith(URL_SCHEME_VIRCADIA + "://")) { + QString lookupUrlString; + + if (lookupUrlInString.startsWith(URL_SCHEME_VIRCADIA + "://")) { + lookupUrlString = lookupUrlInString; + } else { + lookupUrlString = lookupUrl.toString(QUrl::FullyEncoded); + } + if (lookupUrl.host().isEmpty()) { // this was in the form hifi:/somewhere or hifi:somewhere. Fix it by making it hifi://somewhere - static const QRegExp HIFI_SCHEME_REGEX = QRegExp(URL_SCHEME_HIFI + ":\\/{0,2}", Qt::CaseInsensitive); - lookupUrl = QUrl(lookupUrl.toString().replace(HIFI_SCHEME_REGEX, URL_SCHEME_HIFI + "://")); + static const QRegExp HIFI_SCHEME_REGEX = QRegExp(URL_SCHEME_VIRCADIA + ":\\/{0,2}", Qt::CaseInsensitive); + lookupUrl = QUrl(lookupUrl.toString().replace(HIFI_SCHEME_REGEX, URL_SCHEME_VIRCADIA + "://")); } DependencyManager::get()->flagTimeForConnectionStep(LimitedNodeList::ConnectionStep::LookupAddress); @@ -340,6 +348,8 @@ bool AddressManager::handleUrl(const QUrl& lookupUrlIn, LookupTrigger trigger) { // try to look up the domain ID on the metaverse API attemptDomainIDLookup(lookupUrl.host(), lookupUrl.path(), trigger); } else { + // wasn't an address - lookup the place name + // we may have a path that defines a relative viewpoint - pass that through the lookup so we can go to it after UserActivityLogger::getInstance().wentTo(trigger, URL_TYPE_PLACE, lookupUrl.toString()); // save the last visited domain URL. @@ -348,10 +358,26 @@ bool AddressManager::handleUrl(const QUrl& lookupUrlIn, LookupTrigger trigger) { // store this place name as the previous lookup in case we fail to connect and want to refresh API info _previousAPILookup = lookupUrl; - // wasn't an address - lookup the place name - // we may have a path that defines a relative viewpoint - pass that through the lookup so we can go to it after - if (!lookupUrl.host().isNull() && !lookupUrl.host().isEmpty()) { - attemptPlaceNameLookup(lookupUrl.host(), lookupUrl.path(), trigger); + // Let's convert this to a QString for processing in case there are spaces in it. + if (lookupUrlString.contains(URL_SCHEME_VIRCADIA + "://", Qt::CaseInsensitive)) { + lookupUrlString = lookupUrlString.replace((URL_SCHEME_VIRCADIA + "://"), ""); + } else if (lookupUrlString.contains(URL_SCHEME_VIRCADIA + ":/", Qt::CaseInsensitive)) { + lookupUrlString = lookupUrlString.replace((URL_SCHEME_VIRCADIA + ":/"), ""); + } else if (lookupUrlString.contains(URL_SCHEME_VIRCADIA + ":", Qt::CaseInsensitive)) { + lookupUrlString = lookupUrlString.replace((URL_SCHEME_VIRCADIA + ":"), ""); + } + + // Get the path and then strip it out. + QString lookupUrlStringPath; + + int index = lookupUrlString.indexOf('/'); + if (index != -1) { + lookupUrlStringPath = lookupUrlString.mid(index); + lookupUrlString.replace(lookupUrlStringPath, ""); + } + + if (!lookupUrlString.isEmpty()) { + attemptPlaceNameLookup(lookupUrlString, lookupUrlStringPath, trigger); } } } @@ -371,7 +397,7 @@ bool AddressManager::handleUrl(const QUrl& lookupUrlIn, LookupTrigger trigger) { return true; } else if (lookupUrl.scheme() == HIFI_URL_SCHEME_FILE || lookupUrl.scheme() == HIFI_URL_SCHEME_HTTPS || lookupUrl.scheme() == HIFI_URL_SCHEME_HTTP) { - + // Save the last visited domain URL. _lastVisitedURL = lookupUrl; @@ -412,13 +438,13 @@ bool isPossiblePlaceName(QString possiblePlaceName) { } void AddressManager::handleLookupString(const QString& lookupString, bool fromSuggestions) { + QString trimmedString = lookupString.trimmed(); - QString sanitizedString = lookupString.trimmed(); - if (!sanitizedString.isEmpty()) { + if (!trimmedString.isEmpty()) { resetConfirmConnectWithoutAvatarEntities(); // make this a valid hifi URL and handle it off to handleUrl - handleUrl(sanitizedString, fromSuggestions ? Suggestions : UserInput); + handleUrl(trimmedString, fromSuggestions ? Suggestions : UserInput, trimmedString); } } @@ -494,7 +520,7 @@ void AddressManager::goToAddressFromObject(const QVariantMap& dataObject, const qCDebug(networking) << "Possible domain change required to connect to" << domainHostname << "on" << domainPort; QUrl domainURL; - domainURL.setScheme(URL_SCHEME_HIFI); + domainURL.setScheme(URL_SCHEME_VIRCADIA); domainURL.setHost(domainHostname); if (domainPort > 0) { domainURL.setPort(domainPort); @@ -606,8 +632,6 @@ void AddressManager::handleAPIError(QNetworkReply* errorReply) { void AddressManager::attemptPlaceNameLookup(const QString& lookupString, const QString& overridePath, LookupTrigger trigger) { // assume this is a place name and see if we can get any info on it - QString placeName = QUrl::toPercentEncoding(lookupString); - QVariantMap requestParams; // if the user asked for a specific path with this lookup then keep it with the request so we can use it later @@ -618,7 +642,7 @@ void AddressManager::attemptPlaceNameLookup(const QString& lookupString, const Q // remember how this lookup was triggered for history storage handling later requestParams.insert(LOOKUP_TRIGGER_KEY, static_cast(trigger)); - DependencyManager::get()->sendRequest(GET_PLACE.arg(placeName), + DependencyManager::get()->sendRequest(GET_PLACE.arg(lookupString), AccountManagerAuth::None, QNetworkAccessManager::GetOperation, apiCallbackParameters(), @@ -667,7 +691,7 @@ bool AddressManager::handleNetworkAddress(const QString& lookupString, LookupTri emit lookupResultsFinished(); QUrl domainURL; - domainURL.setScheme(URL_SCHEME_HIFI); + domainURL.setScheme(URL_SCHEME_VIRCADIA); domainURL.setHost(domainIPString); if (domainPort > 0) { domainURL.setPort(domainPort); @@ -690,7 +714,7 @@ bool AddressManager::handleNetworkAddress(const QString& lookupString, LookupTri emit lookupResultsFinished(); QUrl domainURL; - domainURL.setScheme(URL_SCHEME_HIFI); + domainURL.setScheme(URL_SCHEME_VIRCADIA); domainURL.setHost(domainHostname); if (domainPort > 0) { domainURL.setPort(domainPort); @@ -823,7 +847,7 @@ bool AddressManager::setHost(const QString& host, LookupTrigger trigger, quint16 addCurrentAddressToHistory(trigger); _domainURL = QUrl(); - _domainURL.setScheme(URL_SCHEME_HIFI); + _domainURL.setScheme(URL_SCHEME_VIRCADIA); _domainURL.setHost(host); if (port > 0) { _domainURL.setPort(port); @@ -860,7 +884,7 @@ bool AddressManager::setDomainInfo(const QUrl& domainURL, LookupTrigger trigger) // clear any current place information _rootPlaceID = QUuid(); - if (_domainURL.scheme() == URL_SCHEME_HIFI) { + if (_domainURL.scheme() == URL_SCHEME_VIRCADIA) { qCDebug(networking) << "Possible domain change required to connect to domain at" << hostname << "on" << port; } else { qCDebug(networking) << "Possible domain change required to serverless domain: " << domainURL.toString(); diff --git a/libraries/networking/src/AddressManager.h b/libraries/networking/src/AddressManager.h index e8793edc1d..0a8f4591ad 100644 --- a/libraries/networking/src/AddressManager.h +++ b/libraries/networking/src/AddressManager.h @@ -4,6 +4,7 @@ // // Created by Stephen Birarda on 2014-09-10. // Copyright 2014 High Fidelity, Inc. +// Copyright 2021 Vircadia contributors. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -35,7 +36,7 @@ const QString GET_PLACE = "/api/v1/places/%1"; * The location API provides facilities related to your current location in the metaverse. * *

Getter/Setter

- *

You can get and set your current metaverse address by directly reading a string value from and writing a string value to + *

You can get and set your current metaverse address by directly reading a string value from and writing a string value to * the location object. This is an alternative to using the location.href property or other object * functions.

* @@ -53,12 +54,12 @@ const QString GET_PLACE = "/api/v1/places/%1"; * localhost, or an IP address). Is blank if you're in a serverless domain. * Read-only. * @property {string} href - Your current metaverse address (e.g., "hifi://domainname/15,-10,26/0,0,0,1") - * regardless of whether or not you're connected to the domain. Starts with "file:///" if you're in a + * regardless of whether or not you're connected to the domain. Starts with "file:///" if you're in a * serverless domain. * Read-only. * @property {boolean} isConnected - true if you're connected to the domain in your current href * metaverse address, otherwise false. - * @property {string} pathname - The location and orientation in your current href metaverse address + * @property {string} pathname - The location and orientation in your current href metaverse address * (e.g., "/15,-10,26/0,0,0,1"). * Read-only. * @property {string} placename - The place name in your current href metaverse address @@ -77,7 +78,7 @@ const QString GET_PLACE = "/api/v1/places/%1"; * @hifi-client-entity * @hifi-avatar * - * @deprecated This API is deprecated and will be removed. Use the {@link location} or {@link Window|Window.location} APIs + * @deprecated This API is deprecated and will be removed. Use the {@link location} or {@link Window|Window.location} APIs * instead. * * @property {Uuid} domainID - A UUID uniquely identifying the domain you're visiting. Is {@link Uuid(0)|Uuid.NULL} if you're not @@ -248,17 +249,17 @@ public slots: /*@jsdoc * Takes you to a specified metaverse address. * @function location.handleLookupString - * @param {string} address - The address to go to: a "hifi://" address, an IP address (e.g., - * "127.0.0.1" or "localhost"), a file:/// address, a domain name, a named path - * on a domain (starts with "/"), a position or position and orientation, or a user (starts with + * @param {string} address - The address to go to: a "hifi://" address, an IP address (e.g., + * "127.0.0.1" or "localhost"), a file:/// address, a domain name, a named path + * on a domain (starts with "/"), a position or position and orientation, or a user (starts with * "@"). - * @param {boolean} [fromSuggestions=false] - Set to true if the address is obtained from the "Goto" dialog. - * Helps ensure that user's location history is correctly maintained. + * @param {boolean} [fromSuggestions=false] - Set to true if the address is obtained from the "Explore" app. + * Helps ensure that the user's location history is correctly maintained. */ void handleLookupString(const QString& lookupString, bool fromSuggestions = false); /*@jsdoc - * Takes you to a position and orientation resulting from a lookup for a named path in the domain (set in the domain + * Takes you to a position and orientation resulting from a lookup for a named path in the domain (set in the domain * server's settings). * @function location.goToViewpointForPath * @param {string} path - The position and orientation corresponding to the named path. @@ -292,7 +293,7 @@ public slots: * location history is correctly maintained. */ void goToLocalSandbox(QString path = "", LookupTrigger trigger = LookupTrigger::StartupFromSettings) { - handleUrl(SANDBOX_HIFI_ADDRESS + path, trigger); + handleUrl(SANDBOX_HIFI_ADDRESS + path, trigger); } /*@jsdoc @@ -307,7 +308,7 @@ public slots: * Takes you to the specified user's location. * @function location.goToUser * @param {string} username - The user's username. - * @param {boolean} [matchOrientation=true] - If true then go to a location just in front of the user and turn + * @param {boolean} [matchOrientation=true] - If true then go to a location just in front of the user and turn * to face them, otherwise go to the user's exact location and orientation. */ void goToUser(const QString& username, bool shouldMatchOrientation = true); @@ -348,7 +349,7 @@ public slots: void copyAddress(); /*@jsdoc - * Copies your current metaverse location and orientation (i.e., location.pathname property value) to the OS + * Copies your current metaverse location and orientation (i.e., location.pathname property value) to the OS * clipboard. * @function location.copyPath */ @@ -374,7 +375,7 @@ signals: void lookupResultsFinished(); /*@jsdoc - * Triggered when looking up the details of a metaverse user or location to go to has completed and the domain or user is + * Triggered when looking up the details of a metaverse user or location to go to has completed and the domain or user is * offline. * @function location.lookupResultIsOffline * @returns {Signal} @@ -390,10 +391,10 @@ signals: void lookupResultIsNotFound(); /*@jsdoc - * Triggered when a request is made to go to an IP address. + * Triggered when a request is made to go to a URL or IP address. * @function location.possibleDomainChangeRequired - * @param {Url} domainURL - URL for domain - * @param {Uuid} domainID - The UUID of the domain to go to. + * @param {string} domainURL - The URL of the domain. + * @param {Uuid} domainID - The UUID of the domain to go to. May be {@link Uuid|Uuid.NULL} if not yet known. * @returns {Signal} */ // No example because this function isn't typically used in scripts. @@ -415,9 +416,9 @@ signals: * @function location.locationChangeRequired * @param {Vec3} position - The position to go to. * @param {boolean} hasOrientationChange - If true then a new orientation has been requested. - * @param {Quat} orientation - The orientation to change to. Is {@link Quat(0)|Quat.IDENTITY} if + * @param {Quat} orientation - The orientation to change to. Is {@link Quat(0)|Quat.IDENTITY} if * hasOrientationChange is false. - * @param {boolean} shouldFaceLocation - If true then the request is to go to a position near that specified + * @param {boolean} shouldFaceLocation - If true then the request is to go to a position near that specified * and orient your avatar to face it. For example when you visit someone from the "People" dialog. * @returns {Signal} * @example
@@ -468,7 +469,7 @@ signals: * Triggered when there's a change in whether or not there's a previous location that can be navigated to using * {@link location.goBack|goBack}. (Reflects changes in the state of the "Goto" dialog's back arrow.) * @function location.goBackPossible - * @param {boolean} isPossible - true if there's a previous location to navigate to, otherwise + * @param {boolean} isPossible - true if there's a previous location to navigate to, otherwise * false. * @returns {Signal} * @example @@ -511,7 +512,7 @@ private: const JSONCallbackParameters& apiCallbackParameters(); - bool handleUrl(const QUrl& lookupUrl, LookupTrigger trigger = UserInput); + bool handleUrl(const QUrl& lookupUrl, LookupTrigger trigger = UserInput, const QString& lookupUrlInString = ""); bool handleNetworkAddress(const QString& lookupString, LookupTrigger trigger, bool& hostChanged); void handlePath(const QString& path, LookupTrigger trigger, bool wasPathOnly = false); diff --git a/libraries/networking/src/DomainHandler.cpp b/libraries/networking/src/DomainHandler.cpp index 5a1d8fb4a0..4ba5565a74 100644 --- a/libraries/networking/src/DomainHandler.cpp +++ b/libraries/networking/src/DomainHandler.cpp @@ -26,7 +26,7 @@ #include "AddressManager.h" #include "Assignment.h" #include "DomainAccountManager.h" -#include "HifiSockAddr.h" +#include "SockAddr.h" #include "NodeList.h" #include "udt/Packet.h" #include "udt/PacketHeaders.h" @@ -37,7 +37,7 @@ DomainHandler::DomainHandler(QObject* parent) : QObject(parent), - _sockAddr(HifiSockAddr(QHostAddress::Null, DEFAULT_DOMAIN_SERVER_PORT)), + _sockAddr(SockAddr(QHostAddress::Null, DEFAULT_DOMAIN_SERVER_PORT)), _icePeer(this), _settingsTimer(this), _apiRefreshTimer(this) @@ -133,7 +133,7 @@ void DomainHandler::hardReset(QString reason) { qCDebug(networking) << "Hard reset in NodeList DomainHandler."; _pendingDomainID = QUuid(); - _iceServerSockAddr = HifiSockAddr(); + _iceServerSockAddr = SockAddr(); _sockAddr.clear(); _domainURL = QUrl(); @@ -170,7 +170,7 @@ void DomainHandler::setErrorDomainURL(const QUrl& url) { return; } -void DomainHandler::setSockAddr(const HifiSockAddr& sockAddr, const QString& hostname) { +void DomainHandler::setSockAddr(const SockAddr& sockAddr, const QString& hostname) { if (_sockAddr != sockAddr) { // we should reset on a sockAddr change hardReset("Changing domain sockAddr"); @@ -184,7 +184,7 @@ void DomainHandler::setSockAddr(const HifiSockAddr& sockAddr, const QString& hos // some callers may pass a hostname, this is not to be used for lookup but for DTLS certificate verification _domainURL = QUrl(); - _domainURL.setScheme(URL_SCHEME_HIFI); + _domainURL.setScheme(URL_SCHEME_VIRCADIA); _domainURL.setHost(hostname); _domainURL.setPort(_sockAddr.getPort()); } @@ -199,7 +199,7 @@ void DomainHandler::setUUID(const QUuid& uuid) { void DomainHandler::setURLAndID(QUrl domainURL, QUuid domainID) { _pendingDomainID = domainID; - if (domainURL.scheme() != URL_SCHEME_HIFI) { + if (domainURL.scheme() != URL_SCHEME_VIRCADIA) { _sockAddr.clear(); // if this is a file URL we need to see if it has a ~ for us to expand @@ -215,7 +215,7 @@ void DomainHandler::setURLAndID(QUrl domainURL, QUuid domainID) { // if it's in the error state, reset and try again. if (_domainURL != domainURL - || (_sockAddr.getPort() != domainPort && domainURL.scheme() == URL_SCHEME_HIFI) + || (_sockAddr.getPort() != domainPort && domainURL.scheme() == URL_SCHEME_VIRCADIA) || isServerless() // For reloading content in serverless domain. || _isInErrorState) { // re-set the domain info so that auth information is reloaded @@ -230,7 +230,7 @@ void DomainHandler::setURLAndID(QUrl domainURL, QUuid domainID) { qCDebug(networking) << "Updated domain hostname to" << domainURL.host(); if (!domainURL.host().isEmpty()) { - if (domainURL.scheme() == URL_SCHEME_HIFI) { + if (domainURL.scheme() == URL_SCHEME_VIRCADIA) { // re-set the sock addr to null and fire off a lookup of the IP address for this domain-server's hostname qCDebug(networking, "Looking up DS hostname %s.", domainURL.host().toLocal8Bit().constData()); QHostInfo::lookupHost(domainURL.host(), this, SLOT(completedHostnameLookup(const QHostInfo&))); @@ -280,9 +280,9 @@ void DomainHandler::setIceServerHostnameAndID(const QString& iceServerHostname, _pendingDomainID = id; - HifiSockAddr* replaceableSockAddr = &_iceServerSockAddr; - replaceableSockAddr->~HifiSockAddr(); - replaceableSockAddr = new (replaceableSockAddr) HifiSockAddr(iceServerHostname, ICE_SERVER_DEFAULT_PORT); + SockAddr* replaceableSockAddr = &_iceServerSockAddr; + replaceableSockAddr->~SockAddr(); + replaceableSockAddr = new (replaceableSockAddr) SockAddr(iceServerHostname, ICE_SERVER_DEFAULT_PORT); _iceServerSockAddr.setObjectName("IceServer"); auto nodeList = DependencyManager::get(); @@ -291,7 +291,7 @@ void DomainHandler::setIceServerHostnameAndID(const QString& iceServerHostname, if (_iceServerSockAddr.getAddress().isNull()) { // connect to lookup completed for ice-server socket so we can request a heartbeat once hostname is looked up - connect(&_iceServerSockAddr, &HifiSockAddr::lookupCompleted, this, &DomainHandler::completedIceServerHostnameLookup); + connect(&_iceServerSockAddr, &SockAddr::lookupCompleted, this, &DomainHandler::completedIceServerHostnameLookup); } else { completedIceServerHostnameLookup(); } @@ -303,7 +303,7 @@ void DomainHandler::setIceServerHostnameAndID(const QString& iceServerHostname, void DomainHandler::activateICELocalSocket() { DependencyManager::get()->flagTimeForConnectionStep(LimitedNodeList::ConnectionStep::SetDomainSocket); _sockAddr = _icePeer.getLocalSocket(); - _domainURL.setScheme(URL_SCHEME_HIFI); + _domainURL.setScheme(URL_SCHEME_VIRCADIA); _domainURL.setHost(_sockAddr.getAddress().toString()); emit domainURLChanged(_domainURL); emit completedSocketDiscovery(); @@ -312,7 +312,7 @@ void DomainHandler::activateICELocalSocket() { void DomainHandler::activateICEPublicSocket() { DependencyManager::get()->flagTimeForConnectionStep(LimitedNodeList::ConnectionStep::SetDomainSocket); _sockAddr = _icePeer.getPublicSocket(); - _domainURL.setScheme(URL_SCHEME_HIFI); + _domainURL.setScheme(URL_SCHEME_VIRCADIA); _domainURL.setHost(_sockAddr.getAddress().toString()); emit domainURLChanged(_domainURL); emit completedSocketDiscovery(); @@ -369,7 +369,7 @@ void DomainHandler::setIsConnected(bool isConnected) { // FIXME: Reinstate the requestDomainSettings() call here in version 2021.2.0 instead of having it in // NodeList::processDomainServerList(). /* - if (_domainURL.scheme() == URL_SCHEME_HIFI && !_domainURL.host().isEmpty()) { + if (_domainURL.scheme() == URL_SCHEME_VIRCADIA && !_domainURL.host().isEmpty()) { // we've connected to new domain - time to ask it for global settings requestDomainSettings(); } @@ -458,7 +458,7 @@ void DomainHandler::processSettingsPacketList(QSharedPointer pa } void DomainHandler::processICEPingReplyPacket(QSharedPointer message) { - const HifiSockAddr& senderSockAddr = message->getSenderSockAddr(); + const SockAddr& senderSockAddr = message->getSenderSockAddr(); qCDebug(networking_ice) << "Received reply from domain-server on" << senderSockAddr; if (getIP().isNull()) { diff --git a/libraries/networking/src/DomainHandler.h b/libraries/networking/src/DomainHandler.h index a56d3162bd..7553168b09 100644 --- a/libraries/networking/src/DomainHandler.h +++ b/libraries/networking/src/DomainHandler.h @@ -25,7 +25,7 @@ #include #include -#include "HifiSockAddr.h" +#include "SockAddr.h" #include "NetworkPeer.h" #include "NLPacket.h" #include "NLPacketList.h" @@ -109,8 +109,8 @@ public: const QHostAddress& getIP() const { return _sockAddr.getAddress(); } void setIPToLocalhost() { _sockAddr.setAddress(QHostAddress(QHostAddress::LocalHost)); } - const HifiSockAddr& getSockAddr() const { return _sockAddr; } - void setSockAddr(const HifiSockAddr& sockAddr, const QString& hostname); + const SockAddr& getSockAddr() const { return _sockAddr; } + void setSockAddr(const SockAddr& sockAddr, const QString& hostname); unsigned short getPort() const { return _sockAddr.getPort(); } void setPort(quint16 port) { _sockAddr.setPort(port); } @@ -126,7 +126,7 @@ public: const QUuid& getICEClientID() const { return _iceClientID; } bool requiresICE() const { return !_iceServerSockAddr.isNull(); } - const HifiSockAddr& getICEServerSockAddr() const { return _iceServerSockAddr; } + const SockAddr& getICEServerSockAddr() const { return _iceServerSockAddr; } NetworkPeer& getICEPeer() { return _icePeer; } void activateICELocalSocket(); void activateICEPublicSocket(); @@ -137,7 +137,7 @@ public: void setCanConnectWithoutAvatarEntities(bool canConnect); bool canConnectWithoutAvatarEntities(); - bool isServerless() const { return _domainURL.scheme() != URL_SCHEME_HIFI; } + bool isServerless() const { return _domainURL.scheme() != URL_SCHEME_VIRCADIA; } bool getInterstitialModeEnabled() const; void setInterstitialModeEnabled(bool enableInterstitialMode); @@ -288,12 +288,12 @@ private: Node::LocalID _localID; QUrl _domainURL; QUrl _errorDomainURL; - HifiSockAddr _sockAddr; + SockAddr _sockAddr; QUuid _assignmentUUID; QUuid _connectionToken; QUuid _pendingDomainID; // ID of domain being connected to, via ICE or direct connection QUuid _iceClientID; - HifiSockAddr _iceServerSockAddr; + SockAddr _iceServerSockAddr; NetworkPeer _icePeer; bool _isConnected { false }; bool _haveAskedConnectWithoutAvatarEntities { false }; diff --git a/libraries/networking/src/LimitedNodeList.cpp b/libraries/networking/src/LimitedNodeList.cpp index 653611ae8c..65e391d467 100644 --- a/libraries/networking/src/LimitedNodeList.cpp +++ b/libraries/networking/src/LimitedNodeList.cpp @@ -4,6 +4,7 @@ // // Created by Stephen Birarda on 2/15/13. // Copyright 2013 High Fidelity, Inc. +// Copyright 2021 Vircadia contributors. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -33,7 +34,7 @@ #include "AccountManager.h" #include "AssetClient.h" #include "Assignment.h" -#include "HifiSockAddr.h" +#include "SockAddr.h" #include "NetworkLogging.h" #include "udt/Packet.h" #include "HMACAuth.h" @@ -103,7 +104,7 @@ LimitedNodeList::LimitedNodeList(int socketListenPort, int dtlsListenPort) : _nodeSocket.setMessageHandler([this](std::unique_ptr packet) { _packetReceiver->handleVerifiedMessagePacket(std::move(packet)); }); - _nodeSocket.setMessageFailureHandler([this](HifiSockAddr from, + _nodeSocket.setMessageFailureHandler([this](SockAddr from, udt::Packet::MessageNumber messageNumber) { _packetReceiver->handleMessageFailure(from, messageNumber); }); @@ -120,7 +121,7 @@ LimitedNodeList::LimitedNodeList(int socketListenPort, int dtlsListenPort) : if (_stunSockAddr.getAddress().isNull()) { // we don't know the stun server socket yet, add it to unfiltered once known - connect(&_stunSockAddr, &HifiSockAddr::lookupCompleted, this, &LimitedNodeList::addSTUNHandlerToUnfiltered); + connect(&_stunSockAddr, &SockAddr::lookupCompleted, this, &LimitedNodeList::addSTUNHandlerToUnfiltered); } else { // we know the stun server socket, add it to unfiltered now addSTUNHandlerToUnfiltered(); @@ -248,11 +249,11 @@ bool LimitedNodeList::packetVersionMatch(const udt::Packet& packet) { if (headerVersion != versionForPacketType(headerType)) { static QMultiHash sourcedVersionDebugSuppressMap; - static QMultiHash versionDebugSuppressMap; + static QMultiHash versionDebugSuppressMap; bool hasBeenOutput = false; QString senderString; - const HifiSockAddr& senderSockAddr = packet.getSenderSockAddr(); + const SockAddr& senderSockAddr = packet.getSenderSockAddr(); QUuid sourceID; if (PacketTypeEnum::getNonSourcedPackets().contains(headerType)) { @@ -413,7 +414,7 @@ qint64 LimitedNodeList::sendUnreliablePacket(const NLPacket& packet, const Node& return sendUnreliablePacket(packet, *destinationNode.getActiveSocket(), destinationNode.getAuthenticateHash()); } -qint64 LimitedNodeList::sendUnreliablePacket(const NLPacket& packet, const HifiSockAddr& sockAddr, +qint64 LimitedNodeList::sendUnreliablePacket(const NLPacket& packet, const SockAddr& sockAddr, HMACAuth* hmacAuth) { Q_ASSERT(!packet.isPartOfMessage()); Q_ASSERT_X(!packet.isReliable(), "LimitedNodeList::sendUnreliablePacket", @@ -446,7 +447,7 @@ qint64 LimitedNodeList::sendPacket(std::unique_ptr packet, const Node& } } -qint64 LimitedNodeList::sendPacket(std::unique_ptr packet, const HifiSockAddr& sockAddr, +qint64 LimitedNodeList::sendPacket(std::unique_ptr packet, const SockAddr& sockAddr, HMACAuth* hmacAuth) { Q_ASSERT(!packet->isPartOfMessage()); if (packet->isReliable()) { @@ -497,7 +498,7 @@ qint64 LimitedNodeList::sendUnreliableUnorderedPacketList(NLPacketList& packetLi } } -qint64 LimitedNodeList::sendUnreliableUnorderedPacketList(NLPacketList& packetList, const HifiSockAddr& sockAddr, +qint64 LimitedNodeList::sendUnreliableUnorderedPacketList(NLPacketList& packetList, const SockAddr& sockAddr, HMACAuth* hmacAuth) { qint64 bytesSent = 0; @@ -511,7 +512,7 @@ qint64 LimitedNodeList::sendUnreliableUnorderedPacketList(NLPacketList& packetLi return bytesSent; } -qint64 LimitedNodeList::sendPacketList(std::unique_ptr packetList, const HifiSockAddr& sockAddr) { +qint64 LimitedNodeList::sendPacketList(std::unique_ptr packetList, const SockAddr& sockAddr) { // close the last packet in the list packetList->closeCurrentPacket(); @@ -543,7 +544,7 @@ qint64 LimitedNodeList::sendPacketList(std::unique_ptr packetList, } qint64 LimitedNodeList::sendPacket(std::unique_ptr packet, const Node& destinationNode, - const HifiSockAddr& overridenSockAddr) { + const SockAddr& overridenSockAddr) { if (overridenSockAddr.isNull() && !destinationNode.getActiveSocket()) { qCDebug(networking) << "LimitedNodeList::sendPacket called without active socket for node" << destinationNode.getUUID() << ". Not sending."; @@ -675,7 +676,7 @@ void LimitedNodeList::handleNodeKill(const SharedNodePointer& node, ConnectionID } SharedNodePointer LimitedNodeList::addOrUpdateNode(const QUuid& uuid, NodeType_t nodeType, - const HifiSockAddr& publicSocket, const HifiSockAddr& localSocket, + const SockAddr& publicSocket, const SockAddr& localSocket, Node::LocalID localID, bool isReplicated, bool isUpstream, const QUuid& connectionSecret, const NodePermissions& permissions) { auto matchingNode = nodeWithUUID(uuid); @@ -1105,7 +1106,7 @@ void LimitedNodeList::processSTUNResponse(std::unique_ptr packe _publicSockAddr.getAddress().toString().toLocal8Bit().constData(), _publicSockAddr.getPort()); - _publicSockAddr = HifiSockAddr(newPublicAddress, newPublicPort); + _publicSockAddr = SockAddr(newPublicAddress, newPublicPort); if (!_hasCompletedInitialSTUN) { // if we're here we have definitely completed our initial STUN sequence @@ -1133,10 +1134,10 @@ void LimitedNodeList::startSTUNPublicSocketUpdate() { if (_stunSockAddr.getAddress().isNull()) { // if we fail to lookup the socket then timeout the STUN address lookup - connect(&_stunSockAddr, &HifiSockAddr::lookupFailed, this, &LimitedNodeList::possiblyTimeoutSTUNAddressLookup); + connect(&_stunSockAddr, &SockAddr::lookupFailed, this, &LimitedNodeList::possiblyTimeoutSTUNAddressLookup); // immediately send a STUN request once we know the socket - connect(&_stunSockAddr, &HifiSockAddr::lookupCompleted, this, &LimitedNodeList::sendSTUNRequest); + connect(&_stunSockAddr, &SockAddr::lookupCompleted, this, &LimitedNodeList::sendSTUNRequest); // start the initial STUN timer once we know the socket connect(&_stunSockAddr, SIGNAL(lookupCompleted()), _initialSTUNTimer, SLOT(start())); @@ -1186,7 +1187,7 @@ void LimitedNodeList::stopInitialSTUNUpdate(bool success) { qCDebug(networking) << "LimitedNodeList public socket will be set with local port and null QHostAddress."; // reset the public address and port to a null address - _publicSockAddr = HifiSockAddr(QHostAddress(), _nodeSocket.localPort()); + _publicSockAddr = SockAddr(QHostAddress(), _nodeSocket.localPort()); // we have changed the publicSockAddr, so emit our signal emit publicSockAddrChanged(_publicSockAddr); @@ -1213,7 +1214,7 @@ void LimitedNodeList::stopInitialSTUNUpdate(bool success) { void LimitedNodeList::updateLocalSocket() { // when update is called, if the local socket is empty then start with the guessed local socket if (_localSockAddr.isNull()) { - setLocalSocket(HifiSockAddr { getGuessedLocalAddress(), _nodeSocket.localPort() }); + setLocalSocket(SockAddr { getGuessedLocalAddress(), _nodeSocket.localPort() }); } // attempt to use Google's DNS to confirm that local IP @@ -1237,7 +1238,7 @@ void LimitedNodeList::connectedForLocalSocketTest() { auto localHostAddress = localIPTestSocket->localAddress(); if (localHostAddress.protocol() == QAbstractSocket::IPv4Protocol) { - setLocalSocket(HifiSockAddr { localHostAddress, _nodeSocket.localPort() }); + setLocalSocket(SockAddr { localHostAddress, _nodeSocket.localPort() }); _hasTCPCheckedLocalSocket = true; } @@ -1253,7 +1254,7 @@ void LimitedNodeList::errorTestingLocalSocket() { // error connecting to the test socket - if we've never set our local socket using this test socket // then use our possibly updated guessed local address as fallback if (!_hasTCPCheckedLocalSocket) { - setLocalSocket(HifiSockAddr { getGuessedLocalAddress(), _nodeSocket.localPort() }); + setLocalSocket(SockAddr { getGuessedLocalAddress(), _nodeSocket.localPort() }); qCCritical(networking) << "PAGE: Can't connect to Google DNS service via TCP, falling back to guessed local address" << getLocalSockAddr(); } @@ -1262,7 +1263,7 @@ void LimitedNodeList::errorTestingLocalSocket() { } } -void LimitedNodeList::setLocalSocket(const HifiSockAddr& sockAddr) { +void LimitedNodeList::setLocalSocket(const SockAddr& sockAddr) { if (sockAddr.getAddress() != _localSockAddr.getAddress()) { if (_localSockAddr.isNull()) { @@ -1283,12 +1284,12 @@ void LimitedNodeList::setLocalSocket(const HifiSockAddr& sockAddr) { } } -void LimitedNodeList::sendPeerQueryToIceServer(const HifiSockAddr& iceServerSockAddr, const QUuid& clientID, +void LimitedNodeList::sendPeerQueryToIceServer(const SockAddr& iceServerSockAddr, const QUuid& clientID, const QUuid& peerID) { sendPacketToIceServer(PacketType::ICEServerQuery, iceServerSockAddr, clientID, peerID); } -SharedNodePointer LimitedNodeList::findNodeWithAddr(const HifiSockAddr& addr) { +SharedNodePointer LimitedNodeList::findNodeWithAddr(const SockAddr& addr) { QReadLocker locker(&_nodeMutex); auto it = std::find_if(std::begin(_nodeHash), std::end(_nodeHash), [&addr](const UUIDNodePair& pair) { return pair.second->getPublicSocket() == addr @@ -1298,7 +1299,7 @@ SharedNodePointer LimitedNodeList::findNodeWithAddr(const HifiSockAddr& addr) { return (it != std::end(_nodeHash)) ? it->second : SharedNodePointer(); } -bool LimitedNodeList::sockAddrBelongsToNode(const HifiSockAddr& sockAddr) { +bool LimitedNodeList::sockAddrBelongsToNode(const SockAddr& sockAddr) { QReadLocker locker(&_nodeMutex); auto it = std::find_if(std::begin(_nodeHash), std::end(_nodeHash), [&sockAddr](const UUIDNodePair& pair) { return pair.second->getPublicSocket() == sockAddr @@ -1308,7 +1309,7 @@ bool LimitedNodeList::sockAddrBelongsToNode(const HifiSockAddr& sockAddr) { return it != std::end(_nodeHash); } -void LimitedNodeList::sendPacketToIceServer(PacketType packetType, const HifiSockAddr& iceServerSockAddr, +void LimitedNodeList::sendPacketToIceServer(PacketType packetType, const SockAddr& iceServerSockAddr, const QUuid& clientID, const QUuid& peerID) { auto icePacket = NLPacket::create(packetType); @@ -1400,7 +1401,7 @@ void LimitedNodeList::flagTimeForConnectionStep(ConnectionStep connectionStep, q } } -void LimitedNodeList::clientConnectionToSockAddrReset(const HifiSockAddr& sockAddr) { +void LimitedNodeList::clientConnectionToSockAddrReset(const SockAddr& sockAddr) { // for certain reliable channels higher level classes may need to know if the udt::Connection has been reset auto matchingNode = findNodeWithAddr(sockAddr); diff --git a/libraries/networking/src/LimitedNodeList.h b/libraries/networking/src/LimitedNodeList.h index 189f3e1b08..47b333220b 100644 --- a/libraries/networking/src/LimitedNodeList.h +++ b/libraries/networking/src/LimitedNodeList.h @@ -145,26 +145,26 @@ public: virtual bool isDomainServer() const { return true; } virtual QUuid getDomainUUID() const { assert(false); return QUuid(); } virtual Node::LocalID getDomainLocalID() const { assert(false); return Node::NULL_LOCAL_ID; } - virtual HifiSockAddr getDomainSockAddr() const { assert(false); return HifiSockAddr(); } + virtual SockAddr getDomainSockAddr() const { assert(false); return SockAddr(); } // use sendUnreliablePacket to send an unreliable packet (that you do not need to move) // either to a node (via its active socket) or to a manual sockaddr qint64 sendUnreliablePacket(const NLPacket& packet, const Node& destinationNode); - qint64 sendUnreliablePacket(const NLPacket& packet, const HifiSockAddr& sockAddr, HMACAuth* hmacAuth = nullptr); + qint64 sendUnreliablePacket(const NLPacket& packet, const SockAddr& sockAddr, HMACAuth* hmacAuth = nullptr); // use sendPacket to send a moved unreliable or reliable NL packet to a node's active socket or manual sockaddr qint64 sendPacket(std::unique_ptr packet, const Node& destinationNode); - qint64 sendPacket(std::unique_ptr packet, const HifiSockAddr& sockAddr, HMACAuth* hmacAuth = nullptr); + qint64 sendPacket(std::unique_ptr packet, const SockAddr& sockAddr, HMACAuth* hmacAuth = nullptr); // use sendUnreliableUnorderedPacketList to unreliably send separate packets from the packet list // either to a node's active socket or to a manual sockaddr qint64 sendUnreliableUnorderedPacketList(NLPacketList& packetList, const Node& destinationNode); - qint64 sendUnreliableUnorderedPacketList(NLPacketList& packetList, const HifiSockAddr& sockAddr, + qint64 sendUnreliableUnorderedPacketList(NLPacketList& packetList, const SockAddr& sockAddr, HMACAuth* hmacAuth = nullptr); // use sendPacketList to send reliable packet lists (ordered or unordered) to a node's active socket // or to a manual sock addr - qint64 sendPacketList(std::unique_ptr packetList, const HifiSockAddr& sockAddr); + qint64 sendPacketList(std::unique_ptr packetList, const SockAddr& sockAddr); qint64 sendPacketList(std::unique_ptr packetList, const Node& destinationNode); std::function linkedDataCreateCallback; @@ -175,7 +175,7 @@ public: SharedNodePointer nodeWithLocalID(Node::LocalID localID) const; SharedNodePointer addOrUpdateNode(const QUuid& uuid, NodeType_t nodeType, - const HifiSockAddr& publicSocket, const HifiSockAddr& localSocket, + const SockAddr& publicSocket, const SockAddr& localSocket, Node::LocalID localID = Node::NULL_LOCAL_ID, bool isReplicated = false, bool isUpstream = false, const QUuid& connectionSecret = QUuid(), const NodePermissions& permissions = DEFAULT_AGENT_PERMISSIONS); @@ -183,9 +183,9 @@ public: static bool parseSTUNResponse(udt::BasePacket* packet, QHostAddress& newPublicAddress, uint16_t& newPublicPort); bool hasCompletedInitialSTUN() const { return _hasCompletedInitialSTUN; } - const HifiSockAddr& getLocalSockAddr() const { return _localSockAddr; } - const HifiSockAddr& getPublicSockAddr() const { return _publicSockAddr; } - const HifiSockAddr& getSTUNSockAddr() const { return _stunSockAddr; } + const SockAddr& getLocalSockAddr() const { return _localSockAddr; } + const SockAddr& getPublicSockAddr() const { return _publicSockAddr; } + const SockAddr& getSTUNSockAddr() const { return _stunSockAddr; } void processKillNode(ReceivedMessage& message); @@ -201,9 +201,9 @@ public: static std::unique_ptr constructICEPingPacket(PingType_t pingType, const QUuid& iceID); static std::unique_ptr constructICEPingReplyPacket(ReceivedMessage& message, const QUuid& iceID); - void sendPeerQueryToIceServer(const HifiSockAddr& iceServerSockAddr, const QUuid& clientID, const QUuid& peerID); + void sendPeerQueryToIceServer(const SockAddr& iceServerSockAddr, const QUuid& clientID, const QUuid& peerID); - SharedNodePointer findNodeWithAddr(const HifiSockAddr& addr); + SharedNodePointer findNodeWithAddr(const SockAddr& addr); using value_type = SharedNodePointer; using const_iterator = std::vector::const_iterator; @@ -369,7 +369,7 @@ private slots: signals: // QUuid might be zero for non-sourced packet types. - void packetVersionMismatch(PacketType type, const HifiSockAddr& senderSockAddr, const QUuid& senderUUID); + void packetVersionMismatch(PacketType type, const SockAddr& senderSockAddr, const QUuid& senderUUID); void uuidChanged(const QUuid& ownerUUID, const QUuid& oldUUID); void nodeAdded(SharedNodePointer); @@ -379,8 +379,8 @@ signals: void clientConnectionToNodeReset(SharedNodePointer); - void localSockAddrChanged(const HifiSockAddr& localSockAddr); - void publicSockAddrChanged(const HifiSockAddr& publicSockAddr); + void localSockAddrChanged(const SockAddr& localSockAddr); + void publicSockAddrChanged(const SockAddr& publicSockAddr); void isAllowedEditorChanged(bool isAllowedEditor); void canRezChanged(bool canRez); @@ -397,7 +397,7 @@ protected slots: void connectedForLocalSocketTest(); void errorTestingLocalSocket(); - void clientConnectionToSockAddrReset(const HifiSockAddr& sockAddr); + void clientConnectionToSockAddrReset(const SockAddr& sockAddr); void processDelayedAdds(); @@ -405,8 +405,8 @@ protected: struct NewNodeInfo { qint8 type; QUuid uuid; - HifiSockAddr publicSocket; - HifiSockAddr localSocket; + SockAddr publicSocket; + SockAddr localSocket; NodePermissions permissions; bool isReplicated; Node::LocalID sessionLocalID; @@ -418,10 +418,10 @@ protected: void operator=(LimitedNodeList const&) = delete; // Don't implement, needed to avoid copies of singleton qint64 sendPacket(std::unique_ptr packet, const Node& destinationNode, - const HifiSockAddr& overridenSockAddr); + const SockAddr& overridenSockAddr); void fillPacketHeader(const NLPacket& packet, HMACAuth* hmacAuth = nullptr); - void setLocalSocket(const HifiSockAddr& sockAddr); + void setLocalSocket(const SockAddr& sockAddr); bool packetSourceAndHashMatchAndTrackBandwidth(const udt::Packet& packet, Node* sourceNode = nullptr); void processSTUNResponse(std::unique_ptr packet); @@ -430,10 +430,10 @@ protected: void stopInitialSTUNUpdate(bool success); - void sendPacketToIceServer(PacketType packetType, const HifiSockAddr& iceServerSockAddr, const QUuid& clientID, + void sendPacketToIceServer(PacketType packetType, const SockAddr& iceServerSockAddr, const QUuid& clientID, const QUuid& peerRequestID = QUuid()); - bool sockAddrBelongsToNode(const HifiSockAddr& sockAddr); + bool sockAddrBelongsToNode(const SockAddr& sockAddr); void addNewNode(NewNodeInfo info); void delayNodeAdd(NewNodeInfo info); @@ -444,9 +444,9 @@ protected: mutable QReadWriteLock _nodeMutex { QReadWriteLock::Recursive }; udt::Socket _nodeSocket; QUdpSocket* _dtlsSocket { nullptr }; - HifiSockAddr _localSockAddr; - HifiSockAddr _publicSockAddr; - HifiSockAddr _stunSockAddr { STUN_SERVER_HOSTNAME, STUN_SERVER_PORT }; + SockAddr _localSockAddr; + SockAddr _publicSockAddr; + SockAddr _stunSockAddr { STUN_SERVER_HOSTNAME, STUN_SERVER_PORT }; bool _hasTCPCheckedLocalSocket { false }; bool _useAuthentication { true }; diff --git a/libraries/networking/src/NLPacket.cpp b/libraries/networking/src/NLPacket.cpp index 620e60945b..8463dab792 100644 --- a/libraries/networking/src/NLPacket.cpp +++ b/libraries/networking/src/NLPacket.cpp @@ -4,6 +4,7 @@ // // Created by Clement on 7/6/15. // Copyright 2015 High Fidelity, Inc. +// Copyright 2021 Vircadia contributors. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -35,7 +36,7 @@ std::unique_ptr NLPacket::create(PacketType type, qint64 size, bool is } std::unique_ptr NLPacket::fromReceivedPacket(std::unique_ptr data, qint64 size, - const HifiSockAddr& senderSockAddr) { + const SockAddr& senderSockAddr) { // Fail with null data Q_ASSERT(data); @@ -89,7 +90,7 @@ NLPacket::NLPacket(const NLPacket& other) : Packet(other) { _sourceID = other._sourceID; } -NLPacket::NLPacket(std::unique_ptr data, qint64 size, const HifiSockAddr& senderSockAddr) : +NLPacket::NLPacket(std::unique_ptr data, qint64 size, const SockAddr& senderSockAddr) : Packet(std::move(data), size, senderSockAddr) { // sanity check before we decrease the payloadSize with the payloadCapacity diff --git a/libraries/networking/src/NLPacket.h b/libraries/networking/src/NLPacket.h index 4103f2068e..b2a174a540 100644 --- a/libraries/networking/src/NLPacket.h +++ b/libraries/networking/src/NLPacket.h @@ -4,6 +4,7 @@ // // Created by Clement on 7/6/15. // Copyright 2015 High Fidelity, Inc. +// Copyright 2021 Vircadia contributors. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -52,7 +53,7 @@ public: bool isReliable = false, bool isPartOfMessage = false, PacketVersion version = 0); static std::unique_ptr fromReceivedPacket(std::unique_ptr data, qint64 size, - const HifiSockAddr& senderSockAddr); + const SockAddr& senderSockAddr); static std::unique_ptr fromBase(std::unique_ptr packet); @@ -87,7 +88,7 @@ public: protected: NLPacket(PacketType type, qint64 size = -1, bool forceReliable = false, bool isPartOfMessage = false, PacketVersion version = 0); - NLPacket(std::unique_ptr data, qint64 size, const HifiSockAddr& senderSockAddr); + NLPacket(std::unique_ptr data, qint64 size, const SockAddr& senderSockAddr); NLPacket(const NLPacket& other); NLPacket(NLPacket&& other); diff --git a/libraries/networking/src/NetworkPeer.cpp b/libraries/networking/src/NetworkPeer.cpp index b7807bc62d..e76b8c31a6 100644 --- a/libraries/networking/src/NetworkPeer.cpp +++ b/libraries/networking/src/NetworkPeer.cpp @@ -4,6 +4,7 @@ // // Created by Stephen Birarda on 2014-10-02. // Copyright 2014 High Fidelity, Inc. +// Copyright 2021 Vircadia contributors. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -37,7 +38,7 @@ NetworkPeer::NetworkPeer(QObject* parent) : _lastHeardMicrostamp = usecTimestampNow(); } -NetworkPeer::NetworkPeer(const QUuid& uuid, const HifiSockAddr& publicSocket, const HifiSockAddr& localSocket, QObject* parent) : +NetworkPeer::NetworkPeer(const QUuid& uuid, const SockAddr& publicSocket, const SockAddr& localSocket, QObject* parent) : QObject(parent), _uuid(uuid), _publicSocket(publicSocket), @@ -50,7 +51,7 @@ NetworkPeer::NetworkPeer(const QUuid& uuid, const HifiSockAddr& publicSocket, co _lastHeardMicrostamp = usecTimestampNow(); } -void NetworkPeer::setPublicSocket(const HifiSockAddr& publicSocket) { +void NetworkPeer::setPublicSocket(const SockAddr& publicSocket) { if (publicSocket != _publicSocket) { if (_activeSocket == &_publicSocket) { // if the active socket was the public socket then reset it to NULL @@ -70,7 +71,7 @@ void NetworkPeer::setPublicSocket(const HifiSockAddr& publicSocket) { } } -void NetworkPeer::setLocalSocket(const HifiSockAddr& localSocket) { +void NetworkPeer::setLocalSocket(const SockAddr& localSocket) { if (localSocket != _localSocket) { if (_activeSocket == &_localSocket) { // if the active socket was the local socket then reset it to NULL @@ -90,7 +91,7 @@ void NetworkPeer::setLocalSocket(const HifiSockAddr& localSocket) { } } -void NetworkPeer::setSymmetricSocket(const HifiSockAddr& symmetricSocket) { +void NetworkPeer::setSymmetricSocket(const SockAddr& symmetricSocket) { if (symmetricSocket != _symmetricSocket) { if (_activeSocket == &_symmetricSocket) { // if the active socket was the symmetric socket then reset it to NULL @@ -110,7 +111,7 @@ void NetworkPeer::setSymmetricSocket(const HifiSockAddr& symmetricSocket) { } } -void NetworkPeer::setActiveSocket(HifiSockAddr* discoveredSocket) { +void NetworkPeer::setActiveSocket(SockAddr* discoveredSocket) { _activeSocket = discoveredSocket; // we have an active socket, stop our ping timer @@ -145,7 +146,7 @@ void NetworkPeer::activateSymmetricSocket() { } } -void NetworkPeer::activateMatchingOrNewSymmetricSocket(const HifiSockAddr& matchableSockAddr) { +void NetworkPeer::activateMatchingOrNewSymmetricSocket(const SockAddr& matchableSockAddr) { if (matchableSockAddr == _publicSocket) { activatePublicSocket(); } else if (matchableSockAddr == _localSocket) { diff --git a/libraries/networking/src/NetworkPeer.h b/libraries/networking/src/NetworkPeer.h index 4c08c97d3c..a3012087af 100644 --- a/libraries/networking/src/NetworkPeer.h +++ b/libraries/networking/src/NetworkPeer.h @@ -4,6 +4,7 @@ // // Created by Stephen Birarda on 2014-10-02. // Copyright 2014 High Fidelity, Inc. +// Copyright 2021 Vircadia contributors. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -18,7 +19,7 @@ #include #include -#include "HifiSockAddr.h" +#include "SockAddr.h" #include "UUID.h" const QString ICE_SERVER_HOSTNAME = "localhost"; @@ -32,7 +33,7 @@ class NetworkPeer : public QObject { Q_OBJECT public: NetworkPeer(QObject* parent = 0); - NetworkPeer(const QUuid& uuid, const HifiSockAddr& publicSocket, const HifiSockAddr& localSocket, QObject* parent = 0); + NetworkPeer(const QUuid& uuid, const SockAddr& publicSocket, const SockAddr& localSocket, QObject* parent = 0); bool isNull() const { return _uuid.isNull(); } bool hasSockets() const { return !_localSocket.isNull() && !_publicSocket.isNull(); } @@ -49,21 +50,21 @@ public: void softReset(); void reset(); - const HifiSockAddr& getPublicSocket() const { return _publicSocket; } - const HifiSockAddr& getLocalSocket() const { return _localSocket; } - const HifiSockAddr& getSymmetricSocket() const { return _symmetricSocket; } + const SockAddr& getPublicSocket() const { return _publicSocket; } + const SockAddr& getLocalSocket() const { return _localSocket; } + const SockAddr& getSymmetricSocket() const { return _symmetricSocket; } - void setPublicSocket(const HifiSockAddr& publicSocket); - void setLocalSocket(const HifiSockAddr& localSocket); - void setSymmetricSocket(const HifiSockAddr& symmetricSocket); + void setPublicSocket(const SockAddr& publicSocket); + void setLocalSocket(const SockAddr& localSocket); + void setSymmetricSocket(const SockAddr& symmetricSocket); - const HifiSockAddr* getActiveSocket() const { return _activeSocket; } + const SockAddr* getActiveSocket() const { return _activeSocket; } void activatePublicSocket(); void activateLocalSocket(); void activateSymmetricSocket(); - void activateMatchingOrNewSymmetricSocket(const HifiSockAddr& matchableSockAddr); + void activateMatchingOrNewSymmetricSocket(const SockAddr& matchableSockAddr); quint64 getWakeTimestamp() const { return _wakeTimestamp; } void setWakeTimestamp(quint64 wakeTimestamp) { _wakeTimestamp = wakeTimestamp; } @@ -93,19 +94,19 @@ public slots: signals: void pingTimerTimeout(); - void socketActivated(const HifiSockAddr& sockAddr); - void socketUpdated(HifiSockAddr previousAddress, HifiSockAddr currentAddress); + void socketActivated(const SockAddr& sockAddr); + void socketUpdated(SockAddr previousAddress, SockAddr currentAddress); protected: - void setActiveSocket(HifiSockAddr* discoveredSocket); + void setActiveSocket(SockAddr* discoveredSocket); QUuid _uuid; LocalID _localID { 0 }; - HifiSockAddr _publicSocket; - HifiSockAddr _localSocket; - HifiSockAddr _symmetricSocket; - HifiSockAddr* _activeSocket; + SockAddr _publicSocket; + SockAddr _localSocket; + SockAddr _symmetricSocket; + SockAddr* _activeSocket; quint64 _wakeTimestamp; std::atomic_ullong _lastHeardMicrostamp; diff --git a/libraries/networking/src/NetworkingConstants.h b/libraries/networking/src/NetworkingConstants.h index d5ad90a6f4..ae3607eed9 100644 --- a/libraries/networking/src/NetworkingConstants.h +++ b/libraries/networking/src/NetworkingConstants.h @@ -25,7 +25,7 @@ namespace NetworkingConstants { // You can avoid changing that and still effectively use a connected domain on staging // if you manually generate a personal access token for the domains scope // at https://staging.highfidelity.com/user/tokens/new?for_domain_server=true - + const QString WEB_ENGINE_VERSION = "Chrome/83.0.4103.122"; // For now we only have one Metaverse server. @@ -35,21 +35,21 @@ namespace NetworkingConstants { // Web Engine requests to this parent domain have an account authorization header added const QString AUTH_HOSTNAME_BASE = "vircadia.com"; const QStringList IS_AUTHABLE_HOSTNAME = { "vircadia.com", "vircadia.io" }; - + // Use a custom User-Agent to avoid ModSecurity filtering, e.g. by hosting providers. const QByteArray VIRCADIA_USER_AGENT = "Mozilla/5.0 (VircadiaInterface)"; - + const QString WEB_ENGINE_USER_AGENT = "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) " + WEB_ENGINE_VERSION + " Mobile Safari/537.36"; const QString MOBILE_USER_AGENT = "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) " + WEB_ENGINE_VERSION + " Mobile Safari/537.36"; - + // WebEntity Defaults const QString WEB_ENTITY_DEFAULT_SOURCE_URL = "https://vircadia.com/"; const QString WEB_ENTITY_DEFAULT_USER_AGENT = WEB_ENGINE_USER_AGENT; - + // Builds URLs const QUrl BUILDS_XML_URL("https://highfidelity.com/builds.xml"); const QUrl MASTER_BUILDS_XML_URL("https://highfidelity.com/dev-builds.xml"); - + const QString DEFAULT_AVATAR_COLLISION_SOUND_URL = "https://hifi-public.s3.amazonaws.com/sounds/Collisions-otherorganic/Body_Hits_Impact.wav"; // CDN URLs @@ -71,20 +71,20 @@ namespace NetworkingConstants { const unsigned short STUN_SERVER_DEFAULT_PORT = 19302; #endif - const QUrl HELP_DOCS_URL { "https://docs.vircadia.dev" }; - const QUrl HELP_FORUM_URL { "https://forums.vircadia.dev" }; + const QUrl HELP_DOCS_URL { "https://docs.vircadia.com" }; + const QUrl HELP_FORUM_URL { "https://forum.vircadia.com" }; const QUrl HELP_SCRIPTING_REFERENCE_URL{ "https://apidocs.vircadia.dev/" }; - const QUrl HELP_RELEASE_NOTES_URL{ "https://docs.vircadia.dev/release-notes.html" }; + const QUrl HELP_RELEASE_NOTES_URL{ "https://docs.vircadia.com/release-notes.html" }; const QUrl HELP_BUG_REPORT_URL{ "https://github.com/vircadia/vircadia/issues" }; - + const QString DEFAULT_VIRCADIA_ADDRESS = "file:///~/serverless/tutorial.json"; const QString DEFAULT_HOME_ADDRESS = "file:///~/serverless/tutorial.json"; const QString REDIRECT_HIFI_ADDRESS = "file:///~/serverless/redirect.json"; } const QString HIFI_URL_SCHEME_ABOUT = "about"; -const QString URL_SCHEME_HIFI = "hifi"; -const QString URL_SCHEME_HIFIAPP = "hifiapp"; +const QString URL_SCHEME_VIRCADIA = "hifi"; +const QString URL_SCHEME_VIRCADIAAPP = "hifiapp"; const QString URL_SCHEME_DATA = "data"; const QString URL_SCHEME_QRC = "qrc"; const QString HIFI_URL_SCHEME_FILE = "file"; diff --git a/libraries/networking/src/Node.cpp b/libraries/networking/src/Node.cpp index a2bd60914a..aa13dd6565 100644 --- a/libraries/networking/src/Node.cpp +++ b/libraries/networking/src/Node.cpp @@ -4,6 +4,7 @@ // // Created by Stephen Birarda on 2/15/13. // Copyright 2013 High Fidelity, Inc. +// Copyright 2021 Vircadia contributors. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -85,8 +86,8 @@ NodeType_t NodeType::fromString(QString type) { } -Node::Node(const QUuid& uuid, NodeType_t type, const HifiSockAddr& publicSocket, - const HifiSockAddr& localSocket, QObject* parent) : +Node::Node(const QUuid& uuid, NodeType_t type, const SockAddr& publicSocket, + const SockAddr& localSocket, QObject* parent) : NetworkPeer(uuid, publicSocket, localSocket, parent), _type(type), _pingMs(-1), // "Uninitialized" diff --git a/libraries/networking/src/Node.h b/libraries/networking/src/Node.h index 7435ebaaf8..cf2f081da6 100644 --- a/libraries/networking/src/Node.h +++ b/libraries/networking/src/Node.h @@ -4,6 +4,7 @@ // // Created by Stephen Birarda on 2/15/13. // Copyright 2013 High Fidelity, Inc. +// Copyright 2021 Vircadia contributors. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -27,7 +28,7 @@ #include -#include "HifiSockAddr.h" +#include "SockAddr.h" #include "NetworkPeer.h" #include "NodeData.h" #include "NodeType.h" @@ -44,7 +45,7 @@ public: using Stats = udt::ConnectionStats::Stats; Node(const QUuid& uuid, NodeType_t type, - const HifiSockAddr& publicSocket, const HifiSockAddr& localSocket, + const SockAddr& publicSocket, const SockAddr& localSocket, QObject* parent = nullptr); bool operator==(const Node& otherNode) const { return _uuid == otherNode._uuid; } diff --git a/libraries/networking/src/NodeList.cpp b/libraries/networking/src/NodeList.cpp index 3d28457633..1e07e14803 100644 --- a/libraries/networking/src/NodeList.cpp +++ b/libraries/networking/src/NodeList.cpp @@ -35,7 +35,7 @@ #include "Assignment.h" #include "AudioHelpers.h" #include "DomainAccountManager.h" -#include "HifiSockAddr.h" +#include "SockAddr.h" #include "FingerprintUtils.h" #include "NetworkLogging.h" @@ -176,11 +176,11 @@ NodeList::NodeList(char newOwnerType, int socketListenPort, int dtlsListenPort) PacketReceiver::makeUnsourcedListenerReference(this, &NodeList::processUsernameFromIDReply)); } -qint64 NodeList::sendStats(QJsonObject statsObject, HifiSockAddr destination) { +qint64 NodeList::sendStats(QJsonObject statsObject, SockAddr destination) { if (thread() != QThread::currentThread()) { QMetaObject::invokeMethod(this, "sendStats", Qt::QueuedConnection, Q_ARG(QJsonObject, statsObject), - Q_ARG(HifiSockAddr, destination)); + Q_ARG(SockAddr, destination)); return 0; } @@ -245,7 +245,7 @@ void NodeList::timePingReply(ReceivedMessage& message, const SharedNodePointer& void NodeList::processPingPacket(QSharedPointer message, SharedNodePointer sendingNode) { // send back a reply auto replyPacket = constructPingReplyPacket(*message); - const HifiSockAddr& senderSockAddr = message->getSenderSockAddr(); + const SockAddr& senderSockAddr = message->getSenderSockAddr(); sendPacket(std::move(replyPacket), *sendingNode, senderSockAddr); // If we don't have a symmetric socket for this node and this socket doesn't match @@ -364,7 +364,7 @@ void NodeList::sendDomainServerCheckIn() { // let the domain handler know we are due to send a checkin packet } else if (!domainHandlerIp.isNull() && !_domainHandler.checkInPacketTimeout()) { bool domainIsConnected = _domainHandler.isConnected(); - HifiSockAddr domainSockAddr = _domainHandler.getSockAddr(); + SockAddr domainSockAddr = _domainHandler.getSockAddr(); PacketType domainPacketType = !domainIsConnected ? PacketType::DomainConnectRequest : PacketType::DomainListRequest; @@ -405,7 +405,7 @@ void NodeList::sendDomainServerCheckIn() { QDataStream packetStream(domainPacket.get()); - HifiSockAddr localSockAddr = _localSockAddr; + SockAddr localSockAddr = _localSockAddr; if (domainPacketType == PacketType::DomainConnectRequest) { #if (PR_BUILD || DEV_BUILD) @@ -823,8 +823,8 @@ void NodeList::processDomainServerList(QSharedPointer message) // FIXME: Remove this call to requestDomainSettings() and reinstate the one in DomainHandler::setIsConnected(), in version // 2021.2.0. (New protocol version implies a domain server upgrade.) - if (!_domainHandler.isConnected() - && _domainHandler.getScheme() == URL_SCHEME_HIFI && !_domainHandler.getHostname().isEmpty()) { + if (!_domainHandler.isConnected() + && _domainHandler.getScheme() == URL_SCHEME_VIRCADIA && !_domainHandler.getHostname().isEmpty()) { // We're about to connect but we need the domain settings (in particular, the node permissions) in order to adjust the // canRezAvatarEntities permission above before using the permissions in determining whether or not to connect without // avatar entities rezzing below. @@ -1012,7 +1012,7 @@ void NodeList::sendKeepAlivePings() { }); } -bool NodeList::sockAddrBelongsToDomainOrNode(const HifiSockAddr& sockAddr) { +bool NodeList::sockAddrBelongsToDomainOrNode(const SockAddr& sockAddr) { return _domainHandler.getSockAddr() == sockAddr || LimitedNodeList::sockAddrBelongsToNode(sockAddr); } diff --git a/libraries/networking/src/NodeList.h b/libraries/networking/src/NodeList.h index 9c47abbd9f..1c01d384cc 100644 --- a/libraries/networking/src/NodeList.h +++ b/libraries/networking/src/NodeList.h @@ -4,6 +4,7 @@ // // Created by Stephen Birarda on 2/15/13. // Copyright 2013 High Fidelity, Inc. +// Copyright 2021 Vircadia contributors. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -57,7 +58,7 @@ public: NodeType_t getOwnerType() const { return _ownerType.load(); } void setOwnerType(NodeType_t ownerType) { _ownerType.store(ownerType); } - Q_INVOKABLE qint64 sendStats(QJsonObject statsObject, HifiSockAddr destination); + Q_INVOKABLE qint64 sendStats(QJsonObject statsObject, SockAddr destination); Q_INVOKABLE qint64 sendStatsToDomainServer(QJsonObject statsObject); DomainHandler& getDomainHandler() { return _domainHandler; } @@ -67,7 +68,7 @@ public: void addSetOfNodeTypesToNodeInterestSet(const NodeSet& setOfNodeTypes); void resetNodeInterestSet() { _nodeTypesOfInterest.clear(); } - void setAssignmentServerSocket(const HifiSockAddr& serverSocket) { _assignmentServerSocket = serverSocket; } + void setAssignmentServerSocket(const SockAddr& serverSocket) { _assignmentServerSocket = serverSocket; } void sendAssignment(Assignment& assignment); void disableDomainPortAutoDiscovery(bool disabled = false) { _domainPortAutoDiscovery = disabled; }; @@ -102,7 +103,7 @@ public: virtual bool isDomainServer() const override { return false; } virtual QUuid getDomainUUID() const override { return _domainHandler.getUUID(); } virtual Node::LocalID getDomainLocalID() const override { return _domainHandler.getLocalID(); } - virtual HifiSockAddr getDomainSockAddr() const override { return _domainHandler.getSockAddr(); } + virtual SockAddr getDomainSockAddr() const override { return _domainHandler.getSockAddr(); } public slots: void reset(QString reason, bool skipDomainHandlerReset = false); @@ -171,12 +172,12 @@ private: void pingPunchForInactiveNode(const SharedNodePointer& node); - bool sockAddrBelongsToDomainOrNode(const HifiSockAddr& sockAddr); + bool sockAddrBelongsToDomainOrNode(const SockAddr& sockAddr); std::atomic _ownerType; NodeSet _nodeTypesOfInterest; DomainHandler _domainHandler; - HifiSockAddr _assignmentServerSocket; + SockAddr _assignmentServerSocket; bool _isShuttingDown { false }; QTimer _keepAlivePingTimer; bool _requestsDomainListData { false }; diff --git a/libraries/networking/src/PacketReceiver.cpp b/libraries/networking/src/PacketReceiver.cpp index c13fb8566b..384355b53c 100644 --- a/libraries/networking/src/PacketReceiver.cpp +++ b/libraries/networking/src/PacketReceiver.cpp @@ -5,6 +5,7 @@ // Created by Stephen Birarda on 1/23/2014. // Update by Ryan Huffman on 7/8/2015. // Copyright 2014 High Fidelity, Inc. +// Copyright 2021 Vircadia contributors. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -152,7 +153,7 @@ void PacketReceiver::handleVerifiedPacket(std::unique_ptr packet) { void PacketReceiver::handleVerifiedMessagePacket(std::unique_ptr packet) { auto nlPacket = NLPacket::fromBase(std::move(packet)); - auto key = std::pair(nlPacket->getSenderSockAddr(), nlPacket->getMessageNumber()); + auto key = std::pair(nlPacket->getSenderSockAddr(), nlPacket->getMessageNumber()); auto it = _pendingMessages.find(key); QSharedPointer message; @@ -174,8 +175,8 @@ void PacketReceiver::handleVerifiedMessagePacket(std::unique_ptr pa } } -void PacketReceiver::handleMessageFailure(HifiSockAddr from, udt::Packet::MessageNumber messageNumber) { - auto key = std::pair(from, messageNumber); +void PacketReceiver::handleMessageFailure(SockAddr from, udt::Packet::MessageNumber messageNumber) { + auto key = std::pair(from, messageNumber); auto it = _pendingMessages.find(key); if (it != _pendingMessages.end()) { auto message = it->second; diff --git a/libraries/networking/src/PacketReceiver.h b/libraries/networking/src/PacketReceiver.h index 4d2f11360e..c354e98a37 100644 --- a/libraries/networking/src/PacketReceiver.h +++ b/libraries/networking/src/PacketReceiver.h @@ -5,6 +5,7 @@ // Created by Stephen Birarda on 1/23/2014. // Update by Ryan Huffman on 7/8/2015. // Copyright 2014 High Fidelity, Inc. +// Copyright 2021 Vircadia contributors. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -34,9 +35,9 @@ class OctreePacketProcessor; namespace std { template <> - struct hash> { - size_t operator()(const std::pair& pair) const { - return hash()(pair.first) ^ hash()(pair.second); + struct hash> { + size_t operator()(const std::pair& pair) const { + return hash()(pair.first) ^ hash()(pair.second); } }; } @@ -78,7 +79,7 @@ public: void handleVerifiedPacket(std::unique_ptr packet); void handleVerifiedMessagePacket(std::unique_ptr message); - void handleMessageFailure(HifiSockAddr from, udt::Packet::MessageNumber messageNumber); + void handleMessageFailure(SockAddr from, udt::Packet::MessageNumber messageNumber); private: template @@ -129,7 +130,7 @@ private: QMutex _directConnectSetMutex; QSet _directlyConnectedObjects; - std::unordered_map, QSharedPointer> _pendingMessages; + std::unordered_map, QSharedPointer> _pendingMessages; friend class EntityEditPacketSender; friend class OctreePacketProcessor; diff --git a/libraries/networking/src/ReceivedMessage.cpp b/libraries/networking/src/ReceivedMessage.cpp index 7ae408ef7a..684ad665ba 100644 --- a/libraries/networking/src/ReceivedMessage.cpp +++ b/libraries/networking/src/ReceivedMessage.cpp @@ -4,6 +4,7 @@ // // Created by Ryan Huffman on 2015/09/17 // Copyright 2015 High Fidelity, Inc. +// Copyright 2021 Vircadia contributors. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -49,7 +50,7 @@ ReceivedMessage::ReceivedMessage(NLPacket& packet) } ReceivedMessage::ReceivedMessage(QByteArray byteArray, PacketType packetType, PacketVersion packetVersion, - const HifiSockAddr& senderSockAddr, NLPacket::LocalID sourceID) : + const SockAddr& senderSockAddr, NLPacket::LocalID sourceID) : _data(byteArray), _headData(_data.mid(0, HEAD_DATA_SIZE)), _numPackets(1), diff --git a/libraries/networking/src/ReceivedMessage.h b/libraries/networking/src/ReceivedMessage.h index c864616635..f9c8245a10 100644 --- a/libraries/networking/src/ReceivedMessage.h +++ b/libraries/networking/src/ReceivedMessage.h @@ -4,6 +4,7 @@ // // Created by Ryan Huffman on 2015/09/15 // Copyright 2015 High Fidelity, Inc. +// Copyright 2021 Vircadia contributors. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -25,7 +26,7 @@ public: ReceivedMessage(const NLPacketList& packetList); ReceivedMessage(NLPacket& packet); ReceivedMessage(QByteArray byteArray, PacketType packetType, PacketVersion packetVersion, - const HifiSockAddr& senderSockAddr, NLPacket::LocalID sourceID = NLPacket::NULL_LOCAL_ID); + const SockAddr& senderSockAddr, NLPacket::LocalID sourceID = NLPacket::NULL_LOCAL_ID); QByteArray getMessage() const { return _data; } const char* getRawMessage() const { return _data.constData(); } @@ -41,7 +42,7 @@ public: bool isComplete() const { return _isComplete; } NLPacket::LocalID getSourceID() const { return _sourceID; } - const HifiSockAddr& getSenderSockAddr() { return _senderSockAddr; } + const SockAddr& getSenderSockAddr() { return _senderSockAddr; } qint64 getPosition() const { return _position; } @@ -99,7 +100,7 @@ private: NLPacket::LocalID _sourceID { NLPacket::NULL_LOCAL_ID }; PacketType _packetType; PacketVersion _packetVersion; - HifiSockAddr _senderSockAddr; + SockAddr _senderSockAddr; std::atomic _isComplete { true }; std::atomic _failed { false }; diff --git a/libraries/networking/src/HifiSockAddr.cpp b/libraries/networking/src/SockAddr.cpp similarity index 78% rename from libraries/networking/src/HifiSockAddr.cpp rename to libraries/networking/src/SockAddr.cpp index 086dd08489..e61ae5bccc 100644 --- a/libraries/networking/src/HifiSockAddr.cpp +++ b/libraries/networking/src/SockAddr.cpp @@ -1,15 +1,16 @@ // -// HifiSockAddr.cpp +// SockAddr.cpp // libraries/networking/src // // Created by Stephen Birarda on 11/26/2013. // Copyright 2013 High Fidelity, Inc. +// Copyright 2021 Vircadia contributors. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include "HifiSockAddr.h" +#include "SockAddr.h" #include #include @@ -24,23 +25,23 @@ #include #endif -int hifiSockAddrMetaTypeId = qRegisterMetaType(); +int sockAddrMetaTypeId = qRegisterMetaType(); -HifiSockAddr::HifiSockAddr() : +SockAddr::SockAddr() : _address(), _port(0) { } -HifiSockAddr::HifiSockAddr(const QHostAddress& address, quint16 port) : +SockAddr::SockAddr(const QHostAddress& address, quint16 port) : _address(address), _port(port) { } -HifiSockAddr::HifiSockAddr(const HifiSockAddr& otherSockAddr) : +SockAddr::SockAddr(const SockAddr& otherSockAddr) : QObject(), _address(otherSockAddr._address), _port(otherSockAddr._port) @@ -48,14 +49,14 @@ HifiSockAddr::HifiSockAddr(const HifiSockAddr& otherSockAddr) : setObjectName(otherSockAddr.objectName()); } -HifiSockAddr& HifiSockAddr::operator=(const HifiSockAddr& rhsSockAddr) { +SockAddr& SockAddr::operator=(const SockAddr& rhsSockAddr) { setObjectName(rhsSockAddr.objectName()); _address = rhsSockAddr._address; _port = rhsSockAddr._port; return *this; } -HifiSockAddr::HifiSockAddr(const QString& hostname, quint16 hostOrderPort, bool shouldBlockForLookup) : +SockAddr::SockAddr(const QString& hostname, quint16 hostOrderPort, bool shouldBlockForLookup) : _address(hostname), _port(hostOrderPort) { @@ -73,7 +74,7 @@ HifiSockAddr::HifiSockAddr(const QString& hostname, quint16 hostOrderPort, bool } } -HifiSockAddr::HifiSockAddr(const sockaddr* sockaddr) { +SockAddr::SockAddr(const sockaddr* sockaddr) { _address = QHostAddress(sockaddr); if (sockaddr->sa_family == AF_INET) { @@ -83,7 +84,7 @@ HifiSockAddr::HifiSockAddr(const sockaddr* sockaddr) { } } -void HifiSockAddr::swap(HifiSockAddr& otherSockAddr) { +void SockAddr::swap(SockAddr& otherSockAddr) { using std::swap; swap(_address, otherSockAddr._address); @@ -95,11 +96,11 @@ void HifiSockAddr::swap(HifiSockAddr& otherSockAddr) { setObjectName(temp); } -bool HifiSockAddr::operator==(const HifiSockAddr& rhsSockAddr) const { +bool SockAddr::operator==(const SockAddr& rhsSockAddr) const { return _address == rhsSockAddr._address && _port == rhsSockAddr._port; } -void HifiSockAddr::handleLookupResult(const QHostInfo& hostInfo) { +void SockAddr::handleLookupResult(const QHostInfo& hostInfo) { if (hostInfo.error() != QHostInfo::NoError) { qCDebug(networking) << "Lookup failed for" << hostInfo.lookupId() << ":" << hostInfo.errorString(); emit lookupFailed(); @@ -117,11 +118,11 @@ void HifiSockAddr::handleLookupResult(const QHostInfo& hostInfo) { } } -QString HifiSockAddr::toString() const { +QString SockAddr::toString() const { return _address.toString() + ":" + QString::number(_port); } -bool HifiSockAddr::hasPrivateAddress() const { +bool SockAddr::hasPrivateAddress() const { // an address is private if it is loopback or falls in any of the RFC1918 address spaces const QPair TWENTY_FOUR_BIT_BLOCK = { QHostAddress("10.0.0.0"), 8 }; const QPair TWENTY_BIT_BLOCK = { QHostAddress("172.16.0.0") , 12 }; @@ -133,22 +134,22 @@ bool HifiSockAddr::hasPrivateAddress() const { || _address.isInSubnet(SIXTEEN_BIT_BLOCK); } -QDebug operator<<(QDebug debug, const HifiSockAddr& sockAddr) { +QDebug operator<<(QDebug debug, const SockAddr& sockAddr) { debug.nospace() << sockAddr._address.toString().toLocal8Bit().constData() << ":" << sockAddr._port; return debug.space(); } -QDataStream& operator<<(QDataStream& dataStream, const HifiSockAddr& sockAddr) { +QDataStream& operator<<(QDataStream& dataStream, const SockAddr& sockAddr) { dataStream << sockAddr._address << sockAddr._port; return dataStream; } -QDataStream& operator>>(QDataStream& dataStream, HifiSockAddr& sockAddr) { +QDataStream& operator>>(QDataStream& dataStream, SockAddr& sockAddr) { dataStream >> sockAddr._address >> sockAddr._port; return dataStream; } -uint qHash(const HifiSockAddr& key, uint seed) { +uint qHash(const SockAddr& key, uint seed) { // use the existing QHostAddress and quint16 hash functions to get our hash return qHash(key.getAddress(), seed) ^ qHash(key.getPort(), seed); } diff --git a/libraries/networking/src/HifiSockAddr.h b/libraries/networking/src/SockAddr.h similarity index 64% rename from libraries/networking/src/HifiSockAddr.h rename to libraries/networking/src/SockAddr.h index dcf7f9a6a9..07b3e8c306 100644 --- a/libraries/networking/src/HifiSockAddr.h +++ b/libraries/networking/src/SockAddr.h @@ -1,16 +1,17 @@ // -// HifiSockAddr.h +// SockAddr.h // libraries/networking/src // // Created by Stephen Birarda on 11/26/2013. // Copyright 2013 High Fidelity, Inc. +// Copyright 2021 Vircadia contributors. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#ifndef hifi_HifiSockAddr_h -#define hifi_HifiSockAddr_h +#ifndef hifi_SockAddr_h +#define hifi_SockAddr_h #include #include @@ -19,23 +20,23 @@ struct sockaddr; #include -class HifiSockAddr : public QObject { +class SockAddr : public QObject { Q_OBJECT public: - HifiSockAddr(); - HifiSockAddr(const QHostAddress& address, quint16 port); - HifiSockAddr(const HifiSockAddr& otherSockAddr); - HifiSockAddr(const QString& hostname, quint16 hostOrderPort, bool shouldBlockForLookup = false); - HifiSockAddr(const sockaddr* sockaddr); + SockAddr(); + SockAddr(const QHostAddress& address, quint16 port); + SockAddr(const SockAddr& otherSockAddr); + SockAddr(const QString& hostname, quint16 hostOrderPort, bool shouldBlockForLookup = false); + SockAddr(const sockaddr* sockaddr); bool isNull() const { return _address.isNull() && _port == 0; } void clear() { _address.clear(); _port = 0;} - HifiSockAddr& operator=(const HifiSockAddr& rhsSockAddr); - void swap(HifiSockAddr& otherSockAddr); + SockAddr& operator=(const SockAddr& rhsSockAddr); + void swap(SockAddr& otherSockAddr); - bool operator==(const HifiSockAddr& rhsSockAddr) const; - bool operator!=(const HifiSockAddr& rhsSockAddr) const { return !(*this == rhsSockAddr); } + bool operator==(const SockAddr& rhsSockAddr) const; + bool operator!=(const SockAddr& rhsSockAddr) const { return !(*this == rhsSockAddr); } const QHostAddress& getAddress() const { return _address; } QHostAddress* getAddressPointer() { return &_address; } @@ -45,16 +46,16 @@ public: quint16* getPortPointer() { return &_port; } void setPort(quint16 port) { _port = port; } - static int packSockAddr(unsigned char* packetData, const HifiSockAddr& packSockAddr); - static int unpackSockAddr(const unsigned char* packetData, HifiSockAddr& unpackDestSockAddr); + static int packSockAddr(unsigned char* packetData, const SockAddr& packSockAddr); + static int unpackSockAddr(const unsigned char* packetData, SockAddr& unpackDestSockAddr); QString toString() const; bool hasPrivateAddress() const; // checks if the address behind this sock addr is private per RFC 1918 - friend QDebug operator<<(QDebug debug, const HifiSockAddr& sockAddr); - friend QDataStream& operator<<(QDataStream& dataStream, const HifiSockAddr& sockAddr); - friend QDataStream& operator>>(QDataStream& dataStream, HifiSockAddr& sockAddr); + friend QDebug operator<<(QDebug debug, const SockAddr& sockAddr); + friend QDataStream& operator<<(QDataStream& dataStream, const SockAddr& sockAddr); + friend QDataStream& operator>>(QDataStream& dataStream, SockAddr& sockAddr); private slots: void handleLookupResult(const QHostInfo& hostInfo); @@ -66,14 +67,14 @@ private: quint16 _port; }; -uint qHash(const HifiSockAddr& key, uint seed); +uint qHash(const SockAddr& key, uint seed); namespace std { template <> - struct hash { + struct hash { // NOTE: this hashing specifically ignores IPv6 addresses - if we begin to support those we will need // to conditionally hash the bytes that represent an IPv6 address - size_t operator()(const HifiSockAddr& sockAddr) const { + size_t operator()(const SockAddr& sockAddr) const { // use XOR of implemented std::hash templates for new hash // depending on the type of address we're looking at @@ -90,6 +91,6 @@ namespace std { }; } -Q_DECLARE_METATYPE(HifiSockAddr); +Q_DECLARE_METATYPE(SockAddr); -#endif // hifi_HifiSockAddr_h +#endif // hifi_SockAddr_h diff --git a/libraries/networking/src/udt/BasePacket.cpp b/libraries/networking/src/udt/BasePacket.cpp index 12a174b7d3..442ed8a2c8 100644 --- a/libraries/networking/src/udt/BasePacket.cpp +++ b/libraries/networking/src/udt/BasePacket.cpp @@ -4,6 +4,7 @@ // // Created by Stephen Birarda on 2015-07-23. // Copyright 2015 High Fidelity, Inc. +// Copyright 2021 Vircadia contributors. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -36,7 +37,7 @@ std::unique_ptr BasePacket::create(qint64 size) { } std::unique_ptr BasePacket::fromReceivedPacket(std::unique_ptr data, - qint64 size, const HifiSockAddr& senderSockAddr) { + qint64 size, const SockAddr& senderSockAddr) { // Fail with invalid size Q_ASSERT(size >= 0); @@ -66,7 +67,7 @@ BasePacket::BasePacket(qint64 size) { _payloadStart = _packet.get(); } -BasePacket::BasePacket(std::unique_ptr data, qint64 size, const HifiSockAddr& senderSockAddr) : +BasePacket::BasePacket(std::unique_ptr data, qint64 size, const SockAddr& senderSockAddr) : _packetSize(size), _packet(std::move(data)), _payloadStart(_packet.get()), diff --git a/libraries/networking/src/udt/BasePacket.h b/libraries/networking/src/udt/BasePacket.h index 4981cb4720..b196f5de24 100644 --- a/libraries/networking/src/udt/BasePacket.h +++ b/libraries/networking/src/udt/BasePacket.h @@ -4,6 +4,7 @@ // // Created by Stephen Birarda on 2015-07-23. // Copyright 2015 High Fidelity, Inc. +// Copyright 2021 Vircadia contributors. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -18,7 +19,7 @@ #include -#include "../HifiSockAddr.h" +#include "../SockAddr.h" #include "Constants.h" #include "../ExtendedIODevice.h" @@ -31,7 +32,7 @@ public: static std::unique_ptr create(qint64 size = -1); static std::unique_ptr fromReceivedPacket(std::unique_ptr data, qint64 size, - const HifiSockAddr& senderSockAddr); + const SockAddr& senderSockAddr); // Current level's header size static int localHeaderSize(); @@ -66,8 +67,8 @@ public: qint64 bytesLeftToRead() const { return _payloadSize - pos(); } qint64 bytesAvailableForWrite() const { return _payloadCapacity - pos(); } - HifiSockAddr& getSenderSockAddr() { return _senderSockAddr; } - const HifiSockAddr& getSenderSockAddr() const { return _senderSockAddr; } + SockAddr& getSenderSockAddr() { return _senderSockAddr; } + const SockAddr& getSenderSockAddr() const { return _senderSockAddr; } // QIODevice virtual functions // WARNING: Those methods all refer to the payload ONLY and NOT the entire packet @@ -87,7 +88,7 @@ public: protected: BasePacket(qint64 size); - BasePacket(std::unique_ptr data, qint64 size, const HifiSockAddr& senderSockAddr); + BasePacket(std::unique_ptr data, qint64 size, const SockAddr& senderSockAddr); BasePacket(const BasePacket& other) : ExtendedIODevice() { *this = other; } BasePacket& operator=(const BasePacket& other); BasePacket(BasePacket&& other); @@ -107,7 +108,7 @@ protected: qint64 _payloadSize = 0; // How much of the payload is actually used - HifiSockAddr _senderSockAddr; // sender address for packet (only used on receiving end) + SockAddr _senderSockAddr; // sender address for packet (only used on receiving end) p_high_resolution_clock::time_point _receiveTime; // captures the time the packet received (only used on receiving end) }; diff --git a/libraries/networking/src/udt/Connection.cpp b/libraries/networking/src/udt/Connection.cpp index 338b95163f..66bf3f6613 100644 --- a/libraries/networking/src/udt/Connection.cpp +++ b/libraries/networking/src/udt/Connection.cpp @@ -4,6 +4,7 @@ // // Created by Clement on 7/27/15. // Copyright 2015 High Fidelity, Inc. +// Copyright 2021 Vircadia contributors. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -17,7 +18,7 @@ #include -#include "../HifiSockAddr.h" +#include "../SockAddr.h" #include "../NetworkLogging.h" #include "CongestionControl.h" @@ -30,7 +31,7 @@ using namespace udt; using namespace std::chrono; -Connection::Connection(Socket* parentSocket, HifiSockAddr destination, std::unique_ptr congestionControl) : +Connection::Connection(Socket* parentSocket, SockAddr destination, std::unique_ptr congestionControl) : _parentSocket(parentSocket), _destination(destination), _congestionControl(move(congestionControl)) @@ -485,7 +486,7 @@ std::unique_ptr PendingReceivedMessage::removeNextPacket() { return std::unique_ptr(); } -void Connection::setDestinationAddress(const HifiSockAddr& destination) { +void Connection::setDestinationAddress(const SockAddr& destination) { if (_destination != destination) { _destination = destination; emit destinationAddressChange(destination); diff --git a/libraries/networking/src/udt/Connection.h b/libraries/networking/src/udt/Connection.h index 00d5beb5ab..2869b7f57d 100644 --- a/libraries/networking/src/udt/Connection.h +++ b/libraries/networking/src/udt/Connection.h @@ -4,6 +4,7 @@ // // Created by Clement on 7/27/15. // Copyright 2015 High Fidelity, Inc. +// Copyright 2021 Vircadia contributors. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -23,7 +24,7 @@ #include "Constants.h" #include "LossList.h" #include "SendQueue.h" -#include "../HifiSockAddr.h" +#include "../SockAddr.h" namespace udt { @@ -52,7 +53,7 @@ class Connection : public QObject { public: using ControlPacketPointer = std::unique_ptr; - Connection(Socket* parentSocket, HifiSockAddr destination, std::unique_ptr congestionControl); + Connection(Socket* parentSocket, SockAddr destination, std::unique_ptr congestionControl); virtual ~Connection(); void sendReliablePacket(std::unique_ptr packet); @@ -68,7 +69,7 @@ public: ConnectionStats::Stats sampleStats() { return _stats.sample(); } - HifiSockAddr getDestination() const { return _destination; } + SockAddr getDestination() const { return _destination; } void setMaxBandwidth(int maxBandwidth); @@ -77,12 +78,12 @@ public: void recordSentUnreliablePackets(int wireSize, int payloadSize); void recordReceivedUnreliablePackets(int wireSize, int payloadSize); - void setDestinationAddress(const HifiSockAddr& destination); + void setDestinationAddress(const SockAddr& destination); signals: void packetSent(); - void receiverHandshakeRequestComplete(const HifiSockAddr& sockAddr); - void destinationAddressChange(HifiSockAddr currentAddress); + void receiverHandshakeRequestComplete(const SockAddr& sockAddr); + void destinationAddressChange(SockAddr currentAddress); private slots: void recordSentPackets(int wireSize, int payloadSize, SequenceNumber seqNum, p_high_resolution_clock::time_point timePoint); @@ -124,7 +125,7 @@ private: SequenceNumber _lastReceivedACK; // The last ACK received Socket* _parentSocket { nullptr }; - HifiSockAddr _destination; + SockAddr _destination; std::unique_ptr _congestionControl; diff --git a/libraries/networking/src/udt/ControlPacket.cpp b/libraries/networking/src/udt/ControlPacket.cpp index 6fdefd36f6..b56f455030 100644 --- a/libraries/networking/src/udt/ControlPacket.cpp +++ b/libraries/networking/src/udt/ControlPacket.cpp @@ -4,6 +4,7 @@ // // Created by Stephen Birarda on 2015-07-24. // Copyright 2015 High Fidelity, Inc. +// Copyright 2021 Vircadia contributors. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -26,7 +27,7 @@ int ControlPacket::maxPayloadSize() { } std::unique_ptr ControlPacket::fromReceivedPacket(std::unique_ptr data, qint64 size, - const HifiSockAddr &senderSockAddr) { + const SockAddr &senderSockAddr) { // Fail with null data Q_ASSERT(data); @@ -56,7 +57,7 @@ ControlPacket::ControlPacket(Type type, qint64 size) : writeType(); } -ControlPacket::ControlPacket(std::unique_ptr data, qint64 size, const HifiSockAddr& senderSockAddr) : +ControlPacket::ControlPacket(std::unique_ptr data, qint64 size, const SockAddr& senderSockAddr) : BasePacket(std::move(data), size, senderSockAddr) { // sanity check before we decrease the payloadSize with the payloadCapacity diff --git a/libraries/networking/src/udt/ControlPacket.h b/libraries/networking/src/udt/ControlPacket.h index 46b9cdbd40..772df41455 100644 --- a/libraries/networking/src/udt/ControlPacket.h +++ b/libraries/networking/src/udt/ControlPacket.h @@ -4,6 +4,7 @@ // // Created by Stephen Birarda on 2015-07-24. // Copyright 2015 High Fidelity, Inc. +// Copyright 2021 Vircadia contributors. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -35,7 +36,7 @@ public: static std::unique_ptr create(Type type, qint64 size = -1); static std::unique_ptr fromReceivedPacket(std::unique_ptr data, qint64 size, - const HifiSockAddr& senderSockAddr); + const SockAddr& senderSockAddr); // Current level's header size static int localHeaderSize(); // Cumulated size of all the headers @@ -48,7 +49,7 @@ public: private: ControlPacket(Type type, qint64 size = -1); - ControlPacket(std::unique_ptr data, qint64 size, const HifiSockAddr& senderSockAddr); + ControlPacket(std::unique_ptr data, qint64 size, const SockAddr& senderSockAddr); ControlPacket(ControlPacket&& other); ControlPacket(const ControlPacket& other) = delete; diff --git a/libraries/networking/src/udt/Packet.cpp b/libraries/networking/src/udt/Packet.cpp index f8b74cea37..8c8f72457c 100644 --- a/libraries/networking/src/udt/Packet.cpp +++ b/libraries/networking/src/udt/Packet.cpp @@ -4,6 +4,7 @@ // // Created by Clement on 7/2/15. // Copyright 2015 High Fidelity, Inc. +// Copyright 2021 Vircadia contributors. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -61,7 +62,7 @@ std::unique_ptr Packet::create(qint64 size, bool isReliable, bool isPart return packet; } -std::unique_ptr Packet::fromReceivedPacket(std::unique_ptr data, qint64 size, const HifiSockAddr& senderSockAddr) { +std::unique_ptr Packet::fromReceivedPacket(std::unique_ptr data, qint64 size, const SockAddr& senderSockAddr) { // Fail with invalid size Q_ASSERT(size >= 0); @@ -87,7 +88,7 @@ Packet::Packet(qint64 size, bool isReliable, bool isPartOfMessage) : writeHeader(); } -Packet::Packet(std::unique_ptr data, qint64 size, const HifiSockAddr& senderSockAddr) : +Packet::Packet(std::unique_ptr data, qint64 size, const SockAddr& senderSockAddr) : BasePacket(std::move(data), size, senderSockAddr) { readHeader(); diff --git a/libraries/networking/src/udt/Packet.h b/libraries/networking/src/udt/Packet.h index 36098235f9..b852635d33 100644 --- a/libraries/networking/src/udt/Packet.h +++ b/libraries/networking/src/udt/Packet.h @@ -4,6 +4,7 @@ // // Created by Clement on 7/2/15. // Copyright 2015 High Fidelity, Inc. +// Copyright 2021 Vircadia contributors. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -69,7 +70,7 @@ public: }; static std::unique_ptr create(qint64 size = -1, bool isReliable = false, bool isPartOfMessage = false); - static std::unique_ptr fromReceivedPacket(std::unique_ptr data, qint64 size, const HifiSockAddr& senderSockAddr); + static std::unique_ptr fromReceivedPacket(std::unique_ptr data, qint64 size, const SockAddr& senderSockAddr); // Provided for convenience, try to limit use static std::unique_ptr createCopy(const Packet& other); @@ -97,7 +98,7 @@ public: protected: Packet(qint64 size, bool isReliable = false, bool isPartOfMessage = false); - Packet(std::unique_ptr data, qint64 size, const HifiSockAddr& senderSockAddr); + Packet(std::unique_ptr data, qint64 size, const SockAddr& senderSockAddr); Packet(const Packet& other); Packet(Packet&& other); diff --git a/libraries/networking/src/udt/PacketList.cpp b/libraries/networking/src/udt/PacketList.cpp index f6ea12242e..d29e79626b 100644 --- a/libraries/networking/src/udt/PacketList.cpp +++ b/libraries/networking/src/udt/PacketList.cpp @@ -4,6 +4,7 @@ // // Created by Clement on 7/13/15. // Copyright 2015 High Fidelity, Inc. +// Copyright 2021 Vircadia contributors. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -53,8 +54,8 @@ PacketList::PacketList(PacketList&& other) : { } -HifiSockAddr PacketList::getSenderSockAddr() const { - return _packets.size() > 0 ? _packets.front()->getSenderSockAddr() : HifiSockAddr(); +SockAddr PacketList::getSenderSockAddr() const { + return _packets.size() > 0 ? _packets.front()->getSenderSockAddr() : SockAddr(); } void PacketList::startSegment() { diff --git a/libraries/networking/src/udt/PacketList.h b/libraries/networking/src/udt/PacketList.h index 8d3ffb2783..af2adf1ddb 100644 --- a/libraries/networking/src/udt/PacketList.h +++ b/libraries/networking/src/udt/PacketList.h @@ -4,6 +4,7 @@ // // Created by Clement on 7/13/15. // Copyright 2015 High Fidelity, Inc. +// Copyright 2021 Vircadia contributors. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -50,7 +51,7 @@ public: virtual qint64 getMaxSegmentSize() const { return Packet::maxPayloadSize(_isOrdered); } - HifiSockAddr getSenderSockAddr() const; + SockAddr getSenderSockAddr() const; void closeCurrentPacket(bool shouldSendEmpty = false); diff --git a/libraries/networking/src/udt/SendQueue.cpp b/libraries/networking/src/udt/SendQueue.cpp index 63447f6e70..9bea47f89e 100644 --- a/libraries/networking/src/udt/SendQueue.cpp +++ b/libraries/networking/src/udt/SendQueue.cpp @@ -4,6 +4,7 @@ // // Created by Clement on 7/21/15. // Copyright 2015 High Fidelity, Inc. +// Copyright 2021 Vircadia contributors. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -65,7 +66,7 @@ private: const microseconds SendQueue::MAXIMUM_ESTIMATED_TIMEOUT = seconds(5); const microseconds SendQueue::MINIMUM_ESTIMATED_TIMEOUT = milliseconds(10); -std::unique_ptr SendQueue::create(Socket* socket, HifiSockAddr destination, SequenceNumber currentSequenceNumber, +std::unique_ptr SendQueue::create(Socket* socket, SockAddr destination, SequenceNumber currentSequenceNumber, MessageNumber currentMessageNumber, bool hasReceivedHandshakeACK) { Q_ASSERT_X(socket, "SendQueue::create", "Must be called with a valid Socket*"); @@ -91,7 +92,7 @@ std::unique_ptr SendQueue::create(Socket* socket, HifiSockAddr destin return queue; } -SendQueue::SendQueue(Socket* socket, HifiSockAddr dest, SequenceNumber currentSequenceNumber, +SendQueue::SendQueue(Socket* socket, SockAddr dest, SequenceNumber currentSequenceNumber, MessageNumber currentMessageNumber, bool hasReceivedHandshakeACK) : _packets(currentMessageNumber), _socket(socket), @@ -561,6 +562,6 @@ bool SendQueue::isFlowWindowFull() const { return seqlen(SequenceNumber { (uint32_t) _lastACKSequenceNumber }, _currentSequenceNumber) > _flowWindowSize; } -void SendQueue::updateDestinationAddress(HifiSockAddr newAddress) { +void SendQueue::updateDestinationAddress(SockAddr newAddress) { _destination = newAddress; } diff --git a/libraries/networking/src/udt/SendQueue.h b/libraries/networking/src/udt/SendQueue.h index 2153745250..ef3ad8bd16 100644 --- a/libraries/networking/src/udt/SendQueue.h +++ b/libraries/networking/src/udt/SendQueue.h @@ -4,6 +4,7 @@ // // Created by Clement on 7/21/15. // Copyright 2015 High Fidelity, Inc. +// Copyright 2021 Vircadia contributors. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -25,7 +26,7 @@ #include -#include "../HifiSockAddr.h" +#include "../SockAddr.h" #include "Constants.h" #include "PacketQueue.h" @@ -50,7 +51,7 @@ public: Stopped }; - static std::unique_ptr create(Socket* socket, HifiSockAddr destination, + static std::unique_ptr create(Socket* socket, SockAddr destination, SequenceNumber currentSequenceNumber, MessageNumber currentMessageNumber, bool hasReceivedHandshakeACK); @@ -75,7 +76,7 @@ public slots: void ack(SequenceNumber ack); void fastRetransmit(SequenceNumber ack); void handshakeACK(); - void updateDestinationAddress(HifiSockAddr newAddress); + void updateDestinationAddress(SockAddr newAddress); signals: void packetSent(int wireSize, int payloadSize, SequenceNumber seqNum, p_high_resolution_clock::time_point timePoint); @@ -89,7 +90,7 @@ private slots: void run(); private: - SendQueue(Socket* socket, HifiSockAddr dest, SequenceNumber currentSequenceNumber, + SendQueue(Socket* socket, SockAddr dest, SequenceNumber currentSequenceNumber, MessageNumber currentMessageNumber, bool hasReceivedHandshakeACK); SendQueue(SendQueue& other) = delete; SendQueue(SendQueue&& other) = delete; @@ -113,7 +114,7 @@ private: PacketQueue _packets; Socket* _socket { nullptr }; // Socket to send packet on - HifiSockAddr _destination; // Destination addr + SockAddr _destination; // Destination addr std::atomic _lastACKSequenceNumber { 0 }; // Last ACKed sequence number diff --git a/libraries/networking/src/udt/Socket.cpp b/libraries/networking/src/udt/Socket.cpp index 017855d628..241ca1db85 100644 --- a/libraries/networking/src/udt/Socket.cpp +++ b/libraries/networking/src/udt/Socket.cpp @@ -4,6 +4,7 @@ // // Created by Stephen Birarda on 2015-07-20. // Copyright 2015 High Fidelity, Inc. +// Copyright 2021 Vircadia contributors. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -123,7 +124,7 @@ void Socket::setSystemBufferSizes() { } } -qint64 Socket::writeBasePacket(const udt::BasePacket& packet, const HifiSockAddr &sockAddr) { +qint64 Socket::writeBasePacket(const udt::BasePacket& packet, const SockAddr &sockAddr) { // Since this is a base packet we have no way to know if this is reliable or not - we just fire it off // this should not be called with an instance of Packet @@ -133,7 +134,7 @@ qint64 Socket::writeBasePacket(const udt::BasePacket& packet, const HifiSockAddr return writeDatagram(packet.getData(), packet.getDataSize(), sockAddr); } -qint64 Socket::writePacket(const Packet& packet, const HifiSockAddr& sockAddr) { +qint64 Socket::writePacket(const Packet& packet, const SockAddr& sockAddr) { Q_ASSERT_X(!packet.isReliable(), "Socket::writePacket", "Cannot send a reliable packet unreliably"); SequenceNumber sequenceNumber; @@ -154,7 +155,7 @@ qint64 Socket::writePacket(const Packet& packet, const HifiSockAddr& sockAddr) { return writeDatagram(packet.getData(), packet.getDataSize(), sockAddr); } -qint64 Socket::writePacket(std::unique_ptr packet, const HifiSockAddr& sockAddr) { +qint64 Socket::writePacket(std::unique_ptr packet, const SockAddr& sockAddr) { if (packet->isReliable()) { // hand this packet off to writeReliablePacket @@ -163,7 +164,7 @@ qint64 Socket::writePacket(std::unique_ptr packet, const HifiSockAddr& s if (QThread::currentThread() != thread()) { QMetaObject::invokeMethod(this, "writeReliablePacket", Qt::QueuedConnection, Q_ARG(Packet*, packet.release()), - Q_ARG(HifiSockAddr, sockAddr)); + Q_ARG(SockAddr, sockAddr)); } else { writeReliablePacket(packet.release(), sockAddr); } @@ -174,7 +175,7 @@ qint64 Socket::writePacket(std::unique_ptr packet, const HifiSockAddr& s return writePacket(*packet, sockAddr); } -qint64 Socket::writePacketList(std::unique_ptr packetList, const HifiSockAddr& sockAddr) { +qint64 Socket::writePacketList(std::unique_ptr packetList, const SockAddr& sockAddr) { if (packetList->getNumPackets() == 0) { qCWarning(networking) << "Trying to send packet list with 0 packets, bailing."; @@ -189,7 +190,7 @@ qint64 Socket::writePacketList(std::unique_ptr packetList, const Hif auto ptr = packetList.release(); QMetaObject::invokeMethod(this, "writeReliablePacketList", Qt::AutoConnection, Q_ARG(PacketList*, ptr), - Q_ARG(HifiSockAddr, sockAddr)); + Q_ARG(SockAddr, sockAddr)); } else { writeReliablePacketList(packetList.release(), sockAddr); } @@ -205,7 +206,7 @@ qint64 Socket::writePacketList(std::unique_ptr packetList, const Hif return totalBytesSent; } -void Socket::writeReliablePacket(Packet* packet, const HifiSockAddr& sockAddr) { +void Socket::writeReliablePacket(Packet* packet, const SockAddr& sockAddr) { auto connection = findOrCreateConnection(sockAddr); if (connection) { connection->sendReliablePacket(std::unique_ptr(packet)); @@ -218,7 +219,7 @@ void Socket::writeReliablePacket(Packet* packet, const HifiSockAddr& sockAddr) { } -void Socket::writeReliablePacketList(PacketList* packetList, const HifiSockAddr& sockAddr) { +void Socket::writeReliablePacketList(PacketList* packetList, const SockAddr& sockAddr) { auto connection = findOrCreateConnection(sockAddr); if (connection) { connection->sendReliablePacketList(std::unique_ptr(packetList)); @@ -230,11 +231,11 @@ void Socket::writeReliablePacketList(PacketList* packetList, const HifiSockAddr& #endif } -qint64 Socket::writeDatagram(const char* data, qint64 size, const HifiSockAddr& sockAddr) { +qint64 Socket::writeDatagram(const char* data, qint64 size, const SockAddr& sockAddr) { return writeDatagram(QByteArray::fromRawData(data, size), sockAddr); } -qint64 Socket::writeDatagram(const QByteArray& datagram, const HifiSockAddr& sockAddr) { +qint64 Socket::writeDatagram(const QByteArray& datagram, const SockAddr& sockAddr) { // don't attempt to write the datagram if we're unbound. Just drop it. // _udpSocket.writeDatagram will return an error anyway, but there are @@ -270,7 +271,7 @@ qint64 Socket::writeDatagram(const QByteArray& datagram, const HifiSockAddr& soc return bytesWritten; } -Connection* Socket::findOrCreateConnection(const HifiSockAddr& sockAddr, bool filterCreate) { +Connection* Socket::findOrCreateConnection(const SockAddr& sockAddr, bool filterCreate) { Lock connectionsLock(_connectionsHashMutex); auto it = _connectionsHash.find(sockAddr); @@ -319,7 +320,7 @@ void Socket::clearConnections() { } } -void Socket::cleanupConnection(HifiSockAddr sockAddr) { +void Socket::cleanupConnection(SockAddr sockAddr) { Lock connectionsLock(_connectionsHashMutex); auto numErased = _connectionsHash.erase(sockAddr); @@ -390,8 +391,8 @@ void Socket::readPendingDatagrams() { // grab a time point we can mark as the receive time of this packet auto receiveTime = p_high_resolution_clock::now(); - // setup a HifiSockAddr to read into - HifiSockAddr senderSockAddr; + // setup a SockAddr to read into + SockAddr senderSockAddr; // setup a buffer to read the packet into auto buffer = std::unique_ptr(new char[packetSizeWithHeader]); @@ -413,7 +414,7 @@ void Socket::readPendingDatagrams() { auto it = _unfilteredHandlers.find(senderSockAddr); if (it != _unfilteredHandlers.end()) { - // we have a registered unfiltered handler for this HifiSockAddr - call that and return + // we have a registered unfiltered handler for this SockAddr - call that and return if (it->second) { auto basePacket = BasePacket::fromReceivedPacket(std::move(buffer), packetSizeWithHeader, senderSockAddr); basePacket->setReceiveTime(receiveTime); @@ -482,7 +483,7 @@ void Socket::readPendingDatagrams() { } } -void Socket::connectToSendSignal(const HifiSockAddr& destinationAddr, QObject* receiver, const char* slot) { +void Socket::connectToSendSignal(const SockAddr& destinationAddr, QObject* receiver, const char* slot) { Lock connectionsLock(_connectionsHashMutex); auto it = _connectionsHash.find(destinationAddr); if (it != _connectionsHash.end()) { @@ -507,7 +508,7 @@ void Socket::setConnectionMaxBandwidth(int maxBandwidth) { } } -ConnectionStats::Stats Socket::sampleStatsForConnection(const HifiSockAddr& destination) { +ConnectionStats::Stats Socket::sampleStatsForConnection(const SockAddr& destination) { auto it = _connectionsHash.find(destination); if (it != _connectionsHash.end()) { return it->second->sampleStats(); @@ -528,8 +529,8 @@ Socket::StatsVector Socket::sampleStatsForAllConnections() { } -std::vector Socket::getConnectionSockAddrs() { - std::vector addr; +std::vector Socket::getConnectionSockAddrs() { + std::vector addr; Lock connectionsLock(_connectionsHashMutex); addr.reserve(_connectionsHash.size()); @@ -569,7 +570,7 @@ void Socket::handleStateChanged(QAbstractSocket::SocketState socketState) { } } -void Socket::handleRemoteAddressChange(HifiSockAddr previousAddress, HifiSockAddr currentAddress) { +void Socket::handleRemoteAddressChange(SockAddr previousAddress, SockAddr currentAddress) { { Lock connectionsLock(_connectionsHashMutex); @@ -597,7 +598,7 @@ void Socket::handleRemoteAddressChange(HifiSockAddr previousAddress, HifiSockAdd #if (PR_BUILD || DEV_BUILD) -void Socket::sendFakedHandshakeRequest(const HifiSockAddr& sockAddr) { +void Socket::sendFakedHandshakeRequest(const SockAddr& sockAddr) { auto connection = findOrCreateConnection(sockAddr); if (connection) { connection->sendHandshakeRequest(); diff --git a/libraries/networking/src/udt/Socket.h b/libraries/networking/src/udt/Socket.h index 6cd2d25659..8c46a22335 100644 --- a/libraries/networking/src/udt/Socket.h +++ b/libraries/networking/src/udt/Socket.h @@ -4,6 +4,7 @@ // // Created by Stephen Birarda on 2015-07-20. // Copyright 2015 High Fidelity, Inc. +// Copyright 2021 Vircadia contributors. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -23,7 +24,7 @@ #include #include -#include "../HifiSockAddr.h" +#include "../SockAddr.h" #include "TCPVegasCC.h" #include "Connection.h" @@ -39,12 +40,12 @@ class PacketList; class SequenceNumber; using PacketFilterOperator = std::function; -using ConnectionCreationFilterOperator = std::function; +using ConnectionCreationFilterOperator = std::function; using BasePacketHandler = std::function)>; using PacketHandler = std::function)>; using MessageHandler = std::function)>; -using MessageFailureHandler = std::function; +using MessageFailureHandler = std::function; class Socket : public QObject { Q_OBJECT @@ -53,19 +54,19 @@ class Socket : public QObject { using Lock = std::unique_lock; public: - using StatsVector = std::vector>; + using StatsVector = std::vector>; Socket(QObject* object = 0, bool shouldChangeSocketOptions = true); quint16 localPort() const { return _udpSocket.localPort(); } // Simple functions writing to the socket with no processing - qint64 writeBasePacket(const BasePacket& packet, const HifiSockAddr& sockAddr); - qint64 writePacket(const Packet& packet, const HifiSockAddr& sockAddr); - qint64 writePacket(std::unique_ptr packet, const HifiSockAddr& sockAddr); - qint64 writePacketList(std::unique_ptr packetList, const HifiSockAddr& sockAddr); - qint64 writeDatagram(const char* data, qint64 size, const HifiSockAddr& sockAddr); - qint64 writeDatagram(const QByteArray& datagram, const HifiSockAddr& sockAddr); + qint64 writeBasePacket(const BasePacket& packet, const SockAddr& sockAddr); + qint64 writePacket(const Packet& packet, const SockAddr& sockAddr); + qint64 writePacket(std::unique_ptr packet, const SockAddr& sockAddr); + qint64 writePacketList(std::unique_ptr packetList, const SockAddr& sockAddr); + qint64 writeDatagram(const char* data, qint64 size, const SockAddr& sockAddr); + qint64 writeDatagram(const QByteArray& datagram, const SockAddr& sockAddr); void bind(const QHostAddress& address, quint16 port = 0); void rebind(quint16 port); @@ -78,7 +79,7 @@ public: void setConnectionCreationFilterOperator(ConnectionCreationFilterOperator filterOperator) { _connectionCreationFilterOperator = filterOperator; } - void addUnfilteredHandler(const HifiSockAddr& senderSockAddr, BasePacketHandler handler) + void addUnfilteredHandler(const SockAddr& senderSockAddr, BasePacketHandler handler) { _unfilteredHandlers[senderSockAddr] = handler; } void setCongestionControlFactory(std::unique_ptr ccFactory); @@ -90,16 +91,16 @@ public: StatsVector sampleStatsForAllConnections(); #if (PR_BUILD || DEV_BUILD) - void sendFakedHandshakeRequest(const HifiSockAddr& sockAddr); + void sendFakedHandshakeRequest(const SockAddr& sockAddr); #endif signals: - void clientHandshakeRequestComplete(const HifiSockAddr& sockAddr); + void clientHandshakeRequestComplete(const SockAddr& sockAddr); public slots: - void cleanupConnection(HifiSockAddr sockAddr); + void cleanupConnection(SockAddr sockAddr); void clearConnections(); - void handleRemoteAddressChange(HifiSockAddr previousAddress, HifiSockAddr currentAddress); + void handleRemoteAddressChange(SockAddr previousAddress, SockAddr currentAddress); private slots: void readPendingDatagrams(); @@ -110,16 +111,16 @@ private slots: private: void setSystemBufferSizes(); - Connection* findOrCreateConnection(const HifiSockAddr& sockAddr, bool filterCreation = false); + Connection* findOrCreateConnection(const SockAddr& sockAddr, bool filterCreation = false); // privatized methods used by UDTTest - they are private since they must be called on the Socket thread - ConnectionStats::Stats sampleStatsForConnection(const HifiSockAddr& destination); + ConnectionStats::Stats sampleStatsForConnection(const SockAddr& destination); - std::vector getConnectionSockAddrs(); - void connectToSendSignal(const HifiSockAddr& destinationAddr, QObject* receiver, const char* slot); + std::vector getConnectionSockAddrs(); + void connectToSendSignal(const SockAddr& destinationAddr, QObject* receiver, const char* slot); - Q_INVOKABLE void writeReliablePacket(Packet* packet, const HifiSockAddr& sockAddr); - Q_INVOKABLE void writeReliablePacketList(PacketList* packetList, const HifiSockAddr& sockAddr); + Q_INVOKABLE void writeReliablePacket(Packet* packet, const SockAddr& sockAddr); + Q_INVOKABLE void writeReliablePacketList(PacketList* packetList, const SockAddr& sockAddr); QUdpSocket _udpSocket { this }; PacketFilterOperator _packetFilterOperator; @@ -131,9 +132,9 @@ private: Mutex _unreliableSequenceNumbersMutex; Mutex _connectionsHashMutex; - std::unordered_map _unfilteredHandlers; - std::unordered_map _unreliableSequenceNumbers; - std::unordered_map> _connectionsHash; + std::unordered_map _unfilteredHandlers; + std::unordered_map _unreliableSequenceNumbers; + std::unordered_map> _connectionsHash; QTimer* _readyReadBackupTimer { nullptr }; @@ -145,7 +146,7 @@ private: int _lastPacketSizeRead { 0 }; SequenceNumber _lastReceivedSequenceNumber; - HifiSockAddr _lastPacketSockAddr; + SockAddr _lastPacketSockAddr; friend UDTTest; }; diff --git a/libraries/procedural/src/procedural/Procedural.h b/libraries/procedural/src/procedural/Procedural.h index ee301d0a72..39c619c687 100644 --- a/libraries/procedural/src/procedural/Procedural.h +++ b/libraries/procedural/src/procedural/Procedural.h @@ -40,7 +40,7 @@ const size_t MAX_PROCEDURAL_TEXTURE_CHANNELS{ 4 }; * If a procedural material contains a vertex shader, the bounding box of the material entity is used to cull the object to which the material is applied. * @property {string} fragmentShaderURL - A link to a fragment shader. Currently, only GLSL shaders are supported. The shader must implement a different method depending on the version. * shaderUrl is an alias. - * @property {string[]} channels=[] - An array of input texture URLs. Currently, up to 4 are supported. + * @property {string[]} channels=[] - An array of input texture URLs or entity IDs. Currently, up to 4 are supported. An entity ID may be that of an Image or Web entity. * @property {ProceduralUniforms} uniforms={} - A {@link ProceduralUniforms} object containing all the custom uniforms to be passed to the shader. */ @@ -212,26 +212,26 @@ public: ProceduralMaterial() : NetworkMaterial() { initializeProcedural(); } ProceduralMaterial(const NetworkMaterial& material) : NetworkMaterial(material) { initializeProcedural(); } - bool isProcedural() const override { return true; } - bool isEnabled() const override { return _procedural.isEnabled(); } - bool isReady() const override { return _procedural.isReady(); } - QString getProceduralString() const override { return _proceduralString; } + virtual bool isProcedural() const override { return true; } + virtual bool isEnabled() const override { return _procedural.isEnabled(); } + virtual bool isReady() const override { return _procedural.isReady(); } + virtual QString getProceduralString() const override { return _proceduralString; } void setProceduralData(const QString& data) { _proceduralString = data; _procedural.setProceduralData(ProceduralData::parse(data)); } - glm::vec4 getColor(const glm::vec4& color) const { return _procedural.getColor(color); } - bool isFading() const { return _procedural.isFading(); } + virtual glm::vec4 getColor(const glm::vec4& color) const { return _procedural.getColor(color); } + virtual bool isFading() const { return _procedural.isFading(); } void setIsFading(bool isFading) { _procedural.setIsFading(isFading); } - uint64_t getFadeStartTime() const { return _procedural.getFadeStartTime(); } - bool hasVertexShader() const { return _procedural.hasVertexShader(); } - void prepare(gpu::Batch& batch, const glm::vec3& position, const glm::vec3& size, const glm::quat& orientation, + virtual uint64_t getFadeStartTime() const { return _procedural.getFadeStartTime(); } + virtual bool hasVertexShader() const { return _procedural.hasVertexShader(); } + virtual void prepare(gpu::Batch& batch, const glm::vec3& position, const glm::vec3& size, const glm::quat& orientation, const uint64_t& created, const ProceduralProgramKey key = ProceduralProgramKey()) { _procedural.prepare(batch, position, size, orientation, created, key); } - void initializeProcedural(); + virtual void initializeProcedural(); void setBoundOperator(const std::function& boundOperator) { _procedural.setBoundOperator(boundOperator); } bool hasBoundOperator() const { return _procedural.hasBoundOperator(); } @@ -243,4 +243,4 @@ private: }; typedef std::shared_ptr ProceduralMaterialPointer; -} \ No newline at end of file +} diff --git a/libraries/procedural/src/procedural/ProceduralMaterialCache.cpp b/libraries/procedural/src/procedural/ProceduralMaterialCache.cpp index af31418bf0..d99f74769c 100644 --- a/libraries/procedural/src/procedural/ProceduralMaterialCache.cpp +++ b/libraries/procedural/src/procedural/ProceduralMaterialCache.cpp @@ -14,6 +14,7 @@ #include "RegisteredMetaTypes.h" #include "Procedural.h" +#include "ReferenceMaterial.h" NetworkMaterialResource::NetworkMaterialResource(const QUrl& url) : Resource(url) {} @@ -75,7 +76,8 @@ bool NetworkMaterialResource::parseJSONColor(const QJsonValue& array, glm::vec3& * A material or set of materials used by a {@link Entities.EntityType|Material entity}. * @typedef {object} Entities.MaterialResource * @property {number} materialVersion=1 - The version of the material. Currently not used. - * @property {Entities.Material|Entities.Material[]} materials - The details of the material or materials. + * @property {Entities.Material|Entities.Material[]|string} materials - The details of the material or materials, or the ID of another + * Material entity. */ NetworkMaterialResource::ParsedMaterials NetworkMaterialResource::parseJSONMaterials(const QJsonDocument& materialJSON, const QUrl& baseUrl) { ParsedMaterials toReturn; @@ -92,14 +94,14 @@ NetworkMaterialResource::ParsedMaterials NetworkMaterialResource::parseJSONMater if (materialsValue.isArray()) { QJsonArray materials = materialsValue.toArray(); for (auto material : materials) { - if (!material.isNull() && material.isObject()) { - auto parsedMaterial = parseJSONMaterial(material.toObject(), baseUrl); + if (!material.isNull() && (material.isObject() || material.isString())) { + auto parsedMaterial = parseJSONMaterial(material, baseUrl); toReturn.networkMaterials[parsedMaterial.first] = parsedMaterial.second; toReturn.names.push_back(parsedMaterial.first); } } - } else if (materialsValue.isObject()) { - auto parsedMaterial = parseJSONMaterial(materialsValue.toObject(), baseUrl); + } else if (materialsValue.isObject() || materialsValue.isString()) { + auto parsedMaterial = parseJSONMaterial(materialsValue, baseUrl); toReturn.networkMaterials[parsedMaterial.first] = parsedMaterial.second; toReturn.names.push_back(parsedMaterial.first); } @@ -110,6 +112,17 @@ NetworkMaterialResource::ParsedMaterials NetworkMaterialResource::parseJSONMater return toReturn; } +NetworkMaterialResource::ParsedMaterials NetworkMaterialResource::parseMaterialForUUID(const QJsonValue& entityIDJSON) { + ParsedMaterials toReturn; + if (!entityIDJSON.isNull() && entityIDJSON.isString()) { + auto parsedMaterial = parseJSONMaterial(entityIDJSON); + toReturn.networkMaterials[parsedMaterial.first] = parsedMaterial.second; + toReturn.names.push_back(parsedMaterial.first); + } + + return toReturn; +} + /*@jsdoc * A material used in a {@link Entities.MaterialResource|MaterialResource}. * @typedef {object} Entities.Material @@ -136,12 +149,14 @@ NetworkMaterialResource::ParsedMaterials NetworkMaterialResource::parseJSONMater * Set to "fallthrough" to fall through to the material below. "hifi_pbr" model only. * @property {number|string} scattering - The scattering, range 0.01.0. * Set to "fallthrough" to fall through to the material below. "hifi_pbr" model only. - * @property {string} emissiveMap - The URL of the emissive texture image. - * Set to "fallthrough" to fall through to the material below. "hifi_pbr" model only. - * @property {string} albedoMap - The URL of the albedo texture image. - * Set to "fallthrough" to fall through to the material below. "hifi_pbr" model only. - * @property {string} opacityMap - The URL of the opacity texture image. Set the value the same as the albedoMap - * value for transparency. + * @property {string} emissiveMap - The URL of the emissive texture image, or an entity ID. An entity ID may be that of an + * Image or Web entity. Set to "fallthrough" to fall through to the material below. + * "hifi_pbr" model only. + * @property {string} albedoMap - The URL of the albedo texture image, or an entity ID. An entity ID may be that of an Image + * or Web entity. Set to "fallthrough" to fall through to the material below. "hifi_pbr" + * model only. + * @property {string} opacityMap - The URL of the opacity texture image, or an entity ID. An entity ID may be that of an Image + * or Web entity. Set the value the same as the albedoMap value for transparency. * "hifi_pbr" model only. * @property {string} opacityMapMode - The mode defining the interpretation of the opacity map. Values can be: *
    @@ -176,23 +191,27 @@ NetworkMaterialResource::ParsedMaterials NetworkMaterialResource::parseJSONMater * @property {string} glossMap - The URL of the gloss texture image. You can use this or roughnessMap, but not * both. * Set to "fallthrough" to fall through to the material below. "hifi_pbr" model only. - * @property {string} metallicMap - The URL of the metallic texture image. You can use this or specularMap, but - * not both. + * @property {string} metallicMap - The URL of the metallic texture image, or an entity ID. An entity ID may be that of an + * Image or Web entity. You can use this or specularMap, but not both. * Set to "fallthrough" to fall through to the material below. "hifi_pbr" model only. - * @property {string} specularMap - The URL of the specular texture image. You can use this or metallicMap, but - * not both. + * @property {string} specularMap - The URL of the specular texture image, or an entity ID. An entity ID may be that of an + * Image or Web entity. You can use this or metallicMap, but not both. * Set to "fallthrough" to fall through to the material below. "hifi_pbr" model only. - * @property {string} normalMap - The URL of the normal texture image. You can use this or bumpMap, but not both. - * Set to "fallthrough" to fall through to the material below. "hifi_pbr" model only. - * @property {string} bumpMap - The URL of the bump texture image. You can use this or normalMap, but not both. - * Set to "fallthrough" to fall through to the material below. "hifi_pbr" model only. - * @property {string} occlusionMap - The URL of the occlusion texture image. - * Set to "fallthrough" to fall through to the material below. "hifi_pbr" model only. - * @property {string} scatteringMap - The URL of the scattering texture image. Only used if normalMap or - * bumpMap is specified. - * Set to "fallthrough" to fall through to the material below. "hifi_pbr" model only. - * @property {string} lightMap - The URL of the light map texture image. + * @property {string} normalMap - The URL of the normal texture image, or an entity ID. An entity ID may be that of an Image + * or Web entity. You can use this or bumpMap, but not both. Set to "fallthrough" to fall + * through to the material below. "hifi_pbr" model only. + * @property {string} bumpMap - The URL of the bump texture image, or an entity ID. An entity ID may be that of an Image + * or Web entity. You can use this or normalMap, but not both. Set to "fallthrough" to + * fall through to the material below. "hifi_pbr" model only. + * @property {string} occlusionMap - The URL of the occlusion texture image, or an entity ID. An entity ID may be that of + * an Image or Web entity. Set to "fallthrough" to fall through to the material below. + * "hifi_pbr" model only. + * @property {string} scatteringMap - The URL of the scattering texture image, or an entity ID. An entity ID may be that of an + * Image or Web entity. Only used if normalMap or bumpMap is specified. * Set to "fallthrough" to fall through to the material below. "hifi_pbr" model only. + * @property {string} lightMap - The URL of the light map texture image, or an entity ID. An entity ID may be that of an Image + * or Web entity. Set to "fallthrough" to fall through to the material below. "hifi_pbr" + * model only. * @property {Mat4|string} texCoordTransform0 - The transform to use for all of the maps apart from occlusionMap * and lightMap. * Set to "fallthrough" to fall through to the material below. "hifi_pbr" model only. @@ -210,10 +229,22 @@ NetworkMaterialResource::ParsedMaterials NetworkMaterialResource::parseJSONMater * @property {ProceduralData} procedural - The definition of a procedural shader material. "hifi_shader_simple" model only. */ // Note: See MaterialEntityItem.h for default values used in practice. -std::pair> NetworkMaterialResource::parseJSONMaterial(const QJsonObject& materialJSON, const QUrl& baseUrl) { +std::pair> NetworkMaterialResource::parseJSONMaterial(const QJsonValue& materialJSONValue, const QUrl& baseUrl) { std::string name = ""; std::shared_ptr networkMaterial; + if (materialJSONValue.isString()) { + QString uuidString = materialJSONValue.toString(); + name = uuidString.toStdString(); + QUuid uuid = QUuid(uuidString); + if (!uuid.isNull()) { + networkMaterial = std::make_shared(uuid); + } + return std::pair>(name, networkMaterial); + } + + QJsonObject materialJSON = materialJSONValue.toObject(); + std::string modelString = graphics::Material::HIFI_PBR; auto modelJSONIter = materialJSON.find("model"); if (modelJSONIter != materialJSON.end() && modelJSONIter.value().isString()) { diff --git a/libraries/procedural/src/procedural/ProceduralMaterialCache.h b/libraries/procedural/src/procedural/ProceduralMaterialCache.h index 0a44ccf0ef..ff0a8cf81c 100644 --- a/libraries/procedural/src/procedural/ProceduralMaterialCache.h +++ b/libraries/procedural/src/procedural/ProceduralMaterialCache.h @@ -33,8 +33,8 @@ public: void setScatteringMap(const QUrl& url); void setLightMap(const QUrl& url); - bool isMissingTexture(); - bool checkResetOpacityMap(); + virtual bool isMissingTexture(); + virtual bool checkResetOpacityMap(); class Texture { public: @@ -100,7 +100,8 @@ public: ParsedMaterials parsedMaterials; static ParsedMaterials parseJSONMaterials(const QJsonDocument& materialJSON, const QUrl& baseUrl); - static std::pair> parseJSONMaterial(const QJsonObject& materialJSON, const QUrl& baseUrl); + static ParsedMaterials parseMaterialForUUID(const QJsonValue& entityIDJSON); + static std::pair> parseJSONMaterial(const QJsonValue& materialJSONValue, const QUrl& baseUrl = QUrl()); private: static bool parseJSONColor(const QJsonValue& array, glm::vec3& color, bool& isSRGB); diff --git a/libraries/procedural/src/procedural/ReferenceMaterial.cpp b/libraries/procedural/src/procedural/ReferenceMaterial.cpp new file mode 100644 index 0000000000..97211eb737 --- /dev/null +++ b/libraries/procedural/src/procedural/ReferenceMaterial.cpp @@ -0,0 +1,266 @@ +// +// Created by HifiExperiments on 3/14/2021 +// Copyright 2021 Vircadia contributors. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include "ReferenceMaterial.h" + +std::function ReferenceMaterial::_unboundMaterialForUUIDOperator = nullptr; + +ReferenceMaterial::ReferenceMaterial(QUuid uuid) : + graphics::ProceduralMaterial() { + if (_unboundMaterialForUUIDOperator) { + _materialForUUIDOperator = std::bind(_unboundMaterialForUUIDOperator, uuid); + } +} + +// Material +graphics::MaterialKey ReferenceMaterial::getKey() const { + return resultWithLock([&] { + auto material = getMaterial(); + return material ? material->getKey() : Parent::getKey(); + }); +} + +glm::vec3 ReferenceMaterial::getEmissive(bool SRGB) const { + return resultWithLock([&] { + auto material = getMaterial(); + return material ? material->getEmissive(SRGB) : glm::vec3(DEFAULT_EMISSIVE); + }); +} + +float ReferenceMaterial::getOpacity() const { + return resultWithLock([&] { + auto material = getMaterial(); + return material ? material->getOpacity() : DEFAULT_OPACITY; + }); +} + +graphics::MaterialKey::OpacityMapMode ReferenceMaterial::getOpacityMapMode() const { + return resultWithLock([&] { + auto material = getMaterial(); + return material ? material->getOpacityMapMode() : DEFAULT_OPACITY_MAP_MODE; + }); +} + +float ReferenceMaterial::getOpacityCutoff() const { + return resultWithLock([&] { + auto material = getMaterial(); + return material ? material->getOpacityCutoff() : DEFAULT_OPACITY_CUTOFF; + }); +} + +graphics::MaterialKey::CullFaceMode ReferenceMaterial::getCullFaceMode() const { + return resultWithLock([&] { + auto material = getMaterial(); + return material ? material->getCullFaceMode() : DEFAULT_CULL_FACE_MODE; + }); +} + +bool ReferenceMaterial::isUnlit() const { + return resultWithLock([&] { + auto material = getMaterial(); + return material ? material->isUnlit() : false; + }); +} + +glm::vec3 ReferenceMaterial::getAlbedo(bool SRGB) const { + return resultWithLock([&] { + auto material = getMaterial(); + return material ? material->getAlbedo(SRGB) : glm::vec3(DEFAULT_ALBEDO); + }); +} + +float ReferenceMaterial::getMetallic() const { + return resultWithLock([&] { + auto material = getMaterial(); + return material ? material->getMetallic() : DEFAULT_METALLIC; + }); +} + +float ReferenceMaterial::getRoughness() const { + return resultWithLock([&] { + auto material = getMaterial(); + return material ? material->getRoughness() : DEFAULT_ROUGHNESS; + }); +} + +float ReferenceMaterial::getScattering() const { + return resultWithLock([&] { + auto material = getMaterial(); + return material ? material->getScattering() : DEFAULT_SCATTERING; + }); +} + +bool ReferenceMaterial::resetOpacityMap() const { + return resultWithLock([&] { + auto material = getMaterial(); + return material ? material->resetOpacityMap() : false; + }); +} + +graphics::Material::TextureMaps ReferenceMaterial::getTextureMaps() const { + return resultWithLock([&] { + auto material = getMaterial(); + return material ? material->getTextureMaps() : Parent::getTextureMaps(); + }); +} + +glm::vec2 ReferenceMaterial::getLightmapParams() const { + return resultWithLock([&] { + auto material = getMaterial(); + return material ? material->getLightmapParams() : glm::vec2(0.0f, 1.0f); + }); +} + +bool ReferenceMaterial::getDefaultFallthrough() const { + return resultWithLock([&] { + auto material = getMaterial(); + return material ? material->getDefaultFallthrough() : false; + }); +} + +// NetworkMaterial +bool ReferenceMaterial::isMissingTexture() { + return resultWithLock([&] { + auto material = getNetworkMaterial(); + return material ? material->isMissingTexture() : false; + }); +} + +bool ReferenceMaterial::checkResetOpacityMap() { + return resultWithLock([&] { + auto material = getNetworkMaterial(); + return material ? material->checkResetOpacityMap() : false; + }); +} + +// ProceduralMaterial +bool ReferenceMaterial::isProcedural() const { + return resultWithLock([&] { + auto material = getMaterial(); + return material ? material->isProcedural() : false; + }); +} + +bool ReferenceMaterial::isEnabled() const { + return resultWithLock([&] { + auto material = getMaterial(); + return material ? material->isEnabled() : false; + }); +} + +bool ReferenceMaterial::isReady() const { + return resultWithLock([&] { + auto material = getMaterial(); + return material ? material->isReady() : false; + }); +} + +QString ReferenceMaterial::getProceduralString() const { + return resultWithLock([&] { + auto material = getMaterial(); + return material ? material->getProceduralString() : QString(); + }); +} + +glm::vec4 ReferenceMaterial::getColor(const glm::vec4& color) const { + return resultWithLock([&] { + auto material = getProceduralMaterial(); + return material ? material->getColor(color) : glm::vec4(); + }); +} + +bool ReferenceMaterial::isFading() const { + return resultWithLock([&] { + auto material = getProceduralMaterial(); + return material ? material->isFading() : false; + }); +} + +uint64_t ReferenceMaterial::getFadeStartTime() const { + return resultWithLock([&] { + auto material = getProceduralMaterial(); + return material ? material->getFadeStartTime() : 0; + }); +} + +bool ReferenceMaterial::hasVertexShader() const { + return resultWithLock([&] { + auto material = getProceduralMaterial(); + return material ? material->hasVertexShader() : false; + }); +} + +void ReferenceMaterial::prepare(gpu::Batch& batch, const glm::vec3& position, const glm::vec3& size, const glm::quat& orientation, + const uint64_t& created, const ProceduralProgramKey key) { + withLock([&] { + if (auto material = getProceduralMaterial()) { + material->prepare(batch, position, size, orientation, created, key); + } + }); +} + +void ReferenceMaterial::initializeProcedural() { + withLock([&] { + if (auto material = getProceduralMaterial()) { + material->initializeProcedural(); + } + }); +} + +void ReferenceMaterial::setMaterialForUUIDOperator(std::function materialForUUIDOperator) { + _unboundMaterialForUUIDOperator = materialForUUIDOperator; +} + +graphics::MaterialPointer ReferenceMaterial::getMaterial() const { + if (_materialForUUIDOperator) { + auto material = _materialForUUIDOperator(); + return material; + } + return nullptr; +} + +std::shared_ptr ReferenceMaterial::getNetworkMaterial() const { + if (_materialForUUIDOperator) { + std::shared_ptr result = nullptr; + if (auto material = _materialForUUIDOperator()) { + return std::static_pointer_cast(material); + } + } + return nullptr; +} + +graphics::ProceduralMaterialPointer ReferenceMaterial::getProceduralMaterial() const { + if (_materialForUUIDOperator) { + auto material = _materialForUUIDOperator(); + if (material && material->isProcedural()) { + return std::static_pointer_cast(material); + } + } + return nullptr; +} + +template +inline T ReferenceMaterial::resultWithLock(F&& f) const { + if (_locked) { + return T(); + } else { + _locked = true; + T result = f(); + _locked = false; + return result; + } +} + +template +inline void ReferenceMaterial::withLock(F&& f) const { + if (!_locked) { + _locked = true; + f(); + _locked = false; + } +} diff --git a/libraries/procedural/src/procedural/ReferenceMaterial.h b/libraries/procedural/src/procedural/ReferenceMaterial.h new file mode 100644 index 0000000000..ac778f94b1 --- /dev/null +++ b/libraries/procedural/src/procedural/ReferenceMaterial.h @@ -0,0 +1,74 @@ +// +// Created by HifiExperiments on 3/14/2021 +// Copyright 2021 Vircadia contributors. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#pragma once + +#include "Procedural.h" + +class ReferenceMaterial : public graphics::ProceduralMaterial { +public: + using Parent = graphics::ProceduralMaterial; + + ReferenceMaterial() {} + ReferenceMaterial(QUuid uuid); + + // Material + graphics::MaterialKey getKey() const override; + glm::vec3 getEmissive(bool SRGB = true) const override; + float getOpacity() const override; + graphics::MaterialKey::OpacityMapMode getOpacityMapMode() const override; + float getOpacityCutoff() const override; + graphics::MaterialKey::CullFaceMode getCullFaceMode() const override; + bool isUnlit() const override; + glm::vec3 getAlbedo(bool SRGB = true) const override; + float getMetallic() const override; + float getRoughness() const override; + float getScattering() const override; + bool resetOpacityMap() const override; + graphics::Material::TextureMaps getTextureMaps() const override; + glm::vec2 getLightmapParams() const override; + bool getDefaultFallthrough() const override; + + // NetworkMaterial + bool isMissingTexture() override; + bool checkResetOpacityMap() override; + + // ProceduralMaterial + bool isProcedural() const override; + bool isEnabled() const override; + bool isReady() const override; + QString getProceduralString() const override; + + glm::vec4 getColor(const glm::vec4& color) const override; + bool isFading() const override; + uint64_t getFadeStartTime() const override; + bool hasVertexShader() const override; + void prepare(gpu::Batch& batch, const glm::vec3& position, const glm::vec3& size, const glm::quat& orientation, + const uint64_t& created, const ProceduralProgramKey key = ProceduralProgramKey()) override; + void initializeProcedural() override; + + bool isReference() const override { return true; } + std::function getReferenceOperator() const { return _materialForUUIDOperator; } + + static void setMaterialForUUIDOperator(std::function materialForUUIDOperator); + +private: + static std::function _unboundMaterialForUUIDOperator; + std::function _materialForUUIDOperator; + mutable bool _locked { false }; + + graphics::MaterialPointer getMaterial() const; + std::shared_ptr getNetworkMaterial() const; + graphics::ProceduralMaterialPointer getProceduralMaterial() const; + + template + T resultWithLock(F&& f) const; + + template + void withLock(F&& f) const; +}; diff --git a/libraries/render-utils/src/RenderPipelines.cpp b/libraries/render-utils/src/RenderPipelines.cpp index fe42cc1d0e..ed9fb326c4 100644 --- a/libraries/render-utils/src/RenderPipelines.cpp +++ b/libraries/render-utils/src/RenderPipelines.cpp @@ -19,6 +19,7 @@ #include #include #include +#include #include "render-utils/ShaderConstants.h" #include "StencilMaskPass.h" @@ -378,6 +379,7 @@ void RenderPipelines::updateMultiMaterial(graphics::MultiMaterial& multiMaterial auto& drawMaterialTextures = multiMaterial.getTextureTable(); multiMaterial.setTexturesLoading(false); + multiMaterial.resetReferenceTexturesAndMaterials(); // The total list of things we need to look for static std::set allFlags; @@ -408,9 +410,13 @@ void RenderPipelines::updateMultiMaterial(graphics::MultiMaterial& multiMaterial } materials.pop(); + if (material->isReference()) { + multiMaterial.addReferenceMaterial(std::static_pointer_cast(material)->getReferenceOperator()); + } + bool defaultFallthrough = material->getDefaultFallthrough(); - const auto& materialKey = material->getKey(); - const auto& textureMaps = material->getTextureMaps(); + const auto materialKey = material->getKey(); + const auto textureMaps = material->getTextureMaps(); auto it = flagsToCheck.begin(); while (it != flagsToCheck.end()) { @@ -482,6 +488,9 @@ void RenderPipelines::updateMultiMaterial(graphics::MultiMaterial& multiMaterial if (itr->second->isDefined()) { material->resetOpacityMap(); drawMaterialTextures->setTexture(gr::Texture::MaterialAlbedo, itr->second->getTextureView()); + if (itr->second->getTextureView().isReference()) { + multiMaterial.addReferenceTexture(itr->second->getTextureView().getTextureOperator()); + } wasSet = true; } else { multiMaterial.setTexturesLoading(true); @@ -501,6 +510,9 @@ void RenderPipelines::updateMultiMaterial(graphics::MultiMaterial& multiMaterial if (itr != textureMaps.end()) { if (itr->second->isDefined()) { drawMaterialTextures->setTexture(gr::Texture::MaterialMetallic, itr->second->getTextureView()); + if (itr->second->getTextureView().isReference()) { + multiMaterial.addReferenceTexture(itr->second->getTextureView().getTextureOperator()); + } wasSet = true; } else { multiMaterial.setTexturesLoading(true); @@ -518,6 +530,9 @@ void RenderPipelines::updateMultiMaterial(graphics::MultiMaterial& multiMaterial if (itr != textureMaps.end()) { if (itr->second->isDefined()) { drawMaterialTextures->setTexture(gr::Texture::MaterialRoughness, itr->second->getTextureView()); + if (itr->second->getTextureView().isReference()) { + multiMaterial.addReferenceTexture(itr->second->getTextureView().getTextureOperator()); + } wasSet = true; } else { multiMaterial.setTexturesLoading(true); @@ -535,6 +550,9 @@ void RenderPipelines::updateMultiMaterial(graphics::MultiMaterial& multiMaterial if (itr != textureMaps.end()) { if (itr->second->isDefined()) { drawMaterialTextures->setTexture(gr::Texture::MaterialNormal, itr->second->getTextureView()); + if (itr->second->getTextureView().isReference()) { + multiMaterial.addReferenceTexture(itr->second->getTextureView().getTextureOperator()); + } wasSet = true; } else { multiMaterial.setTexturesLoading(true); @@ -552,6 +570,9 @@ void RenderPipelines::updateMultiMaterial(graphics::MultiMaterial& multiMaterial if (itr != textureMaps.end()) { if (itr->second->isDefined()) { drawMaterialTextures->setTexture(gr::Texture::MaterialOcclusion, itr->second->getTextureView()); + if (itr->second->getTextureView().isReference()) { + multiMaterial.addReferenceTexture(itr->second->getTextureView().getTextureOperator()); + } wasSet = true; } else { multiMaterial.setTexturesLoading(true); @@ -569,6 +590,9 @@ void RenderPipelines::updateMultiMaterial(graphics::MultiMaterial& multiMaterial if (itr != textureMaps.end()) { if (itr->second->isDefined()) { drawMaterialTextures->setTexture(gr::Texture::MaterialScattering, itr->second->getTextureView()); + if (itr->second->getTextureView().isReference()) { + multiMaterial.addReferenceTexture(itr->second->getTextureView().getTextureOperator()); + } wasSet = true; } else { multiMaterial.setTexturesLoading(true); @@ -587,6 +611,9 @@ void RenderPipelines::updateMultiMaterial(graphics::MultiMaterial& multiMaterial if (itr != textureMaps.end()) { if (itr->second->isDefined()) { drawMaterialTextures->setTexture(gr::Texture::MaterialEmissiveLightmap, itr->second->getTextureView()); + if (itr->second->getTextureView().isReference()) { + multiMaterial.addReferenceTexture(itr->second->getTextureView().getTextureOperator()); + } wasSet = true; } else { multiMaterial.setTexturesLoading(true); @@ -607,6 +634,9 @@ void RenderPipelines::updateMultiMaterial(graphics::MultiMaterial& multiMaterial if (itr != textureMaps.end()) { if (itr->second->isDefined()) { drawMaterialTextures->setTexture(gr::Texture::MaterialEmissiveLightmap, itr->second->getTextureView()); + if (itr->second->getTextureView().isReference()) { + multiMaterial.addReferenceTexture(itr->second->getTextureView().getTextureOperator()); + } wasSet = true; } else { multiMaterial.setTexturesLoading(true); diff --git a/libraries/script-engine/src/AbstractScriptingServicesInterface.h b/libraries/script-engine/src/AbstractScriptingServicesInterface.h index ac26b166b6..c3acac7c76 100644 --- a/libraries/script-engine/src/AbstractScriptingServicesInterface.h +++ b/libraries/script-engine/src/AbstractScriptingServicesInterface.h @@ -9,6 +9,9 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +/// @addtogroup ScriptEngine +/// @{ + #ifndef hifi_AbstractScriptingServicesInterface_h #define hifi_AbstractScriptingServicesInterface_h @@ -23,3 +26,5 @@ public: #endif // hifi_AbstractScriptingServicesInterface_h + +/// @} diff --git a/libraries/script-engine/src/ArrayBufferClass.h b/libraries/script-engine/src/ArrayBufferClass.h index 295b9c3fa4..6438272f5b 100644 --- a/libraries/script-engine/src/ArrayBufferClass.h +++ b/libraries/script-engine/src/ArrayBufferClass.h @@ -9,6 +9,9 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +/// @addtogroup ScriptEngine +/// @{ + #ifndef hifi_ArrayBufferClass_h #define hifi_ArrayBufferClass_h @@ -23,6 +26,7 @@ class ScriptEngine; +/// Implements the ArrayBuffer scripting class class ArrayBufferClass : public QObject, public QScriptClass { Q_OBJECT public: @@ -58,3 +62,5 @@ private: }; #endif // hifi_ArrayBufferClass_h + +/// @} diff --git a/libraries/script-engine/src/ArrayBufferPrototype.h b/libraries/script-engine/src/ArrayBufferPrototype.h index f9dd667dc4..324f317660 100644 --- a/libraries/script-engine/src/ArrayBufferPrototype.h +++ b/libraries/script-engine/src/ArrayBufferPrototype.h @@ -9,12 +9,16 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +/// @addtogroup ScriptEngine +/// @{ + #ifndef hifi_ArrayBufferPrototype_h #define hifi_ArrayBufferPrototype_h #include #include +/// The javascript functions associated with an ArrayBuffer instance prototype class ArrayBufferPrototype : public QObject, public QScriptable { Q_OBJECT public: @@ -30,4 +34,6 @@ private: QByteArray* thisArrayBuffer() const; }; -#endif // hifi_ArrayBufferPrototype_h \ No newline at end of file +#endif // hifi_ArrayBufferPrototype_h + +/// @} diff --git a/libraries/script-engine/src/ArrayBufferViewClass.h b/libraries/script-engine/src/ArrayBufferViewClass.h index 67af4a3fc3..173f607334 100644 --- a/libraries/script-engine/src/ArrayBufferViewClass.h +++ b/libraries/script-engine/src/ArrayBufferViewClass.h @@ -9,6 +9,9 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +/// @addtogroup ScriptEngine +/// @{ + #ifndef hifi_ArrayBufferViewClass_h #define hifi_ArrayBufferViewClass_h @@ -26,6 +29,7 @@ static const QString BUFFER_PROPERTY_NAME = "buffer"; static const QString BYTE_OFFSET_PROPERTY_NAME = "byteOffset"; static const QString BYTE_LENGTH_PROPERTY_NAME = "byteLength"; +/// The base class containing common code for ArrayBuffer views class ArrayBufferViewClass : public QObject, public QScriptClass { Q_OBJECT public: @@ -50,3 +54,5 @@ protected: }; #endif // hifi_ArrayBufferViewClass_h + +/// @} diff --git a/libraries/script-engine/src/AssetScriptingInterface.h b/libraries/script-engine/src/AssetScriptingInterface.h index 5ec53e913e..b9fcb3c1c7 100644 --- a/libraries/script-engine/src/AssetScriptingInterface.h +++ b/libraries/script-engine/src/AssetScriptingInterface.h @@ -9,6 +9,9 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +/// @addtogroup ScriptEngine +/// @{ + #pragma once #ifndef hifi_AssetScriptingInterface_h @@ -41,6 +44,7 @@ * @hifi-server-entity * @hifi-assignment-client */ +/// Provides the Assets scripting API class AssetScriptingInterface : public BaseAssetScriptingInterface, QScriptable { Q_OBJECT public: @@ -544,3 +548,5 @@ protected: }; #endif // hifi_AssetScriptingInterface_h + +/// @} diff --git a/libraries/script-engine/src/AudioScriptingInterface.h b/libraries/script-engine/src/AudioScriptingInterface.h index 1a8f752861..6bfb7352ee 100644 --- a/libraries/script-engine/src/AudioScriptingInterface.h +++ b/libraries/script-engine/src/AudioScriptingInterface.h @@ -9,6 +9,9 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +/// @addtogroup ScriptEngine +/// @{ + #ifndef hifi_AudioScriptingInterface_h #define hifi_AudioScriptingInterface_h @@ -19,6 +22,7 @@ class ScriptAudioInjector; +/// Provides the Audio scripting API class AudioScriptingInterface : public QObject, public Dependency { Q_OBJECT SINGLETON_DEPENDENCY @@ -290,3 +294,5 @@ private: void registerAudioMetaTypes(QScriptEngine* engine); #endif // hifi_AudioScriptingInterface_h + +/// @} diff --git a/libraries/script-engine/src/BatchLoader.h b/libraries/script-engine/src/BatchLoader.h index 3affacc07d..89a388c6e1 100644 --- a/libraries/script-engine/src/BatchLoader.h +++ b/libraries/script-engine/src/BatchLoader.h @@ -9,6 +9,9 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +/// @addtogroup ScriptEngine +/// @{ + #ifndef hifi_BatchLoader_h #define hifi_BatchLoader_h @@ -23,6 +26,7 @@ #include +// Proxy object internal to BatchLoader to ensure threadsafety during loading actions class ScriptCacheSignalProxy : public QObject { Q_OBJECT public: @@ -32,6 +36,7 @@ signals: void contentAvailable(const QString& url, const QString& contents, bool isURL, bool success, const QString& status); }; +/// Load one or more files for use by the scripting engine class BatchLoader : public QObject { Q_OBJECT public: @@ -54,3 +59,5 @@ private: }; #endif // hifi_BatchLoader_h + +/// @} diff --git a/libraries/script-engine/src/ConsoleScriptingInterface.h b/libraries/script-engine/src/ConsoleScriptingInterface.h index 1e56526cd1..591d44b22d 100644 --- a/libraries/script-engine/src/ConsoleScriptingInterface.h +++ b/libraries/script-engine/src/ConsoleScriptingInterface.h @@ -15,6 +15,9 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +/// @addtogroup ScriptEngine +/// @{ + #pragma once #ifndef hifi_ConsoleScriptingInterface_h #define hifi_ConsoleScriptingInterface_h @@ -37,7 +40,7 @@ * @hifi-server-entity * @hifi-assignment-client */ -// Scriptable interface of "console" object. Used exclusively in the JavaScript API +/// Provides the console scripting API class ConsoleScriptingInterface : public QObject, protected QScriptable { Q_OBJECT public: @@ -220,3 +223,5 @@ private: }; #endif // hifi_ConsoleScriptingInterface_h + +/// @} diff --git a/libraries/script-engine/src/DataViewClass.h b/libraries/script-engine/src/DataViewClass.h index 72c920a727..179aad87d1 100644 --- a/libraries/script-engine/src/DataViewClass.h +++ b/libraries/script-engine/src/DataViewClass.h @@ -9,11 +9,15 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +/// @addtogroup ScriptEngine +/// @{ + #ifndef hifi_DataViewClass_h #define hifi_DataViewClass_h #include "ArrayBufferViewClass.h" +/// Implements the DataView scripting class class DataViewClass : public ArrayBufferViewClass { Q_OBJECT public: @@ -34,3 +38,5 @@ private: #endif // hifi_DataViewClass_h + +/// @} diff --git a/libraries/script-engine/src/DataViewPrototype.h b/libraries/script-engine/src/DataViewPrototype.h index da0261dad4..b4d9462e8f 100644 --- a/libraries/script-engine/src/DataViewPrototype.h +++ b/libraries/script-engine/src/DataViewPrototype.h @@ -9,12 +9,16 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +/// @addtogroup ScriptEngine +/// @{ + #ifndef hifi_DataViewPrototype_h #define hifi_DataViewPrototype_h #include #include +/// The javascript functions associated with a DataView instance prototype class DataViewPrototype : public QObject, public QScriptable { Q_OBJECT public: @@ -65,4 +69,6 @@ private: bool realOffset(qint32& offset, size_t size) const; }; -#endif // hifi_DataViewPrototype_h \ No newline at end of file +#endif // hifi_DataViewPrototype_h + +/// @} diff --git a/libraries/script-engine/src/EventTypes.h b/libraries/script-engine/src/EventTypes.h index 906006e4f4..052d736d48 100644 --- a/libraries/script-engine/src/EventTypes.h +++ b/libraries/script-engine/src/EventTypes.h @@ -9,6 +9,9 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +/// @addtogroup ScriptEngine +/// @{ + #ifndef hifi_EventTypes_h #define hifi_EventTypes_h @@ -17,3 +20,5 @@ void registerEventTypes(QScriptEngine* engine); #endif // hifi_EventTypes_h + +/// @} diff --git a/libraries/script-engine/src/FileScriptingInterface.h b/libraries/script-engine/src/FileScriptingInterface.h index 4bc73346ac..2afa995214 100644 --- a/libraries/script-engine/src/FileScriptingInterface.h +++ b/libraries/script-engine/src/FileScriptingInterface.h @@ -9,6 +9,9 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +/// @addtogroup ScriptEngine +/// @{ + #ifndef hifi_FileScriptingInterface_h #define hifi_FileScriptingInterface_h @@ -27,7 +30,7 @@ * @hifi-server-entity * @hifi-assignment-client */ - +/// Provides the File scripting API class FileScriptingInterface : public QObject { Q_OBJECT @@ -113,4 +116,6 @@ private: }; -#endif // hifi_FileScriptingInterface_h \ No newline at end of file +#endif // hifi_FileScriptingInterface_h + +/// @} diff --git a/libraries/script-engine/src/KeyEvent.h b/libraries/script-engine/src/KeyEvent.h index 350b733eaf..10c5fde404 100644 --- a/libraries/script-engine/src/KeyEvent.h +++ b/libraries/script-engine/src/KeyEvent.h @@ -9,12 +9,16 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +/// @addtogroup ScriptEngine +/// @{ + #ifndef hifi_KeyEvent_h #define hifi_KeyEvent_h #include #include +/// Represents a keyboard event to the scripting engine. Exposed as KeyEvent class KeyEvent { public: KeyEvent(); @@ -38,4 +42,6 @@ public: Q_DECLARE_METATYPE(KeyEvent) -#endif // hifi_KeyEvent_h \ No newline at end of file +#endif // hifi_KeyEvent_h + +/// @} diff --git a/libraries/script-engine/src/MIDIEvent.h b/libraries/script-engine/src/MIDIEvent.h index 6bf4a4b72b..fd8f83d9cb 100644 --- a/libraries/script-engine/src/MIDIEvent.h +++ b/libraries/script-engine/src/MIDIEvent.h @@ -9,11 +9,15 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include +/// @addtogroup ScriptEngine +/// @{ #ifndef hifi_MIDIEvent_h #define hifi_MIDIEvent_h +#include + +/// Represents a MIDI protocol event to the scripting engine. class MIDIEvent { public: double deltaTime; @@ -29,4 +33,6 @@ void registerMIDIMetaTypes(QScriptEngine* engine); QScriptValue midiEventToScriptValue(QScriptEngine* engine, const MIDIEvent& event); void midiEventFromScriptValue(const QScriptValue &object, MIDIEvent& event); -#endif // hifi_MIDIEvent_h \ No newline at end of file +#endif // hifi_MIDIEvent_h + +/// @} diff --git a/libraries/script-engine/src/Mat4.h b/libraries/script-engine/src/Mat4.h index 93f83c427e..204e87c57d 100644 --- a/libraries/script-engine/src/Mat4.h +++ b/libraries/script-engine/src/Mat4.h @@ -11,6 +11,9 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +/// @addtogroup ScriptEngine +/// @{ + #ifndef hifi_Mat4_h #define hifi_Mat4_h @@ -35,8 +38,7 @@ * @hifi-server-entity * @hifi-assignment-client */ - -/// Scriptable Mat4 object. Used exclusively in the JavaScript API +/// Provides the Mat4 scripting interface class Mat4 : public QObject, protected QScriptable { Q_OBJECT @@ -321,3 +323,5 @@ public slots: }; #endif // hifi_Mat4_h + +/// @} diff --git a/libraries/script-engine/src/MenuItemProperties.h b/libraries/script-engine/src/MenuItemProperties.h index 9de4337838..30b78cd55b 100644 --- a/libraries/script-engine/src/MenuItemProperties.h +++ b/libraries/script-engine/src/MenuItemProperties.h @@ -9,6 +9,9 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +/// @addtogroup ScriptEngine +/// @{ + #ifndef hifi_MenuItemProperties_h #define hifi_MenuItemProperties_h @@ -17,6 +20,7 @@ #include "KeyEvent.h" +/// Represents a menu item a script may declare and bind events to. Exposed as MenuItemProperties class MenuItemProperties { public: MenuItemProperties() {} @@ -56,3 +60,5 @@ void registerMenuItemProperties(QScriptEngine* engine); #endif // hifi_MenuItemProperties_h + +/// @} diff --git a/libraries/script-engine/src/ModelScriptingInterface.h b/libraries/script-engine/src/ModelScriptingInterface.h index f936ca900c..5bd8d08944 100644 --- a/libraries/script-engine/src/ModelScriptingInterface.h +++ b/libraries/script-engine/src/ModelScriptingInterface.h @@ -9,6 +9,9 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +/// @addtogroup ScriptEngine +/// @{ + #ifndef hifi_ModelScriptingInterface_h #define hifi_ModelScriptingInterface_h @@ -32,6 +35,7 @@ class QScriptEngine; * * @deprecated This API is deprecated. Use the {@link Graphics} API instead. */ +/// Provides the Model scripting interface class ModelScriptingInterface : public QObject { Q_OBJECT @@ -97,3 +101,5 @@ private: }; #endif // hifi_ModelScriptingInterface_h + +/// @} diff --git a/libraries/script-engine/src/MouseEvent.h b/libraries/script-engine/src/MouseEvent.h index d9b00a8e01..7c668a6901 100644 --- a/libraries/script-engine/src/MouseEvent.h +++ b/libraries/script-engine/src/MouseEvent.h @@ -9,6 +9,9 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +/// @addtogroup ScriptEngine +/// @{ + #ifndef hifi_MouseEvent_h #define hifi_MouseEvent_h @@ -17,6 +20,7 @@ class QScriptEngine; +/// Represents a mouse event to the scripting engine. Exposed as MouseEvent class MouseEvent { public: MouseEvent(); @@ -42,3 +46,5 @@ public: Q_DECLARE_METATYPE(MouseEvent) #endif // hifi_MouseEvent_h + +/// @} diff --git a/libraries/script-engine/src/Quat.h b/libraries/script-engine/src/Quat.h index d603e5a800..cdda723ee0 100644 --- a/libraries/script-engine/src/Quat.h +++ b/libraries/script-engine/src/Quat.h @@ -11,6 +11,9 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +/// @addtogroup ScriptEngine +/// @{ + #ifndef hifi_Quat_h #define hifi_Quat_h @@ -51,8 +54,7 @@ * print(JSON.stringify(Quat.IDENTITY)); // { x: 0, y: 0, z: 0, w: 1 } * print(JSON.stringify(Quat.safeEulerAngles(Quat.IDENTITY))); // { x: 0, y: 0, z: 0 } */ - -/// Scriptable interface a Quaternion helper class object. Used exclusively in the JavaScript API +/// Provides the Quat scripting interface class Quat : public QObject, protected QScriptable { Q_OBJECT Q_PROPERTY(glm::quat IDENTITY READ IDENTITY CONSTANT) @@ -470,3 +472,5 @@ private: }; #endif // hifi_Quat_h + +/// @} diff --git a/libraries/script-engine/src/RecordingScriptingInterface.h b/libraries/script-engine/src/RecordingScriptingInterface.h index b9a7d1db83..bc88566b9a 100644 --- a/libraries/script-engine/src/RecordingScriptingInterface.h +++ b/libraries/script-engine/src/RecordingScriptingInterface.h @@ -6,6 +6,9 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +/// @addtogroup ScriptEngine +/// @{ + #ifndef hifi_RecordingScriptingInterface_h #define hifi_RecordingScriptingInterface_h @@ -34,6 +37,7 @@ class QScriptValue; * @hifi-avatar * @hifi-assignment-client */ +/// Provides the Recording scripting interface class RecordingScriptingInterface : public QObject, public Dependency { Q_OBJECT @@ -369,3 +373,5 @@ private: }; #endif // hifi_RecordingScriptingInterface_h + +/// @} diff --git a/libraries/script-engine/src/SceneScriptingInterface.h b/libraries/script-engine/src/SceneScriptingInterface.h index 817a89753b..6c65ed5244 100644 --- a/libraries/script-engine/src/SceneScriptingInterface.h +++ b/libraries/script-engine/src/SceneScriptingInterface.h @@ -9,6 +9,9 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +/// @addtogroup ScriptEngine +/// @{ + #ifndef hifi_SceneScriptingInterface_h #define hifi_SceneScriptingInterface_h @@ -28,6 +31,7 @@ * @property {boolean} shouldRenderEntities - true if entities (domain, avatar, and local) are rendered, * false if they aren't. */ +/// Provides the Scene scripting interface class SceneScriptingInterface : public QObject, public Dependency { Q_OBJECT SINGLETON_DEPENDENCY @@ -69,3 +73,5 @@ protected: }; #endif // hifi_SceneScriptingInterface_h + +/// @} diff --git a/libraries/script-engine/src/ScriptAudioInjector.h b/libraries/script-engine/src/ScriptAudioInjector.h index 8ed5956fea..8818ffab43 100644 --- a/libraries/script-engine/src/ScriptAudioInjector.h +++ b/libraries/script-engine/src/ScriptAudioInjector.h @@ -9,6 +9,9 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +/// @addtogroup ScriptEngine +/// @{ + #ifndef hifi_ScriptAudioInjector_h #define hifi_ScriptAudioInjector_h @@ -35,6 +38,7 @@ * Read-only. * @property {AudioInjector.AudioInjectorOptions} options - Configures how the injector plays the audio. */ +/// Provides the AudioInjector scripting interface class ScriptAudioInjector : public QObject { Q_OBJECT @@ -148,3 +152,5 @@ QScriptValue injectorToScriptValue(QScriptEngine* engine, ScriptAudioInjector* c void injectorFromScriptValue(const QScriptValue& object, ScriptAudioInjector*& out); #endif // hifi_ScriptAudioInjector_h + +/// @} diff --git a/libraries/script-engine/src/ScriptCache.h b/libraries/script-engine/src/ScriptCache.h index 4ab4458ee9..03d815e4ad 100644 --- a/libraries/script-engine/src/ScriptCache.h +++ b/libraries/script-engine/src/ScriptCache.h @@ -9,6 +9,9 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +/// @addtogroup ScriptEngine +/// @{ + #ifndef hifi_ScriptCache_h #define hifi_ScriptCache_h @@ -32,7 +35,7 @@ public: int maxRetries { MAX_RETRIES }; }; -/// Interface for loading scripts +/// Dependency for for loading and caching scripts class ScriptCache : public QObject, public Dependency { Q_OBJECT SINGLETON_DEPENDENCY @@ -65,3 +68,5 @@ private: }; #endif // hifi_ScriptCache_h + +/// @} diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index 417e6d94e5..6627f75ae6 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -2405,7 +2405,7 @@ void ScriptEngine::entityScriptContentAvailable(const EntityItemID& entityID, co QString currentDomain = DependencyManager::get()->getDomainURL().host(); QString domainSafeIP = nodeList->getDomainHandler().getHostname(); - QString domainSafeURL = URL_SCHEME_HIFI + "://" + currentDomain; + QString domainSafeURL = URL_SCHEME_VIRCADIA + "://" + currentDomain; for (const auto& str : safeURLPrefixes) { if (domainSafeURL.startsWith(str) || domainSafeIP.startsWith(str)) { qCDebug(scriptengine) << whitelistPrefix << "Whitelist Bypassed, entire domain is whitelisted. Current Domain Host: " diff --git a/libraries/script-engine/src/ScriptEngine.h b/libraries/script-engine/src/ScriptEngine.h index 0855b0bd73..a6f7341f77 100644 --- a/libraries/script-engine/src/ScriptEngine.h +++ b/libraries/script-engine/src/ScriptEngine.h @@ -10,6 +10,9 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +/// @addtogroup ScriptEngine +/// @{ + #ifndef hifi_ScriptEngine_h #define hifi_ScriptEngine_h @@ -133,6 +136,7 @@ public: * Read-only. * @property {Script.ResourceBuckets} ExternalPaths - External resource buckets. */ +/// The main class managing a scripting engine. Also provides the Script scripting interface class ScriptEngine : public BaseScriptEngine, public EntitiesScriptEngineProvider { Q_OBJECT Q_PROPERTY(QString context READ getContext) @@ -182,7 +186,7 @@ public: * Script.setInterval(function () { * print("Hello"); * }, 1000); - * + * * Script.setTimeout(function () { * Script.stop(true); * }, 5000); @@ -303,7 +307,7 @@ public: /*@jsdoc * Checks whether the script is running as an Interface or avatar script. * @function Script.isClientScript - * @returns {boolean} true if the script is running as an Interface or avatar script, false if it + * @returns {boolean} true if the script is running as an Interface or avatar script, false if it * isn't. */ Q_INVOKABLE bool isClientScript() const { return _context == CLIENT_SCRIPT; } @@ -311,7 +315,7 @@ public: /*@jsdoc * Checks whether the application was compiled as a debug build. * @function Script.isDebugMode - * @returns {boolean} true if the application was compiled as a debug build, false if it was + * @returns {boolean} true if the application was compiled as a debug build, false if it was * compiled as a release build. */ Q_INVOKABLE bool isDebugMode() const; @@ -333,7 +337,7 @@ public: /*@jsdoc * Checks whether the script is running as an assignment client script. * @function Script.isAgentScript - * @returns {boolean} true if the script is running as an assignment client script, false if it + * @returns {boolean} true if the script is running as an assignment client script, false if it * isn't. */ Q_INVOKABLE bool isAgentScript() const { return _context == AGENT_SCRIPT; } @@ -347,7 +351,7 @@ public: * @function Script.addEventHandler * @param {Uuid} entityID - The ID of the entity. * @param {Script.EntityEvent} eventName - The name of the event. - * @param {Script~entityEventCallback|Script~pointerEventCallback|Script~collisionEventCallback} handler - The function to + * @param {Script~entityEventCallback|Script~pointerEventCallback|Script~collisionEventCallback} handler - The function to * call when the event occurs on the entity. It can be either the name of a function or an in-line definition. * @example
* var entityID = Entities.addEntity({ @@ -356,11 +360,11 @@ public: * dimensions: { x: 0.5, y: 0.5, z: 0.5 }, * lifetime: 300 // Delete after 5 minutes. * }); - * + * * function reportMousePress(entityID, event) { * print("Mouse pressed on entity: " + JSON.stringify(event)); * } - * + * * Script.addEventHandler(entityID, "mousePressOnEntity", reportMousePress); */ Q_INVOKABLE void addEventHandler(const EntityItemID& entityID, const QString& eventName, QScriptValue handler); @@ -376,7 +380,7 @@ public: Q_INVOKABLE void removeEventHandler(const EntityItemID& entityID, const QString& eventName, QScriptValue handler); /*@jsdoc - * Starts running another script in Interface, if it isn't already running. The script is not automatically loaded next + * Starts running another script in Interface, if it isn't already running. The script is not automatically loaded next * time Interface starts. *

Supported Script Types: Interface Scripts • Avatar Scripts

*

See also, {@link ScriptDiscoveryService.loadScript}.

@@ -398,13 +402,13 @@ public: Q_INVOKABLE void load(const QString& loadfile); /*@jsdoc - * Includes JavaScript from other files in the current script. If a callback is specified, the files are loaded and - * included asynchronously, otherwise they are included synchronously (i.e., script execution blocks while the files are + * Includes JavaScript from other files in the current script. If a callback is specified, the files are loaded and + * included asynchronously, otherwise they are included synchronously (i.e., script execution blocks while the files are * included). * @function Script.include * @variation 0 * @param {string[]} filenames - The URLs of the scripts to include. Each can be relative to the current script. - * @param {function} [callback=null] - The function to call back when the scripts have been included. It can be either the + * @param {function} [callback=null] - The function to call back when the scripts have been included. It can be either the * name of a function or an in-line definition. */ Q_INVOKABLE void include(const QStringList& includeFiles, QScriptValue callback = QScriptValue()); @@ -414,7 +418,7 @@ public: * asynchronously, otherwise it is included synchronously (i.e., script execution blocks while the file is included). * @function Script.include * @param {string} filename - The URL of the script to include. It can be relative to the current script. - * @param {function} [callback=null] - The function to call back when the script has been included. It can be either the + * @param {function} [callback=null] - The function to call back when the script has been included. It can be either the * name of a function or an in-line definition. * @example * // First file: scriptA.js @@ -438,12 +442,12 @@ public: // MODULE related methods /*@jsdoc - * Provides access to methods or objects provided in an external JavaScript or JSON file. - * See {@link https://docs.vircadia.dev/script/js-tips.html} for further details. + * Provides access to methods or objects provided in an external JavaScript or JSON file. + * See {@link https://docs.vircadia.com/script/js-tips.html} for further details. * @function Script.require - * @param {string} module - The module to use. May be a JavaScript file, a JSON file, or the name of a system module such + * @param {string} module - The module to use. May be a JavaScript file, a JSON file, or the name of a system module such * as "appUi" (i.e., the "appUi.js" system module JavaScript file). - * @returns {object|array} The value assigned to module.exports in the JavaScript file, or the value defined + * @returns {object|array} The value assigned to module.exports in the JavaScript file, or the value defined * in the JSON file. */ Q_INVOKABLE QScriptValue require(const QString& moduleId); @@ -550,7 +554,7 @@ public: Q_INVOKABLE QUrl resourcesPath() const; /*@jsdoc - * Starts timing a section of code in order to send usage data about it to Vircadia. Shouldn't be used outside of the + * Starts timing a section of code in order to send usage data about it to Vircadia. Shouldn't be used outside of the * standard scripts. * @function Script.beginProfileRange * @param {string} label - A name that identifies the section of code. @@ -558,7 +562,7 @@ public: Q_INVOKABLE void beginProfileRange(const QString& label) const; /*@jsdoc - * Finishes timing a section of code in order to send usage data about it to Vircadia. Shouldn't be used outside of + * Finishes timing a section of code in order to send usage data about it to Vircadia. Shouldn't be used outside of * the standard scripts. * @function Script.endProfileRange * @param {string} label - A name that identifies the section of code. @@ -640,7 +644,7 @@ public: Q_INVOKABLE void callEntityScriptMethod(const EntityItemID& entityID, const QString& methodName, const EntityItemID& otherID, const Collision& collision); /*@jsdoc - * Manually runs the JavaScript garbage collector which reclaims memory by disposing of objects that are no longer + * Manually runs the JavaScript garbage collector which reclaims memory by disposing of objects that are no longer * reachable. * @function Script.requestGarbageCollection */ @@ -695,9 +699,9 @@ public: * but this method will return the asset's current URL.) * @function Script.getExternalPath * @param {Script.ResourceBucket} bucket - The external resource bucket that the asset is in. - * @param {string} path - The path within the external resource bucket where the asset is located. + * @param {string} path - The path within the external resource bucket where the asset is located. *

Normally, this should start with a path or filename to be appended to the bucket URL. - * Alternatively, it can be a relative path starting with ./ or ../, to navigate within the + * Alternatively, it can be a relative path starting with ./ or ../, to navigate within the * resource bucket's URL.

* @Returns {string} The URL of an external asset. * @example @@ -793,8 +797,8 @@ signals: void cleanupMenuItem(const QString& menuItemString); /*@jsdoc - * Triggered when the script prints a message to the program log via {@link print}, {@link Script.print}, - * {@link console.log}, {@link console.debug}, {@link console.group}, {@link console.groupEnd}, {@link console.time}, or + * Triggered when the script prints a message to the program log via {@link print}, {@link Script.print}, + * {@link console.log}, {@link console.debug}, {@link console.group}, {@link console.groupEnd}, {@link console.time}, or * {@link console.timeEnd}. * @function Script.printedMessage * @param {string} message - The message. @@ -804,7 +808,7 @@ signals: void printedMessage(const QString& message, const QString& scriptName); /*@jsdoc - * Triggered when the script generates an error, {@link console.error} or {@link console.exception} is called, or + * Triggered when the script generates an error, {@link console.error} or {@link console.exception} is called, or * {@link console.assert} is called and fails. * @function Script.errorMessage * @param {string} message - The error message. @@ -1012,3 +1016,5 @@ ScriptEnginePointer scriptEngineFactory(ScriptEngine::Context context, const QString& fileNameString); #endif // hifi_ScriptEngine_h + +/// @} diff --git a/libraries/script-engine/src/ScriptEngineLogging.h b/libraries/script-engine/src/ScriptEngineLogging.h index 3096dd4927..07e7c507d6 100644 --- a/libraries/script-engine/src/ScriptEngineLogging.h +++ b/libraries/script-engine/src/ScriptEngineLogging.h @@ -9,6 +9,9 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +/// @addtogroup ScriptEngine +/// @{ + #ifndef hifi_ScriptEngineLogging_h #define hifi_ScriptEngineLogging_h @@ -20,3 +23,4 @@ Q_DECLARE_LOGGING_CATEGORY(scriptengine_script) #endif // hifi_ScriptEngineLogging_h +/// @} diff --git a/libraries/script-engine/src/ScriptEngines.h b/libraries/script-engine/src/ScriptEngines.h index 13e0cb2e21..52c9a922af 100644 --- a/libraries/script-engine/src/ScriptEngines.h +++ b/libraries/script-engine/src/ScriptEngines.h @@ -6,6 +6,9 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +/// @addtogroup ScriptEngine +/// @{ + #ifndef hifi_ScriptEngines_h #define hifi_ScriptEngines_h @@ -49,7 +52,7 @@ class ScriptEngine; * scripts directory of the Interface installation. * Read-only. */ - +/// Provides the ScriptDiscoveryService scripting interface class ScriptEngines : public QObject, public Dependency, public ScriptInitializerMixin { Q_OBJECT @@ -362,3 +365,5 @@ QString expandScriptPath(const QString& rawPath); QUrl expandScriptUrl(const QUrl& rawScriptURL); #endif // hifi_ScriptEngine_h + +/// @} diff --git a/libraries/script-engine/src/ScriptGatekeeper.h b/libraries/script-engine/src/ScriptGatekeeper.h index 22bda8d5d5..71bce13193 100644 --- a/libraries/script-engine/src/ScriptGatekeeper.h +++ b/libraries/script-engine/src/ScriptGatekeeper.h @@ -9,11 +9,15 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +/// @addtogroup ScriptEngine +/// @{ + #ifndef vircadia_ScriptGatekeeper_h #define vircadia_ScriptGatekeeper_h #include +/// Manages script whitelisting in a domain class ScriptGatekeeper : public QObject { Q_OBJECT public: @@ -27,3 +31,5 @@ private: }; #endif // vircadia_ScriptGatekeeper_h + +/// @} diff --git a/libraries/script-engine/src/ScriptUUID.h b/libraries/script-engine/src/ScriptUUID.h index 27e5cc0c7b..24edb91184 100644 --- a/libraries/script-engine/src/ScriptUUID.h +++ b/libraries/script-engine/src/ScriptUUID.h @@ -11,6 +11,9 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +/// @addtogroup ScriptEngine +/// @{ + #ifndef hifi_ScriptUUID_h #define hifi_ScriptUUID_h @@ -32,8 +35,7 @@ * * @property {Uuid} NULL - The null UUID, "{00000000-0000-0000-0000-000000000000}". */ - -/// Scriptable interface for a UUID helper class object. Used exclusively in the JavaScript API +/// Provides the Uuid scripting interface class ScriptUUID : public QObject, protected QScriptable { Q_OBJECT Q_PROPERTY(QString NULL READ NULL_UUID CONSTANT) // String for use in scripts. @@ -127,3 +129,5 @@ private: }; #endif // hifi_ScriptUUID_h + +/// @} diff --git a/libraries/script-engine/src/ScriptsModel.h b/libraries/script-engine/src/ScriptsModel.h index 5703b30d3d..2c90a73d2d 100644 --- a/libraries/script-engine/src/ScriptsModel.h +++ b/libraries/script-engine/src/ScriptsModel.h @@ -9,6 +9,9 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +/// @addtogroup ScriptEngine +/// @{ + #ifndef hifi_ScriptsModel_h #define hifi_ScriptsModel_h @@ -119,6 +122,7 @@ public: * print("Scripts:"); * printDirectory(null, 0, ""); // null index for the root directory. */ +/// Provides script file information available from the ScriptDiscoveryService scripting interface class ScriptsModel : public QAbstractItemModel { Q_OBJECT public: @@ -191,3 +195,5 @@ private: }; #endif // hifi_ScriptsModel_h + +/// @} diff --git a/libraries/script-engine/src/ScriptsModelFilter.h b/libraries/script-engine/src/ScriptsModelFilter.h index f6c2119647..7a52be76e4 100644 --- a/libraries/script-engine/src/ScriptsModelFilter.h +++ b/libraries/script-engine/src/ScriptsModelFilter.h @@ -9,6 +9,9 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +/// @addtogroup ScriptEngine +/// @{ + #ifndef hifi_ScriptsModelFilter_h #define hifi_ScriptsModelFilter_h @@ -71,6 +74,7 @@ * print("Edit scripts:"); * printDirectory(null, 0, ""); // null index for the root directory. */ +/// Provides script file information available from the ScriptDiscoveryService scripting interface class ScriptsModelFilter : public QSortFilterProxyModel { Q_OBJECT public: @@ -81,3 +85,5 @@ protected: }; #endif // hifi_ScriptsModelFilter_h + +/// @} diff --git a/libraries/script-engine/src/SpatialEvent.h b/libraries/script-engine/src/SpatialEvent.h index e0fcc03824..1ea31f1ed3 100644 --- a/libraries/script-engine/src/SpatialEvent.h +++ b/libraries/script-engine/src/SpatialEvent.h @@ -9,6 +9,9 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +/// @addtogroup ScriptEngine +/// @{ + #ifndef hifi_SpatialEvent_h #define hifi_SpatialEvent_h @@ -17,6 +20,7 @@ #include +/// [unused] Represents a spatial event to the scripting engine class SpatialEvent { public: SpatialEvent(); @@ -33,4 +37,6 @@ public: Q_DECLARE_METATYPE(SpatialEvent) -#endif // hifi_SpatialEvent_h \ No newline at end of file +#endif // hifi_SpatialEvent_h + +/// @} diff --git a/libraries/script-engine/src/StackTestScriptingInterface.h b/libraries/script-engine/src/StackTestScriptingInterface.h index 74e3290ddb..2138f06baf 100644 --- a/libraries/script-engine/src/StackTestScriptingInterface.h +++ b/libraries/script-engine/src/StackTestScriptingInterface.h @@ -9,6 +9,9 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +/// @addtogroup ScriptEngine +/// @{ + #pragma once #ifndef hifi_StackTestScriptingInterface_h @@ -29,3 +32,5 @@ public: }; #endif // hifi_StackTestScriptingInterface_h + +/// @} diff --git a/libraries/script-engine/src/TouchEvent.h b/libraries/script-engine/src/TouchEvent.h index 62cb1b1801..d084514ff6 100644 --- a/libraries/script-engine/src/TouchEvent.h +++ b/libraries/script-engine/src/TouchEvent.h @@ -9,6 +9,9 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +/// @addtogroup ScriptEngine +/// @{ + #ifndef hifi_TouchEvent_h #define hifi_TouchEvent_h @@ -20,6 +23,7 @@ class QScriptValue; class QScriptEngine; +/// Represents a display or device event to the scripting engine. Exposed as TouchEvent class TouchEvent { public: TouchEvent(); @@ -60,3 +64,5 @@ private: Q_DECLARE_METATYPE(TouchEvent) #endif // hifi_TouchEvent_h + +/// @} diff --git a/libraries/script-engine/src/TypedArrayPrototype.h b/libraries/script-engine/src/TypedArrayPrototype.h index 86d578ace0..adcc9f3abf 100644 --- a/libraries/script-engine/src/TypedArrayPrototype.h +++ b/libraries/script-engine/src/TypedArrayPrototype.h @@ -9,11 +9,15 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +/// @addtogroup ScriptEngine +/// @{ + #ifndef hifi_TypedArrayPrototype_h #define hifi_TypedArrayPrototype_h #include "ArrayBufferViewClass.h" +/// The javascript functions associated with a TypedArray instance prototype class TypedArrayPrototype : public QObject, public QScriptable { Q_OBJECT public: @@ -30,4 +34,6 @@ private: QByteArray* thisArrayBuffer() const; }; -#endif // hifi_TypedArrayPrototype_h \ No newline at end of file +#endif // hifi_TypedArrayPrototype_h + +/// @} diff --git a/libraries/script-engine/src/TypedArrays.h b/libraries/script-engine/src/TypedArrays.h index 141e7870d9..948b9677f1 100644 --- a/libraries/script-engine/src/TypedArrays.h +++ b/libraries/script-engine/src/TypedArrays.h @@ -9,6 +9,9 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +/// @addtogroup ScriptEngine +/// @{ + #ifndef hifi_TypedArrays_h #define hifi_TypedArrays_h @@ -27,6 +30,7 @@ static const QString UINT_32_ARRAY_CLASS_NAME = "Uint32Array"; static const QString FLOAT_32_ARRAY_CLASS_NAME = "Float32Array"; static const QString FLOAT_64_ARRAY_CLASS_NAME = "Float64Array"; +/// Implements the TypedArray scripting class class TypedArray : public ArrayBufferViewClass { Q_OBJECT public: @@ -146,3 +150,5 @@ public: }; #endif // hifi_TypedArrays_h + +/// @} diff --git a/libraries/script-engine/src/UsersScriptingInterface.h b/libraries/script-engine/src/UsersScriptingInterface.h index ccf5a1d693..8bca34ad0b 100644 --- a/libraries/script-engine/src/UsersScriptingInterface.h +++ b/libraries/script-engine/src/UsersScriptingInterface.h @@ -10,6 +10,9 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +/// @addtogroup ScriptEngine +/// @{ + #pragma once #ifndef hifi_UsersScriptingInterface_h @@ -38,6 +41,7 @@ * @property {BanFlags} BAN_BY_FINGERPRINT - Ban user by fingerprint. Read-only. * @property {BanFlags} BAN_BY_IP - Ban user by IP address. Read-only. */ +/// Provides the Users scripting interface class UsersScriptingInterface : public QObject, public Dependency { Q_OBJECT SINGLETON_DEPENDENCY @@ -262,3 +266,5 @@ private: #endif // hifi_UsersScriptingInterface_h + +/// @} diff --git a/libraries/script-engine/src/Vec3.h b/libraries/script-engine/src/Vec3.h index f10b3fa9a9..3c357ae6fc 100644 --- a/libraries/script-engine/src/Vec3.h +++ b/libraries/script-engine/src/Vec3.h @@ -11,6 +11,9 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +/// @addtogroup ScriptEngine +/// @{ + #pragma once #ifndef hifi_Vec3_h #define hifi_Vec3_h @@ -71,8 +74,7 @@ * @property {Vec3} FRONT - { x: 0, y: 0, z: -1 } : Unit vector in the "front" direction. Synonym for * UNIT_NEG_Z. Read-only. */ - -/// Scriptable interface a Vec3ernion helper class object. Used exclusively in the JavaScript API +/// Provides the Vec3 scripting interface class Vec3 : public QObject, protected QScriptable { Q_OBJECT Q_PROPERTY(glm::vec3 UNIT_X READ UNIT_X CONSTANT) @@ -419,3 +421,5 @@ private: }; #endif // hifi_Vec3_h + +/// @} diff --git a/libraries/script-engine/src/WebSocketClass.cpp b/libraries/script-engine/src/WebSocketClass.cpp index f0360fc9cc..a001e2b2c2 100644 --- a/libraries/script-engine/src/WebSocketClass.cpp +++ b/libraries/script-engine/src/WebSocketClass.cpp @@ -159,7 +159,7 @@ void WebSocketClass::handleOnError(QAbstractSocket::SocketError error) { } /*@jsdoc - * Triggered when a message is received. + * Called when a message is received. * @callback WebSocket~onMessageCallback * @param {WebSocket.MessageData} message - The message received. */ diff --git a/libraries/script-engine/src/WebSocketClass.h b/libraries/script-engine/src/WebSocketClass.h index bf3d015dbc..457c955dc8 100644 --- a/libraries/script-engine/src/WebSocketClass.h +++ b/libraries/script-engine/src/WebSocketClass.h @@ -9,6 +9,9 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +/// @addtogroup ScriptEngine +/// @{ + #ifndef hifi_WebSocketClass_h #define hifi_WebSocketClass_h @@ -78,6 +81,7 @@ * webSocket.send("Test message"); * }; */ +/// Provides the WebSocket scripting interface class WebSocketClass : public QObject { Q_OBJECT Q_PROPERTY(QString binaryType READ getBinaryType WRITE setBinaryType) @@ -254,3 +258,5 @@ QScriptValue wscReadyStateToScriptValue(QScriptEngine* engine, const WebSocketCl void wscReadyStateFromScriptValue(const QScriptValue& object, WebSocketClass::ReadyState& readyState); #endif // hifi_WebSocketClass_h + +/// @} diff --git a/libraries/script-engine/src/WebSocketServerClass.h b/libraries/script-engine/src/WebSocketServerClass.h index de6042b9da..7cf03d7b41 100644 --- a/libraries/script-engine/src/WebSocketServerClass.h +++ b/libraries/script-engine/src/WebSocketServerClass.h @@ -9,6 +9,9 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +/// @addtogroup ScriptEngine +/// @{ + #ifndef hifi_WebSocketServerClass_h #define hifi_WebSocketServerClass_h @@ -73,6 +76,7 @@ * webSocket.send(TEST_MESSAGE); * }; */ +/// Provides the WebSocketServer scripting interface class WebSocketServerClass : public QObject { Q_OBJECT Q_PROPERTY(QString url READ getURL) @@ -118,3 +122,5 @@ signals: }; #endif // hifi_WebSocketServerClass_h + +/// @} diff --git a/libraries/script-engine/src/WheelEvent.h b/libraries/script-engine/src/WheelEvent.h index 88ac828578..a2b14ac29d 100644 --- a/libraries/script-engine/src/WheelEvent.h +++ b/libraries/script-engine/src/WheelEvent.h @@ -9,6 +9,9 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +/// @addtogroup ScriptEngine +/// @{ + #ifndef hifi_WheelEvent_h #define hifi_WheelEvent_h @@ -18,6 +21,7 @@ class QScriptValue; class QScriptEngine; +/// Represents a mouse wheel event to the scripting engine. Exposed as WheelEvent class WheelEvent { public: WheelEvent(); @@ -42,3 +46,5 @@ public: Q_DECLARE_METATYPE(WheelEvent) #endif // hifi_WheelEvent_h + +/// @} diff --git a/libraries/script-engine/src/XMLHttpRequestClass.h b/libraries/script-engine/src/XMLHttpRequestClass.h index cf95bf1298..013f888be8 100644 --- a/libraries/script-engine/src/XMLHttpRequestClass.h +++ b/libraries/script-engine/src/XMLHttpRequestClass.h @@ -9,6 +9,9 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +/// @addtogroup ScriptEngine +/// @{ + #ifndef hifi_XMLHttpRequestClass_h #define hifi_XMLHttpRequestClass_h @@ -149,6 +152,7 @@ XMlHttpRequest.getResponseHeader(QString) function * req.open("GET", URL); * req.send(); */ +/// Provides the XMLHttpRequest scripting interface class XMLHttpRequestClass : public QObject { Q_OBJECT Q_PROPERTY(QScriptValue response READ getResponse) @@ -374,3 +378,5 @@ private slots: }; #endif // hifi_XMLHttpRequestClass_h + +/// @} diff --git a/plugins/hifiLeapMotion/CMakeLists.txt b/plugins/hifiLeapMotion/CMakeLists.txt index 3075107bb3..de2becc360 100644 --- a/plugins/hifiLeapMotion/CMakeLists.txt +++ b/plugins/hifiLeapMotion/CMakeLists.txt @@ -6,7 +6,12 @@ # See the accompanying file LICENSE or http:#www.apache.org/licenses/LICENSE-2.0.html # -find_package(LEAPMOTION) +if (USE_LEAPMOTION) + find_package(LEAPMOTION) +else() + message(STATUS "Use of Leap Motion SDK not enabled. Run cmake with -DUSE_LEAPMOTION=1 to use it.") +endif() + if (LEAPMOTION_FOUND) set(TARGET_NAME hifiLeapMotion) setup_hifi_plugin(Qml) diff --git a/prebuild.py b/prebuild.py index d5bed2d813..f272b04b23 100644 --- a/prebuild.py +++ b/prebuild.py @@ -130,23 +130,33 @@ def main(): with timer('NSIS'): hifi_utils.downloadAndExtract(assets_url + '/dependencies/NSIS-hifi-plugins-1.0.tgz', "C:/Program Files (x86)") - qtInstallPath = '' + qtInstallPath = None # If not android, install our Qt build if not args.android: qt = hifi_qt.QtDownloader(args) qtInstallPath = qt.cmakePath - with hifi_singleton.Singleton(qt.lockFile) as lock: - with timer('Qt'): - qt.installQt() - qt.writeConfig() + + if qtInstallPath is not None: + # qtInstallPath is None when we're doing a system Qt build + print("cmake path: " + qtInstallPath) + + with hifi_singleton.Singleton(qt.lockFile) as lock: + with timer('Qt'): + qt.installQt() + qt.writeConfig() + else: + if (os.environ["VIRCADIA_USE_SYSTEM_QT"]): + print("System Qt selected") + else: + raise Exception("Internal error: System Qt not selected, but hifi_qt.py failed to return a cmake path") pm = hifi_vcpkg.VcpkgRepo(args) - if qtInstallPath != '': + if qtInstallPath is not None: pm.writeVar('QT_CMAKE_PREFIX_PATH', qtInstallPath) # Only allow one instance of the program to run at a time - if qtInstallPath != '': + if qtInstallPath is not None: pm.writeVar('QT_CMAKE_PREFIX_PATH', qtInstallPath) # Only allow one instance of the program to run at a time @@ -197,4 +207,7 @@ def main(): logger.info('end') print(sys.argv) -main() +try: + main() +except hifi_utils.SilentFatalError as fatal_ex: + sys.exit(fatal_ex.exit_code) diff --git a/scripts/system/create/entityProperties/html/js/entityProperties.js b/scripts/system/create/entityProperties/html/js/entityProperties.js index 5c6806653d..65e14d7203 100644 --- a/scripts/system/create/entityProperties/html/js/entityProperties.js +++ b/scripts/system/create/entityProperties/html/js/entityProperties.js @@ -918,7 +918,6 @@ const GROUPS = [ label: "Material Scale", type: "vec2", vec2Type: "xyz", - min: 0, step: 0.1, decimals: 4, subLabels: [ "x", "y" ], @@ -3695,20 +3694,20 @@ function requestZoneList() { })); } -function addZoneToZonesSelection(propertyId) { +function addZoneToZonesSelection(propertyId, id) { let hiddenField = document.getElementById(propertyId); if (JSON.stringify(hiddenField.value) === '"undefined"') { hiddenField.value = "[]"; } let selectedZones = JSON.parse(hiddenField.value); - let zoneToAdd = document.getElementById("zones-select-" + propertyId).value; - if (!selectedZones.includes(zoneToAdd)) { - selectedZones.push(zoneToAdd); + if (!selectedZones.includes(id)) { + selectedZones.push(id); } hiddenField.value = JSON.stringify(selectedZones); displaySelectedZones(propertyId, true); let propertyName = propertyId.replace("property-", ""); updateProperty(propertyName, selectedZones, false); + document.getElementById("zones-select-selector-list-panel-" + propertyId).style.display = "none"; } function removeZoneFromZonesSelection(propertyId, zoneId) { @@ -3798,7 +3797,12 @@ function createZonesSelection(property, elProperty) { function setZonesSelectionData(element, isEditable) { let zoneSelectorContainer = document.getElementById("zones-selector-" + element.id); - let zoneSelector = "
"; + zoneSelector += "
"; + zoneSelector += "
Select the Zone to add:
"; + zoneSelector += "
"; let i, name; for (i = 0; i < zonesList.length; i++) { if (zonesList[i].name === "") { @@ -3806,28 +3810,34 @@ function setZonesSelectionData(element, isEditable) { } else { name = zonesList[i].name; } - zoneSelector += ""; + zoneSelector += "
"; } - zoneSelector += " "; - zoneSelector += "
"; + zoneSelector += "
"; + zoneSelector += "
"; + zoneSelector += ""; + zoneSelector += "
"; zoneSelector += "
"; zoneSelectorContainer.innerHTML = zoneSelector; displaySelectedZones(element.id, isEditable); } function updateAllZoneSelect() { - let allZoneSelects = document.querySelectorAll(".zoneSelect"); - let i, j, name, propId; + let allZoneSelects = document.querySelectorAll(".zoneSelectList"); + let i, j, name, propId, btnList; for (i = 0; i < allZoneSelects.length; i++) { - allZoneSelects[i].options.length = 0; + btnList = ""; for (j = 0; j < zonesList.length; j++) { if (zonesList[j].name === "") { name = zonesList[j].id; } else { name = zonesList[j].name; } - allZoneSelects[i].options[j] = new Option(name, zonesList[j].id, false , false); + btnList += "
"; } + allZoneSelects[i].innerHTML = btnList; propId = allZoneSelects[i].id.replace("zones-select-", ""); if (document.getElementById("multiZoneSelTools-" + propId).style.display === "block") { displaySelectedZones(propId, true); @@ -4500,6 +4510,7 @@ function loaded() { }); updateVisibleSpaceModeProperties(); + requestZoneList(); if (window.EventBridge !== undefined) { EventBridge.scriptEventReceived.connect(function(data) { diff --git a/scripts/system/html/css/edit-style.css b/scripts/system/html/css/edit-style.css index 9f7f329040..5aea382d63 100644 --- a/scripts/system/html/css/edit-style.css +++ b/scripts/system/html/css/edit-style.css @@ -1955,6 +1955,65 @@ div.multiZoneSelToolbar { padding: 0px; } +div.zoneSelectorListPanel { + position: absolute; + display: none; + width: 100%; + height: 100%; + top: 0px; + left: 0px; + right: 0px; + bottom: 0px; + border-width: 0px; + background-color: #666666; + color: #dddddd; + padding: 0% 2% 0% 2%; + z-index: 2; + cursor: pointer; +} + +div.zoneSelectListHeader { + position: static; + width: 96%; + height: 6%; + top: 0px; + left: 0px; + right: 0px; + bottom: 0px; + padding-top: 4px; + cursor: pointer; + border-width: 0px; +} + +div.zoneSelectList { + position: static; + width: 96%; + height: 86%; + top: 0px; + left: 0px; + right: 0px; + bottom: 0px; + border-width: 0px; + background-color: #c0c0c0; + overflow-y: auto; + padding: 0px; + cursor: pointer; +} + +div.zoneSelectListFooter { + position: static; + width: 96%; + height: auto; + top: 0px; + left: 0px; + right: 0px; + bottom: 0px; + padding: 2px; + cursor: pointer; + border-width: 0px; + text-align: right; +} + #menuBackgroundOverlay{ background-color:transparent; position:fixed; diff --git a/server-console/src/content-update.html b/server-console/src/content-update.html index 7c6b4c9971..d016ba33ad 100644 --- a/server-console/src/content-update.html +++ b/server-console/src/content-update.html @@ -1,13 +1,13 @@ - Vircadia Sandbox + Vircadia Server
-

We backed up your old Sandbox content, just in case.

+

We backed up your old server content, just in case.

To restore it, follow these steps:

@@ -25,7 +25,7 @@
Step 1 -

1. Stop your Sandbox server. +

1. Stop your Vircadia Server.

@@ -35,7 +35,7 @@
Step 4 -

4. Restart your Sandbox server. +

4. Restart your Vircadia Server.

@@ -45,7 +45,7 @@
diff --git a/server-console/src/splash.html b/server-console/src/splash.html index f273ef16b7..e2e84eebae 100644 --- a/server-console/src/splash.html +++ b/server-console/src/splash.html @@ -28,7 +28,7 @@ You can make your home yours by uploading your own models and scripts.

- To get started exploring and creating, check out our Quick-start Guide + To get started exploring and creating, check out our Quick-start Guide

@@ -51,7 +51,7 @@ You can make your home yours by uploading your own models and scripts.

- For more information on managing your server, visit our documentation + For more information on managing your server, visit our documentation

diff --git a/tests/networking/src/PacketTests.cpp b/tests/networking/src/PacketTests.cpp index 589c5f4302..1b13a38488 100644 --- a/tests/networking/src/PacketTests.cpp +++ b/tests/networking/src/PacketTests.cpp @@ -4,6 +4,7 @@ // // Created by Stephen Birarda on 07/14/15. // Copyright 2015 High Fidelity, Inc. +// Copyright 2021 Vircadia contributors. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -20,7 +21,7 @@ std::unique_ptr copyToReadPacket(std::unique_ptr& packet) { auto size = packet->getDataSize(); auto data = std::unique_ptr(new char[size]); memcpy(data.get(), packet->getData(), size); - return NLPacket::fromReceivedPacket(std::move(data), size, HifiSockAddr()); + return NLPacket::fromReceivedPacket(std::move(data), size, SockAddr()); } void PacketTests::emptyPacketTest() { diff --git a/tools/ac-client/src/ACClientApp.cpp b/tools/ac-client/src/ACClientApp.cpp index 3b5db1a1b1..3b6e36b63e 100644 --- a/tools/ac-client/src/ACClientApp.cpp +++ b/tools/ac-client/src/ACClientApp.cpp @@ -49,7 +49,7 @@ ACClientApp::ACClientApp(int argc, char* argv[]) : parser.addOption(listenPortOption); if (!parser.parse(QCoreApplication::arguments())) { - qCritical() << parser.errorText() << endl; + qCritical() << parser.errorText() << Qt::endl; parser.showHelp(); Q_UNREACHABLE(); } diff --git a/tools/atp-client/src/ATPClientApp.cpp b/tools/atp-client/src/ATPClientApp.cpp index 09fcf38dff..a4b9543257 100644 --- a/tools/atp-client/src/ATPClientApp.cpp +++ b/tools/atp-client/src/ATPClientApp.cpp @@ -59,7 +59,7 @@ ATPClientApp::ATPClientApp(int argc, char* argv[]) : parser.addOption(listenPortOption); if (!parser.parse(QCoreApplication::arguments())) { - qCritical() << parser.errorText() << endl; + qCritical() << parser.errorText() << Qt::endl; parser.showHelp(); Q_UNREACHABLE(); } diff --git a/tools/doxygen/Doxyfile b/tools/doxygen/Doxyfile index ac8136a0c5..de001ea220 100644 --- a/tools/doxygen/Doxyfile +++ b/tools/doxygen/Doxyfile @@ -794,7 +794,7 @@ CITE_BIB_FILES = # messages are off. # The default value is: NO. -QUIET = NO +QUIET = YES # The WARNINGS tag can be used to turn on/off the warning messages that are # generated to standard error (stderr) by doxygen. If WARNINGS is set to YES diff --git a/tools/doxygen/README.md b/tools/doxygen/README.md index d6a6646033..a8363abd6c 100644 --- a/tools/doxygen/README.md +++ b/tools/doxygen/README.md @@ -7,8 +7,6 @@ **Doxygen** ≥ 1.9.1 - https://www.doxygen.nl/ -Make a `/build/doxygen/` directory. - If you want to run Doxygen from a command prompt, add the Doxygen install's `/bin` directory to your system PATH. diff --git a/tools/ice-client/src/ICEClientApp.cpp b/tools/ice-client/src/ICEClientApp.cpp index 0301fad6f4..d35223885a 100644 --- a/tools/ice-client/src/ICEClientApp.cpp +++ b/tools/ice-client/src/ICEClientApp.cpp @@ -4,6 +4,7 @@ // // Created by Seth Alves on 3/5/15. // Copyright 2015 High Fidelity, Inc. +// Copyright 2021 Vircadia contributors. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -45,7 +46,7 @@ ICEClientApp::ICEClientApp(int argc, char* argv[]) : parser.addOption(cacheSTUNOption); if (!parser.parse(QCoreApplication::arguments())) { - qCritical() << parser.errorText() << endl; + qCritical() << parser.errorText() << Qt::endl; parser.showHelp(); Q_UNREACHABLE(); } @@ -62,7 +63,7 @@ ICEClientApp::ICEClientApp(int argc, char* argv[]) : const_cast(&networking())->setEnabled(QtWarningMsg, false); } - _stunSockAddr = HifiSockAddr(STUN_SERVER_HOSTNAME, STUN_SERVER_PORT, true); + _stunSockAddr = SockAddr(STUN_SERVER_HOSTNAME, STUN_SERVER_PORT, true); _cacheSTUNResult = parser.isSet(cacheSTUNOption); @@ -79,7 +80,7 @@ ICEClientApp::ICEClientApp(int argc, char* argv[]) : } } - _iceServerAddr = HifiSockAddr("127.0.0.1", ICE_SERVER_DEFAULT_PORT); + _iceServerAddr = SockAddr("127.0.0.1", ICE_SERVER_DEFAULT_PORT); if (parser.isSet(iceServerAddressOption)) { // parse the IP and port combination for this target QString hostnamePortString = parser.value(iceServerAddressOption); @@ -96,7 +97,7 @@ ICEClientApp::ICEClientApp(int argc, char* argv[]) : QMetaObject::invokeMethod(this, "quit", Qt::QueuedConnection); } else { - _iceServerAddr = HifiSockAddr(address, port); + _iceServerAddr = SockAddr(address, port); } } @@ -142,8 +143,8 @@ void ICEClientApp::openSocket() { if (_verbose) { qDebug() << "local port is" << _socket->localPort(); } - _localSockAddr = HifiSockAddr("127.0.0.1", _socket->localPort()); - _publicSockAddr = HifiSockAddr("127.0.0.1", _socket->localPort()); + _localSockAddr = SockAddr("127.0.0.1", _socket->localPort()); + _publicSockAddr = SockAddr("127.0.0.1", _socket->localPort()); _domainPingCount = 0; } @@ -238,7 +239,7 @@ void ICEClientApp::stunResponseTimeout() { QCoreApplication::exit(stunFailureExitStatus); } -void ICEClientApp::sendPacketToIceServer(PacketType packetType, const HifiSockAddr& iceServerSockAddr, +void ICEClientApp::sendPacketToIceServer(PacketType packetType, const SockAddr& iceServerSockAddr, const QUuid& clientID, const QUuid& peerID) { std::unique_ptr icePacket = NLPacket::create(packetType); @@ -303,7 +304,7 @@ void ICEClientApp::processSTUNResponse(std::unique_ptr packet) uint16_t newPublicPort; QHostAddress newPublicAddress; if (LimitedNodeList::parseSTUNResponse(packet.get(), newPublicAddress, newPublicPort)) { - _publicSockAddr = HifiSockAddr(newPublicAddress, newPublicPort); + _publicSockAddr = SockAddr(newPublicAddress, newPublicPort); if (_verbose) { qDebug() << "My public address is" << _publicSockAddr; } @@ -326,7 +327,7 @@ void ICEClientApp::processPacket(std::unique_ptr packet) { } QSharedPointer message = QSharedPointer::create(*nlPacket); - const HifiSockAddr& senderAddr = message->getSenderSockAddr(); + const SockAddr& senderAddr = message->getSenderSockAddr(); if (nlPacket->getType() == PacketType::ICEServerPeerInformation) { // cancel the timeout timer diff --git a/tools/ice-client/src/ICEClientApp.h b/tools/ice-client/src/ICEClientApp.h index 642b9bc36b..c541c99d0b 100644 --- a/tools/ice-client/src/ICEClientApp.h +++ b/tools/ice-client/src/ICEClientApp.h @@ -4,6 +4,7 @@ // // Created by Seth Alves on 2016-9-16 // Copyright 2016 High Fidelity, Inc. +// Copyright 2021 Vircadia contributors. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -54,7 +55,7 @@ private: void setState(int newState); void doSomething(); - void sendPacketToIceServer(PacketType packetType, const HifiSockAddr& iceServerSockAddr, + void sendPacketToIceServer(PacketType packetType, const SockAddr& iceServerSockAddr, const QUuid& clientID, const QUuid& peerID); void icePingDomainServer(); void processSTUNResponse(std::unique_ptr packet); @@ -65,7 +66,7 @@ private: bool _cacheSTUNResult; // should we only talk to stun server once? bool _stunResultSet { false }; // have we already talked to stun server? - HifiSockAddr _stunSockAddr; + SockAddr _stunSockAddr; unsigned int _actionCount { 0 }; unsigned int _actionMax { 0 }; @@ -75,10 +76,10 @@ private: QTimer* _pingDomainTimer { nullptr }; - HifiSockAddr _iceServerAddr; + SockAddr _iceServerAddr; - HifiSockAddr _localSockAddr; - HifiSockAddr _publicSockAddr; + SockAddr _localSockAddr; + SockAddr _publicSockAddr; udt::Socket* _socket { nullptr }; bool _domainServerPeerSet { false }; diff --git a/tools/jsdoc/api-mainpage.md b/tools/jsdoc/api-mainpage.md index 9135c88bbc..2b8f28ebd4 100644 --- a/tools/jsdoc/api-mainpage.md +++ b/tools/jsdoc/api-mainpage.md @@ -1,9 +1,11 @@ -The Vircadia JavaScript API lets content creators and developers create new experiences and transform virtual worlds within the Vircadia metaverse. With it, you can build great content, customize avatars, play audio and so much more. +The Vircadia JavaScript API lets content creators and developers create new experiences and transform virtual worlds within the Vircadia metaverse. With it, you can build great content, customize avatars, play audio and so much more. You are most likely to interact with these APIs: * The **[Entities](Entities.html)** namespace lets you add, remove, and edit entities around you to build an interactive environment. In addition, you can use this namespace to find entities in range, direction, collision, or raytrace. -* The **[AvatarList](AvatarList.html)**, **[MyAvatar](MyAvatar.html)**, and **[Avatar](Avatar.html)** namespaces affect your personal avatars, and lets you get information on other people's avatars. +* The **[AvatarList](AvatarList.html)**, **[MyAvatar](MyAvatar.html)**, and **[Avatar](Avatar.html)** namespaces affect your personal avatars, and lets you get information on other people's avatars. * The **[Script](Script.html)** namespace lets you to connect callbacks from your client to script, such as functionality that is dependent on time (`Script.update`, `Script.setTimeout`, `Script.setInterval`, etc), connect paths relatively to assets (`Script.resolvePath`), refer to other scripts (`Script.require`, `Script.include`), or connect functions to events which occur when the script is turned off (`Script.scriptEnding`). -To learn more about using Vircadia and exploring the metaverse, visit the [Vircadia Documentation](https://docs.vircadia.dev). +To learn more about using Vircadia and exploring the metaverse, visit the [Vircadia User Documentation](https://docs.vircadia.com). + +For source developer oriented documentation, visit the [Vircadia Developer Documentation](https://docs.vircadia.dev). diff --git a/tools/nitpick/CMakeLists.txt b/tools/nitpick/CMakeLists.txt index 8b4a5d03df..18ee84c0e5 100644 --- a/tools/nitpick/CMakeLists.txt +++ b/tools/nitpick/CMakeLists.txt @@ -12,7 +12,7 @@ generate_qrc(OUTPUT ${RESOURCES_QRC} PATH ${CMAKE_CURRENT_SOURCE_DIR}/resources add_custom_command( OUTPUT ${RESOURCES_RCC} DEPENDS ${RESOURCES_QRC} ${GENERATE_QRC_DEPENDS} - COMMAND "${QT_DIR}/bin/rcc" + COMMAND "${RCC_BINARY}" ARGS ${RESOURCES_QRC} -binary -o ${RESOURCES_RCC} ) diff --git a/tools/nitpick/src/TestCreator.cpp b/tools/nitpick/src/TestCreator.cpp index 652292b9dc..baecb3e173 100644 --- a/tools/nitpick/src/TestCreator.cpp +++ b/tools/nitpick/src/TestCreator.cpp @@ -207,11 +207,11 @@ void TestCreator::appendTestResultsToFile(const TestResult& testResult, const QP // Create text file describing the failure QTextStream stream(&descriptionFile); - stream << "TestCreator in folder " << testResult._pathname.left(testResult._pathname.length() - 1) << endl; // remove trailing '/' - stream << "Expected image was " << testResult._expectedImageFilename << endl; - stream << "Actual image was " << testResult._actualImageFilename << endl; - stream << "Similarity index was " << testResult._errorGlobal << endl; - stream << "Worst tile was " << testResult._errorLocal << endl; + stream << "TestCreator in folder " << testResult._pathname.left(testResult._pathname.length() - 1) << Qt::endl; // remove trailing '/' + stream << "Expected image was " << testResult._expectedImageFilename << Qt::endl; + stream << "Actual image was " << testResult._actualImageFilename << Qt::endl; + stream << "Similarity index was " << testResult._errorGlobal << Qt::endl; + stream << "Worst tile was " << testResult._errorLocal << Qt::endl; descriptionFile.close(); @@ -415,7 +415,7 @@ void TestCreator::includeTest(QTextStream& textStream, const QString& testPathna QString partialPath = extractPathFromTestsDown(testPathname); QString partialPathWithoutTests = partialPath.right(partialPath.length() - 7); - textStream << "Script.include(testsRootPath + \"" << partialPathWithoutTests + "\");" << endl; + textStream << "Script.include(testsRootPath + \"" << partialPathWithoutTests + "\");" << Qt::endl; } void TestCreator::createTests(const QString& clientProfile) { @@ -994,7 +994,7 @@ void TestCreator::createRecursiveScript(const QString& directory, bool interacti QTextStream textStream(&recursiveTestsFile); - textStream << "// This is an automatically generated file, created by nitpick" << endl; + textStream << "// This is an automatically generated file, created by nitpick" << Qt::endl; // Include 'nitpick.js' QString branch = nitpick->getSelectedBranch(); @@ -1002,31 +1002,31 @@ void TestCreator::createRecursiveScript(const QString& directory, bool interacti textStream << "PATH_TO_THE_REPO_PATH_UTILS_FILE = \"https://raw.githubusercontent.com/" + user + "/hifi_tests/" + branch + "/tests/utils/branchUtils.js\";" - << endl; - textStream << "Script.include(PATH_TO_THE_REPO_PATH_UTILS_FILE);" << endl << endl; + << Qt::endl; + textStream << "Script.include(PATH_TO_THE_REPO_PATH_UTILS_FILE);" << Qt::endl << Qt::endl; // The 'depth' variable is used to signal when to start running the recursive scripts - textStream << "if (typeof depth === 'undefined') {" << endl; - textStream << " depth = 0;" << endl; - textStream << " nitpick = createNitpick(Script.resolvePath(\".\"));" << endl; - textStream << " testsRootPath = nitpick.getTestsRootPath();" << endl << endl; - textStream << " nitpick.enableRecursive();" << endl; - textStream << " nitpick.enableAuto();" << endl; - textStream << "} else {" << endl; - textStream << " depth++" << endl; - textStream << "}" << endl << endl; + textStream << "if (typeof depth === 'undefined') {" << Qt::endl; + textStream << " depth = 0;" << Qt::endl; + textStream << " nitpick = createNitpick(Script.resolvePath(\".\"));" << Qt::endl; + textStream << " testsRootPath = nitpick.getTestsRootPath();" << Qt::endl << Qt::endl; + textStream << " nitpick.enableRecursive();" << Qt::endl; + textStream << " nitpick.enableAuto();" << Qt::endl; + textStream << "} else {" << Qt::endl; + textStream << " depth++" << Qt::endl; + textStream << "}" << Qt::endl << Qt::endl; // Now include the test scripts for (int i = 0; i < directories.length(); ++i) { includeTest(textStream, directories.at(i)); } - textStream << endl; - textStream << "if (depth > 0) {" << endl; - textStream << " depth--;" << endl; - textStream << "} else {" << endl; - textStream << " nitpick.runRecursive();" << endl; - textStream << "}" << endl << endl; + textStream << Qt::endl; + textStream << "if (depth > 0) {" << Qt::endl; + textStream << " depth--;" << Qt::endl; + textStream << "} else {" << Qt::endl; + textStream << " nitpick.runRecursive();" << Qt::endl; + textStream << "}" << Qt::endl << Qt::endl; recursiveTestsFile.close(); } diff --git a/tools/skeleton-dump/src/SkeletonDumpApp.cpp b/tools/skeleton-dump/src/SkeletonDumpApp.cpp index 42a1c78090..a736cf60b8 100644 --- a/tools/skeleton-dump/src/SkeletonDumpApp.cpp +++ b/tools/skeleton-dump/src/SkeletonDumpApp.cpp @@ -29,7 +29,7 @@ SkeletonDumpApp::SkeletonDumpApp(int argc, char* argv[]) : QCoreApplication(argc parser.addOption(inputFilenameOption); if (!parser.parse(QCoreApplication::arguments())) { - qCritical() << parser.errorText() << endl; + qCritical() << parser.errorText() << Qt::endl; parser.showHelp(); _returnCode = 1; return; diff --git a/tools/udt-test/src/UDTTest.cpp b/tools/udt-test/src/UDTTest.cpp index 65bf2c7ebd..a546b61b96 100644 --- a/tools/udt-test/src/UDTTest.cpp +++ b/tools/udt-test/src/UDTTest.cpp @@ -4,6 +4,7 @@ // // Created by Stephen Birarda on 2015-07-30. // Copyright 2015 High Fidelity, Inc. +// Copyright 2021 Vircadia contributors. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -90,7 +91,7 @@ UDTTest::UDTTest(int& argc, char** argv) : QMetaObject::invokeMethod(this, "quit", Qt::QueuedConnection); } else { - _target = HifiSockAddr(address, port); + _target = SockAddr(address, port); qDebug() << "Packets will be sent to" << _target; } } @@ -198,7 +199,7 @@ UDTTest::UDTTest(int& argc, char** argv) : }); } _socket.setMessageFailureHandler( - [this](HifiSockAddr from, udt::Packet::MessageNumber messageNumber) { + [this](SockAddr from, udt::Packet::MessageNumber messageNumber) { _pendingMessages.erase(messageNumber); } ); diff --git a/tools/udt-test/src/UDTTest.h b/tools/udt-test/src/UDTTest.h index 3a4b1b897d..0202d75b38 100644 --- a/tools/udt-test/src/UDTTest.h +++ b/tools/udt-test/src/UDTTest.h @@ -4,6 +4,7 @@ // // Created by Stephen Birarda on 2015-07-30. // Copyright 2015 High Fidelity, Inc. +// Copyright 2021 Vircadia contributors. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -49,7 +50,7 @@ private: QCommandLineParser _argumentParser; udt::Socket _socket; - HifiSockAddr _target; // the target for sent packets + SockAddr _target; // the target for sent packets int _minPacketSize { udt::MAX_PACKET_SIZE }; int _maxPacketSize { udt::MAX_PACKET_SIZE }; diff --git a/tools/vhacd-util/src/VHACDUtilApp.cpp b/tools/vhacd-util/src/VHACDUtilApp.cpp index 3d675f8baf..bf97adbd92 100644 --- a/tools/vhacd-util/src/VHACDUtilApp.cpp +++ b/tools/vhacd-util/src/VHACDUtilApp.cpp @@ -188,7 +188,7 @@ VHACDUtilApp::VHACDUtilApp(int argc, char* argv[]) : if (!parser.parse(QCoreApplication::arguments())) { - qCritical() << parser.errorText() << endl; + qCritical() << parser.errorText() << Qt::endl; parser.showHelp(); Q_UNREACHABLE(); }
ValueNameDescription
Report location change requests.Report when ability to navigate back changes.Report when a mouse press occurs on a particular entity.Include a script file asynchronously.Report the URL of a default particle.