diff --git a/.github/stale.yml b/.github/stale.yml new file mode 100644 index 0000000000..d5c79b8504 --- /dev/null +++ b/.github/stale.yml @@ -0,0 +1,17 @@ +# Number of days of inactivity before an issue becomes stale +daysUntilStale: 120 +# 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 +# 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. +# 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 ee6ef88d0e..685c5c9524 100644 --- a/.github/workflows/master_build.yml +++ b/.github/workflows/master_build.yml @@ -35,7 +35,7 @@ jobs: include: - os: ubuntu-18.04 build_type: full - apt-dependencies: mesa-common-dev libegl1 libglvnd-dev libdouble-conversion1 libpulse0 + apt-dependencies: mesa-common-dev libegl1 libglvnd-dev libdouble-conversion1 libpulse0 libsnappy1v5 libwebpdemux2 libwebpmux3 fail-fast: false runs-on: ${{matrix.os}} steps: @@ -50,6 +50,7 @@ jobs: echo "UPLOAD_PREFIX=master" >> $GITHUB_ENV echo ::set-output name=github_sha_short::`echo $GIT_COMMIT | cut -c1-7` echo "JOB_NAME=build (${{matrix.os}}, ${{matrix.build_type}})" >> $GITHUB_ENV + echo "APP_TARGET_NAME=$APP_NAME" >> $GITHUB_ENV # Linux build variables if [[ "${{ matrix.os }}" = "ubuntu-"* ]]; then echo "PYTHON_EXEC=python3" >> $GITHUB_ENV @@ -65,6 +66,7 @@ jobs: echo "INSTALLER_EXT=dmg" >> $GITHUB_ENV echo "CMAKE_EXTRA=-DCMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_REQUIRED=OFF -DOPENSSL_ROOT_DIR=/usr/local/opt/openssl -G Xcode" >> $GITHUB_ENV echo "::set-output name=symbols_archive::${BUILD_NUMBER}-${{ matrix.build_type }}-mac-symbols.zip" + echo "APP_TARGET_NAME=Vircadia" >> $GITHUB_ENV fi # Windows build variables if [ "${{ matrix.os }}" = "windows-latest" ]; then @@ -126,7 +128,7 @@ jobs: - name: Build application working-directory: ${{runner.workspace}}/build shell: bash - run: cmake --build . --config $BUILD_TYPE --target $APP_NAME $CMAKE_BUILD_EXTRA + run: cmake --build . --config $BUILD_TYPE --target $APP_TARGET_NAME $CMAKE_BUILD_EXTRA - name: Build domain server working-directory: ${{runner.workspace}}/build shell: bash diff --git a/.github/workflows/pr_build.yml b/.github/workflows/pr_build.yml index 9d6984b5b2..8b4201f068 100644 --- a/.github/workflows/pr_build.yml +++ b/.github/workflows/pr_build.yml @@ -36,9 +36,11 @@ jobs: build_type: full - os: macOS-latest build_type: full + - os: macOS-latest + build_type: client - os: ubuntu-18.04 build_type: full - apt-dependencies: mesa-common-dev libegl1 libglvnd-dev libdouble-conversion1 libpulse0 + apt-dependencies: mesa-common-dev libegl1 libglvnd-dev libdouble-conversion1 libpulse0 libsnappy1v5 libwebpdemux2 libwebpmux3 - os: ubuntu-18.04 build_type: android apt-dependencies: mesa-common-dev libegl1 libglvnd-dev libdouble-conversion1 libpulse0 @@ -52,25 +54,39 @@ jobs: run: | echo ::set-output name=github_sha_short::`echo $GIT_COMMIT | cut -c1-7` echo "JOB_NAME=build (${{matrix.os}}, ${{matrix.build_type}})" >> $GITHUB_ENV + echo "APP_TARGET_NAME=$APP_NAME" >> $GITHUB_ENV # Linux build variables if [[ "${{ matrix.os }}" = "ubuntu-"* ]]; then echo "PYTHON_EXEC=python3" >> $GITHUB_ENV echo "INSTALLER_EXT=*" >> $GITHUB_ENV echo "CMAKE_BUILD_EXTRA=-- -j3" >> $GITHUB_ENV - echo "CMAKE_EXTRA=-DBUILD_TOOLS:BOOLEAN=FALSE -DHIFI_PYTHON_EXEC:FILEPATH=$(which python3)" >> $GITHUB_ENV + if [ "${{ matrix.build_type }}" = "full" ]; then + echo "CMAKE_EXTRA=-DBUILD_TOOLS:BOOLEAN=FALSE -DHIFI_PYTHON_EXEC:FILEPATH=$(which python3)" >> $GITHUB_ENV + else + echo "CMAKE_EXTRA=-DCLIENT_ONLY=1 -DBUILD_TOOLS:BOOLEAN=FALSE -DHIFI_PYTHON_EXEC:FILEPATH=$(which python3)" >> $GITHUB_ENV + fi fi # Mac build variables if [ "${{ matrix.os }}" = "macOS-latest" ]; then echo "PYTHON_EXEC=python3" >> $GITHUB_ENV echo "INSTALLER_EXT=dmg" >> $GITHUB_ENV - echo "CMAKE_EXTRA=-DCMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_REQUIRED=OFF -DOPENSSL_ROOT_DIR=/usr/local/opt/openssl -G Xcode" >> $GITHUB_ENV + if [ "${{ matrix.build_type }}" = "full" ]; then + echo "CMAKE_EXTRA=-DCMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_REQUIRED=OFF -DOPENSSL_ROOT_DIR=/usr/local/opt/openssl -G Xcode" >> $GITHUB_ENV + else + echo "CMAKE_EXTRA=-DCLIENT_ONLY=1 -DCMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_REQUIRED=OFF -DOPENSSL_ROOT_DIR=/usr/local/opt/openssl -G Xcode" >> $GITHUB_ENV + fi + echo "APP_TARGET_NAME=Vircadia" >> $GITHUB_ENV fi # Windows build variables if [ "${{ matrix.os }}" = "windows-latest" ]; then echo "PYTHON_EXEC=python" >> $GITHUB_ENV echo "INSTALLER_EXT=exe" >> $GITHUB_ENV - echo "CMAKE_EXTRA=-A x64" >> $GITHUB_ENV + if [ "${{ matrix.build_type }}" = "full" ]; then + echo "CMAKE_EXTRA=-A x64" >> $GITHUB_ENV + else + echo "CMAKE_EXTRA=-A x64 -DCLIENT_ONLY=1" >> $GITHUB_ENV + fi fi # Android + Quest build variables if [[ "${{ matrix.build_type }}" == "android" ]]; then @@ -86,9 +102,13 @@ jobs: echo "${{ steps.buildenv1.outputs.symbols_archive }}" echo "GIT_COMMIT_SHORT=${{ steps.buildenv1.outputs.github_sha_short }}" >> $GITHUB_ENV if [[ "${{ matrix.build_type }}" != "android" ]]; then - echo "ARTIFACT_PATTERN=Vircadia-PR${{ github.event.number }}-*.$INSTALLER_EXT" >> $GITHUB_ENV - # Build type variables - echo "INSTALLER=Vircadia-$RELEASE_NUMBER-$GIT_COMMIT_SHORT.$INSTALLER_EXT" >> $GITHUB_ENV + if [ "${{ matrix.build_type }}" = "full" ]; then + echo "ARTIFACT_PATTERN=Vircadia-PR${{ github.event.number }}-*.$INSTALLER_EXT" >> $GITHUB_ENV + echo "INSTALLER=Vircadia-$RELEASE_NUMBER-$GIT_COMMIT_SHORT.$INSTALLER_EXT" >> $GITHUB_ENV + else + echo "ARTIFACT_PATTERN=Vircadia-Interface-PR${{ github.event.number }}-*.$INSTALLER_EXT" >> $GITHUB_ENV + echo "INSTALLER=Vircadia-Interface-$RELEASE_NUMBER-$GIT_COMMIT_SHORT.$INSTALLER_EXT" >> $GITHUB_ENV + fi else echo "ARTIFACT_PATTERN=*.$INSTALLER_EXT" >> $GITHUB_ENV fi @@ -124,7 +144,7 @@ jobs: if: matrix.build_type == 'full' || matrix.build_type == 'client' working-directory: ${{runner.workspace}}/build shell: bash - run: cmake --build . --config $BUILD_TYPE --target $APP_NAME $CMAKE_BUILD_EXTRA + run: cmake --build . --config $BUILD_TYPE --target $APP_TARGET_NAME $CMAKE_BUILD_EXTRA - name: Build Domain Server if: matrix.build_type == 'full' working-directory: ${{runner.workspace}}/build @@ -136,7 +156,7 @@ jobs: shell: bash run: cmake --build . --config $BUILD_TYPE --target assignment-client $CMAKE_BUILD_EXTRA - name: Build Console - if: matrix.build_type == 'full' + if: matrix.build_type == 'full' || matrix.os == 'windows-latest' working-directory: ${{runner.workspace}}/build shell: bash run: cmake --build . --config $BUILD_TYPE --target packaged-server-console $CMAKE_BUILD_EXTRA @@ -168,6 +188,16 @@ jobs: done } retry cmake --build . --config $BUILD_TYPE --target package $CMAKE_BUILD_EXTRA + # As of 05/17/21 GitHub Virtual Environments changed their "Ubuntu 18.04.5 LTS" image to include two versions of CMake for Android + # https://github.com/actions/virtual-environments/blob/ubuntu18/20210517.1/images/linux/Ubuntu1804-README.md + # Removing 3.18.1 version of CMake as its not compatible with our Android build. + # It will fall back to 3.10.2 which is already installed + - name: Nuke CMake 3.18.1-g262b901 + if: matrix.build_type == 'android' + shell: bash + working-directory: ${{runner.workspace}}/vircadia + run: | + /usr/local/lib/android/sdk/tools/bin/sdkmanager --uninstall 'cmake;3.18.1' - name: Build for Android + Quest if: matrix.build_type == 'android' shell: bash diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000000..c8cdef6d56 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "vircadia-web"] + path = vircadia-web + url = ../vircadia-web.git \ No newline at end of file diff --git a/.grenrc.js b/.grenrc.js new file mode 100644 index 0000000000..0ac3acc842 --- /dev/null +++ b/.grenrc.js @@ -0,0 +1,43 @@ +// +// .grenrc.js +// +// Created by Kalila L. on May 25, 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 +// +// This configuration is for generating a changelog with gren for a GitHub repository. +// https://github.com/github-tools/github-release-notes +// +// gren changelog -G +// + +module.exports = { + "dataSource": "prs", + "prefix": "", + "ignoreLabels": [ + "enhancement", + "bugfix", + "CR Approved", + "QA Approved", + "allow-build-upload", + "bug", + "confirmed", + "do not merge", + "duplicate", + "good first issue", + "help wanted", + "hifi migration", + "high risk", + "rebuild", + "merge right before snip" + ], + "onlyMilestones": true, + "groupBy": { + "Enhancements": ["enhancement"], + "Bug Fixes": ["bugfix"], + "Docs": ["docs"] + }, + "changelogFilename": "CHANGELOG.md" +} diff --git a/BUILD.md b/BUILD.md index 02d528d03a..82da773f08 100644 --- a/BUILD.md +++ b/BUILD.md @@ -1,116 +1,153 @@ # General Build Information -*Last Updated on August 26, 2020* +*Last Updated on March 8, 2021* -### OS Specific Build Guides +## OS Specific Build Guides * [Build Windows](BUILD_WIN.md) - complete instructions for Windows. * [Build Linux](BUILD_LINUX.md) - additional instructions for Linux. * [Build OSX](BUILD_OSX.md) - additional instructions for OS X. * [Build Android](BUILD_ANDROID.md) - additional instructions for Android. -### Dependencies -- [git](https://git-scm.com/downloads): >= 1.6 -- [cmake](https://cmake.org/download/): 3.9 +## Dependencies +- [git](https://git-scm.com/downloads): >= 1.6 +- [CMake](https://cmake.org/download/): 3.9 (or greater up to 3.18.x) - [Python](https://www.python.org/downloads/): 3.6 or higher - [Node.JS](https://nodejs.org/en/): >= 12.13.1 LTS - Used to build the Screen Sharing executable. -### CMake External Project Dependencies +## CMake External Project Dependencies These dependencies need not be installed manually. They are automatically downloaded on the platforms where they are required. -- [Bullet Physics Engine](https://github.com/bulletphysics/bullet3/releases): 2.83 -- [glm](https://glm.g-truc.net/0.9.8/index.html): 0.9.8 -- [Oculus SDK](https://developer.oculus.com/downloads/): 1.11 (Windows) / 0.5 (Mac) -- [OpenVR](https://github.com/ValveSoftware/openvr): 1.11.11 (Windows, Linux) -- [Polyvox](http://www.volumesoffun.com/): 0.2.1 -- [QuaZip](https://sourceforge.net/projects/quazip/files/quazip/): 0.7.3 -- [SDL2](https://www.libsdl.org/download-2.0.php): 2.0.3 -- [Intel Threading Building Blocks](https://www.threadingbuildingblocks.org/): 4.3 -- [vcpkg](https://github.com/hifi-archive/vcpkg): -- [VHACD](https://github.com/virneo/v-hacd) -- [zlib](http://www.zlib.net/): 1.28 (Win32 only) -- [nvtt](https://github.com/hifi-archive/nvidia-texture-tools): 2.1.1 (customized) +- [Bullet Physics Engine](https://github.com/bulletphysics/bullet3/releases): 2.83 +- [glm](https://glm.g-truc.net/0.9.8/index.html): 0.9.8 +- [Oculus SDK](https://developer.oculus.com/downloads/): 1.11 (Windows) / 0.5 (Mac) +- [OpenVR](https://github.com/ValveSoftware/openvr): 1.11.11 (Windows, Linux) +- [Polyvox](http://www.volumesoffun.com/): 0.2.1 +- [QuaZip](https://sourceforge.net/projects/quazip/files/quazip/): 0.7.3 +- [SDL2](https://www.libsdl.org/download-2.0.php): 2.0.3 +- [Intel Threading Building Blocks](https://www.threadingbuildingblocks.org/): 4.3 +- [vcpkg](https://github.com/hifi-archive/vcpkg): +- [VHACD](https://github.com/virneo/v-hacd) +- [zlib](http://www.zlib.net/): 1.28 (Win32 only) +- [nvtt](https://github.com/hifi-archive/nvidia-texture-tools): 2.1.1 (customized) The above dependencies will be downloaded, built, linked and included automatically by CMake where we require them. The CMakeLists files that handle grabbing each of the following external dependencies can be found in the [cmake/externals folder](cmake/externals). The resulting downloads, source files and binaries will be placed in the `build/ext` folder in each of the subfolders for each external project. These are not placed in your normal build tree when doing an out of source build so that they do not need to be re-downloaded and re-compiled every time the CMake build folder is cleared. Should you want to force a re-download and re-compile of a specific external, you can simply remove that directory from the appropriate subfolder in `build/ext`. Should you want to force a re-download and re-compile of all externals, just remove the `build/ext` folder. -#### CMake +### CMake Vircadia uses CMake to generate build files and project files for your platform. -#### Qt -CMake will download Qt 5.12.3 using vcpkg. +### Qt -To override this (i.e. use an installed Qt configuration - you will need to set a QT_CMAKE_PREFIX_PATH environment variable pointing to your Qt **lib/cmake** folder. -This can either be entered directly into your shell session before you build or in your shell profile (e.g.: ~/.bash_profile, ~/.bashrc, ~/.zshrc - this depends on your shell and environment). The path it needs to be set to will depend on where and how Qt5 was installed. e.g. +CMake will download Qt 5.15.2 using vcpkg. - export QT_CMAKE_PREFIX_PATH=/usr/local/Qt5.12.3/gcc_64/lib/cmake - export QT_CMAKE_PREFIX_PATH=/usr/local/qt/5.12.3/clang_64/lib/cmake/ - export QT_CMAKE_PREFIX_PATH=/usr/local/Cellar/qt5/5.12.3/lib/cmake - export QT_CMAKE_PREFIX_PATH=/usr/local/opt/qt5/lib/cmake +To override this - i.e., use an installed Qt configuration - you need to set a QT_CMAKE_PREFIX_PATH environment variable pointing to your Qt **lib/cmake** folder. +This can either be entered directly into your shell session before you build or in your shell profile (e.g.: ~/.bash_profile, ~/.bashrc, ~/.zshrc - this depends on your shell and environment). The path it needs to be set to will depend on where and how Qt5 was installed. -#### VCPKG +For example, under Linux: +```bash +export QT_CMAKE_PREFIX_PATH=/usr/local/Qt5.15.2/gcc_64/lib/cmake +export QT_CMAKE_PREFIX_PATH=/usr/local/qt/5.15.2/clang_64/lib/cmake/ +export QT_CMAKE_PREFIX_PATH=/usr/local/Cellar/qt5/5.15.2/lib/cmake +export QT_CMAKE_PREFIX_PATH=/usr/local/opt/qt5/lib/cmake +``` + +For example, under Windows: + + set QT_CMAKE_PREFIX_PATH=C:\Qt\5.15.2\msvc2019_64\lib\cmake + +For example, under OSX: + + export QT_CMAKE_PREFIX_PATH=/usr/local/Cellar/qt5/5.15.2/lib/cmake + +Note: You only need the following components checked under Qt 5.15.2 (select the "Custom Installation" option): +"MSVC 2019 64-bit", "Qt WebEngine", and "Qt Script (Deprecated)". + +Note: Installing the sources is optional but recommended if you have room for them (~3GB). You may also want the Qt debug +information files (~7GB). + +Note: Installing Qt Creator is optional but recommended if you will be editing QML files. + +### VCPKG Vircadia uses vcpkg to download and build dependencies. You do not need to install vcpkg. Building the dependencies can be lengthy and the resulting files will be stored in your OS temp directory. -However, those files can potentially get cleaned up by the OS, so in order to avoid this and having to redo the lengthy build step, you can set the following environment variable: +However, those files can potentially get cleaned up by the OS, so in order to avoid this and having to redo the lengthy build step, you can set an environment variable. - export HIFI_VCPKG_BASE=/path/to/directory +Linux: + +```bash +export HIFI_VCPKG_BASE=/path/to/directory +``` + +Windows: +```bash +set HIFI_VCPKG_BASE=/path/to/directory +``` Where `/path/to/directory` is the path to a directory where you wish the build files to get stored. -#### Generating Build Files +### Generating Build Files -##### Possible Environment Variables +#### Possible Environment Variables - // The URL to post the dump to. - CMAKE_BACKTRACE_URL - // The identifying tag of the release. - CMAKE_BACKTRACE_TOKEN - - // The release version, e.g., 2021.3.2. - RELEASE_NUMBER - // The release name, e.g., Eos. - RELEASE_NAME - // The build commit, e.g., use a Git hash for the most recent commit in the branch - fd6973b. - BUILD_NUMBER +```text +// The URL to post the dump to. +CMAKE_BACKTRACE_URL +// The identifying tag of the release. +CMAKE_BACKTRACE_TOKEN - // The type of release. - RELEASE_TYPE=PRODUCTION|PR|DEV - - // The Interface will have a custom default home and startup location. - INITIAL_STARTUP_LOCATION=Location/IP/URL - - // Code-signing environment variables must be set during runtime of CMake AND globally when the signing takes place. - HF_PFX_FILE=Path to certificate - HF_PFX_PASSPHRASE=Passphrase for certificate - - // Determine the build type - PRODUCTION_BUILD=0|1 - PR_BUILD=0|1 - STABLE_BUILD=0|1 - - // Determine if to utilize testing or stable Metaverse URLs - USE_STABLE_GLOBAL_SERVICES=1 - BUILD_GLOBAL_SERVICES=STABLE - -##### Generate Files +// The release version, e.g., 2021.3.2. +RELEASE_NUMBER +// The release name, e.g., Eos. +RELEASE_NAME +// The build commit, e.g., use a Git hash for the most recent commit in the branch - fd6973b. + +BUILD_NUMBER + +// The type of release. +RELEASE_TYPE=PRODUCTION|PR|DEV + +// The Interface will have a custom default home and startup location. +PRELOADED_STARTUP_LOCATION=Location/IP/URL +// The Interface will have a custom default script whitelist, comma separated, no spaces. +// This will also activate the whitelist on Interface's first run. +PRELOADED_SCRIPT_WHITELIST=ListOfEntries + +// Code-signing environment variables must be set during runtime of CMake AND globally when the signing takes place. +HF_PFX_FILE=Path to certificate +HF_PFX_PASSPHRASE=Passphrase for certificate + +// Determine the build type +PRODUCTION_BUILD=0|1 +PR_BUILD=0|1 +STABLE_BUILD=0|1 + +// Determine if to utilize testing or stable Metaverse URLs +USE_STABLE_GLOBAL_SERVICES=1 +BUILD_GLOBAL_SERVICES=STABLE +``` + +#### Generate Files Create a build directory in the root of your checkout and then run the CMake build from there. This will keep the rest of the directory clean. - mkdir build - cd build - cmake .. +```bash +mkdir build +cd build +cmake .. +``` If CMake gives you the same error message repeatedly after the build fails, try removing `CMakeCache.txt`. -##### Generating a release/debug only vcpkg build +#### Generating a release/debug only vcpkg build -In order to generate a release or debug only vcpkg package, you could use the use the `VCPKG_BUILD_TYPE` define in your cmake generate command. Building a release only vcpkg can drastically decrease the total build time. +In order to generate a release or debug only vcpkg package, you could use the use the `VCPKG_BUILD_TYPE` define in your CMake generate command. Building a release only vcpkg can drastically decrease the total build time. For release only vcpkg: @@ -120,15 +157,17 @@ For debug only vcpkg: `cmake .. -DVCPKG_BUILD_TYPE=debug` -#### Variables +### Variables Any variables that need to be set for CMake to find dependencies can be set as ENV variables in your shell profile, or passed directly to CMake with a `-D` flag appended to the `cmake ..` command. For example, to pass the QT_CMAKE_PREFIX_PATH variable (if not using the vcpkg'ed version) during build file generation: - cmake .. -DQT_CMAKE_PREFIX_PATH=/usr/local/qt/5.12.3/lib/cmake +```bash +cmake .. -DQT_CMAKE_PREFIX_PATH=/usr/local/qt/5.12.3/lib/cmake +``` -#### Finding Dependencies +### Finding Dependencies The following applies for dependencies we do not grab via CMake ExternalProject (OpenSSL is an example), or for dependencies you have opted not to grab as a CMake ExternalProject (via -DUSE_LOCAL_$NAME=0). The list of dependencies we grab by default as external projects can be found in [the CMake External Project Dependencies section](#cmake-external-project-dependencies). @@ -140,9 +179,9 @@ In the examples below the variable $NAME would be replaced by the name of the de * $NAME_ROOT_DIR - set this variable in your ENV * HIFI_LIB_DIR - set this variable in your ENV to your Vircadia lib folder, should contain a folder '$name' -### Optional Components +## Optional Components -#### Build Options +### Build Options The following build options can be used when running CMake @@ -153,12 +192,12 @@ The following build options can be used when running CMake * CLIENT_ONLY // Will package only the Interface * SERVER_ONLY // Will package only the Server -#### Developer Build Options +### Developer Build Options * USE_GLES * DISABLE_UI -#### Devices +### Devices You can support external input/output devices such as Leap Motion, MIDI, and more by adding each individual SDK in the visible building path. Refer to the readme file available in each device folder in [interface/external/](interface/external) for the detailed explanation of the requirements to use the device. - + diff --git a/BUILD_ANDROID.md b/BUILD_ANDROID.md index c52f6a1d8f..0556e175d6 100644 --- a/BUILD_ANDROID.md +++ b/BUILD_ANDROID.md @@ -42,11 +42,13 @@ Follow the directions [here](https://developer.android.com/studio/publish/app-si Create a `gradle.properties` file in the `.gradle` folder (`$HOME/.gradle` on Unix, `Users//.gradle` on Windows). Edit the file to contain the following - HIFI_ANDROID_PRECOMPILED=/Android/hifi_externals - HIFI_ANDROID_KEYSTORE=/.jks - HIFI_ANDROID_KEYSTORE_PASSWORD= - HIFI_ANDROID_KEY_ALIAS= - HIFI_ANDROID_KEY_PASSWORD= +```properties +HIFI_ANDROID_PRECOMPILED=/Android/hifi_externals +HIFI_ANDROID_KEYSTORE=/.jks +HIFI_ANDROID_KEYSTORE_PASSWORD= +HIFI_ANDROID_KEY_ALIAS= +HIFI_ANDROID_KEY_PASSWORD= +``` Note, do not use $HOME for the path. It must be a fully qualified path name. Also, be sure to use forward slashes in your path. @@ -54,21 +56,26 @@ Note, do not use $HOME for the path. It must be a fully qualified path name. Als Add these lines to `gradle.properties` - SUPPRESS_QUEST_INTERFACE - SUPPRESS_QUEST_FRAME_PLAYER +```properties +SUPPRESS_QUEST_INTERFACE +SUPPRESS_QUEST_FRAME_PLAYER +``` #### If you are building for an Oculus Quest Add these lines to `gradle.properties` - SUPPRESS_INTERFACE - SUPPRESS_FRAME_PLAYER - +```properties +SUPPRESS_INTERFACE +SUPPRESS_FRAME_PLAYER +``` #### The Frame Player for both Android Phone and Oculus Quest is optional, so if you encounter problems with these during your build, you can skip them by adding these lines to `gradle.properties` - SUPPRESS_FRAME_PLAYER - SUPPRESS_QUEST_FRAME_PLAYER +```properties +SUPPRESS_FRAME_PLAYER +SUPPRESS_QUEST_FRAME_PLAYER +``` ### Clone the repository diff --git a/BUILD_LINUX.md b/BUILD_LINUX.md index 90782e90b4..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 @@ -168,39 +171,3 @@ If your goal is to set up a development environment, it is desirable to set the directory that vcpkg builds into with the `HIFI_VCPKG_BASE` environment variable. For example, you might set `HIFI_VCPKG_BASE` to `/home/$USER/vcpkg`. By default, vcpkg will build in the system `/tmp` directory. - -##### Ubuntu 18.04 only - -In Ubuntu 18.04 there is a problem related with NVidia driver library version. - -It can be worked around following these steps: - -1. Uninstall incompatible nvtt libraries: -`sudo apt-get remove libnvtt2 libnvtt-dev` - -1. Install libssl1.0-dev: -`sudo apt-get -y install libssl1.0-dev` - -1. Clone castano nvidia-texture-tools: -`git clone https://github.com/castano/nvidia-texture-tools` -`cd nvidia-texture-tools/` - -1. Make these changes in repo: -* In file **VERSION** set `2.2.1` -* In file **configure**: - * set `build="release"` - * set `-DNVTT_SHARED=1` - -1. Configure, build and install: -`./configure` -`make` -`sudo make install` - -1. Link compiled files: -`sudo ln -s /usr/local/lib/libnvcore.so /usr/lib/libnvcore.so` -`sudo ln -s /usr/local/lib/libnvimage.so /usr/lib/libnvimage.so` -`sudo ln -s /usr/local/lib/libnvmath.so /usr/lib/libnvmath.so` -`sudo ln -s /usr/local/lib/libnvtt.so /usr/lib/libnvtt.so` - -1. After running these steps you can run interface: -`interface/interface` diff --git a/BUILD_OSX.md b/BUILD_OSX.md index 525a7a5965..d9c7f0ee0f 100644 --- a/BUILD_OSX.md +++ b/BUILD_OSX.md @@ -1,55 +1,63 @@ # Build OSX -*Last Updated on August 26, 2020* +*Last Updated on January 16, 2021* Please read the [general build guide](BUILD.md) for information on dependencies required for all platforms. Only macOS specific instructions are found in this document. -### Homebrew +## Homebrew [Homebrew](https://brew.sh/) is an excellent package manager for macOS. It makes install of some Vircadia dependencies very simple. - brew install cmake openssl npm +```bash +brew install cmake openssl npm +``` -### Python 3 +Note: cmake versions > 3.18.x have known problems building Vircadia, so alternatively you can download cmake 3.18.4 (or earlier versions) from [Github](https://github.com/Kitware/CMake/releases). -Download an install Python 3.6.6 or higher from [here](https://www.python.org/downloads/). +## Python 3 + +Download an install Python 3.6.6 or higher from [here](https://www.python.org/downloads/). Execute the `Update Shell Profile.command` script that is provided with the installer. -### OSX SDK +## OSX SDK You will need version `10.12` of the OSX SDK for building, otherwise you may have crashing or other unintended issues due to the deprecation of OpenGL on OSX. You can get that SDK from [here](https://github.com/phracker/MacOSX-SDKs). You must copy it in to your Xcode SDK directory, e.g. - cp -rp ~/Downloads/MacOSX10.12.sdk /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/ +```bash +cp -rp ~/Downloads/MacOSX10.12.sdk /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/ +``` -### OpenSSL +## OpenSSL -Assuming you've installed OpenSSL using the homebrew instructions above, you'll need to set OPENSSL_ROOT_DIR so CMake can find your installations. +Assuming you've installed OpenSSL using the homebrew instructions above, you'll need to set OPENSSL_ROOT_DIR so CMake can find your installations. For OpenSSL installed via homebrew, set OPENSSL_ROOT_DIR via `export OPENSSL_ROOT_DIR=/usr/local/opt/openssl` or by appending `-DOPENSSL_ROOT_DIR=/usr/local/opt/openssl` to `cmake` -### Xcode +## Xcode You can ask CMake to generate Xcode project files instead of Unix Makefiles using the `-G Xcode` parameter after CMake. You will need to select the Xcode installation in the terminal first if you have not done so already. - - sudo xcode-select --switch /Applications/Xcode.app/Contents/Developer - - cmake ../ -DCMAKE_OSX_SYSROOT="/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.12.sdk" -DCMAKE_OSX_DEPLOYMENT_TARGET=10.12 -DOPENSSL_ROOT_DIR=/usr/local/opt/openssl -DOSX_SDK=10.12 .. -If `cmake` complains about Python 3 being missing, you may need to update your CMake binary with command `brew upgrade cmake`, or by downloading and running the latest CMake installer, depending on how you originally instaled CMake +```bash +sudo xcode-select --switch /Applications/Xcode.app/Contents/Developer + +cmake ../ -DCMAKE_OSX_SYSROOT="/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.12.sdk" -DCMAKE_OSX_DEPLOYMENT_TARGET=10.12 -DOPENSSL_ROOT_DIR=/usr/local/opt/openssl -DOSX_SDK=10.12 .. +``` + +If `cmake` complains about Python 3 being missing, you may need to update your CMake binary with command `brew upgrade cmake`, or by downloading and running the latest CMake installer, depending on how you originally installed CMake. After running CMake, you will have the make files or Xcode project file necessary to build all of the components. Open the hifi.xcodeproj file, choose ALL_BUILD from the Product > Scheme menu (or target drop down), and click Run. If the build completes successfully, you will have built targets for all components located in the `build/${target_name}/Debug` directories. -### make +## make If you build with make rather than Xcode, you can append `-j4` for assigning more threads. The number indicates the number of threads, e.g. 4. To package the installation, you can simply run `make package` afterwards. -### FAQ +## FAQ 1. **Problem:** Running the scheme `interface.app` from Xcode causes a crash for Interface related to `libgl` - 1. **Cause:** The target `gl` generates a binary called `libgl`. A macOS `libGL.framework` item gets loaded instead by Xcode. + 1. **Cause:** The target `gl` generates a binary called `libgl`. A macOS `libGL.framework` item gets loaded instead by Xcode. 1. **Solution:** In the Xcode target settings for `libgl`, set the version to 1.0.0 diff --git a/BUILD_WIN.md b/BUILD_WIN.md index 96f570981a..f7e5cebc46 100644 --- a/BUILD_WIN.md +++ b/BUILD_WIN.md @@ -1,40 +1,35 @@ # Build Windows -*Last Updated on May 17, 2020* +*Last Updated on 15 Apr 2021* -This is a stand-alone guide for creating your first Vircadia build for Windows 64-bit. +This is a stand-alone guide for creating your first Vircadia build for Windows 64-bit. -Note: We are now using Visual Studio 2017 or 2019 and Qt 5.12.3. -If you are upgrading from previous versions, do a clean uninstall of those versions before going through this guide. +Note: We are now using Visual Studio 2019 and Qt 5.15.2. +If you are upgrading from previous versions, do a clean uninstall of those versions before going through this guide. **Note: The prerequisites will require about 10 GB of space on your drive. You will also need a system with at least 8GB of main memory.** -### Step 1. Visual Studio & Python 3.x +## Step 1. Visual Studio & Python 3.x -If you don’t have Community or Professional edition of Visual Studio, download [Visual Studio Community 2019](https://visualstudio.microsoft.com/vs/). If you have Visual Studio 2017, you are not required to download Visual Studio 2019. +If you don't have Community or Professional edition of Visual Studio 2019, download [Visual Studio Community 2019](https://visualstudio.microsoft.com/vs/). If you have Visual Studio 2017, you need to download Visual Studio 2019. -When selecting components, check "Desktop development with C++". +When selecting components, check "Desktop development with C++". If you do not already have a Python 3.x development environment installed and want to install it with Visual Studio, check "Python Development". If you already have Visual Studio installed and need to add Python, open the "Add or remove programs" control panel and find the "Microsoft Visual Studio Installer". Select it and click "Modify". In the installer, select "Modify" again, then check "Python Development" and allow the installer to apply the changes. -On the right on the Summary toolbar, select the following components based on your Visual Studio version. +### Visual Studio 2019 -#### If you're installing Visual Studio 2017 - -* Windows 8.1 SDK and UCRT SDK -* VC++ 2015.3 v14.00 (v140) toolset for desktop - -#### If you're installing Visual Studio 2019 +On the right on the Summary toolbar, select the following components. * MSVC v142 - VS 2019 C++ X64/x86 build tools * MSVC v141 - VS 2017 C++ x64/x86 build tools * MSVC v140 - VS 2015 C++ build tools (v14.00) -### Step 1a. Alternate Python +## Step 1a. Alternate Python If you do not wish to use the Python installation bundled with Visual Studio, you can download the installer from [here](https://www.python.org/downloads/). Ensure that you get version 3.6.6 or higher. -### Step 2. Python Dependencies +## Step 2. Python Dependencies In an administrator command-line that can access Python's pip you will need to run the following command: @@ -42,52 +37,68 @@ In an administrator command-line that can access Python's pip you will need to r If you do not use an administrator command-line, you will get errors. -### Step 3. Installing CMake +## Step 3. Installing CMake -Download and install the latest version of CMake 3.15. +Download and install the latest version of CMake 3.15. * Note that earlier versions of CMake will work, but there is a specific bug related to the interaction of Visual Studio 2019 and CMake versions prior to 3.15 that will cause Visual Studio to rebuild far more than it needs to on every build Download the file named win64-x64 Installer from the [CMake Website](https://cmake.org/download/). You can access the installer on this [3.15 Version page](https://cmake.org/files/v3.15/). During installation, make sure to check "Add CMake to system PATH for all users" when prompted. -### Step 4. Node.JS and NPM +## Step 4. Node.JS and NPM Install version 10.15.0 LTS (or greater) of [Node.JS and NPM](). -### Step 5. Create VCPKG environment variable +## Step 5. (Optional) Install Qt + +If you would like to compile Qt instead of using the precompiled package provided during CMake, you can do so now. Install version 5.12.3 of [Qt](), as well as the following packages: +* Qt 5.15.2 +* MSVC 2019 64-bit +* Qt WebEngine +* Qt Script (Deprecated) + +For convenience, you may also want the "Qt Debug Information" and "Sources" packages. + +You'll need to create the environment variable that CMake uses to find your system's Qt install. + +To create this variable: +* Navigate to 'Edit the System Environment Variables' through the Start menu. +* Click on 'Environment Variables' +* Select 'New' +* Set "Variable name" to `QT_CMAKE_PREFIX_PATH` +* Set "Variable value" to `%QT_INSTALL_DIR%\5.15.2\msvc2019_64\lib\cmake`, where `%QT_INSTALL_DIR%` is the directory you specified for Qt's installation. The default is `C:\Qt`. + +## Step 6. Create VCPKG environment variable In the next step, you will use CMake to build Vircadia. By default, the CMake process builds dependency files in Windows' `%TEMP%` directory, which is periodically cleared by the operating system. To prevent you from having to re-build the dependencies in the event that Windows clears that directory, we recommend that you create a `HIFI_VCPKG_BASE` environment variable linked to a directory somewhere on your machine. That directory will contain all dependency files until you manually remove them. To create this variable: -* Naviagte to 'Edit the System Environment Variables' Through the start menu. +* Navigate to 'Edit the System Environment Variables' Through the Start menu. * Click on 'Environment Variables' -* Select 'New' +* Select 'New' * Set "Variable name" to `HIFI_VCPKG_BASE` * Set "Variable value" to any directory that you have control over. -Additionally, if you have Visual Studio 2019 installed and _only_ Visual Studio 2019 (i.e. you do not have Visual Studio 2017 installed) you must add an additional environment variable `HIFI_VCPKG_BOOTSTRAP` that will fix a bug in our `vcpkg` pre-build step. +Additionally, if you have Visual Studio 2019 installed and _only_ Visual Studio 2019 (i.e., you do not have Visual Studio 2017 installed) you must add an additional environment variable `HIFI_VCPKG_BOOTSTRAP` that will fix a bug in our `vcpkg` pre-build step. To create this variable: -* Naviagte to 'Edit the System Environment Variables' Through the start menu. +* Navigate to 'Edit the System Environment Variables' through the Start menu. * Click on 'Environment Variables' -* Select 'New' +* Select 'New' * Set "Variable name" to `HIFI_VCPKG_BOOTSTRAP` * Set "Variable value" to `1` -### Step 6. Running CMake to Generate Build Files +## Step 7. Running CMake to Generate Build Files -Run Command Prompt from Start and run the following commands: -`cd "%VIRCADIA_DIR%"` -`mkdir build` -`cd build` +Run Command Prompt from Start and run the following commands: +`cd "%VIRCADIA_DIR%"` +`mkdir build` +`cd build` -#### If you're using Visual Studio 2017, -Run `cmake .. -G "Visual Studio 15 Win64"`. - -#### If you're using Visual Studio 2019, +### Visual Studio 2019 Run `cmake .. -G "Visual Studio 16 2019" -A x64`. Where `%VIRCADIA_DIR%` is the directory for the Vircadia repository. -### Step 7. Making a Build +## Step 8. Making a Build Open `%VIRCADIA_DIR%\build\vircadia.sln` using Visual Studio. @@ -95,7 +106,7 @@ Change the Solution Configuration (menu ribbon under the menu bar, next to the g Run from the menu bar `Build > Build Solution`. -### Step 8. Testing Interface +## Step 9. Testing Interface Create another environment variable (see Step #3) * Set "Variable name": `_NO_DEBUG_HEAP` @@ -103,24 +114,24 @@ Create another environment variable (see Step #3) Restart Visual Studio again. -In Visual Studio, right+click "interface" under the Apps folder in Solution Explorer and select "Set as Startup Project". Run from the menu bar `Debug > Start Debugging`. +In Visual Studio, right-click "interface" under the Apps folder in Solution Explorer and select "Set as Startup Project". Run from the menu bar `Debug > Start Debugging`. Now, you should have a full build of Vircadia and be able to run the Interface using Visual Studio. Note: You can also run Interface by launching it from command line or File Explorer from `%VIRCADIA_DIR%\build\interface\Release\interface.exe` -## Troubleshooting +# Troubleshooting -For any problems after Step #7, first try this: -* Delete your locally cloned copy of the Vircadia repository -* Restart your computer -* Redownload the [repository](https://github.com/vircadia/vircadia) -* Restart directions from Step #7 +For any problems after Step #7, first try this: +* Delete your locally cloned copy of the Vircadia repository +* Restart your computer +* Redownload the [repository](https://github.com/vircadia/vircadia) +* Restart directions from Step #7 -#### CMake gives you the same error message repeatedly after the build fails +## CMake gives you the same error message repeatedly after the build fails Remove `CMakeCache.txt` found in the `%VIRCADIA_DIR%\build` directory. -#### CMake can't find OpenSSL +## CMake can't find OpenSSL Remove `CMakeCache.txt` found in the `%VIRCADIA_DIR%\build` directory. Verify that your HIFI_VCPKG_BASE environment variable is set and pointing to the correct location. Verify that the file `${HIFI_VCPKG_BASE}/installed/x64-windows/include/openssl/ssl.h` exists. diff --git a/CMakeLists.txt b/CMakeLists.txt index f111f482ae..facc1c999f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -41,8 +41,15 @@ endif() file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/_env/EXTERNAL_BUILD_ASSETS.txt" "${EXTERNAL_BUILD_ASSETS}") MESSAGE(STATUS "EXTERNAL_BUILD_ASSETS: ${EXTERNAL_BUILD_ASSETS}") +# read USE_GLES enviroment variable and sets it as GLES option +# TODO still gets overwritten by "use GLES on linux aarch64" set(GLES_OPTION "$ENV{USE_GLES}") +# use GLES on linux aarch64 +if (CMAKE_SYSTEM_NAME STREQUAL "Linux" AND CMAKE_SYSTEM_PROCESSOR STREQUAL "aarch64") + set(GLES_OPTION ON) +endif() + # Will affect VCPKG dependencies file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/_env/USE_GLES.txt" "${GLES_OPTION}") MESSAGE(STATUS "GLES_OPTION: ${GLES_OPTION}") @@ -70,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 "") @@ -79,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) @@ -87,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() @@ -94,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) @@ -125,6 +140,15 @@ else() set(MOBILE 0) endif() +set(SCREENSHARE 0) +if (WIN32) + set(SCREENSHARE 1) +endif() +if (APPLE AND NOT CLIENT_ONLY) + # Don't include Screenshare in OSX client-only builds. + set(SCREENSHARE 1) +endif() + # Use default time server if none defined in environment set_from_env(TIMESERVER_URL TIMESERVER_URL "http://timestamp.comodoca.com?td=sha256") @@ -187,7 +211,7 @@ else () set(PLATFORM_QT_COMPONENTS WebEngine Xml) endif () -if (USE_GLES AND (NOT ANDROID)) +if (USE_GLES AND (NOT ANDROID AND NOT UNIX)) set(DISABLE_QML_OPTION ON) endif() @@ -258,17 +282,26 @@ add_custom_target(cmake SOURCES ${CMAKE_SRC}) GroupSources("cmake") unset(CMAKE_SRC) -file(GLOB_RECURSE JS_SRC scripts/*.js unpublishedScripts/*.js) +file(GLOB_RECURSE JS_SRC scripts/*.* unpublishedScripts/*.*) add_custom_target(js SOURCES ${JS_SRC}) GroupSources("scripts") GroupSources("unpublishedScripts") unset(JS_SRC) +file(GLOB_RECURSE WEB_APP_SRC vircadia-web/*.*) +list(FILTER WEB_APP_SRC EXCLUDE REGEX "vircadia-web/(dist|node_modules|public)/*" ) +add_custom_target(vircadia-web SOURCES ${WEB_APP_SRC}) +GroupSources("vircadia-web") +unset(WEB_APP_SRC) + 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 ) @@ -316,8 +349,11 @@ endif() if (BUILD_CLIENT) add_subdirectory(interface) - add_subdirectory(screenshare) - set_target_properties(interface PROPERTIES FOLDER "Apps") + if (APPLE) + set_target_properties(Vircadia PROPERTIES FOLDER "Apps") + else() + set_target_properties(interface PROPERTIES FOLDER "Apps") + endif() option(USE_SIXENSE "Build Interface with sixense library/plugin" OFF) endif() @@ -327,6 +363,10 @@ if (BUILD_CLIENT OR BUILD_SERVER) add_subdirectory(server-console) endif() +if (SCREENSHARE) + add_subdirectory(screenshare) +endif() + # BUILD_TOOLS option will be handled inside the tools's CMakeLists.txt because 'scribe' tool is required for build anyway add_subdirectory(tools) diff --git a/INSTALLER.md b/INSTALLER.md index 84ee14eaaa..95ac376ea5 100644 --- a/INSTALLER.md +++ b/INSTALLER.md @@ -1,6 +1,6 @@ # Creating an Installer -*Last Updated on August 24, 2020* +*Last Updated on June 16, 2021* Follow the [build guide](BUILD.md) to figure out how to build Vircadia for your platform. @@ -9,13 +9,13 @@ During generation, CMake should produce an `install` target and a `package` targ The `install` target will copy the Vircadia targets and their dependencies to your `CMAKE_INSTALL_PREFIX`. This variable is set by the `project(hifi)` command in `CMakeLists.txt` to `C:/Program Files/hifi` and stored in `build/CMakeCache.txt` -### Packaging +## Packaging To produce an installer, run the `package` target. However you will want to follow the steps specific to your platform below. -#### Windows +### Windows -##### Prerequisites +#### Prerequisites To produce an executable installer on Windows, the following are required: @@ -63,11 +63,11 @@ To produce an executable installer on Windows, the following are required: 1. [Node.JS and NPM]() 1. Install version 10.15.0 LTS (or greater) -##### Code Signing (optional) +#### Code Signing (optional) For code signing to work, you will need to set the `HF_PFX_FILE` and `HF_PFX_PASSPHRASE` environment variables to be present during CMake runtime and globally as we proceed to package the installer. -##### Creating the Installer +#### Creating the Installer 1. Perform a clean cmake from a new terminal. 1. Open the `vircadia.sln` solution with elevated (administrator) permissions on Visual Studio and select the **Release** configuration. @@ -79,20 +79,195 @@ For code signing to work, you will need to set the `HF_PFX_FILE` and `HF_PFX_PAS 1. Build CMakeTargets->PACKAGE The installer is now available in `build\_CPack_Packages\win64\NSIS` -#### OS X -1. [npm]() - Install version 12.16.3 LTS - -1. Perform a clean CMake. -1. Perform a Release build of ALL_BUILD -1. Perform a Release build of `packaged-server-console` - This will add a folder to `build\server-console\` - - Sandbox-darwin-x64 -1. Perform a Release build of `package` - Installer is now available in `build/_CPack_Packages/Darwin/DragNDrop - -### FAQ +#### Create an MSIX Package + +1. Get the 'MSIX Packaging Tool' from the Windows Store. +2. Run the process to create a new MSIX package from an existing .exe or .msi installer. This process will allow you to install Vircadia with the usual installer, however it will monitor changes to the computer to replicate the functionality in the MSIX Package. Therefore, you will want to avoid doing anything else on your computer during this process. +3. Be sure to select no shortcuts and install only the Vircadia Interface. +4. When asked for "Entry" points, select only the Interface entry and not the uninstaller. This is because the MSIX package is uninstalled by Windows itself. If for some reason the uninstaller shows up anyway, you can edit the manifest to manually remove it from view even if the uninstaller is present in the package. This is necessary to uplaod to the Windows Store. +5. Once completed, you can sign the package with this application or with other tools such as 'MSIX Hero'. It must be signed with a local certificate to test, and with a proper certificate to distribute. +6. If uploading to the Windows Store, you will have to ensure all your manifest info including publisher information matches what is registered with your Microsoft Developer account for Windows. You will see these errors and the expected values when validating it. + +#### FAQ 1. **Problem:** Failure to open a file. ```File: failed opening file "\FOLDERSHARE\XYZSRelease\...\Credits.rtf" Error in script "C:\TFS\XYZProject\Releases\NullsoftInstaller\XYZWin7Installer.nsi" on line 77 -- aborting creation process``` 1. **Cause:** The complete path (current directory + relative path) has to be < 260 characters to any of the relevant files. 1. **Solution:** Move your build and packaging folder as high up in the drive as possible to prevent an overage. + +### MacOS + +1. Ensure you have all the prerequisites fulfilled from the [MacOS Build Guide](BUILD_OSX.md). +2. Perform a clean CMake in your build folder. e.g. + ```bash + BUILD_GLOBAL_SERVICES=STABLE USE_STABLE_GLOBAL_SERVICES=1 RELEASE_BUILD=PRODUCTION BUILD_NUMBER="Insert Build Identifier here e.g. short hash of your last Git commit" RELEASE_NAME="Insert Release Name Here" STABLE_BUILD=1 PRODUCTION_BUILD=1 RELEASE_NUMBER="Insert Release Version Here e.g. 1.1.0" RELEASE_TYPE=PRODUCTION cmake -DCMAKE_OSX_SYSROOT="/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.12.sdk" -DCLIENT_ONLY=1 -DCMAKE_OSX_DEPLOYMENT_TARGET=10.12 -DOPENSSL_ROOT_DIR=/usr/local/opt/openssl -DOSX_SDK=10.12 .. + ``` +3. Pick a method to build and package your release. + +#### Option A: Use Xcode GUI + +1. Perform a Release build of ALL_BUILD +2. Perform a Release build of `packaged-server-console` + This will add a folder to `build\server-console\` - + Sandbox-darwin-x64 +3. Perform a Release build of `package` + Installer is now available in `build/_CPack_Packages/Darwin/DragNDrop` + +#### Option B: Use Terminal + +1. Navigate to your build folder with your terminal. +2. `make -j4`, you can change the number to match the number of threads you would like to use. +3. `make package` to create the package. + +### Linux + +#### Server + +##### Ubuntu 18.04 | .deb + +1. Ensure you are using an Ubuntu 18.04 system. There is no required minimum to the amount of CPU cores needed, however it's recommended that you use as many as you have available in order to have an efficient experience. + ```text + Recommended CPU Cores: 16 + Minimum Disk Space: 40GB + ``` +3. Get and bootstrap Vircadia Builder. + ```bash + git clone https://github.com/vircadia/vircadia-builder.git + cd vircadia-builder + ``` +3. Run Vircadia Builder. + ```bash + ./vircadia-builder --build server + ``` +4. If Vircadia Builder needed to install dependencies and asks you to run it again then do so. Otherwise, skip to the next step. + ```bash + ./vircadia-builder --build server + ``` +5. Vircadia Builder will ask you to configure it to build the server. The values will be prefilled with defaults, the following steps will explain what they are and what you might want to put. *Advanced users: See [here](BUILD.md#possible-environment-variables) for possible environment variables and settings.* +6. This value is the Git repository of Vircadia. You can set this URL to your fork of the Vircadia repository if you need to. + ```text + Git repository: https://github.com/vircadia/vircadia/ + # OR, for example + Git repository: https://github.com/digisomni/vircadia/ + ``` +7. This value is the tag on the repository. If you would like to use a specific version of Vircadia, typically tags will be named like this: "v2021.1.0-rc" + ```text + Git tag: master + # OR, for example + Git tag: v2021.1.0-rc + ``` +8. This value is the release type. For example, the options are `production`, `pr`, or `dev`. If you are making a build for yourself and others to use then use `production`. + ```text + Release type: DEV + # OR, for example we recommend you use + Release type: PRODUCTION + ``` +9. This value is the release version. Release numbers should be in a format of `YEAR-MAJORVERSION-MINORVERSION` which might look like this: `2021.1.0`. + ```text + Release number: 2021.1.0 + ``` +10. This value is the build number. We typically use the hash of the most recent commit on that Git tag which might look like this: `fd6973b`. + ```text + Build number: fd6973b + ``` +11. This value is the directory that Vircadia will get installed to. You should leave this as the default value unless you are an advanced user. + ```text + Installation dir: /home/ubuntu/Vircadia + ``` +12. This value is the number of CPU cores that the Vircadia Builder will use to compile the Vircadia server. By default it will use all cores available on your build server. You should leave this as the default value it gives you for your build server. + ```text + CPU cores to use for Vircadia: 16 + ``` +13. This value is the number of CPU cores that the Vircadia Builder will use to compile Qt5 (a required component for Vircadia). By default it will use all cores available on your build server. You should leave this as the default value it gives you for your build server. + ```text + CPU cores to use for Qt5: 16 + ``` +14. It will ask you if you would like to proceed with the specified values. If you're happy with the configuration, type `yes`, otherwise enter `no` and press enter to start over. You can press `Ctrl` + `C` simultaneously on your keyboard to exit. +15. Vircadia Builder will now run, it may take a while. See this [table](https://github.com/vircadia/vircadia-builder#how-long-does-it-take) for estimated times. +16. Navigate to the `pkg-scripts` directory. + ```bash + cd ../Vircadia/source/pkg-scripts/ + ``` +17. Generate the .rpm package. Set `RPMVERSION` to the same version you entered for the `Release number` on Vircadia Builder. *Advanced users: the version cannot begin with a letter and cannot include underscores or dashes in it.* + ```bash + DEBVERSION="2021.1.0" DEBEMAIL="your-email@somewhere.com" DEBFULLNAME="Your Full Name" ./make-deb-server + ``` +18. If successful, the generated .deb package will be in the `pkg-scripts` folder. + +##### Amazon Linux 2 | .rpm + +1. Ensure you are using an Amazon Linux 2 system. You will need many CPU cores to complete this process within a reasonable time. As an alternative to AWS EC2, you may use a [virtual machine](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/amazon-linux-2-virtual-machine.html). Here are the recommended specs: + ```text + AWS EC2 Instance Type: C5a.4xlarge + Recommended CPU Cores: 16 + Minimum Disk Space: 40GB + ``` +2. Update the system and install dependencies. + ```bash + sudo yum update -y + sudo yum install git -y + sudo yum install rpm-build + ``` +3. Get and bootstrap Vircadia Builder. + ```bash + git clone https://github.com/vircadia/vircadia-builder.git + cd vircadia-builder + sudo ./install_amazon_linux_deps.sh + ``` +4. Run Vircadia Builder. + ```bash + ./vircadia-builder --build server + ``` +5. If Vircadia Builder needed to install dependencies and asks you to run it again then do so. Otherwise, skip to the next step. + ```bash + ./vircadia-builder --build server + ``` +6. Vircadia Builder will ask you to configure it to build the server. The values will be prefilled with defaults, the following steps will explain what they are and what you might want to put. *Advanced users: See [here](BUILD.md#possible-environment-variables) for possible environment variables and settings.* +7. This value is the Git repository of Vircadia. You can set this URL to your fork of the Vircadia repository if you need to. + ```text + Git repository: https://github.com/vircadia/vircadia/ + # OR, for example + Git repository: https://github.com/digisomni/vircadia/ + ``` +8. This value is the tag on the repository. If you would like to use a specific version of Vircadia, typically tags will be named like this: "v2021.1.0-rc". + ```text + Git tag: master + # OR, for example + Git tag: v2021.1.0-rc + ``` +9. This value is the release type. For example, the options are `production`, `pr`, or `dev`. If you are making a build for yourself and others to use then use `production`. + ```text + Release type: DEV + # OR, for example we recommend you use + Release type: PRODUCTION + ``` +10. This value is the release version. Release numbers typically should be in a format of `YEAR-MAJORVERSION-MINORVERSION` which might look like this: `2021.1.0`. + ```text + Release number: 2021.1.0 + ``` +11. This value is the build number. We typically use the hash of the most recent commit on that Git tag which might look like this: `fd6973b`. + ```text + Build number: fd6973b + ``` +12. This value is the directory that Vircadia will get installed to. You should leave this as the default value unless you are an advanced user. + ```text + Installation dir: /root/Vircadia + ``` +13. This value is the number of CPU cores that the Vircadia Builder will use to compile the Vircadia server. By default it will use all cores available on your build server given you have enough memory. You should leave this as the default value it gives you for your build server. + ```text + CPU cores to use for Vircadia: 16 + ``` +14. This value is the number of CPU cores that the Vircadia Builder will use to compile Qt5 (a required component for Vircadia). By default it will use all cores available on your build server given you have enough memory. You should leave this as the default value it gives you for your build server. + ```text + CPU cores to use for Qt5: 16 + ``` +15. It will ask you if you would like to proceed with the specified values. If you're happy with the configuration, type `yes`, otherwise enter `no` and press enter to start over. You can press `Ctrl` + `C` simultaneously on your keyboard to exit. +16. Vircadia Builder will now run, it may take a while. See this [table](https://github.com/vircadia/vircadia-builder#how-long-does-it-take) for estimated times. +17. Navigate to the `pkg-scripts` directory. + ```bash + cd ../Vircadia/source/pkg-scripts/ + ``` +18. Generate the .rpm package. Set `RPMVERSION` to the same version you entered for the `Release number` on Vircadia Builder. *Advanced users: the version cannot begin with a letter and cannot include underscores or dashes in it.* + ```bash + RPMVERSION="2021.1.0" ./make-rpm-server + ``` +19. If successful, the generated .rpm package will be in the `pkg-scripts` folder of the Vircadia source files. diff --git a/README.md b/README.md index d260c76d0d..58e3a501d4 100644 --- a/README.md +++ b/README.md @@ -1,37 +1,52 @@ -# Vircadia (Codename Athena) +

Vircadia - Codename Athena

+

Website | Discord | Download

+

GitHub contributors GitHub stars GitHub forks Apache 2.0 Discord

+

Build Status

+

Master CI Build

### What is this? -Vircadia™ is a 3D social software project seeking to incrementally bring about a truly free and open metaverse, in desktop and XR. +Vircadia™ is a 3D social software project seeking to incrementally bring about a truly free and open metaverse. -### [Website](https://vircadia.com/) | [Discord](https://discordapp.com/invite/Pvx2vke) | [Download](https://vircadia.com/download-vircadia/) +* Desktop and VR use +* Hundreds of users simultaneously +* Full-body avatars +* FBX, glTF, and OBJ support +* JavaScript scripting engine +* 16km³ world space in a server +* Fully self-hosted +* Apache 2.0 ### Releases [View Releases here](https://github.com/vircadia/vircadia/releases/) -### How to build the Interface +### How to deploy a Server + +- [For Windows and Linux](https://vircadia.com/deploy-a-server/) + +### Building + +#### How to build the Interface - [For Windows](https://github.com/vircadia/vircadia/blob/master/BUILD_WIN.md) - [For Mac](https://github.com/vircadia/vircadia/blob/master/BUILD_OSX.md) - [For Linux](https://github.com/vircadia/vircadia/blob/master/BUILD_LINUX.md) - [For Linux - Vircadia Builder](https://github.com/vircadia/vircadia-builder) -### How to deploy a Server - -- [For Windows and Linux](https://vircadia.com/deploy-a-server/) - -### How to build a Server +#### How to build a Server - [For Windows](https://github.com/vircadia/vircadia/blob/master/BUILD_WIN.md) - [For Linux](https://github.com/vircadia/vircadia/blob/master/BUILD_LINUX.md) - [For Linux - Vircadia Builder](https://github.com/vircadia/vircadia-builder) -### How to generate an Installer +#### How to generate an Installer -- [For Windows](https://github.com/vircadia/vircadia/blob/master/INSTALLER.md) -- [For Mac](https://github.com/vircadia/vircadia/blob/master/INSTALLER.md#os-x) -- [For Linux - AppImage - Vircadia Builder](https://github.com/vircadia/vircadia-builder/blob/master/README.md#building-appimages) +- [For Windows - Interface & Server](https://github.com/vircadia/vircadia/blob/master/INSTALLER.md) +- [For Mac - Interface](https://github.com/vircadia/vircadia/blob/master/INSTALLER.md#os-x) +- [For Linux - Server .deb - Vircadia Builder](INSTALLER.md#ubuntu-1804--deb) +- [For Linux - Server .rpm - Vircadia Builder](INSTALLER.md#amazon-linux-2--rpm) +- [For Linux - Interface AppImage - Vircadia Builder](https://github.com/vircadia/vircadia-builder/blob/master/README.md#building-appimages) ### Boot to Metaverse: [The Goal](https://vircadia.com/vision/) @@ -43,14 +58,16 @@ Vircadia consists of many projects and codebases with its unifying structure's g - The Interface (Codename Athena) - You are here! - The Server (Codename Athena) - You are also here! -- The UI Framework (Codename Nyx) - Codebase coming soon. -- [The Metaverse (Codename Iamus)](https://github.com/vircadia/Iamus/) -- [The Metaverse Dashboard (Codename Iamus)](https://github.com/vircadia/project-iamus-dashboard/) -- [The Launcher (Codename Pantheon)](https://github.com/vircadia/pantheon-launcher/) +- [The Web Interface (Codename Aether)](https://github.com/vircadia/vircadia-web/) +- [The Web SDK (Codename Ananke)](https://github.com/vircadia/vircadia-web-sdk/) +- [The Metaverse Server (Codename Iamus)](https://github.com/vircadia/Iamus/) +- [The Metaverse Server Dashboard (Codename Iamus)](https://github.com/vircadia/project-iamus-dashboard/) +- [The Launcher (Codename Pantheon)](https://github.com/vircadia/pantheon-launcher/) - Currently Windows only. #### Child Projects - [Vircadia Builder for Linux](https://github.com/vircadia/vircadia-builder/) -- [General Documentation](https://github.com/vircadia/vircadia-docs-sphinx/) +- [User Documentation](https://github.com/vircadia/vircadia-docs-sphinx/) +- [Developer Documentation](https://github.com/vircadia/vircadia-dev-docs/) ### Contribution diff --git a/android/apps/interface/CMakeLists.txt b/android/apps/interface/CMakeLists.txt index 500d555915..2f21d22b12 100644 --- a/android/apps/interface/CMakeLists.txt +++ b/android/apps/interface/CMakeLists.txt @@ -1,6 +1,6 @@ set(TARGET_NAME native-lib) setup_hifi_library() -link_hifi_libraries(shared task networking gl gpu qml image fbx hfm render-utils physics entities octree ${PLATFORM_GL_BACKEND}) +link_hifi_libraries(shared task networking gl gpu qml image model-serializers hfm render-utils physics entities octree ${PLATFORM_GL_BACKEND}) target_opengl() target_bullet() diff --git a/android/apps/questInterface/CMakeLists.txt b/android/apps/questInterface/CMakeLists.txt index 97ca46f6e5..72448cc9cf 100644 --- a/android/apps/questInterface/CMakeLists.txt +++ b/android/apps/questInterface/CMakeLists.txt @@ -2,7 +2,7 @@ set(TARGET_NAME questInterface) setup_hifi_library() link_hifi_libraries( shared task networking qml - image fbx hfm render-utils physics entities octree + image model-serializers hfm render-utils physics entities octree oculusMobile oculusMobilePlugin gl gpu ${PLATFORM_GL_BACKEND} ) diff --git a/assignment-client/CMakeLists.txt b/assignment-client/CMakeLists.txt index 31d8c9e5a8..abb94f95e3 100644 --- a/assignment-client/CMakeLists.txt +++ b/assignment-client/CMakeLists.txt @@ -8,10 +8,11 @@ if (APPLE) endif () setup_memory_debugger() +setup_thread_debugger() # link in the shared libraries link_hifi_libraries( - audio avatars octree gpu graphics shaders fbx hfm entities + audio avatars octree gpu graphics shaders model-serializers hfm entities networking animation recording shared script-engine embedded-webserver controllers physics plugins midi image material-networking model-networking ktx shaders diff --git a/assignment-client/src/AgentScriptingInterface.h b/assignment-client/src/AgentScriptingInterface.h index b1a8aaff96..cd5aa5ad65 100644 --- a/assignment-client/src/AgentScriptingInterface.h +++ b/assignment-client/src/AgentScriptingInterface.h @@ -17,7 +17,7 @@ #include "Agent.h" -/**jsdoc +/*@jsdoc * The Agent API enables an assignment client to emulate an avatar. Setting isAvatar = true connects * the assignment client to the avatar and audio mixers, and enables the {@link Avatar} API to be used. * @@ -62,7 +62,7 @@ public: QUuid getSessionUUID() const { return _agent->getSessionUUID(); } public slots: - /**jsdoc + /*@jsdoc * Sets whether the script should emulate an avatar. * @function Agent.setIsAvatar * @param {boolean} isAvatar - true if the script emulates an avatar, otherwise false. @@ -75,7 +75,7 @@ public slots: */ void setIsAvatar(bool isAvatar) const { _agent->setIsAvatar(isAvatar); } - /**jsdoc + /*@jsdoc * Checks whether the script is emulating an avatar. * @function Agent.isAvatar * @returns {boolean} true if the script is emulating an avatar, otherwise false. @@ -87,7 +87,7 @@ public slots: */ bool isAvatar() const { return _agent->isAvatar(); } - /**jsdoc + /*@jsdoc * Plays a sound from the position and with the orientation of the emulated avatar's head. No sound is played unless * isAvatar == true. * @function Agent.playAvatarSound diff --git a/assignment-client/src/avatars/AvatarMixerClientData.cpp b/assignment-client/src/avatars/AvatarMixerClientData.cpp index f86dc7f766..c83b95c464 100644 --- a/assignment-client/src/avatars/AvatarMixerClientData.cpp +++ b/assignment-client/src/avatars/AvatarMixerClientData.cpp @@ -269,7 +269,13 @@ void AvatarMixerClientData::processSetTraitsMessage(ReceivedMessage& message, // the avatar mixer uses the negative value of the sent version instanceVersionRef = -packetTraitVersion; } else { - _avatar->processTraitInstance(traitType, instanceID, message.read(traitSize)); + // Don't accept avatar entity data for distribution unless sender has rez permissions on the domain. + // The sender shouldn't be sending avatar entity data, however this provides a back-up. + auto trait = message.read(traitSize); + if (sendingNode.getCanRezAvatarEntities()) { + _avatar->processTraitInstance(traitType, instanceID, trait); + } + instanceVersionRef = packetTraitVersion; } @@ -290,6 +296,29 @@ void AvatarMixerClientData::processSetTraitsMessage(ReceivedMessage& message, } } +void AvatarMixerClientData::emulateDeleteEntitiesTraitsMessage(const QList& avatarEntityIDs) { + // Emulates processSetTraitsMessage() actions on behalf of an avatar whose canRezAvatarEntities permission has been removed. + // The source avatar should be removing its avatar entities. However, using this method provides a back-up. + + auto traitType = AvatarTraits::AvatarEntity; + for (const auto& entityID : avatarEntityIDs) { + auto& instanceVersionRef = _lastReceivedTraitVersions.getInstanceValueRef(traitType, entityID); + + _avatar->processDeletedTraitInstance(traitType, entityID); + // Mixer doesn't need deleted IDs. + _avatar->getAndClearRecentlyRemovedIDs(); + + // to track a deleted instance but keep version information + // the avatar mixer uses the negative value of the sent version + // Because there is no originating message from an avatar we enlarge the magnitude by 1. + // If a user subsequently has canRezAvatarEntities permission granted, they will have to relog in order for their + // avatar entities to be visible to others. + instanceVersionRef = -instanceVersionRef - 1; + } + + _lastReceivedTraitsChange = std::chrono::steady_clock::now(); +} + void AvatarMixerClientData::processBulkAvatarTraitsAckMessage(ReceivedMessage& message) { // Avatar Traits flow control marks each outgoing avatar traits packet with a // sequence number. The mixer caches the traits sent in the traits packet. diff --git a/assignment-client/src/avatars/AvatarMixerClientData.h b/assignment-client/src/avatars/AvatarMixerClientData.h index 98c8d7e15b..83a2ff384a 100644 --- a/assignment-client/src/avatars/AvatarMixerClientData.h +++ b/assignment-client/src/avatars/AvatarMixerClientData.h @@ -132,6 +132,7 @@ public: int processPackets(const SlaveSharedData& slaveSharedData); // returns number of packets processed void processSetTraitsMessage(ReceivedMessage& message, const SlaveSharedData& slaveSharedData, Node& sendingNode); + void emulateDeleteEntitiesTraitsMessage(const QList& avatarEntityIDs); void processBulkAvatarTraitsAckMessage(ReceivedMessage& message); void checkSkeletonURLAgainstWhitelist(const SlaveSharedData& slaveSharedData, Node& sendingNode, AvatarTraits::TraitVersion traitVersion); diff --git a/assignment-client/src/avatars/AvatarMixerSlave.cpp b/assignment-client/src/avatars/AvatarMixerSlave.cpp index 522f0bf163..9a3ef3d0b5 100644 --- a/assignment-client/src/avatars/AvatarMixerSlave.cpp +++ b/assignment-client/src/avatars/AvatarMixerSlave.cpp @@ -432,6 +432,17 @@ void AvatarMixerSlave::broadcastAvatarDataToAgent(const SharedNodePointer& node) } } + // The source avatar should be removing its avatar entities. However, provide a back-up. + if (sendAvatar) { + if (!sourceAvatarNode->getCanRezAvatarEntities()) { + auto sourceAvatarNodeData = reinterpret_cast(sourceAvatarNode->getLinkedData()); + auto avatarEntityIDs = sourceAvatarNodeData->getAvatar().getAvatarEntityIDs(); + if (avatarEntityIDs.count() > 0) { + sourceAvatarNodeData->emulateDeleteEntitiesTraitsMessage(avatarEntityIDs); + } + } + } + if (sendAvatar) { AvatarDataSequenceNumber lastSeqToReceiver = destinationNodeData->getLastBroadcastSequenceNumber(sourceAvatarNode->getLocalID()); AvatarDataSequenceNumber lastSeqFromSender = sourceAvatarNodeData->getLastReceivedSequenceNumber(); diff --git a/assignment-client/src/avatars/ScriptableAvatar.cpp b/assignment-client/src/avatars/ScriptableAvatar.cpp index cbf6ff4eaf..752eaf81d2 100644 --- a/assignment-client/src/avatars/ScriptableAvatar.cpp +++ b/assignment-client/src/avatars/ScriptableAvatar.cpp @@ -398,7 +398,7 @@ void ScriptableAvatar::setAvatarEntityData(const AvatarEntityMap& avatarEntityDa // clear deleted traits for (const auto& id : idsToClear) { - clearAvatarEntity(id); + clearAvatarEntityInternal(id); } } @@ -408,7 +408,7 @@ void ScriptableAvatar::updateAvatarEntity(const QUuid& entityID, const QByteArra std::map::iterator itr = _entities.find(entityID); if (itr != _entities.end()) { _entities.erase(itr); - clearAvatarEntity(entityID); + clearAvatarEntityInternal(entityID); } return; } diff --git a/assignment-client/src/avatars/ScriptableAvatar.h b/assignment-client/src/avatars/ScriptableAvatar.h index 1e6046ba7e..8e58108e8c 100644 --- a/assignment-client/src/avatars/ScriptableAvatar.h +++ b/assignment-client/src/avatars/ScriptableAvatar.h @@ -18,7 +18,7 @@ #include #include -/**jsdoc +/*@jsdoc * The Avatar API is used to manipulate scriptable avatars on the domain. This API is a subset of the * {@link MyAvatar} API. To enable this API, set {@link Agent|Agent.isAvatar} to true. * @@ -110,7 +110,7 @@ public: ScriptableAvatar(); - /**jsdoc + /*@jsdoc * Starts playing an animation on the avatar. * @function Avatar.startAnimation * @param {string} url - The animation file's URL. Animation files need to be in glTF or FBX format but only need to @@ -130,13 +130,13 @@ public: bool hold = false, float firstFrame = 0.0f, float lastFrame = FLT_MAX, const QStringList& maskedJoints = QStringList()); - /**jsdoc + /*@jsdoc * Stops playing the current animation. * @function Avatar.stopAnimation */ Q_INVOKABLE void stopAnimation(); - /**jsdoc + /*@jsdoc * Gets the details of the current avatar animation that is being or was recently played. * @function Avatar.getAnimationDetails * @returns {Avatar.AnimationDetails} The current or recent avatar animation. @@ -146,30 +146,30 @@ public: */ Q_INVOKABLE AnimationDetails getAnimationDetails(); - /**jsdoc + /*@jsdoc * @comment Uses the base class's JSDoc. */ Q_INVOKABLE virtual QStringList getJointNames() const override; - /**jsdoc + /*@jsdoc * @comment Uses the base class's JSDoc. */ /// Returns the index of the joint with the specified name, or -1 if not found/unknown. Q_INVOKABLE virtual int getJointIndex(const QString& name) const override; - /**jsdoc + /*@jsdoc * @comment Uses the base class's JSDoc. */ Q_INVOKABLE virtual void setSkeletonModelURL(const QUrl& skeletonModelURL) override; - /**jsdoc + /*@jsdoc * @comment Uses the base class's JSDoc. */ int sendAvatarDataPacket(bool sendAll = false) override; virtual QByteArray toByteArrayStateful(AvatarDataDetail dataDetail, bool dropFaceTracking = false) override; - /**jsdoc + /*@jsdoc * Gets details of all avatar entities. *

Warning: Potentially an expensive call. Do not use if possible.

* @function Avatar.getAvatarEntityData @@ -184,7 +184,7 @@ public: AvatarEntityMap getAvatarEntityDataInternal(bool allProperties) const; - /**jsdoc + /*@jsdoc * Sets all avatar entities from an object. *

Warning: Potentially an expensive call. Do not use if possible.

* @function Avatar.setAvatarEntityData @@ -192,20 +192,20 @@ public: */ Q_INVOKABLE void setAvatarEntityData(const AvatarEntityMap& avatarEntityData) override; - /**jsdoc + /*@jsdoc * @comment Uses the base class's JSDoc. */ Q_INVOKABLE void updateAvatarEntity(const QUuid& entityID, const QByteArray& entityData) override; public slots: - /**jsdoc + /*@jsdoc * @function Avatar.update * @param {number} deltaTime - Delta time. * @deprecated This function is deprecated and will be removed. */ void update(float deltatime); - /**jsdoc + /*@jsdoc * @function Avatar.setJointMappingsFromNetworkReply * @deprecated This function is deprecated and will be removed. */ diff --git a/assignment-client/src/entities/EntityTreeHeadlessViewer.h b/assignment-client/src/entities/EntityTreeHeadlessViewer.h index a8503510e0..a0f9930f06 100644 --- a/assignment-client/src/entities/EntityTreeHeadlessViewer.h +++ b/assignment-client/src/entities/EntityTreeHeadlessViewer.h @@ -23,7 +23,7 @@ class EntitySimulation; -/**jsdoc +/*@jsdoc * The EntityViewer API provides a headless viewer for assignment client scripts, so that they can "see" entities * in order for them to be available in the {@link Entities} API. * diff --git a/assignment-client/src/messages/MessagesMixer.cpp b/assignment-client/src/messages/MessagesMixer.cpp index bcf4881fcf..017d3a80b7 100644 --- a/assignment-client/src/messages/MessagesMixer.cpp +++ b/assignment-client/src/messages/MessagesMixer.cpp @@ -20,6 +20,7 @@ #include const QString MESSAGES_MIXER_LOGGING_NAME = "messages-mixer"; +const int MESSAGES_MIXER_RATE_LIMITER_INTERVAL = 1000; // 1 second MessagesMixer::MessagesMixer(ReceivedMessage& message) : ThreadedAssignment(message) { @@ -44,10 +45,20 @@ void MessagesMixer::handleMessages(QSharedPointer receivedMessa QByteArray data; QUuid senderID; bool isText; + auto senderUUID = senderNode->getUUID(); MessagesClient::decodeMessagesPacket(receivedMessage, channel, isText, message, data, senderID); auto nodeList = DependencyManager::get(); + auto itr = _allSubscribers.find(senderUUID); + if (itr == _allSubscribers.end()) { + _allSubscribers[senderUUID] = 1; + } else if (*itr >= _maxMessagesPerSecond) { + return; + } else { + *itr += 1; + } + nodeList->eachMatchingNode( [&](const SharedNodePointer& node)->bool { return node->getActiveSocket() && _channelSubscribers[channel].contains(node->getUUID()); @@ -60,14 +71,18 @@ void MessagesMixer::handleMessages(QSharedPointer receivedMessa } void MessagesMixer::handleMessagesSubscribe(QSharedPointer message, SharedNodePointer senderNode) { + auto senderUUID = senderNode->getUUID(); QString channel = QString::fromUtf8(message->getMessage()); - _channelSubscribers[channel] << senderNode->getUUID(); + + _channelSubscribers[channel] << senderUUID; } void MessagesMixer::handleMessagesUnsubscribe(QSharedPointer message, SharedNodePointer senderNode) { + auto senderUUID = senderNode->getUUID(); QString channel = QString::fromUtf8(message->getMessage()); + if (_channelSubscribers.contains(channel)) { - _channelSubscribers[channel].remove(senderNode->getUUID()); + _channelSubscribers[channel].remove(senderUUID); } } @@ -88,7 +103,48 @@ void MessagesMixer::sendStatsPacket() { } void MessagesMixer::run() { - ThreadedAssignment::commonInit(MESSAGES_MIXER_LOGGING_NAME, NodeType::MessagesMixer); auto nodeList = DependencyManager::get(); nodeList->addSetOfNodeTypesToNodeInterestSet({ NodeType::Agent, NodeType::EntityScriptServer }); + DomainHandler& domainHandler = nodeList->getDomainHandler(); + connect(&domainHandler, &DomainHandler::settingsReceived, this, &MessagesMixer::domainSettingsRequestComplete); + + ThreadedAssignment::commonInit(MESSAGES_MIXER_LOGGING_NAME, NodeType::MessagesMixer); + + startMaxMessagesProcessor(); +} + +void MessagesMixer::domainSettingsRequestComplete() { + auto nodeList = DependencyManager::get(); + + // parse the settings to pull out the values we need + parseDomainServerSettings(nodeList->getDomainHandler().getSettingsObject()); +} + +void MessagesMixer::parseDomainServerSettings(const QJsonObject& domainSettings) { + const QString MESSAGES_MIXER_SETTINGS_KEY = "messages_mixer"; + QJsonObject messagesMixerGroupObject = domainSettings[MESSAGES_MIXER_SETTINGS_KEY].toObject(); + + const QString NODE_MESSAGES_PER_SECOND_KEY = "max_node_messages_per_second"; + QJsonValue maxMessagesPerSecondValue = messagesMixerGroupObject.value(NODE_MESSAGES_PER_SECOND_KEY); + _maxMessagesPerSecond = maxMessagesPerSecondValue.toInt(DEFAULT_NODE_MESSAGES_PER_SECOND); +} + +void MessagesMixer::processMaxMessagesContainer() { + _allSubscribers.clear(); +} + +void MessagesMixer::startMaxMessagesProcessor() { + if (_maxMessagesTimer) { + stopMaxMessagesProcessor(); + } + + _maxMessagesTimer = new QTimer(); + connect(_maxMessagesTimer, &QTimer::timeout, this, &MessagesMixer::processMaxMessagesContainer); + _maxMessagesTimer->start(MESSAGES_MIXER_RATE_LIMITER_INTERVAL); // Clear the container every second. +} + +void MessagesMixer::stopMaxMessagesProcessor() { + _maxMessagesTimer->stop(); + _maxMessagesTimer->deleteLater(); + _maxMessagesTimer = nullptr; } diff --git a/assignment-client/src/messages/MessagesMixer.h b/assignment-client/src/messages/MessagesMixer.h index 800d42199b..9a43aca347 100644 --- a/assignment-client/src/messages/MessagesMixer.h +++ b/assignment-client/src/messages/MessagesMixer.h @@ -32,9 +32,21 @@ private slots: void handleMessages(QSharedPointer message, SharedNodePointer senderNode); void handleMessagesSubscribe(QSharedPointer message, SharedNodePointer senderNode); void handleMessagesUnsubscribe(QSharedPointer message, SharedNodePointer senderNode); + void parseDomainServerSettings(const QJsonObject& domainSettings); + void domainSettingsRequestComplete(); + + void startMaxMessagesProcessor(); + void stopMaxMessagesProcessor(); + void processMaxMessagesContainer(); private: - QHash> _channelSubscribers; + QHash> _channelSubscribers; + QHash _allSubscribers; + + const int DEFAULT_NODE_MESSAGES_PER_SECOND = 1000; + int _maxMessagesPerSecond { 0 }; + + QTimer* _maxMessagesTimer { nullptr }; }; #endif // hifi_MessagesMixer_h diff --git a/assignment-client/src/octree/OctreeHeadlessViewer.h b/assignment-client/src/octree/OctreeHeadlessViewer.h index 2debf2cb84..17173718e8 100644 --- a/assignment-client/src/octree/OctreeHeadlessViewer.h +++ b/assignment-client/src/octree/OctreeHeadlessViewer.h @@ -27,7 +27,7 @@ public: public slots: - /**jsdoc + /*@jsdoc * Updates the entities currently in view. * @function EntityViewer.queryOctree */ @@ -36,28 +36,28 @@ public slots: // setters for camera attributes - /**jsdoc + /*@jsdoc * Sets the position of the view frustum. * @function EntityViewer.setPosition * @param {Vec3} position - The position of the view frustum. */ void setPosition(const glm::vec3& position) { _hasViewFrustum = true; _viewFrustum.setPosition(position); } - /**jsdoc + /*@jsdoc * Sets the orientation of the view frustum. * @function EntityViewer.setOrientation * @param {Quat} orientation - The orientation of the view frustum. */ void setOrientation(const glm::quat& orientation) { _hasViewFrustum = true; _viewFrustum.setOrientation(orientation); } - /**jsdoc + /*@jsdoc * Sets the radius of the center "keyhole" in the view frustum. * @function EntityViewer.setCenterRadius * @param {number} radius - The radius of the center "keyhole" in the view frustum. */ void setCenterRadius(float radius) { _hasViewFrustum = true; _viewFrustum.setCenterRadius(radius); } - /**jsdoc + /*@jsdoc * Sets the radius of the center "keyhole" in the view frustum. * @function EntityViewer.setKeyholeRadius * @param {number} radius - The radius of the center "keyhole" in the view frustum. @@ -69,21 +69,21 @@ public slots: // setters for LOD and PPS - /**jsdoc + /*@jsdoc * @function EntityViewer.setVoxelSizeScale * @param {number} sizeScale - The voxel size scale. * @deprecated This function is deprecated and will be removed. */ void setVoxelSizeScale(float sizeScale) { _octreeQuery.setOctreeSizeScale(sizeScale) ; } - /**jsdoc + /*@jsdoc * @function EntityViewer.setBoundaryLevelAdjust * @param {number} boundaryLevelAdjust - The boundary level adjust factor. * @deprecated This function is deprecated and will be removed. */ void setBoundaryLevelAdjust(int boundaryLevelAdjust) { _octreeQuery.setBoundaryLevelAdjust(boundaryLevelAdjust); } - /**jsdoc + /*@jsdoc * Sets the maximum number of entity packets to receive from the domain server per second. * @function EntityViewer.setMaxPacketsPerSecond * @param {number} maxPacketsPerSecond - The maximum number of entity packets to receive per second. @@ -92,14 +92,14 @@ public slots: // getters for camera attributes - /**jsdoc + /*@jsdoc * Gets the position of the view frustum. * @function EntityViewer.getPosition * @returns {Vec3} The position of the view frustum. */ const glm::vec3& getPosition() const { return _viewFrustum.getPosition(); } - /**jsdoc + /*@jsdoc * Gets the orientation of the view frustum. * @function EntityViewer.getOrientation * @returns {Quat} The orientation of the view frustum. @@ -109,21 +109,21 @@ public slots: // getters for LOD and PPS - /**jsdoc + /*@jsdoc * @function EntityViewer.getVoxelSizeScale * @returns {number} The voxel size scale. * @deprecated This function is deprecated and will be removed. */ float getVoxelSizeScale() const { return _octreeQuery.getOctreeSizeScale(); } - /**jsdoc + /*@jsdoc * @function EntityViewer.getBoundaryLevelAdjust * @returns {number} The boundary level adjust factor. * @deprecated This function is deprecated and will be removed. */ int getBoundaryLevelAdjust() const { return _octreeQuery.getBoundaryLevelAdjust(); } - /**jsdoc + /*@jsdoc * Gets the maximum number of entity packets to receive from the domain server per second. * @function EntityViewer.getMaxPacketsPerSecond * @returns {number} The maximum number of entity packets to receive per second. @@ -131,7 +131,7 @@ public slots: int getMaxPacketsPerSecond() const { return _octreeQuery.getMaxQueryPacketsPerSecond(); } - /**jsdoc + /*@jsdoc * Gets the number of nodes in the octree. * @function EntityViewer.getOctreeElementsCount * @returns {number} The number of nodes in the octree. diff --git a/cmake/externals/steamworks/CMakeLists.txt b/cmake/externals/steamworks/CMakeLists.txt index 1ec72d7d28..f418b82ab5 100644 --- a/cmake/externals/steamworks/CMakeLists.txt +++ b/cmake/externals/steamworks/CMakeLists.txt @@ -54,7 +54,7 @@ elseif(APPLE) LOG 1 ) -elseif(NOT ANDROID) +elseif(NOT ANDROID AND NOT CMAKE_SYSTEM_PROCESSOR STREQUAL "aarch64") # FIXME need to account for different architectures set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${SOURCE_DIR}/redistributable_bin/linux64/libsteam_api.so CACHE STRING INTERNAL) diff --git a/cmake/macros/GenerateInstallers.cmake b/cmake/macros/GenerateInstallers.cmake index 89eeecfbbb..15690f6012 100644 --- a/cmake/macros/GenerateInstallers.cmake +++ b/cmake/macros/GenerateInstallers.cmake @@ -21,9 +21,9 @@ macro(GENERATE_INSTALLERS) set(INSTALLER_TYPE "client_only") string(REGEX REPLACE "Vircadia" "Vircadia Interface" _DISPLAY_NAME ${BUILD_ORGANIZATION}) elseif (SERVER_ONLY) - set(_PACKAGE_NAME_EXTRA "-Sandbox") + set(_PACKAGE_NAME_EXTRA "-Server") set(INSTALLER_TYPE "server_only") - string(REGEX REPLACE "Vircadia" "Vircadia Sandbox" _DISPLAY_NAME ${BUILD_ORGANIZATION}) + string(REGEX REPLACE "Vircadia" "Vircadia Server" _DISPLAY_NAME ${BUILD_ORGANIZATION}) else () set(_DISPLAY_NAME ${BUILD_ORGANIZATION}) set(INSTALLER_TYPE "full") @@ -96,19 +96,23 @@ macro(GENERATE_INSTALLERS) set(CPACK_PACKAGING_INSTALL_PREFIX /) set(CPACK_OSX_PACKAGE_VERSION ${CMAKE_OSX_DEPLOYMENT_TARGET}) - # make sure a High Fidelity directory exists, in case this hits prior to other installs - install(CODE "file(MAKE_DIRECTORY \"\${CMAKE_INSTALL_PREFIX}/${DMG_SUBFOLDER_NAME}\")") + # Create folder if used. + if (NOT INTERFACE_INSTALL_DIR STREQUAL ".") + # make sure a High Fidelity directory exists, in case this hits prior to other installs + install(CODE "file(MAKE_DIRECTORY \"\${CMAKE_INSTALL_PREFIX}/${DMG_SUBFOLDER_NAME}\")") - # add the resource file to the Icon file inside the folder - install(CODE - "execute_process(COMMAND Rez -append ${DMG_SUBFOLDER_ICON} -o \${CMAKE_INSTALL_PREFIX}/${ESCAPED_DMG_SUBFOLDER_NAME}/Icon\\r)" - ) + # add the resource file to the Icon file inside the folder + install(CODE + "execute_process(COMMAND Rez -append ${DMG_SUBFOLDER_ICON} -o \${CMAKE_INSTALL_PREFIX}/${ESCAPED_DMG_SUBFOLDER_NAME}/Icon\\r)" + ) - # modify the folder to use that custom icon - install(CODE "execute_process(COMMAND SetFile -a C \${CMAKE_INSTALL_PREFIX}/${ESCAPED_DMG_SUBFOLDER_NAME})") + # modify the folder to use that custom icon + install(CODE "execute_process(COMMAND SetFile -a C \${CMAKE_INSTALL_PREFIX}/${ESCAPED_DMG_SUBFOLDER_NAME})") + + # hide the special Icon? file + install(CODE "execute_process(COMMAND SetFile -a V \${CMAKE_INSTALL_PREFIX}/${ESCAPED_DMG_SUBFOLDER_NAME}/Icon\\r)") + endif () - # hide the special Icon? file - install(CODE "execute_process(COMMAND SetFile -a V \${CMAKE_INSTALL_PREFIX}/${ESCAPED_DMG_SUBFOLDER_NAME}/Icon\\r)") endif () # configure a cpack properties file for custom variables in template @@ -123,7 +127,7 @@ macro(GENERATE_INSTALLERS) endif () if (BUILD_SERVER) - cpack_add_component(${SERVER_COMPONENT} DISPLAY_NAME "Vircadia Sandbox") + cpack_add_component(${SERVER_COMPONENT} DISPLAY_NAME "Vircadia Server") endif () include(CPack) diff --git a/cmake/macros/LinkHifiLibraries.cmake b/cmake/macros/LinkHifiLibraries.cmake index 6a430f5b13..390bdf2326 100644 --- a/cmake/macros/LinkHifiLibraries.cmake +++ b/cmake/macros/LinkHifiLibraries.cmake @@ -26,5 +26,6 @@ function(LINK_HIFI_LIBRARIES) endforeach() setup_memory_debugger() + setup_thread_debugger() endfunction() diff --git a/cmake/macros/ManuallyInstallOpenSSLForQt.cmake b/cmake/macros/ManuallyInstallOpenSSLForQt.cmake index eae0eaca58..baee173572 100644 --- a/cmake/macros/ManuallyInstallOpenSSLForQt.cmake +++ b/cmake/macros/ManuallyInstallOpenSSLForQt.cmake @@ -3,6 +3,7 @@ # # Created by Stephen Birarda on 1/15/16. # Copyright 2014 High Fidelity, Inc. +# Copyright 2020 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 @@ -19,13 +20,13 @@ macro(manually_install_openssl_for_qt) find_package(OpenSSL REQUIRED) install( - FILES "${VCPKG_INSTALL_ROOT}/bin/ssleay32.dll" + FILES "${VCPKG_INSTALL_ROOT}/bin/libcrypto-1_1-x64.dll" DESTINATION ${TARGET_INSTALL_DIR} COMPONENT ${TARGET_INSTALL_COMPONENT} ) install( - FILES "${VCPKG_INSTALL_ROOT}/bin/libeay32.dll" + FILES "${VCPKG_INSTALL_ROOT}/bin/libssl-1_1-x64.dll" DESTINATION ${TARGET_INSTALL_DIR} COMPONENT ${TARGET_INSTALL_COMPONENT} ) diff --git a/cmake/macros/MemoryDebugger.cmake b/cmake/macros/MemoryDebugger.cmake index 09716715f0..244d47b02e 100644 --- a/cmake/macros/MemoryDebugger.cmake +++ b/cmake/macros/MemoryDebugger.cmake @@ -8,23 +8,43 @@ # macro(SETUP_MEMORY_DEBUGGER) -if (DEFINED ENV{HIFI_MEMORY_DEBUGGING}) - SET( HIFI_MEMORY_DEBUGGING true ) +if ("$ENV{VIRCADIA_MEMORY_DEBUGGING}") + if (VIRCADIA_THREAD_DEBUGGING) + message(FATAL_ERROR "Thread debugging and memory debugging can't be enabled at the same time." ) + endif() + + SET( VIRCADIA_MEMORY_DEBUGGING true ) endif () -if (HIFI_MEMORY_DEBUGGING) - if (UNIX) - if (CMAKE_CXX_COMPILER_ID MATCHES "Clang") - # for clang on Linux - SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-omit-frame-pointer -shared-libasan -fsanitize=undefined -fsanitize=address -fsanitize-recover=address") - SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -shared-libasan -fsanitize=undefined -fsanitize=address -fsanitize-recover=address") - SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -shared-libasan -fsanitize=undefined -fsanitize=address -fsanitize-recover=address") - else () - # for gcc on Linux - SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=undefined -fsanitize=address -U_FORTIFY_SOURCE -fno-stack-protector -fno-omit-frame-pointer") - SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libasan -static-libstdc++ -fsanitize=undefined -fsanitize=address") - SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libasan -static-libstdc++ -fsanitize=undefined -fsanitize=address") +if (VIRCADIA_MEMORY_DEBUGGING) + if (CMAKE_CXX_COMPILER_ID MATCHES "Clang") + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-omit-frame-pointer -fsanitize=undefined -fsanitize=address -fsanitize-recover=address") + SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=undefined -fsanitize=address -fsanitize-recover=address") + SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=undefined -fsanitize=address -fsanitize-recover=address") + if (UNIX) + # Only supported on Linux and OSX + # https://clang.llvm.org/docs/LeakSanitizer.html + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=leak") + SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=leak") + SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=leak") endif() - endif (UNIX) + elseif(CMAKE_CXX_COMPILER_ID MATCHES "GNU") + # for gcc + # For some reason, using -fstack-protector results in this error: + # usr/bin/ld: ../../libraries/audio/libaudio.so: undefined reference to `FIR_1x4_AVX512(float*, float*, float*, float*, float*, float (*) [64], int)' + # The '-DSTACK_PROTECTOR' argument below disables the usage of this function in the code. This should be fine as it only works on the latest Intel hardware, + # and is an optimization that should make no functional difference. + + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=undefined -fsanitize=address -fsanitize=leak -U_FORTIFY_SOURCE -DSTACK_PROTECTOR -fstack-protector-strong -fno-omit-frame-pointer") + SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=undefined -fsanitize=address -fsanitize=leak ") + SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=undefined -fsanitize=address -fsanitize=leak") + elseif(CMAKE_CXX_COMPILER_ID MATCHES "MSVC") + # https://docs.microsoft.com/en-us/cpp/sanitizers/asan?view=msvc-160 + # Supported experimentally starting from VS2019 v16.4, and officially from v16.9. + # UBSan and leak detection don't seem to be implemented yet. + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /fsanitize=address /Zi") + else() + message(FATAL_ERROR "Memory debugging is not supported on this compiler.") + endif() endif () endmacro(SETUP_MEMORY_DEBUGGER) diff --git a/cmake/macros/SetPackagingParameters.cmake b/cmake/macros/SetPackagingParameters.cmake index 9311594938..abe93275f6 100644 --- a/cmake/macros/SetPackagingParameters.cmake +++ b/cmake/macros/SetPackagingParameters.cmake @@ -25,7 +25,10 @@ macro(SET_PACKAGING_PARAMETERS) set_from_env(RELEASE_NUMBER RELEASE_NUMBER "") set_from_env(RELEASE_NAME RELEASE_NAME "") set_from_env(STABLE_BUILD STABLE_BUILD 0) - set_from_env(INITIAL_STARTUP_LOCATION INITIAL_STARTUP_LOCATION "") + + set_from_env(PRELOADED_STARTUP_LOCATION PRELOADED_STARTUP_LOCATION "") + set_from_env(PRELOADED_SCRIPT_WHITELIST PRELOADED_SCRIPT_WHITELIST "") + set_from_env(BYPASS_SIGNING BYPASS_SIGNING 0) message(STATUS "The RELEASE_TYPE variable is: ${RELEASE_TYPE}") @@ -35,6 +38,12 @@ macro(SET_PACKAGING_PARAMETERS) set(CLIENT_COMPONENT client) set(SERVER_COMPONENT server) + if (APPLE) + set(INTERFACE_BUNDLE_NAME "Vircadia") + else() + set(INTERFACE_BUNDLE_NAME "interface") + endif() + if (RELEASE_TYPE STREQUAL "PRODUCTION") set(DEPLOY_PACKAGE TRUE) set(PRODUCTION_BUILD 1) @@ -42,7 +51,6 @@ macro(SET_PACKAGING_PARAMETERS) set(BUILD_ORGANIZATION "Vircadia") set(HIGH_FIDELITY_PROTOCOL "hifi") set(HIGH_FIDELITY_APP_PROTOCOL "hifiapp") - set(INTERFACE_BUNDLE_NAME "interface") set(INTERFACE_ICON_PREFIX "interface") # add definition for this release type @@ -65,7 +73,6 @@ macro(SET_PACKAGING_PARAMETERS) set(PR_BUILD 1) set(BUILD_VERSION "PR${RELEASE_NUMBER}") set(BUILD_ORGANIZATION "Vircadia - PR${RELEASE_NUMBER}") - set(INTERFACE_BUNDLE_NAME "interface") set(INTERFACE_ICON_PREFIX "interface-beta") # add definition for this release type @@ -74,7 +81,6 @@ macro(SET_PACKAGING_PARAMETERS) set(DEV_BUILD 1) set(BUILD_VERSION "dev") set(BUILD_ORGANIZATION "Vircadia - ${BUILD_VERSION}") - set(INTERFACE_BUNDLE_NAME "interface") set(INTERFACE_ICON_PREFIX "interface-beta") # add definition for this release type @@ -82,7 +88,11 @@ macro(SET_PACKAGING_PARAMETERS) endif () set(NITPICK_BUNDLE_NAME "nitpick") - set(NITPICK_ICON_PREFIX "nitpick") + if (RELEASE_TYPE STREQUAL "PRODUCTION") + set(NITPICK_ICON_PREFIX "nitpick") + else () + set(NITPICK_ICON_PREFIX "nitpick-beta") + endif () string(TIMESTAMP BUILD_TIME "%d/%m/%Y") @@ -122,10 +132,10 @@ macro(SET_PACKAGING_PARAMETERS) set(DMG_SUBFOLDER_ICON "${HF_CMAKE_DIR}/installer/install-folder.rsrc") - set(CONSOLE_INSTALL_DIR ${DMG_SUBFOLDER_NAME}) - set(INTERFACE_INSTALL_DIR ${DMG_SUBFOLDER_NAME}) - set(SCREENSHARE_INSTALL_DIR ${DMG_SUBFOLDER_NAME}) - set(NITPICK_INSTALL_DIR ${DMG_SUBFOLDER_NAME}) + set(CONSOLE_INSTALL_DIR ".") + set(INTERFACE_INSTALL_DIR ".") + set(SCREENSHARE_INSTALL_DIR ".") + set(NITPICK_INSTALL_DIR ".") if (CLIENT_ONLY) set(CONSOLE_EXEC_NAME "Console.app") @@ -144,7 +154,7 @@ macro(SET_PACKAGING_PARAMETERS) set(SCREENSHARE_APP_CONTENTS "${SCREENSHARE_INSTALL_APP_PATH}/Contents") - set(INTERFACE_INSTALL_APP_PATH "${CONSOLE_INSTALL_DIR}/${INTERFACE_BUNDLE_NAME}.app") + set(INTERFACE_INSTALL_APP_PATH "${INTERFACE_INSTALL_DIR}/${INTERFACE_BUNDLE_NAME}.app") set(INTERFACE_ICON_FILENAME "${INTERFACE_ICON_PREFIX}.icns") set(NITPICK_ICON_FILENAME "${NITPICK_ICON_PREFIX}.icns") else () @@ -177,12 +187,12 @@ macro(SET_PACKAGING_PARAMETERS) if (PRODUCTION_BUILD) set(INTERFACE_SHORTCUT_NAME "Vircadia") set(CONSOLE_SHORTCUT_NAME "Console") - set(SANDBOX_SHORTCUT_NAME "Sandbox") + set(SANDBOX_SHORTCUT_NAME "Server") set(APP_USER_MODEL_ID "com.vircadia.console") else () set(INTERFACE_SHORTCUT_NAME "Vircadia - ${BUILD_VERSION_NO_SHA}") set(CONSOLE_SHORTCUT_NAME "Console - ${BUILD_VERSION_NO_SHA}") - set(SANDBOX_SHORTCUT_NAME "Sandbox - ${BUILD_VERSION_NO_SHA}") + set(SANDBOX_SHORTCUT_NAME "Server - ${BUILD_VERSION_NO_SHA}") endif () set(INTERFACE_HF_SHORTCUT_NAME "${INTERFACE_SHORTCUT_NAME}") diff --git a/cmake/macros/SetupHifiClientServerPlugin.cmake b/cmake/macros/SetupHifiClientServerPlugin.cmake index 1ce0b0ca6e..5c98ceb139 100644 --- a/cmake/macros/SetupHifiClientServerPlugin.cmake +++ b/cmake/macros/SetupHifiClientServerPlugin.cmake @@ -11,7 +11,11 @@ macro(SETUP_HIFI_CLIENT_SERVER_PLUGIN) setup_hifi_library() if (BUILD_CLIENT) - add_dependencies(interface ${TARGET_NAME}) + if (APPLE) + add_dependencies(Vircadia ${TARGET_NAME}) + else() + add_dependencies(interface ${TARGET_NAME}) + endif() endif() if (BUILD_SERVER) diff --git a/cmake/macros/SetupHifiLibrary.cmake b/cmake/macros/SetupHifiLibrary.cmake index 108786a651..5c6eb0a4c6 100644 --- a/cmake/macros/SetupHifiLibrary.cmake +++ b/cmake/macros/SetupHifiLibrary.cmake @@ -30,7 +30,7 @@ macro(SETUP_HIFI_LIBRARY) foreach(SRC ${AVX2_SRCS}) if (WIN32) set_source_files_properties(${SRC} PROPERTIES COMPILE_FLAGS /arch:AVX2) - elseif (APPLE OR (UNIX AND NOT ANDROID)) + elseif (APPLE OR (UNIX AND NOT ANDROID AND NOT CMAKE_SYSTEM_PROCESSOR STREQUAL "aarch64")) set_source_files_properties(${SRC} PROPERTIES COMPILE_FLAGS "-mavx2 -mfma") endif() endforeach() @@ -53,6 +53,7 @@ macro(SETUP_HIFI_LIBRARY) endforeach() setup_memory_debugger() + setup_thread_debugger() # create a library and set the property so it can be referenced later if (${${TARGET_NAME}_SHARED}) diff --git a/cmake/macros/SetupHifiPlugin.cmake b/cmake/macros/SetupHifiPlugin.cmake index 023c7603dc..22fa02dd79 100644 --- a/cmake/macros/SetupHifiPlugin.cmake +++ b/cmake/macros/SetupHifiPlugin.cmake @@ -9,7 +9,11 @@ macro(SETUP_HIFI_PLUGIN) set(${TARGET_NAME}_SHARED 1) setup_hifi_library(${ARGV}) if (BUILD_CLIENT) - add_dependencies(interface ${TARGET_NAME}) + if (APPLE) + add_dependencies(Vircadia ${TARGET_NAME}) + else() + add_dependencies(interface ${TARGET_NAME}) + endif() endif() target_link_libraries(${TARGET_NAME} ${CMAKE_THREAD_LIBS_INIT}) set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "Plugins") diff --git a/cmake/macros/SetupQt.cmake b/cmake/macros/SetupQt.cmake index bd198a2195..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 "") @@ -18,13 +21,16 @@ endfunction() function(calculate_qt5_version result _QT_DIR) # All Qt5 packages have little "private" include directories named with the actual Qt version such as: - # .../include/QtCore/5.12.3/QtCore/private + # .../include/QtCore/5.15.2/QtCore/private # Sometimes we need to include these private headers for debug hackery. # Hence we find one of these directories and pick apart its path to determine the actual QT_VERSION. if (APPLE) 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/macros/ThreadDebugger.cmake b/cmake/macros/ThreadDebugger.cmake new file mode 100644 index 0000000000..0353e3b1cb --- /dev/null +++ b/cmake/macros/ThreadDebugger.cmake @@ -0,0 +1,36 @@ +# +# MemoryDebugger.cmake +# +# 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 +# + +macro(SETUP_THREAD_DEBUGGER) +if ("$ENV{VIRCADIA_THREAD_DEBUGGING}") + if (VIRCADIA_MEMORY_DEBUGGING ) + message(FATAL_ERROR "Thread debugging and memory debugging can't be enabled at the same time." ) + endif () + + SET(VIRCADIA_THREAD_DEBUGGING true) +endif () + +if (VIRCADIA_THREAD_DEBUGGING) + if (UNIX) + if (CMAKE_CXX_COMPILER_ID MATCHES "Clang") + # for clang on Linux + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=thread -fno-omit-frame-pointer") + SET(CMAKE_EXE_LINKER_FLAGS "-fsanitize=thread ${CMAKE_EXE_LINKER_FLAGS}") + SET(CMAKE_SHARED_LINKER_FLAGS "-fsanitize=thread ${CMAKE_EXE_LINKER_FLAGS}") + else () + # for gcc on Linux + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=thread -fno-omit-frame-pointer") + SET(CMAKE_EXE_LINKER_FLAGS " -fsanitize=thread ${CMAKE_EXE_LINKER_FLAGS}") + SET(CMAKE_SHARED_LINKER_FLAGS "-fsanitize=thread ${CMAKE_EXE_LINKER_FLAGS}") + endif() + else() + message(FATAL_ERROR "Thread debugging is not supported on this platform.") + endif() +endif () +endmacro(SETUP_THREAD_DEBUGGER) 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/draco/portfile.cmake b/cmake/ports/draco/portfile.cmake index 853d45e862..cc6e9e5f8f 100644 --- a/cmake/ports/draco/portfile.cmake +++ b/cmake/ports/draco/portfile.cmake @@ -19,9 +19,9 @@ include(vcpkg_common_functions) vcpkg_from_github( OUT_SOURCE_PATH SOURCE_PATH - REPO google/draco - REF 1.3.3 - SHA512 80ed5a623046822f5bb26b2454c8ee8cc93ffe9eb3012e8461cefdfc577b26d69a92ea0f0c5e14f5f48c1ef99f9a7263b01710df376792e74358ae14e49c3897 + REPO vircadia/draco + REF 1.3.5-fixed + SHA512 68bb15de013093077946d431ab1f4080b84a66d45d20873f2c0dc44aa28034fb4ec1f6e24f9300fde563da53943b73d47163b9c6acf2667312128c50c6d075bd HEAD_REF master ) diff --git a/cmake/ports/hifi-client-deps/CONTROL b/cmake/ports/hifi-client-deps/CONTROL index 4a8a2bc44e..3a8c4693b3 100644 --- a/cmake/ports/hifi-client-deps/CONTROL +++ b/cmake/ports/hifi-client-deps/CONTROL @@ -1,4 +1,4 @@ Source: hifi-client-deps Version: 0.1 Description: Collected dependencies for High Fidelity applications -Build-Depends: hifi-deps, aristo (windows), glslang, liblo (windows), nlohmann-json, openvr (linux|windows), quazip (!android), sdl2 (!android), spirv-cross (!android), spirv-tools (!android), sranipal (windows), vulkanmemoryallocator +Build-Depends: hifi-deps, aristo (windows), glslang, liblo (windows), nlohmann-json, openvr ((linux&!arm)|windows), quazip (!android), sdl2 (!android), spirv-cross (!android), spirv-tools (!android), sranipal (windows), vulkanmemoryallocator diff --git a/cmake/ports/nvtt/portfile.cmake b/cmake/ports/nvtt/portfile.cmake index b21bb5609c..cf068a6db1 100644 --- a/cmake/ports/nvtt/portfile.cmake +++ b/cmake/ports/nvtt/portfile.cmake @@ -10,8 +10,8 @@ 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 ) diff --git a/cmake/ports/openssl-windows/CONTROL b/cmake/ports/openssl-windows/CONTROL index 881c311d00..54ca58580d 100644 --- a/cmake/ports/openssl-windows/CONTROL +++ b/cmake/ports/openssl-windows/CONTROL @@ -1,3 +1,3 @@ Source: openssl-windows -Version: 1.0.2p-1 +Version: 1.1.1h Description: OpenSSL is an open source project that provides a robust, commercial-grade, and full-featured toolkit for the Transport Layer Security (TLS) and Secure Sockets Layer (SSL) protocols. It is also a general-purpose cryptography library. diff --git a/cmake/ports/openssl-windows/ConfigureIncludeQuotesFix.patch b/cmake/ports/openssl-windows/ConfigureIncludeQuotesFix.patch deleted file mode 100644 index 09494f5650..0000000000 --- a/cmake/ports/openssl-windows/ConfigureIncludeQuotesFix.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/Configure b/Configure -index c98107a..77ad9d3 100644 ---- a/Configure -+++ b/Configure -@@ -972,7 +972,7 @@ PROCESS_ARGS: - } - elsif (/^--with-zlib-include=(.*)$/) - { -- $withargs{"zlib-include"}="-I$1"; -+ $withargs{"zlib-include"}="-I\"$1\""; - } - elsif (/^--with-fipsdir=(.*)$/) - { diff --git a/cmake/ports/openssl-windows/EmbedSymbolsInStaticLibsZ7.patch b/cmake/ports/openssl-windows/EmbedSymbolsInStaticLibsZ7.patch deleted file mode 100644 index 1a8de2c4bd..0000000000 --- a/cmake/ports/openssl-windows/EmbedSymbolsInStaticLibsZ7.patch +++ /dev/null @@ -1,25 +0,0 @@ -diff --git a/util/pl/VC-32.pl b/util/pl/VC-32.pl -index dba96cb..5722f6e 100644 ---- a/util/pl/VC-32.pl -+++ b/util/pl/VC-32.pl -@@ -154,9 +154,17 @@ else - $cflags=$opt_cflags.$base_cflags; - } - --# generate symbols.pdb unconditionally --$app_cflag.=" /Zi /Fd\$(TMP_D)/app"; --$lib_cflag.=" /Zi /Fd\$(TMP_D)/lib"; -+# generate symbols.pdb when building dlls and embed symbols when building static libs -+if ($shlib) -+ { -+ $app_cflag.=" /Zi /Fd\$(TMP_D)/app.pdb"; -+ $lib_cflag.=" /Zi /Fd\$(TMP_D)/lib.pdb"; -+ } -+else -+ { -+ $app_cflag.=" /Z7"; -+ $lib_cflag.=" /Z7"; -+ } - $lflags.=" /debug"; - - $obj='.obj'; diff --git a/cmake/ports/openssl-windows/STRINGIFYPatch.patch b/cmake/ports/openssl-windows/STRINGIFYPatch.patch deleted file mode 100644 index dd8f9c2972..0000000000 --- a/cmake/ports/openssl-windows/STRINGIFYPatch.patch +++ /dev/null @@ -1,23 +0,0 @@ -diff --git a/crypto/cversion.c b/crypto/cversion.c -index bfff699..17b7912 100644 ---- a/crypto/cversion.c -+++ b/crypto/cversion.c -@@ -56,6 +56,9 @@ - * [including the GNU Public Licence.] - */ - -+#define STRINGIFY2(x) #x -+#define STRINGIFY(x) STRINGIFY2(x) -+ - #include "cryptlib.h" - - #ifndef NO_WINDOWS_BRAINDEATH -@@ -79,7 +82,7 @@ const char *SSLeay_version(int t) - } - if (t == SSLEAY_CFLAGS) { - #ifdef CFLAGS -- return (CFLAGS); -+ return STRINGIFY(CFLAGS); - #else - return ("compiler: information not available"); - #endif diff --git a/cmake/ports/openssl-windows/portfile.cmake b/cmake/ports/openssl-windows/portfile.cmake index d58d51431e..edf826b4eb 100644 --- a/cmake/ports/openssl-windows/portfile.cmake +++ b/cmake/ports/openssl-windows/portfile.cmake @@ -3,7 +3,7 @@ if(VCPKG_CMAKE_SYSTEM_NAME) endif() include(vcpkg_common_functions) -set(OPENSSL_VERSION 1.0.2p) +set(OPENSSL_VERSION 1.1.1h) set(MASTER_COPY_SOURCE_PATH ${CURRENT_BUILDTREES_DIR}/src/openssl-${OPENSSL_VERSION}) vcpkg_find_acquire_program(PERL) @@ -12,18 +12,12 @@ get_filename_component(PERL_EXE_PATH ${PERL} DIRECTORY) set(ENV{PATH} "$ENV{PATH};${PERL_EXE_PATH}") vcpkg_download_distfile(OPENSSL_SOURCE_ARCHIVE - URLS "https://www.openssl.org/source/openssl-${OPENSSL_VERSION}.tar.gz" "https://www.openssl.org/source/old/1.0.2/openssl-${OPENSSL_VERSION}.tar.gz" + URLS "https://www.openssl.org/source/openssl-${OPENSSL_VERSION}.tar.gz" "https://www.openssl.org/source/old/1.1.1/openssl-${OPENSSL_VERSION}.tar.gz" FILENAME "openssl-${OPENSSL_VERSION}.tar.gz" - SHA512 958c5a7c3324bbdc8f07dfb13e11329d9a1b4452c07cf41fbd2d42b5fe29c95679332a3476d24c2dc2b88be16e4a24744aba675a05a388c0905756c77a8a2f16 + SHA512 da50fd99325841ed7a4367d9251c771ce505a443a73b327d8a46b2c6a7d2ea99e43551a164efc86f8743b22c2bdb0020bf24a9cbd445e9d68868b2dc1d34033a ) vcpkg_extract_source_archive(${OPENSSL_SOURCE_ARCHIVE}) -vcpkg_apply_patches( - SOURCE_PATH ${MASTER_COPY_SOURCE_PATH} - PATCHES ${CMAKE_CURRENT_LIST_DIR}/ConfigureIncludeQuotesFix.patch - ${CMAKE_CURRENT_LIST_DIR}/STRINGIFYPatch.patch - ${CMAKE_CURRENT_LIST_DIR}/EmbedSymbolsInStaticLibsZ7.patch -) vcpkg_find_acquire_program(NASM) get_filename_component(NASM_EXE_PATH ${NASM} DIRECTORY) @@ -40,39 +34,26 @@ set(CONFIGURE_COMMAND ${PERL} Configure if(VCPKG_TARGET_ARCHITECTURE STREQUAL "x86") set(OPENSSL_ARCH VC-WIN32) - set(OPENSSL_DO "ms\\do_nasm.bat") elseif(VCPKG_TARGET_ARCHITECTURE STREQUAL "x64") set(OPENSSL_ARCH VC-WIN64A) - set(OPENSSL_DO "ms\\do_win64a.bat") else() message(FATAL_ERROR "Unsupported target architecture: ${VCPKG_TARGET_ARCHITECTURE}") endif() -if(VCPKG_LIBRARY_LINKAGE STREQUAL dynamic) - set(OPENSSL_MAKEFILE "ms\\ntdll.mak") -else() - set(OPENSSL_MAKEFILE "ms\\nt.mak") -endif() - file(REMOVE_RECURSE ${CURRENT_BUILDTREES_DIR}/${TARGET_TRIPLET}-rel ${CURRENT_BUILDTREES_DIR}/${TARGET_TRIPLET}-dbg) if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "release") + message(STATUS "Configure ${TARGET_TRIPLET}-rel") file(COPY ${MASTER_COPY_SOURCE_PATH} DESTINATION ${CURRENT_BUILDTREES_DIR}/${TARGET_TRIPLET}-rel) set(SOURCE_PATH_RELEASE ${CURRENT_BUILDTREES_DIR}/${TARGET_TRIPLET}-rel/openssl-${OPENSSL_VERSION}) set(OPENSSLDIR_RELEASE ${CURRENT_PACKAGES_DIR}) - message(STATUS "Configure ${TARGET_TRIPLET}-rel") vcpkg_execute_required_process( COMMAND ${CONFIGURE_COMMAND} ${OPENSSL_ARCH} "--prefix=${OPENSSLDIR_RELEASE}" "--openssldir=${OPENSSLDIR_RELEASE}" -FS WORKING_DIRECTORY ${SOURCE_PATH_RELEASE} LOGNAME configure-perl-${TARGET_TRIPLET}-${CMAKE_BUILD_TYPE}-rel ) - vcpkg_execute_required_process( - COMMAND ${OPENSSL_DO} - WORKING_DIRECTORY ${SOURCE_PATH_RELEASE} - LOGNAME configure-do-${TARGET_TRIPLET}-${CMAKE_BUILD_TYPE}-rel - ) message(STATUS "Configure ${TARGET_TRIPLET}-rel done") message(STATUS "Build ${TARGET_TRIPLET}-rel") @@ -80,16 +61,16 @@ if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "release") # This is ok; we just do as much work as we can in parallel first, then follow up with a single-threaded build. make_directory(${SOURCE_PATH_RELEASE}/inc32/openssl) execute_process( - COMMAND ${JOM} -k -j $ENV{NUMBER_OF_PROCESSORS} -f ${OPENSSL_MAKEFILE} + COMMAND ${JOM} -k -j $ENV{NUMBER_OF_PROCESSORS} WORKING_DIRECTORY ${SOURCE_PATH_RELEASE} OUTPUT_FILE ${CURRENT_BUILDTREES_DIR}/build-${TARGET_TRIPLET}-rel-0-out.log ERROR_FILE ${CURRENT_BUILDTREES_DIR}/build-${TARGET_TRIPLET}-rel-0-err.log ) vcpkg_execute_required_process( - COMMAND nmake -f ${OPENSSL_MAKEFILE} install + COMMAND nmake install WORKING_DIRECTORY ${SOURCE_PATH_RELEASE} - LOGNAME build-${TARGET_TRIPLET}-rel-1) - + LOGNAME build-${TARGET_TRIPLET}-rel-1 + ) message(STATUS "Build ${TARGET_TRIPLET}-rel done") endif() @@ -101,39 +82,46 @@ if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "debug") set(OPENSSLDIR_DEBUG ${CURRENT_PACKAGES_DIR}/debug) vcpkg_execute_required_process( - COMMAND ${CONFIGURE_COMMAND} debug-${OPENSSL_ARCH} "--prefix=${OPENSSLDIR_DEBUG}" "--openssldir=${OPENSSLDIR_DEBUG}" -FS + COMMAND ${CONFIGURE_COMMAND} ${OPENSSL_ARCH} --debug "--prefix=${OPENSSLDIR_DEBUG}" "--openssldir=${OPENSSLDIR_DEBUG}" -FS WORKING_DIRECTORY ${SOURCE_PATH_DEBUG} LOGNAME configure-perl-${TARGET_TRIPLET}-${CMAKE_BUILD_TYPE}-dbg ) - vcpkg_execute_required_process( - COMMAND ${OPENSSL_DO} - WORKING_DIRECTORY ${SOURCE_PATH_DEBUG} - LOGNAME configure-do-${TARGET_TRIPLET}-${CMAKE_BUILD_TYPE}-dbg - ) message(STATUS "Configure ${TARGET_TRIPLET}-dbg done") message(STATUS "Build ${TARGET_TRIPLET}-dbg") make_directory(${SOURCE_PATH_DEBUG}/inc32/openssl) execute_process( - COMMAND ${JOM} -k -j $ENV{NUMBER_OF_PROCESSORS} -f ${OPENSSL_MAKEFILE} + COMMAND ${JOM} -k -j $ENV{NUMBER_OF_PROCESSORS} WORKING_DIRECTORY ${SOURCE_PATH_DEBUG} OUTPUT_FILE ${CURRENT_BUILDTREES_DIR}/build-${TARGET_TRIPLET}-dbg-0-out.log ERROR_FILE ${CURRENT_BUILDTREES_DIR}/build-${TARGET_TRIPLET}-dbg-0-err.log ) vcpkg_execute_required_process( - COMMAND nmake -f ${OPENSSL_MAKEFILE} install + COMMAND nmake install WORKING_DIRECTORY ${SOURCE_PATH_DEBUG} - LOGNAME build-${TARGET_TRIPLET}-dbg-1) - + LOGNAME build-${TARGET_TRIPLET}-dbg-1 + ) message(STATUS "Build ${TARGET_TRIPLET}-dbg done") endif() +file(REMOVE_RECURSE ${CURRENT_PACKAGES_DIR}/certs) +file(REMOVE_RECURSE ${CURRENT_PACKAGES_DIR}/lib/engines-1_1) +file(REMOVE_RECURSE ${CURRENT_PACKAGES_DIR}/private) +file(REMOVE_RECURSE ${CURRENT_PACKAGES_DIR}/debug/certs) file(REMOVE_RECURSE ${CURRENT_PACKAGES_DIR}/debug/include) +file(REMOVE_RECURSE ${CURRENT_PACKAGES_DIR}/debug/lib/engines-1_1) +file(REMOVE_RECURSE ${CURRENT_PACKAGES_DIR}/debug/private) file(REMOVE - ${CURRENT_PACKAGES_DIR}/debug/bin/openssl.exe - ${CURRENT_PACKAGES_DIR}/debug/openssl.cnf ${CURRENT_PACKAGES_DIR}/openssl.cnf + ${CURRENT_PACKAGES_DIR}/openssl.cnf.dist + ${CURRENT_PACKAGES_DIR}/ct_log_list.cnf + ${CURRENT_PACKAGES_DIR}/ct_log_list.cnf.dist + ${CURRENT_PACKAGES_DIR}/debug/openssl.cnf + ${CURRENT_PACKAGES_DIR}/debug/openssl.cnf.dist + ${CURRENT_PACKAGES_DIR}/debug/ct_log_list.cnf + ${CURRENT_PACKAGES_DIR}/debug/ct_log_list.cnf.dist + ${CURRENT_PACKAGES_DIR}/debug/bin/openssl.exe ) file(MAKE_DIRECTORY ${CURRENT_PACKAGES_DIR}/tools/openssl/) @@ -147,14 +135,6 @@ if(VCPKG_LIBRARY_LINKAGE STREQUAL static) file(REMOVE_RECURSE ${CURRENT_PACKAGES_DIR}/bin/) endif() -file(READ "${CURRENT_PACKAGES_DIR}/include/openssl/dtls1.h" _contents) -string(REPLACE "" "" _contents "${_contents}") -file(WRITE "${CURRENT_PACKAGES_DIR}/include/openssl/dtls1.h" "${_contents}") - -file(READ "${CURRENT_PACKAGES_DIR}/include/openssl/rand.h" _contents) -string(REPLACE "# include " "#ifndef _WINSOCKAPI_\n#define _WINSOCKAPI_\n#endif\n# include " _contents "${_contents}") -file(WRITE "${CURRENT_PACKAGES_DIR}/include/openssl/rand.h" "${_contents}") - vcpkg_copy_pdbs() file(COPY ${CMAKE_CURRENT_LIST_DIR}/usage DESTINATION ${CURRENT_PACKAGES_DIR}/share/${PORT}) 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/cmake/templates/BuildInfo.h.in b/cmake/templates/BuildInfo.h.in index 7f3a63d4b4..99726d270f 100644 --- a/cmake/templates/BuildInfo.h.in +++ b/cmake/templates/BuildInfo.h.in @@ -29,7 +29,8 @@ namespace BuildInfo { const QString BUILD_NUMBER = "@BUILD_NUMBER@"; const QString BUILD_GLOBAL_SERVICES = "@BUILD_GLOBAL_SERVICES@"; const QString BUILD_TIME = "@BUILD_TIME@"; - const QString INITIAL_STARTUP_LOCATION = "@INITIAL_STARTUP_LOCATION@"; + const QString PRELOADED_STARTUP_LOCATION = "@PRELOADED_STARTUP_LOCATION@"; + const QString PRELOADED_SCRIPT_WHITELIST = "@PRELOADED_SCRIPT_WHITELIST@"; enum BuildType { Dev, diff --git a/cmake/templates/NSIS.template.in b/cmake/templates/NSIS.template.in index 4c44ed1fbd..33587f3e5a 100644 --- a/cmake/templates/NSIS.template.in +++ b/cmake/templates/NSIS.template.in @@ -251,8 +251,8 @@ Var substringResult !macro InitSection SecName ; This macro reads component installed flag from the registry and - ;changes checked state of the section on the components page. - ;Input: section index constant name specified in Section command. + ; changes checked state of the section on the components page. + ; Input: section index constant name specified in Section command. ClearErrors ;Reading component status from registry @@ -718,7 +718,7 @@ Function InstallTypesPage StrCpy $OffsetUnits u StrCpy $Express "0" - ${NSD_CreateRadioButton} 30% $CurrentOffset$OffsetUnits 100% 10u "Express Install (Recommended)"; $\nInstalls Vircadia Interface and Vircadia Sandbox" + ${NSD_CreateRadioButton} 30% $CurrentOffset$OffsetUnits 100% 10u "Express Install (Recommended)"; $\nInstalls Vircadia Interface" pop $ExpressInstallRadioButton ${NSD_OnClick} $ExpressInstallRadioButton ChangeExpressLabel IntOp $CurrentOffset $CurrentOffset + 15 @@ -1346,6 +1346,7 @@ Section "-Core installation" ${EndIf} ${If} @SERVER_COMPONENT_CONDITIONAL@ + ${AndIf} $Express != "1" ; handling for server console shortcut Delete "$SMPROGRAMS\$STARTMENU_FOLDER\@CONSOLE_SHORTCUT_NAME@.lnk" CreateShortCut "$SMPROGRAMS\$STARTMENU_FOLDER\@SANDBOX_HF_SHORTCUT_NAME@.lnk" \ diff --git a/domain-server/CMakeLists.txt b/domain-server/CMakeLists.txt index 693132a8f7..a3a85684b4 100644 --- a/domain-server/CMakeLists.txt +++ b/domain-server/CMakeLists.txt @@ -15,6 +15,7 @@ if (APPLE) endif () setup_memory_debugger() +setup_thread_debugger() # TODO: find a solution that will handle web file changes in resources on windows without a re-build. # Currently the resources are only copied on post-build. If one is changed but the domain-server is not, they will diff --git a/domain-server/resources/describe-settings.json b/domain-server/resources/describe-settings.json index bb7acf344c..b91a10a17c 100644 --- a/domain-server/resources/describe-settings.json +++ b/domain-server/resources/describe-settings.json @@ -1,5 +1,5 @@ { - "version": 2.4, + "version": 2.5, "settings": [ { "name": "metaverse", @@ -295,10 +295,10 @@ }, { "name": "approved_safe_urls", - "label": "Approved Script and QML URLs", + "label": "Approved Script and QML URLs (Not Enabled)", "help": "These URLs will be sent to the Interface as safe URLs to allow through the whitelist if the Interface has this security option enabled.", - "placeholder": "0", - "default": "1", + "placeholder": "", + "default": "", "advanced": false }, { @@ -338,7 +338,7 @@ "name": "standard_permissions", "type": "table", "label": "Domain-Wide User Permissions", - "help": "Indicate which types of users can have which domain-wide permissions.", + "help": "Indicate which types of users can have which domain-wide permissions.", "caption": "Standard Permissions", "can_add_new_rows": false, "groups": [ @@ -347,8 +347,8 @@ "span": 1 }, { - "label": "Permissions ?", - "span": 11 + "label": "Permissions ?", + "span": 12 } ], "columns": [ @@ -363,6 +363,13 @@ "editable": true, "default": false }, + { + "name": "id_can_rez_avatar_entities", + "label": "Avatar Entities", + "type": "checkbox", + "editable": true, + "default": false + }, { "name": "id_can_adjust_locks", "label": "Lock / Unlock", @@ -439,17 +446,20 @@ "default": [ { "id_can_connect": true, + "id_can_rez_avatar_entities": true, "id_can_rez_tmp_certified": true, "permissions_id": "anonymous" }, { "id_can_connect": true, + "id_can_rez_avatar_entities": true, "id_can_rez_tmp_certified": true, "permissions_id": "friends" }, { - "id_can_adjust_locks": true, "id_can_connect": true, + "id_can_rez_avatar_entities": true, + "id_can_adjust_locks": true, "id_can_connect_past_max_capacity": true, "id_can_kick": true, "id_can_replace_content": true, @@ -463,6 +473,7 @@ }, { "id_can_connect": true, + "id_can_rez_avatar_entities": true, "id_can_rez_tmp_certified": true, "permissions_id": "logged-in" } @@ -484,8 +495,8 @@ "span": 1 }, { - "label": "Permissions ?", - "span": 11 + "label": "Permissions ?", + "span": 12 } ], "columns": [ @@ -525,6 +536,13 @@ "editable": true, "default": false }, + { + "name": "id_can_rez_avatar_entities", + "label": "Avatar Entities", + "type": "checkbox", + "editable": true, + "default": false + }, { "name": "id_can_adjust_locks", "label": "Lock / Unlock", @@ -613,8 +631,8 @@ "span": 1 }, { - "label": "Permissions ?", - "span": 11 + "label": "Permissions ?", + "span": 12 } ], "columns": [ @@ -651,6 +669,13 @@ "editable": true, "default": false }, + { + "name": "id_can_rez_avatar_entities", + "label": "Avatar Entities", + "type": "checkbox", + "editable": true, + "default": false + }, { "name": "id_can_adjust_locks", "label": "Lock / Unlock", @@ -734,8 +759,8 @@ "span": 1 }, { - "label": "Permissions ?", - "span": 11 + "label": "Permissions ?", + "span": 12 } ], "columns": [ @@ -750,6 +775,13 @@ "editable": true, "default": false }, + { + "name": "id_can_rez_avatar_entities", + "label": "Avatar Entities", + "type": "checkbox", + "editable": true, + "default": false + }, { "name": "id_can_adjust_locks", "label": "Lock / Unlock", @@ -833,8 +865,8 @@ "span": 1 }, { - "label": "Permissions ?", - "span": 11 + "label": "Permissions ?", + "span": 12 } ], "columns": [ @@ -849,6 +881,13 @@ "editable": true, "default": false }, + { + "name": "id_can_rez_avatar_entities", + "label": "Avatar Entities", + "type": "checkbox", + "editable": true, + "default": false + }, { "name": "id_can_adjust_locks", "label": "Lock / Unlock", @@ -932,8 +971,8 @@ "span": 1 }, { - "label": "Permissions ?", - "span": 11 + "label": "Permissions ?", + "span": 12 } ], "columns": [ @@ -948,6 +987,13 @@ "editable": true, "default": false }, + { + "name": "id_can_rez_avatar_entities", + "label": "Avatar Entities", + "type": "checkbox", + "editable": true, + "default": false + }, { "name": "id_can_adjust_locks", "label": "Lock / Unlock", @@ -1031,8 +1077,8 @@ "span": 1 }, { - "label": "Permissions ?", - "span": 11 + "label": "Permissions ?", + "span": 12 } ], "columns": [ @@ -1047,6 +1093,13 @@ "editable": true, "default": false }, + { + "name": "id_can_rez_avatar_entities", + "label": "Avatar Entities", + "type": "checkbox", + "editable": true, + "default": false + }, { "name": "id_can_adjust_locks", "label": "Lock / Unlock", @@ -1488,6 +1541,24 @@ } ] }, + { + "name": "messages_mixer", + "label": "Messages Mixer", + "assignment-types": [ + 4 + ], + "settings": [ + { + "name": "max_node_messages_per_second", + "type": "int", + "label": "Maximum Message Rate", + "help": "Maximum message send rate (messages per second) per node", + "placeholder": 1000, + "default": 1000, + "advanced": true + } + ] + }, { "name": "entity_server_settings", "label": "Entities", 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/resources/web/wizard/js/wizard.js b/domain-server/resources/web/wizard/js/wizard.js index 38842cf79f..2ce23d3fcf 100644 --- a/domain-server/resources/web/wizard/js/wizard.js +++ b/domain-server/resources/web/wizard/js/wizard.js @@ -465,6 +465,7 @@ function savePermissions() { "standard_permissions": [ { "id_can_connect": anonymousCanConnect, + "id_can_rez_avatar_entities": anonymousCanConnect, "id_can_rez": anonymousCanRez, "id_can_rez_certified": anonymousCanRez, "id_can_rez_tmp": anonymousCanRez, @@ -473,6 +474,7 @@ function savePermissions() { }, { "id_can_connect": friendsCanConnect, + "id_can_rez_avatar_entities": friendsCanConnect, "id_can_rez": friendsCanRez, "id_can_rez_certified": friendsCanRez, "id_can_rez_tmp": friendsCanRez, @@ -481,6 +483,7 @@ function savePermissions() { }, { "id_can_connect": loggedInCanConnect, + "id_can_rez_avatar_entities": loggedInCanConnect, "id_can_rez": loggedInCanRez, "id_can_rez_certified": loggedInCanRez, "id_can_rez_tmp": loggedInCanRez, @@ -490,6 +493,7 @@ function savePermissions() { { "id_can_adjust_locks": localhostPermissions, "id_can_connect": localhostPermissions, + "id_can_rez_avatar_entities": localhostPermissions, "id_can_connect_past_max_capacity": localhostPermissions, "id_can_kick": localhostPermissions, "id_can_replace_content": localhostPermissions, diff --git a/domain-server/src/DomainGatekeeper.cpp b/domain-server/src/DomainGatekeeper.cpp index 7126c525bc..035caaa328 100644 --- a/domain-server/src/DomainGatekeeper.cpp +++ b/domain-server/src/DomainGatekeeper.cpp @@ -353,6 +353,7 @@ void DomainGatekeeper::updateNodePermissions() { userPerms.permissions |= NodePermissions::Permission::canWriteToAssetServer; userPerms.permissions |= NodePermissions::Permission::canReplaceDomainContent; userPerms.permissions |= NodePermissions::Permission::canGetAndSetPrivateUserData; + userPerms.permissions |= NodePermissions::Permission::canRezAvatarEntities; } 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 @@ -448,6 +449,7 @@ SharedNodePointer DomainGatekeeper::processAssignmentConnectRequest(const NodeCo userPerms.permissions |= NodePermissions::Permission::canWriteToAssetServer; userPerms.permissions |= NodePermissions::Permission::canReplaceDomainContent; userPerms.permissions |= NodePermissions::Permission::canGetAndSetPrivateUserData; + userPerms.permissions |= NodePermissions::Permission::canRezAvatarEntities; newNode->setPermissions(userPerms); return newNode; } diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index bb79bb367a..3acd17f6af 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -66,6 +66,7 @@ using namespace std::chrono; Q_LOGGING_CATEGORY(domain_server, "hifi.domain_server") Q_LOGGING_CATEGORY(domain_server_ice, "hifi.domain_server.ice") +Q_LOGGING_CATEGORY(domain_server_auth, "vircadia.domain_server.auth") const QString ACCESS_TOKEN_KEY_PATH = "metaverse.access_token"; const QString DomainServer::REPLACEMENT_FILE_EXTENSION = ".replace"; @@ -660,7 +661,7 @@ bool DomainServer::isPacketVerified(const udt::Packet& packet) { // if this is a mismatching connect packet, we can't simply drop it on the floor // send back a packet to the interface that tells them we refuse connection for a mismatch - if (headerType == PacketType::DomainConnectRequest + if ((headerType == PacketType::DomainConnectRequest || headerType == PacketType::DomainConnectRequestPending) && headerVersion != versionForPacketType(PacketType::DomainConnectRequest)) { DomainGatekeeper::sendProtocolMismatchConnectionDenial(packet.getSenderSockAddr()); } @@ -806,6 +807,8 @@ void DomainServer::setupNodeListAndAssignments() { // register the gatekeeper for the packets it needs to receive packetReceiver.registerListener(PacketType::DomainConnectRequest, PacketReceiver::makeUnsourcedListenerReference(&_gatekeeper, &DomainGatekeeper::processConnectRequestPacket)); + packetReceiver.registerListener(PacketType::DomainConnectRequestPending, + PacketReceiver::makeUnsourcedListenerReference(&_gatekeeper, &DomainGatekeeper::processConnectRequestPacket)); packetReceiver.registerListener(PacketType::ICEPing, PacketReceiver::makeUnsourcedListenerReference(&_gatekeeper, &DomainGatekeeper::processICEPingPacket)); packetReceiver.registerListener(PacketType::ICEPingReply, @@ -1545,9 +1548,9 @@ void DomainServer::sendHeartbeatToMetaverse(const QString& networkAddress, const static const QString PORT_SETTINGS_KEY = "domain_server." + PUBLIC_SOCKET_PORT_KEY; const int portFromSettings = _settingsManager.valueForKeyPath(PORT_SETTINGS_KEY).toInt(); - if (port != NULL) { + if (port != 0) { domainObject[PUBLIC_SOCKET_PORT_KEY] = port; - } else if (portFromSettings != NULL) { + } else if (portFromSettings != 0) { domainObject[PUBLIC_SOCKET_PORT_KEY] = portFromSettings; } @@ -2771,6 +2774,20 @@ void DomainServer::profileRequestFinished() { } } +QString DomainServer::operationToString(const QNetworkAccessManager::Operation &op) { + switch(op) { + case QNetworkAccessManager::Operation::HeadOperation: return "HEAD"; + case QNetworkAccessManager::Operation::GetOperation: return "GET"; + case QNetworkAccessManager::Operation::PutOperation: return "PUT"; + case QNetworkAccessManager::Operation::PostOperation: return "POST"; + case QNetworkAccessManager::Operation::DeleteOperation: return "DELETE"; + case QNetworkAccessManager::Operation::CustomOperation: return "CUSTOM"; + case QNetworkAccessManager::Operation::UnknownOperation: + default: + return "UNKNOWN"; + } +} + std::pair DomainServer::isAuthenticatedRequest(HTTPConnection* connection) { static const QByteArray HTTP_COOKIE_HEADER_KEY = "Cookie"; @@ -2784,6 +2801,9 @@ std::pair DomainServer::isAuthenticatedRequest(HTTPConnection* c QVariant adminUsersVariant = _settingsManager.valueForKeyPath(ADMIN_USERS_CONFIG_KEY); QVariant adminRolesVariant = _settingsManager.valueForKeyPath(ADMIN_ROLES_CONFIG_KEY); + QString httpPeerAddress = connection->peerAddress().toString(); + QString httpOperation = operationToString(connection->requestOperation()); + if (_oauthEnable) { QString cookieString = connection->requestHeader(HTTP_COOKIE_HEADER_KEY); @@ -2817,11 +2837,15 @@ std::pair DomainServer::isAuthenticatedRequest(HTTPConnection* c foreach(const QString& userRole, sessionData.getRoles()) { if (adminRolesArray.contains(userRole)) { // this user has a role that allows them to administer the domain-server + qCInfo(domain_server_auth) << httpPeerAddress << "- OAuth:" << profileUsername << " - " + << httpOperation << " " << connection->requestUrl(); return { true, profileUsername }; } } } + qCWarning(domain_server_auth) << httpPeerAddress << "- OAuth authentication failed for " << profileUsername << "-" + << httpOperation << " " << connection->requestUrl(); connection->respond(HTTPConnection::StatusCode401, UNAUTHENTICATED_BODY); // the user does not have allowed username or role, return 401 @@ -2833,6 +2857,9 @@ std::pair DomainServer::isAuthenticatedRequest(HTTPConnection* c if (connection->requestHeader(REQUESTED_WITH_HEADER) == XML_REQUESTED_WITH) { // unauthorized XHR requests get a 401 and not a 302, since there isn't an XHR // path to OAuth authorize + + qCWarning(domain_server_auth) << httpPeerAddress << "- OAuth unauthorized XHR -" + << httpOperation << " " << connection->requestUrl(); connection->respond(HTTPConnection::StatusCode401, UNAUTHENTICATED_BODY); } else { // re-direct this user to OAuth page @@ -2849,6 +2876,8 @@ std::pair DomainServer::isAuthenticatedRequest(HTTPConnection* c redirectHeaders.insert("Location", authURL.toEncoded()); + qCWarning(domain_server_auth) << httpPeerAddress << "- OAuth redirecting -" + << httpOperation << " " << connection->requestUrl(); connection->respond(HTTPConnection::StatusCode302, QByteArray(), HTTPConnection::DefaultContentType, redirectHeaders); } @@ -2883,7 +2912,12 @@ std::pair DomainServer::isAuthenticatedRequest(HTTPConnection* c "" : QCryptographicHash::hash(headerPassword.toUtf8(), QCryptographicHash::Sha256).toHex(); if (settingsUsername == headerUsername && hexHeaderPassword == settingsPassword) { + qCInfo(domain_server_auth) << httpPeerAddress << "- Basic:" << headerUsername << "-" + << httpOperation << " " << connection->requestUrl(); return { true, headerUsername }; + } else { + qCWarning(domain_server_auth) << httpPeerAddress << "- Basic auth failed for" << headerUsername << "-" + << httpOperation << " " << connection->requestUrl(); } } } @@ -2904,11 +2938,13 @@ std::pair DomainServer::isAuthenticatedRequest(HTTPConnection* c connection->respond(HTTPConnection::StatusCode401, UNAUTHENTICATED_BODY, HTTPConnection::DefaultContentType, basicAuthHeader); + qCWarning(domain_server_auth) << httpPeerAddress << "- Basic auth required -" << httpOperation << " " << connection->requestUrl(); // not authenticated, bubble up false return { false, QString() }; } else { // we don't have an OAuth URL + admin roles/usernames, so all users are authenticated + qCWarning(domain_server_auth) << httpPeerAddress << "- OPEN ACCESS -" << httpOperation << " " << connection->requestUrl(); return { true, QString() }; } } diff --git a/domain-server/src/DomainServer.h b/domain-server/src/DomainServer.h index 24d26540c1..11d04cb255 100644 --- a/domain-server/src/DomainServer.h +++ b/domain-server/src/DomainServer.h @@ -43,6 +43,7 @@ Q_DECLARE_LOGGING_CATEGORY(domain_server) Q_DECLARE_LOGGING_CATEGORY(domain_server_ice) +Q_DECLARE_LOGGING_CATEGORY(domain_server_auth) typedef QSharedPointer SharedAssignmentPointer; typedef QMultiHash TransactionHash; @@ -233,6 +234,8 @@ private: std::initializer_list optionalData = { }, bool requireAccessToken = true); + QString operationToString(const QNetworkAccessManager::Operation &op); + SubnetList _acSubnetWhitelist; std::vector _replicatedUsernames; diff --git a/domain-server/src/DomainServerSettingsManager.cpp b/domain-server/src/DomainServerSettingsManager.cpp index 08cf56b188..7b04c72845 100644 --- a/domain-server/src/DomainServerSettingsManager.cpp +++ b/domain-server/src/DomainServerSettingsManager.cpp @@ -37,6 +37,7 @@ #include #include #include +#include #include "DomainServerNodeData.h" @@ -527,6 +528,28 @@ void DomainServerSettingsManager::setupConfigMap(const QString& userConfigFilena *newAdminRoles = adminRoles; } + if (oldVersion < 2.5) { + // Default values for new canRezAvatarEntities permission. + unpackPermissions(); + std::list> permissionsSets{ + _standardAgentPermissions.get(), + _agentPermissions.get(), + _ipPermissions.get(), + _macPermissions.get(), + _machineFingerprintPermissions.get(), + _groupPermissions.get(), + _groupForbiddens.get() + }; + foreach (auto permissionsSet, permissionsSets) { + for (auto entry : permissionsSet) { + const auto& userKey = entry.first; + if (permissionsSet[userKey]->can(NodePermissions::Permission::canConnectToDomain)) { + permissionsSet[userKey]->set(NodePermissions::Permission::canRezAvatarEntities); + } + } + } + packPermissions(); + } // write the current description version to our settings *versionVariant = _descriptionVersion; @@ -863,6 +886,20 @@ void DomainServerSettingsManager::processNodeKickRequestPacket(QSharedPointerreadWithoutCopy(NUM_BYTES_RFC4122_UUID)); + bool hasOptionalBanParameters = false; + int banParameters; + bool banByUsername; + bool banByFingerprint; + bool banByIP; + // pull optional ban parameters from the packet + if (message.data()->getSize() == (NUM_BYTES_RFC4122_UUID + sizeof(int))) { + hasOptionalBanParameters = true; + message->readPrimitive(&banParameters); + banByUsername = banParameters & ModerationFlags::BanFlags::BAN_BY_USERNAME; + banByFingerprint = banParameters & ModerationFlags::BanFlags::BAN_BY_FINGERPRINT; + banByIP = banParameters & ModerationFlags::BanFlags::BAN_BY_IP; + } + if (!nodeUUID.isNull() && nodeUUID != sendingNode->getUUID()) { // make sure we actually have a node with this UUID auto limitedNodeList = DependencyManager::get(); @@ -881,16 +918,20 @@ void DomainServerSettingsManager::processNodeKickRequestPacket(QSharedPointergetPermissions().getKey()]; + // grab or create permissions for the given username + auto userPermissions = _agentPermissions[matchingNode->getPermissions().getKey()]; - newPermissions = !hadPermissions || userPermissions->can(NodePermissions::Permission::canConnectToDomain); + newPermissions = + !hadPermissions || userPermissions->can(NodePermissions::Permission::canConnectToDomain); - // ensure that the connect permission is clear - userPermissions->clear(NodePermissions::Permission::canConnectToDomain); + // ensure that the connect permission is clear + userPermissions->clear(NodePermissions::Permission::canConnectToDomain); + } } // if we didn't have a username, or this domain-server uses the "multi-kick" setting to @@ -898,7 +939,7 @@ void DomainServerSettingsManager::processNodeKickRequestPacket(QSharedPointer(matchingNode->getLinkedData()); if (nodeData) { @@ -923,36 +964,39 @@ void DomainServerSettingsManager::processNodeKickRequestPacket(QSharedPointerclear(NodePermissions::Permission::canConnectToDomain); } } else { - // if no node data, all we can do is IP address - auto& kickAddress = matchingNode->getActiveSocket() - ? matchingNode->getActiveSocket()->getAddress() - : matchingNode->getPublicSocket().getAddress(); + // if no node data, all we can do is ban by IP address + banByIP = true; + } + } + + if (banByIP) { + auto& kickAddress = matchingNode->getActiveSocket() + ? matchingNode->getActiveSocket()->getAddress() + : matchingNode->getPublicSocket().getAddress(); - // probably isLoopback covers it, as whenever I try to ban an agent on same machine as the domain-server - // it is always 127.0.0.1, but looking at the public and local addresses just to be sure - // TODO: soon we will have feedback (in the form of a message to the client) after we kick. When we - // do, we will have a success flag, and perhaps a reason for failure. For now, just don't do it. - if (kickAddress == limitedNodeList->getPublicSockAddr().getAddress() || - kickAddress == limitedNodeList->getLocalSockAddr().getAddress() || - kickAddress.isLoopback() ) { - qWarning() << "attempt to kick node running on same machine as domain server, ignoring KickRequest"; - return; - } + // probably isLoopback covers it, as whenever I try to ban an agent on same machine as the domain-server + // it is always 127.0.0.1, but looking at the public and local addresses just to be sure + // TODO: soon we will have feedback (in the form of a message to the client) after we kick. When we + // do, we will have a success flag, and perhaps a reason for failure. For now, just don't do it. + if (kickAddress == limitedNodeList->getPublicSockAddr().getAddress() || + kickAddress == limitedNodeList->getLocalSockAddr().getAddress() || + kickAddress.isLoopback() ) { + qWarning() << "attempt to kick node running on same machine as domain server, ignoring KickRequest"; + return; + } + NodePermissionsKey ipAddressKey(kickAddress.toString(), QUuid()); - NodePermissionsKey ipAddressKey(kickAddress.toString(), QUuid()); + // check if there were already permissions for the IP + bool hadIPPermissions = hasPermissionsForIP(kickAddress); - // check if there were already permissions for the IP - bool hadIPPermissions = hasPermissionsForIP(kickAddress); + // grab or create permissions for the given IP address + auto ipPermissions = _ipPermissions[ipAddressKey]; - // grab or create permissions for the given IP address - auto ipPermissions = _ipPermissions[ipAddressKey]; + if (!hadIPPermissions || ipPermissions->can(NodePermissions::Permission::canConnectToDomain)) { + newPermissions = true; - if (!hadIPPermissions || ipPermissions->can(NodePermissions::Permission::canConnectToDomain)) { - newPermissions = true; - - ipPermissions->clear(NodePermissions::Permission::canConnectToDomain); - } + ipPermissions->clear(NodePermissions::Permission::canConnectToDomain); } } @@ -1448,6 +1492,8 @@ QJsonObject DomainServerSettingsManager::settingsResponseObjectForType(const QSt SettingsBackupFlag settingsBackupFlag) { QJsonObject responseObject; + responseObject["version"] = _descriptionVersion; // Domain settings version number. + if (!typeValue.isEmpty() || authentication == Authenticated) { // convert the string type value to a QJsonValue QJsonValue queryType = typeValue.isEmpty() ? QJsonValue() : QJsonValue(typeValue.toInt()); diff --git a/hifi_qt.py b/hifi_qt.py index 48e9b337a6..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 @@ -27,68 +52,152 @@ endif() def __init__(self, args): self.args = args self.configFilePath = os.path.join(args.build_root, 'qt.cmake') - self.version = os.getenv('VIRCADIA_USE_QT_VERSION', '5.12.3') - + 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() + 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.12.3-windows3.tar.gz%3FversionId=5ADqP0M0j5ZfimUHrx4zJld6vYceHEsI' + self.qtUrl = self.assets_url + '/dependencies/vcpkg/qt5-install-5.15.2-windows.tar.gz' elif 'Darwin' == system: - self.qtUrl = self.assets_url + '/dependencies/vcpkg/qt5-install-5.12.3-macos.tar.gz%3FversionId=bLAgnoJ8IMKpqv8NFDcAu8hsyQy3Rwwz' + 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 distro.id() == 'ubuntu': - u_major = int( distro.major_version() ) - u_minor = int( distro.minor_version() ) + if 'x86_64' == cpu_architecture: + if distro.id() == 'ubuntu': + u_major = int( distro.major_version() ) + u_minor = int( distro.minor_version() ) - if u_major == 16: - self.qtUrl = self.assets_url + '/dependencies/vcpkg/qt5-install-5.12.3-ubuntu-16.04-with-symbols.tar.gz' - elif u_major == 18: - self.qtUrl = self.assets_url + '/dependencies/vcpkg/qt5-install-5.12.3-ubuntu-18.04.tar.gz' - elif u_major == 19 and u_minor == 10: - self.qtUrl = self.assets_url + '/dependencies/vcpkg/qt5-install-5.12.6-ubuntu-19.10.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!!!') + 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: + self.__no_qt_package_error() + else: + self.__unsupported_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.__no_qt_package_error() + + elif 'aarch64' == cpu_architecture: + if distro.id() == 'ubuntu': + u_major = int( distro.major_version() ) + u_minor = int( distro.minor_version() ) + + 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: + self.__no_qt_package_error() + else: + self.__unsupported_error() + + elif distro.id() == 'debian': + u_major = int( distro.major_version() ) + u_minor = int( distro.minor_version() ) + + if u_major == 10: + #self.qtUrl = self.assets_url + '/dependencies/vcpkg/qt5-install-5.12.3-ubuntu-16.04-with-symbols.tar.gz' + self.__no_qt_package_error() + elif u_major > 10: + self.__no_qt_package_error() + else: + self.__unsupported_error() + + else: + self.__no_qt_package_error() else: - print("Sorry, " + distro.name(pretty=True) + " is not supported. 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!!!') + raise Exception('UNKNOWN CPU ARCHITECTURE!!!') + else: print("System : " + platform.system()) print("Architecture: " + platform.architecture()) 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 @@ -103,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 ebdfb6c972..642ed1253e 100644 --- a/hifi_vcpkg.py +++ b/hifi_vcpkg.py @@ -44,13 +44,14 @@ endif() self.assets_url = self.readVar('EXTERNAL_BUILD_ASSETS') # The noClean flag indicates we're doing weird dependency maintenance stuff - # i.e. we've got an explicit checkout of vcpkg and we don't want the script to - # do stuff it might otherwise do. It typically indicates that we're using our + # i.e. we've got an explicit checkout of vcpkg and we don't want the script to + # do stuff it might otherwise do. It typically indicates that we're using our # own git checkout of vcpkg and manually managing it self.noClean = False # OS dependent information system = platform.system() + machine = platform.machine() if 'HIFI_VCPKG_PATH' in os.environ: self.path = os.environ['HIFI_VCPKG_PATH'] @@ -59,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') @@ -105,6 +106,12 @@ endif() self.bootstrapEnv['CXXFLAGS'] = '-D_CTERMID_H_' if usePrebuilt: self.prebuiltArchive = self.assets_url + "/dependencies/vcpkg/builds/vcpkg-osx.tgz%3FversionId=6JrIMTdvpBF3MAsjA92BMkO79Psjzs6Z" + elif 'Linux' == system and 'aarch64' == machine: + self.exe = os.path.join(self.path, 'vcpkg') + self.bootstrapCmds = [ os.path.join(self.path, 'bootstrap-vcpkg.sh'), '-disableMetrics' ] + self.vcpkgUrl = 'http://motofckr9k.ddns.net/vircadia_packages/vcpkg-2020.11-1_arm64.tar.xz' + self.vcpkgHash = 'f39fa1c34d2ba820954b8ce4acc05e3d0ce5fa5efe5440516ba910ff222c85c658ba4bbfc92b3fa6cbb594f99be115cda69ebe44ed38d4d3988058fb1faefbb3' + self.hostTriplet = 'arm64-linux' else: self.exe = os.path.join(self.path, 'vcpkg') self.bootstrapCmds = [ os.path.join(self.path, 'bootstrap-vcpkg.sh'), '-disableMetrics' ] diff --git a/ice-server/CMakeLists.txt b/ice-server/CMakeLists.txt index 07b90b369e..9234d68faf 100644 --- a/ice-server/CMakeLists.txt +++ b/ice-server/CMakeLists.txt @@ -19,6 +19,7 @@ endif () include_directories(SYSTEM "${OPENSSL_INCLUDE_DIR}") setup_memory_debugger() +setup_thread_debugger() # append OpenSSL to our list of libraries to link target_link_libraries(${TARGET_NAME} ${OPENSSL_LIBRARIES}) diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index 0a0ade149d..a2a29ed4ba 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -1,4 +1,10 @@ -set(TARGET_NAME interface) +if (APPLE) + # Make the OSX DMG app be Vircadia.app. + set(TARGET_NAME Vircadia) +else() + set(TARGET_NAME interface) +endif() + project(${TARGET_NAME}) file(GLOB_RECURSE QML_SRC resources/qml/*.qml resources/qml/*.js) @@ -28,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() @@ -47,6 +53,7 @@ add_custom_target(resources ALL DEPENDS ${GENERATE_QRC_DEPENDS}) set(OPTIONAL_EXTERNALS "LeapMotion") setup_memory_debugger() +setup_thread_debugger() foreach(EXTERNAL ${OPTIONAL_EXTERNALS}) string(TOUPPER ${EXTERNAL} ${EXTERNAL}_UPPERCASE) @@ -191,9 +198,12 @@ if (BUILD_TOOLS AND NPM_EXECUTABLE) endif() if (WIN32 OR APPLE) - add_dependencies(${TARGET_NAME} resources screenshare) + add_dependencies(${TARGET_NAME} resources) endif() +if (SCREENSHARE) + add_dependencies(${TARGET_NAME} screenshare) +endif() if (WIN32) # These are external plugins, but we need to do the 'add dependency' here so that their @@ -218,7 +228,7 @@ endif() # link required hifi libraries link_hifi_libraries( shared workload task octree ktx gpu gl procedural graphics graphics-scripting render - pointers recording hfm fbx networking material-networking + pointers recording hfm model-serializers networking material-networking model-networking model-baker entities avatars audio audio-client animation script-engine physics render-utils entities-renderer avatars-renderer ui qml auto-updater midi @@ -299,7 +309,7 @@ target_link_libraries( ${PLATFORM_QT_LIBRARIES} ) -if (UNIX AND NOT ANDROID) +if (UNIX AND NOT ANDROID AND NOT VIRCADIA_THREAD_DEBUGGING) if (CMAKE_SYSTEM_NAME MATCHES "Linux") # Linux target_link_libraries(${TARGET_NAME} pthread atomic) @@ -333,10 +343,6 @@ if (APPLE) COMMAND "${CMAKE_COMMAND}" -E copy_directory "${CMAKE_SOURCE_DIR}/scripts" "${RESOURCES_DEV_DIR}/scripts" - # copy screenshare app to the resource folder - COMMAND "${CMAKE_COMMAND}" -E copy_directory - "${CMAKE_CURRENT_BINARY_DIR}/../screenshare/hifi-screenshare-darwin-x64/hifi-screenshare.app" - "${RESOURCES_DEV_DIR}/hifi-screenshare.app" # copy JSDoc files beside the executable COMMAND "${CMAKE_COMMAND}" -E copy_directory "${CMAKE_SOURCE_DIR}/tools/jsdoc/out" @@ -363,6 +369,15 @@ if (APPLE) "${RESOURCES_DEV_DIR}/serverless/redirect.json" ) + if (SCREENSHARE) + add_custom_command(TARGET ${TARGET_NAME} POST_BUILD + # copy screenshare app to the resource folder + COMMAND "${CMAKE_COMMAND}" -E copy_directory + "${CMAKE_CURRENT_BINARY_DIR}/../screenshare/hifi-screenshare-darwin-x64/hifi-screenshare.app" + "${RESOURCES_DEV_DIR}/hifi-screenshare.app" + ) + endif() + # call the fixup_interface macro to add required bundling commands for installation fixup_interface() @@ -420,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/controlsUit/SpinBox.qml b/interface/resources/qml/controlsUit/SpinBox.qml index a888bbd07c..719b0d00c1 100644 --- a/interface/resources/qml/controlsUit/SpinBox.qml +++ b/interface/resources/qml/controlsUit/SpinBox.qml @@ -73,9 +73,9 @@ SpinBox { } } - stepSize: realStepSize * factor - to : realTo*factor - from : realFrom*factor + stepSize: Math.round(realStepSize * factor) + to : Math.round(realTo*factor) + from : Math.round(realFrom*factor) font.family: "Fira Sans SemiBold" font.pixelSize: hifi.fontSizes.textFieldInput @@ -97,11 +97,11 @@ SpinBox { } textFromValue: function(value, locale) { - return parseFloat(value / factor).toFixed(decimals); + return (value / factor).toFixed(decimals); } valueFromText: function(text, locale) { - return Number.fromLocaleString(locale, text) * factor; + return Math.round(Number.fromLocaleString(locale, text) * factor); } diff --git a/interface/resources/qml/dialogs/preferences/SpinBoxPreference.qml b/interface/resources/qml/dialogs/preferences/SpinBoxPreference.qml index 1b080c2759..5b3a28cd1d 100644 --- a/interface/resources/qml/dialogs/preferences/SpinBoxPreference.qml +++ b/interface/resources/qml/dialogs/preferences/SpinBoxPreference.qml @@ -51,6 +51,7 @@ Preference { decimals: preference.decimals minimumValue: preference.min maximumValue: preference.max + realStepSize: preference.step width: 100 anchors { verticalCenter: parent.verticalCenter diff --git a/interface/resources/qml/dialogs/preferences/SpinnerSliderPreference.qml b/interface/resources/qml/dialogs/preferences/SpinnerSliderPreference.qml index cbc804d9d7..bf7ea08d3a 100644 --- a/interface/resources/qml/dialogs/preferences/SpinnerSliderPreference.qml +++ b/interface/resources/qml/dialogs/preferences/SpinnerSliderPreference.qml @@ -76,6 +76,7 @@ Preference { realValue: preference.value minimumValue: preference.min maximumValue: preference.max + realStepSize: preference.step width: 100 onValueChanged: { slider.value = realValue; diff --git a/interface/resources/qml/hifi/AvatarApp.qml b/interface/resources/qml/hifi/AvatarApp.qml index cfc1121af9..2c8d62a598 100644 --- a/interface/resources/qml/hifi/AvatarApp.qml +++ b/interface/resources/qml/hifi/AvatarApp.qml @@ -518,7 +518,12 @@ Rectangle { glyphText: "\ue02e" onClicked: { - adjustWearables.open(currentAvatar); + if (!AddressManager.isConnected || Entities.canRezAvatarEntities()) { + adjustWearables.open(currentAvatar); + } else { + Window.alert("You cannot use wearables on this domain.") + } + } } @@ -529,7 +534,11 @@ Rectangle { glyphText: wearablesFrozen ? hifi.glyphs.lock : hifi.glyphs.unlock; onClicked: { - emitSendToScript({'method' : 'toggleWearablesFrozen'}); + if (!AddressManager.isConnected || Entities.canRezAvatarEntities()) { + emitSendToScript({'method' : 'toggleWearablesFrozen'}); + } else { + Window.alert("You cannot use wearables on this domain.") + } } } } diff --git a/interface/resources/qml/hifi/Pal.qml b/interface/resources/qml/hifi/Pal.qml index 55f2bb80b1..15fa8df93d 100644 --- a/interface/resources/qml/hifi/Pal.qml +++ b/interface/resources/qml/hifi/Pal.qml @@ -478,7 +478,7 @@ Rectangle { visible: iAmAdmin; role: "mute"; title: "SILENCE"; - width: actionButtonWidth; + width: actionButtonWidth - 8; movable: false; resizable: false; } @@ -506,6 +506,7 @@ Rectangle { id: itemCell; property bool isCheckBox: styleData.role === "personalMute" || styleData.role === "ignore"; property bool isButton: styleData.role === "mute" || styleData.role === "kick"; + property bool isBan: styleData.role === "kick"; property bool isAvgAudio: styleData.role === "avgAudioLevel"; opacity: !isButton ? (model && model.isPresent ? 1.0 : 0.4) : 1.0; // Admin actions shouldn't turn gray @@ -605,7 +606,9 @@ Rectangle { color: 2; // Red visible: isButton; enabled: !nameCard.isReplicated; - anchors.centerIn: parent; + anchors.verticalCenter: itemCell.verticalCenter; + anchors.left: parent.left; + anchors.leftMargin: styleData.role === "kick" ? 1 : 14; width: 32; height: 32; onClicked: { @@ -620,7 +623,39 @@ Rectangle { HiFiGlyphs { text: (styleData.role === "kick") ? hifi.glyphs.error : hifi.glyphs.muted; // Size - size: parent.height*1.3; + size: parent.height * 1.3; + // Anchors + anchors.fill: parent; + // Style + horizontalAlignment: Text.AlignHCenter; + color: enabled ? hifi.buttons.textColor[actionButton.color] + : hifi.buttons.disabledTextColor[actionButton.colorScheme]; + } + } + + HifiControlsUit.Button { + id: hardBanButton; + color: 2; // Red + visible: isBan; + enabled: !nameCard.isReplicated; + anchors.verticalCenter: itemCell.verticalCenter; + anchors.left: parent.left; + anchors.leftMargin: actionButton.width + 3; + width: 32; + height: 32; + onClicked: { + Users[styleData.role](model.sessionId, Users.BAN_BY_USERNAME | Users.BAN_BY_FINGERPRINT | Users.BAN_BY_IP); + UserActivityLogger["palAction"](styleData.role, model.sessionId); + if (styleData.role === "kick") { + nearbyUserModelData.splice(model.userIndex, 1); + nearbyUserModel.remove(model.userIndex); // after changing nearbyUserModelData, b/c ListModel can frob the data + } + } + // muted/error glyphs + HiFiGlyphs { + text: hifi.glyphs.alert; + // Size + size: parent.height * 1.3; // Anchors anchors.fill: parent; // Style @@ -720,7 +755,8 @@ Rectangle { onClicked: letterbox(hifi.glyphs.question, "Admin Actions", "Silence mutes a user's microphone. Silenced users can unmute themselves by clicking "UNMUTE" on their toolbar.

" + - "Ban removes a user from this domain and prevents them from returning. Admins can un-ban users from the Sandbox Domain Settings page."); + "Ban (left) identifies a user by username (if applicable) and machine fingerprint, then removes them from this domain and prevents them from returning. Admins can un-ban users from the Server Domain Settings page.

" + + "Hard Ban (right) identifies a user by username (if applicable), machine fingerprint, and IP address, then removes them from this domain and prevents them from returning. Admins can un-ban users from the Server Domain Settings page."); onEntered: adminHelpText.color = "#94132e"; onExited: adminHelpText.color = hifi.colors.redHighlight; } diff --git a/interface/resources/qml/hifi/audio/Audio.qml b/interface/resources/qml/hifi/audio/Audio.qml index 31f3ee44df..0f7d521653 100644 --- a/interface/resources/qml/hifi/audio/Audio.qml +++ b/interface/resources/qml/hifi/audio/Audio.qml @@ -15,6 +15,7 @@ import QtQuick 2.10 import QtQuick.Controls 2.2 import QtQuick.Layouts 1.3 +import QtGraphicalEffects 1.0 import stylesUit 1.0 import controlsUit 1.0 as HifiControlsUit @@ -104,6 +105,11 @@ Rectangle { AudioScriptingInterface.setSystemInjectorGain(sliderValue); } } + function updateNoiseReductionThresholdFromQML(sliderValue) { + if (AudioScriptingInterface.getNoiseReductionThreshold() !== sliderValue) { + AudioScriptingInterface.setNoiseReductionThreshold(sliderValue); + } + } Component.onCompleted: { enablePeakValues(); @@ -164,7 +170,7 @@ Rectangle { x: 2 * margins.paddings; width: parent.width; // switch heights + 2 * top margins - height: (root.switchHeight) * 6 + 48; + height: (bar.currentIndex === 0) ? (root.switchHeight) * 2 + 48 : (root.switchHeight) * 4 + 48; anchors.top: firstSeparator.bottom; anchors.topMargin: 10; @@ -175,6 +181,7 @@ Rectangle { height: parent.height; anchors.top: parent.top anchors.left: parent.left; + HifiControlsUit.Switch { id: muteMic; height: root.switchHeight; @@ -193,45 +200,11 @@ Rectangle { } } - HifiControlsUit.Switch { - id: noiseReductionSwitch; - height: root.switchHeight; - switchWidth: root.switchWidth; - anchors.top: muteMic.bottom; - anchors.topMargin: 24 - anchors.left: parent.left - labelTextOn: "Noise Reduction"; - labelTextSize: 16; - backgroundOnColor: "#E3E3E3"; - checked: AudioScriptingInterface.noiseReduction; - onCheckedChanged: { - AudioScriptingInterface.noiseReduction = checked; - checked = Qt.binding(function() { return AudioScriptingInterface.noiseReduction; }); // restore binding - } - } - - HifiControlsUit.Switch { - id: acousticEchoCancellationSwitch; - height: root.switchHeight; - switchWidth: root.switchWidth; - anchors.top: noiseReductionSwitch.bottom - anchors.topMargin: 24 - anchors.left: parent.left - labelTextOn: "Echo Cancellation"; - labelTextSize: 16; - backgroundOnColor: "#E3E3E3"; - checked: AudioScriptingInterface.acousticEchoCancellation; - onCheckedChanged: { - AudioScriptingInterface.acousticEchoCancellation = checked; - checked = Qt.binding(function() { return AudioScriptingInterface.acousticEchoCancellation; }); - } - } - HifiControlsUit.Switch { id: pttSwitch height: root.switchHeight; switchWidth: root.switchWidth; - anchors.top: acousticEchoCancellationSwitch.bottom; + anchors.top: muteMic.bottom; anchors.topMargin: 24 anchors.left: parent.left labelTextOn: (bar.currentIndex === 0) ? qsTr("Push To Talk (T)") : qsTr("Push To Talk"); @@ -254,6 +227,7 @@ Rectangle { height: parent.height; anchors.top: parent.top anchors.left: switchContainer.right; + HifiControlsUit.Switch { id: warnMutedSwitch height: root.switchHeight; @@ -271,7 +245,6 @@ Rectangle { } } - HifiControlsUit.Switch { id: audioLevelSwitch height: root.switchHeight; @@ -519,13 +492,282 @@ Rectangle { anchors.top: systemInjectorGainContainer.bottom; anchors.topMargin: 10; } + + Item { + id: noiseReductionHeader + x: margins.paddings; + width: parent.width - margins.paddings * 2; + height: 36; + anchors.top: secondSeparator.bottom; + anchors.topMargin: 10; + + HiFiGlyphs { + width: margins.sizeCheckBox; + text: hifi.glyphs.mic; + color: hifi.colors.white; + anchors.left: parent.left; + anchors.leftMargin: -size / 4; // The glyph has empty space at left about 25% + anchors.verticalCenter: parent.verticalCenter; + size: 30; + } + + RalewayRegular { + anchors.verticalCenter: parent.verticalCenter; + width: margins.sizeText + margins.sizeLevel; + anchors.left: parent.left; + anchors.leftMargin: margins.sizeCheckBox; + size: 22; + color: hifi.colors.white; + text: qsTr("Noise Reduction"); + } + } + + Item { + id: noiseReductionSwitches; + x: 2 * margins.paddings; + width: parent.width; + // switch heights + 2 * top margins + height: (root.switchHeight) * 5 + 48; + anchors.top: noiseReductionHeader.bottom; + anchors.topMargin: 0; + + Item { + id: noiseReductionSwitchContainer; + x: margins.paddings; + width: parent.width / 2; + height: parent.height; + anchors.top: parent.top; + anchors.left: parent.left; + + HifiControlsUit.Switch { + id: acousticEchoCancellationSwitch; + height: root.switchHeight; + switchWidth: root.switchWidth; + anchors.top: noiseReductionSwitchContainer.top + anchors.topMargin: 24 + anchors.left: parent.left + labelTextOn: "Echo Cancellation"; + labelTextSize: 16; + backgroundOnColor: "#E3E3E3"; + checked: AudioScriptingInterface.acousticEchoCancellation; + onCheckedChanged: { + AudioScriptingInterface.acousticEchoCancellation = checked; + checked = Qt.binding(function () { return AudioScriptingInterface.acousticEchoCancellation; }); + } + } + + HifiControlsUit.Switch { + id: noiseReductionSwitch; + height: root.switchHeight; + switchWidth: root.switchWidth; + anchors.top: acousticEchoCancellationSwitch.bottom; + anchors.topMargin: 24 + anchors.left: parent.left + labelTextOn: "Noise Reduction"; + labelTextSize: 16; + backgroundOnColor: "#E3E3E3"; + checked: AudioScriptingInterface.noiseReduction; + onCheckedChanged: { + AudioScriptingInterface.noiseReduction = checked; + checked = Qt.binding(function () { return AudioScriptingInterface.noiseReduction; }); // restore binding + } + } + + HifiControlsUit.Switch { + id: noiseReductionAutomaticSwitch; + height: root.switchHeight; + switchWidth: root.switchWidth; + anchors.top: noiseReductionSwitch.bottom; + anchors.topMargin: 24; + anchors.left: parent.left; + labelTextOn: "Manual Noise Reduction"; + labelTextSize: 16; + backgroundOnColor: "#E3E3E3"; + checked: !AudioScriptingInterface.noiseReductionAutomatic; + visible: AudioScriptingInterface.noiseReduction; + onCheckedChanged: { + AudioScriptingInterface.noiseReductionAutomatic = !checked; + checked = Qt.binding(function () { return !AudioScriptingInterface.noiseReductionAutomatic; }); // restore binding + } + } + } + } + + Item { + id: noiseReductionThresholdContainer + x: margins.paddings; + anchors.top: noiseReductionSwitches.bottom; + anchors.topMargin: 16; + width: parent.width - margins.paddings * 2; + height: avatarGainSliderTextMetrics.height + 10; + visible: AudioScriptingInterface.noiseReduction && !AudioScriptingInterface.noiseReductionAutomatic; + + HifiControlsUit.Slider { + id: noiseReductionThresholdSlider + anchors.right: parent.right + height: noiseReductionThresholdSliderTextMetrics.height + width: 200 + minimumValue: 0.0 + maximumValue: 1.0 + stepSize: 0.05 + value: AudioScriptingInterface.getNoiseReductionThreshold() + onValueChanged: { + updateNoiseReductionThresholdFromQML(value); + } + onPressedChanged: { + if (!pressed) { + updateNoiseReductionThresholdFromQML(value); + } + } + + MouseArea { + anchors.fill: parent + onWheel: { + // Do nothing. + } + onDoubleClicked: { + noiseReductionThresholdSlider.value = 0.0; + } + onPressed: { + // Pass through to Slider + mouse.accepted = false; + } + onReleased: { + // the above mouse.accepted seems to make this + // never get called, nonetheless... + mouse.accepted = false; + } + } + } + TextMetrics { + id: noiseReductionThresholdSliderTextMetrics + text: noiseReductionThresholdSliderText.text + font: noiseReductionThresholdSliderText.font + } + RalewayRegular { + // The slider for my card is special, it controls the master gain + id: noiseReductionThresholdSliderText; + text: "Audio input threshold"; + size: 16; + anchors.left: parent.left; + color: hifi.colors.white; + horizontalAlignment: Text.AlignLeft; + verticalAlignment: Text.AlignTop; + } + + Item { + id: noisePeak + anchors.right: parent.right + anchors.rightMargin: 5; + anchors.top: noiseReductionThresholdSlider.bottom; + + width: noiseReductionThresholdSlider.width - 10; + height: 8; + + Text { + id: status; + + anchors { + horizontalCenter: parent.horizontalCenter; + verticalCenter: parent.verticalCenter; + } + + visible: AudioScriptingInterface.muted; + color: "#E2334D"; + + text: "MUTED"; + font.pointSize: 10; + } + + Item { + id: noiseBar; + + property bool gated: false; + property var level: AudioScriptingInterface.inputLevel; + + width: parent.width; + height: parent.height; + + anchors { fill: parent } + + visible: !status.visible; + + function onNoiseGateOpened() { + noiseBar.gated = false; + } + + function onNoiseGateClosed() { + noiseBar.gated = true; + } + + function onInputLevelChanged(level) { + noiseBar.level = level; + } + + Component.onCompleted: { + AudioScriptingInterface.noiseGateOpened.connect(onNoiseGateOpened); + AudioScriptingInterface.noiseGateClosed.connect(onNoiseGateClosed); + AudioScriptingInterface.inputLevelChanged.connect(onInputLevelChanged); + } + + Component.onDestruction: { + AudioScriptingInterface.noiseGateOpened.disconnect(onNoiseGateOpened); + AudioScriptingInterface.noiseGateClosed.disconnect(onNoiseGateClosed); + AudioScriptingInterface.inputLevelChanged.disconnect(onInputLevelChanged); + } + + Rectangle { // base + radius: 4; + anchors { fill: parent } + color: colors.gutter; + } + + Rectangle { // noiseMask + id: noiseMask; + width: parent.width * noiseBar.level; + radius: 5; + anchors { + bottom: parent.bottom; + bottomMargin: 0; + top: parent.top; + topMargin: 0; + left: parent.left; + leftMargin: 0; + } + } + + LinearGradient { + anchors { fill: noiseMask } + source: noiseMask + start: Qt.point(0, 0); + end: Qt.point(noiseBar.width, 0); + gradient: Gradient { + GradientStop { + position: 0; + color: noiseBar.gated ? "#E2334D" : "#39A38F"; + } + GradientStop { + position: 1; + color: noiseBar.gated ? "#E2334D" : "#39A38F"; + } + } + } + } + } + } + + Separator { + id: thirdSeparator; + anchors.top: noiseReductionThresholdContainer.bottom; + anchors.topMargin: 14; + } Item { id: inputDeviceHeader x: margins.paddings; width: parent.width - margins.paddings*2; height: 36; - anchors.top: secondSeparator.bottom; + anchors.top: thirdSeparator.bottom; anchors.topMargin: 10; HiFiGlyphs { @@ -597,19 +839,19 @@ Rectangle { } } AudioControls.InputPeak { - id: inputLevel - anchors.right: parent.right - peak: model.peak; - anchors.verticalCenter: parent.verticalCenter - visible: ((bar.currentIndex === 1 && isVR) || - (bar.currentIndex === 0 && !isVR)) && - AudioScriptingInterface.devices.input.peakValuesAvailable; + id: inputLevel + anchors.right: parent.right + peak: model.peak; + anchors.verticalCenter: parent.verticalCenter + visible: ((bar.currentIndex === 1 && isVR) || + (bar.currentIndex === 0 && !isVR)) && + AudioScriptingInterface.devices.input.peakValuesAvailable; } } } Separator { - id: thirdSeparator; + id: fourthSeparator; anchors.top: inputView.bottom; anchors.topMargin: 10; } @@ -617,7 +859,7 @@ Rectangle { Item { id: outputDeviceHeader; anchors.topMargin: 10; - anchors.top: thirdSeparator.bottom; + anchors.top: fourthSeparator.bottom; x: margins.paddings; width: parent.width - margins.paddings*2 height: 36 @@ -684,4 +926,4 @@ Rectangle { } } } -} \ No newline at end of file +} 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/resources/serverless/Models/Planter.glb b/interface/resources/serverless/Models/Planter.glb new file mode 100644 index 0000000000..7e575d0ddf Binary files /dev/null and b/interface/resources/serverless/Models/Planter.glb differ diff --git a/interface/resources/serverless/Models/Stands.fbx b/interface/resources/serverless/Models/Stands.fbx new file mode 100644 index 0000000000..ac5b2cafda Binary files /dev/null and b/interface/resources/serverless/Models/Stands.fbx differ diff --git a/interface/resources/serverless/Models/Trees1.glb b/interface/resources/serverless/Models/Trees1.glb new file mode 100644 index 0000000000..23c66c6c05 Binary files /dev/null and b/interface/resources/serverless/Models/Trees1.glb differ diff --git a/interface/resources/serverless/Models/VircadiaLogo.fbx b/interface/resources/serverless/Models/VircadiaLogo.fbx new file mode 100644 index 0000000000..78de8d27cd Binary files /dev/null and b/interface/resources/serverless/Models/VircadiaLogo.fbx differ diff --git a/interface/resources/serverless/Models/bowl2.fbx b/interface/resources/serverless/Models/bowl2.fbx new file mode 100644 index 0000000000..0f3d0048b2 Binary files /dev/null and b/interface/resources/serverless/Models/bowl2.fbx differ diff --git a/interface/resources/serverless/Models/dome2.glb b/interface/resources/serverless/Models/dome2.glb new file mode 100644 index 0000000000..0069f88f54 Binary files /dev/null and b/interface/resources/serverless/Models/dome2.glb differ diff --git a/interface/resources/serverless/Models/dome2_glass.glb b/interface/resources/serverless/Models/dome2_glass.glb new file mode 100644 index 0000000000..757bbeb9d5 Binary files /dev/null and b/interface/resources/serverless/Models/dome2_glass.glb differ diff --git a/interface/resources/serverless/Models/mirror_without_backface.baked.fbx b/interface/resources/serverless/Models/mirror_without_backface.baked.fbx new file mode 100644 index 0000000000..83f9de79b9 Binary files /dev/null and b/interface/resources/serverless/Models/mirror_without_backface.baked.fbx differ diff --git a/interface/resources/serverless/Models/seagull-ANI.fbx b/interface/resources/serverless/Models/seagull-ANI.fbx new file mode 100644 index 0000000000..9bb180f3c4 Binary files /dev/null and b/interface/resources/serverless/Models/seagull-ANI.fbx differ diff --git a/interface/resources/serverless/Models/temple5.glb b/interface/resources/serverless/Models/temple5.glb new file mode 100644 index 0000000000..08a10975ac Binary files /dev/null and b/interface/resources/serverless/Models/temple5.glb differ diff --git a/interface/resources/serverless/Scripts/materialSequencer.js b/interface/resources/serverless/Scripts/materialSequencer.js new file mode 100644 index 0000000000..998a8759e6 --- /dev/null +++ b/interface/resources/serverless/Scripts/materialSequencer.js @@ -0,0 +1,59 @@ +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// 2020 Silverfish. +//material sequencer, put on a material entity (server script) to make it iterate through discrete steps of X UV offset. + +/*UserData: +{ + "verticalOffset": 0, + "segments": 16, + "updateInterval": 250 +} +*/ + +(function() { + var DEFAULT_VERTICAL_OFFSET = 0.0; + var DEFAULT_HORIZONTAL_SPEED = 1; + var DEFAULT_UPDATE_INTERVAL = 1000; + var DEFAULT_SEGMENTS = 16; + + var self = this; + var _entityID; + this.preload = function(entityID) { + _entityID = entityID; + var verticalOffset = DEFAULT_VERTICAL_OFFSET; + var updateInterval = DEFAULT_UPDATE_INTERVAL; + var moveDistance = 1 / DEFAULT_SEGMENTS; + var verticalOffset = DEFAULT_VERTICAL_OFFSET; + var oldPosition = 0; + var currentPosition = 0; + var userData = JSON.parse(Entities.getEntityProperties(_entityID, ["userData"]).userData); + if (userData !== undefined) { + if (userData.segments !== undefined) { + moveDistance = 1 / userData.segments; + } + if (userData.verticalOffset !== undefined) { + verticalOffset = userData.verticalOffset; + } + if (userData.updateInterval !== undefined) { + updateInterval = userData.updateInterval; + } + } + + self.intervalID = Script.setInterval(function() { + if(currentPosition >= 1){ + currentPosition = 0; + oldPosition = 0; + } + + Entities.editEntity(_entityID, { materialMappingPos: { x: currentPosition, y: verticalOffset}}); + // print("current Pos: " + currentPosition); + currentPosition = oldPosition + moveDistance; + oldPosition = currentPosition; + }, updateInterval); + }; + + this.unload = function() { + Script.clearInterval(self.intervalID); + } +}); \ No newline at end of file diff --git a/interface/resources/serverless/Scripts/mirrorClient.js b/interface/resources/serverless/Scripts/mirrorClient.js new file mode 100644 index 0000000000..9b917668cd --- /dev/null +++ b/interface/resources/serverless/Scripts/mirrorClient.js @@ -0,0 +1,182 @@ +// +// mirrorClient.js +// +// Created by Patrick Manalich +// Edited by Rebecca Stankus on 8/30/17. +// Edited by David Back on 11/17/17. +// Edited by Anna Brewer on 7/12/19. +// Copyright 2017 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +// Attach `mirrorClient.js` to a box entity whose z dimension is very small, +// and whose x and y dimensions are up to you. See comments in `mirrorReflection.js` +// for more information about the mirror on/off zone. + +"use strict"; + +(function () { // BEGIN LOCAL SCOPE + + // VARIABLES + /* globals utils, Render */ + var _this = this; + var MAX_MIRROR_RESOLUTION_SIDE_PX = 960; // The max pixel resolution of the long side of the mirror + var ZERO_ROT = { w: 1, x: 0, y: 0, z: 0 }; // Constant quaternion for a rotation of 0 + var FAR_CLIP_DISTANCE = 16; // The far clip distance for the spectator camera when the mirror is on + var mirrorLocalEntityID = false; // The entity ID of the local entity that displays the mirror reflection + var mirrorLocalEntityRunning; // True if mirror local entity is reflecting, false otherwise + var mirrorLocalEntityOffset = 0.01; // The distance between the center of the mirror and the mirror local entity + var spectatorCameraConfig = Render.getConfig("SecondaryCamera"); // Render configuration for the spectator camera + var lastDimensions = { x: 0, y: 0 }; // The previous dimensions of the mirror + var previousFarClipDistance; // Store the specator camera's previous far clip distance that we override for the mirror + + // LOCAL FUNCTIONS + function isPositionInsideBox(position, boxProperties) { + var localPosition = Vec3.multiplyQbyV(Quat.inverse(boxProperties.rotation), + Vec3.subtract(MyAvatar.position, boxProperties.position)); + var halfDimensions = Vec3.multiply(boxProperties.dimensions, 0.5); + return -halfDimensions.x <= localPosition.x && + halfDimensions.x >= localPosition.x && + -halfDimensions.y <= localPosition.y && + halfDimensions.y >= localPosition.y && + -halfDimensions.z <= localPosition.z && + halfDimensions.z >= localPosition.z; + } + + // When x or y dimensions of the mirror change - reset the resolution of the + // spectator camera and edit the mirror local entity to adjust for the new dimensions + function updateMirrorDimensions(forceUpdate) { + + if (!mirrorLocalEntityID) { + return; + } + + if (mirrorLocalEntityRunning) { + var newDimensions = Entities.getEntityProperties(_this.entityID, 'dimensions').dimensions; + + if (forceUpdate === true || (newDimensions.x != lastDimensions.x || newDimensions.y != lastDimensions.y)) { + var mirrorResolution = _this.calculateMirrorResolution(newDimensions); + spectatorCameraConfig.resetSizeSpectatorCamera(mirrorResolution.x, mirrorResolution.y); + Entities.editEntity(mirrorLocalEntityID, { + dimensions: { + x: (Math.max(newDimensions.x, newDimensions.y)), + y: (Math.max(newDimensions.x, newDimensions.y)), + z: 0 + } + }); + } + lastDimensions = newDimensions; + } + } + + // Takes in an mirror scalar number which is used for the index of "halfDimSigns" that is needed to adjust the mirror + // local entity's position. Deletes and re-adds the mirror local entity so the url and position are updated. + function createMirrorLocalEntity() { + + if (mirrorLocalEntityID) { + Entities.deleteEntity(mirrorLocalEntityID); + mirrorLocalEntityID = false; + } + + if (mirrorLocalEntityRunning) { + mirrorLocalEntityID = Entities.addEntity({ + type: "Image", + name: "mirrorLocalEntity", + imageURL: "resource://spectatorCameraFrame", + emissive: true, + parentID: _this.entityID, + alpha: 1, + localPosition: { + x: 0, + y: 0, + z: mirrorLocalEntityOffset + }, + localRotation: Quat.fromPitchYawRollDegrees(0, 0, 180), + isVisibleInSecondaryCamera: false + }, "local"); + + updateMirrorDimensions(true); + } + + } + + _this.calculateMirrorResolution = function(entityDimensions) { + var mirrorResolutionX, mirrorResolutionY; + if (entityDimensions.x > entityDimensions.y) { + mirrorResolutionX = MAX_MIRROR_RESOLUTION_SIDE_PX; + mirrorResolutionY = Math.round(mirrorResolutionX * entityDimensions.y / entityDimensions.x); + } else { + mirrorResolutionY = MAX_MIRROR_RESOLUTION_SIDE_PX; + mirrorResolutionX = Math.round(mirrorResolutionY * entityDimensions.x / entityDimensions.y); + } + + var resolution = { + "x": mirrorResolutionX, + "y": mirrorResolutionY + }; + + return resolution; + }; + + // Sets up spectator camera to render the mirror, calls 'createMirrorLocalEntity' once to set up + // mirror local entity, then connects 'updateMirrorDimensions' to update dimension changes + _this.mirrorLocalEntityOn = function(onPreload) { + if (!mirrorLocalEntityRunning) { + if (!spectatorCameraConfig.attachedEntityId) { + mirrorLocalEntityRunning = true; + spectatorCameraConfig.mirrorProjection = true; + spectatorCameraConfig.attachedEntityId = _this.entityID; + previousFarClipDistance = spectatorCameraConfig.farClipPlaneDistance; + spectatorCameraConfig.farClipPlaneDistance = FAR_CLIP_DISTANCE; + var entityProperties = Entities.getEntityProperties(_this.entityID, ['dimensions']); + var mirrorEntityDimensions = entityProperties.dimensions; + var initialResolution = _this.calculateMirrorResolution(mirrorEntityDimensions); + spectatorCameraConfig.resetSizeSpectatorCamera(initialResolution.x, initialResolution.y); + spectatorCameraConfig.enableSecondaryCameraRenderConfigs(true); + createMirrorLocalEntity(); + Script.update.connect(updateMirrorDimensions); + } else { + print("Cannot turn on mirror if spectator camera is already in use"); + } + } + }; + + // Resets spectator camera, deletes the mirror local entity, and disconnects 'updateMirrorDimensions' + _this.mirrorLocalEntityOff = function() { + if (mirrorLocalEntityRunning) { + spectatorCameraConfig.enableSecondaryCameraRenderConfigs(false); + spectatorCameraConfig.mirrorProjection = false; + spectatorCameraConfig.attachedEntityId = null; + spectatorCameraConfig.farClipPlaneDistance = previousFarClipDistance; + if (mirrorLocalEntityID) { + Entities.deleteEntity(mirrorLocalEntityID); + mirrorLocalEntityID = false; + } + Script.update.disconnect(updateMirrorDimensions); + mirrorLocalEntityRunning = false; + } + }; + + // ENTITY FUNCTIONS + _this.preload = function(entityID) { + _this.entityID = entityID; + mirrorlocalEntityRunning = false; + + // If avatar is already inside the mirror zone at the time preload is called then turn on the mirror + var children = Entities.getChildrenIDs(_this.entityID); + var childZero = Entities.getEntityProperties(children[0]); + if (isPositionInsideBox(MyAvatar.position, { + position: childZero.position, + rotation: childZero.rotation, + dimensions: childZero.dimensions + })) { + _this.mirrorLocalEntityOn(true); + } + }; + + // Turn off mirror on unload + _this.unload = function(entityID) { + _this.mirrorLocalEntityOff(); + }; +}); diff --git a/interface/resources/serverless/Scripts/mirrorReflection.js b/interface/resources/serverless/Scripts/mirrorReflection.js new file mode 100644 index 0000000000..11f4f0781d --- /dev/null +++ b/interface/resources/serverless/Scripts/mirrorReflection.js @@ -0,0 +1,32 @@ +// +// mirrorReflection.js +// +// Created by Rebecca Stankus on 8/30/17. +// Copyright 2017 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +// Attach `mirrorReflection.js` to a zone entity that is parented to +// the box entity whose Script is `mirrorClient.js`. +// When a user enters this zone, the mirror will turn on. +// When a user leaves this zone, the mirror will turn off. + +(function () { + var mirrorID, reflectionAreaID; + // get id of reflection area and mirror + this.preload = function(entityID) { + reflectionAreaID = entityID; + mirrorID = Entities.getEntityProperties(reflectionAreaID, 'parentID').parentID; + }; + + // when avatar enters reflection area, begin reflecting + this.enterEntity = function(entityID){ + Entities.callEntityMethod(mirrorID, 'mirrorLocalEntityOn'); + }; + + // when avatar leaves reflection area, stop reflecting + this.leaveEntity = function (entityID) { + Entities.callEntityMethod(mirrorID, 'mirrorLocalEntityOff'); + }; +}); diff --git a/interface/resources/serverless/Scripts/portal.js b/interface/resources/serverless/Scripts/portal.js new file mode 100644 index 0000000000..0542e74796 --- /dev/null +++ b/interface/resources/serverless/Scripts/portal.js @@ -0,0 +1,47 @@ +// +// portal.js +// Created by Zach Fox on 2019-05-23 +// Copyright 2019 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html + +(function () { + var Portal = function() {}; + + + Portal.prototype = { + enterEntity: function (id) { + var properties = Entities.getEntityProperties(id, ["userData"]); + var userData; + + try { + userData = JSON.parse(properties.userData); + } catch (e) { + console.error("Error parsing userData: ", e); + } + + if (userData) { + if (userData.destination) { + var destination = userData.destination; + + if (userData.destination.indexOf("bookmark:") > -1) { + var bookmarkName = userData.destination.replace("bookmark:", ""); + destination = LocationBookmarks.getAddress(bookmarkName); + } + + Window.location = destination; + } else { + console.log("Please specify `destination` inside this entity's `userData`!"); + return; + } + } else { + console.log("Please specify this entity's `userData`! See README.md for instructions."); + return; + } + } + }; + + + return new Portal(); +}); diff --git a/interface/resources/serverless/Scripts/soundEmitter.js b/interface/resources/serverless/Scripts/soundEmitter.js new file mode 100644 index 0000000000..504bd418f9 --- /dev/null +++ b/interface/resources/serverless/Scripts/soundEmitter.js @@ -0,0 +1,202 @@ +/* eslint-disable no-magic-numbers */ +// +// soundEmitter.js +// +// Created by Zach Fox on 2019-07-05 +// Copyright High Fidelity 2019 +// +// Licensed under the Apache 2.0 License +// See accompanying license file or http://apache.org/ +// + +(function() { + var that; + var SOUND_EMITTER_UPDATE_INTERVAL_MS = 500; + var DEFAULT_AUDIO_INJECTOR_OPTIONS = { + "position": { + "x": 0, + "y": 0, + "z": 0 + }, + "volume": 0.5, + "loop": false, + "localOnly": false + }; + + + var SoundEmitter = function() { + that = this; + that.entityID = false; + that.soundObjectURL = false; + that.soundObject = false; + that.audioInjector = false; + that.audioInjectorOptions = DEFAULT_AUDIO_INJECTOR_OPTIONS; + that.signalsConnected = {}; + that.soundEmitterUpdateInterval = false; + }; + + + SoundEmitter.prototype = { + preload: function(entityID) { + that.entityID = entityID; + + var properties = Entities.getEntityProperties(that.entityID, ["userData"]); + + var userData; + + try { + userData = JSON.parse(properties.userData); + } catch (e) { + console.error("Error parsing userData: ", e); + } + + if (userData) { + if (userData.soundURL && userData.soundURL.length > 0) { + that.handleNewSoundURL(userData.soundURL); + } else { + console.log("Please specify this entity's `userData`! See README.md for instructions."); + return; + } + } else { + console.log("Please specify this entity's `userData`! See README.md for instructions."); + return; + } + }, + + + clearCurrentSoundData: function() { + that.soundObjectURL = false; + + if (that.signalsConnected["soundObjectReady"]) { + that.soundObject.ready.disconnect(that.updateSoundEmitter); + that.signalsConnected["soundObjectReady"] = false; + } + + that.soundObject = false; + + if (that.audioInjector) { + if (that.audioInjector.playing) { + that.audioInjector.stop(); + } + + that.audioInjector = false; + } + + that.audioInjectorOptions = DEFAULT_AUDIO_INJECTOR_OPTIONS; + + if (that.soundEmitterUpdateInterval) { + Script.clearInterval(that.soundEmitterUpdateInterval); + that.soundEmitterUpdateInterval = false; + } + }, + + + unload: function() { + that.clearCurrentSoundData(); + }, + + + handleNewSoundURL: function(newSoundURL) { + that.clearCurrentSoundData(); + + that.soundObjectURL = newSoundURL; + that.soundObject = SoundCache.getSound(that.soundObjectURL); + + if (that.soundObject.downloaded) { + that.updateSoundEmitter(); + } else { + that.soundObject.ready.connect(that.updateSoundEmitter); + that.signalsConnected["soundObjectReady"] = true; + } + }, + + + positionChanged: function(newPos) { + return (newPos.x !== that.audioInjectorOptions.position.x || + newPos.y !== that.audioInjectorOptions.position.y || + newPos.z !== that.audioInjectorOptions.position.z); + }, + + + updateSoundEmitter: function() { + var properties = Entities.getEntityProperties(that.entityID, ["userData", "position", "script", "serverScripts"]); + + var userData; + + try { + userData = JSON.parse(properties.userData); + } catch (e) { + console.error("Error parsing userData: ", e); + } + + var optionsChanged = false; + var shouldRestartPlayback = false; + var newPosition = properties.position; + + if (userData) { + if (userData.soundURL && userData.soundURL.length > 0 && userData.soundURL !== that.soundObjectURL) { + console.log("Sound Emitter: User put a new sound URL into `userData`! Resetting..."); + that.handleNewSoundURL(userData.soundURL); + return; + } + + if (typeof(userData.volume) !== "undefined" && !isNaN(userData.volume) && userData.volume !== that.audioInjectorOptions.volume) { + optionsChanged = true; + that.audioInjectorOptions.volume = userData.volume; + } + + if (typeof(userData.shouldLoop) !== "undefined" && userData.shouldLoop !== that.audioInjectorOptions.shouldLoop) { + optionsChanged = true; + + if (!that.audioInjectorOptions.loop && userData.shouldLoop && that.audioInjector && !that.audioInjector.playing) { + shouldRestartPlayback = true; + } + + that.audioInjectorOptions.loop = userData.shouldLoop; + } + + if (typeof(userData.positionOverride) !== "undefined" && !isNaN(userData.positionOverride.x) && + !isNaN(userData.positionOverride.y) && !isNaN(userData.positionOverride.z)) { + newPosition = userData.positionOverride; + } + } else { + console.log("Please specify this entity's `userData`! See README.md for instructions."); + that.clearCurrentSoundData(); + return; + } + + var localOnly = that.audioInjectorOptions.localOnly; + // If this script is attached as a client entity script... + if (properties.script.indexOf("soundEmitter.js") > -1) { + // ... Make sure that the audio injector IS local only. + localOnly = true; + // Else if this script is attached as a client server script... + } else if (properties.serverScripts.indexOf("soundEmitter.js") > -1) { + // ... Make sure that the audio injector IS NOT local only. + localOnly = false; + } + if (localOnly !== that.audioInjectorOptions.localOnly) { + optionsChanged = true; + that.audioInjectorOptions.localOnly = localOnly; + } + + if (that.positionChanged(newPosition)) { + optionsChanged = true; + that.audioInjectorOptions["position"] = newPosition; + } + + if (!that.audioInjector || shouldRestartPlayback) { + that.audioInjector = Audio.playSound(that.soundObject, that.audioInjectorOptions); + } else if (optionsChanged) { + that.audioInjector.setOptions(that.audioInjectorOptions); + } + + if (!that.soundEmitterUpdateInterval) { + that.soundEmitterUpdateInterval = Script.setInterval(that.updateSoundEmitter, SOUND_EMITTER_UPDATE_INTERVAL_MS); + } + } + }; + + + return new SoundEmitter(); +}); diff --git a/interface/resources/serverless/Scripts/wizardLoader.js b/interface/resources/serverless/Scripts/wizardLoader.js new file mode 100644 index 0000000000..8d28b581cc --- /dev/null +++ b/interface/resources/serverless/Scripts/wizardLoader.js @@ -0,0 +1,77 @@ +'use strict'; + +// +// wizardLoader.js +// +// Created by Kalila L. on Feb 19 2021. +// Copyright 2021 Vircadia contributors. +// +// This script is used to load the onboarding wizard at the location of the entity it's on. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +(function() { + var CONFIG_WIZARD_WEB_URL = 'https://cdn-1.vircadia.com/us-e-1/DomainContent/Tutorial/Apps/configWizard/dist/index.html'; + + var loaderEntityID; + var configWizardEntityID; + + function onWebAppEventReceived(sendingEntityID, event) { + if (sendingEntityID === configWizardEntityID) { + var eventJSON = JSON.parse(event); + + if (eventJSON.command === 'first-run-wizard-ready') { + var objectToSend = { + command: 'script-to-web-initialize', + data: { + performancePreset: Performance.getPerformancePreset(), + refreshRateProfile: Performance.getRefreshRateProfile(), + displayName: MyAvatar.displayName + } + }; + + Entities.emitScriptEvent(configWizardEntityID, JSON.stringify(objectToSend)); + } + + if (eventJSON.command === 'complete-wizard') { + Performance.setPerformancePreset(eventJSON.data.performancePreset); + Performance.setRefreshRateProfile(eventJSON.data.refreshRateProfile); + MyAvatar.displayName = eventJSON.data.displayName; + + Entities.deleteEntity(configWizardEntityID); + Entities.webEventReceived.disconnect(onWebAppEventReceived); + } + } + } + + this.preload = function (entityID) { + loaderEntityID = entityID; + var loaderEntityProps = Entities.getEntityProperties(loaderEntityID, ['position', 'rotation']); + + configWizardEntityID = Entities.addEntity({ + type: 'Web', + sourceUrl: CONFIG_WIZARD_WEB_URL, + maxFPS: 60, + dpi: 20, + useBackground: false, + grab: { + grabbable: false + }, + position: loaderEntityProps.position, + rotation: loaderEntityProps.rotation, + dimensions: { x: 1.4, y: 0.75, z: 0 } + }, 'local'); + + Entities.webEventReceived.connect(onWebAppEventReceived); + } + + this.unload = function () { + if (configWizardEntityID) { + Entities.deleteEntity(configWizardEntityID); + Entities.webEventReceived.disconnect(onWebAppEventReceived); + } + } + +}) diff --git a/interface/resources/serverless/Sounds/468407__onderwish__sci-fi-survival-dreamscape.mp3 b/interface/resources/serverless/Sounds/468407__onderwish__sci-fi-survival-dreamscape.mp3 new file mode 100644 index 0000000000..218cc967b3 Binary files /dev/null and b/interface/resources/serverless/Sounds/468407__onderwish__sci-fi-survival-dreamscape.mp3 differ diff --git a/interface/resources/serverless/Textures/default_particle.png b/interface/resources/serverless/Textures/default_particle.png new file mode 100644 index 0000000000..6c781c824b Binary files /dev/null and b/interface/resources/serverless/Textures/default_particle.png differ diff --git a/interface/resources/serverless/Textures/galaxySkybox.JPG b/interface/resources/serverless/Textures/galaxySkybox.JPG new file mode 100644 index 0000000000..e3ff7a4cf6 Binary files /dev/null and b/interface/resources/serverless/Textures/galaxySkybox.JPG differ diff --git a/interface/resources/serverless/Textures/galaxySkybox.png b/interface/resources/serverless/Textures/galaxySkybox.png new file mode 100644 index 0000000000..c7d9bf6d68 Binary files /dev/null and b/interface/resources/serverless/Textures/galaxySkybox.png differ diff --git a/interface/resources/serverless/Textures/gradient1.jpg b/interface/resources/serverless/Textures/gradient1.jpg new file mode 100644 index 0000000000..ef61b4dd97 Binary files /dev/null and b/interface/resources/serverless/Textures/gradient1.jpg differ diff --git a/interface/resources/serverless/tutorial.json b/interface/resources/serverless/tutorial.json index 17e7ea26e7..90d7e91aa3 100644 --- a/interface/resources/serverless/tutorial.json +++ b/interface/resources/serverless/tutorial.json @@ -1,19 +1,22 @@ { - "DataVersion": 0, - "Paths": { - "/": "/0.155245,-0.941538,23.9289/0,0.791589,0,0.611053" -}, + "DataVersion": 0, + "Paths": { + "/old": "/0.155245,-0.941538,23.9289/0,0.791589,0,0.611053", + "/": "/21.6727,1.02002,25.1977/0,0.999868,0,-0.016252" + + }, "Entities": [ - { + { "id": "{0a199807-4a83-4286-b09c-f21124627c3e}", "type": "Box", "name": "Config Wizard Loader", + "locked": true, "lastEdited": 1613737207915514, "visible": false, "position": { - "x": -1.2722, - "y": 0.4266, - "z": 24.2307 + "x": 21.8, + "y": 1.9, + "z": 28 }, "dimensions": { "x": 0.20000000298023224, @@ -21,10 +24,10 @@ "z": 0.20000000298023224 }, "rotation": { - "x": 0, - "y": -0.7660443782806396, - "z": 0, - "w": -0.6427876949310303 + "x": 3.5931313391301956e-7, + "y": -0.9996991753578186, + "z": 0.000014645980627392419, + "w": 0.024525845423340797 }, "created": 1613736996738696, "lastEditedBy": "{ff9b500e-e450-4127-b41f-1c42be16f71b}", @@ -41,7 +44,7 @@ "angularDamping": 0, "collisionless": true, "ignoreForCollisions": true, - "script": "https://cdn-1.vircadia.com/us-e-1/DomainContent/Tutorial/Apps/configWizard/dist/wizardLoader.js", + "script": "qrc:///serverless/Scripts/wizardLoader.js", "color": { "red": 0, "green": 180, @@ -55,717 +58,35 @@ "isFacingAvatar": false }, { - "id": "{eb485a2d-2040-42f6-a960-51c88e2434b9}", - "type": "Box", - "lastEdited": 1601257171039244, - "parentID": "{3deeadb3-5bab-4d1a-a8df-d3d4b192c76a}", - "visible": false, - "name": "Portal Cube", - "locked": true, - "userData": "{\"destination\":\"hifi://172.104.248.237:40102/154.572,-96.8437,-417.945/0,1,0,-1.52586e-05\"}", - "position": { - "x": -0.0005140304565429688, - "y": -0.3913555145263672, - "z": 0.0000209808349609375 - }, - "dimensions": { - "x": 1.5066394805908203, - "y": 2.504150629043579, - "z": 0.20000000298023224 - }, - "rotation": { - "x": -0.0000152587890625, - "y": -0.0000152587890625, - "z": -0.0000152587890625, - "w": 1 - }, - "created": 1601254455054086, - "lastEditedBy": "{70099fa7-d189-42dc-80a0-02c37d1942d1}", - "queryAACube": { - "x": -20.05035400390625, - "y": -6.776813983917236, - "z": -13.91693115234375, - "scale": 2.929288864135742 - }, - "grab": { - "grabbable": false, - "equippableLeftRotation": { - "x": -0.0000152587890625, - "y": -0.0000152587890625, - "z": -0.0000152587890625, - "w": 1 - }, - "equippableRightRotation": { - "x": -0.0000152587890625, - "y": -0.0000152587890625, - "z": -0.0000152587890625, - "w": 1 - } - }, - "damping": 0, - "angularDamping": 0, - "collisionMask": 0, - "collidesWith": "", - "script": "https://cdn-1.vircadia.com/us-e-1/DomainContent/Tutorial/Scripts/portal.js", - "color": { - "red": 0, - "green": 180, - "blue": 239 - }, - "shape": "Cube", - "clientOnly": false, - "avatarEntity": false, - "localEntity": false, - "faceCamera": false, - "isFacingAvatar": false -}, - { - "id": "{7624234a-c3f9-433c-9ffa-ce17894f1842}", - "type": "Text", - "lastEdited": 1601257171039090, - "parentID": "{3deeadb3-5bab-4d1a-a8df-d3d4b192c76a}", - "name": "Portal Sign", - "locked": true, - "position": { - "x": 0.0000591278076171875, - "y": 1.9068689346313477, - "z": -0.00003337860107421875 - }, - "dimensions": { - "x": 3.3015296459198, - "y": 0.511300265789032, - "z": 0.009999999776482582 - }, - "rotation": { - "x": -0.0000152587890625, - "y": -0.0000152587890625, - "z": -0.0000152587890625, - "w": 1 - }, - "created": 1601237788304107, - "lastEditedBy": "{70099fa7-d189-42dc-80a0-02c37d1942d1}", - "queryAACube": { - "x": -20.255495071411133, - "y": -4.684395790100098, - "z": -14.123543739318848, - "scale": 3.3409018516540527 - }, - "grab": { - "grabbable": false, - "equippableLeftRotation": { - "x": -0.0000152587890625, - "y": -0.0000152587890625, - "z": -0.0000152587890625, - "w": 1 - }, - "equippableRightRotation": { - "x": -0.0000152587890625, - "y": -0.0000152587890625, - "z": -0.0000152587890625, - "w": 1 - } - }, - "damping": 0, - "angularDamping": 0, - "collisionMask": 23, - "collidesWith": "static,dynamic,kinematic,otherAvatar,", - "billboardMode": "yaw", - "text": "Portal to The Hub", - "lineHeight": 0.4690000116825104, - "textColor": { - "red": 53, - "green": 184, - "blue": 240 - }, - "backgroundAlpha": 0, - "unlit": true, - "textEffect": "outline fill", - "textEffectColor": { - "red": 0, - "green": 0, - "blue": 0 - }, - "textEffectThickness": 0.36000001430511475, - "clientOnly": false, - "avatarEntity": false, - "localEntity": false, - "faceCamera": true, - "isFacingAvatar": false -}, - { - "id": "{4cc92ee0-e117-43f9-ae71-c6ff97979f11}", - "type": "Material", - "lastEdited": 1601257171040710, - "parentID": "{3deeadb3-5bab-4d1a-a8df-d3d4b192c76a}", - "parentJointIndex": 4, - "name": "portal_scroll (2)", - "locked": false, - "userData": "{\n \"verticalOffset\": 0,\n \"segments\": 64,\n \"updateInterval\": 200\n}", - "position": { - "x": -0.00000476837158203125, - "y": -0.5752763748168945, - "z": 0.2233133316040039 - }, - "rotation": { - "x": -0.0000457763671875, - "y": -0.0000152587890625, - "z": -0.0000152587890625, - "w": 1 - }, - "created": 1601249935956042, - "lastEditedBy": "{70099fa7-d189-42dc-80a0-02c37d1942d1}", - "queryAACube": { - "x": -23.118024826049805, - "y": -7.00716495513916, - "z": -14.539131164550781, - "scale": 6.618997573852539 - }, - "canCastShadow": false, - "primitiveMode": "lines", - "grab": { - "grabbable": false, - "equippableLeftRotation": { - "x": -0.0000152587890625, - "y": -0.0000152587890625, - "z": -0.0000152587890625, - "w": 1 - }, - "equippableRightRotation": { - "x": -0.0000152587890625, - "y": -0.0000152587890625, - "z": -0.0000152587890625, - "w": 1 - } - }, - "collisionMask": 23, - "collidesWith": "static,dynamic,kinematic,otherAvatar,", - "script": "https://cdn-1.vircadia.com/us-e-1/DomainContent/Tutorial/Scripts/materialSequencer.js", - "scriptTimestamp": 1601250646975, - "materialURL": "materialData", - "priority": 3, - "parentMaterialName": "[mat::move]", - "materialMappingPos": { - "x": 0.984375, - "y": 0 - }, - "materialData": "{\"materialVersion\":1,\"materials\":[{\"name\":\"baseMaterial2\",\"model\":\"hifi_pbr\",\"opacity\":0.8,\"albedo\":[1,1,1],\"roughness\":1,\"metallic\":0,\"emissive\":[0,0,0],\"scattering\":0,\"unlit\":false,\"emissiveMap\":\"https://cdn-1.vircadia.com/us-e-1/DomainContent/Tutorial/Images/gradient1.jpg\",\"albedoMap\":\"https://cdn-1.vircadia.com/us-e-1/DomainContent/Tutorial/Images/gradient1.jpg\",\"opacityMapMode\":\"OPACITY_MAP_BLEND\",\"cullFaceMode\":\"CULL_NONE\",\"defaultFallthrough\":false}]}", - "clientOnly": false, - "avatarEntity": false, - "localEntity": false, - "faceCamera": false, - "isFacingAvatar": false -}, - { - "id": "{d431d791-8f9d-42ba-8031-d94b1d8d8815}", + "id": "{b9444e0f-1cda-4ad3-80e5-9ef3bf0ec6cd}", "type": "Model", - "lastEdited": 1601258385755309, - "parentID": "{ee9b7ff6-97f0-4957-aea1-3b517b6e68b8}", - "locked": true, - "position": { - "x": -21.901264190673828, - "y": -4.0628180503845215, - "z": 4.366877555847168 - }, - "dimensions": { - "x": 5.791271686553955, - "y": 3.2263991832733154, - "z": 1.5121190547943115 - }, - "rotation": { - "x": -0.0001068115234375, - "y": -0.7046158313751221, - "z": -0.0001373291015625, - "w": 0.7095597982406616 - }, - "created": 1601076086837263, - "lastEditedBy": "{0ff4c9e5-fb36-4bdd-9fbc-b2ed60e1aa3b}", - "queryAACube": { - "x": -25.301368713378906, - "y": -8.470065116882324, - "z": 0.9665484428405762, - "scale": 6.799631118774414 - }, - "grab": { - "grabbable": false, - "equippableLeftRotation": { - "x": -0.0000152587890625, - "y": -0.0000152587890625, - "z": -0.0000152587890625, - "w": 1 - }, - "equippableRightRotation": { - "x": -0.0000152587890625, - "y": -0.0000152587890625, - "z": -0.0000152587890625, - "w": 1 - } - }, - "damping": 0, - "angularDamping": 0, - "shapeType": "simple-hull", - "modelURL": "https://cdn-1.vircadia.com/us-e-1/DomainContent/Tutorial/Models/controls_sign.fbx", - "blendshapeCoefficients": "{\n}\n", - "animation": { - "allowTranslation": false - }, - "clientOnly": false, - "avatarEntity": false, - "localEntity": false, - "faceCamera": false, - "isFacingAvatar": false -}, - { - "id": "{60bb4eb3-6fa6-47c2-a264-23a9b562fd20}", - "type": "Material", - "lastEdited": 1601257171043513, - "parentID": "{1a837deb-9f62-4d25-b027-b05bc092f7a5}", - "name": "canopy light material (2)", - "locked": true, - "position": { - "x": 0.8513965606689453, - "y": 0.9252982139587402, - "z": -1.2880910634994507 - }, - "rotation": { - "x": -0.0000152587890625, - "y": -0.0000152587890625, - "z": -0.0000152587890625, - "w": 1 - }, - "created": 1600724957561027, - "lastEditedBy": "{70099fa7-d189-42dc-80a0-02c37d1942d1}", - "queryAACube": { - "x": 10.290059089660645, - "y": -7.974443435668945, - "z": -21.87716293334961, - "scale": 5.676094055175781 - }, - "grab": { - "grabbable": false, - "equippableLeftRotation": { - "x": -0.0000152587890625, - "y": -0.0000152587890625, - "z": -0.0000152587890625, - "w": 1 - }, - "equippableRightRotation": { - "x": -0.0000152587890625, - "y": -0.0000152587890625, - "z": -0.0000152587890625, - "w": 1 - } - }, - "damping": 0, - "angularDamping": 0, - "materialURL": "materialData", - "priority": 1, - "parentMaterialName": "[mat::light material]", - "materialData": "{ \"materialVersion\": 1, \"materials\": [ { \"name\": \"untitled\", \"albedo\": [0.6352941176470588, 0.9647058823529412, 0.8980392156862745], \"metallic\": 0.001, \"roughness\": 0.5, \"opacity\": 1, \"emissive\": [1.154705882352941, 1.3323529411764705, 1.3205098039215686], \"scattering\": 0, \"unlit\": false, \"model\": \"hifi_pbr\" } ]}", - "clientOnly": false, - "avatarEntity": false, - "localEntity": false, - "faceCamera": false, - "isFacingAvatar": false -}, - { - "id": "{0735f399-0e78-4170-87c2-e1f30572ba04}", - "type": "Text", - "lastEdited": 1601257171043607, - "parentID": "{ee9b7ff6-97f0-4957-aea1-3b517b6e68b8}", - "name": "Mirror Sign", - "locked": true, - "position": { - "x": 20.39116668701172, - "y": -2.923142910003662, - "z": -8.373934745788574 - }, - "dimensions": { - "x": 1.7557624578475952, - "y": 0.6635230779647827, - "z": 0.009999999776482582 - }, - "rotation": { - "x": -0.0000457763671875, - "y": -0.5629816055297852, - "z": -0.0000457763671875, - "w": 0.8264439105987549 - }, - "created": 1601082108221117, - "lastEditedBy": "{70099fa7-d189-42dc-80a0-02c37d1942d1}", - "queryAACube": { - "x": 19.452810287475586, - "y": -4.870745658874512, - "z": -9.311684608459473, - "scale": 1.8769828081130981 - }, - "grab": { - "grabbable": false, - "equippableLeftRotation": { - "x": -0.0000152587890625, - "y": -0.0000152587890625, - "z": -0.0000152587890625, - "w": 1 - }, - "equippableRightRotation": { - "x": -0.0000152587890625, - "y": -0.0000152587890625, - "z": -0.0000152587890625, - "w": 1 - } - }, - "damping": 0, - "angularDamping": 0, - "text": "Mirror", - "lineHeight": 0.6470000147819519, - "textColor": { - "red": 0, - "green": 0, - "blue": 0 - }, - "backgroundAlpha": 0, - "unlit": true, - "textEffect": "outline fill", - "textEffectColor": { - "red": 94, - "green": 207, - "blue": 255 - }, - "textEffectThickness": 0.3400000035762787, - "clientOnly": false, - "avatarEntity": false, - "localEntity": false, - "faceCamera": false, - "isFacingAvatar": false -}, - { - "id": "{a4a586c6-b6f8-4b79-9ac9-76d6296e3ab8}", - "type": "Zone", - "lastEdited": 1601257171043415, - "parentID": "{ecf5857e-f1d5-411e-a8a1-919ab8f27ad8}", - "visible": false, - "name": "mirror_zone", - "locked": true, - "userData": "{\"grabbableKey\":{\"grabbable\":false},\"original\":{\"id\":\"{da1e2fcd-d69b-47d7-b861-25b31f1c7175}\"}}", - "position": { - "x": -0.01726818084716797, - "y": 0.2113490104675293, - "z": 1.704751968383789 - }, - "dimensions": { - "x": 2.8482747077941895, - "y": 3.153184413909912, - "z": 3.6725244522094727 - }, - "rotation": { - "x": -0.0161592960357666, - "y": 0.0000152587890625, - "z": -0.006424069404602051, - "w": 0.999847412109375 - }, - "created": 1601081037655929, - "lastEditedBy": "{70099fa7-d189-42dc-80a0-02c37d1942d1}", - "queryAACube": { - "x": 15.947319030761719, - "y": -7.93642520904541, - "z": -10.575695991516113, - "scale": 5.6162872314453125 - }, - "grab": { - "grabbable": false, - "equippableLeftRotation": { - "x": -0.0000152587890625, - "y": -0.0000152587890625, - "z": -0.0000152587890625, - "w": 1 - }, - "equippableRightRotation": { - "x": -0.0000152587890625, - "y": -0.0000152587890625, - "z": -0.0000152587890625, - "w": 1 - } - }, - "script": "https://cdn-1.vircadia.com/us-e-1/DomainContent/Tutorial/Scripts/mirrorReflection.js", - "scriptTimestamp": 1601084668318, - "shapeType": "box", - "clientOnly": false, - "avatarEntity": false, - "localEntity": false, - "faceCamera": false, - "isFacingAvatar": false -}, - { - "id": "{f2ac10e4-89f3-4125-bb8f-917e510394df}", - "type": "Box", - "lastEdited": 1601257171038745, - "name": "Sound Emitter", - "locked": true, - "userData": "{\"soundURL\":\"https://cdn-1.vircadia.com/us-e-1/DomainContent/Tutorial/Sounds/468407__onderwish__sci-fi-survival-dreamscape.mp3?dl=1\",\"shouldLoop\":true,\"volume\":0.18,\"refreshInterval\":100,\"grabbableKey\":{\"grabbable\":false}}", - "position": { - "x": 18.58538055419922, - "y": 5.378335952758789, - "z": 20.337299346923828 - }, - "dimensions": { - "x": 0.20000000298023224, - "y": 0.20000000298023224, - "z": 0.20000000298023224 - }, - "rotation": { - "x": -0.0000152587890625, - "y": -0.0000152587890625, - "z": -0.0000152587890625, - "w": 1 - }, - "created": 1601078881703340, - "lastEditedBy": "{70099fa7-d189-42dc-80a0-02c37d1942d1}", - "queryAACube": { - "x": 18.41217613220215, - "y": 5.2051310539245605, - "z": 20.164094924926758, - "scale": 0.3464101552963257 - }, - "grab": { - "grabbable": false, - "equippableLeftRotation": { - "x": -0.0000152587890625, - "y": -0.0000152587890625, - "z": -0.0000152587890625, - "w": 1 - }, - "equippableRightRotation": { - "x": -0.0000152587890625, - "y": -0.0000152587890625, - "z": -0.0000152587890625, - "w": 1 - } - }, - "damping": 0, - "angularDamping": 0, - "script": "https://cdn-1.vircadia.com/us-e-1/usefulUtilities/soundEmitter/soundEmitter.js", - "scriptTimestamp": 1601079357399, - "color": { - "red": 0, - "green": 180, - "blue": 239 - }, - "shape": "Cube", - "clientOnly": false, - "avatarEntity": false, - "localEntity": false, - "faceCamera": false, - "isFacingAvatar": false -}, - { - "id": "{698d7e54-ee5b-4005-bc9d-62840aa07c19}", - "type": "Model", - "lastEdited": 1601257171043706, - "locked": true, - "position": { - "x": 20.58482551574707, - "y": 3.3026206493377686, - "z": 22.10502052307129 - }, - "dimensions": { - "x": 0.9342527389526367, - "y": 0.8603132963180542, - "z": 0.47802668809890747 - }, - "rotation": { - "x": -0.0175631046295166, - "y": -0.4897993206977844, - "z": 0.030106067657470703, - "w": 0.8711223602294922 - }, - "created": 1594159515504117, - "lastEditedBy": "{70099fa7-d189-42dc-80a0-02c37d1942d1}", - "queryAACube": { - "x": 19.906320571899414, - "y": 2.624115467071533, - "z": 21.426515579223633, - "scale": 1.3570102453231812 - }, - "grab": { - "grabbable": false, - "equippableLeftRotation": { - "x": -0.0000152587890625, - "y": -0.0000152587890625, - "z": -0.0000152587890625, - "w": 1 - }, - "equippableRightRotation": { - "x": -0.0000152587890625, - "y": -0.0000152587890625, - "z": -0.0000152587890625, - "w": 1 - } - }, - "damping": 0, - "angularDamping": 0, - "shapeType": "simple-compound", - "modelURL": "https://cdn-1.vircadia.com/us-e-1/DomainContent/Tutorial/Models/seagull-ANI.fbx", - "blendshapeCoefficients": "{\n}\n", - "animation": { - "url": "https://cdn-1.vircadia.com/us-e-1/DomainContent/Tutorial/Models/seagull-ANI.fbx", - "allowTranslation": false, - "currentFrame": 68.07844543457031, - "running": true, - "lastFrame": 120 - }, - "clientOnly": false, - "avatarEntity": false, - "localEntity": false, - "faceCamera": false, - "isFacingAvatar": false -}, - { - "id": "{523b7462-9a49-4949-8d31-d84749cbab0a}", - "type": "Model", - "lastEdited": 1601257171038388, - "name": "Vircadia Sign", - "locked": true, - "position": { - "x": 40.31134796142578, - "y": 3.2890982627868652, - "z": 19.960262298583984 - }, - "dimensions": { - "x": 4.443090915679932, - "y": 0.7363157868385315, - "z": 0.16073395311832428 - }, - "rotation": { - "x": -0.0000152587890625, - "y": -0.7011978626251221, - "z": 0.0000152587890625, - "w": 0.7129777669906616 - }, - "created": 1600983484676932, - "lastEditedBy": "{70099fa7-d189-42dc-80a0-02c37d1942d1}", - "queryAACube": { - "x": 38.05807113647461, - "y": 1.0358200073242188, - "z": 17.70698356628418, - "scale": 4.506556510925293 - }, - "grab": { - "grabbable": false, - "equippableLeftRotation": { - "x": -0.0000152587890625, - "y": -0.0000152587890625, - "z": -0.0000152587890625, - "w": 1 - }, - "equippableRightRotation": { - "x": -0.0000152587890625, - "y": -0.0000152587890625, - "z": -0.0000152587890625, - "w": 1 - } - }, - "damping": 0, - "angularDamping": 0, - "modelURL": "https://cdn-1.vircadia.com/us-e-1/DomainContent/Tutorial/Models/VircadiaLogo.fbx", - "blendshapeCoefficients": "{\n}\n", - "animation": { - "allowTranslation": false - }, - "clientOnly": false, - "avatarEntity": false, - "localEntity": false, - "faceCamera": false, - "isFacingAvatar": false -}, - { - "id": "{1a837deb-9f62-4d25-b027-b05bc092f7a5}", - "type": "Model", - "lastEdited": 1601257171043086, - "name": "(2)", - "locked": true, - "description": "cyberpunk light building", - "position": { - "x": 32.089881896972656, - "y": 0.20440244674682617, - "z": 0 - }, - "dimensions": { - "x": 2.9088404178619385, - "y": 2.9556829929351807, - "z": 3.8756446838378906 - }, - "rotation": { - "x": -0.0000762939453125, - "y": -0.269459068775177, - "z": -0.0000152587890625, - "w": 0.9629815816879272 - }, - "created": 1600724957559377, - "lastEditedBy": "{70099fa7-d189-42dc-80a0-02c37d1942d1}", - "queryAACube": { - "x": 29.251834869384766, - "y": -2.6336443424224854, - "z": -2.8380467891693115, - "scale": 5.676093578338623 - }, - "grab": { - "grabbable": false, - "equippableLeftRotation": { - "x": -0.0000152587890625, - "y": -0.0000152587890625, - "z": -0.0000152587890625, - "w": 1 - }, - "equippableRightRotation": { - "x": -0.0000152587890625, - "y": -0.0000152587890625, - "z": -0.0000152587890625, - "w": 1 - } - }, - "damping": 0, - "angularDamping": 0, - "shapeType": "static-mesh", - "modelURL": "https://cdn-1.vircadia.com/us-e-1/DomainContent/Tutorial/Models/cyberpunk%20light%20building.fbx", - "blendshapeCoefficients": "{\n}\n", - "animation": { - "allowTranslation": false - }, - "clientOnly": false, - "avatarEntity": false, - "localEntity": false, - "faceCamera": false, - "isFacingAvatar": false -}, - { - "id": "{ecf5857e-f1d5-411e-a8a1-919ab8f27ad8}", - "type": "Model", - "lastEdited": 1601257171043259, + "lastEdited": 1617134731448079, "name": "mirror_reflectingPlane", "locked": true, "userData": "{\"grabbableKey\":{\"grabbable\":false,\"ignoreIK\":false},\"original\":{\"id\":\"{6291b4e5-0dcb-484c-9c11-fe47725a4ad8}\"}}", "position": { - "x": 38.92219543457031, - "y": 0, - "z": 11.933252334594727 + "x": 3.3984665870666504, + "y": 1.891787052154541, + "z": 20.900876998901367 }, "dimensions": { - "x": 1.846174716949463, - "y": 2.2880923748016357, + "x": 1.6291353702545166, + "y": 2.206333875656128, "z": 0.01092288363724947 }, "rotation": { - "x": -0.0001678466796875, - "y": 0.5556267499923706, - "z": 0.0009613037109375, - "w": -0.8314183354377747 + "x": -0.0000152587890625, + "y": -0.8816205263137817, + "z": 0.0000152587890625, + "w": -0.4719768166542053 }, - "created": 1601081037655824, - "lastEditedBy": "{70099fa7-d189-42dc-80a0-02c37d1942d1}", + "created": 1614198986204053, + "lastEditedBy": "{0b759026-5fea-494c-99de-ab6301e73d4c}", "queryAACube": { - "x": 37.45217514038086, - "y": -1.4700210094451904, - "z": 10.463231086730957, - "scale": 2.940042018890381 + "x": 2.0271434783935547, + "y": 0.5204638242721558, + "z": 19.52955436706543, + "scale": 2.7426464557647705 }, "grab": { "grabbable": false, @@ -787,9 +108,9 @@ "ignoreForCollisions": true, "collisionMask": 0, "collidesWith": "", - "script": "https://cdn-1.vircadia.com/us-e-1/DomainContent/Tutorial/Scripts/mirrorClient.js", + "script": "qrc:///serverless/Scripts/mirrorClient.js", "scriptTimestamp": 1601084665601, - "modelURL": "https://cdn-1.vircadia.com/us-e-1/DomainContent/Tutorial/Models/mirror_without_backface.baked.fbx", + "modelURL": "qrc:///serverless/Models/mirror_without_backface.baked.fbx", "blendshapeCoefficients": "{\n}\n", "clientOnly": false, "avatarEntity": false, @@ -798,10 +119,1285 @@ "isFacingAvatar": false }, { - "id": "{32132863-ae54-4d1b-95a9-d8e5fd7df066}", + "id": "{61e0e141-bb95-4e7a-a043-3f4f783e39f4}", + "type": "Text", + "lastEdited": 1617134727215565, + "locked": true, + "description": "mirror text", + "position": { + "x": 3.306519031524658, + "y": 4.0622100830078125, + "z": 20.931333541870117 + }, + "dimensions": { + "x": 3.2473599910736084, + "y": 0.6462407112121582, + "z": 0.009999999776482582 + }, + "rotation": { + "x": 0.0008392333984375, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 0.999969482421875 + }, + "created": 1614383649622836, + "lastEditedBy": "{0b759026-5fea-494c-99de-ab6301e73d4c}", + "queryAACube": { + "x": 1.6509922742843628, + "y": 2.4066834449768066, + "z": 19.275806427001953, + "scale": 3.311053514480591 + }, + "billboardMode": "yaw", + "grab": { + "grabbable": false, + "equippableLeftRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + }, + "equippableRightRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + } + }, + "damping": 0, + "angularDamping": 0, + "collisionMask": 23, + "collidesWith": "static,dynamic,kinematic,otherAvatar,", + "text": "Mirror", + "lineHeight": 0.6000000238418579, + "textColor": { + "red": 0, + "green": 0, + "blue": 0 + }, + "backgroundAlpha": 0, + "unlit": true, + "font": "Inconsolata", + "textEffect": "outline fill", + "textEffectColor": { + "red": 0, + "green": 208, + "blue": 255 + }, + "textEffectThickness": 0.30000001192092896, + "alignment": "center", + "clientOnly": false, + "avatarEntity": false, + "localEntity": false, + "faceCamera": true, + "isFacingAvatar": false +}, + { + "id": "{4b1ac4d3-325b-46a2-9c27-0e94ee1afcaf}", + "type": "Model", + "lastEdited": 1617140845328587, + "name": "Seagull", + "locked": true, + "position": { + "x": 23.798669815063477, + "y": 4.926492214202881, + "z": 10.381175994873047 + }, + "dimensions": { + "x": 0.9342527389526367, + "y": 0.8603132963180542, + "z": 0.47802668809890747 + }, + "rotation": { + "x": -0.017654716968536377, + "y": -0.4898908734321594, + "z": 0.030106067657470703, + "w": 0.8710917234420776 + }, + "created": 1614198986205195, + "lastEditedBy": "{7f097416-1c40-4cba-aa7c-6e20a7281823}", + "queryAACube": { + "x": 23.12016487121582, + "y": 4.247987270355225, + "z": 9.70267105102539, + "scale": 1.3570102453231812 + }, + "grab": { + "grabbable": false, + "equippableLeftRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + }, + "equippableRightRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + } + }, + "damping": 0, + "angularDamping": 0, + "shapeType": "simple-compound", + "modelURL": "qrc:///serverless/Models/seagull-ANI.fbx", + "blendshapeCoefficients": "{\n}\n", + "animation": { + "url": "qrc:///serverless/Models/seagull-ANI.fbx", + "allowTranslation": false, + "currentFrame": 99.81153869628906, + "running": true, + "lastFrame": 120 + }, + "clientOnly": false, + "avatarEntity": false, + "localEntity": false, + "faceCamera": false, + "isFacingAvatar": false +}, + { + "id": "{7c7f80be-4fa3-4615-86f3-5446c6737350}", + "type": "Box", + "lastEdited": 1617140739515673, + "parentID": "{6c76b816-5064-424c-84b2-dbb478e47d5d}", + "visible": false, + "name": "Sound Emitter", + "locked": true, + "userData": "{\"soundURL\":\"qrc:///serverless/Sounds/468407__onderwish__sci-fi-survival-dreamscape.mp3\",\"shouldLoop\":true,\"volume\":0.18,\"refreshInterval\":100,\"grabbableKey\":{\"grabbable\":false}}", + "position": { + "x": 0, + "y": 1.0455207824707031, + "z": 0 + }, + "dimensions": { + "x": 0.20000000298023224, + "y": 0.20000000298023224, + "z": 0.20000000298023224 + }, + "rotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + }, + "created": 1614198017837347, + "lastEditedBy": "{7f097416-1c40-4cba-aa7c-6e20a7281823}", + "queryAACube": { + "x": 28.069303512573242, + "y": 5.205089092254639, + "z": 26.711923599243164, + "scale": 0.3464101552963257 + }, + "grab": { + "grabbable": false, + "equippableLeftRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + }, + "equippableRightRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + } + }, + "damping": 0, + "angularDamping": 0, + "script": "qrc:///serverless/Scripts/soundEmitter.js", + "scriptTimestamp": 1601079357399, + "color": { + "red": 0, + "green": 180, + "blue": 239 + }, + "shape": "Cube", + "clientOnly": false, + "avatarEntity": false, + "localEntity": false, + "faceCamera": false, + "isFacingAvatar": false +}, + { + "id": "{0436152a-b188-4608-abe9-a3fb1c4b283d}", + "type": "Model", + "lastEdited": 1617140818158676, + "name": "Vircadia Sign", + "locked": true, + "position": { + "x": 43.52519226074219, + "y": 4.912969589233398, + "z": 8.236417770385742 + }, + "dimensions": { + "x": 4.443090915679932, + "y": 0.7363157868385315, + "z": 0.16073395311832428 + }, + "rotation": { + "x": -0.0000152587890625, + "y": -0.7019302845001221, + "z": 0.0000152587890625, + "w": 0.7122453451156616 + }, + "created": 1614198986205729, + "lastEditedBy": "{7f097416-1c40-4cba-aa7c-6e20a7281823}", + "queryAACube": { + "x": 41.271915435791016, + "y": 2.659691333770752, + "z": 5.983139514923096, + "scale": 4.506556510925293 + }, + "grab": { + "grabbable": false, + "equippableLeftRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + }, + "equippableRightRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + } + }, + "damping": 0, + "angularDamping": 0, + "modelURL": "qrc:///serverless/Models/VircadiaLogo.fbx", + "blendshapeCoefficients": "{\n}\n", + "animation": { + "allowTranslation": false + }, + "clientOnly": false, + "avatarEntity": false, + "localEntity": false, + "faceCamera": false, + "isFacingAvatar": false +}, + { + "id": "{06b826d4-5385-4c49-92c2-47e24f97b35a}", + "type": "Text", + "lastEdited": 1617134764395172, + "name": "(2)", + "locked": true, + "description": "mirror text", + "position": { + "x": 34.17714309692383, + "y": 4.050739288330078, + "z": 27.204530715942383 + }, + "dimensions": { + "x": 3.2473599910736084, + "y": 0.6462407112121582, + "z": 0.009999999776482582 + }, + "rotation": { + "x": 0.0008392333984375, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 0.999969482421875 + }, + "created": 1614453280539951, + "lastEditedBy": "{0b759026-5fea-494c-99de-ab6301e73d4c}", + "queryAACube": { + "x": 32.5216178894043, + "y": 2.3952126502990723, + "z": 25.54900360107422, + "scale": 3.311053514480591 + }, + "billboardMode": "yaw", + "grab": { + "grabbable": false, + "equippableLeftRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + }, + "equippableRightRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + } + }, + "damping": 0, + "angularDamping": 0, + "collisionMask": 23, + "collidesWith": "static,dynamic,kinematic,otherAvatar,", + "text": "Controls", + "lineHeight": 0.6000000238418579, + "textColor": { + "red": 0, + "green": 0, + "blue": 0 + }, + "backgroundAlpha": 0, + "unlit": true, + "font": "Inconsolata", + "textEffect": "outline fill", + "textEffectColor": { + "red": 0, + "green": 208, + "blue": 255 + }, + "textEffectThickness": 0.30000001192092896, + "alignment": "center", + "clientOnly": false, + "avatarEntity": false, + "localEntity": false, + "faceCamera": true, + "isFacingAvatar": false +}, + { + "id": "{159f2743-d862-47e3-9f27-5de062b09941}", + "type": "Material", + "lastEdited": 1617140810844450, + "parentID": "{0436152a-b188-4608-abe9-a3fb1c4b283d}", + "parentJointIndex": 0, + "name": "VClogo", + "locked": true, + "userData": "{\"verticalOffset\":0,\"segments\":16,\"updateInterval\":1000}", + "position": { + "x": -0.00001823902130126953, + "y": -0.0002636909484863281, + "z": 0.10145187377929688 + }, + "rotation": { + "x": 0.0012969970703125, + "y": 0.0000152587890625, + "z": 0.0000457763671875, + "w": 0.999969482421875 + }, + "created": 1614198986205783, + "lastEditedBy": "{7f097416-1c40-4cba-aa7c-6e20a7281823}", + "queryAACube": { + "x": 47.7151985168457, + "y": 1.0358200073242188, + "z": 24.254812240600586, + "scale": 4.506557464599609 + }, + "canCastShadow": false, + "grab": { + "grabbable": false, + "equippableLeftRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + }, + "equippableRightRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + } + }, + "collisionMask": 23, + "collidesWith": "static,dynamic,kinematic,otherAvatar,", + "scriptTimestamp": 1597610738986, + "materialURL": "materialData", + "priority": 3, + "parentMaterialName": "[mat::NeonTubes]", + "materialMappingPos": { + "x": 0.8125, + "y": 0 + }, + "materialData": "{\"materialVersion\":1,\"materials\":[{\"name\":\"baseMaterial2\",\"model\":\"hifi_pbr\",\"opacity\":1,\"albedo\":[0,0,0],\"roughness\":1,\"metallic\":0,\"emissive\":[2.3,2,2],\"scattering\":0,\"unlit\":false,\"opacityMapMode\":\"OPACITY_MAP_MASK\",\"cullFaceMode\":\"CULL_BACK\",\"defaultFallthrough\":false}]}", + "clientOnly": false, + "avatarEntity": false, + "localEntity": false, + "faceCamera": false, + "isFacingAvatar": false +}, +{ + "id": "{5b6443c5-ec22-4c8a-9581-85134ceb6856}", + "parentID": "{6c76b816-5064-424c-84b2-dbb478e47d5d}", + "type": "Model", + "name": "Bowl", + "locked": true, + "lastEdited": 1617218059378792, + "dimensions": { + "x": 1.7757656574249268, + "y": 1.2933320999145508, + "z": 1.7757654190063477 + }, + "rotation": { + "x": -0.000030517578125, + "y": -0.000030517578125, + "z": -0.000030517578125, + "w": 1 + }, + "created": 1617216882976266, + "lastEditedBy": "{f72b151a-b325-4c9f-805a-7a7a520f82f7}", + "position": { + "x": -0.00001823902130126953, + "y": -5.1002636909484863281, + "z": 0.10145187377929688 + }, + "queryAACube": { + "x": -1.4123910665512085, + "y": -1.4123910665512085, + "z": -1.4123910665512085, + "scale": 2.824782133102417 + }, + "grab": { + "grabbable": false, + "equippableLeftRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + }, + "equippableRightRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + } + }, + "damping": 0, + "angularDamping": 0, + "shapeType": "static-mesh", + "modelURL": "qrc:///serverless/Models/bowl2.fbx", + "blendshapeCoefficients": "{\n}\n", + "animation": { + "allowTranslation": false + }, + "clientOnly": false, + "avatarEntity": false, + "localEntity": false, + "faceCamera": false, + "isFacingAvatar": false +}, + { + "id": "{9c451827-4c87-4bf7-8372-aeb6bbd61eaa}", + "type": "ParticleEffect", + "lastEdited": 1617217817025177, + "parentID": "{5b6443c5-ec22-4c8a-9581-85134ceb6856}", + "name": "Brew", + "locked": true, + "position": { + "x": 0, + "y": 0.44699999690055847, + "z": 0 + }, + "dimensions": { + "x": 16.263307571411133, + "y": 16.263307571411133, + "z": 16.263307571411133 + }, + "rotation": { + "x": 8.988587651970192e-12, + "y": -0.00008631677337689325, + "z": -0.7071500420570374, + "w": 0.7070636749267578 + }, + "created": 1617216898348298, + "lastEditedBy": "{f72b151a-b325-4c9f-805a-7a7a520f82f7}", + "queryAACube": { + "x": 7.714627265930176, + "y": -12.719738006591797, + "z": -5.470824241638184, + "scale": 28.168874740600586 + }, + "grab": { + "grabbable": false, + "equippableLeftRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + }, + "equippableRightRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + } + }, + "damping": 0, + "angularDamping": 0, + "shapeType": "ellipsoid", + "color": { + "red": 4, + "green": 101, + "blue": 143 + }, + "alpha": 0.30000001192092896, + "textures": "qrc:///serverless/Textures/default_particle.png", + "maxParticles": 80, + "lifespan": 2, + "emitRate": 47, + "emitSpeed": 0.30000001192092896, + "speedSpread": 0, + "emitOrientation": { + "x": 0, + "y": 0, + "z": 0, + "w": 1 + }, + "emitDimensions": { + "x": 1, + "y": 1, + "z": 0 + }, + "emitRadiusStart": 0, + "polarStart": 0.8700000047683716, + "polarFinish": 1.2200000286102295, + "azimuthStart": 3.0999999046325684, + "azimuthFinish": 3.140000104904175, + "emitAcceleration": { + "x": 0, + "y": -0.9900000095367432, + "z": 0 + }, + "accelerationSpread": { + "x": 0.10000000149011612, + "y": 0.3400000035762787, + "z": 0.10000000149011612 + }, + "particleRadius": 1.5, + "radiusStart": 0.5, + "radiusFinish": 0.30000001192092896, + "colorSpread": { + "red": 0, + "green": 150, + "blue": 150 + }, + "colorStart": { + "red": 0, + "green": 0, + "blue": 0 + }, + "colorFinish": { + "red": 0, + "green": 0, + "blue": 0 + }, + "alphaStart": 0.5, + "alphaFinish": 0, + "emitterShouldTrail": true, + "spinStart": null, + "spinFinish": null, + "clientOnly": false, + "avatarEntity": false, + "localEntity": false, + "faceCamera": false, + "isFacingAvatar": false +}, + { + "id": "{77cbbb3f-e1fe-436c-8b0a-11b45b96181b}", + "type": "ParticleEffect", + "lastEdited": 1617216897203063, + "parentID": "{5b6443c5-ec22-4c8a-9581-85134ceb6856}", + "name": "steam", + "locked": true, + "position": { + "x": 0.03824615478515625, + "y": 5.34733772277832, + "z": 0.057065125554800034 + }, + "dimensions": { + "x": 14.4042329788208, + "y": 14.4042329788208, + "z": 14.4042329788208 + }, + "rotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + }, + "created": 1617216882977327, + "lastEditedBy": "{7f097416-1c40-4cba-aa7c-6e20a7281823}", + "queryAACube": { + "x": 9.363174438476562, + "y": -6.209394454956055, + "z": -3.8040504455566406, + "scale": 24.948863983154297 + }, + "grab": { + "grabbable": false, + "equippableLeftRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + }, + "equippableRightRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + } + }, + "damping": 0, + "angularDamping": 0, + "shapeType": "ellipsoid", + "alpha": 0.014999999664723873, + "textures": "qrc:///serverless/Textures/default_particle.png", + "maxParticles": 100, + "lifespan": 3.069999933242798, + "emitSpeed": 0.4000000059604645, + "speedSpread": 0.10000000149011612, + "emitOrientation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + }, + "polarFinish": 3.1415927410125732, + "emitAcceleration": { + "x": 0, + "y": -1, + "z": 0 + }, + "particleRadius": 1.5, + "radiusStart": 0.5, + "radiusFinish": 0.4000000059604645, + "colorStart": { + "red": 0, + "green": 0, + "blue": 0 + }, + "colorFinish": { + "red": 0, + "green": 0, + "blue": 0 + }, + "alphaStart": 0.5, + "alphaFinish": 0, + "emitterShouldTrail": true, + "spinStart": null, + "spinFinish": null, + "clientOnly": false, + "avatarEntity": false, + "localEntity": false, + "faceCamera": false, + "isFacingAvatar": false +}, + { + "id": "{463bad19-9d44-479e-af6c-9d86ee76fc45}", "type": "Light", - "lastEdited": 1601257171038209, - "parentID": "{70e655f0-9e82-4be9-a31f-bf8d00798b70}", + "lastEdited": 1617217841543322, + "parentID": "{5b6443c5-ec22-4c8a-9581-85134ceb6856}", + "name": "blacklight", + "locked": true, + "position": { + "x": 0, + "y": 1.6233999729156494, + "z": 0 + }, + "dimensions": { + "x": 3.867255687713623, + "y": 3.867255687713623, + "z": 4.0243144035339355 + }, + "rotation": { + "x": -0.7071176171302795, + "y": 3.849143226375418e-12, + "z": -0.000021579189706244506, + "w": 0.7070960402488708 + }, + "created": 1617217525079443, + "lastEditedBy": "{f72b151a-b325-4c9f-805a-7a7a520f82f7}", + "queryAACube": { + "x": 18.404050827026367, + "y": -0.8539872169494629, + "z": 5.2184553146362305, + "scale": 6.790172100067139 + }, + "grab": { + "grabbable": false, + "equippableLeftRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + }, + "equippableRightRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + } + }, + "damping": 0, + "angularDamping": 0, + "isSpotlight": true, + "intensity": -25.700000762939453, + "exponent": 19.6299991607666, + "cutoff": 73.94000244140625, + "falloffRadius": 72.4000015258789, + "clientOnly": false, + "avatarEntity": false, + "localEntity": false, + "faceCamera": false, + "isFacingAvatar": false +}, + { + "id": "{a80ee618-752e-44e4-a9de-04f089b4fe03}", + "type": "Model", + "lastEdited": 1617140830643374, + "parentID": "{6c76b816-5064-424c-84b2-dbb478e47d5d}", + "name": "Dome Glass", + "locked": true, + "position": { + "x": -0.000016799232980702072, + "y": 3.1790809631347656, + "z": 0.000016798756405478343 + }, + "dimensions": { + "x": 44.38727569580078, + "y": 7.3717122077941895, + "z": 44.38727569580078 + }, + "rotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + }, + "created": 1614198986204337, + "lastEditedBy": "{7f097416-1c40-4cba-aa7c-6e20a7281823}", + "queryAACube": { + "x": -3.359670639038086, + "y": -24.09037208557129, + "z": -4.717145919799805, + "scale": 63.20445251464844 + }, + "grab": { + "grabbable": false, + "equippableLeftRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + }, + "equippableRightRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + } + }, + "damping": 0, + "angularDamping": 0, + "shapeType": "static-mesh", + "modelURL": "qrc:///serverless/Models/dome2_glass.glb", + "blendshapeCoefficients": "{\n}\n", + "animation": { + "allowTranslation": false + }, + "clientOnly": false, + "avatarEntity": false, + "localEntity": false, + "faceCamera": false, + "isFacingAvatar": false +}, + { + "id": "{d2ef46ed-c85f-4ab5-bef3-14feb46e9091}", + "type": "Model", + "lastEdited": 1617134717193282, + "parentID": "{6c76b816-5064-424c-84b2-dbb478e47d5d}", + "name": "trees", + "locked": true, + "position": { + "x": -0.000016800577213871293, + "y": -0.5505132675170898, + "z": 0.000016800084267742932 + }, + "dimensions": { + "x": 26.59911346435547, + "y": 9.549417495727539, + "z": 26.465896606445312 + }, + "rotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + }, + "created": 1614198986202454, + "lastEditedBy": "{0b759026-5fea-494c-99de-ab6301e73d4c}", + "queryAACube": { + "x": 8.883026123046875, + "y": -15.577155113220215, + "z": 7.525779724121094, + "scale": 38.71883010864258 + }, + "grab": { + "grabbable": false, + "equippableLeftRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + }, + "equippableRightRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + } + }, + "damping": 0, + "angularDamping": 0, + "modelURL": "qrc:///serverless/Models/Trees1.glb", + "blendshapeCoefficients": "{\n}\n", + "animation": { + "allowTranslation": false + }, + "clientOnly": false, + "avatarEntity": false, + "localEntity": false, + "faceCamera": false, + "isFacingAvatar": false +}, + { + "id": "{f3d87e87-a250-42f8-a285-84cbeb777353}", + "type": "Model", + "lastEdited": 1617140880548597, + "parentID": "{6c76b816-5064-424c-84b2-dbb478e47d5d}", + "name": "Panels", + "locked": true, + "position": { + "x": -0.0001735687255859375, + "y": -5.685686111450195, + "z": 0.00017449550796300173 + }, + "dimensions": { + "x": 36.70009231567383, + "y": 3.3704721927642822, + "z": 25.731521606445312 + }, + "rotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + }, + "created": 1614377167635894, + "lastEditedBy": "{7f097416-1c40-4cba-aa7c-6e20a7281823}", + "queryAACube": { + "x": -5.742575168609619, + "y": -23.827165603637695, + "z": 4.4112548828125, + "scale": 59.816864013671875 + }, + "grab": { + "grabbable": false, + "equippableLeftRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + }, + "equippableRightRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + } + }, + "damping": 0, + "angularDamping": 0, + "modelURL": "qrc:///serverless/Models/Stands.fbx", + "blendshapeCoefficients": "{\n}\n", + "useOriginalPivot": true, + "animation": { + "url": "qrc:///serverless/Models/Stands.fbx", + "allowTranslation": false, + "currentFrame": 68342.515625, + "running": true + }, + "clientOnly": false, + "avatarEntity": false, + "localEntity": false, + "faceCamera": false, + "isFacingAvatar": false +}, + { + "id": "{25638e51-c19c-420a-a9cc-ff02626b62ef}", + "type": "Box", + "lastEdited": 1617134697724395, + "visible": false, + "name": "portalCube", + "locked": true, + "userData": "{\"destination\":\"hifi://172.104.248.237:40102/154.572,-96.8437,-417.945/0,1,0,-1.52586e-05\"}", + "position": { + "x": 0.06047534942626953, + "y": 1.751168131828308, + "z": 4.2923126220703125 + }, + "dimensions": { + "x": 1.6716244220733643, + "y": 2.5448203086853027, + "z": 0.26420968770980835 + }, + "rotation": { + "x": 0.0000152587890625, + "y": 0.6351872682571411, + "z": -0.0000457763671875, + "w": 0.772335410118103 + }, + "created": 1614454164933827, + "lastEditedBy": "{0b759026-5fea-494c-99de-ab6301e73d4c}", + "queryAACube": { + "x": -1.4676154851913452, + "y": 0.22307729721069336, + "z": 2.764221668243408, + "scale": 3.0561816692352295 + }, + "grab": { + "grabbable": false, + "equippableLeftRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + }, + "equippableRightRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + } + }, + "collisionMask": 23, + "collidesWith": "static,dynamic,kinematic,otherAvatar,", + "damping": 0, + "angularDamping": 0, + "script": "qrc:///serverless/Scripts/portal.js", + "scriptTimestamp": 1617134674001, + "color": { + "red": 0, + "green": 180, + "blue": 239 + }, + "shape": "Cube", + "clientOnly": false, + "avatarEntity": false, + "localEntity": false, + "faceCamera": false, + "isFacingAvatar": false +}, + { + "id": "{e0261cde-c5e0-44bf-a747-787c4c867d79}", + "type": "Light", + "lastEdited": 1617140788480898, + "name": "mainDomeLight", + "locked": true, + "position": { + "x": 21.799074172973633, + "y": 10.247319221496582, + "z": 8.613605499267578 + }, + "dimensions": { + "x": 61.943946838378906, + "y": 61.943946838378906, + "z": 61.943946838378906 + }, + "rotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + }, + "created": 1614198986202528, + "lastEditedBy": "{7f097416-1c40-4cba-aa7c-6e20a7281823}", + "queryAACube": { + "x": -31.845956802368164, + "y": -43.39771270751953, + "z": -45.03142547607422, + "scale": 107.2900619506836 + }, + "grab": { + "grabbable": false, + "equippableLeftRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + }, + "equippableRightRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + } + }, + "damping": 0, + "angularDamping": 0, + "collisionMask": 23, + "collidesWith": "static,dynamic,kinematic,otherAvatar,", + "color": { + "red": 255, + "green": 235, + "blue": 87 + }, + "intensity": 0.8999999761581421, + "exponent": 1, + "cutoff": 75, + "falloffRadius": 30, + "clientOnly": false, + "avatarEntity": false, + "localEntity": false, + "faceCamera": false, + "isFacingAvatar": false +}, + { + "id": "{6c76b816-5064-424c-84b2-dbb478e47d5d}", + "type": "Model", + "lastEdited": 1617134709051164, + "name": "Dome", + "locked": true, + "position": { + "x": 21.799192428588867, + "y": 5.9566450119018555, + "z": 8.613487243652344 + }, + "dimensions": { + "x": 54.60203552246094, + "y": 13.734564781188965, + "z": 54.60203552246094 + }, + "rotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + }, + "created": 1614198986203467, + "lastEditedBy": "{0b759026-5fea-494c-99de-ab6301e73d4c}", + "queryAACube": { + "x": -25952.515625, + "y": -25921.0625, + "z": -25953.87890625, + "scale": 51961.5234375 + }, + "grab": { + "grabbable": false, + "equippableLeftRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + }, + "equippableRightRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + } + }, + "damping": 0, + "angularDamping": 0, + "shapeType": "static-mesh", + "modelURL": "qrc:///serverless/Models/dome2.glb", + "blendshapeCoefficients": "{\n}\n", + "animation": { + "allowTranslation": false + }, + "clientOnly": false, + "avatarEntity": false, + "localEntity": false, + "faceCamera": false, + "isFacingAvatar": false +}, + { + "id": "{52c84c1c-6567-4670-9b2b-9aa9bc1456ea}", + "type": "Model", + "lastEdited": 1617134574674644, + "parentID": "{6c76b816-5064-424c-84b2-dbb478e47d5d}", + "locked": true, + "position": { + "x": 4.238387418808998e-12, + "y": -2.3088181018829346, + "z": -7.275957614183426e-12 + }, + "dimensions": { + "x": 5.688337802886963, + "y": 7.10263204574585, + "z": 5.688361644744873 + }, + "rotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + }, + "created": 1614198986204522, + "lastEditedBy": "{78b82b17-4e7a-410f-95ce-1c3ace1cd609}", + "queryAACube": { + "x": -4.850972652435303, + "y": -3.341723680496216, + "z": -4.9151411056518555, + "scale": 38.45905685424805 + }, + "grab": { + "grabbable": false, + "equippableLeftRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + }, + "equippableRightRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + } + }, + "damping": 0, + "angularDamping": 0, + "scriptTimestamp": 1598912452582, + "shapeType": "static-mesh", + "modelURL": "qrc:///serverless/Models/temple5.glb", + "blendshapeCoefficients": "{\n}\n", + "animation": { + "allowTranslation": false + }, + "clientOnly": false, + "avatarEntity": false, + "localEntity": false, + "faceCamera": false, + "isFacingAvatar": false +}, + { + "id": "{d344138a-adb8-4ae7-9aae-447266a48869}", + "type": "Light", + "lastEdited": 1617140788480765, + "parentID": "{b9444e0f-1cda-4ad3-80e5-9ef3bf0ec6cd}", + "name": "mirrorLight", + "locked": true, + "position": { + "x": -0.0015339851379394531, + "y": -0.000001519918441772461, + "z": 0.26983165740966797 + }, + "dimensions": { + "x": 3.8637032508850098, + "y": 3.8637032508850098, + "z": 4 + }, + "rotation": { + "x": 0.0000152587890625, + "y": 1, + "z": 0.0000152587890625, + "w": -0.0000152587890625 + }, + "created": 1614453808970411, + "lastEditedBy": "{7f097416-1c40-4cba-aa7c-6e20a7281823}", + "queryAACube": { + "x": 6.681288719177246, + "y": -3.11796498298645, + "z": 35.638336181640625, + "scale": 6.771735668182373 + }, + "grab": { + "grabbable": false, + "equippableLeftRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + }, + "equippableRightRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + } + }, + "damping": 0, + "angularDamping": 0, + "color": { + "red": 255, + "green": 255, + "blue": 235 + }, + "isSpotlight": true, + "intensity": 0.699999988079071, + "exponent": 1, + "cutoff": 75, + "falloffRadius": 10, + "clientOnly": false, + "avatarEntity": false, + "localEntity": false, + "faceCamera": false, + "isFacingAvatar": false +}, + { + "id": "{0d85144d-a15c-4d1b-84a5-b3a379d31798}", + "type": "Light", + "lastEdited": 1617140731977291, + "parentID": "{b9444e0f-1cda-4ad3-80e5-9ef3bf0ec6cd}", + "name": "Mirror Light", + "locked": true, + "position": { + "x": 0.08925724029541016, + "y": 0.4832591116428375, + "z": 0.20032405853271484 + }, + "dimensions": { + "x": 6.747879505157471, + "y": 6.747879505157471, + "z": 6.985918998718262 + }, + "rotation": { + "x": -0.999969482421875, + "y": -0.0001373291015625, + "z": -0.0000762939453125, + "w": 0.00856029987335205 + }, + "created": 1614198986203073, + "lastEditedBy": "{7f097416-1c40-4cba-aa7c-6e20a7281823}", + "queryAACube": { + "x": 4.045637607574463, + "y": -5.162182331085205, + "z": 33.07383346557617, + "scale": 11.826699256896973 + }, + "grab": { + "grabbable": false, + "equippableLeftRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + }, + "equippableRightRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + } + }, + "damping": 0, + "angularDamping": 0, + "isSpotlight": true, + "intensity": 2, + "exponent": 1, + "cutoff": 75, + "falloffRadius": 5.699999809265137, + "clientOnly": false, + "avatarEntity": false, + "localEntity": false, + "faceCamera": false, + "isFacingAvatar": false +}, + { + "id": "{89f2cd0b-782f-4e4e-a674-587ae5893f7d}", + "type": "Light", + "lastEdited": 1617140712801743, + "parentID": "{52c84c1c-6567-4670-9b2b-9aa9bc1456ea}", + "name": "templeLight", "locked": true, "position": { "x": -0.10364770889282227, @@ -819,12 +1415,12 @@ "z": -0.0000152587890625, "w": 1 }, - "created": 1598733516961728, - "lastEditedBy": "{70099fa7-d189-42dc-80a0-02c37d1942d1}", + "created": 1614198986204117, + "lastEditedBy": "{7f097416-1c40-4cba-aa7c-6e20a7281823}", "queryAACube": { - "x": -4.850877285003662, - "y": -7.476483345031738, - "z": -4.915230751037598, + "x": 23.39162826538086, + "y": -2.135477066040039, + "z": 21.969898223876953, "scale": 9.494348526000977 }, "grab": { @@ -860,770 +1456,10 @@ "isFacingAvatar": false }, { - "id": "{74fcc311-ac54-4c92-b658-67b616d89124}", - "type": "Model", - "lastEdited": 1601257562566663, - "parentID": "{ee9b7ff6-97f0-4957-aea1-3b517b6e68b8}", - "locked": true, - "position": { - "x": 2.8377300509419e-13, - "y": -5.038946151733398, - "z": 0 - }, - "dimensions": { - "x": 1.7757656574249268, - "y": 1.2933320999145508, - "z": 1.7757654190063477 - }, - "rotation": { - "x": -0.0000152587890625, - "y": -0.0000152587890625, - "z": -0.0000152587890625, - "w": 1 - }, - "created": 1600122372976180, - "lastEditedBy": "{68e3a576-152f-48c2-adf3-6dde43ee51ba}", - "queryAACube": { - "x": -15.658815383911133, - "y": -20.814706802368164, - "z": -15.639467239379883, - "scale": 31.393596649169922 - }, - "grab": { - "grabbable": false, - "equippableLeftRotation": { - "x": -0.0000152587890625, - "y": -0.0000152587890625, - "z": -0.0000152587890625, - "w": 1 - }, - "equippableRightRotation": { - "x": -0.0000152587890625, - "y": -0.0000152587890625, - "z": -0.0000152587890625, - "w": 1 - } - }, - "damping": 0, - "angularDamping": 0, - "shapeType": "static-mesh", - "modelURL": "https://cdn-1.vircadia.com/us-e-1/DomainContent/Tutorial/Models/bowl2.fbx", - "blendshapeCoefficients": "{\n}\n", - "animation": { - "allowTranslation": false - }, - "clientOnly": false, - "avatarEntity": false, - "localEntity": false, - "faceCamera": false, - "isFacingAvatar": false -}, - { - "id": "{1cfc9c02-50cc-4c22-bf79-9aeb57522b04}", - "type": "Light", - "lastEdited": 1601257171037813, - "parentID": "{ee9b7ff6-97f0-4957-aea1-3b517b6e68b8}", - "name": "TreeLight_1", - "locked": true, - "position": { - "x": 9.000457763671875, - "y": -0.2475719451904297, - "z": 8.999537467956543 - }, - "dimensions": { - "x": 10.24996280670166, - "y": 10.24996280670166, - "z": 10.24996280670166 - }, - "rotation": { - "x": -0.0000152587890625, - "y": -0.0000152587890625, - "z": -0.0000152587890625, - "w": 1 - }, - "created": 1600983484676879, - "lastEditedBy": "{70099fa7-d189-42dc-80a0-02c37d1942d1}", - "queryAACube": { - "x": 0.12341690063476562, - "y": -10.132533073425293, - "z": 0.1231222152709961, - "scale": 17.753456115722656 - }, - "grab": { - "grabbable": false, - "equippableLeftRotation": { - "x": -0.0000152587890625, - "y": -0.0000152587890625, - "z": -0.0000152587890625, - "w": 1 - }, - "equippableRightRotation": { - "x": -0.0000152587890625, - "y": -0.0000152587890625, - "z": -0.0000152587890625, - "w": 1 - } - }, - "damping": 0, - "angularDamping": 0, - "color": { - "red": 69, - "green": 106, - "blue": 255 - }, - "intensity": 17.799999237060547, - "exponent": 1, - "cutoff": 75, - "falloffRadius": 26.100000381469727, - "clientOnly": false, - "avatarEntity": false, - "localEntity": false, - "faceCamera": false, - "isFacingAvatar": false -}, - { - "id": "{8233c8d0-ae61-4b7c-8ac4-8200e897dc86}", - "type": "Light", - "lastEdited": 1601257171037784, - "parentID": "{ee9b7ff6-97f0-4957-aea1-3b517b6e68b8}", - "name": "TreeLight_2", - "locked": true, - "position": { - "x": -8.819664001464844, - "y": -0.24757671356201172, - "z": 8.97313404083252 - }, - "dimensions": { - "x": 10.24996280670166, - "y": 10.24996280670166, - "z": 10.24996280670166 - }, - "rotation": { - "x": -0.0000152587890625, - "y": -0.0000152587890625, - "z": -0.0000152587890625, - "w": 1 - }, - "created": 1600983484676428, - "lastEditedBy": "{70099fa7-d189-42dc-80a0-02c37d1942d1}", - "queryAACube": { - "x": -17.696704864501953, - "y": -10.13199520111084, - "z": 0.0961751937866211, - "scale": 17.753456115722656 - }, - "grab": { - "grabbable": false, - "equippableLeftRotation": { - "x": -0.0000152587890625, - "y": -0.0000152587890625, - "z": -0.0000152587890625, - "w": 1 - }, - "equippableRightRotation": { - "x": -0.0000152587890625, - "y": -0.0000152587890625, - "z": -0.0000152587890625, - "w": 1 - } - }, - "damping": 0, - "angularDamping": 0, - "color": { - "red": 191, - "green": 31, - "blue": 255 - }, - "intensity": 15, - "exponent": 1, - "cutoff": 75, - "falloffRadius": 26.100000381469727, - "clientOnly": false, - "avatarEntity": false, - "localEntity": false, - "faceCamera": false, - "isFacingAvatar": false -}, - { - "id": "{a09d75c8-91d7-470f-a7ff-d49f59d8fd66}", - "type": "Light", - "lastEdited": 1601257171037821, - "locked": true, - "position": { - "x": 20.86223793029785, - "y": 3.7069454193115234, - "z": 22.919116973876953 - }, - "dimensions": { - "x": 7.6550493240356445, - "y": 7.6550493240356445, - "z": 7.6550493240356445 - }, - "rotation": { - "x": -0.0000152587890625, - "y": -0.0000152587890625, - "z": -0.0000152587890625, - "w": 1 - }, - "created": 1601156079314076, - "lastEditedBy": "{70099fa7-d189-42dc-80a0-02c37d1942d1}", - "queryAACube": { - "x": 14.232770919799805, - "y": -2.9225220680236816, - "z": 16.289649963378906, - "scale": 13.25893497467041 - }, - "grab": { - "grabbable": false, - "equippableLeftRotation": { - "x": -0.0000152587890625, - "y": -0.0000152587890625, - "z": -0.0000152587890625, - "w": 1 - }, - "equippableRightRotation": { - "x": -0.0000152587890625, - "y": -0.0000152587890625, - "z": -0.0000152587890625, - "w": 1 - } - }, - "damping": 0, - "angularDamping": 0, - "intensity": 5, - "exponent": 1, - "cutoff": 75, - "falloffRadius": 1, - "clientOnly": false, - "avatarEntity": false, - "localEntity": false, - "faceCamera": false, - "isFacingAvatar": false -}, - { - "id": "{70e655f0-9e82-4be9-a31f-bf8d00798b70}", - "type": "Model", - "lastEdited": 1601257491990357, - "parentID": "{ee9b7ff6-97f0-4957-aea1-3b517b6e68b8}", - "locked": true, - "position": { - "x": 4.238387418808998e-12, - "y": -2.3088181018829346, - "z": -7.275957614183426e-12 - }, - "dimensions": { - "x": 5.688337802886963, - "y": 7.10263204574585, - "z": 5.688361644744873 - }, - "rotation": { - "x": -0.0000152587890625, - "y": -0.0000152587890625, - "z": -0.0000152587890625, - "w": 1 - }, - "created": 1598733420183555, - "lastEditedBy": "{68e3a576-152f-48c2-adf3-6dde43ee51ba}", - "queryAACube": { - "x": -5.365779876708984, - "y": -8.682729721069336, - "z": -5.365577697753906, - "scale": 10.73135757446289 - }, - "grab": { - "grabbable": false, - "equippableLeftRotation": { - "x": -0.0000152587890625, - "y": -0.0000152587890625, - "z": -0.0000152587890625, - "w": 1 - }, - "equippableRightRotation": { - "x": -0.0000152587890625, - "y": -0.0000152587890625, - "z": -0.0000152587890625, - "w": 1 - } - }, - "damping": 0, - "angularDamping": 0, - "scriptTimestamp": 1598912452582, - "shapeType": "static-mesh", - "modelURL": "https://cdn-1.vircadia.com/us-e-1/DomainContent/Tutorial/Models/SmallTemple5.glb", - "blendshapeCoefficients": "{\n}\n", - "animation": { - "allowTranslation": false - }, - "clientOnly": false, - "avatarEntity": false, - "localEntity": false, - "faceCamera": false, - "isFacingAvatar": false -}, - { - "id": "{a700075e-206d-447c-a0f2-cdd2d377c621}", - "type": "ParticleEffect", - "lastEdited": 1601257171034843, - "parentID": "{74fcc311-ac54-4c92-b658-67b616d89124}", - "locked": true, - "position": { - "x": 0.03811454772949219, - "y": 0.9292696714401245, - "z": 0.05720067024230957 - }, - "dimensions": { - "x": 18.12510108947754, - "y": 18.12510108947754, - "z": 18.12510108947754 - }, - "rotation": { - "x": -0.0000152587890625, - "y": -0.0000152587890625, - "z": -0.0000152587890625, - "w": 1 - }, - "created": 1600122719130701, - "lastEditedBy": "{70099fa7-d189-42dc-80a0-02c37d1942d1}", - "queryAACube": { - "x": -15.658815383911133, - "y": -20.814706802368164, - "z": -15.639467239379883, - "scale": 31.393596649169922 - }, - "grab": { - "grabbable": false, - "equippableLeftRotation": { - "x": -0.0000152587890625, - "y": -0.0000152587890625, - "z": -0.0000152587890625, - "w": 1 - }, - "equippableRightRotation": { - "x": -0.0000152587890625, - "y": -0.0000152587890625, - "z": -0.0000152587890625, - "w": 1 - } - }, - "damping": 0, - "angularDamping": 0, - "shapeType": "ellipsoid", - "alpha": 0, - "textures": "http://eu-central-1.linodeobjects.com/vircadia-assets/interface/default/default_particle.png", - "maxParticles": 100, - "lifespan": 2.5, - "emitRate": 20, - "emitSpeed": 0.5, - "speedSpread": 0.10000000149011612, - "emitOrientation": { - "x": -0.0000152587890625, - "y": -0.0000152587890625, - "z": -0.0000152587890625, - "w": 1 - }, - "polarFinish": 3.1415927410125732, - "emitAcceleration": { - "x": 0, - "y": -2, - "z": 0 - }, - "particleRadius": 1.5, - "radiusStart": 0.5, - "radiusFinish": 0.4000000059604645, - "colorStart": { - "red": 0, - "green": 0, - "blue": 0 - }, - "colorFinish": { - "red": 0, - "green": 0, - "blue": 0 - }, - "alphaStart": 0.5, - "alphaFinish": 0, - "emitterShouldTrail": true, - "spinStart": null, - "spinFinish": null, - "clientOnly": false, - "avatarEntity": false, - "localEntity": false, - "faceCamera": false, - "isFacingAvatar": false -}, - { - "id": "{1257cabd-b553-482e-92d8-be6da0a65769}", - "type": "Shape", - "lastEdited": 1601258198368340, - "parentID": "{ee9b7ff6-97f0-4957-aea1-3b517b6e68b8}", - "locked": true, - "position": { - "x": -3.5344172033546783e-11, - "y": -7.235068321228027, - "z": -5.820766091346741e-11 - }, - "dimensions": { - "x": 54.22285461425781, - "y": 0.890187680721283, - "z": 54.22285461425781 - }, - "rotation": { - "x": -0.0000152587890625, - "y": -0.0000152587890625, - "z": -0.0000152587890625, - "w": 1 - }, - "created": 1600721905502275, - "lastEditedBy": "{0ff4c9e5-fb36-4bdd-9fbc-b2ed60e1aa3b}", - "queryAACube": { - "x": -38.34418487548828, - "y": -46.58723449707031, - "z": -38.34368133544922, - "scale": 76.6878662109375 - }, - "grab": { - "grabbable": false, - "equippableLeftRotation": { - "x": -0.0000152587890625, - "y": -0.0000152587890625, - "z": -0.0000152587890625, - "w": 1 - }, - "equippableRightRotation": { - "x": -0.0000152587890625, - "y": -0.0000152587890625, - "z": -0.0000152587890625, - "w": 1 - } - }, - "damping": 0, - "angularDamping": 0, - "color": { - "red": 0, - "green": 0, - "blue": 0 - }, - "shape": "Cylinder", - "clientOnly": false, - "avatarEntity": false, - "localEntity": false, - "faceCamera": false, - "isFacingAvatar": false -}, - { - "id": "{9ca25d38-4e0b-4eee-8736-0f569f053c56}", - "type": "Light", - "lastEdited": 1601257171036649, - "locked": true, - "position": { - "x": 18.585229873657227, - "y": 8.62344741821289, - "z": 20.33745002746582 - }, - "dimensions": { - "x": 61.943946838378906, - "y": 61.943946838378906, - "z": 61.943946838378906 - }, - "rotation": { - "x": -0.0000152587890625, - "y": -0.0000152587890625, - "z": -0.0000152587890625, - "w": 1 - }, - "created": 1600985305517745, - "lastEditedBy": "{70099fa7-d189-42dc-80a0-02c37d1942d1}", - "queryAACube": { - "x": -35.05979919433594, - "y": -45.021583557128906, - "z": -33.307579040527344, - "scale": 107.2900619506836 - }, - "grab": { - "grabbable": false, - "equippableLeftRotation": { - "x": -0.0000152587890625, - "y": -0.0000152587890625, - "z": -0.0000152587890625, - "w": 1 - }, - "equippableRightRotation": { - "x": -0.0000152587890625, - "y": -0.0000152587890625, - "z": -0.0000152587890625, - "w": 1 - } - }, - "damping": 0, - "angularDamping": 0, - "collisionMask": 23, - "collidesWith": "static,dynamic,kinematic,otherAvatar,", - "color": { - "red": 255, - "green": 235, - "blue": 87 - }, - "exponent": 1, - "cutoff": 75, - "falloffRadius": 30, - "clientOnly": false, - "avatarEntity": false, - "localEntity": false, - "faceCamera": false, - "isFacingAvatar": false -}, - { - "id": "{30d38443-925c-44d2-a6dd-bfe90cf03169}", - "type": "Model", - "lastEdited": 1601258262276262, - "parentID": "{ee9b7ff6-97f0-4957-aea1-3b517b6e68b8}", - "name": "Dome Glass", - "locked": true, - "position": { - "x": -0.000016799232980702072, - "y": 3.1790809631347656, - "z": 0.000016798756405478343 - }, - "dimensions": { - "x": 44.38727569580078, - "y": 7.3717122077941895, - "z": 44.38727569580078 - }, - "rotation": { - "x": -0.0000152587890625, - "y": -0.0000152587890625, - "z": -0.0000152587890625, - "w": 1 - }, - "created": 1601235894674966, - "lastEditedBy": "{0ff4c9e5-fb36-4bdd-9fbc-b2ed60e1aa3b}", - "queryAACube": { - "x": -31.602176666259766, - "y": -29.431379318237305, - "z": -31.602275848388672, - "scale": 63.20445251464844 - }, - "grab": { - "grabbable": false, - "equippableLeftRotation": { - "x": -0.0000152587890625, - "y": -0.0000152587890625, - "z": -0.0000152587890625, - "w": 1 - }, - "equippableRightRotation": { - "x": -0.0000152587890625, - "y": -0.0000152587890625, - "z": -0.0000152587890625, - "w": 1 - } - }, - "damping": 0, - "angularDamping": 0, - "shapeType": "static-mesh", - "modelURL": "https://cdn-1.vircadia.com/us-e-1/DomainContent/Tutorial/Models/dome2_glass.glb", - "blendshapeCoefficients": "{\n}\n", - "animation": { - "allowTranslation": false - }, - "clientOnly": false, - "avatarEntity": false, - "localEntity": false, - "faceCamera": false, - "isFacingAvatar": false -}, - { - "id": "{369d555d-f945-4555-9ef3-8f323fea547c}", - "type": "Light", - "lastEdited": 1601257171034893, - "parentID": "{ee9b7ff6-97f0-4957-aea1-3b517b6e68b8}", - "name": "TreeLight_4", - "locked": true, - "position": { - "x": -8.819656372070312, - "y": -0.07544326782226562, - "z": -9.190401077270508 - }, - "dimensions": { - "x": 10.24996280670166, - "y": 10.24996280670166, - "z": 10.24996280670166 - }, - "rotation": { - "x": -0.0000152587890625, - "y": -0.0000152587890625, - "z": -0.0000152587890625, - "w": 1 - }, - "created": 1600983484676513, - "lastEditedBy": "{70099fa7-d189-42dc-80a0-02c37d1942d1}", - "queryAACube": { - "x": -17.696136474609375, - "y": -9.960415840148926, - "z": -18.067365646362305, - "scale": 17.753456115722656 - }, - "grab": { - "grabbable": false, - "equippableLeftRotation": { - "x": -0.0000152587890625, - "y": -0.0000152587890625, - "z": -0.0000152587890625, - "w": 1 - }, - "equippableRightRotation": { - "x": -0.0000152587890625, - "y": -0.0000152587890625, - "z": -0.0000152587890625, - "w": 1 - } - }, - "damping": 0, - "angularDamping": 0, - "color": { - "red": 250, - "green": 214, - "blue": 32 - }, - "intensity": 15, - "exponent": 1, - "cutoff": 75, - "falloffRadius": 26.100000381469727, - "clientOnly": false, - "avatarEntity": false, - "localEntity": false, - "faceCamera": false, - "isFacingAvatar": false -}, - { - "id": "{5cb5d8ee-d17b-4d72-941a-bef2f8d8a91e}", - "type": "Material", - "lastEdited": 1601257171038436, - "parentID": "{523b7462-9a49-4949-8d31-d84749cbab0a}", - "parentJointIndex": 0, - "name": "VClogo", - "locked": true, - "userData": "{\"verticalOffset\":0,\"segments\":16,\"updateInterval\":1000}", - "position": { - "x": -0.00001823902130126953, - "y": -0.0002636909484863281, - "z": 0.10145187377929688 - }, - "rotation": { - "x": 0.0012969970703125, - "y": 0.0000152587890625, - "z": 0.0000457763671875, - "w": 0.999969482421875 - }, - "created": 1600983484676983, - "lastEditedBy": "{70099fa7-d189-42dc-80a0-02c37d1942d1}", - "queryAACube": { - "x": 19.472692489624023, - "y": -4.3051862716674805, - "z": -2.6303162574768066, - "scale": 4.506556510925293 - }, - "canCastShadow": false, - "grab": { - "grabbable": false, - "equippableLeftRotation": { - "x": -0.0000152587890625, - "y": -0.0000152587890625, - "z": -0.0000152587890625, - "w": 1 - }, - "equippableRightRotation": { - "x": -0.0000152587890625, - "y": -0.0000152587890625, - "z": -0.0000152587890625, - "w": 1 - } - }, - "collisionMask": 23, - "collidesWith": "static,dynamic,kinematic,otherAvatar,", - "scriptTimestamp": 1597610738986, - "materialURL": "materialData", - "priority": 3, - "parentMaterialName": "[mat::NeonTubes]", - "materialMappingPos": { - "x": 0.8125, - "y": 0 - }, - "materialData": "{\"materialVersion\":1,\"materials\":[{\"name\":\"baseMaterial2\",\"model\":\"hifi_pbr\",\"opacity\":1,\"albedo\":[0,0,0],\"roughness\":1,\"metallic\":0,\"emissive\":[2.3,2,2],\"scattering\":0,\"unlit\":false,\"opacityMapMode\":\"OPACITY_MAP_MASK\",\"cullFaceMode\":\"CULL_BACK\",\"defaultFallthrough\":false}]}", - "clientOnly": false, - "avatarEntity": false, - "localEntity": false, - "faceCamera": false, - "isFacingAvatar": false -}, - { - "id": "{9bfb2207-70d2-4578-ba34-016449cc1569}", - "type": "Light", - "lastEdited": 1601257171035017, - "parentID": "{ee9b7ff6-97f0-4957-aea1-3b517b6e68b8}", - "name": "TreeLight_3", - "locked": true, - "position": { - "x": 9.418960571289062, - "y": -0.07544326782226562, - "z": -9.190400123596191 - }, - "dimensions": { - "x": 10.24996280670166, - "y": 10.24996280670166, - "z": 10.24996280670166 - }, - "rotation": { - "x": -0.0000152587890625, - "y": -0.0000152587890625, - "z": -0.0000152587890625, - "w": 1 - }, - "created": 1600983484676750, - "lastEditedBy": "{70099fa7-d189-42dc-80a0-02c37d1942d1}", - "queryAACube": { - "x": 0.54248046875, - "y": -9.960972785949707, - "z": -18.06680679321289, - "scale": 17.753456115722656 - }, - "grab": { - "grabbable": false, - "equippableLeftRotation": { - "x": -0.0000152587890625, - "y": -0.0000152587890625, - "z": -0.0000152587890625, - "w": 1 - }, - "equippableRightRotation": { - "x": -0.0000152587890625, - "y": -0.0000152587890625, - "z": -0.0000152587890625, - "w": 1 - } - }, - "damping": 0, - "angularDamping": 0, - "color": { - "red": 69, - "green": 255, - "blue": 69 - }, - "intensity": 20.5, - "exponent": 1, - "cutoff": 75, - "falloffRadius": 26.100000381469727, - "clientOnly": false, - "avatarEntity": false, - "localEntity": false, - "faceCamera": false, - "isFacingAvatar": false -}, - { - "id": "{72cb8c19-406e-4979-b1b2-5a2e4247b278}", + "id": "{3a740728-5d6f-4a3b-a710-49a8c6cb1ae0}", "type": "Zone", - "lastEdited": 1601258385750995, - "parentID": "{ee9b7ff6-97f0-4957-aea1-3b517b6e68b8}", + "lastEdited": 1617140938876740, + "parentID": "{6c76b816-5064-424c-84b2-dbb478e47d5d}", "name": "MainDomeZone", "locked": true, "userData": "{\n \"grabbableKey\": {\n \"grabbable\": false,\n \"ignoreIK\": false\n }\n}", @@ -1638,17 +1474,17 @@ "z": 10000 }, "rotation": { - "x": -0.14595149457454681, - "y": -0.023671336472034454, - "z": 0.0017202693270519376, - "w": 0.9890071153640747 + "x": 0.44721001386642456, + "y": 0.5232430100440979, + "z": 0.06775686889886856, + "w": 0.7222389578819275 }, - "created": 1593477197502695, - "lastEditedBy": "{0ff4c9e5-fb36-4bdd-9fbc-b2ed60e1aa3b}", + "created": 1614198986203133, + "lastEditedBy": "{7f097416-1c40-4cba-aa7c-6e20a7281823}", "queryAACube": { - "x": -25980.759765625, - "y": -25926.40234375, - "z": -25980.763671875, + "x": -25952.515625, + "y": -25921.0625, + "z": -25953.87890625, "scale": 51961.5234375 }, "grab": { @@ -1680,7 +1516,7 @@ "green": 127, "blue": 68 }, - "intensity": 2, + "intensity": 1.5, "direction": { "x": 0.20760862529277802, "y": -0.7512804269790649, @@ -1691,8 +1527,8 @@ "shadowMaxDistance": 57.79999923706055 }, "ambientLight": { - "ambientIntensity": 0.20000000298023224, - "ambientURL": "https://cdn-1.vircadia.com/us-e-1/DomainContent/Tutorial/Images/galaxySkybox.png" + "ambientIntensity": 0.8999999761581421, + "ambientURL": "qrc:///serverless/Textures/galaxySkybox.png" }, "skybox": { "color": { @@ -1700,7 +1536,7 @@ "green": 235, "blue": 235 }, - "url": "https://cdn-1.vircadia.com/us-e-1/DomainContent/Tutorial/Images/galaxySkybox.png" + "url": "qrc:///serverless/Textures/galaxySkybox.png" }, "haze": { "hazeRange": 50, @@ -1738,21 +1574,21 @@ "isFacingAvatar": false }, { - "id": "{a701dd17-68d7-4252-8c50-d18ac081ff1e}", - "type": "Model", - "lastEdited": 1601257171034627, - "parentID": "{ee9b7ff6-97f0-4957-aea1-3b517b6e68b8}", - "name": "trees", + "id": "{c5a35dbf-8253-4782-b121-26d0c609aad5}", + "type": "Shape", + "lastEdited": 1617140925236269, + "parentID": "{6c76b816-5064-424c-84b2-dbb478e47d5d}", + "name": "MainCollision", "locked": true, "position": { - "x": -0.000016800577213871293, - "y": -0.5505132675170898, - "z": 0.000016800084267742932 + "x": 0.00002288818359375, + "y": -6.380376815795898, + "z": -0.00002409383887425065 }, "dimensions": { - "x": 26.59911346435547, - "y": 9.549417495727539, - "z": 26.465896606445312 + "x": 54.22285461425781, + "y": 0.890187680721283, + "z": 54.22285461425781 }, "rotation": { "x": -0.0000152587890625, @@ -1760,13 +1596,13 @@ "z": -0.0000152587890625, "w": 1 }, - "created": 1600983484676798, - "lastEditedBy": "{70099fa7-d189-42dc-80a0-02c37d1942d1}", + "created": 1614198986204167, + "lastEditedBy": "{7f097416-1c40-4cba-aa7c-6e20a7281823}", "queryAACube": { - "x": -19.359479904174805, - "y": -20.918161392211914, - "z": -19.359350204467773, - "scale": 38.71883010864258 + "x": -10.101629257202148, + "y": -40.391536712646484, + "z": -11.458602905273438, + "scale": 76.6878662109375 }, "grab": { "grabbable": false, @@ -1785,11 +1621,12 @@ }, "damping": 0, "angularDamping": 0, - "modelURL": "https://cdn-1.vircadia.com/us-e-1/DomainContent/Tutorial/Models/Trees1.glb", - "blendshapeCoefficients": "{\n}\n", - "animation": { - "allowTranslation": false + "color": { + "red": 0, + "green": 0, + "blue": 0 }, + "shape": "Cylinder", "clientOnly": false, "avatarEntity": false, "localEntity": false, @@ -1797,33 +1634,37 @@ "isFacingAvatar": false }, { - "id": "{3deeadb3-5bab-4d1a-a8df-d3d4b192c76a}", - "type": "Model", - "lastEdited": 1601257171037923, + "id": "{99f186d7-a623-4339-930e-1689d62a23e0}", + "type": "Zone", + "lastEdited": 1617134741129783, + "parentID": "{b9444e0f-1cda-4ad3-80e5-9ef3bf0ec6cd}", + "visible": false, + "name": "mirror_zone", "locked": true, + "userData": "{\"grabbableKey\":{\"grabbable\":false},\"original\":{\"id\":\"{da1e2fcd-d69b-47d7-b861-25b31f1c7175}\"}}", "position": { - "x": 0, - "y": 0.42019224166870117, - "z": 7.884521484375 + "x": -0.01726818084716797, + "y": 0.2113490104675293, + "z": 1.704751968383789 }, "dimensions": { - "x": 2.6655850410461426, - "y": 3.2029099464416504, - "z": 0.21786867082118988 + "x": 2.8482747077941895, + "y": 3.153184413909912, + "z": 3.6725244522094727 }, "rotation": { - "x": -0.0000152587890625, - "y": 0.4771343469619751, - "z": -0.0001068115234375, - "w": 0.8788127899169922 + "x": -0.0161592960357666, + "y": 0.0000152587890625, + "z": -0.006424069404602051, + "w": 0.999847412109375 }, - "created": 1601249822682598, - "lastEditedBy": "{70099fa7-d189-42dc-80a0-02c37d1942d1}", + "created": 1614198986202623, + "lastEditedBy": "{0b759026-5fea-494c-99de-ab6301e73d4c}", "queryAACube": { - "x": -2.086350917816162, - "y": -1.666158676147461, - "z": 5.798170566558838, - "scale": 4.172701835632324 + "x": 8.46190071105957, + "y": -2.328949451446533, + "z": 35.4334716796875, + "scale": 5.6162872314453125 }, "grab": { "grabbable": false, @@ -1840,16 +1681,9 @@ "w": 1 } }, - "damping": 0, - "angularDamping": 0, - "modelURL": "https://cdn-1.vircadia.com/us-e-1/DomainContent/Tutorial/Models/portal2.fbx", - "blendshapeCoefficients": "{\n}\n", - "animation": { - "url": "https://cdn-1.vircadia.com/us-e-1/DomainContent/Tutorial/Models/portal2.fbx", - "allowTranslation": false, - "currentFrame": 57265.5, - "running": true - }, + "script": "qrc:///serverless/Scripts/mirrorReflection.js", + "scriptTimestamp": 1601084668318, + "shapeType": "box", "clientOnly": false, "avatarEntity": false, "localEntity": false, @@ -1857,35 +1691,35 @@ "isFacingAvatar": false }, { - "id": "{9debec8d-26a7-4838-ac32-cce1fe59c72e}", + "id": "{33d5305a-641d-4a4f-baa9-23ec22bb9d48}", "type": "Light", - "lastEdited": 1601257171038206, - "parentID": "{ee9b7ff6-97f0-4957-aea1-3b517b6e68b8}", - "name": "Mirror Light", + "lastEdited": 1617140731977526, + "parentID": "{6c76b816-5064-424c-84b2-dbb478e47d5d}", + "name": "TreeLight_4", "locked": true, "position": { - "x": 20.063940048217773, - "y": -2.7442214488983154, - "z": -8.21159553527832 + "x": -8.819656372070312, + "y": -0.07544326782226562, + "z": -9.190401077270508 }, "dimensions": { - "x": 6.488605499267578, - "y": 6.488605499267578, - "z": 6.488605499267578 + "x": 10.24996280670166, + "y": 10.24996280670166, + "z": 10.24996280670166 }, "rotation": { "x": -0.0000152587890625, - "y": 0.17360186576843262, - "z": -0.0000762939453125, - "w": 0.9848020076751709 + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 }, - "created": 1601081824307531, - "lastEditedBy": "{70099fa7-d189-42dc-80a0-02c37d1942d1}", + "created": 1614198986202730, + "lastEditedBy": "{7f097416-1c40-4cba-aa7c-6e20a7281823}", "queryAACube": { - "x": 14.444778442382812, - "y": -9.372614860534668, - "z": -13.83016586303711, - "scale": 11.238594055175781 + "x": 10.546369552612305, + "y": -4.619409561157227, + "z": 8.817764282226562, + "scale": 17.753456115722656 }, "grab": { "grabbable": false, @@ -1904,10 +1738,15 @@ }, "damping": 0, "angularDamping": 0, - "intensity": 3, + "color": { + "red": 250, + "green": 214, + "blue": 32 + }, + "intensity": 15, "exponent": 1, "cutoff": 75, - "falloffRadius": 16.600000381469727, + "falloffRadius": 26.100000381469727, "clientOnly": false, "avatarEntity": false, "localEntity": false, @@ -1915,10 +1754,395 @@ "isFacingAvatar": false }, { - "id": "{b7a9788d-58a9-4999-8e8f-55fe07acb486}", + "id": "{67b2c758-41ea-4448-80eb-f171d792ab5c}", + "type": "Box", + "lastEdited": 1617140777516274, + "visible": false, + "name": "LandingPoint", + "locked": true, + "position": { + "x": 21.792818069458008, + "y": 0, + "z": 25.644922256469727 + }, + "dimensions": { + "x": 3.2382099628448486, + "y": 0.20000000298023224, + "z": 1.8551445007324219 + }, + "rotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + }, + "created": 1617140160943861, + "lastEditedBy": "{7f097416-1c40-4cba-aa7c-6e20a7281823}", + "queryAACube": { + "x": 19.924158096313477, + "y": -1.8686603307724, + "z": 23.776262283325195, + "scale": 3.7373206615448 + }, + "grab": { + "grabbable": false, + "equippableLeftRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + }, + "equippableRightRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + } + }, + "damping": 0, + "angularDamping": 0, + "color": { + "red": 0, + "green": 180, + "blue": 239 + }, + "shape": "Cube", + "clientOnly": false, + "avatarEntity": false, + "localEntity": false, + "faceCamera": false, + "isFacingAvatar": false +}, + { + "id": "{a4421b2e-123a-4619-8788-e36eef8029ea}", + "type": "Light", + "lastEdited": 1617140788480412, + "parentID": "{6c76b816-5064-424c-84b2-dbb478e47d5d}", + "name": "TreeLight_2", + "locked": true, + "position": { + "x": -8.819664001464844, + "y": -0.24757671356201172, + "z": 8.97313404083252 + }, + "dimensions": { + "x": 10.24996280670166, + "y": 10.24996280670166, + "z": 10.24996280670166 + }, + "rotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + }, + "created": 1614198986202574, + "lastEditedBy": "{7f097416-1c40-4cba-aa7c-6e20a7281823}", + "queryAACube": { + "x": 10.54580307006836, + "y": -4.790988445281982, + "z": 26.981304168701172, + "scale": 17.753456115722656 + }, + "grab": { + "grabbable": false, + "equippableLeftRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + }, + "equippableRightRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + } + }, + "damping": 0, + "angularDamping": 0, + "color": { + "red": 191, + "green": 31, + "blue": 255 + }, + "intensity": 15, + "exponent": 1, + "cutoff": 75, + "falloffRadius": 26.100000381469727, + "clientOnly": false, + "avatarEntity": false, + "localEntity": false, + "faceCamera": false, + "isFacingAvatar": false +}, + { + "id": "{523e1c2d-1603-47bb-80f1-314747b161b0}", + "type": "Material", + "lastEdited": 1617140991884044, + "parentID": "{f3d87e87-a250-42f8-a285-84cbeb777353}", + "parentJointIndex": 4, + "name": "moveMaterial", + "userData": "{\n \"verticalOffset\": 0,\n \"segments\": 64,\n \"updateInterval\": 200\n}", + "position": { + "x": 0.00000476837158203125, + "y": 7.152557373046875e-7, + "z": 0.000003814697265625 + }, + "rotation": { + "x": -0.0000152587890625, + "y": -0.0000457763671875, + "z": -0.0000152587890625, + "w": 1 + }, + "created": 1614382837959471, + "lastEditedBy": "{7f097416-1c40-4cba-aa7c-6e20a7281823}", + "queryAACube": { + "x": -5.742575168609619, + "y": -21.97960662841797, + "z": 11.547750473022461, + "scale": 52.68036651611328 + }, + "canCastShadow": false, + "grab": { + "grabbable": false, + "equippableLeftRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + }, + "equippableRightRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + } + }, + "collisionMask": 23, + "collidesWith": "static,dynamic,kinematic,otherAvatar,", + "script": "qrc:///serverless/Scripts/materialSequencer.js", + "scriptTimestamp": 1601250646975, + "materialURL": "materialData", + "priority": 3, + "parentMaterialName": "[mat::move]", + "materialMappingPos": { + "x": 0.265625, + "y": 0 + }, + "materialData": "{\"materialVersion\":1,\"materials\":[{\"name\":\"moveMaterial\",\"model\":\"hifi_pbr\",\"opacity\":0.8,\"albedo\":[1,1,1],\"roughness\":1,\"metallic\":0,\"emissive\":[0,0,0],\"scattering\":0,\"unlit\":false,\"emissiveMap\":\"qrc:///serverless/Textures/gradient1.jpg\",\"albedoMap\":\"qrc:///serverless/Textures/gradient1.jpg\",\"opacityMapMode\":\"OPACITY_MAP_BLEND\",\"cullFaceMode\":\"CULL_NONE\",\"defaultFallthrough\":false}]}", + "clientOnly": false, + "avatarEntity": false, + "localEntity": false, + "faceCamera": false, + "isFacingAvatar": false +}, + { + "id": "{35eb5c90-08e6-44de-b6b9-46c9fd36494a}", + "type": "Text", + "lastEdited": 1617134723640851, + "name": "(2)", + "locked": true, + "description": "mirror text", + "position": { + "x": 0, + "y": 4.090241432189941, + "z": 4.291414260864258 + }, + "dimensions": { + "x": 3.2473599910736084, + "y": 0.6462407112121582, + "z": 0.009999999776482582 + }, + "rotation": { + "x": 0.0008392333984375, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 0.999969482421875 + }, + "created": 1614453187953099, + "lastEditedBy": "{0b759026-5fea-494c-99de-ab6301e73d4c}", + "queryAACube": { + "x": -1.6555267572402954, + "y": 2.4347147941589355, + "z": 2.635887622833252, + "scale": 3.311053514480591 + }, + "billboardMode": "yaw", + "grab": { + "grabbable": false, + "equippableLeftRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + }, + "equippableRightRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + } + }, + "damping": 0, + "angularDamping": 0, + "collisionMask": 23, + "collidesWith": "static,dynamic,kinematic,otherAvatar,", + "text": "Portal", + "lineHeight": 0.6000000238418579, + "textColor": { + "red": 0, + "green": 0, + "blue": 0 + }, + "backgroundAlpha": 0, + "unlit": true, + "font": "Inconsolata", + "textEffect": "outline fill", + "textEffectColor": { + "red": 0, + "green": 208, + "blue": 255 + }, + "textEffectThickness": 0.30000001192092896, + "alignment": "center", + "clientOnly": false, + "avatarEntity": false, + "localEntity": false, + "faceCamera": true, + "isFacingAvatar": false +}, + { + "id": "{7d040847-617e-494b-9593-05ab35142098}", + "type": "Light", + "lastEdited": 1617140731977921, + "parentID": "{6c76b816-5064-424c-84b2-dbb478e47d5d}", + "name": "TreeLight_3", + "locked": true, + "position": { + "x": 9.418960571289062, + "y": -0.07544326782226562, + "z": -9.190400123596191 + }, + "dimensions": { + "x": 10.24996280670166, + "y": 10.24996280670166, + "z": 10.24996280670166 + }, + "rotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + }, + "created": 1614198986202887, + "lastEditedBy": "{7f097416-1c40-4cba-aa7c-6e20a7281823}", + "queryAACube": { + "x": 28.784984588623047, + "y": -4.61996603012085, + "z": 8.818321228027344, + "scale": 17.753456115722656 + }, + "grab": { + "grabbable": false, + "equippableLeftRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + }, + "equippableRightRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + } + }, + "damping": 0, + "angularDamping": 0, + "color": { + "red": 69, + "green": 255, + "blue": 69 + }, + "intensity": 20.5, + "exponent": 1, + "cutoff": 75, + "falloffRadius": 26.100000381469727, + "clientOnly": false, + "avatarEntity": false, + "localEntity": false, + "faceCamera": false, + "isFacingAvatar": false +}, + { + "id": "{c191dc9f-7a8e-4f98-9974-b23c9bb7992d}", + "type": "Light", + "lastEdited": 1617140788480592, + "parentID": "{6c76b816-5064-424c-84b2-dbb478e47d5d}", + "name": "TreeLight_1", + "locked": true, + "position": { + "x": 9.000457763671875, + "y": -0.2475719451904297, + "z": 8.999537467956543 + }, + "dimensions": { + "x": 10.24996280670166, + "y": 10.24996280670166, + "z": 10.24996280670166 + }, + "rotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + }, + "created": 1614198986203735, + "lastEditedBy": "{7f097416-1c40-4cba-aa7c-6e20a7281823}", + "queryAACube": { + "x": 28.365924835205078, + "y": -4.791526794433594, + "z": 27.008251190185547, + "scale": 17.753456115722656 + }, + "grab": { + "grabbable": false, + "equippableLeftRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + }, + "equippableRightRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + } + }, + "damping": 0, + "angularDamping": 0, + "color": { + "red": 69, + "green": 106, + "blue": 255 + }, + "intensity": 17.799999237060547, + "exponent": 1, + "cutoff": 75, + "falloffRadius": 26.100000381469727, + "clientOnly": false, + "avatarEntity": false, + "localEntity": false, + "faceCamera": false, + "isFacingAvatar": false +}, + { + "id": "{cf666211-2b88-4ee6-af3c-a1a92bd6c513}", "type": "Model", - "lastEdited": 1601257171034676, - "parentID": "{ee9b7ff6-97f0-4957-aea1-3b517b6e68b8}", + "lastEdited": 1617140858220173, + "parentID": "{6c76b816-5064-424c-84b2-dbb478e47d5d}", "name": "Planters", "locked": true, "position": { @@ -1937,12 +2161,12 @@ "z": -0.0000152587890625, "w": 1 }, - "created": 1600983484676673, - "lastEditedBy": "{70099fa7-d189-42dc-80a0-02c37d1942d1}", + "created": 1614198986203890, + "lastEditedBy": "{7f097416-1c40-4cba-aa7c-6e20a7281823}", "queryAACube": { - "x": -13.858329772949219, - "y": -20.452945709228516, - "z": -13.857589721679688, + "x": 14.384176254272461, + "y": -15.1119384765625, + "z": 13.02754020690918, "scale": 27.715923309326172 }, "grab": { @@ -1963,7 +2187,7 @@ "damping": 0, "angularDamping": 0, "shapeType": "static-mesh", - "modelURL": "https://cdn-1.vircadia.com/us-e-1/DomainContent/Tutorial/Models/Planter.glb", + "modelURL": "qrc:///serverless/Models/Planter.glb", "blendshapeCoefficients": "{\n}\n", "animation": { "allowTranslation": false @@ -1973,124 +2197,8 @@ "localEntity": false, "faceCamera": false, "isFacingAvatar": false -}, - { - "id": "{ee9b7ff6-97f0-4957-aea1-3b517b6e68b8}", - "type": "Model", - "lastEdited": 1601258385751160, - "name": "Dome", - "locked": true, - "position": { - "x": 18.58534812927246, - "y": 4.332773208618164, - "z": 20.337331771850586 - }, - "dimensions": { - "x": 54.60203552246094, - "y": 13.734564781188965, - "z": 54.60203552246094 - }, - "rotation": { - "x": -0.0000152587890625, - "y": -0.0000152587890625, - "z": -0.0000152587890625, - "w": 1 - }, - "created": 1600983484676623, - "lastEditedBy": "{0ff4c9e5-fb36-4bdd-9fbc-b2ed60e1aa3b}", - "queryAACube": { - "x": -25980.759765625, - "y": -25926.40234375, - "z": -25980.763671875, - "scale": 51961.5234375 - }, - "grab": { - "grabbable": false, - "equippableLeftRotation": { - "x": -0.0000152587890625, - "y": -0.0000152587890625, - "z": -0.0000152587890625, - "w": 1 - }, - "equippableRightRotation": { - "x": -0.0000152587890625, - "y": -0.0000152587890625, - "z": -0.0000152587890625, - "w": 1 - } - }, - "damping": 0, - "angularDamping": 0, - "shapeType": "static-mesh", - "modelURL": "https://cdn-1.vircadia.com/us-e-1/DomainContent/Tutorial/Models/dome2.glb", - "blendshapeCoefficients": "{\n}\n", - "animation": { - "allowTranslation": false - }, - "clientOnly": false, - "avatarEntity": false, - "localEntity": false, - "faceCamera": false, - "isFacingAvatar": false -}, - { - "id": "{7b9901a2-94ed-48a2-ae33-1ccabd0ee1e5}", - "type": "Light", - "lastEdited": 1601257171037705, - "parentID": "{74fcc311-ac54-4c92-b658-67b616d89124}", - "locked": true, - "position": { - "x": 0.041241057217121124, - "y": 1.0814814567565918, - "z": -0.03974604234099388 - }, - "dimensions": { - "x": 9.067279815673828, - "y": 9.067279815673828, - "z": 9.067279815673828 - }, - "rotation": { - "x": -0.0000152587890625, - "y": -0.0000152587890625, - "z": -0.0000152587890625, - "w": 1 - }, - "created": 1600122409224272, - "lastEditedBy": "{70099fa7-d189-42dc-80a0-02c37d1942d1}", - "queryAACube": { - "x": -7.811369895935059, - "y": -12.818197250366211, - "z": -7.892119884490967, - "scale": 15.704989433288574 - }, - "grab": { - "grabbable": false, - "equippableLeftRotation": { - "x": -0.0000152587890625, - "y": -0.0000152587890625, - "z": -0.0000152587890625, - "w": 1 - }, - "equippableRightRotation": { - "x": -0.0000152587890625, - "y": -0.0000152587890625, - "z": -0.0000152587890625, - "w": 1 - } - }, - "damping": 0, - "angularDamping": 0, - "intensity": 5, - "exponent": 1, - "cutoff": 75, - "falloffRadius": 1, - "clientOnly": false, - "avatarEntity": false, - "localEntity": false, - "faceCamera": false, - "isFacingAvatar": false } ], - "Id": "{190133e9-0517-4f19-b163-786c40f120ec}", - "Version": 128 + "Id": "{2fef14da-af5c-43f2-855c-b36bfa23d90f}", + "Version": 133 } diff --git a/interface/resources/serverless/tutorialqrc.json b/interface/resources/serverless/tutorialqrc.json new file mode 100644 index 0000000000..90d7e91aa3 --- /dev/null +++ b/interface/resources/serverless/tutorialqrc.json @@ -0,0 +1,2204 @@ +{ + "DataVersion": 0, + "Paths": { + "/old": "/0.155245,-0.941538,23.9289/0,0.791589,0,0.611053", + "/": "/21.6727,1.02002,25.1977/0,0.999868,0,-0.016252" + + }, + "Entities": [ + { + "id": "{0a199807-4a83-4286-b09c-f21124627c3e}", + "type": "Box", + "name": "Config Wizard Loader", + "locked": true, + "lastEdited": 1613737207915514, + "visible": false, + "position": { + "x": 21.8, + "y": 1.9, + "z": 28 + }, + "dimensions": { + "x": 0.20000000298023224, + "y": 0.20000000298023224, + "z": 0.20000000298023224 + }, + "rotation": { + "x": 3.5931313391301956e-7, + "y": -0.9996991753578186, + "z": 0.000014645980627392419, + "w": 0.024525845423340797 + }, + "created": 1613736996738696, + "lastEditedBy": "{ff9b500e-e450-4127-b41f-1c42be16f71b}", + "queryAACube": { + "x": -0.17320507764816284, + "y": -0.17320507764816284, + "z": -0.17320507764816284, + "scale": 0.3464101552963257 + }, + "grab": { + "grabbable": false + }, + "damping": 0, + "angularDamping": 0, + "collisionless": true, + "ignoreForCollisions": true, + "script": "qrc:///serverless/Scripts/wizardLoader.js", + "color": { + "red": 0, + "green": 180, + "blue": 239 + }, + "shape": "Cube", + "clientOnly": false, + "avatarEntity": false, + "localEntity": false, + "faceCamera": false, + "isFacingAvatar": false + }, + { + "id": "{b9444e0f-1cda-4ad3-80e5-9ef3bf0ec6cd}", + "type": "Model", + "lastEdited": 1617134731448079, + "name": "mirror_reflectingPlane", + "locked": true, + "userData": "{\"grabbableKey\":{\"grabbable\":false,\"ignoreIK\":false},\"original\":{\"id\":\"{6291b4e5-0dcb-484c-9c11-fe47725a4ad8}\"}}", + "position": { + "x": 3.3984665870666504, + "y": 1.891787052154541, + "z": 20.900876998901367 + }, + "dimensions": { + "x": 1.6291353702545166, + "y": 2.206333875656128, + "z": 0.01092288363724947 + }, + "rotation": { + "x": -0.0000152587890625, + "y": -0.8816205263137817, + "z": 0.0000152587890625, + "w": -0.4719768166542053 + }, + "created": 1614198986204053, + "lastEditedBy": "{0b759026-5fea-494c-99de-ab6301e73d4c}", + "queryAACube": { + "x": 2.0271434783935547, + "y": 0.5204638242721558, + "z": 19.52955436706543, + "scale": 2.7426464557647705 + }, + "grab": { + "grabbable": false, + "grabFollowsController": false, + "equippableLeftRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + }, + "equippableRightRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + } + }, + "collisionless": true, + "ignoreForCollisions": true, + "collisionMask": 0, + "collidesWith": "", + "script": "qrc:///serverless/Scripts/mirrorClient.js", + "scriptTimestamp": 1601084665601, + "modelURL": "qrc:///serverless/Models/mirror_without_backface.baked.fbx", + "blendshapeCoefficients": "{\n}\n", + "clientOnly": false, + "avatarEntity": false, + "localEntity": false, + "faceCamera": false, + "isFacingAvatar": false +}, + { + "id": "{61e0e141-bb95-4e7a-a043-3f4f783e39f4}", + "type": "Text", + "lastEdited": 1617134727215565, + "locked": true, + "description": "mirror text", + "position": { + "x": 3.306519031524658, + "y": 4.0622100830078125, + "z": 20.931333541870117 + }, + "dimensions": { + "x": 3.2473599910736084, + "y": 0.6462407112121582, + "z": 0.009999999776482582 + }, + "rotation": { + "x": 0.0008392333984375, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 0.999969482421875 + }, + "created": 1614383649622836, + "lastEditedBy": "{0b759026-5fea-494c-99de-ab6301e73d4c}", + "queryAACube": { + "x": 1.6509922742843628, + "y": 2.4066834449768066, + "z": 19.275806427001953, + "scale": 3.311053514480591 + }, + "billboardMode": "yaw", + "grab": { + "grabbable": false, + "equippableLeftRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + }, + "equippableRightRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + } + }, + "damping": 0, + "angularDamping": 0, + "collisionMask": 23, + "collidesWith": "static,dynamic,kinematic,otherAvatar,", + "text": "Mirror", + "lineHeight": 0.6000000238418579, + "textColor": { + "red": 0, + "green": 0, + "blue": 0 + }, + "backgroundAlpha": 0, + "unlit": true, + "font": "Inconsolata", + "textEffect": "outline fill", + "textEffectColor": { + "red": 0, + "green": 208, + "blue": 255 + }, + "textEffectThickness": 0.30000001192092896, + "alignment": "center", + "clientOnly": false, + "avatarEntity": false, + "localEntity": false, + "faceCamera": true, + "isFacingAvatar": false +}, + { + "id": "{4b1ac4d3-325b-46a2-9c27-0e94ee1afcaf}", + "type": "Model", + "lastEdited": 1617140845328587, + "name": "Seagull", + "locked": true, + "position": { + "x": 23.798669815063477, + "y": 4.926492214202881, + "z": 10.381175994873047 + }, + "dimensions": { + "x": 0.9342527389526367, + "y": 0.8603132963180542, + "z": 0.47802668809890747 + }, + "rotation": { + "x": -0.017654716968536377, + "y": -0.4898908734321594, + "z": 0.030106067657470703, + "w": 0.8710917234420776 + }, + "created": 1614198986205195, + "lastEditedBy": "{7f097416-1c40-4cba-aa7c-6e20a7281823}", + "queryAACube": { + "x": 23.12016487121582, + "y": 4.247987270355225, + "z": 9.70267105102539, + "scale": 1.3570102453231812 + }, + "grab": { + "grabbable": false, + "equippableLeftRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + }, + "equippableRightRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + } + }, + "damping": 0, + "angularDamping": 0, + "shapeType": "simple-compound", + "modelURL": "qrc:///serverless/Models/seagull-ANI.fbx", + "blendshapeCoefficients": "{\n}\n", + "animation": { + "url": "qrc:///serverless/Models/seagull-ANI.fbx", + "allowTranslation": false, + "currentFrame": 99.81153869628906, + "running": true, + "lastFrame": 120 + }, + "clientOnly": false, + "avatarEntity": false, + "localEntity": false, + "faceCamera": false, + "isFacingAvatar": false +}, + { + "id": "{7c7f80be-4fa3-4615-86f3-5446c6737350}", + "type": "Box", + "lastEdited": 1617140739515673, + "parentID": "{6c76b816-5064-424c-84b2-dbb478e47d5d}", + "visible": false, + "name": "Sound Emitter", + "locked": true, + "userData": "{\"soundURL\":\"qrc:///serverless/Sounds/468407__onderwish__sci-fi-survival-dreamscape.mp3\",\"shouldLoop\":true,\"volume\":0.18,\"refreshInterval\":100,\"grabbableKey\":{\"grabbable\":false}}", + "position": { + "x": 0, + "y": 1.0455207824707031, + "z": 0 + }, + "dimensions": { + "x": 0.20000000298023224, + "y": 0.20000000298023224, + "z": 0.20000000298023224 + }, + "rotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + }, + "created": 1614198017837347, + "lastEditedBy": "{7f097416-1c40-4cba-aa7c-6e20a7281823}", + "queryAACube": { + "x": 28.069303512573242, + "y": 5.205089092254639, + "z": 26.711923599243164, + "scale": 0.3464101552963257 + }, + "grab": { + "grabbable": false, + "equippableLeftRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + }, + "equippableRightRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + } + }, + "damping": 0, + "angularDamping": 0, + "script": "qrc:///serverless/Scripts/soundEmitter.js", + "scriptTimestamp": 1601079357399, + "color": { + "red": 0, + "green": 180, + "blue": 239 + }, + "shape": "Cube", + "clientOnly": false, + "avatarEntity": false, + "localEntity": false, + "faceCamera": false, + "isFacingAvatar": false +}, + { + "id": "{0436152a-b188-4608-abe9-a3fb1c4b283d}", + "type": "Model", + "lastEdited": 1617140818158676, + "name": "Vircadia Sign", + "locked": true, + "position": { + "x": 43.52519226074219, + "y": 4.912969589233398, + "z": 8.236417770385742 + }, + "dimensions": { + "x": 4.443090915679932, + "y": 0.7363157868385315, + "z": 0.16073395311832428 + }, + "rotation": { + "x": -0.0000152587890625, + "y": -0.7019302845001221, + "z": 0.0000152587890625, + "w": 0.7122453451156616 + }, + "created": 1614198986205729, + "lastEditedBy": "{7f097416-1c40-4cba-aa7c-6e20a7281823}", + "queryAACube": { + "x": 41.271915435791016, + "y": 2.659691333770752, + "z": 5.983139514923096, + "scale": 4.506556510925293 + }, + "grab": { + "grabbable": false, + "equippableLeftRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + }, + "equippableRightRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + } + }, + "damping": 0, + "angularDamping": 0, + "modelURL": "qrc:///serverless/Models/VircadiaLogo.fbx", + "blendshapeCoefficients": "{\n}\n", + "animation": { + "allowTranslation": false + }, + "clientOnly": false, + "avatarEntity": false, + "localEntity": false, + "faceCamera": false, + "isFacingAvatar": false +}, + { + "id": "{06b826d4-5385-4c49-92c2-47e24f97b35a}", + "type": "Text", + "lastEdited": 1617134764395172, + "name": "(2)", + "locked": true, + "description": "mirror text", + "position": { + "x": 34.17714309692383, + "y": 4.050739288330078, + "z": 27.204530715942383 + }, + "dimensions": { + "x": 3.2473599910736084, + "y": 0.6462407112121582, + "z": 0.009999999776482582 + }, + "rotation": { + "x": 0.0008392333984375, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 0.999969482421875 + }, + "created": 1614453280539951, + "lastEditedBy": "{0b759026-5fea-494c-99de-ab6301e73d4c}", + "queryAACube": { + "x": 32.5216178894043, + "y": 2.3952126502990723, + "z": 25.54900360107422, + "scale": 3.311053514480591 + }, + "billboardMode": "yaw", + "grab": { + "grabbable": false, + "equippableLeftRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + }, + "equippableRightRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + } + }, + "damping": 0, + "angularDamping": 0, + "collisionMask": 23, + "collidesWith": "static,dynamic,kinematic,otherAvatar,", + "text": "Controls", + "lineHeight": 0.6000000238418579, + "textColor": { + "red": 0, + "green": 0, + "blue": 0 + }, + "backgroundAlpha": 0, + "unlit": true, + "font": "Inconsolata", + "textEffect": "outline fill", + "textEffectColor": { + "red": 0, + "green": 208, + "blue": 255 + }, + "textEffectThickness": 0.30000001192092896, + "alignment": "center", + "clientOnly": false, + "avatarEntity": false, + "localEntity": false, + "faceCamera": true, + "isFacingAvatar": false +}, + { + "id": "{159f2743-d862-47e3-9f27-5de062b09941}", + "type": "Material", + "lastEdited": 1617140810844450, + "parentID": "{0436152a-b188-4608-abe9-a3fb1c4b283d}", + "parentJointIndex": 0, + "name": "VClogo", + "locked": true, + "userData": "{\"verticalOffset\":0,\"segments\":16,\"updateInterval\":1000}", + "position": { + "x": -0.00001823902130126953, + "y": -0.0002636909484863281, + "z": 0.10145187377929688 + }, + "rotation": { + "x": 0.0012969970703125, + "y": 0.0000152587890625, + "z": 0.0000457763671875, + "w": 0.999969482421875 + }, + "created": 1614198986205783, + "lastEditedBy": "{7f097416-1c40-4cba-aa7c-6e20a7281823}", + "queryAACube": { + "x": 47.7151985168457, + "y": 1.0358200073242188, + "z": 24.254812240600586, + "scale": 4.506557464599609 + }, + "canCastShadow": false, + "grab": { + "grabbable": false, + "equippableLeftRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + }, + "equippableRightRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + } + }, + "collisionMask": 23, + "collidesWith": "static,dynamic,kinematic,otherAvatar,", + "scriptTimestamp": 1597610738986, + "materialURL": "materialData", + "priority": 3, + "parentMaterialName": "[mat::NeonTubes]", + "materialMappingPos": { + "x": 0.8125, + "y": 0 + }, + "materialData": "{\"materialVersion\":1,\"materials\":[{\"name\":\"baseMaterial2\",\"model\":\"hifi_pbr\",\"opacity\":1,\"albedo\":[0,0,0],\"roughness\":1,\"metallic\":0,\"emissive\":[2.3,2,2],\"scattering\":0,\"unlit\":false,\"opacityMapMode\":\"OPACITY_MAP_MASK\",\"cullFaceMode\":\"CULL_BACK\",\"defaultFallthrough\":false}]}", + "clientOnly": false, + "avatarEntity": false, + "localEntity": false, + "faceCamera": false, + "isFacingAvatar": false +}, +{ + "id": "{5b6443c5-ec22-4c8a-9581-85134ceb6856}", + "parentID": "{6c76b816-5064-424c-84b2-dbb478e47d5d}", + "type": "Model", + "name": "Bowl", + "locked": true, + "lastEdited": 1617218059378792, + "dimensions": { + "x": 1.7757656574249268, + "y": 1.2933320999145508, + "z": 1.7757654190063477 + }, + "rotation": { + "x": -0.000030517578125, + "y": -0.000030517578125, + "z": -0.000030517578125, + "w": 1 + }, + "created": 1617216882976266, + "lastEditedBy": "{f72b151a-b325-4c9f-805a-7a7a520f82f7}", + "position": { + "x": -0.00001823902130126953, + "y": -5.1002636909484863281, + "z": 0.10145187377929688 + }, + "queryAACube": { + "x": -1.4123910665512085, + "y": -1.4123910665512085, + "z": -1.4123910665512085, + "scale": 2.824782133102417 + }, + "grab": { + "grabbable": false, + "equippableLeftRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + }, + "equippableRightRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + } + }, + "damping": 0, + "angularDamping": 0, + "shapeType": "static-mesh", + "modelURL": "qrc:///serverless/Models/bowl2.fbx", + "blendshapeCoefficients": "{\n}\n", + "animation": { + "allowTranslation": false + }, + "clientOnly": false, + "avatarEntity": false, + "localEntity": false, + "faceCamera": false, + "isFacingAvatar": false +}, + { + "id": "{9c451827-4c87-4bf7-8372-aeb6bbd61eaa}", + "type": "ParticleEffect", + "lastEdited": 1617217817025177, + "parentID": "{5b6443c5-ec22-4c8a-9581-85134ceb6856}", + "name": "Brew", + "locked": true, + "position": { + "x": 0, + "y": 0.44699999690055847, + "z": 0 + }, + "dimensions": { + "x": 16.263307571411133, + "y": 16.263307571411133, + "z": 16.263307571411133 + }, + "rotation": { + "x": 8.988587651970192e-12, + "y": -0.00008631677337689325, + "z": -0.7071500420570374, + "w": 0.7070636749267578 + }, + "created": 1617216898348298, + "lastEditedBy": "{f72b151a-b325-4c9f-805a-7a7a520f82f7}", + "queryAACube": { + "x": 7.714627265930176, + "y": -12.719738006591797, + "z": -5.470824241638184, + "scale": 28.168874740600586 + }, + "grab": { + "grabbable": false, + "equippableLeftRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + }, + "equippableRightRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + } + }, + "damping": 0, + "angularDamping": 0, + "shapeType": "ellipsoid", + "color": { + "red": 4, + "green": 101, + "blue": 143 + }, + "alpha": 0.30000001192092896, + "textures": "qrc:///serverless/Textures/default_particle.png", + "maxParticles": 80, + "lifespan": 2, + "emitRate": 47, + "emitSpeed": 0.30000001192092896, + "speedSpread": 0, + "emitOrientation": { + "x": 0, + "y": 0, + "z": 0, + "w": 1 + }, + "emitDimensions": { + "x": 1, + "y": 1, + "z": 0 + }, + "emitRadiusStart": 0, + "polarStart": 0.8700000047683716, + "polarFinish": 1.2200000286102295, + "azimuthStart": 3.0999999046325684, + "azimuthFinish": 3.140000104904175, + "emitAcceleration": { + "x": 0, + "y": -0.9900000095367432, + "z": 0 + }, + "accelerationSpread": { + "x": 0.10000000149011612, + "y": 0.3400000035762787, + "z": 0.10000000149011612 + }, + "particleRadius": 1.5, + "radiusStart": 0.5, + "radiusFinish": 0.30000001192092896, + "colorSpread": { + "red": 0, + "green": 150, + "blue": 150 + }, + "colorStart": { + "red": 0, + "green": 0, + "blue": 0 + }, + "colorFinish": { + "red": 0, + "green": 0, + "blue": 0 + }, + "alphaStart": 0.5, + "alphaFinish": 0, + "emitterShouldTrail": true, + "spinStart": null, + "spinFinish": null, + "clientOnly": false, + "avatarEntity": false, + "localEntity": false, + "faceCamera": false, + "isFacingAvatar": false +}, + { + "id": "{77cbbb3f-e1fe-436c-8b0a-11b45b96181b}", + "type": "ParticleEffect", + "lastEdited": 1617216897203063, + "parentID": "{5b6443c5-ec22-4c8a-9581-85134ceb6856}", + "name": "steam", + "locked": true, + "position": { + "x": 0.03824615478515625, + "y": 5.34733772277832, + "z": 0.057065125554800034 + }, + "dimensions": { + "x": 14.4042329788208, + "y": 14.4042329788208, + "z": 14.4042329788208 + }, + "rotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + }, + "created": 1617216882977327, + "lastEditedBy": "{7f097416-1c40-4cba-aa7c-6e20a7281823}", + "queryAACube": { + "x": 9.363174438476562, + "y": -6.209394454956055, + "z": -3.8040504455566406, + "scale": 24.948863983154297 + }, + "grab": { + "grabbable": false, + "equippableLeftRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + }, + "equippableRightRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + } + }, + "damping": 0, + "angularDamping": 0, + "shapeType": "ellipsoid", + "alpha": 0.014999999664723873, + "textures": "qrc:///serverless/Textures/default_particle.png", + "maxParticles": 100, + "lifespan": 3.069999933242798, + "emitSpeed": 0.4000000059604645, + "speedSpread": 0.10000000149011612, + "emitOrientation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + }, + "polarFinish": 3.1415927410125732, + "emitAcceleration": { + "x": 0, + "y": -1, + "z": 0 + }, + "particleRadius": 1.5, + "radiusStart": 0.5, + "radiusFinish": 0.4000000059604645, + "colorStart": { + "red": 0, + "green": 0, + "blue": 0 + }, + "colorFinish": { + "red": 0, + "green": 0, + "blue": 0 + }, + "alphaStart": 0.5, + "alphaFinish": 0, + "emitterShouldTrail": true, + "spinStart": null, + "spinFinish": null, + "clientOnly": false, + "avatarEntity": false, + "localEntity": false, + "faceCamera": false, + "isFacingAvatar": false +}, + { + "id": "{463bad19-9d44-479e-af6c-9d86ee76fc45}", + "type": "Light", + "lastEdited": 1617217841543322, + "parentID": "{5b6443c5-ec22-4c8a-9581-85134ceb6856}", + "name": "blacklight", + "locked": true, + "position": { + "x": 0, + "y": 1.6233999729156494, + "z": 0 + }, + "dimensions": { + "x": 3.867255687713623, + "y": 3.867255687713623, + "z": 4.0243144035339355 + }, + "rotation": { + "x": -0.7071176171302795, + "y": 3.849143226375418e-12, + "z": -0.000021579189706244506, + "w": 0.7070960402488708 + }, + "created": 1617217525079443, + "lastEditedBy": "{f72b151a-b325-4c9f-805a-7a7a520f82f7}", + "queryAACube": { + "x": 18.404050827026367, + "y": -0.8539872169494629, + "z": 5.2184553146362305, + "scale": 6.790172100067139 + }, + "grab": { + "grabbable": false, + "equippableLeftRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + }, + "equippableRightRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + } + }, + "damping": 0, + "angularDamping": 0, + "isSpotlight": true, + "intensity": -25.700000762939453, + "exponent": 19.6299991607666, + "cutoff": 73.94000244140625, + "falloffRadius": 72.4000015258789, + "clientOnly": false, + "avatarEntity": false, + "localEntity": false, + "faceCamera": false, + "isFacingAvatar": false +}, + { + "id": "{a80ee618-752e-44e4-a9de-04f089b4fe03}", + "type": "Model", + "lastEdited": 1617140830643374, + "parentID": "{6c76b816-5064-424c-84b2-dbb478e47d5d}", + "name": "Dome Glass", + "locked": true, + "position": { + "x": -0.000016799232980702072, + "y": 3.1790809631347656, + "z": 0.000016798756405478343 + }, + "dimensions": { + "x": 44.38727569580078, + "y": 7.3717122077941895, + "z": 44.38727569580078 + }, + "rotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + }, + "created": 1614198986204337, + "lastEditedBy": "{7f097416-1c40-4cba-aa7c-6e20a7281823}", + "queryAACube": { + "x": -3.359670639038086, + "y": -24.09037208557129, + "z": -4.717145919799805, + "scale": 63.20445251464844 + }, + "grab": { + "grabbable": false, + "equippableLeftRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + }, + "equippableRightRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + } + }, + "damping": 0, + "angularDamping": 0, + "shapeType": "static-mesh", + "modelURL": "qrc:///serverless/Models/dome2_glass.glb", + "blendshapeCoefficients": "{\n}\n", + "animation": { + "allowTranslation": false + }, + "clientOnly": false, + "avatarEntity": false, + "localEntity": false, + "faceCamera": false, + "isFacingAvatar": false +}, + { + "id": "{d2ef46ed-c85f-4ab5-bef3-14feb46e9091}", + "type": "Model", + "lastEdited": 1617134717193282, + "parentID": "{6c76b816-5064-424c-84b2-dbb478e47d5d}", + "name": "trees", + "locked": true, + "position": { + "x": -0.000016800577213871293, + "y": -0.5505132675170898, + "z": 0.000016800084267742932 + }, + "dimensions": { + "x": 26.59911346435547, + "y": 9.549417495727539, + "z": 26.465896606445312 + }, + "rotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + }, + "created": 1614198986202454, + "lastEditedBy": "{0b759026-5fea-494c-99de-ab6301e73d4c}", + "queryAACube": { + "x": 8.883026123046875, + "y": -15.577155113220215, + "z": 7.525779724121094, + "scale": 38.71883010864258 + }, + "grab": { + "grabbable": false, + "equippableLeftRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + }, + "equippableRightRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + } + }, + "damping": 0, + "angularDamping": 0, + "modelURL": "qrc:///serverless/Models/Trees1.glb", + "blendshapeCoefficients": "{\n}\n", + "animation": { + "allowTranslation": false + }, + "clientOnly": false, + "avatarEntity": false, + "localEntity": false, + "faceCamera": false, + "isFacingAvatar": false +}, + { + "id": "{f3d87e87-a250-42f8-a285-84cbeb777353}", + "type": "Model", + "lastEdited": 1617140880548597, + "parentID": "{6c76b816-5064-424c-84b2-dbb478e47d5d}", + "name": "Panels", + "locked": true, + "position": { + "x": -0.0001735687255859375, + "y": -5.685686111450195, + "z": 0.00017449550796300173 + }, + "dimensions": { + "x": 36.70009231567383, + "y": 3.3704721927642822, + "z": 25.731521606445312 + }, + "rotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + }, + "created": 1614377167635894, + "lastEditedBy": "{7f097416-1c40-4cba-aa7c-6e20a7281823}", + "queryAACube": { + "x": -5.742575168609619, + "y": -23.827165603637695, + "z": 4.4112548828125, + "scale": 59.816864013671875 + }, + "grab": { + "grabbable": false, + "equippableLeftRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + }, + "equippableRightRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + } + }, + "damping": 0, + "angularDamping": 0, + "modelURL": "qrc:///serverless/Models/Stands.fbx", + "blendshapeCoefficients": "{\n}\n", + "useOriginalPivot": true, + "animation": { + "url": "qrc:///serverless/Models/Stands.fbx", + "allowTranslation": false, + "currentFrame": 68342.515625, + "running": true + }, + "clientOnly": false, + "avatarEntity": false, + "localEntity": false, + "faceCamera": false, + "isFacingAvatar": false +}, + { + "id": "{25638e51-c19c-420a-a9cc-ff02626b62ef}", + "type": "Box", + "lastEdited": 1617134697724395, + "visible": false, + "name": "portalCube", + "locked": true, + "userData": "{\"destination\":\"hifi://172.104.248.237:40102/154.572,-96.8437,-417.945/0,1,0,-1.52586e-05\"}", + "position": { + "x": 0.06047534942626953, + "y": 1.751168131828308, + "z": 4.2923126220703125 + }, + "dimensions": { + "x": 1.6716244220733643, + "y": 2.5448203086853027, + "z": 0.26420968770980835 + }, + "rotation": { + "x": 0.0000152587890625, + "y": 0.6351872682571411, + "z": -0.0000457763671875, + "w": 0.772335410118103 + }, + "created": 1614454164933827, + "lastEditedBy": "{0b759026-5fea-494c-99de-ab6301e73d4c}", + "queryAACube": { + "x": -1.4676154851913452, + "y": 0.22307729721069336, + "z": 2.764221668243408, + "scale": 3.0561816692352295 + }, + "grab": { + "grabbable": false, + "equippableLeftRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + }, + "equippableRightRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + } + }, + "collisionMask": 23, + "collidesWith": "static,dynamic,kinematic,otherAvatar,", + "damping": 0, + "angularDamping": 0, + "script": "qrc:///serverless/Scripts/portal.js", + "scriptTimestamp": 1617134674001, + "color": { + "red": 0, + "green": 180, + "blue": 239 + }, + "shape": "Cube", + "clientOnly": false, + "avatarEntity": false, + "localEntity": false, + "faceCamera": false, + "isFacingAvatar": false +}, + { + "id": "{e0261cde-c5e0-44bf-a747-787c4c867d79}", + "type": "Light", + "lastEdited": 1617140788480898, + "name": "mainDomeLight", + "locked": true, + "position": { + "x": 21.799074172973633, + "y": 10.247319221496582, + "z": 8.613605499267578 + }, + "dimensions": { + "x": 61.943946838378906, + "y": 61.943946838378906, + "z": 61.943946838378906 + }, + "rotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + }, + "created": 1614198986202528, + "lastEditedBy": "{7f097416-1c40-4cba-aa7c-6e20a7281823}", + "queryAACube": { + "x": -31.845956802368164, + "y": -43.39771270751953, + "z": -45.03142547607422, + "scale": 107.2900619506836 + }, + "grab": { + "grabbable": false, + "equippableLeftRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + }, + "equippableRightRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + } + }, + "damping": 0, + "angularDamping": 0, + "collisionMask": 23, + "collidesWith": "static,dynamic,kinematic,otherAvatar,", + "color": { + "red": 255, + "green": 235, + "blue": 87 + }, + "intensity": 0.8999999761581421, + "exponent": 1, + "cutoff": 75, + "falloffRadius": 30, + "clientOnly": false, + "avatarEntity": false, + "localEntity": false, + "faceCamera": false, + "isFacingAvatar": false +}, + { + "id": "{6c76b816-5064-424c-84b2-dbb478e47d5d}", + "type": "Model", + "lastEdited": 1617134709051164, + "name": "Dome", + "locked": true, + "position": { + "x": 21.799192428588867, + "y": 5.9566450119018555, + "z": 8.613487243652344 + }, + "dimensions": { + "x": 54.60203552246094, + "y": 13.734564781188965, + "z": 54.60203552246094 + }, + "rotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + }, + "created": 1614198986203467, + "lastEditedBy": "{0b759026-5fea-494c-99de-ab6301e73d4c}", + "queryAACube": { + "x": -25952.515625, + "y": -25921.0625, + "z": -25953.87890625, + "scale": 51961.5234375 + }, + "grab": { + "grabbable": false, + "equippableLeftRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + }, + "equippableRightRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + } + }, + "damping": 0, + "angularDamping": 0, + "shapeType": "static-mesh", + "modelURL": "qrc:///serverless/Models/dome2.glb", + "blendshapeCoefficients": "{\n}\n", + "animation": { + "allowTranslation": false + }, + "clientOnly": false, + "avatarEntity": false, + "localEntity": false, + "faceCamera": false, + "isFacingAvatar": false +}, + { + "id": "{52c84c1c-6567-4670-9b2b-9aa9bc1456ea}", + "type": "Model", + "lastEdited": 1617134574674644, + "parentID": "{6c76b816-5064-424c-84b2-dbb478e47d5d}", + "locked": true, + "position": { + "x": 4.238387418808998e-12, + "y": -2.3088181018829346, + "z": -7.275957614183426e-12 + }, + "dimensions": { + "x": 5.688337802886963, + "y": 7.10263204574585, + "z": 5.688361644744873 + }, + "rotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + }, + "created": 1614198986204522, + "lastEditedBy": "{78b82b17-4e7a-410f-95ce-1c3ace1cd609}", + "queryAACube": { + "x": -4.850972652435303, + "y": -3.341723680496216, + "z": -4.9151411056518555, + "scale": 38.45905685424805 + }, + "grab": { + "grabbable": false, + "equippableLeftRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + }, + "equippableRightRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + } + }, + "damping": 0, + "angularDamping": 0, + "scriptTimestamp": 1598912452582, + "shapeType": "static-mesh", + "modelURL": "qrc:///serverless/Models/temple5.glb", + "blendshapeCoefficients": "{\n}\n", + "animation": { + "allowTranslation": false + }, + "clientOnly": false, + "avatarEntity": false, + "localEntity": false, + "faceCamera": false, + "isFacingAvatar": false +}, + { + "id": "{d344138a-adb8-4ae7-9aae-447266a48869}", + "type": "Light", + "lastEdited": 1617140788480765, + "parentID": "{b9444e0f-1cda-4ad3-80e5-9ef3bf0ec6cd}", + "name": "mirrorLight", + "locked": true, + "position": { + "x": -0.0015339851379394531, + "y": -0.000001519918441772461, + "z": 0.26983165740966797 + }, + "dimensions": { + "x": 3.8637032508850098, + "y": 3.8637032508850098, + "z": 4 + }, + "rotation": { + "x": 0.0000152587890625, + "y": 1, + "z": 0.0000152587890625, + "w": -0.0000152587890625 + }, + "created": 1614453808970411, + "lastEditedBy": "{7f097416-1c40-4cba-aa7c-6e20a7281823}", + "queryAACube": { + "x": 6.681288719177246, + "y": -3.11796498298645, + "z": 35.638336181640625, + "scale": 6.771735668182373 + }, + "grab": { + "grabbable": false, + "equippableLeftRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + }, + "equippableRightRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + } + }, + "damping": 0, + "angularDamping": 0, + "color": { + "red": 255, + "green": 255, + "blue": 235 + }, + "isSpotlight": true, + "intensity": 0.699999988079071, + "exponent": 1, + "cutoff": 75, + "falloffRadius": 10, + "clientOnly": false, + "avatarEntity": false, + "localEntity": false, + "faceCamera": false, + "isFacingAvatar": false +}, + { + "id": "{0d85144d-a15c-4d1b-84a5-b3a379d31798}", + "type": "Light", + "lastEdited": 1617140731977291, + "parentID": "{b9444e0f-1cda-4ad3-80e5-9ef3bf0ec6cd}", + "name": "Mirror Light", + "locked": true, + "position": { + "x": 0.08925724029541016, + "y": 0.4832591116428375, + "z": 0.20032405853271484 + }, + "dimensions": { + "x": 6.747879505157471, + "y": 6.747879505157471, + "z": 6.985918998718262 + }, + "rotation": { + "x": -0.999969482421875, + "y": -0.0001373291015625, + "z": -0.0000762939453125, + "w": 0.00856029987335205 + }, + "created": 1614198986203073, + "lastEditedBy": "{7f097416-1c40-4cba-aa7c-6e20a7281823}", + "queryAACube": { + "x": 4.045637607574463, + "y": -5.162182331085205, + "z": 33.07383346557617, + "scale": 11.826699256896973 + }, + "grab": { + "grabbable": false, + "equippableLeftRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + }, + "equippableRightRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + } + }, + "damping": 0, + "angularDamping": 0, + "isSpotlight": true, + "intensity": 2, + "exponent": 1, + "cutoff": 75, + "falloffRadius": 5.699999809265137, + "clientOnly": false, + "avatarEntity": false, + "localEntity": false, + "faceCamera": false, + "isFacingAvatar": false +}, + { + "id": "{89f2cd0b-782f-4e4e-a674-587ae5893f7d}", + "type": "Light", + "lastEdited": 1617140712801743, + "parentID": "{52c84c1c-6567-4670-9b2b-9aa9bc1456ea}", + "name": "templeLight", + "locked": true, + "position": { + "x": -0.10364770889282227, + "y": 0.5877461433410645, + "z": -0.16811557114124298 + }, + "dimensions": { + "x": 5.481564998626709, + "y": 5.481564998626709, + "z": 5.481564998626709 + }, + "rotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + }, + "created": 1614198986204117, + "lastEditedBy": "{7f097416-1c40-4cba-aa7c-6e20a7281823}", + "queryAACube": { + "x": 23.39162826538086, + "y": -2.135477066040039, + "z": 21.969898223876953, + "scale": 9.494348526000977 + }, + "grab": { + "grabbable": false, + "equippableLeftRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + }, + "equippableRightRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + } + }, + "damping": 0, + "angularDamping": 0, + "color": { + "red": 255, + "green": 0, + "blue": 255 + }, + "intensity": 10, + "exponent": 1, + "cutoff": 75, + "falloffRadius": 1, + "clientOnly": false, + "avatarEntity": false, + "localEntity": false, + "faceCamera": false, + "isFacingAvatar": false +}, + { + "id": "{3a740728-5d6f-4a3b-a710-49a8c6cb1ae0}", + "type": "Zone", + "lastEdited": 1617140938876740, + "parentID": "{6c76b816-5064-424c-84b2-dbb478e47d5d}", + "name": "MainDomeZone", + "locked": true, + "userData": "{\n \"grabbableKey\": {\n \"grabbable\": false,\n \"ignoreIK\": false\n }\n}", + "position": { + "x": 0.0006103417836129665, + "y": 55.367820739746094, + "z": -0.0006103613413870335 + }, + "dimensions": { + "x": 10000, + "y": 10000, + "z": 10000 + }, + "rotation": { + "x": 0.44721001386642456, + "y": 0.5232430100440979, + "z": 0.06775686889886856, + "w": 0.7222389578819275 + }, + "created": 1614198986203133, + "lastEditedBy": "{7f097416-1c40-4cba-aa7c-6e20a7281823}", + "queryAACube": { + "x": -25952.515625, + "y": -25921.0625, + "z": -25953.87890625, + "scale": 51961.5234375 + }, + "grab": { + "grabbable": false, + "grabFollowsController": false, + "equippableLeftRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + }, + "equippableRightRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + } + }, + "angularVelocity": { + "x": 0.008699734695255756, + "y": 0.008700265549123287, + "z": 8.107145163527285e-12 + }, + "angularDamping": 0, + "shapeType": "box", + "keyLight": { + "color": { + "red": 158, + "green": 127, + "blue": 68 + }, + "intensity": 1.5, + "direction": { + "x": 0.20760862529277802, + "y": -0.7512804269790649, + "z": 0.6264793872833252 + }, + "castShadows": true, + "shadowBias": 0.20000000298023224, + "shadowMaxDistance": 57.79999923706055 + }, + "ambientLight": { + "ambientIntensity": 0.8999999761581421, + "ambientURL": "qrc:///serverless/Textures/galaxySkybox.png" + }, + "skybox": { + "color": { + "red": 235, + "green": 235, + "blue": 235 + }, + "url": "qrc:///serverless/Textures/galaxySkybox.png" + }, + "haze": { + "hazeRange": 50, + "hazeColor": { + "red": 4, + "green": 25, + "blue": 94 + }, + "hazeGlareColor": { + "red": 255, + "green": 0, + "blue": 255 + }, + "hazeEnableGlare": true, + "hazeGlareAngle": 27, + "hazeAltitudeEffect": true, + "hazeCeiling": -75, + "hazeBaseRef": -250, + "hazeBackgroundBlend": 0.5 + }, + "bloom": { + "bloomIntensity": 0.4000000059604645, + "bloomThreshold": 0.800000011920929, + "bloomSize": 1 + }, + "keyLightMode": "enabled", + "ambientLightMode": "enabled", + "skyboxMode": "enabled", + "hazeMode": "enabled", + "bloomMode": "enabled", + "clientOnly": false, + "avatarEntity": false, + "localEntity": false, + "faceCamera": false, + "isFacingAvatar": false +}, + { + "id": "{c5a35dbf-8253-4782-b121-26d0c609aad5}", + "type": "Shape", + "lastEdited": 1617140925236269, + "parentID": "{6c76b816-5064-424c-84b2-dbb478e47d5d}", + "name": "MainCollision", + "locked": true, + "position": { + "x": 0.00002288818359375, + "y": -6.380376815795898, + "z": -0.00002409383887425065 + }, + "dimensions": { + "x": 54.22285461425781, + "y": 0.890187680721283, + "z": 54.22285461425781 + }, + "rotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + }, + "created": 1614198986204167, + "lastEditedBy": "{7f097416-1c40-4cba-aa7c-6e20a7281823}", + "queryAACube": { + "x": -10.101629257202148, + "y": -40.391536712646484, + "z": -11.458602905273438, + "scale": 76.6878662109375 + }, + "grab": { + "grabbable": false, + "equippableLeftRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + }, + "equippableRightRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + } + }, + "damping": 0, + "angularDamping": 0, + "color": { + "red": 0, + "green": 0, + "blue": 0 + }, + "shape": "Cylinder", + "clientOnly": false, + "avatarEntity": false, + "localEntity": false, + "faceCamera": false, + "isFacingAvatar": false +}, + { + "id": "{99f186d7-a623-4339-930e-1689d62a23e0}", + "type": "Zone", + "lastEdited": 1617134741129783, + "parentID": "{b9444e0f-1cda-4ad3-80e5-9ef3bf0ec6cd}", + "visible": false, + "name": "mirror_zone", + "locked": true, + "userData": "{\"grabbableKey\":{\"grabbable\":false},\"original\":{\"id\":\"{da1e2fcd-d69b-47d7-b861-25b31f1c7175}\"}}", + "position": { + "x": -0.01726818084716797, + "y": 0.2113490104675293, + "z": 1.704751968383789 + }, + "dimensions": { + "x": 2.8482747077941895, + "y": 3.153184413909912, + "z": 3.6725244522094727 + }, + "rotation": { + "x": -0.0161592960357666, + "y": 0.0000152587890625, + "z": -0.006424069404602051, + "w": 0.999847412109375 + }, + "created": 1614198986202623, + "lastEditedBy": "{0b759026-5fea-494c-99de-ab6301e73d4c}", + "queryAACube": { + "x": 8.46190071105957, + "y": -2.328949451446533, + "z": 35.4334716796875, + "scale": 5.6162872314453125 + }, + "grab": { + "grabbable": false, + "equippableLeftRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + }, + "equippableRightRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + } + }, + "script": "qrc:///serverless/Scripts/mirrorReflection.js", + "scriptTimestamp": 1601084668318, + "shapeType": "box", + "clientOnly": false, + "avatarEntity": false, + "localEntity": false, + "faceCamera": false, + "isFacingAvatar": false +}, + { + "id": "{33d5305a-641d-4a4f-baa9-23ec22bb9d48}", + "type": "Light", + "lastEdited": 1617140731977526, + "parentID": "{6c76b816-5064-424c-84b2-dbb478e47d5d}", + "name": "TreeLight_4", + "locked": true, + "position": { + "x": -8.819656372070312, + "y": -0.07544326782226562, + "z": -9.190401077270508 + }, + "dimensions": { + "x": 10.24996280670166, + "y": 10.24996280670166, + "z": 10.24996280670166 + }, + "rotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + }, + "created": 1614198986202730, + "lastEditedBy": "{7f097416-1c40-4cba-aa7c-6e20a7281823}", + "queryAACube": { + "x": 10.546369552612305, + "y": -4.619409561157227, + "z": 8.817764282226562, + "scale": 17.753456115722656 + }, + "grab": { + "grabbable": false, + "equippableLeftRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + }, + "equippableRightRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + } + }, + "damping": 0, + "angularDamping": 0, + "color": { + "red": 250, + "green": 214, + "blue": 32 + }, + "intensity": 15, + "exponent": 1, + "cutoff": 75, + "falloffRadius": 26.100000381469727, + "clientOnly": false, + "avatarEntity": false, + "localEntity": false, + "faceCamera": false, + "isFacingAvatar": false +}, + { + "id": "{67b2c758-41ea-4448-80eb-f171d792ab5c}", + "type": "Box", + "lastEdited": 1617140777516274, + "visible": false, + "name": "LandingPoint", + "locked": true, + "position": { + "x": 21.792818069458008, + "y": 0, + "z": 25.644922256469727 + }, + "dimensions": { + "x": 3.2382099628448486, + "y": 0.20000000298023224, + "z": 1.8551445007324219 + }, + "rotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + }, + "created": 1617140160943861, + "lastEditedBy": "{7f097416-1c40-4cba-aa7c-6e20a7281823}", + "queryAACube": { + "x": 19.924158096313477, + "y": -1.8686603307724, + "z": 23.776262283325195, + "scale": 3.7373206615448 + }, + "grab": { + "grabbable": false, + "equippableLeftRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + }, + "equippableRightRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + } + }, + "damping": 0, + "angularDamping": 0, + "color": { + "red": 0, + "green": 180, + "blue": 239 + }, + "shape": "Cube", + "clientOnly": false, + "avatarEntity": false, + "localEntity": false, + "faceCamera": false, + "isFacingAvatar": false +}, + { + "id": "{a4421b2e-123a-4619-8788-e36eef8029ea}", + "type": "Light", + "lastEdited": 1617140788480412, + "parentID": "{6c76b816-5064-424c-84b2-dbb478e47d5d}", + "name": "TreeLight_2", + "locked": true, + "position": { + "x": -8.819664001464844, + "y": -0.24757671356201172, + "z": 8.97313404083252 + }, + "dimensions": { + "x": 10.24996280670166, + "y": 10.24996280670166, + "z": 10.24996280670166 + }, + "rotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + }, + "created": 1614198986202574, + "lastEditedBy": "{7f097416-1c40-4cba-aa7c-6e20a7281823}", + "queryAACube": { + "x": 10.54580307006836, + "y": -4.790988445281982, + "z": 26.981304168701172, + "scale": 17.753456115722656 + }, + "grab": { + "grabbable": false, + "equippableLeftRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + }, + "equippableRightRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + } + }, + "damping": 0, + "angularDamping": 0, + "color": { + "red": 191, + "green": 31, + "blue": 255 + }, + "intensity": 15, + "exponent": 1, + "cutoff": 75, + "falloffRadius": 26.100000381469727, + "clientOnly": false, + "avatarEntity": false, + "localEntity": false, + "faceCamera": false, + "isFacingAvatar": false +}, + { + "id": "{523e1c2d-1603-47bb-80f1-314747b161b0}", + "type": "Material", + "lastEdited": 1617140991884044, + "parentID": "{f3d87e87-a250-42f8-a285-84cbeb777353}", + "parentJointIndex": 4, + "name": "moveMaterial", + "userData": "{\n \"verticalOffset\": 0,\n \"segments\": 64,\n \"updateInterval\": 200\n}", + "position": { + "x": 0.00000476837158203125, + "y": 7.152557373046875e-7, + "z": 0.000003814697265625 + }, + "rotation": { + "x": -0.0000152587890625, + "y": -0.0000457763671875, + "z": -0.0000152587890625, + "w": 1 + }, + "created": 1614382837959471, + "lastEditedBy": "{7f097416-1c40-4cba-aa7c-6e20a7281823}", + "queryAACube": { + "x": -5.742575168609619, + "y": -21.97960662841797, + "z": 11.547750473022461, + "scale": 52.68036651611328 + }, + "canCastShadow": false, + "grab": { + "grabbable": false, + "equippableLeftRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + }, + "equippableRightRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + } + }, + "collisionMask": 23, + "collidesWith": "static,dynamic,kinematic,otherAvatar,", + "script": "qrc:///serverless/Scripts/materialSequencer.js", + "scriptTimestamp": 1601250646975, + "materialURL": "materialData", + "priority": 3, + "parentMaterialName": "[mat::move]", + "materialMappingPos": { + "x": 0.265625, + "y": 0 + }, + "materialData": "{\"materialVersion\":1,\"materials\":[{\"name\":\"moveMaterial\",\"model\":\"hifi_pbr\",\"opacity\":0.8,\"albedo\":[1,1,1],\"roughness\":1,\"metallic\":0,\"emissive\":[0,0,0],\"scattering\":0,\"unlit\":false,\"emissiveMap\":\"qrc:///serverless/Textures/gradient1.jpg\",\"albedoMap\":\"qrc:///serverless/Textures/gradient1.jpg\",\"opacityMapMode\":\"OPACITY_MAP_BLEND\",\"cullFaceMode\":\"CULL_NONE\",\"defaultFallthrough\":false}]}", + "clientOnly": false, + "avatarEntity": false, + "localEntity": false, + "faceCamera": false, + "isFacingAvatar": false +}, + { + "id": "{35eb5c90-08e6-44de-b6b9-46c9fd36494a}", + "type": "Text", + "lastEdited": 1617134723640851, + "name": "(2)", + "locked": true, + "description": "mirror text", + "position": { + "x": 0, + "y": 4.090241432189941, + "z": 4.291414260864258 + }, + "dimensions": { + "x": 3.2473599910736084, + "y": 0.6462407112121582, + "z": 0.009999999776482582 + }, + "rotation": { + "x": 0.0008392333984375, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 0.999969482421875 + }, + "created": 1614453187953099, + "lastEditedBy": "{0b759026-5fea-494c-99de-ab6301e73d4c}", + "queryAACube": { + "x": -1.6555267572402954, + "y": 2.4347147941589355, + "z": 2.635887622833252, + "scale": 3.311053514480591 + }, + "billboardMode": "yaw", + "grab": { + "grabbable": false, + "equippableLeftRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + }, + "equippableRightRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + } + }, + "damping": 0, + "angularDamping": 0, + "collisionMask": 23, + "collidesWith": "static,dynamic,kinematic,otherAvatar,", + "text": "Portal", + "lineHeight": 0.6000000238418579, + "textColor": { + "red": 0, + "green": 0, + "blue": 0 + }, + "backgroundAlpha": 0, + "unlit": true, + "font": "Inconsolata", + "textEffect": "outline fill", + "textEffectColor": { + "red": 0, + "green": 208, + "blue": 255 + }, + "textEffectThickness": 0.30000001192092896, + "alignment": "center", + "clientOnly": false, + "avatarEntity": false, + "localEntity": false, + "faceCamera": true, + "isFacingAvatar": false +}, + { + "id": "{7d040847-617e-494b-9593-05ab35142098}", + "type": "Light", + "lastEdited": 1617140731977921, + "parentID": "{6c76b816-5064-424c-84b2-dbb478e47d5d}", + "name": "TreeLight_3", + "locked": true, + "position": { + "x": 9.418960571289062, + "y": -0.07544326782226562, + "z": -9.190400123596191 + }, + "dimensions": { + "x": 10.24996280670166, + "y": 10.24996280670166, + "z": 10.24996280670166 + }, + "rotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + }, + "created": 1614198986202887, + "lastEditedBy": "{7f097416-1c40-4cba-aa7c-6e20a7281823}", + "queryAACube": { + "x": 28.784984588623047, + "y": -4.61996603012085, + "z": 8.818321228027344, + "scale": 17.753456115722656 + }, + "grab": { + "grabbable": false, + "equippableLeftRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + }, + "equippableRightRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + } + }, + "damping": 0, + "angularDamping": 0, + "color": { + "red": 69, + "green": 255, + "blue": 69 + }, + "intensity": 20.5, + "exponent": 1, + "cutoff": 75, + "falloffRadius": 26.100000381469727, + "clientOnly": false, + "avatarEntity": false, + "localEntity": false, + "faceCamera": false, + "isFacingAvatar": false +}, + { + "id": "{c191dc9f-7a8e-4f98-9974-b23c9bb7992d}", + "type": "Light", + "lastEdited": 1617140788480592, + "parentID": "{6c76b816-5064-424c-84b2-dbb478e47d5d}", + "name": "TreeLight_1", + "locked": true, + "position": { + "x": 9.000457763671875, + "y": -0.2475719451904297, + "z": 8.999537467956543 + }, + "dimensions": { + "x": 10.24996280670166, + "y": 10.24996280670166, + "z": 10.24996280670166 + }, + "rotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + }, + "created": 1614198986203735, + "lastEditedBy": "{7f097416-1c40-4cba-aa7c-6e20a7281823}", + "queryAACube": { + "x": 28.365924835205078, + "y": -4.791526794433594, + "z": 27.008251190185547, + "scale": 17.753456115722656 + }, + "grab": { + "grabbable": false, + "equippableLeftRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + }, + "equippableRightRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + } + }, + "damping": 0, + "angularDamping": 0, + "color": { + "red": 69, + "green": 106, + "blue": 255 + }, + "intensity": 17.799999237060547, + "exponent": 1, + "cutoff": 75, + "falloffRadius": 26.100000381469727, + "clientOnly": false, + "avatarEntity": false, + "localEntity": false, + "faceCamera": false, + "isFacingAvatar": false +}, + { + "id": "{cf666211-2b88-4ee6-af3c-a1a92bd6c513}", + "type": "Model", + "lastEdited": 1617140858220173, + "parentID": "{6c76b816-5064-424c-84b2-dbb478e47d5d}", + "name": "Planters", + "locked": true, + "position": { + "x": -0.00016648943710606545, + "y": -5.586750030517578, + "z": 0.00017049156303983182 + }, + "dimensions": { + "x": 19.592937469482422, + "y": 0.6371747255325317, + "z": 19.592937469482422 + }, + "rotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + }, + "created": 1614198986203890, + "lastEditedBy": "{7f097416-1c40-4cba-aa7c-6e20a7281823}", + "queryAACube": { + "x": 14.384176254272461, + "y": -15.1119384765625, + "z": 13.02754020690918, + "scale": 27.715923309326172 + }, + "grab": { + "grabbable": false, + "equippableLeftRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + }, + "equippableRightRotation": { + "x": -0.0000152587890625, + "y": -0.0000152587890625, + "z": -0.0000152587890625, + "w": 1 + } + }, + "damping": 0, + "angularDamping": 0, + "shapeType": "static-mesh", + "modelURL": "qrc:///serverless/Models/Planter.glb", + "blendshapeCoefficients": "{\n}\n", + "animation": { + "allowTranslation": false + }, + "clientOnly": false, + "avatarEntity": false, + "localEntity": false, + "faceCamera": false, + "isFacingAvatar": false +} + ], + "Id": "{2fef14da-af5c-43f2-855c-b36bfa23d90f}", + "Version": 133 +} diff --git a/interface/src/AboutUtil.h b/interface/src/AboutUtil.h index f072ae8b4a..0ec3691863 100644 --- a/interface/src/AboutUtil.h +++ b/interface/src/AboutUtil.h @@ -16,7 +16,7 @@ #include -/**jsdoc +/*@jsdoc * The About API provides information about the version of Interface that is currently running. It also has the * functionality to open a web page in an Interface browser window. * @@ -41,7 +41,7 @@ * print("Qt version: " + About.qtVersion); */ - /**jsdoc + /*@jsdoc * The HifiAbout API provides information about the version of Interface that is currently running. It also * has the functionality to open a web page in an Interface browser window. * @@ -82,7 +82,7 @@ public: public slots: - /**jsdoc + /*@jsdoc * Display a web page in an Interface browser window or the tablet. * @function About.openUrl * @param {string} url - The URL of the web page you want to view in Interface. diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index c1d28fa7f9..e7920b4b30 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -658,7 +658,7 @@ private: } }; -/**jsdoc +/*@jsdoc *

The Controller.Hardware.Application object has properties representing Interface's state. The property * values are integer IDs, uniquely identifying each output. Read-only.

*

These states can be mapped to actions or functions or Controller.Standard items in a {@link RouteObject} @@ -1012,7 +1012,7 @@ const bool DEFAULT_HMD_TABLET_BECOMES_TOOLBAR = false; const bool DEFAULT_PREFER_STYLUS_OVER_LASER = false; const bool DEFAULT_PREFER_AVATAR_FINGER_OVER_STYLUS = false; const QString DEFAULT_CURSOR_NAME = "DEFAULT"; -const bool DEFAULT_MINI_TABLET_ENABLED = true; +const bool DEFAULT_MINI_TABLET_ENABLED = false; const bool DEFAULT_AWAY_STATE_WHEN_FOCUS_LOST_IN_VR_ENABLED = true; QSharedPointer getOffscreenUI() { @@ -1307,6 +1307,9 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo _entityServerConnectionTimer.setSingleShot(true); connect(&_entityServerConnectionTimer, &QTimer::timeout, this, &Application::setFailedToConnectToEntityServer); + connect(&domainHandler, &DomainHandler::confirmConnectWithoutAvatarEntities, + this, &Application::confirmConnectWithoutAvatarEntities); + connect(&domainHandler, &DomainHandler::connectedToDomain, this, [this]() { if (!isServerlessMode()) { _entityServerConnectionTimer.setInterval(ENTITY_SERVER_ADDED_TIMEOUT); @@ -1970,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 @@ -2520,7 +2523,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo return viewFrustum.getPosition(); }); - DependencyManager::get()->setKickConfirmationOperator([this] (const QUuid& nodeID) { userKickConfirmation(nodeID); }); + DependencyManager::get()->setKickConfirmationOperator([this] (const QUuid& nodeID, unsigned int banFlags) { userKickConfirmation(nodeID, banFlags); }); render::entities::WebEntityRenderer::setAcquireWebSurfaceOperator([=](const QString& url, bool htmlContent, QSharedPointer& webSurface, bool& cachedWebSurface) { bool isTablet = url == TabletScriptingInterface::QML; @@ -2648,7 +2651,7 @@ void Application::setCachebustRequire() { return; } bool enable = menu->isOptionChecked(MenuOption::CachebustRequire); - + Setting::Handle{ CACHEBUST_SCRIPT_REQUIRE_SETTING_NAME, false }.set(enable); } @@ -3016,6 +3019,8 @@ Application::~Application() { qInstallMessageHandler(LogHandler::verboseMessageHandler); #ifdef Q_OS_MAC + // 26 Feb 2021 - Tried re-enabling this call but OSX still crashes on exit. + // // 10/16/2019 - Disabling this call. This causes known crashes (A), and it is not // fully understood whether it might cause other unknown crashes (B). // @@ -3268,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 { @@ -3600,7 +3605,7 @@ void Application::onDesktopRootItemCreated(QQuickItem* rootItem) { _desktopRootItemCreated = true; } -void Application::userKickConfirmation(const QUuid& nodeID) { +void Application::userKickConfirmation(const QUuid& nodeID, unsigned int banFlags) { auto avatarHashMap = DependencyManager::get(); auto avatar = avatarHashMap->getAvatarBySessionID(nodeID); @@ -3625,7 +3630,7 @@ void Application::userKickConfirmation(const QUuid& nodeID) { // ask the NodeList to kick the user with the given session ID if (yes) { - DependencyManager::get()->kickNodeBySessionID(nodeID); + DependencyManager::get()->kickNodeBySessionID(nodeID, banFlags); } DependencyManager::get()->setWaitForKickResponse(false); @@ -4040,11 +4045,11 @@ void Application::handleSandboxStatus(QNetworkReply* reply) { // If this is a first run we short-circuit the address passed in if (_firstRun.get()) { - if (!BuildInfo::INITIAL_STARTUP_LOCATION.isEmpty()) { + if (!BuildInfo::PRELOADED_STARTUP_LOCATION.isEmpty()) { DependencyManager::get()->setHomeLocationToAddress(NetworkingConstants::DEFAULT_VIRCADIA_ADDRESS); Menu::getInstance()->triggerOption(MenuOption::HomeLocation); } - + if (!_overrideEntry) { DependencyManager::get()->goToEntry(); sentTo = SENT_TO_ENTRY; @@ -7220,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; } @@ -7923,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); @@ -9199,6 +9204,32 @@ void Application::setShowBulletConstraintLimits(bool value) { _physicsEngine->setShowBulletConstraintLimits(value); } +void Application::confirmConnectWithoutAvatarEntities() { + + if (_confirmConnectWithoutAvatarEntitiesDialog) { + // Dialog is already displayed. + return; + } + + if (!getMyAvatar()->hasAvatarEntities()) { + // No avatar entities so continue with login. + DependencyManager::get()->getDomainHandler().setCanConnectWithoutAvatarEntities(true); + return; + } + + QString continueMessage = "Your wearables will not display on this domain. Continue?"; + _confirmConnectWithoutAvatarEntitiesDialog = OffscreenUi::asyncQuestion("Continue Without Wearables", continueMessage, + QMessageBox::Yes | QMessageBox::No); + if (_confirmConnectWithoutAvatarEntitiesDialog->getDialogItem()) { + QObject::connect(_confirmConnectWithoutAvatarEntitiesDialog, &ModalDialogListener::response, this, [=](QVariant answer) { + QObject::disconnect(_confirmConnectWithoutAvatarEntitiesDialog, &ModalDialogListener::response, this, nullptr); + _confirmConnectWithoutAvatarEntitiesDialog = nullptr; + bool shouldConnect = (static_cast(answer.toInt()) == QMessageBox::Yes); + DependencyManager::get()->getDomainHandler().setCanConnectWithoutAvatarEntities(shouldConnect); + }); + } +} + void Application::createLoginDialog() { const glm::vec3 LOGIN_DIMENSIONS { 0.89f, 0.5f, 0.01f }; const auto OFFSET = glm::vec2(0.7f, -0.1f); diff --git a/interface/src/Application.h b/interface/src/Application.h index 5cb5fdd5c0..e771d7ea38 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -50,6 +50,8 @@ #include #include #include +#include +#include #include "avatar/MyAvatar.h" #include "FancyCamera.h" @@ -325,6 +327,8 @@ public: int getOtherAvatarsReplicaCount() { return DependencyManager::get()->getReplicaCount(); } void setOtherAvatarsReplicaCount(int count) { DependencyManager::get()->setReplicaCount(count); } + void confirmConnectWithoutAvatarEntities(); + bool getLoginDialogPoppedUp() const { return _loginDialogPoppedUp; } void createLoginDialog(); void updateLoginDialogPosition(); @@ -608,7 +612,7 @@ private: void toggleTabletUI(bool shouldOpen = false) const; bool shouldCaptureMouse() const; - void userKickConfirmation(const QUuid& nodeID); + void userKickConfirmation(const QUuid& nodeID, unsigned int banFlags = ModerationFlags::getDefaultBanFlags()); MainWindow* _window; QElapsedTimer& _sessionRunTimer; @@ -723,6 +727,8 @@ private: bool _loginDialogPoppedUp{ false }; bool _desktopRootItemCreated{ false }; + ModalDialogListener* _confirmConnectWithoutAvatarEntitiesDialog { nullptr }; + bool _developerMenuVisible{ false }; QString _previousAvatarSkeletonModel; float _previousAvatarTargetScale; diff --git a/interface/src/AvatarBookmarks.cpp b/interface/src/AvatarBookmarks.cpp index 9aa1d91a0f..f5d7eadc4d 100644 --- a/interface/src/AvatarBookmarks.cpp +++ b/interface/src/AvatarBookmarks.cpp @@ -180,7 +180,7 @@ void AvatarBookmarks::updateAvatarEntities(const QVariantList &avatarEntities) { } } -/**jsdoc +/*@jsdoc * Details of an avatar bookmark. * @typedef {object} AvatarBookmarks.BookmarkData * @property {number} version - The version of the bookmark data format. diff --git a/interface/src/AvatarBookmarks.h b/interface/src/AvatarBookmarks.h index 82db23a7f7..c2c7eb5a0a 100644 --- a/interface/src/AvatarBookmarks.h +++ b/interface/src/AvatarBookmarks.h @@ -16,7 +16,7 @@ #include #include "Bookmarks.h" -/**jsdoc +/*@jsdoc * The AvatarBookmarks API provides facilities for working with avatar bookmarks ("favorites" in the Avatar app). * An avatar bookmark associates a name with an avatar model, scale, and avatar entities (wearables). * @@ -36,7 +36,7 @@ public: AvatarBookmarks(); void setupMenus(Menu* menubar, MenuWrapper* menu) override {}; - /**jsdoc + /*@jsdoc * Gets the details of an avatar bookmark. * @function AvatarBookmarks.getBookmark * @param {string} bookmarkName - The name of the avatar bookmark (case sensitive). @@ -45,7 +45,7 @@ public: Q_INVOKABLE QVariantMap getBookmark(const QString& bookmarkName); public slots: - /**jsdoc + /*@jsdoc * Adds a new (or updates an existing) avatar bookmark with your current avatar model, scale, and avatar entities. * @function AvatarBookmarks.addBookmark * @param {string} bookmarkName - The name of the avatar bookmark (case sensitive). @@ -57,7 +57,7 @@ public slots: */ void addBookmark(const QString& bookmarkName); - /**jsdoc + /*@jsdoc * Updates an existing bookmark with your current avatar model, scale, and wearables. No action is taken if the bookmark * doesn't exist. * @function AvatarBookmarks.saveBookmark @@ -65,7 +65,7 @@ public slots: */ void saveBookmark(const QString& bookmarkName); - /**jsdoc + /*@jsdoc * Loads an avatar bookmark, setting your avatar model, scale, and avatar entities (or attachments if an old bookmark) to * those in the bookmark. * @function AvatarBookmarks.loadBookmark @@ -73,14 +73,14 @@ public slots: */ void loadBookmark(const QString& bookmarkName); - /**jsdoc + /*@jsdoc * Deletes an avatar bookmark. * @function AvatarBookmarks.removeBookmark * @param {string} bookmarkName - The name of the avatar bookmark to delete (case sensitive). */ void removeBookmark(const QString& bookmarkName); - /**jsdoc + /*@jsdoc * Updates the avatar entities and their properties. Current avatar entities not included in the list provided are deleted. * @function AvatarBookmarks.updateAvatarEntities * @param {MyAvatar.AvatarEntityData[]} avatarEntities - The avatar entity IDs and properties. @@ -88,7 +88,7 @@ public slots: */ void updateAvatarEntities(const QVariantList& avatarEntities); - /**jsdoc + /*@jsdoc * Gets the details of all avatar bookmarks. * @function AvatarBookmarks.getBookmarks * @returns {Object} The current avatar bookmarks in an object where the keys are the @@ -103,7 +103,7 @@ public slots: QVariantMap getBookmarks() { return _bookmarks; } signals: - /**jsdoc + /*@jsdoc * Triggered when an avatar bookmark is loaded, setting your avatar model, scale, and avatar entities (or attachments if an * old bookmark) to those in the bookmark. * @function AvatarBookmarks.bookmarkLoaded @@ -112,7 +112,7 @@ signals: */ void bookmarkLoaded(const QString& bookmarkName); - /**jsdoc + /*@jsdoc * Triggered when an avatar bookmark is deleted. * @function AvatarBookmarks.bookmarkDeleted * @param {string} bookmarkName - The name of the avatar bookmark deleted. @@ -124,7 +124,7 @@ signals: */ void bookmarkDeleted(const QString& bookmarkName); - /**jsdoc + /*@jsdoc * Triggered when a new avatar bookmark is added or an existing avatar bookmark is updated, using * {@link AvatarBookmarks.addBookmark|addBookmark}. * @function AvatarBookmarks.bookmarkAdded @@ -139,7 +139,7 @@ protected: QVariantMap getAvatarDataToBookmark(); protected slots: - /**jsdoc + /*@jsdoc * Performs no action. * @function AvatarBookmarks.deleteBookmark * @deprecated This function is deprecated and will be removed. diff --git a/interface/src/Bookmarks.h b/interface/src/Bookmarks.h index e4480b7552..f0d2a421fa 100644 --- a/interface/src/Bookmarks.h +++ b/interface/src/Bookmarks.h @@ -51,7 +51,7 @@ protected: bool _isMenuSorted; protected slots: - /**jsdoc + /*@jsdoc * Prompts the user to delete a bookmark. The user can select the bookmark to delete in the dialog that is opened. * @function LocationBookmarks.deleteBookmark */ diff --git a/interface/src/ConnectionMonitor.cpp b/interface/src/ConnectionMonitor.cpp index 070015f05b..cd5235e42b 100644 --- a/interface/src/ConnectionMonitor.cpp +++ b/interface/src/ConnectionMonitor.cpp @@ -35,6 +35,7 @@ void ConnectionMonitor::init() { connect(&domainHandler, &DomainHandler::connectedToDomain, this, &ConnectionMonitor::stopTimer); connect(&domainHandler, &DomainHandler::domainConnectionRefused, this, &ConnectionMonitor::stopTimer); connect(&domainHandler, &DomainHandler::redirectToErrorDomainURL, this, &ConnectionMonitor::stopTimer); + connect(&domainHandler, &DomainHandler::confirmConnectWithoutAvatarEntities, this, &ConnectionMonitor::stopTimer); connect(this, &ConnectionMonitor::setRedirectErrorState, &domainHandler, &DomainHandler::setRedirectErrorState); auto accountManager = DependencyManager::get(); connect(accountManager.data(), &AccountManager::loginComplete, this, &ConnectionMonitor::startTimer); diff --git a/interface/src/FancyCamera.h b/interface/src/FancyCamera.h index afcd5197ff..5bdf621efa 100644 --- a/interface/src/FancyCamera.h +++ b/interface/src/FancyCamera.h @@ -18,7 +18,7 @@ class FancyCamera : public Camera { Q_OBJECT - /**jsdoc + /*@jsdoc * The Camera API provides access to the "camera" that defines your view in desktop and HMD display modes. * The Vircadia camera has axes x = right, y = up, -z = forward. * @@ -51,7 +51,7 @@ public: public slots: - /**jsdoc + /*@jsdoc * Gets the ID of the entity that the camera is set to follow (i.e., use the position and orientation from) when it's in * entity mode. You can also get the entity ID using the {@link Camera|Camera.cameraEntity} property. * @function Camera.getCameraEntity @@ -60,7 +60,7 @@ public slots: */ QUuid getCameraEntity() const; - /**jsdoc + /*@jsdoc * Sets the entity that the camera should follow (i.e., use the position and orientation from) when it's in entity mode. * You can also set the entity using the {@link Camera|Camera.cameraEntity} property. * @function Camera.setCameraEntity diff --git a/interface/src/LODManager.cpp b/interface/src/LODManager.cpp index 4cd5025fc1..1c6ef387f3 100644 --- a/interface/src/LODManager.cpp +++ b/interface/src/LODManager.cpp @@ -4,6 +4,7 @@ // // Created by Clement on 1/16/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 @@ -19,8 +20,12 @@ #include "ui/DialogsManager.h" #include "InterfaceLogging.h" -Setting::Handle desktopWorldDetailQuality("desktopWorldDetailQuality", (int)DEFAULT_WORLD_DETAIL_QUALITY); -Setting::Handle hmdWorldDetailQuality("hmdWorldDetailQuality", (int)DEFAULT_WORLD_DETAIL_QUALITY); +const QString LOD_SETTINGS_PREFIX { "lodManager/" }; + +Setting::Handle automaticLODAdjust(LOD_SETTINGS_PREFIX + "automaticLODAdjust", (bool)DEFAULT_LOD_AUTO_ADJUST); +Setting::Handle lodHalfAngle(LOD_SETTINGS_PREFIX + "lodHalfAngle", (float)getHalfAngleFromVisibilityDistance(DEFAULT_VISIBILITY_DISTANCE_FOR_UNIT_ELEMENT)); +Setting::Handle desktopWorldDetailQuality(LOD_SETTINGS_PREFIX + "desktopWorldDetailQuality", (int)DEFAULT_WORLD_DETAIL_QUALITY); +Setting::Handle hmdWorldDetailQuality(LOD_SETTINGS_PREFIX + "hmdWorldDetailQuality", (int)DEFAULT_WORLD_DETAIL_QUALITY); LODManager::LODManager() { } @@ -188,12 +193,14 @@ void LODManager::setVisibilityDistance(float distance) { // Maintain behavior with deprecated _boundaryLevelAdjust property float userDistance = distance / powf(2.0f, _boundaryLevelAdjust); _lodHalfAngle = getHalfAngleFromVisibilityDistance(userDistance); + saveSettings(); } void LODManager::setLODAngleDeg(float lodAngle) { auto newLODAngleDeg = std::max(0.001f, std::min(lodAngle, 90.f)); auto newLODHalfAngle = glm::radians(newLODAngleDeg * 0.5f); _lodHalfAngle = newLODHalfAngle; + saveSettings(); } void LODManager::setSmoothScale(float t) { @@ -244,6 +251,7 @@ void LODManager::resetLODAdjust() { void LODManager::setAutomaticLODAdjust(bool value) { std::lock_guard { _automaticLODLock }; _automaticLODAdjust = value; + saveSettings(); emit autoLODChanged(); } @@ -330,14 +338,19 @@ void LODManager::loadSettings() { if (qApp->property(hifi::properties::OCULUS_STORE).toBool() && firstRun.get()) { hmdQuality = WORLD_DETAIL_HIGH; } + + _automaticLODAdjust = automaticLODAdjust.get(); + _lodHalfAngle = lodHalfAngle.get(); setWorldDetailQuality(desktopQuality, false); setWorldDetailQuality(hmdQuality, true); } void LODManager::saveSettings() { + automaticLODAdjust.set((bool)_automaticLODAdjust); desktopWorldDetailQuality.set((int)_desktopWorldDetailQuality); hmdWorldDetailQuality.set((int)_hmdWorldDetailQuality); + lodHalfAngle.set((float)_lodHalfAngle); } const float MIN_DECREASE_FPS = 0.5f; @@ -405,6 +418,7 @@ void LODManager::setWorldDetailQuality(WorldDetailQuality quality, bool isHMDMod void LODManager::setWorldDetailQuality(WorldDetailQuality quality) { setWorldDetailQuality(quality, qApp->isHMDMode()); + saveSettings(); emit worldDetailQualityChanged(); } diff --git a/interface/src/LODManager.h b/interface/src/LODManager.h index 16b0529b05..419ca9cddc 100644 --- a/interface/src/LODManager.h +++ b/interface/src/LODManager.h @@ -4,6 +4,7 @@ // // Created by Clement on 1/16/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 -/**jsdoc +/*@jsdoc *

The world detail quality rendered.

* * @@ -44,10 +45,12 @@ enum WorldDetailQuality { }; Q_DECLARE_METATYPE(WorldDetailQuality); +const bool DEFAULT_LOD_AUTO_ADJUST = false; // true for auto, false for manual. + #ifdef Q_OS_ANDROID -const float LOD_DEFAULT_QUALITY_LEVEL = 0.2f; // default quality level setting is High (lower framerate) +const float DEFAULT_LOD_QUALITY_LEVEL = 0.2f; // default quality level setting is High (lower framerate) #else -const float LOD_DEFAULT_QUALITY_LEVEL = 0.5f; // default quality level setting is Mid +const float DEFAULT_LOD_QUALITY_LEVEL = 0.5f; // default quality level setting is Mid #endif #ifdef Q_OS_ANDROID @@ -65,7 +68,7 @@ const float LOD_OFFSET_FPS = 5.0f; // offset of FPS to add for computing the tar class AABox; -/**jsdoc +/*@jsdoc * The LODManager API manages the Level of Detail displayed in Interface. If the LOD is being automatically * adjusted, the LOD is decreased if the measured frame rate is lower than the target FPS, and increased if the measured frame * rate is greater than the target FPS. @@ -162,14 +165,14 @@ class LODManager : public QObject, public Dependency { public: - /**jsdoc + /*@jsdoc * Sets whether the LOD should be automatically adjusted. * @function LODManager.setAutomaticLODAdjust * @param {boolean} value - true to automatically adjust the LOD, false to manually adjust it. */ Q_INVOKABLE void setAutomaticLODAdjust(bool value); - /**jsdoc + /*@jsdoc * Gets whether the LOD is being automatically adjusted. * @function LODManager.getAutomaticLODAdjust * @returns {boolean} true if the LOD is being automatically adjusted, false if it is being @@ -177,14 +180,14 @@ public: */ Q_INVOKABLE bool getAutomaticLODAdjust() const { return _automaticLODAdjust; } - /**jsdoc + /*@jsdoc * Sets the target desktop LOD FPS. * @function LODManager.setDesktopLODTargetFPS * @param {number} value - The target desktop LOD FPS, in Hz. */ Q_INVOKABLE void setDesktopLODTargetFPS(float value); - /**jsdoc + /*@jsdoc * Gets the target desktop LOD FPS. * @function LODManager.getDesktopLODTargetFPS * @returns {number} The target desktop LOD FPS, in Hz. @@ -192,7 +195,7 @@ public: Q_INVOKABLE float getDesktopLODTargetFPS() const; - /**jsdoc + /*@jsdoc * Sets the target HMD LOD FPS. * @function LODManager.setHMDLODTargetFPS * @param {number} value - The target HMD LOD FPS, in Hz. @@ -200,7 +203,7 @@ public: Q_INVOKABLE void setHMDLODTargetFPS(float value); - /**jsdoc + /*@jsdoc * Gets the target HMD LOD FPS. * The target FPS in HMD mode. The LOD is adjusted to ... * @function LODManager.getHMDLODTargetFPS @@ -211,7 +214,7 @@ public: // User Tweakable LOD Items - /**jsdoc + /*@jsdoc * Gets a text description of the current level of detail rendered. * @function LODManager.getLODFeedbackText * @returns {string} A text description of the current level of detail rendered. @@ -220,42 +223,41 @@ public: */ Q_INVOKABLE QString getLODFeedbackText(); - /**jsdoc + /*@jsdoc * @function LODManager.setOctreeSizeScale * @param {number} sizeScale - The octree size scale. * @deprecated This function is deprecated and will be removed. Use the lodAngleDeg property instead. */ Q_INVOKABLE void setOctreeSizeScale(float sizeScale); - /**jsdoc + /*@jsdoc * @function LODManager.getOctreeSizeScale * @returns {number} The octree size scale. * @deprecated This function is deprecated and will be removed. Use the lodAngleDeg property instead. */ Q_INVOKABLE float getOctreeSizeScale() const; - /**jsdoc + /*@jsdoc * @function LODManager.setBoundaryLevelAdjust * @param {number} boundaryLevelAdjust - The boundary level adjust factor. * @deprecated This function is deprecated and will be removed. */ Q_INVOKABLE void setBoundaryLevelAdjust(int boundaryLevelAdjust); - /**jsdoc + /*@jsdoc * @function LODManager.getBoundaryLevelAdjust * @returns {number} The boundary level adjust factor. * @deprecated This function is deprecated and will be removed. */ Q_INVOKABLE int getBoundaryLevelAdjust() const { return _boundaryLevelAdjust; } - /**jsdoc + /*@jsdoc * The target LOD FPS per the current desktop or HMD display mode, capped by the target refresh rate. * @function LODManager.getLODTargetFPS * @returns {number} The target LOD FPS, in Hz. */ Q_INVOKABLE float getLODTargetFPS() const; - float getPresentTime() const { return _presentTime; } float getEngineRunTime() const { return _engineRunTime; } float getBatchTime() const { return _batchTime; } @@ -307,7 +309,7 @@ public: signals: - /**jsdoc + /*@jsdoc * Not triggered. * @function LODManager.LODIncreased * @returns {Signal} @@ -315,7 +317,7 @@ signals: */ void LODIncreased(); - /**jsdoc + /*@jsdoc * Not triggered. * @function LODManager.LODDecreased * @returns {Signal} @@ -323,14 +325,14 @@ signals: */ void LODDecreased(); - /**jsdoc + /*@jsdoc * Triggered when whether or not the LOD is being automatically adjusted changes. * @function LODManager.autoLODChanged * @returns {Signal} */ void autoLODChanged(); - /**jsdoc + /*@jsdoc * Triggered when the lodQualityLevel property value changes. * @function LODManager.lodQualityLevelChanged * @returns {Signal} @@ -338,7 +340,7 @@ signals: */ void lodQualityLevelChanged(); - /**jsdoc + /*@jsdoc * Triggered when the world detail quality changes. * @function LODManager.worldDetailQualityChanged * @returns {Signal} @@ -351,7 +353,7 @@ private: void setWorldDetailQuality(WorldDetailQuality quality, bool isHMDMode); std::mutex _automaticLODLock; - bool _automaticLODAdjust = true; + bool _automaticLODAdjust = DEFAULT_LOD_AUTO_ADJUST; float _presentTime{ 0.0f }; // msec float _engineRunTime{ 0.0f }; // msec @@ -362,7 +364,7 @@ private: float _smoothScale{ 10.0f }; // smooth is evaluated over 10 times longer than now float _smoothRenderTime{ 0.0f }; // msec - float _lodQualityLevel{ LOD_DEFAULT_QUALITY_LEVEL }; + float _lodQualityLevel{ DEFAULT_LOD_QUALITY_LEVEL }; WorldDetailQuality _desktopWorldDetailQuality { DEFAULT_WORLD_DETAIL_QUALITY }; WorldDetailQuality _hmdWorldDetailQuality { DEFAULT_WORLD_DETAIL_QUALITY }; diff --git a/interface/src/LocationBookmarks.h b/interface/src/LocationBookmarks.h index 574060fb61..2bea44f78c 100644 --- a/interface/src/LocationBookmarks.h +++ b/interface/src/LocationBookmarks.h @@ -16,7 +16,7 @@ #include "Bookmarks.h" -/**jsdoc +/*@jsdoc * The LocationBookmarks API provides facilities for working with location bookmarks. A location bookmark * associates a name with a metaverse address. * @@ -37,7 +37,7 @@ public: void setupMenus(Menu* menubar, MenuWrapper* menu) override; static const QString HOME_BOOKMARK; - /**jsdoc + /*@jsdoc * Gets the metaverse address associated with a bookmark. * @function LocationBookmarks.getAddress * @param {string} bookmarkName - Name of the bookmark to get the metaverse address for (case sensitive). @@ -49,21 +49,21 @@ public: public slots: - /**jsdoc + /*@jsdoc * Prompts the user to bookmark their current location. The user can specify the name of the bookmark in the dialog that is * opened. * @function LocationBookmarks.addBookmark */ void addBookmark(); - /**jsdoc + /*@jsdoc * Sets the metaverse address associated with the "Home" bookmark. * @function LocationBookmarks.setHomeLocationToAddress * @param {string} address - The metaverse address to set the "Home" bookmark to. */ void setHomeLocationToAddress(const QVariant& address); - /**jsdoc + /*@jsdoc * Gets the metaverse address associated with the "Home" bookmark. * @function LocationBookmarks.getHomeLocationAddress * @returns {string} The metaverse address for the "Home" bookmark. diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 471645e342..3a320cc628 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -556,8 +556,6 @@ Menu::Menu() { }); addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::FixGaze, 0, false); - addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::ToggleHipsFollowing, 0, false, - avatar.get(), SLOT(setToggleHips(bool))); addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::AnimDebugDrawBaseOfSupport, 0, false, avatar.get(), SLOT(setEnableDebugDrawBaseOfSupport(bool))); addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::AnimDebugDrawDefaultPose, 0, false, diff --git a/interface/src/Menu.h b/interface/src/Menu.h index cac8e77f9e..5cd4c2112e 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -211,7 +211,6 @@ namespace MenuOption { const QString ThirdPerson = "Third Person Legacy"; const QString ThreePointCalibration = "3 Point Calibration"; const QString ThrottleFPSIfNotFocus = "Throttle FPS If Not Focus"; // FIXME - this value duplicated in Basic2DWindowOpenGLDisplayPlugin.cpp - const QString ToggleHipsFollowing = "Toggle Hips Following"; const QString ToolWindow = "Tool Window"; const QString TransmitterDrive = "Transmitter Drive"; const QString TurnWithHead = "Turn using Head"; diff --git a/interface/src/RefreshRateManager.cpp b/interface/src/RefreshRateManager.cpp index bb4ec42e41..b61f1e944b 100644 --- a/interface/src/RefreshRateManager.cpp +++ b/interface/src/RefreshRateManager.cpp @@ -17,7 +17,7 @@ static const int VR_TARGET_RATE = 90; -/**jsdoc +/*@jsdoc *

Refresh rate profile.

*
* @@ -36,7 +36,7 @@ static const int VR_TARGET_RATE = 90; static const std::array REFRESH_RATE_PROFILE_TO_STRING = { { "Eco", "Interactive", "Realtime" } }; -/**jsdoc +/*@jsdoc *

Interface states that affect the refresh rate.

*
* @@ -56,7 +56,7 @@ static const std::array REFRESH_RATE_REGIME_TO_STRING = { { "FocusActive", "FocusInactive", "Unfocus", "Minimized", "StartUp", "ShutDown" } }; -/**jsdoc +/*@jsdoc *

User experience (UX) modes.

*
* diff --git a/interface/src/RefreshRateManager.h b/interface/src/RefreshRateManager.h index 18fad392c9..cab7539823 100644 --- a/interface/src/RefreshRateManager.h +++ b/interface/src/RefreshRateManager.h @@ -31,7 +31,7 @@ public: }; static bool isValidRefreshRateProfile(RefreshRateProfile value) { return (value >= RefreshRateProfile::ECO && value <= RefreshRateProfile::REALTIME); } - /**jsdoc + /*@jsdoc *

Interface states that affect the refresh rate.

*
* @@ -59,7 +59,7 @@ public: }; static bool isValidRefreshRateRegime(RefreshRateRegime value) { return (value >= RefreshRateRegime::FOCUS_ACTIVE && value <= RefreshRateRegime::SHUTDOWN); } - /**jsdoc + /*@jsdoc *

User experience (UX) modes.

*
* diff --git a/interface/src/SpeechRecognizer.h b/interface/src/SpeechRecognizer.h index ae35f63a35..ff00069073 100644 --- a/interface/src/SpeechRecognizer.h +++ b/interface/src/SpeechRecognizer.h @@ -22,7 +22,7 @@ #include -/**jsdoc +/*@jsdoc * The SpeechRecognizer API provides facilities to recognize voice commands. *

Speech recognition is enabled or disabled via the Developer > Scripting > Enable Speech Control API menu item or * the {@link SpeechRecognizer.setEnabled} method.

@@ -43,21 +43,21 @@ public: public slots: - /**jsdoc + /*@jsdoc * Enables or disables speech recognition. * @function SpeechRecognizer.setEnabled * @param {boolean} enabled - true to enable speech recognition, false to disable. */ void setEnabled(bool enabled); - /**jsdoc + /*@jsdoc * Adds a voice command to the speech recognizer. * @function SpeechRecognizer.addCommand * @param {string} command - The voice command to recognize. */ void addCommand(const QString& command); - /**jsdoc + /*@jsdoc * Removes a voice command from the speech recognizer. * @function SpeechRecognizer.removeCommand * @param {string} command - The voice command to stop recognizing. @@ -66,7 +66,7 @@ public slots: signals: - /**jsdoc + /*@jsdoc * Triggered when a voice command has been recognized. * @function SpeechRecognizer.commandRecognized * @param {string} command - The voice command recognized. @@ -115,7 +115,7 @@ signals: */ void commandRecognized(const QString& command); - /**jsdoc + /*@jsdoc * Triggered when speech recognition is enabled or disabled. * @function SpeechRecognizer.enabledUpdated * @param {boolean} enabled - true if speech recognition is enabled, false if it is disabled. diff --git a/interface/src/audio/AudioScope.h b/interface/src/audio/AudioScope.h index 26b228e900..ea60fc6eeb 100644 --- a/interface/src/audio/AudioScope.h +++ b/interface/src/audio/AudioScope.h @@ -25,7 +25,7 @@ class AudioScope : public QObject, public Dependency { Q_OBJECT SINGLETON_DEPENDENCY - /**jsdoc + /*@jsdoc * The AudioScope API provides facilities for an audio scope. * * @namespace AudioScope @@ -60,67 +60,67 @@ public: public slots: - /**jsdoc + /*@jsdoc * Toggle. * @function AudioScope.toggle */ void toggle() { setVisible(!_isEnabled); } - /**jsdoc + /*@jsdoc * Set visible. * @function AudioScope.setVisible * @param {boolean} visible - Visible. */ void setVisible(bool visible); - /**jsdoc + /*@jsdoc * Get visible. * @function AudioScope.getVisible * @returns {boolean} Visible. */ bool getVisible() const { return _isEnabled; } - /**jsdoc + /*@jsdoc * Toggle pause. * @function AudioScope.togglePause */ void togglePause() { setPause(!_isPaused); } - /**jsdoc + /*@jsdoc * Set pause. * @function AudioScope.setPause * @param {boolean} pause - Pause. */ void setPause(bool paused) { _isPaused = paused; emit pauseChanged(); } - /**jsdoc + /*@jsdoc * Get pause. * @function AudioScope.getPause * @returns {boolean} Pause. */ bool getPause() { return _isPaused; } - /**jsdoc + /*@jsdoc * Toggle trigger. * @function AudioScope.toggleTrigger */ void toggleTrigger() { _autoTrigger = !_autoTrigger; } - /**jsdoc + /*@jsdoc * Get auto trigger. * @function AudioScope.getAutoTrigger * @returns {boolean} Auto trigger. */ bool getAutoTrigger() { return _autoTrigger; } - /**jsdoc + /*@jsdoc * Set auto trigger. * @function AudioScope.setAutoTrigger * @param {boolean} autoTrigger - Auto trigger. */ void setAutoTrigger(bool autoTrigger) { _isTriggered = false; _autoTrigger = autoTrigger; } - /**jsdoc + /*@jsdoc * Set trigger values. * @function AudioScope.setTriggerValues * @param {number} x - X. @@ -128,102 +128,102 @@ public slots: */ void setTriggerValues(int x, int y) { _triggerValues.x = x; _triggerValues.y = y; } - /**jsdoc + /*@jsdoc * Set triggered. * @function AudioScope.setTriggered * @param {boolean} triggered - Triggered. */ void setTriggered(bool triggered) { _isTriggered = triggered; } - /**jsdoc + /*@jsdoc * Get triggered. * @function AudioScope.getTriggered * @returns {boolean} Triggered. */ bool getTriggered() { return _isTriggered; } - /**jsdoc + /*@jsdoc * Get frames per second. * @function AudioScope.getFramesPerSecond * @returns {number} Frames per second. */ float getFramesPerSecond(); - /**jsdoc + /*@jsdoc * Get frames per scope. * @function AudioScope.getFramesPerScope * @returns {number} Frames per scope. */ int getFramesPerScope() { return _framesPerScope; } - /**jsdoc + /*@jsdoc * Select five frames audio scope. * @function AudioScope.selectAudioScopeFiveFrames */ void selectAudioScopeFiveFrames(); - /**jsdoc + /*@jsdoc * Select twenty frames audio scope. * @function AudioScope.selectAudioScopeTwentyFrames */ void selectAudioScopeTwentyFrames(); - /**jsdoc + /*@jsdoc * Select fifty frames audio scope. * @function AudioScope.selectAudioScopeFiftyFrames */ void selectAudioScopeFiftyFrames(); - /**jsdoc + /*@jsdoc * Get scope input. * @function AudioScope.getScopeInput * @returns {number[]} Scope input. */ QVector getScopeInput() { return _scopeInputData; }; - /**jsdoc + /*@jsdoc * Get scope left output. * @function AudioScope.getScopeOutputLeft * @returns {number[]} Scope left output. */ QVector getScopeOutputLeft() { return _scopeOutputLeftData; }; - /**jsdoc + /*@jsdoc * Get scope right output. * @function AudioScope.getScopeOutputRight * @returns {number[]} Scope right output. */ QVector getScopeOutputRight() { return _scopeOutputRightData; }; - /**jsdoc + /*@jsdoc * Get trigger input. * @function AudioScope.getTriggerInput * @returns {number[]} Trigger input. */ QVector getTriggerInput() { return _triggerInputData; }; - /**jsdoc + /*@jsdoc * Get left trigger output. * @function AudioScope.getTriggerOutputLeft * @returns {number[]} Left trigger output. */ QVector getTriggerOutputLeft() { return _triggerOutputLeftData; }; - /**jsdoc + /*@jsdoc * Get right trigger output. * @function AudioScope.getTriggerOutputRight * @returns {number[]} Right trigger output. */ QVector getTriggerOutputRight() { return _triggerOutputRightData; }; - /**jsdoc + /*@jsdoc * Set local echo. * @function AudioScope.setLocalEcho * @parm {boolean} localEcho - Local echo. */ void setLocalEcho(bool localEcho); - /**jsdoc + /*@jsdoc * Set server echo. * @function AudioScope.setServerEcho * @parm {boolean} serverEcho - Server echo. @@ -232,14 +232,14 @@ public slots: signals: - /**jsdoc + /*@jsdoc * Triggered when pause changes. * @function AudioScope.pauseChanged * @returns {Signal} */ void pauseChanged(); - /**jsdoc + /*@jsdoc * Triggered when scope is triggered. * @function AudioScope.triggered * @returns {Signal} diff --git a/interface/src/avatar/AvatarActionFarGrab.h b/interface/src/avatar/AvatarActionFarGrab.h index c9b8f6ff3c..36b4dc0d48 100644 --- a/interface/src/avatar/AvatarActionFarGrab.h +++ b/interface/src/avatar/AvatarActionFarGrab.h @@ -15,7 +15,7 @@ #include #include -/**jsdoc +/*@jsdoc * The "far-grab" {@link Entities.ActionType|ActionType} moves and rotates an entity to a target position and * orientation, optionally relative to another entity. Collisions between the entity and the user's avatar are disabled during * the far-grab. diff --git a/interface/src/avatar/AvatarActionHold.cpp b/interface/src/avatar/AvatarActionHold.cpp index b7019bd6f0..36b1020990 100644 --- a/interface/src/avatar/AvatarActionHold.cpp +++ b/interface/src/avatar/AvatarActionHold.cpp @@ -444,7 +444,7 @@ bool AvatarActionHold::updateArguments(QVariantMap arguments) { return true; } -/**jsdoc +/*@jsdoc * The "hold" {@link Entities.ActionType|ActionType} positions and rotates an entity relative to an avatar's hand. * Collisions between the entity and the user's avatar are disabled during the hold. * It has arguments in addition to the common {@link Entities.ActionArguments|ActionArguments}: 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/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index 91d339a38d..943845bda7 100755 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -544,7 +544,7 @@ void AvatarManager::removeDeadAvatarEntities(const SetOfEntities& deadEntities) QUuid entityOwnerID = entity->getOwningAvatarID(); AvatarSharedPointer avatar = getAvatarBySessionID(entityOwnerID); if (avatar) { - avatar->clearAvatarEntity(entity->getID()); + avatar->clearAvatarEntityInternal(entity->getID()); } } } @@ -1008,7 +1008,7 @@ void AvatarManager::setAvatarSortCoefficient(const QString& name, const QScriptV } } -/**jsdoc +/*@jsdoc * PAL (People Access List) data for an avatar. * @typedef {object} AvatarManager.PalData * @property {Uuid} sessionUUID - The avatar's session ID. "" if the avatar is your own. diff --git a/interface/src/avatar/AvatarManager.h b/interface/src/avatar/AvatarManager.h index 30f68297b4..1fd9c63aab 100644 --- a/interface/src/avatar/AvatarManager.h +++ b/interface/src/avatar/AvatarManager.h @@ -36,7 +36,7 @@ using SortedAvatar = std::pair>; -/**jsdoc +/*@jsdoc * The AvatarManager API provides information about avatars within the current domain. The avatars available are * those that Interface has displayed and therefore knows about. * @@ -69,7 +69,7 @@ class AvatarManager : public AvatarHashMap { public: - /**jsdoc + /*@jsdoc * Gets the IDs of all avatars known about in the domain. * Your own avatar is included in the list as a null value. * @function AvatarManager.getAvatarIdentifiers @@ -80,7 +80,7 @@ public: * // A null item is included for your avatar. */ - /**jsdoc + /*@jsdoc * Gets the IDs of all avatars known about within a specified distance from a point. * Your own avatar's ID is included in the list if it is in range. * @function AvatarManager.getAvatarsInRange @@ -105,7 +105,7 @@ public: std::shared_ptr getMyAvatar() { return _myAvatar; } glm::vec3 getMyAvatarPosition() const { return _myAvatar->getWorldPosition(); } - /**jsdoc + /*@jsdoc * @comment Uses the base class's JSDoc. */ // Null/Default-constructed QUuids will return MyAvatar @@ -136,7 +136,7 @@ public: void handleChangedMotionStates(const VectorOfMotionStates& motionStates); void handleCollisionEvents(const CollisionEvents& collisionEvents); - /**jsdoc + /*@jsdoc * Gets the amount of avatar mixer data being generated by an avatar other than your own. * @function AvatarManager.getAvatarDataRate * @param {Uuid} sessionID - The ID of the avatar whose data rate you're retrieving. @@ -145,7 +145,7 @@ public: */ Q_INVOKABLE float getAvatarDataRate(const QUuid& sessionID, const QString& rateName = QString("")) const; - /**jsdoc + /*@jsdoc * Gets the update rate of avatar mixer data being generated by an avatar other than your own. * @function AvatarManager.getAvatarUpdateRate * @param {Uuid} sessionID - The ID of the avatar whose update rate you're retrieving. @@ -154,7 +154,7 @@ public: */ Q_INVOKABLE float getAvatarUpdateRate(const QUuid& sessionID, const QString& rateName = QString("")) const; - /**jsdoc + /*@jsdoc * Gets the simulation rate of an avatar other than your own. * @function AvatarManager.getAvatarSimulationRate * @param {Uuid} sessionID - The ID of the avatar whose simulation you're retrieving. @@ -163,7 +163,7 @@ public: */ Q_INVOKABLE float getAvatarSimulationRate(const QUuid& sessionID, const QString& rateName = QString("")) const; - /**jsdoc + /*@jsdoc * Find the first avatar intersected by a {@link PickRay}. * @function AvatarManager.findRayIntersection * @param {PickRay} ray - The ray to use for finding avatars. @@ -189,7 +189,7 @@ public: const QScriptValue& avatarIdsToInclude = QScriptValue(), const QScriptValue& avatarIdsToDiscard = QScriptValue(), bool pickAgainstMesh = true); - /**jsdoc + /*@jsdoc * @function AvatarManager.findRayIntersectionVector * @param {PickRay} ray - Ray. * @param {Uuid[]} avatarsToInclude - Avatars to include. @@ -203,7 +203,7 @@ public: const QVector& avatarsToDiscard, bool pickAgainstMesh); - /**jsdoc + /*@jsdoc * @function AvatarManager.findParabolaIntersectionVector * @param {PickParabola} pick - Pick. * @param {Uuid[]} avatarsToInclude - Avatars to include. @@ -215,7 +215,7 @@ public: const QVector& avatarsToInclude, const QVector& avatarsToDiscard); - /**jsdoc + /*@jsdoc * @function AvatarManager.getAvatarSortCoefficient * @param {string} name - Name. * @returns {number} Value. @@ -224,7 +224,7 @@ public: // TODO: remove this HACK once we settle on optimal default sort coefficients Q_INVOKABLE float getAvatarSortCoefficient(const QString& name); - /**jsdoc + /*@jsdoc * @function AvatarManager.setAvatarSortCoefficient * @param {string} name - Name * @param {number} value - Value. @@ -232,7 +232,7 @@ public: */ Q_INVOKABLE void setAvatarSortCoefficient(const QString& name, const QScriptValue& value); - /**jsdoc + /*@jsdoc * Gets PAL (People Access List) data for one or more avatars. Using this method is faster than iterating over each avatar * and obtaining data about each individually. * @function AvatarManager.getPalData @@ -255,14 +255,14 @@ public: void accumulateGrabPositions(std::map& grabAccumulators); public slots: - /**jsdoc + /*@jsdoc * @function AvatarManager.updateAvatarRenderStatus * @param {boolean} shouldRenderAvatars - Should render avatars. * @deprecated This function is deprecated and will be removed. */ void updateAvatarRenderStatus(bool shouldRenderAvatars); - /**jsdoc + /*@jsdoc * Displays other avatars skeletons debug graphics. * @function AvatarManager.setEnableDebugDrawOtherSkeletons * @param {boolean} enabled - true to show the debug graphics, false to hide. diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 0f66f3bb41..0d650bf2e7 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -278,6 +278,9 @@ MyAvatar::MyAvatar(QThread* thread) : // when we leave a domain we lift whatever restrictions that domain may have placed on our scale connect(&domainHandler, &DomainHandler::disconnectedFromDomain, this, &MyAvatar::leaveDomain); + auto nodeList = DependencyManager::get(); + connect(nodeList.data(), &NodeList::canRezAvatarEntitiesChanged, this, &MyAvatar::handleCanRezAvatarEntitiesChanged); + _bodySensorMatrix = deriveBodyFromHMDSensor(); using namespace recording; @@ -365,12 +368,20 @@ MyAvatar::MyAvatar(QThread* thread) : connect(&(_skeletonModel->getRig()), &Rig::onLoadFailed, this, &MyAvatar::onLoadFailed); _characterController.setDensity(_density); + + _addAvatarEntitiesToTreeTimer.setSingleShot(true); + connect(&_addAvatarEntitiesToTreeTimer, &QTimer::timeout, [this] { + addAvatarEntitiesToTree(); + }); } MyAvatar::~MyAvatar() { _lookAtTargetAvatar.reset(); delete _scriptEngine; _scriptEngine = nullptr; + if (_addAvatarEntitiesToTreeTimer.isActive()) { + _addAvatarEntitiesToTreeTimer.stop(); + } } QString MyAvatar::getDominantHand() const { @@ -1393,15 +1404,9 @@ float loadSetting(Settings& settings, const QString& name, float defaultValue) { } void MyAvatar::setToggleHips(bool followHead) { - _follow.setToggleHipsFollowing(followHead); -} - -void MyAvatar::FollowHelper::setToggleHipsFollowing(bool followHead) { - _toggleHipsFollowing = followHead; -} - -bool MyAvatar::FollowHelper::getToggleHipsFollowing() const { - return _toggleHipsFollowing; + Q_UNUSED(followHead); + qCDebug(interfaceapp) << "MyAvatar.setToggleHips is deprecated; it no longer does anything; it will soon be removed from the API; " + "please update your script"; } void MyAvatar::setEnableDebugDrawBaseOfSupport(bool isEnabled) { @@ -1533,7 +1538,23 @@ void MyAvatar::storeAvatarEntityDataPayload(const QUuid& entityID, const QByteAr void MyAvatar::clearAvatarEntity(const QUuid& entityID, bool requiresRemovalFromTree) { // NOTE: the requiresRemovalFromTree argument is unused - AvatarData::clearAvatarEntity(entityID); + + if (!DependencyManager::get()->getThisNodeCanRezAvatarEntities()) { + qCDebug(interfaceapp) << "Ignoring clearAvatarEntity() because don't have canRezAvatarEntities permission on domain"; + return; + } + + clearAvatarEntityInternal(entityID); +} + +void MyAvatar::clearAvatarEntityInternal(const QUuid& entityID) { + AvatarData::clearAvatarEntityInternal(entityID); + + if (!DependencyManager::get()->getThisNodeCanRezAvatarEntities()) { + // Don't delete potentially non-rezzed avatar entities from cache, otherwise they're removed from settings. + return; + } + _avatarEntitiesLock.withWriteLock([&] { _cachedAvatarEntityBlobsToDelete.push_back(entityID); }); @@ -1564,6 +1585,39 @@ void MyAvatar::sanitizeAvatarEntityProperties(EntityItemProperties& properties) properties.markAllChanged(); } +void MyAvatar::addAvatarEntitiesToTree() { + AvatarEntityMap::const_iterator constItr = _cachedAvatarEntityBlobs.begin(); + while (constItr != _cachedAvatarEntityBlobs.end()) { + QUuid id = constItr.key(); + _entitiesToAdd.push_back(id); // worked once: hat shown. then unshown when permissions removed but then entity was deleted somewhere along the line! + ++constItr; + } +} + +bool MyAvatar::hasAvatarEntities() const { + return _cachedAvatarEntityBlobs.count() > 0; +} + +void MyAvatar::handleCanRezAvatarEntitiesChanged(bool canRezAvatarEntities) { + if (canRezAvatarEntities) { + // Start displaying avatar entities. + // Allow time for the avatar mixer to be updated with the user's permissions so that it doesn't discard the avatar + // entities sent. In theory, typical worst case would be Interface running on same PC as server and the timings of + // Interface and the avatar mixer sending DomainListRequest to the domain server being such that the avatar sends its + // DomainListRequest and gets its DomainList response DOMAIN_SERVER_CHECK_IN_MSECS after Interface does. Allow extra + // time in case the avatar mixer is bogged down. + _addAvatarEntitiesToTreeTimer.start(5 * DOMAIN_SERVER_CHECK_IN_MSECS); // Single-shot. + } else { + // Cancel any pending addAvatarEntitiesToTree() call. + if (_addAvatarEntitiesToTreeTimer.isActive()) { + _addAvatarEntitiesToTreeTimer.stop(); + } + + // Stop displaying avatar entities. + removeAvatarEntitiesFromTree(); + } +} + void MyAvatar::handleChangedAvatarEntityData() { // NOTE: this is a per-frame update if (getID().isNull() || @@ -1583,6 +1637,8 @@ void MyAvatar::handleChangedAvatarEntityData() { return; } + bool canRezAvatarEntites = DependencyManager::get()->getThisNodeCanRezAvatarEntities(); + // We collect changes to AvatarEntities and then handle them all in one spot per frame: handleChangedAvatarEntityData(). // Basically this is a "transaction pattern" with an extra complication: these changes can come from two // "directions" and the "authoritative source" of each direction is different, so we maintain two distinct sets @@ -1669,12 +1725,15 @@ void MyAvatar::handleChangedAvatarEntityData() { continue; } sanitizeAvatarEntityProperties(properties); - entityTree->withWriteLock([&] { - EntityItemPointer entity = entityTree->addEntity(id, properties); - if (entity) { - packetSender->queueEditAvatarEntityMessage(entityTree, id); - } - }); + if (canRezAvatarEntites) { + entityTree->withWriteLock([&] { + EntityItemPointer entity = entityTree->addEntity(id, properties); + if (entity) { + packetSender->queueEditAvatarEntityMessage(entityTree, id); + } + }); + } + } // CHANGE real entities @@ -1692,7 +1751,7 @@ void MyAvatar::handleChangedAvatarEntityData() { skip = true; } }); - if (!skip) { + if (!skip && canRezAvatarEntites) { sanitizeAvatarEntityProperties(properties); entityTree->withWriteLock([&] { if (entityTree->updateEntity(id, properties)) { @@ -1834,6 +1893,11 @@ AvatarEntityMap MyAvatar::getAvatarEntityData() const { return data; } + if (!DependencyManager::get()->getThisNodeCanRezAvatarEntities()) { + qCDebug(interfaceapp) << "Ignoring getAvatarEntityData() because don't have canRezAvatarEntities permission on domain"; + return data; + } + QList avatarEntityIDs; _avatarEntitiesLock.withReadLock([&] { avatarEntityIDs = _packedAvatarEntityData.keys(); @@ -1879,6 +1943,12 @@ void MyAvatar::setAvatarEntityData(const AvatarEntityMap& avatarEntityData) { // avatarEntityData is expected to be a map of QByteArrays that represent EntityItemProperties objects from JavaScript, // aka: unfortunately-formatted-binary-blobs because we store them in non-human-readable format in Settings. // + + if (!DependencyManager::get()->getThisNodeCanRezAvatarEntities()) { + qCDebug(interfaceapp) << "Ignoring setAvatarEntityData() because don't have canRezAvatarEntities permission on domain"; + return; + } + if (avatarEntityData.size() > MAX_NUM_AVATAR_ENTITIES) { // the data is suspect qCDebug(interfaceapp) << "discard suspect AvatarEntityData with size =" << avatarEntityData.size(); @@ -1939,6 +2009,12 @@ void MyAvatar::setAvatarEntityData(const AvatarEntityMap& avatarEntityData) { void MyAvatar::updateAvatarEntity(const QUuid& entityID, const QByteArray& entityData) { // NOTE: this is an invokable Script call + + if (!DependencyManager::get()->getThisNodeCanRezAvatarEntities()) { + qCDebug(interfaceapp) << "Ignoring updateAvatarEntity() because don't have canRezAvatarEntities permission on domain"; + return; + } + bool changed = false; _avatarEntitiesLock.withWriteLock([&] { auto data = QJsonDocument::fromBinaryData(entityData); @@ -2030,7 +2106,6 @@ void MyAvatar::loadData() { allowAvatarLeaningPreferenceStrings[static_cast(AllowAvatarLeaningPreference::Default)]))); setEnableMeshVisible(Menu::getInstance()->isOptionChecked(MenuOption::MeshVisible)); - _follow.setToggleHipsFollowing (Menu::getInstance()->isOptionChecked(MenuOption::ToggleHipsFollowing)); setEnableDebugDrawBaseOfSupport(Menu::getInstance()->isOptionChecked(MenuOption::AnimDebugDrawBaseOfSupport)); setEnableDebugDrawDefaultPose(Menu::getInstance()->isOptionChecked(MenuOption::AnimDebugDrawDefaultPose)); setEnableDebugDrawAnimPose(Menu::getInstance()->isOptionChecked(MenuOption::AnimDebugDrawAnimPose)); @@ -2532,7 +2607,7 @@ void MyAvatar::removeWornAvatarEntity(const EntityItemID& entityID) { auto entity = entityTree->findEntityByID(entityID); if (entity && isWearableEntity(entity)) { treeRenderer->deleteEntity(entityID); - clearAvatarEntity(entityID); + clearAvatarEntityInternal(entityID); } } } @@ -2547,7 +2622,7 @@ void MyAvatar::clearWornAvatarEntities() { } } -/**jsdoc +/*@jsdoc *

Information about an avatar entity.

*
* @@ -2565,6 +2640,13 @@ QVariantList MyAvatar::getAvatarEntitiesVariant() { QVariantList avatarEntitiesData; auto treeRenderer = DependencyManager::get(); EntityTreePointer entityTree = treeRenderer ? treeRenderer->getTree() : nullptr; + + if (entityTree && !DependencyManager::get()->getThisNodeCanRezAvatarEntities()) { + qCDebug(interfaceapp) + << "Ignoring getAvatarEntitiesVariant() because don't have canRezAvatarEntities permission on domain"; + return avatarEntitiesData; + } + if (entityTree) { QList avatarEntityIDs; _avatarEntitiesLock.withReadLock([&] { @@ -2897,6 +2979,11 @@ void MyAvatar::attach(const QString& modelURL, const QString& jointName, ); return; } + if (!DependencyManager::get()->getThisNodeCanRezAvatarEntities()) { + qCDebug(interfaceapp) << "Ignoring attach() because don't have canRezAvatarEntities permission on domain"; + return; + } + AttachmentData data; data.modelURL = modelURL; data.jointName = jointName; @@ -2918,6 +3005,11 @@ void MyAvatar::detachOne(const QString& modelURL, const QString& jointName) { ); return; } + if (!DependencyManager::get()->getThisNodeCanRezAvatarEntities()) { + qCDebug(interfaceapp) << "Ignoring detachOne() because don't have canRezAvatarEntities permission on domain"; + return; + } + QUuid entityID; if (findAvatarEntity(modelURL, jointName, entityID)) { DependencyManager::get()->deleteEntity(entityID); @@ -2933,6 +3025,11 @@ void MyAvatar::detachAll(const QString& modelURL, const QString& jointName) { ); return; } + if (!DependencyManager::get()->getThisNodeCanRezAvatarEntities()) { + qCDebug(interfaceapp) << "Ignoring detachAll() because don't have canRezAvatarEntities permission on domain"; + return; + } + QUuid entityID; while (findAvatarEntity(modelURL, jointName, entityID)) { DependencyManager::get()->deleteEntity(entityID); @@ -2946,6 +3043,11 @@ void MyAvatar::setAttachmentData(const QVector& attachmentData) Q_ARG(const QVector&, attachmentData)); return; } + if (!DependencyManager::get()->getThisNodeCanRezAvatarEntities()) { + qCDebug(interfaceapp) << "Ignoring setAttachmentData() because don't have canRezAvatarEntities permission on domain"; + return; + } + std::vector newEntitiesProperties; for (auto& data : attachmentData) { QUuid entityID; @@ -2968,6 +3070,12 @@ void MyAvatar::setAttachmentData(const QVector& attachmentData) QVector MyAvatar::getAttachmentData() const { QVector attachmentData; + + if (!DependencyManager::get()->getThisNodeCanRezAvatarEntities()) { + qCDebug(interfaceapp) << "Ignoring getAttachmentData() because don't have canRezAvatarEntities permission on domain"; + return attachmentData; + } + QList avatarEntityIDs; _avatarEntitiesLock.withReadLock([&] { avatarEntityIDs = _packedAvatarEntityData.keys(); @@ -2982,6 +3090,13 @@ QVector MyAvatar::getAttachmentData() const { QVariantList MyAvatar::getAttachmentsVariant() const { QVariantList result; + + if (!DependencyManager::get()->getThisNodeCanRezAvatarEntities()) { + qCDebug(interfaceapp) + << "Ignoring getAttachmentsVariant() because don't have canRezAvatarEntities permission on domain"; + return result; + } + for (const auto& attachment : getAttachmentData()) { result.append(attachment.toVariant()); } @@ -2994,6 +3109,13 @@ void MyAvatar::setAttachmentsVariant(const QVariantList& variant) { Q_ARG(const QVariantList&, variant)); return; } + + if (!DependencyManager::get()->getThisNodeCanRezAvatarEntities()) { + qCDebug(interfaceapp) + << "Ignoring setAttachmentsVariant() because don't have canRezAvatarEntities permission on domain"; + return; + } + QVector newAttachments; newAttachments.reserve(variant.size()); for (const auto& attachmentVar : variant) { @@ -4065,7 +4187,8 @@ float MyAvatar::getGravity() { void MyAvatar::setSessionUUID(const QUuid& sessionUUID) { QUuid oldSessionID = getSessionUUID(); Avatar::setSessionUUID(sessionUUID); - bool sendPackets = !DependencyManager::get()->getSessionUUID().isNull(); + bool sendPackets = !DependencyManager::get()->getSessionUUID().isNull() + && DependencyManager::get()->getThisNodeCanRezAvatarEntities(); if (!sendPackets) { return; } @@ -4177,7 +4300,7 @@ void MyAvatar::clearScaleRestriction() { _haveReceivedHeightLimitsFromDomain = false; } -/**jsdoc +/*@jsdoc * A teleport target. * @typedef {object} MyAvatar.GoToProperties * @property {Vec3} position - The avatar's new position. @@ -4672,7 +4795,7 @@ void MyAvatar::setCollisionWithOtherAvatarsFlags() { _characterController.setPendingFlagsUpdateCollisionMask(); } -/**jsdoc +/*@jsdoc * A collision capsule is a cylinder with hemispherical ends. It is often used to approximate the extents of an avatar. * @typedef {object} MyAvatar.CollisionCapsule * @property {Vec3} start - The bottom end of the cylinder, excluding the bottom hemisphere. @@ -5514,7 +5637,7 @@ void MyAvatar::setSitStandStateChange(bool stateChanged) { } // Determine if the user's real-world sit/stand state has changed. -float MyAvatar::getSitStandStateChange() const { +bool MyAvatar::getSitStandStateChange() const { return _sitStandStateChange; } @@ -5696,7 +5819,7 @@ bool MyAvatar::FollowHelper::shouldActivateHorizontal_userSitting(const MyAvatar bool stepDetected = false; if (forwardLeanAmount > MAX_FORWARD_LEAN) { stepDetected = true; - } else if (forwardLeanAmount < 0 && forwardLeanAmount < -MAX_BACKWARD_LEAN) { + } else if (forwardLeanAmount < -MAX_BACKWARD_LEAN) { stepDetected = true; } else { stepDetected = fabs(lateralLeanAmount) > MAX_LATERAL_LEAN; @@ -6485,7 +6608,7 @@ void MyAvatar::addAvatarHandsToFlow(const std::shared_ptr& otherAvatar) } } -/**jsdoc +/*@jsdoc * Physics options to use in the flow simulation of a joint. * @typedef {object} MyAvatar.FlowPhysicsOptions * @property {boolean} [active=true] - true to enable flow on the joint, otherwise false. @@ -6496,7 +6619,7 @@ void MyAvatar::addAvatarHandsToFlow(const std::shared_ptr& otherAvatar) * @property {number} [stiffness=0.0] - The stiffness of each thread. * @property {number} [delta=0.55] - Delta time for every integration step. */ -/**jsdoc +/*@jsdoc * Collision options to use in the flow simulation of a joint. * @typedef {object} MyAvatar.FlowCollisionsOptions * @property {string} [type="sphere"] - Currently, only "sphere" is supported. @@ -6571,7 +6694,7 @@ void MyAvatar::useFlow(bool isActive, bool isCollidable, const QVariantMap& phys } } -/**jsdoc +/*@jsdoc * Flow options currently used in flow simulation. * @typedef {object} MyAvatar.FlowData * @property {boolean} initialized - true if flow has been initialized for the current avatar, false @@ -6585,7 +6708,7 @@ void MyAvatar::useFlow(bool isActive, bool isCollidable, const QVariantMap& phys * @property {Object} threads - The threads that have been configured, with the first joint's name as the * ThreadName and value as an array of the indexes of all the joints in the thread. */ -/**jsdoc +/*@jsdoc * A set of physics options currently used in flow simulation. * @typedef {object} MyAvatar.FlowPhysicsData * @property {boolean} active - true to enable flow on the joint, otherwise false. @@ -6597,7 +6720,7 @@ void MyAvatar::useFlow(bool isActive, bool isCollidable, const QVariantMap& phys * @property {number} delta - Delta time for every integration step. * @property {number[]} jointIndices - The indexes of the joints the options are applied to. */ -/**jsdoc +/*@jsdoc * A set of collision options currently used in flow simulation. * @typedef {object} MyAvatar.FlowCollisionsData * @property {number} radius - Collision sphere radius. diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 3d278cf983..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 @@ -40,18 +41,18 @@ class ModelItemID; class MyHead; class DetailedMotionState; -/**jsdoc +/*@jsdoc *

Locomotion control types.

*
* * * * - * - * - * * *
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.
@@ -87,7 +88,7 @@ class MyAvatar : public Avatar { Q_OBJECT friend class AnimStats; - /**jsdoc + /*@jsdoc * Your avatar is your in-world representation of you. The MyAvatar API is used to manipulate the avatar. * For example, you can customize the avatar's appearance, run custom avatar animations, * change the avatar's position within the domain, or manage the avatar's collisions with the environment and other avatars. @@ -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 @@ -434,8 +435,8 @@ class MyAvatar : public Avatar { const bool DEFAULT_STRAFE_ENABLED = true; public: - /**jsdoc - * The DriveKeys API provides constant numeric values that represent different logical keys that drive your + /*@jsdoc + * The DriveKeys API provides constant numeric values that represent different logical keys that drive your * avatar and camera. * * @namespace DriveKeys @@ -444,58 +445,58 @@ 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. */ - /**jsdoc + /*@jsdoc *

Logical keys that drive your avatar and camera.

* * * * * - * - * - * - * * * * - * - * * - * - * * *
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.
@@ -518,7 +519,7 @@ public: }; Q_ENUM(DriveKeys) - /**jsdoc + /*@jsdoc *

Specifies different avatar leaning and recentering behaviors.

*

Deprecated: This type is deprecated and will be removed.

* @@ -526,16 +527,16 @@ public: * * * - * - * - * - * * @@ -590,23 +591,23 @@ public: void setCollisionWithOtherAvatarsFlags() override; - /**jsdoc + /*@jsdoc * Resets the sensor positioning of your HMD (if in use) and recenters your avatar body and head. * @function MyAvatar.resetSensorsAndBody */ 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 + /*@jsdoc + * 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 */ Q_INVOKABLE void centerBody(); // thread-safe - /**jsdoc + /*@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 */ @@ -620,14 +621,14 @@ public: const glm::vec3& getHMDSensorPosition() const { return _hmdSensorPosition; } const glm::quat& getHMDSensorOrientation() const { return _hmdSensorOrientation; } - /**jsdoc + /*@jsdoc * Gets the avatar orientation. Suitable for use in QML. * @function MyAvatar.setOrientationVar * @param {object} newOrientationVar - The avatar's orientation. */ Q_INVOKABLE void setOrientationVar(const QVariant& newOrientationVar); - /**jsdoc + /*@jsdoc * Gets the avatar orientation. Suitable for use in QML. * @function MyAvatar.getOrientationVar * @returns {object} The avatar's orientation. @@ -655,9 +656,9 @@ public: void setRealWorldFieldOfView(float realWorldFov) { _realWorldFieldOfView.set(realWorldFov); } - /**jsdoc + /*@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. @@ -669,20 +670,20 @@ public: float getRealWorldFieldOfView() { return _realWorldFieldOfView.get(); } - /**jsdoc + /*@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. @@ -699,13 +700,13 @@ public: */ Q_INVOKABLE void overrideAnimation(const QString& url, float fps, bool loop, float firstFrame, float lastFrame); - /**jsdoc + /*@jsdoc * Overrides the default hand poses that are triggered with controller buttons. * 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. @@ -721,12 +722,12 @@ public: */ Q_INVOKABLE void overrideHandAnimation(bool isLeft, const QString& url, float fps, bool loop, float firstFrame, float lastFrame); - /**jsdoc + /*@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 @@ -738,7 +739,7 @@ public: */ Q_INVOKABLE void restoreAnimation(); - /**jsdoc + /*@jsdoc * Restores the default hand animation state machine that is driven by the state machine in the avatar-animation JSON. *

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 @@ -755,12 +756,12 @@ public: */ Q_INVOKABLE void restoreHandAnimation(bool isLeft); - /**jsdoc + /*@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. @@ -773,25 +774,25 @@ public: */ Q_INVOKABLE QStringList getAnimationRoles(); - /**jsdoc + /*@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. @@ -813,15 +814,15 @@ public: */ Q_INVOKABLE void overrideRoleAnimation(const QString& role, const QString& url, float fps, bool loop, float firstFrame, float lastFrame); - /**jsdoc + /*@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. @@ -837,39 +838,39 @@ public: // adding one of the other handlers. While any handler may change a value in animStateDictionaryIn (or supply different values in animStateDictionaryOut) // 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 + /*@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 * 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 * function animStateHandler(dictionary) { * print("Anim state dictionary: " + JSON.stringify(dictionary)); * } - * + * * var handler = MyAvatar.addAnimationStateHandler(animStateHandler, null); - * + * * Script.setTimeout(function () { * MyAvatar.removeAnimationStateHandler(handler); * }, 100); */ Q_INVOKABLE QScriptValue addAnimationStateHandler(QScriptValue handler, QScriptValue propertiesList) { return _skeletonModel->getRig().addAnimationStateHandler(handler, propertiesList); } - /**jsdoc + /*@jsdoc * Removes an animation state handler function. * @function MyAvatar.removeAnimationStateHandler * @param {number} handler - The ID of the animation state handler function to remove. @@ -878,124 +879,124 @@ public: Q_INVOKABLE void removeAnimationStateHandler(QScriptValue handler) { _skeletonModel->getRig().removeAnimationStateHandler(handler); } - /**jsdoc + /*@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; } - /**jsdoc + /*@jsdoc * Sets whether you do snap turns or smooth turns in HMD mode. * @function MyAvatar.setSnapTurn * @param {boolean} on - true to do snap turns in HMD mode; false to do smooth turns in HMD mode. */ Q_INVOKABLE void setSnapTurn(bool on) { _useSnapTurn = on; } - /**jsdoc + /*@jsdoc * Gets the control scheme that is in use. * @function MyAvatar.getControlScheme * @returns {MyAvatar.LocomotionControlsMode} The control scheme that is in use. */ Q_INVOKABLE int getControlScheme() const { return _controlSchemeIndex; } - /**jsdoc + /*@jsdoc * Sets the control scheme to use. * @function MyAvatar.setControlScheme * @param {MyAvatar.LocomotionControlsMode} controlScheme - The control scheme to use. */ Q_INVOKABLE void setControlScheme(int index) { _controlSchemeIndex = (index >= 0 && index <= 2) ? index : 0; } - - /**jsdoc + + /*@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(). Q_INVOKABLE bool hoverWhenUnsupported() const { return _hoverWhenUnsupported; } - /**jsdoc + /*@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; } - /**jsdoc + /*@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); - /**jsdoc + /*@jsdoc * Gets the avatar's dominant hand. * @function MyAvatar.getDominantHand * @returns {string} "left" for the left hand, "right" for the right hand. */ Q_INVOKABLE QString getDominantHand() const; - /**jsdoc + /*@jsdoc * Sets whether strafing is enabled. * @function MyAvatar.setStrafeEnabled * @param {boolean} enabled - true if strafing is enabled, false if it isn't. */ Q_INVOKABLE void setStrafeEnabled(bool enabled); - /**jsdoc + /*@jsdoc * Gets whether strafing is enabled. * @function MyAvatar.getStrafeEnabled * @returns {boolean} true if strafing is enabled, false if it isn't. */ Q_INVOKABLE bool getStrafeEnabled() const; - /**jsdoc + /*@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); - /**jsdoc + /*@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; - /**jsdoc + /*@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; } - /**jsdoc + /*@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 + /*@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 * 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; } - /**jsdoc + /*@jsdoc * Gets 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. * @function MyAvatar.getHMDLeanRecenterEnabled @@ -1003,16 +1004,16 @@ 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 + /*@jsdoc + * 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 */ Q_INVOKABLE void requestEnableHandTouch(); - /**jsdoc + /*@jsdoc * Requests that the hand touch effect is enabled 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 @@ -1021,7 +1022,7 @@ public: */ Q_INVOKABLE void requestDisableHandTouch(); - /**jsdoc + /*@jsdoc * Disables the hand touch effect on a specific entity. *

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.

@@ -1030,7 +1031,7 @@ public: */ Q_INVOKABLE void disableHandTouchForID(const QUuid& entityID); - /**jsdoc + /*@jsdoc * Enables the hand touch effect on a specific entity. *

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.

@@ -1072,7 +1073,7 @@ public: void setSprintMode(bool sprint); float getDriveKey(DriveKeys key) const; - /**jsdoc + /*@jsdoc * Gets the value of a drive key, regardless of whether it is disabled. * @function MyAvatar.getRawDriveKey * @param {DriveKey} key - The drive key. @@ -1081,8 +1082,8 @@ public: Q_INVOKABLE float getRawDriveKey(DriveKeys key) const; void relayDriveKeysToCharacterController(); - - /**jsdoc + + /*@jsdoc * Disables the action associated with a drive key. * @function MyAvatar.disableDriveKey * @param {DriveKey} key - The drive key to disable. @@ -1096,15 +1097,15 @@ public: */ Q_INVOKABLE void disableDriveKey(DriveKeys key); - /**jsdoc - * Enables the action associated with a drive key. The action may have been disabled with + /*@jsdoc + * 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. */ Q_INVOKABLE void enableDriveKey(DriveKeys key); - /**jsdoc + /*@jsdoc * Checks whether a drive key is disabled. * @function MyAvatar.isDriveKeyDisabled * @param {DriveKey} key - The drive key to check. @@ -1113,30 +1114,30 @@ public: Q_INVOKABLE bool isDriveKeyDisabled(DriveKeys key) const; - /**jsdoc - * Recenter the avatar in the vertical direction, if {@link MyAvatar|MyAvatar.hmdLeanRecenterEnabled} is + /*@jsdoc + * 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 + /*@jsdoc + * Recenter the avatar in the horizontal direction, if {@link MyAvatar|MyAvatar.hmdLeanRecenterEnabled} is * false. * @function MyAvatar.triggerHorizontalRecenter */ Q_INVOKABLE void triggerHorizontalRecenter(); - /**jsdoc + /*@jsdoc * Recenter the avatar's rotation, if {@link MyAvatar|MyAvatar.hmdLeanRecenterEnabled} is false. * @function MyAvatar.triggerRotationRecenter */ Q_INVOKABLE void triggerRotationRecenter(); - /**jsdoc + /*@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; @@ -1145,7 +1146,7 @@ public: const MyHead* getMyHead() const; - /**jsdoc + /*@jsdoc * Gets the current position of the avatar's "Head" joint. * @function MyAvatar.getHeadPosition * @returns {Vec3} The current position of the avatar's "Head" joint. @@ -1154,29 +1155,29 @@ public: */ Q_INVOKABLE glm::vec3 getHeadPosition() const { return getHead()->getPosition(); } - /**jsdoc + /*@jsdoc * Gets the yaw of the avatar's head relative to its body. * @function MyAvatar.getHeadFinalYaw * @returns {number} The yaw of the avatar's head, in degrees. */ Q_INVOKABLE float getHeadFinalYaw() const { return getHead()->getFinalYaw(); } - /**jsdoc + /*@jsdoc * Gets the roll of the avatar's head relative to its body. * @function MyAvatar.getHeadFinalRoll * @returns {number} The roll of the avatar's head, in degrees. */ Q_INVOKABLE float getHeadFinalRoll() const { return getHead()->getFinalRoll(); } - /**jsdoc + /*@jsdoc * Gets the pitch of the avatar's head relative to its body. * @function MyAvatar.getHeadFinalPitch * @returns {number} The pitch of the avatar's head, in degrees. */ 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 + /*@jsdoc + * 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 @@ -1184,7 +1185,7 @@ public: */ Q_INVOKABLE float getHeadDeltaPitch() const { return getHead()->getDeltaPitch(); } - /**jsdoc + /*@jsdoc * Gets the current position of the point directly between the avatar's eyes. * @function MyAvatar.getEyePosition * @returns {Vec3} The current position of the point directly between the avatar's eyes. @@ -1194,77 +1195,77 @@ public: */ Q_INVOKABLE glm::vec3 getEyePosition() const { return getHead()->getEyePosition(); } - /**jsdoc + /*@jsdoc * Gets the position of the avatar your avatar is currently looking at. * @function MyAvatar.getTargetAvatarPosition * @returns {Vec3} The position of the avatar beeing looked at. * @example * 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; } - /**jsdoc + /*@jsdoc * Gets information on the avatar your avatar is currently looking at. * @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 + /*@jsdoc + * 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 * print(JSON.stringify(MyAvatar.getLeftHandPosition())); */ 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 + /*@jsdoc + * 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 * print(JSON.stringify(MyAvatar.getLeftHandPosition())); */ 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 + /*@jsdoc + * 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; - /**jsdoc + /*@jsdoc * 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 + /*@jsdoc + * 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. @@ -1273,32 +1274,32 @@ 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 + /*@jsdoc + * 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 * 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 + /*@jsdoc + * 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; - /**jsdoc + /*@jsdoc * Gets the pose (position, rotation, velocity, and angular velocity) of the avatar's right 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 @@ -1328,7 +1329,7 @@ public: virtual void clearJointData(const QString& name) override; virtual void clearJointsData() override; - /**jsdoc + /*@jsdoc * Sets and locks a joint's position and orientation. *

Note: Only works on the hips joint.

* @function MyAvatar.pinJoint @@ -1341,7 +1342,7 @@ public: bool isJointPinned(int index); - /**jsdoc + /*@jsdoc * Clears a lock on a joint's position and orientation, as set by {@link MyAvatar.pinJoint|pinJoint}. *

Note: Only works on the hips joint.

* @function MyAvatar.clearPinOnJoint @@ -1350,14 +1351,14 @@ public: */ Q_INVOKABLE bool clearPinOnJoint(int index); - /**jsdoc + /*@jsdoc * Gets the maximum error distance from the most recent inverse kinematics (IK) solution. * @function MyAvatar.getIKErrorOnLastSolve * @returns {number} The maximum IK error distance. */ Q_INVOKABLE float getIKErrorOnLastSolve() const; - /**jsdoc + /*@jsdoc * Changes the user's avatar and associated descriptive name. * @function MyAvatar.useFullAvatarURL * @param {string} fullAvatarURL - The URL of the avatar's .fst file. @@ -1365,7 +1366,7 @@ public: */ Q_INVOKABLE void useFullAvatarURL(const QUrl& fullAvatarURL, const QString& modelName = QString()); - /**jsdoc + /*@jsdoc * Gets the complete URL for the current avatar. * @function MyAvatar.getFullAvatarURLFromPreferences * @returns {string} The full avatar model name. @@ -1374,7 +1375,7 @@ public: */ Q_INVOKABLE QUrl getFullAvatarURLFromPreferences() const { return _fullAvatarURLFromPreferences; } - /**jsdoc + /*@jsdoc * Gets the full avatar model name for the current avatar. * @function MyAvatar.getFullAvatarModelName * @returns {string} The full avatar model name. @@ -1445,7 +1446,7 @@ public: bool hasDriveInput() const; - /**jsdoc + /*@jsdoc * Gets the current avatar entity IDs and their properties. * @function MyAvatar.getAvatarEntitiesVariant * @returns {MyAvatar.AvatarEntityData[]} The current avatar entity IDs and their properties. @@ -1454,59 +1455,60 @@ public: void removeWornAvatarEntity(const EntityItemID& entityID); void clearWornAvatarEntities(); + bool hasAvatarEntities() const; - /**jsdoc + /*@jsdoc * Checks whether your avatar is flying. * @function MyAvatar.isFlying * @returns {boolean} true if your avatar is flying and not taking off or falling, false if not. */ Q_INVOKABLE bool isFlying(); - /**jsdoc + /*@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 + /*@jsdoc + * 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 + /*@jsdoc + * 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 + /*@jsdoc + * 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); - /**jsdoc + /*@jsdoc * 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(); - /**jsdoc + /*@jsdoc * Sets your preference for flying in HMD display mode. Note that your ability to fly also depends on whether the domain * you're in allows you to fly. * @function MyAvatar.setFlyingHMDPref @@ -1515,7 +1517,7 @@ public: */ Q_INVOKABLE void setFlyingHMDPref(bool enabled); - /**jsdoc + /*@jsdoc * Gets your preference for flying in HMD display mode. Note that your ability to fly also depends on whether the domain * you're in allows you to fly. * @function MyAvatar.getFlyingHMDPref @@ -1524,7 +1526,7 @@ public: */ Q_INVOKABLE bool getFlyingHMDPref(); - /**jsdoc + /*@jsdoc * Set your preference for hand-relative movement. * @function MyAvatar.setHandRelativeMovement * @param {number} enabled - Set true if you want to enable hand-relative movement, otherwise set to false. @@ -1532,7 +1534,7 @@ public: */ Q_INVOKABLE void setMovementReference(int enabled); - /**jsdoc + /*@jsdoc * Get your preference for hand-relative movement. * @function MyAvatar.getHandRelativeMovement * @returns {number} true if your preference is for user locomotion to be relative to the direction your @@ -1540,70 +1542,70 @@ public: */ Q_INVOKABLE int getMovementReference(); - /**jsdoc + /*@jsdoc * Set the first 'shifting point' for acceleration step function. * @function MyAvatar.setDriveGear1 * @param {number} shiftPoint - Set the first shift point for analog movement acceleration step function, between [0.0, 1.0]. Must be less than or equal to Gear 2. */ Q_INVOKABLE void setDriveGear1(float shiftPoint); - /**jsdoc + /*@jsdoc * Get the first 'shifting point' for acceleration step function. * @function MyAvatar.getDriveGear1 * @returns {number} Value between [0.0, 1.0]. */ Q_INVOKABLE float getDriveGear1(); - /**jsdoc + /*@jsdoc * Set the second 'shifting point' for acceleration step function. * @function MyAvatar.setDriveGear2 * @param {number} shiftPoint - Defines the second shift point for analog movement acceleration step function, between [0, 1]. Must be greater than or equal to Gear 1 and less than or equal to Gear 2. */ Q_INVOKABLE void setDriveGear2(float shiftPoint); - /**jsdoc + /*@jsdoc * Get the second 'shifting point' for acceleration step function. * @function MyAvatar.getDriveGear2 * @returns {number} Value between [0.0, 1.0]. */ Q_INVOKABLE float getDriveGear2(); - /**jsdoc + /*@jsdoc * Set the third 'shifting point' for acceleration step function. * @function MyAvatar.setDriveGear3 * @param {number} shiftPoint - Defines the third shift point for analog movement acceleration step function, between [0, 1]. Must be greater than or equal to Gear 2 and less than or equal to Gear 4. */ Q_INVOKABLE void setDriveGear3(float shiftPoint); - /**jsdoc + /*@jsdoc * Get the third 'shifting point' for acceleration step function. * @function MyAvatar.getDriveGear3 * @returns {number} Value between [0.0, 1.0]. */ Q_INVOKABLE float getDriveGear3(); - /**jsdoc + /*@jsdoc * Set the fourth 'shifting point' for acceleration step function. * @function MyAvatar.setDriveGear4 * @param {number} shiftPoint - Defines the fourth shift point for analog movement acceleration step function, between [0, 1]. Must be greater than Gear 3 and less than Gear 5. */ Q_INVOKABLE void setDriveGear4(float shiftPoint); - /**jsdoc + /*@jsdoc * Get the fourth 'shifting point' for acceleration step function. * @function MyAvatar.getDriveGear4 * @returns {number} Value between [0.0, 1.0]. */ Q_INVOKABLE float getDriveGear4(); - /**jsdoc + /*@jsdoc * Set the fifth 'shifting point' for acceleration step function. * @function MyAvatar.setDriveGear5 * @param {number} shiftPoint - Defines the fifth shift point for analog movement acceleration step function, between [0, 1]. Must be greater than or equal to Gear 4. */ Q_INVOKABLE void setDriveGear5(float shiftPoint); - /**jsdoc + /*@jsdoc * Get the fifth 'shifting point' for acceleration step function. * @function MyAvatar.getDriveGear5 * @returns {number} Value between [0.0, 1.0]. @@ -1614,7 +1616,7 @@ public: int getControlSchemeIndex(); - /**jsdoc + /*@jsdoc * Gets 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.getAvatarScale @@ -1622,26 +1624,26 @@ 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. + /*@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. * @function MyAvatar.setAvatarScale * @param {number} scale - The target scale for the avatar, range 0.0051000.0. */ Q_INVOKABLE void setAvatarScale(float scale); - /**jsdoc + /*@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); - /**jsdoc + /*@jsdoc * Gets whether the avatar will currently collide with entities. *

Note: The avatar will always collide with entities if in a zone that disallows collisionless avatars. * @function MyAvatar.getCollisionsEnabled @@ -1649,31 +1651,31 @@ public: */ Q_INVOKABLE bool getCollisionsEnabled(); - /**jsdoc + /*@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); - /**jsdoc + /*@jsdoc * Gets whether the avatar will collide with other avatars. * @function MyAvatar.getOtherAvatarsCollisionsEnabled * @returns {boolean} true if the avatar will collide with other avatars, false if it won't. */ Q_INVOKABLE bool getOtherAvatarsCollisionsEnabled(); - /**jsdoc + /*@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. */ Q_INVOKABLE QVariantMap getCollisionCapsule() const; - /**jsdoc + /*@jsdoc * @function MyAvatar.setCharacterControllerEnabled * @param {boolean} enabled - true to enable the avatar to collide with entities, false to * disable. @@ -1681,14 +1683,14 @@ public: */ Q_INVOKABLE void setCharacterControllerEnabled(bool enabled); // deprecated - /**jsdoc + /*@jsdoc * @function MyAvatar.getCharacterControllerEnabled * @returns {boolean} true if the avatar will currently collide with entities, false if it won't. * @deprecated This function is deprecated and will be removed. Use {@link MyAvatar.getCollisionsEnabled} instead. */ Q_INVOKABLE bool getCharacterControllerEnabled(); // deprecated - /**jsdoc + /*@jsdoc * Gets the rotation of a joint relative to the avatar. * @comment Different behavior to the Avatar version of this method. * @function MyAvatar.getAbsoluteJointRotationInObjectFrame @@ -1701,7 +1703,7 @@ public: */ virtual glm::quat getAbsoluteJointRotationInObjectFrame(int index) const override; - /**jsdoc + /*@jsdoc * Gets the translation of a joint relative to the avatar. * @comment Different behavior to the Avatar version of this method. * @function MyAvatar.getAbsoluteJointTranslationInObjectFrame @@ -1744,22 +1746,22 @@ public: // results are in sensor frame (-z foward) 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 + /*@jsdoc + * 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 + /*@jsdoc + * 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; }; @@ -1800,7 +1802,7 @@ public: void setAnalogPlusSprintSpeed(float value); float getAnalogPlusSprintSpeed() const; void setSitStandStateChange(bool stateChanged); - float getSitStandStateChange() const; + bool getSitStandStateChange() const; void updateSitStandState(float newHeightReading, float dt); QVector getScriptUrls(); @@ -1819,7 +1821,7 @@ public: glm::vec3 getNextPosition() { return _goToPending ? _goToPosition : getWorldPosition(); } void prepareAvatarEntityDataForReload(); - /**jsdoc + /*@jsdoc * Turns the avatar's head until it faces the target point within a +90/-90 degree range. * Once this method is called, API calls have full control of the head for a limited time. * If this method is not called for 2 seconds, the engine regains control of the head. @@ -1828,43 +1830,43 @@ public: */ Q_INVOKABLE void setHeadLookAt(const glm::vec3& lookAtTarget); - /**jsdoc + /*@jsdoc * Gets the current target point of the head's look direction in world coordinates. * @function MyAvatar.getHeadLookAt * @returns {Vec3} The head's look-at target in world coordinates. */ Q_INVOKABLE glm::vec3 getHeadLookAt() { return _lookAtCameraTarget; } - /**jsdoc + /*@jsdoc * Returns control of the avatar's head to the engine, and releases control from API calls. * @function MyAvatar.releaseHeadLookAtControl */ Q_INVOKABLE void releaseHeadLookAtControl(); - /**jsdoc + /*@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. */ Q_INVOKABLE void setEyesLookAt(const glm::vec3& lookAtTarget); - /**jsdoc + /*@jsdoc * Gets the current target point of the eyes look direction in world coordinates. * @function MyAvatar.getEyesLookAt * @returns {Vec3} The eyes' look-at target in world coordinates. */ Q_INVOKABLE glm::vec3 getEyesLookAt() { return _eyesLookAtTarget.get(); } - /**jsdoc + /*@jsdoc * Returns control of the avatar's eyes to the engine, and releases control from API calls. * @function MyAvatar.releaseEyesLookAtControl */ Q_INVOKABLE void releaseEyesLookAtControl(); - /**jsdoc - * Sets the point-at target for the "point" reaction that may be started with {@link MyAvatar.beginReaction}. + /*@jsdoc + * 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 @@ -1875,7 +1877,7 @@ public: glm::quat getLookAtRotation() { return _lookAtYaw * _lookAtPitch; } - /**jsdoc + /*@jsdoc * Creates a new grab that grabs an entity. * @function MyAvatar.grab * @param {Uuid} targetID - The ID of the entity to grab. @@ -1905,14 +1907,14 @@ public: Q_INVOKABLE const QUuid grab(const QUuid& targetID, int parentJointIndex, glm::vec3 positionalOffset, glm::quat rotationalOffset); - /**jsdoc + /*@jsdoc * Releases (deletes) a grab to stop grabbing an entity. * @function MyAvatar.releaseGrab * @param {Uuid} grabID - The ID of the grab to release. */ Q_INVOKABLE void releaseGrab(const QUuid& grabID); - /**jsdoc + /*@jsdoc * Gets details of all avatar entities. *

Warning: Potentially an expensive call. Do not use if possible.

* @function MyAvatar.getAvatarEntityData @@ -1925,57 +1927,59 @@ public: AvatarEntityMap getAvatarEntityDataNonDefault() const override; - /**jsdoc + /*@jsdoc * Sets all avatar entities from an object. * @function MyAvatar.setAvatarEntityData * @param {AvatarEntityMap} avatarEntityData - Details of the avatar entities. */ void setAvatarEntityData(const AvatarEntityMap& avatarEntityData) override; - /**jsdoc + /*@jsdoc * @comment Uses the base class's JSDoc. */ void updateAvatarEntity(const QUuid& entityID, const QByteArray& entityData) override; void avatarEntityDataToJson(QJsonObject& root) const override; - /**jsdoc + void storeAvatarEntityDataPayload(const QUuid& entityID, const QByteArray& payload) override; + + /*@jsdoc * @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 + /*@jsdoc + * 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()); - /**jsdoc + /*@jsdoc * Gets the current flow configuration. * @function MyAvatar.getFlowData * @returns {MyAvatar.FlowData} */ Q_INVOKABLE QVariantMap getFlowData(); - /**jsdoc + /*@jsdoc * Gets the indexes of currently colliding flow joints. * @function MyAvatar.getCollidingFlowJoints * @returns {number[]} The indexes of currently colliding flow joints. */ Q_INVOKABLE QVariantList getCollidingFlowJoints(); - /**jsdoc + /*@jsdoc * Starts a sitting action for the avatar. * @function MyAvatar.beginSit * @param {Vec3} position - The position where the avatar should sit. @@ -1983,7 +1987,7 @@ public: */ Q_INVOKABLE void beginSit(const glm::vec3& position, const glm::quat& rotation); - /**jsdoc + /*@jsdoc * Ends a sitting action for the avatar. * @function MyAvatar.endSit * @param {Vec3} position - The position of the avatar when standing up. @@ -1991,7 +1995,7 @@ public: */ Q_INVOKABLE void endSit(const glm::vec3& position, const glm::quat& rotation); - /**jsdoc + /*@jsdoc * Gets whether the avatar is in a seated pose. The seated pose is set by calling {@link MyAvatar.beginSit}. * @function MyAvatar.isSeated * @returns {boolean} true if the avatar is in a seated pose, false if it isn't. @@ -2024,12 +2028,12 @@ public: public slots: - /**jsdoc + /*@jsdoc * @comment Uses the base class's JSDoc. */ virtual void setSessionUUID(const QUuid& sessionUUID) override; - /**jsdoc + /*@jsdoc * Increases the avatar's scale by five percent, up to a minimum scale of 1000. * @function MyAvatar.increaseSize * @example
@@ -2042,7 +2046,7 @@ public slots: */ void increaseSize(); - /**jsdoc + /*@jsdoc * Decreases the avatar's scale by five percent, down to a minimum scale of 0.25. * @function MyAvatar.decreaseSize * @example @@ -2055,35 +2059,35 @@ public slots: */ void decreaseSize(); - /**jsdoc + /*@jsdoc * Resets the avatar's scale back to the default scale of 1.0. * @function MyAvatar.resetSize */ void resetSize(); - /**jsdoc + /*@jsdoc * @function MyAvatar.animGraphLoaded * @deprecated This function is deprecated and will be removed. */ void animGraphLoaded(); - /**jsdoc + /*@jsdoc * Sets the amount of gravity applied to the avatar in the y-axis direction. (Negative values are downward.) * @function MyAvatar.setGravity * @param {number} gravity - The amount of gravity to be applied to the avatar, in m/s2. */ 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 + /*@jsdoc + * 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. */ float getGravity(); - /**jsdoc - * Moves the avatar to a new position and/or orientation in the domain, with safe landing, while taking into account avatar + /*@jsdoc + * 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. @@ -2092,37 +2096,37 @@ 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 + /*@jsdoc * Moves the avatar to a new position and/or orientation in the domain. * @function MyAvatar.goToLocation * @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. */ void goToLocation(const glm::vec3& newPosition, bool hasOrientation = false, const glm::quat& newOrientation = glm::quat(), bool shouldFaceLocation = false, bool withSafeLanding = true); - /**jsdoc + /*@jsdoc * Moves the avatar to a new position and (optional) orientation in the domain, with safe landing. * @function MyAvatar.goToLocation * @param {MyAvatar.GoToProperties} target - The goto target. */ void goToLocation(const QVariant& properties); - /**jsdoc + /*@jsdoc * Moves the avatar to a new position, with safe landing, and enables collisions. * @function MyAvatar.goToLocationAndEnableCollisions * @param {Vec3} position - The new position for the avatar, in world coordinates. */ void goToLocationAndEnableCollisions(const glm::vec3& newPosition); - /**jsdoc + /*@jsdoc * @function MyAvatar.safeLanding * @param {Vec3} position -The new position for the avatar, in world coordinates. * @returns {boolean} true if the avatar was moved, false if it wasn't. @@ -2131,171 +2135,165 @@ public slots: bool safeLanding(const glm::vec3& position); - /**jsdoc + /*@jsdoc * @function MyAvatar.restrictScaleFromDomainSettings * @param {object} domainSettings - Domain settings. * @deprecated This function is deprecated and will be removed. */ void restrictScaleFromDomainSettings(const QJsonObject& domainSettingsObject); - /**jsdoc + /*@jsdoc * @function MyAvatar.clearScaleRestriction * @deprecated This function is deprecated and will be removed. */ void clearScaleRestriction(); - /**jsdoc + /*@jsdoc * 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 void addThrust(glm::vec3 newThrust) { _thrust += newThrust; }; - /**jsdoc + /*@jsdoc * 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; }; - /**jsdoc + /*@jsdoc * 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 + /*@jsdoc + * Updates avatar motion behavior from the Developer > Avatar > Enable Default Motor Control and Enable Scripted * Motor Control menu items. * @function MyAvatar.updateMotionBehaviorFromMenu */ Q_INVOKABLE void updateMotionBehaviorFromMenu(); - /**jsdoc + /*@jsdoc * @function MyAvatar.setToggleHips * @param {boolean} enabled - Enabled. * @deprecated This function is deprecated and will be removed. */ 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 + /*@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 * step happens). * @function MyAvatar.setEnableDebugDrawBaseOfSupport * @param {boolean} enabled - true to show the debug graphics, false to hide. */ void setEnableDebugDrawBaseOfSupport(bool isEnabled); - /**jsdoc + /*@jsdoc * Displays default pose debug graphics. * @function MyAvatar.setEnableDebugDrawDefaultPose * @param {boolean} enabled - true to show the debug graphics, false to hide. */ void setEnableDebugDrawDefaultPose(bool isEnabled); - /**jsdoc - * Displays animation debug graphics. By default, the animation poses used for rendering are displayed. However, + /*@jsdoc + * 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. */ void setEnableDebugDrawAnimPose(bool isEnabled); - /**jsdoc - * Sets the animation node to display when animation debug graphics are enabled with + /*@jsdoc + * 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); - /**jsdoc + /*@jsdoc * Displays position debug graphics. * @function MyAvatar.setEnableDebugDrawPosition * @param {boolean} enabled - true to show the debug graphics, false to hide. */ void setEnableDebugDrawPosition(bool isEnabled); - /**jsdoc + /*@jsdoc * Displays controller hand target debug graphics. * @function MyAvatar.setEnableDebugDrawHandControllers * @param {boolean} enabled - true to show the debug graphics, false to hide. */ void setEnableDebugDrawHandControllers(bool isEnabled); - /**jsdoc + /*@jsdoc * Displays sensor-to-world matrix debug graphics. * @function MyAvatar.setEnableDebugDrawSensorToWorldMatrix * @param {boolean} enable - true to show the debug graphics, false to hide. */ void setEnableDebugDrawSensorToWorldMatrix(bool isEnabled); - /**jsdoc + /*@jsdoc * Displays inverse kinematics targets debug graphics. * @function MyAvatar.setEnableDebugDrawIKTargets * @param {boolean} enabled - true to show the debug graphics, false to hide. */ void setEnableDebugDrawIKTargets(bool isEnabled); - /**jsdoc + /*@jsdoc * Displays inverse kinematics constraints debug graphics. * @function MyAvatar.setEnableDebugDrawIKConstraints * @param {boolean} enabled - true to show the debug graphics, false to hide. */ void setEnableDebugDrawIKConstraints(bool isEnabled); - /**jsdoc + /*@jsdoc * Displays inverse kinematics chains debug graphics. * @function MyAvatar.setEnableDebugDrawIKChains * @param {boolean} enabled - true to show the debug graphics, false to hide. */ void setEnableDebugDrawIKChains(bool isEnabled); - /**jsdoc + /*@jsdoc * Displays detailed collision debug graphics. * @function MyAvatar.setEnableDebugDrawDetailedCollision * @param {boolean} enabled - true to show the debug graphics, false to hide. */ void setEnableDebugDrawDetailedCollision(bool isEnabled); - /**jsdoc + /*@jsdoc * Gets whether your avatar mesh is visible. * @function MyAvatar.getEnableMeshVisible * @returns {boolean} true if your avatar's mesh is visible, otherwise false. */ bool getEnableMeshVisible() const override; - /**jsdoc - * @function MyAvatar.storeAvatarEntityDataPayload - * @deprecated This function is deprecated and will be removed. - */ - void storeAvatarEntityDataPayload(const QUuid& entityID, const QByteArray& payload) override; - - /**jsdoc + /*@jsdoc * @comment Uses the base class's JSDoc. */ void clearAvatarEntity(const QUuid& entityID, bool requiresRemovalFromTree = true) override; - /**jsdoc + /*@jsdoc * @function MyAvatar.sanitizeAvatarEntityProperties * @param {EntityItemProperties} properties - Properties. * @deprecated This function is deprecated and will be removed. */ void sanitizeAvatarEntityProperties(EntityItemProperties& properties) const; - /**jsdoc + /*@jsdoc * Sets whether your avatar mesh is visible to you. * @function MyAvatar.setEnableMeshVisible * @param {boolean} enabled - true to show your avatar mesh, false to hide. @@ -2307,7 +2305,7 @@ public slots: */ virtual void setEnableMeshVisible(bool isEnabled) override; - /**jsdoc + /*@jsdoc * Sets whether inverse kinematics (IK) is enabled for your avatar. * @function MyAvatar.setEnableInverseKinematics * @param {boolean} enabled - true to enable IK, false to disable. @@ -2315,28 +2313,28 @@ public slots: void setEnableInverseKinematics(bool isEnabled); - /**jsdoc + /*@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 + /*@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. */ void setAnimGraphOverrideUrl(QUrl value); // thread-safe - /**jsdoc + /*@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. @@ -2345,16 +2343,16 @@ public slots: */ QUrl getAnimGraphUrl() const; // thread-safe - /**jsdoc + /*@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. */ void setAnimGraphUrl(const QUrl& url); // thread-safe - /**jsdoc + /*@jsdoc * Gets your listening position for spatialized audio. The position depends on the value of the * {@link Myavatar|audioListenerMode} property. * @function MyAvatar.getPositionForAudio @@ -2362,22 +2360,22 @@ public slots: */ glm::vec3 getPositionForAudio(); - /**jsdoc - * Gets the orientation of your listening position for spatialized audio. The orientation depends on the value of the + /*@jsdoc + * 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. */ glm::quat getOrientationForAudio(); - /**jsdoc + /*@jsdoc * @function MyAvatar.setModelScale * @param {number} scale - The scale. * @deprecated This function is deprecated and will be removed. */ virtual void setModelScale(float scale) override; - /**jsdoc + /*@jsdoc * Gets the list of reactions names that can be triggered using {@link MyAvatar.triggerReaction}. *

See also: {@link MyAvatar.getBeginEndReactions}. * @function MyAvatar.getTriggerReactions @@ -2388,8 +2386,8 @@ public slots: QStringList getTriggerReactions() const; - /**jsdoc - * Gets the list of reactions names that can be enabled using {@link MyAvatar.beginReaction} and + /*@jsdoc + * 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 @@ -2400,7 +2398,7 @@ public slots: */ QStringList getBeginEndReactions() const; - /**jsdoc + /*@jsdoc * Plays a reaction on the avatar. Once the reaction is complete it will stop playing. *

Only reaction names returned by {@link MyAvatar.getTriggerReactions} are available.

* @function MyAvatar.triggerReaction @@ -2409,8 +2407,8 @@ public slots: */ bool triggerReaction(QString reactionName); - /**jsdoc - * Starts playing a reaction on the avatar. The reaction will continue to play until stopped using + /*@jsdoc + * 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 @@ -2419,7 +2417,7 @@ public slots: */ bool beginReaction(QString reactionName); - /**jsdoc + /*@jsdoc * Stops playing a reaction that was started using {@link MyAvatar.beginReaction}. * @function MyAvatar.endReaction * @param {string} reactionName - The reaction to stop playing. @@ -2429,63 +2427,63 @@ public slots: signals: - /**jsdoc + /*@jsdoc * Triggered when the {@link MyAvatar|audioListenerMode} property value changes. * @function MyAvatar.audioListenerModeChanged - * @returns {Signal} + * @returns {Signal} */ void audioListenerModeChanged(); - /**jsdoc + /*@jsdoc * 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); - /**jsdoc + /*@jsdoc * 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 + /*@jsdoc + * 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 + /*@jsdoc + * 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 + /*@jsdoc * @function MyAvatar.transformChanged - * @returns {Signal} + * @returns {Signal} * @deprecated This signal is deprecated and will be removed. */ void transformChanged(); - /**jsdoc + /*@jsdoc * 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); - /**jsdoc + /*@jsdoc * Triggered when the avatar collides with an entity. * @function MyAvatar.collisionWithEntity * @param {Collision} collision - Details of the collision. @@ -2497,25 +2495,25 @@ signals: */ void collisionWithEntity(const Collision& collision); - /**jsdoc + /*@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} */ void collisionsEnabledChanged(bool enabled); - /**jsdoc + /*@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} */ void otherAvatarsCollisionsEnabledChanged(bool enabled); - /**jsdoc + /*@jsdoc * Triggered when the avatar's animation graph being used changes. * @function MyAvatar.animGraphUrlChanged * @param {string} url - The URL of the new animation graph JSON file. @@ -2526,40 +2524,40 @@ signals: * }); */ void animGraphUrlChanged(const QUrl& url); - /**jsdoc + /*@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); - /**jsdoc + /*@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(); - /**jsdoc + /*@jsdoc * Triggered when the avatar's model finishes loading. * @function MyAvatar.onLoadComplete * @returns {Signal} */ void onLoadComplete(); - /**jsdoc + /*@jsdoc * Triggered when the avatar's model has failed to load. * @function MyAvatar.onLoadFailed * @returns {Signal} */ void onLoadFailed(); - /**jsdoc + /*@jsdoc * Triggered when your avatar changes from being active to being away. * @function MyAvatar.wentAway - * @returns {Signal} + * @returns {Signal} * @example * MyAvatar.wentAway.connect(function () { * print("My avatar went away"); @@ -2568,77 +2566,77 @@ signals: */ void wentAway(); - /**jsdoc + /*@jsdoc * Triggered when your avatar changes from being away to being active. * @function MyAvatar.wentActive - * @returns {Signal} + * @returns {Signal} */ void wentActive(); - /**jsdoc + /*@jsdoc * 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(); - /**jsdoc + /*@jsdoc * 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 + /*@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} */ void hmdAvatarAlignmentTypeChanged(const QString& type); - /**jsdoc + /*@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 + /*@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 * {@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 + /*@jsdoc + * 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(); - /**jsdoc + /*@jsdoc * Triggered when the hand touch effect is enabled or disabled for the avatar. *

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} */ void shouldDisableHandTouchChanged(bool shouldDisable); - /**jsdoc + /*@jsdoc * Triggered when the hand touch is enabled or disabled on a specific entity. *

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.

@@ -2656,6 +2654,7 @@ private slots: protected: void handleChangedAvatarEntityData(); + void handleCanRezAvatarEntitiesChanged(bool canRezAvatarEntities); virtual void beParentOfChild(SpatiallyNestablePointer newChild) const override; virtual void forgetChild(SpatiallyNestablePointer newChild) const override; virtual void recalculateChildCauterization() const override; @@ -2705,18 +2704,22 @@ 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; bool findAvatarEntity(const QString& modelURL, const QString& jointName, QUuid& entityID); + void addAvatarEntitiesToTree(); + + // FIXME: Rename to clearAvatarEntity() once the API call is removed. + void clearAvatarEntityInternal(const QUuid& entityID) override; bool cameraInsideHead(const glm::vec3& cameraPosition) const; void updateEyeContactTarget(float deltaTime); // These are made private for MyAvatar so that you will use the "use" methods instead - /**jsdoc + /*@jsdoc * @comment Borrows the base class's JSDoc. */ Q_INVOKABLE virtual void setSkeletonModelURL(const QUrl& skeletonModelURL) override; @@ -2907,8 +2910,6 @@ private: void setForceActivateVertical(bool val); bool getForceActivateHorizontal() const; void setForceActivateHorizontal(bool val); - bool getToggleHipsFollowing() const; - void setToggleHipsFollowing(bool followHead); std::atomic _forceActivateRotation { false }; std::atomic _forceActivateVertical { false }; std::atomic _forceActivateHorizontal { false }; @@ -3109,6 +3110,8 @@ private: glm::vec3 _cameraEyesOffset; float _landingAfterJumpTime { 0.0f }; + + QTimer _addAvatarEntitiesToTreeTimer; }; QScriptValue audioListenModeToScriptValue(QScriptEngine* engine, const AudioListenerMode& audioListenerMode); diff --git a/interface/src/commerce/Wallet.h b/interface/src/commerce/Wallet.h index 52b956dc5b..224e58d58c 100644 --- a/interface/src/commerce/Wallet.h +++ b/interface/src/commerce/Wallet.h @@ -55,7 +55,7 @@ public: void getWalletStatus(); - /**jsdoc + /*@jsdoc *

A WalletStatus may have one of the following values:

*
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.

Play a clapping animation on your avatar for three seconds. Log all the animation state dictionary parameters for a short while.Report the position of the avatar you're currently looking at.Report the position of your left hand relative to your avatar.Report the position of your right hand relative to your avatar.Report the pose of your avatar's right hand.Reset your avatar's size to default then grow it 5 times.Reset your avatar's size to default then shrink it 5 times.Report when your avatar goes away.
* diff --git a/interface/src/raypick/CollisionPick.cpp b/interface/src/raypick/CollisionPick.cpp index 2602bdb0a0..842de9f48a 100644 --- a/interface/src/raypick/CollisionPick.cpp +++ b/interface/src/raypick/CollisionPick.cpp @@ -57,7 +57,7 @@ void buildObjectIntersectionsMap(IntersectionType intersectionType, const std::v } } -/**jsdoc +/*@jsdoc * An intersection result for a collision pick. * * @typedef {object} CollisionPickResult @@ -66,7 +66,7 @@ void buildObjectIntersectionsMap(IntersectionType intersectionType, const std::v * @property {CollisionRegion} collisionRegion - The collision region that was used. Valid even if there was no intersection. */ -/**jsdoc +/*@jsdoc * Information about a {@link CollisionPick}'s intersection with an object. * * @typedef {object} IntersectingObject @@ -76,7 +76,7 @@ void buildObjectIntersectionsMap(IntersectionType intersectionType, const std::v * @property {CollisionContact[]} collisionContacts - Information on the penetration between the pick and the object. */ -/**jsdoc +/*@jsdoc * A pair of points that represents part of an overlap between a {@link CollisionPick} and an object in the physics engine. * Points which are further apart represent deeper overlap. * diff --git a/interface/src/raypick/LaserPointerScriptingInterface.h b/interface/src/raypick/LaserPointerScriptingInterface.h index 5745e29e69..ab3bca57d6 100644 --- a/interface/src/raypick/LaserPointerScriptingInterface.h +++ b/interface/src/raypick/LaserPointerScriptingInterface.h @@ -20,7 +20,7 @@ class LaserPointerScriptingInterface : public QObject, public Dependency { Q_OBJECT SINGLETON_DEPENDENCY -/**jsdoc +/*@jsdoc * The LaserPointers API is a subset of the {@link Pointers} API. It lets you create, manage, and visually * represent objects for repeatedly calculating ray intersections with avatars, entities, and overlays. Ray pointers can also * be configured to generate events on entities and overlays intersected. @@ -40,7 +40,7 @@ class LaserPointerScriptingInterface : public QObject, public Dependency { */ public: - /**jsdoc + /*@jsdoc * Creates a new ray pointer. The pointer can have a wide range of behaviors depending on the properties specified. For * example, it may be a static ray pointer, a mouse ray pointer, or joint ray pointer. *

Warning: Pointers created using this method currently always intersect at least visible and @@ -61,7 +61,7 @@ public: // jsdoc @borrows from Pointers Q_INVOKABLE void removeLaserPointer(unsigned int uid) const { DependencyManager::get()->removePointer(uid); } - /**jsdoc + /*@jsdoc * Edits a render state of a pointer, to change its visual appearance for the state when the pointer is intersecting * something. *

Note: You can only edit the properties of the existing parts of the pointer; you cannot change the @@ -75,7 +75,7 @@ public: */ Q_INVOKABLE void editRenderState(unsigned int uid, const QString& renderState, const QVariant& properties) const; - /**jsdoc + /*@jsdoc * Sets the render state of a pointer, to change its visual appearance and possibly disable or enable it. * @function LaserPointers.setRenderState * @param {string} renderState -

The name of the render state to set the pointer to. This may be:

@@ -87,7 +87,7 @@ public: */ Q_INVOKABLE void setRenderState(unsigned int uid, const QString& renderState) const { DependencyManager::get()->setRenderState(uid, renderState.toStdString()); } - /**jsdoc + /*@jsdoc * Gets the most recent intersection of a pointer. A pointer continues to be updated ready to return a result, as long as * it is enabled, regardless of the render state. * @function LaserPointers.getPrevRayPickResult @@ -99,7 +99,7 @@ public: // jsdoc @borrows from Pointers Q_INVOKABLE void setPrecisionPicking(unsigned int uid, bool precisionPicking) const { DependencyManager::get()->setPrecisionPicking(uid, precisionPicking); } - /**jsdoc + /*@jsdoc * Sets the length of a pointer. * @function LaserPointers.setLaserLength * @param {number} id - The ID of the pointer. @@ -107,7 +107,7 @@ public: */ Q_INVOKABLE void setLaserLength(unsigned int uid, float laserLength) const { DependencyManager::get()->setLength(uid, laserLength); } - /**jsdoc + /*@jsdoc * Sets a list of entity and avatar IDs that a pointer should ignore during intersection. * @function LaserPointers.setIgnoreItems * @param {number} id - The ID of the pointer. @@ -115,7 +115,7 @@ public: */ Q_INVOKABLE void setIgnoreItems(unsigned int uid, const QScriptValue& ignoreEntities) const; - /**jsdoc + /*@jsdoc * Sets a list of entity and avatar IDs that a pointer should include during intersection, instead of intersecting with * everything. * @function LaserPointers.setIncludeItems @@ -125,7 +125,7 @@ public: Q_INVOKABLE void setIncludeItems(unsigned int uid, const QScriptValue& includeEntities) const; - /**jsdoc + /*@jsdoc * Locks a pointer onto a specific entity or avatar. * @function LaserPointers.setLockEndUUID * @param {number} id - The ID of the pointer. @@ -137,7 +137,7 @@ public: Q_INVOKABLE void setLockEndUUID(unsigned int uid, const QUuid& objectID, bool isAvatar, const glm::mat4& offsetMat = glm::mat4()) const { DependencyManager::get()->setLockEndUUID(uid, objectID, isAvatar, offsetMat); } - /**jsdoc + /*@jsdoc * Checks if a pointer is associated with the left hand: a pointer with joint property set to * "_CONTROLLER_LEFTHAND" or "_CAMERA_RELATIVE_CONTROLLER_LEFTHAND". * @function LaserPointers.isLeftHand @@ -146,7 +146,7 @@ public: */ Q_INVOKABLE bool isLeftHand(unsigned int uid) { return DependencyManager::get()->isLeftHand(uid); } - /**jsdoc + /*@jsdoc * Checks if a pointer is associated with the right hand: a pointer with joint property set to * "_CONTROLLER_RIGHTHAND" or "_CAMERA_RELATIVE_CONTROLLER_RIGHTHAND". * @function LaserPointers.isRightHand @@ -155,7 +155,7 @@ public: */ Q_INVOKABLE bool isRightHand(unsigned int uid) { return DependencyManager::get()->isRightHand(uid); } - /**jsdoc + /*@jsdoc * Checks if a pointer is associated with the system mouse: a pointer with joint property set to * "Mouse". * @function LaserPointers.isMouse diff --git a/interface/src/raypick/ParabolaPick.h b/interface/src/raypick/ParabolaPick.h index 0d720914cc..cb03ecbb76 100644 --- a/interface/src/raypick/ParabolaPick.h +++ b/interface/src/raypick/ParabolaPick.h @@ -42,7 +42,7 @@ public: float parabolicDistance { FLT_MAX }; bool intersects { false }; - /**jsdoc + /*@jsdoc * An intersection result for a parabola pick. * * @typedef {object} ParabolaPickResult diff --git a/interface/src/raypick/PickScriptingInterface.cpp b/interface/src/raypick/PickScriptingInterface.cpp index 1f940f761d..e7777efe45 100644 --- a/interface/src/raypick/PickScriptingInterface.cpp +++ b/interface/src/raypick/PickScriptingInterface.cpp @@ -71,7 +71,7 @@ PickFilter getPickFilter(unsigned int filter) { return PickFilter(filter); } -/**jsdoc +/*@jsdoc * The properties of a ray pick. * * @typedef {object} Picks.RayPickProperties @@ -157,7 +157,7 @@ std::shared_ptr PickScriptingInterface::buildRayPick(const QVariantMa return rayPick; } -/**jsdoc +/*@jsdoc * The properties of a stylus pick. * * @typedef {object} Picks.StylusPickProperties @@ -209,7 +209,7 @@ std::shared_ptr PickScriptingInterface::buildStylusPick(const QVarian // NOTE: Laser pointer still uses scaleWithAvatar. Until scaleWithAvatar is also deprecated for pointers, scaleWithAvatar // should not be removed from the pick API. -/**jsdoc +/*@jsdoc * The properties of a parabola pick. * * @typedef {object} Picks.ParabolaPickProperties @@ -320,7 +320,7 @@ std::shared_ptr PickScriptingInterface::buildParabolaPick(const QVari } -/**jsdoc +/*@jsdoc * The properties of a collision pick. * * @typedef {object} Picks.CollisionPickProperties diff --git a/interface/src/raypick/PickScriptingInterface.h b/interface/src/raypick/PickScriptingInterface.h index 58ed3326ec..72470b42ee 100644 --- a/interface/src/raypick/PickScriptingInterface.h +++ b/interface/src/raypick/PickScriptingInterface.h @@ -15,7 +15,7 @@ #include #include -/**jsdoc +/*@jsdoc * The Picks API lets you create and manage objects for repeatedly calculating intersections. * * @namespace Picks @@ -105,7 +105,7 @@ class PickScriptingInterface : public QObject, public Dependency { public: void registerMetaTypes(QScriptEngine* engine); - /**jsdoc + /*@jsdoc * Creates a new pick. Different {@link PickType}s use different properties, and within one PickType the properties you * choose can lead to a wide range of behaviors. For example, with PickType.Ray, the properties could * configure a mouse ray pick, an avatar head ray pick, or a joint ray pick. @@ -120,21 +120,21 @@ public: // TODO: expand Pointers to be able to be fully configurable with PickFilters Q_INVOKABLE unsigned int createPick(const PickQuery::PickType type, const QVariant& properties); - /**jsdoc + /*@jsdoc * Enables a pick. Enabled picks update their pick results. * @function Picks.enablePick * @param {number} id - The ID of the pick. */ Q_INVOKABLE void enablePick(unsigned int uid); - /**jsdoc + /*@jsdoc * Disables a pick. Disabled picks do not update their pick results. * @function Picks.disablePick * @param {number} id - The ID of the pick. */ Q_INVOKABLE void disablePick(unsigned int uid); - /**jsdoc + /*@jsdoc * Get the enabled status of a pick. Enabled picks update their pick results. * @function Picks.isPickEnabled * @param {number} id - The ID of the pick. @@ -142,14 +142,14 @@ public: */ Q_INVOKABLE bool isPickEnabled(unsigned int uid) const; - /**jsdoc + /*@jsdoc * Removes (deletes) a pick. * @function Picks.removePick * @param {number} id - The ID of the pick. */ Q_INVOKABLE void removePick(unsigned int uid); - /**jsdoc + /*@jsdoc * Gets the current properties of the pick. * @function Picks.getPickProperties * @param {number} id - The ID of the pick. @@ -158,7 +158,7 @@ public: */ Q_INVOKABLE QVariantMap getPickProperties(unsigned int uid) const; - /**jsdoc + /*@jsdoc * Gets the parameters that were passed in to {@link Picks.createPick} to create the pick, if the pick was created through * a script. Note that these properties do not reflect the current state of the pick. * See {@link Picks.getPickProperties}. @@ -169,14 +169,14 @@ public: */ Q_INVOKABLE QVariantMap getPickScriptParameters(unsigned int uid) const; - /**jsdoc + /*@jsdoc * Gets all picks which currently exist, including disabled picks. * @function Picks.getPicks * @returns {number[]} picks - The IDs of the picks. */ Q_INVOKABLE QVector getPicks() const; - /**jsdoc + /*@jsdoc * Gets the most recent result from a pick. A pick continues to be updated ready to return a result, as long as it is * enabled. *

Note: Stylus picks only intersect with objects in their include list, set using @@ -228,7 +228,7 @@ public: */ Q_INVOKABLE QVariantMap getPrevPickResult(unsigned int uid); - /**jsdoc + /*@jsdoc * Sets whether or not a pick should use precision picking, i.e., whether it should pick against precise meshes or coarse * meshes. * This has the same effect as using the PICK_PRECISE or PICK_COARSE filter flags. @@ -238,7 +238,7 @@ public: */ Q_INVOKABLE void setPrecisionPicking(unsigned int uid, bool precisionPicking); - /**jsdoc + /*@jsdoc * Sets a list of entity and avatar IDs that a pick should ignore during intersection. *

Note: Not used by stylus picks.

* @function Picks.setIgnoreItems @@ -247,7 +247,7 @@ public: */ Q_INVOKABLE void setIgnoreItems(unsigned int uid, const QScriptValue& ignoreItems); - /**jsdoc + /*@jsdoc * Sets a list of entity and avatar IDs that a pick should include during intersection, instead of intersecting with * everything. *

Note: Stylus picks only intersect with items in their include list.

@@ -257,7 +257,7 @@ public: */ Q_INVOKABLE void setIncludeItems(unsigned int uid, const QScriptValue& includeItems); - /**jsdoc + /*@jsdoc * Checks if a pick is associated with the left hand: a ray or parabola pick with joint property set to * "_CONTROLLER_LEFTHAND" or "_CAMERA_RELATIVE_CONTROLLER_LEFTHAND", or a stylus pick with * hand property set to 0. @@ -267,7 +267,7 @@ public: */ Q_INVOKABLE bool isLeftHand(unsigned int uid); - /**jsdoc + /*@jsdoc * Checks if a pick is associated with the right hand: a ray or parabola pick with joint property set to * "_CONTROLLER_RIGHTHAND" or "_CAMERA_RELATIVE_CONTROLLER_RIGHTHAND", or a stylus pick with * hand property set to 1. @@ -277,7 +277,7 @@ public: */ Q_INVOKABLE bool isRightHand(unsigned int uid); - /**jsdoc + /*@jsdoc * Checks if a pick is associated with the system mouse: a ray or parabola pick with joint property set to * "Mouse". * @function Picks.isMouse @@ -293,7 +293,7 @@ public: public slots: - /**jsdoc + /*@jsdoc * @function Picks.PICK_ENTITIES * @deprecated This function is deprecated and will be removed. Use the Picks.PICK_DOMAIN_ENTITIES | * Picks.PICK_AVATAR_ENTITIES properties expression instead. @@ -301,7 +301,7 @@ public slots: */ static constexpr unsigned int PICK_ENTITIES() { return PickFilter::getBitMask(PickFilter::FlagBit::DOMAIN_ENTITIES) | PickFilter::getBitMask(PickFilter::FlagBit::AVATAR_ENTITIES); } - /**jsdoc + /*@jsdoc * @function Picks.PICK_OVERLAYS * @deprecated This function is deprecated and will be removed. Use the Picks.PICK_LOCAL_ENTITIES property * instead. @@ -310,7 +310,7 @@ public slots: static constexpr unsigned int PICK_OVERLAYS() { return PickFilter::getBitMask(PickFilter::FlagBit::LOCAL_ENTITIES); } - /**jsdoc + /*@jsdoc * @function Picks.PICK_DOMAIN_ENTITIES * @deprecated This function is deprecated and will be removed. Use the Picks.PICK_DOMAIN_ENTITIES property * instead. @@ -318,7 +318,7 @@ public slots: */ static constexpr unsigned int PICK_DOMAIN_ENTITIES() { return PickFilter::getBitMask(PickFilter::FlagBit::DOMAIN_ENTITIES); } - /**jsdoc + /*@jsdoc * @function Picks.PICK_AVATAR_ENTITIES * @deprecated This function is deprecated and will be removed. Use the Picks.PICK_AVATAR_ENTITIES property * instead. @@ -326,7 +326,7 @@ public slots: */ static constexpr unsigned int PICK_AVATAR_ENTITIES() { return PickFilter::getBitMask(PickFilter::FlagBit::AVATAR_ENTITIES); } - /**jsdoc + /*@jsdoc * @function Picks.PICK_LOCAL_ENTITIES * @deprecated This function is deprecated and will be removed. Use the Picks.PICK_LOCAL_ENTITIES property * instead. @@ -334,7 +334,7 @@ public slots: */ static constexpr unsigned int PICK_LOCAL_ENTITIES() { return PickFilter::getBitMask(PickFilter::FlagBit::LOCAL_ENTITIES); } - /**jsdoc + /*@jsdoc * @function Picks.PICK_AVATARS * @deprecated This function is deprecated and will be removed. Use the Picks.PICK_AVATARS property * instead. @@ -342,7 +342,7 @@ public slots: */ static constexpr unsigned int PICK_AVATARS() { return PickFilter::getBitMask(PickFilter::FlagBit::AVATARS); } - /**jsdoc + /*@jsdoc * @function Picks.PICK_HUD * @deprecated This function is deprecated and will be removed. Use the Picks.PICK_HUD property instead. * @returns {number} @@ -350,7 +350,7 @@ public slots: static constexpr unsigned int PICK_HUD() { return PickFilter::getBitMask(PickFilter::FlagBit::HUD); } - /**jsdoc + /*@jsdoc * @function Picks.PICK_INCLUDE_VISIBLE * @deprecated This function is deprecated and will be removed. Use the Picks.PICK_INCLUDE_VISIBLE property * instead. @@ -358,7 +358,7 @@ public slots: */ static constexpr unsigned int PICK_INCLUDE_VISIBLE() { return PickFilter::getBitMask(PickFilter::FlagBit::VISIBLE); } - /**jsdoc + /*@jsdoc * @function Picks.PICK_INCLUDE_INVISIBLE * @deprecated This function is deprecated and will be removed. Use the Picks.PICK_INCLUDE_INVISIBLE property * instead. @@ -367,7 +367,7 @@ public slots: static constexpr unsigned int PICK_INCLUDE_INVISIBLE() { return PickFilter::getBitMask(PickFilter::FlagBit::INVISIBLE); } - /**jsdoc + /*@jsdoc * @function Picks.PICK_INCLUDE_COLLIDABLE * @deprecated This function is deprecated and will be removed. Use the Picks.PICK_INCLUDE_COLLIDABLE property * instead. @@ -375,7 +375,7 @@ public slots: */ static constexpr unsigned int PICK_INCLUDE_COLLIDABLE() { return PickFilter::getBitMask(PickFilter::FlagBit::COLLIDABLE); } - /**jsdoc + /*@jsdoc * @function Picks.PICK_INCLUDE_NONCOLLIDABLE * @deprecated This function is deprecated and will be removed. Use the Picks.PICK_INCLUDE_NONCOLLIDABLE * property instead. @@ -384,14 +384,14 @@ public slots: static constexpr unsigned int PICK_INCLUDE_NONCOLLIDABLE() { return PickFilter::getBitMask(PickFilter::FlagBit::NONCOLLIDABLE); } - /**jsdoc + /*@jsdoc * @function Picks.PICK_PRECISE * @deprecated This function is deprecated and will be removed. Use the Picks.PICK_PRECISE property instead. * @returns {number} */ static constexpr unsigned int PICK_PRECISE() { return PickFilter::getBitMask(PickFilter::FlagBit::PRECISE); } - /**jsdoc + /*@jsdoc * @function Picks.PICK_COARSE * @deprecated This function is deprecated and will be removed. Use the Picks.PICK_COARSE property instead. * @returns {number} @@ -399,7 +399,7 @@ public slots: static constexpr unsigned int PICK_COARSE() { return PickFilter::getBitMask(PickFilter::FlagBit::COARSE); } - /**jsdoc + /*@jsdoc * @function Picks.PICK_ALL_INTERSECTIONS * @deprecated This function is deprecated and will be removed. Use the Picks.PICK_ALL_INTERSECTIONS property * instead. @@ -407,7 +407,7 @@ public slots: */ static constexpr unsigned int PICK_ALL_INTERSECTIONS() { return PickFilter::getBitMask(PickFilter::FlagBit::PICK_ALL_INTERSECTIONS); } - /**jsdoc + /*@jsdoc * @function Picks.INTERSECTED_NONE * @deprecated This function is deprecated and will be removed. Use the Picks.INTERSECTED_NONE property * instead. @@ -415,7 +415,7 @@ public slots: */ static constexpr unsigned int INTERSECTED_NONE() { return IntersectionType::NONE; } - /**jsdoc + /*@jsdoc * @function Picks.INTERSECTED_ENTITY * @deprecated This function is deprecated and will be removed. Use the Picks.INTERSECTED_ENTITY property * instead. @@ -423,7 +423,7 @@ public slots: */ static constexpr unsigned int INTERSECTED_ENTITY() { return IntersectionType::ENTITY; } - /**jsdoc + /*@jsdoc * @function Picks.INTERSECTED_LOCAL_ENTITY * @deprecated This function is deprecated and will be removed. Use the Picks.INTERSECTED_LOCAL_ENTITY * property instead. @@ -431,7 +431,7 @@ public slots: */ static constexpr unsigned int INTERSECTED_LOCAL_ENTITY() { return IntersectionType::LOCAL_ENTITY; } - /**jsdoc + /*@jsdoc * @function Picks.INTERSECTED_OVERLAY * @deprecated This function is deprecated and will be removed. Use the Picks.INTERSECTED_LOCAL_ENTITY * property instead. @@ -439,7 +439,7 @@ public slots: */ static constexpr unsigned int INTERSECTED_OVERLAY() { return INTERSECTED_LOCAL_ENTITY(); } - /**jsdoc + /*@jsdoc * @function Picks.INTERSECTED_AVATAR * @deprecated This function is deprecated and will be removed. Use the Picks.INTERSECTED_AVATAR property * instead. @@ -447,7 +447,7 @@ public slots: */ static constexpr unsigned int INTERSECTED_AVATAR() { return IntersectionType::AVATAR; } - /**jsdoc + /*@jsdoc * @function Picks.INTERSECTED_HUD * @deprecated This function is deprecated and will be removed. Use the Picks.INTERSECTED_HUD property * instead. diff --git a/interface/src/raypick/PointerScriptingInterface.cpp b/interface/src/raypick/PointerScriptingInterface.cpp index a3aeb314e5..0b4c399d3b 100644 --- a/interface/src/raypick/PointerScriptingInterface.cpp +++ b/interface/src/raypick/PointerScriptingInterface.cpp @@ -83,7 +83,7 @@ QVariantMap PointerScriptingInterface::getPointerScriptParameters(unsigned int u return DependencyManager::get()->getPointerScriptParameters(uid); } -/**jsdoc +/*@jsdoc * The properties of a stylus pointer. These include the properties from the underlying stylus pick that the pointer uses. * @typedef {object} Pointers.StylusPointerProperties * @property {Pointers.StylusPointerModel} [model] - Override some or all of the default stylus model properties. @@ -96,7 +96,7 @@ QVariantMap PointerScriptingInterface::getPointerScriptParameters(unsigned int u * @see {@link Picks.StylusPickProperties} for additional properties from the underlying stylus pick. */ -/**jsdoc +/*@jsdoc * The properties of a stylus pointer model. * @typedef {object} Pointers.StylusPointerModel * @property {string} [url] - The url of a model to use for the stylus, to override the default stylus mode. @@ -141,14 +141,14 @@ std::shared_ptr PointerScriptingInterface::buildStylus(const QVariant& return std::make_shared(properties, StylusPointer::buildStylus(propertyMap), hover, enabled, modelPositionOffset, modelRotationOffset, modelDimensions); } -/**jsdoc +/*@jsdoc * Properties that define the visual appearance of a ray pointer when the pointer is not intersecting something. These are the * properties of {@link Pointers.RayPointerRenderState} but with an additional property. * @typedef {object} Pointers.DefaultRayPointerRenderState * @property {number} distance - The distance at which to render the end of the ray pointer. * @see {@link Pointers.RayPointerRenderState} for the remainder of the properties. */ -/**jsdoc +/*@jsdoc * Properties that define the visual appearance of a ray pointer when the pointer is intersecting something. * @typedef {object} Pointers.RayPointerRenderState * @property {string} name - When creating using {@link Pointers.createPointer}, the name of the render state. @@ -171,7 +171,7 @@ std::shared_ptr PointerScriptingInterface::buildStylus(const QVariant& *

When getting using {@link Pointers.getPointerProperties}, the ID of the overlay rendered at the end of the ray; * null if there is no overlay. */ -/**jsdoc +/*@jsdoc * The properties of a ray pointer. These include the properties from the underlying ray pick that the pointer uses. * @typedef {object} Pointers.RayPointerProperties * @property {boolean} [faceAvatar=false] - true if the overlay rendered at the end of the ray rotates about the @@ -329,7 +329,7 @@ std::shared_ptr PointerScriptingInterface::buildLaserPointer(const QVar distanceScaleEnd, scaleWithParent, enabled); } -/**jsdoc +/*@jsdoc * The visual appearance of the parabolic path. * @typedef {object} Pointers.ParabolaPointerPath * @property {Color} [color=255,255,255] - The color of the parabola. @@ -340,14 +340,14 @@ std::shared_ptr PointerScriptingInterface::buildLaserPointer(const QVar * @property {boolean} [drawInFront=false] - true if the parabola is rendered in front of objects in the world, * but behind the HUD, false if it is occluded by objects in front of it. */ -/**jsdoc +/*@jsdoc * Properties that define the visual appearance of a parabola pointer when the pointer is not intersecting something. These are * properties of {@link Pointers.ParabolaPointerRenderState} but with an additional property. * @typedef {object} Pointers.DefaultParabolaPointerRenderState * @property {number} distance - The distance along the parabola at which to render the end of the parabola pointer. * @see {@link Pointers.ParabolaPointerRenderState} for the remainder of the properties. */ -/**jsdoc +/*@jsdoc * Properties that define the visual appearance of a parabola pointer when the pointer is intersecting something. * @typedef {object} Pointers.ParabolaPointerRenderState * @property {string} name - When creating using {@link Pointers.createPointer}, the name of the render state. @@ -366,7 +366,7 @@ std::shared_ptr PointerScriptingInterface::buildLaserPointer(const QVar *

When getting using {@link Pointers.getPointerProperties}, the ID of the overlay rendered at the end of the parabola; * null if there is no overlay. */ -/**jsdoc +/*@jsdoc * The properties of a parabola pointer. These include the properties from the underlying parabola pick that the pointer uses. * @typedef {object} Pointers.ParabolaPointerProperties * @property {boolean} [faceAvatar=false] - true if the overlay rendered at the end of the ray rotates about the diff --git a/interface/src/raypick/PointerScriptingInterface.h b/interface/src/raypick/PointerScriptingInterface.h index 555136e7a7..58439f221d 100644 --- a/interface/src/raypick/PointerScriptingInterface.h +++ b/interface/src/raypick/PointerScriptingInterface.h @@ -15,7 +15,7 @@ #include #include -/**jsdoc +/*@jsdoc * The Pointers API lets you create, manage, and visually represent objects for repeatedly calculating * intersections with avatars, entities, and overlays. Pointers can also be configured to generate events on entities and * overlays intersected. @@ -33,7 +33,7 @@ class PointerScriptingInterface : public QObject, public Dependency { public: - /**jsdoc + /*@jsdoc * Specifies that a {@link Controller} action or function should trigger events on the entity or overlay currently * intersected by a {@link Pointers.RayPointerProperties|Ray} or {@link Pointers.ParabolaPointerProperties|Parabola} * pointer. @@ -50,7 +50,7 @@ public: * */ - /**jsdoc + /*@jsdoc * Creates a new ray, parabola, or stylus pointer. The pointer can have a wide range of behaviors depending on the * properties specified. For example, a ray pointer may be a static ray pointer, a mouse ray pointer, or joint ray * pointer. @@ -131,21 +131,21 @@ public: // TODO: expand Pointers to be able to be fully configurable with PickFilters Q_INVOKABLE unsigned int createPointer(const PickQuery::PickType& type, const QVariant& properties); - /**jsdoc + /*@jsdoc * Enables and shows a pointer. Enabled pointers update their pick results and generate events. * @function Pointers.enablePointer * @param {number} id - The ID of the pointer. */ Q_INVOKABLE void enablePointer(unsigned int uid) const { DependencyManager::get()->enablePointer(uid); } - /**jsdoc + /*@jsdoc * Disables and hides a pointer. Disabled pointers do not update their pick results or generate events. * @function Pointers.disablePointer * @param {number} id - The ID of the pointer. */ Q_INVOKABLE void disablePointer(unsigned int uid) const { DependencyManager::get()->disablePointer(uid); } - /**jsdoc + /*@jsdoc * Gets the enabled status of a pointer. Enabled pointers update their pick results and generate events. * @function Pointers.isPointerEnabled * @param {number} id - The ID of the pointer. @@ -153,14 +153,14 @@ public: */ Q_INVOKABLE bool isPointerEnabled(unsigned int uid) const; - /**jsdoc + /*@jsdoc * Removes (deletes) a pointer. * @function Pointers.removePointer * @param {number} id - The ID of the pointer. */ Q_INVOKABLE void removePointer(unsigned int uid) const { DependencyManager::get()->removePointer(uid); } - /**jsdoc + /*@jsdoc * Gets the parameters that were passed in to {@link Pointers.createPointer} to create the pointer when the pointer was * created through a script. *

Note: These properties do not reflect the current state of the pointer. To get the current state @@ -172,14 +172,14 @@ public: */ Q_INVOKABLE QVariantMap getPointerScriptParameters(unsigned int uid) const; - /**jsdoc + /*@jsdoc * Gets all pointers which currently exist, including disabled pointers. * @function Pointers.getPointers * @returns {number[]} pointers - The IDs of the pointers. */ Q_INVOKABLE QVector getPointers() const; - /**jsdoc + /*@jsdoc * Edits a render state of a {@link Pointers.RayPointerProperties|ray} or * {@link Pointers.ParabolaPointerProperties|parabola} pointer, to change its visual appearance for the state when the * pointer is intersecting something. @@ -251,7 +251,7 @@ public: */ Q_INVOKABLE void editRenderState(unsigned int uid, const QString& renderState, const QVariant& properties) const; - /**jsdoc + /*@jsdoc * Sets the render state of a pointer, to change its visual appearance and possibly disable or enable it. * @function Pointers.setRenderState * @param {number} id - The ID of the pointer. @@ -330,7 +330,7 @@ public: Q_INVOKABLE void setRenderState(unsigned int uid, const QString& renderState) const { DependencyManager::get()->setRenderState(uid, renderState.toStdString()); } - /**jsdoc + /*@jsdoc * Gets the most recent intersection of a pointer. A pointer continues to be updated ready to return a result, as long as * it is enabled, regardless of the render state. * @function Pointers.getPrevPickResult @@ -340,7 +340,7 @@ public: Q_INVOKABLE QVariantMap getPrevPickResult(unsigned int uid) const; - /**jsdoc + /*@jsdoc * Sets whether or not a pointer should use precision picking, i.e., whether it should pick against precise meshes or * coarse meshes. This has the same effect as using the PICK_PRECISE or PICK_COARSE filter flags. * @function Pointers.setPrecisionPicking @@ -349,7 +349,7 @@ public: */ Q_INVOKABLE void setPrecisionPicking(unsigned int uid, bool precisionPicking) const { DependencyManager::get()->setPrecisionPicking(uid, precisionPicking); } - /**jsdoc + /*@jsdoc * Sets the length of a pointer. *

Note: Not used by stylus pointers.

* @function Pointers.setLength @@ -358,7 +358,7 @@ public: */ Q_INVOKABLE void setLength(unsigned int uid, float length) const { DependencyManager::get()->setLength(uid, length); } - /**jsdoc + /*@jsdoc * Sets a list of entity and avatar IDs that a pointer should ignore during intersection. *

Note: Not used by stylus pointers.

* @function Pointers.setIgnoreItems @@ -367,7 +367,7 @@ public: */ Q_INVOKABLE void setIgnoreItems(unsigned int uid, const QScriptValue& ignoreEntities) const; - /**jsdoc + /*@jsdoc * Sets a list of entity and avatar IDs that a pointer should include during intersection, instead of intersecting with * everything. *

Note: Stylus pointers only intersect with items in their include list.

@@ -378,7 +378,7 @@ public: Q_INVOKABLE void setIncludeItems(unsigned int uid, const QScriptValue& includeEntities) const; - /**jsdoc + /*@jsdoc * Locks a pointer onto a specific entity or avatar. *

Note: Not used by stylus pointers.

* @function Pointers.setLockEndUUID @@ -391,7 +391,7 @@ public: Q_INVOKABLE void setLockEndUUID(unsigned int uid, const QUuid& objectID, bool isAvatar, const glm::mat4& offsetMat = glm::mat4()) const { DependencyManager::get()->setLockEndUUID(uid, objectID, isAvatar, offsetMat); } - /**jsdoc + /*@jsdoc * Checks if a pointer is associated with the left hand: a ray or parabola pointer with joint property set to * "_CONTROLLER_LEFTHAND" or "_CAMERA_RELATIVE_CONTROLLER_LEFTHAND", or a stylus pointer with * hand property set to 0. @@ -401,7 +401,7 @@ public: */ Q_INVOKABLE bool isLeftHand(unsigned int uid) { return DependencyManager::get()->isLeftHand(uid); } - /**jsdoc + /*@jsdoc * Checks if a pointer is associated with the right hand: a ray or parabola pointer with joint property set to * "_CONTROLLER_RIGHTHAND" or "_CAMERA_RELATIVE_CONTROLLER_RIGHTHAND", or a stylus pointer with * hand property set to 1. @@ -411,7 +411,7 @@ public: */ Q_INVOKABLE bool isRightHand(unsigned int uid) { return DependencyManager::get()->isRightHand(uid); } - /**jsdoc + /*@jsdoc * Checks if a pointer is associated with the system mouse: a ray or parabola pointer with joint property set * to "Mouse". * @function Pointers.isMouse @@ -420,7 +420,7 @@ public: */ Q_INVOKABLE bool isMouse(unsigned int uid) { return DependencyManager::get()->isMouse(uid); } - /**jsdoc + /*@jsdoc * Gets information about a pointer. * @function Pointers.getPointerProperties * @param {number} id - The ID of the pointer. diff --git a/interface/src/raypick/RayPick.h b/interface/src/raypick/RayPick.h index 3bd82f4194..d5e604c4df 100644 --- a/interface/src/raypick/RayPick.h +++ b/interface/src/raypick/RayPick.h @@ -39,7 +39,7 @@ public: float distance { FLT_MAX }; bool intersects { false }; - /**jsdoc + /*@jsdoc * An intersection result for a ray pick. * * @typedef {object} RayPickResult diff --git a/interface/src/raypick/RayPickScriptingInterface.h b/interface/src/raypick/RayPickScriptingInterface.h index 204407e92d..0aed9e4bdf 100644 --- a/interface/src/raypick/RayPickScriptingInterface.h +++ b/interface/src/raypick/RayPickScriptingInterface.h @@ -18,7 +18,7 @@ #include "PickScriptingInterface.h" -/**jsdoc +/*@jsdoc * The RayPick API is a subset of the {@link Picks} API, as used for ray picks. * * @namespace RayPick @@ -65,7 +65,7 @@ class RayPickScriptingInterface : public QObject, public Dependency { public: - /**jsdoc + /*@jsdoc * Creates a new ray pick. *

Warning: Picks created using this method currently always intersect at least visible and collidable * things but this may not always be the case.

@@ -75,28 +75,28 @@ public: */ Q_INVOKABLE unsigned int createRayPick(const QVariant& properties); - /**jsdoc + /*@jsdoc * Enables a ray pick. * @function RayPick.enableRayPick * @param {number} id - The ID of the ray pick. */ Q_INVOKABLE void enableRayPick(unsigned int uid); - /**jsdoc + /*@jsdoc * Disables a ray pick. * @function RayPick.disableRayPick * @param {number} id - The ID of the ray pick. */ Q_INVOKABLE void disableRayPick(unsigned int uid); - /**jsdoc + /*@jsdoc * Removes (deletes) a ray pick. * @function RayPick.removeRayPick * @param {number} id - The ID of the ray pick. */ Q_INVOKABLE void removeRayPick(unsigned int uid); - /**jsdoc + /*@jsdoc * Gets the most recent pick result from a ray pick. A ray pick continues to be updated ready to return a result, as long * as it is enabled. * @function RayPick.getPrevRayPickResult @@ -106,7 +106,7 @@ public: Q_INVOKABLE QVariantMap getPrevRayPickResult(unsigned int uid); - /**jsdoc + /*@jsdoc * Sets whether or not a ray pick should use precision picking, i.e., whether it should pick against precise meshes or * coarse meshes. * @function RayPick.setPrecisionPicking @@ -115,7 +115,7 @@ public: */ Q_INVOKABLE void setPrecisionPicking(unsigned int uid, bool precisionPicking); - /**jsdoc + /*@jsdoc * Sets a list of entity and avatar IDs that a ray pick should ignore during intersection. * @function RayPick.setIgnoreItems * @param {number} id - The ID of the ray pick. @@ -123,7 +123,7 @@ public: */ Q_INVOKABLE void setIgnoreItems(unsigned int uid, const QScriptValue& ignoreEntities); - /**jsdoc + /*@jsdoc * Sets a list of entity and avatar IDs that a ray pick should include during intersection, instead of intersecting with * everything. * @function RayPick.setIncludeItems @@ -133,7 +133,7 @@ public: Q_INVOKABLE void setIncludeItems(unsigned int uid, const QScriptValue& includeEntities); - /**jsdoc + /*@jsdoc * Checks if a pick is associated with the left hand: a ray or parabola pick with joint property set to * "_CONTROLLER_LEFTHAND" or "_CAMERA_RELATIVE_CONTROLLER_LEFTHAND", or a stylus pick with * hand property set to 0. @@ -143,7 +143,7 @@ public: */ Q_INVOKABLE bool isLeftHand(unsigned int uid); - /**jsdoc + /*@jsdoc * Checks if a pick is associated with the right hand: a ray or parabola pick with joint property set to * "_CONTROLLER_RIGHTHAND" or "_CAMERA_RELATIVE_CONTROLLER_RIGHTHAND", or a stylus pick with * hand property set to 1. @@ -153,7 +153,7 @@ public: */ Q_INVOKABLE bool isRightHand(unsigned int uid); - /**jsdoc + /*@jsdoc * Checks if a pick is associated with the system mouse: a ray or parabola pick with joint property set to * "Mouse". * @function RayPick.isMouse @@ -164,42 +164,42 @@ public: public slots: - /**jsdoc + /*@jsdoc * @function RayPick.PICK_ENTITIES * @deprecated This function is deprecated and will be removed. Use the Raypick.PICK_ENTITIES property instead. * @returns {number} */ static unsigned int PICK_ENTITIES() { return PickScriptingInterface::PICK_ENTITIES(); } - /**jsdoc + /*@jsdoc * @function RayPick.PICK_OVERLAYS * @deprecated This function is deprecated and will be removed. Use the RayPick.PICK_OVERLAYS property instead. * @returns {number} */ static unsigned int PICK_OVERLAYS() { return PickScriptingInterface::PICK_OVERLAYS(); } - /**jsdoc + /*@jsdoc * @function RayPick.PICK_AVATARS * @deprecated This function is deprecated and will be removed. Use the RayPick.PICK_AVATARS property instead. * @returns {number} */ static unsigned int PICK_AVATARS() { return PickScriptingInterface::PICK_AVATARS(); } - /**jsdoc + /*@jsdoc * @function RayPick.PICK_HUD * @deprecated This function is deprecated and will be removed. Use the RayPick.PICK_HUD property instead. * @returns {number} */ static unsigned int PICK_HUD() { return PickScriptingInterface::PICK_HUD(); } - /**jsdoc + /*@jsdoc * @function RayPick.PICK_COARSE * @deprecated This function is deprecated and will be removed. Use the RayPick.PICK_COARSE property instead. * @returns {number} */ static unsigned int PICK_COARSE() { return PickScriptingInterface::PICK_COARSE(); } - /**jsdoc + /*@jsdoc * @function RayPick.PICK_INCLUDE_INVISIBLE * @deprecated This function is deprecated and will be removed. Use the RayPick.PICK_INCLUDE_INVISIBLE * property instead. @@ -207,7 +207,7 @@ public slots: */ static unsigned int PICK_INCLUDE_INVISIBLE() { return PickScriptingInterface::PICK_INCLUDE_INVISIBLE(); } - /**jsdoc + /*@jsdoc * @function RayPick.PICK_INCLUDE_NONCOLLIDABLE * @deprecated This function is deprecated and will be removed. Use the RayPick.PICK_INCLUDE_NONCOLLIDABLE * property instead. @@ -215,7 +215,7 @@ public slots: */ static unsigned int PICK_INCLUDE_NONCOLLIDABLE() { return PickScriptingInterface::PICK_INCLUDE_NONCOLLIDABLE(); } - /**jsdoc + /*@jsdoc * @function RayPick.PICK_ALL_INTERSECTIONS * @deprecated This function is deprecated and will be removed. Use the RayPick.PICK_ALL_INTERSECTIONS * property instead. @@ -223,7 +223,7 @@ public slots: */ static unsigned int PICK_ALL_INTERSECTIONS() { return PickScriptingInterface::PICK_ALL_INTERSECTIONS(); } - /**jsdoc + /*@jsdoc * @function RayPick.INTERSECTED_NONE * @deprecated This function is deprecated and will be removed. Use the RayPick.INTERSECTED_NONE property * instead. @@ -231,7 +231,7 @@ public slots: */ static unsigned int INTERSECTED_NONE() { return PickScriptingInterface::INTERSECTED_NONE(); } - /**jsdoc + /*@jsdoc * @function RayPick.INTERSECTED_ENTITY * @deprecated This function is deprecated and will be removed. Use the RayPick.INTERSECTED_ENTITY property * instead. @@ -239,7 +239,7 @@ public slots: */ static unsigned int INTERSECTED_ENTITY() { return PickScriptingInterface::INTERSECTED_ENTITY(); } - /**jsdoc + /*@jsdoc * @function RayPick.INTERSECTED_OVERLAY * @deprecated This function is deprecated and will be removed. Use the RayPick.INTERSECTED_LOCAL_ENTITY * property instead. @@ -247,7 +247,7 @@ public slots: */ static unsigned int INTERSECTED_LOCAL_ENTITY() { return PickScriptingInterface::INTERSECTED_LOCAL_ENTITY(); } - /**jsdoc + /*@jsdoc * @function RayPick.INTERSECTED_OVERLAY * @deprecated This function is deprecated and will be removed. Use the RayPick.INTERSECTED_OVERLAY property * instead. @@ -255,7 +255,7 @@ public slots: */ static unsigned int INTERSECTED_OVERLAY() { return PickScriptingInterface::INTERSECTED_LOCAL_ENTITY(); } - /**jsdoc + /*@jsdoc * @function RayPick.INTERSECTED_AVATAR * @deprecated This function is deprecated and will be removed. Use the RayPick.INTERSECTED_AVATAR property * instead. @@ -263,7 +263,7 @@ public slots: */ static unsigned int INTERSECTED_AVATAR() { return PickScriptingInterface::INTERSECTED_AVATAR(); } - /**jsdoc + /*@jsdoc * @function RayPick.INTERSECTED_HUD * @deprecated This function is deprecated and will be removed. Use the RayPick.INTERSECTED_HUD property * instead. diff --git a/interface/src/raypick/StylusPick.h b/interface/src/raypick/StylusPick.h index 89444149d8..fa9ed90a1c 100644 --- a/interface/src/raypick/StylusPick.h +++ b/interface/src/raypick/StylusPick.h @@ -40,7 +40,7 @@ public: glm::vec3 intersection { NAN }; glm::vec3 surfaceNormal { NAN }; - /**jsdoc + /*@jsdoc * An intersection result for a stylus pick. * * @typedef {object} StylusPickResult diff --git a/interface/src/scripting/AccountServicesScriptingInterface.cpp b/interface/src/scripting/AccountServicesScriptingInterface.cpp index 5f8fb065ff..34f33903e2 100644 --- a/interface/src/scripting/AccountServicesScriptingInterface.cpp +++ b/interface/src/scripting/AccountServicesScriptingInterface.cpp @@ -112,7 +112,7 @@ DownloadInfoResult::DownloadInfoResult() : { } -/**jsdoc +/*@jsdoc * Information on the assets currently being downloaded and pending download. * @typedef {object} AccountServices.DownloadInfoResult * @property {number[]} downloading - The download percentage remaining of each asset currently downloading. diff --git a/interface/src/scripting/AccountServicesScriptingInterface.h b/interface/src/scripting/AccountServicesScriptingInterface.h index 288137e166..00c17db380 100644 --- a/interface/src/scripting/AccountServicesScriptingInterface.h +++ b/interface/src/scripting/AccountServicesScriptingInterface.h @@ -37,7 +37,7 @@ void DownloadInfoResultFromScriptValue(const QScriptValue& object, DownloadInfoR class AccountServicesScriptingInterface : public QObject { Q_OBJECT - /**jsdoc + /*@jsdoc * The AccountServices API provides functions that give information on user connectivity, visibility, and * asset download progress. * @@ -62,7 +62,7 @@ class AccountServicesScriptingInterface : public QObject { * — typically "https://metaverse.highfidelity.com". Read-only. */ - /**jsdoc + /*@jsdoc * The Account API provides functions that give information on user connectivity, visibility, and asset * download progress. * @@ -102,7 +102,7 @@ class AccountServicesScriptingInterface : public QObject { * @borrows AccountServices.loggedInChanged as loggedInChanged */ - /**jsdoc + /*@jsdoc * The GlobalServices API provides functions that give information on user connectivity, visibility, and asset * download progress. * @@ -156,21 +156,21 @@ public: public slots: - /**jsdoc + /*@jsdoc * Gets information on the download progress of assets in the domain. * @function AccountServices.getDownloadInfo * @returns {AccountServices.DownloadInfoResult} Information on the download progress of assets. */ DownloadInfoResult getDownloadInfo(); - /**jsdoc + /*@jsdoc * Triggers a {@link AccountServices.downloadInfoChanged|downloadInfoChanged} signal with information on the current * download progress of the assets in the domain. * @function AccountServices.updateDownloadInfo */ void updateDownloadInfo(); - /**jsdoc + /*@jsdoc * Checks whether the user is logged in. * @function AccountServices.isLoggedIn * @returns {boolean} true if the user is logged in, false if not. @@ -180,14 +180,14 @@ public slots: */ bool isLoggedIn(); - /**jsdoc + /*@jsdoc * The function returns the login status of the user and prompts the user to log in (with a login dialog) if they're not already logged in. * @function AccountServices.checkAndSignalForAccessToken * @returns {boolean} true if the user is logged in, false if not. */ bool checkAndSignalForAccessToken(); - /**jsdoc + /*@jsdoc * Logs the user out. * @function AccountServices.logOut */ @@ -205,14 +205,14 @@ private slots: signals: - /**jsdoc + /*@jsdoc * Not currently used. * @function AccountServices.connected * @returns {Signal} */ void connected(); - /**jsdoc + /*@jsdoc * Triggered when the user logs out. * @function AccountServices.disconnected * @param {string} reason - Has the value, "logout". @@ -220,7 +220,7 @@ signals: */ void disconnected(const QString& reason); - /**jsdoc + /*@jsdoc * Triggered when the username logged in with changes, i.e., when the user logs in or out. * @function AccountServices.myUsernameChanged * @param {string} username - The user name of the user logged in. If there is no user logged in, it is "". @@ -232,7 +232,7 @@ signals: */ void myUsernameChanged(const QString& username); - /**jsdoc + /*@jsdoc * Triggered when the download progress of the assets in the domain changes. * @function AccountServices.downloadInfoChanged * @param {AccountServices.DownloadInfoResult} downloadInfo - Information on the download progress of assets. @@ -240,7 +240,7 @@ signals: */ void downloadInfoChanged(DownloadInfoResult info); - /**jsdoc + /*@jsdoc * Triggered when the user's visibility to others changes. * @function AccountServices.findableByChanged * @param {string} findableBy - The user's visibility to other people: @@ -268,7 +268,7 @@ signals: */ void findableByChanged(const QString& discoverabilityMode); - /**jsdoc + /*@jsdoc * Triggered when the login status of the user changes. * @function AccountServices.loggedInChanged * @param {boolean} loggedIn - true if the user is logged in, false if not. diff --git a/interface/src/scripting/Audio.cpp b/interface/src/scripting/Audio.cpp index 43958188e3..4a96e36939 100644 --- a/interface/src/scripting/Audio.cpp +++ b/interface/src/scripting/Audio.cpp @@ -25,6 +25,8 @@ QString Audio::DESKTOP { "Desktop" }; QString Audio::HMD { "VR" }; Setting::Handle enableNoiseReductionSetting { QStringList { Audio::AUDIO, "NoiseReduction" }, true }; +Setting::Handle enableNoiseReductionAutomaticSetting { QStringList { Audio::AUDIO, "NoiseReductionAutomatic" }, true }; +Setting::Handle setNoiseReductionThresholdSetting { QStringList { Audio::AUDIO, "NoiseReductionThreshold" }, 0.1f }; Setting::Handle enableWarnWhenMutedSetting { QStringList { Audio::AUDIO, "WarnWhenMuted" }, true }; Setting::Handle enableAcousticEchoCancellationSetting { QStringList { Audio::AUDIO, "AcousticEchoCancellation" }, true }; @@ -40,6 +42,8 @@ Audio::Audio() : _devices(_contextIsHMD) { auto client = DependencyManager::get().data(); connect(client, &AudioClient::muteToggled, this, &Audio::setMuted); connect(client, &AudioClient::noiseReductionChanged, this, &Audio::enableNoiseReduction); + connect(client, &AudioClient::noiseReductionAutomaticChanged, this, &Audio::enableNoiseReductionAutomatic); + connect(client, &AudioClient::noiseReductionThresholdChanged, this, &Audio::setNoiseReductionThreshold); connect(client, &AudioClient::warnWhenMutedChanged, this, &Audio::enableWarnWhenMuted); connect(client, &AudioClient::acousticEchoCancellationChanged, this, &Audio::enableAcousticEchoCancellation); connect(client, &AudioClient::inputLoudnessChanged, this, &Audio::onInputLoudnessChanged); @@ -47,6 +51,8 @@ Audio::Audio() : _devices(_contextIsHMD) { connect(this, &Audio::contextChanged, &_devices, &AudioDevices::onContextChanged); connect(this, &Audio::pushingToTalkChanged, this, &Audio::handlePushedToTalk); enableNoiseReduction(enableNoiseReductionSetting.get()); + enableNoiseReductionAutomatic(enableNoiseReductionAutomaticSetting.get()); + setNoiseReductionThreshold(setNoiseReductionThresholdSetting.get()); enableWarnWhenMuted(enableWarnWhenMutedSetting.get()); enableAcousticEchoCancellation(enableAcousticEchoCancellationSetting.get()); onContextChanged(); @@ -286,6 +292,50 @@ void Audio::enableNoiseReduction(bool enable) { } } +bool Audio::noiseReductionAutomatic() const { + return resultWithReadLock([&] { + return _noiseReductionAutomatic; + }); +} + +void Audio::enableNoiseReductionAutomatic(bool enable) { + bool changed = false; + withWriteLock([&] { + if (_noiseReductionAutomatic != enable) { + _noiseReductionAutomatic = enable; + auto client = DependencyManager::get().data(); + QMetaObject::invokeMethod(client, "setNoiseReductionAutomatic", Q_ARG(bool, enable), Q_ARG(bool, false)); + enableNoiseReductionAutomaticSetting.set(enable); + changed = true; + } + }); + if (changed) { + emit noiseReductionAutomaticChanged(enable); + } +} + +float Audio::getNoiseReductionThreshold() { + return resultWithReadLock([&] { + return _noiseReductionThreshold; + }); +} + +void Audio::setNoiseReductionThreshold(float threshold) { + bool changed = false; + withWriteLock([&] { + if (_noiseReductionThreshold != threshold) { + _noiseReductionThreshold = threshold; + auto client = DependencyManager::get().data(); + QMetaObject::invokeMethod(client, "setNoiseReductionThreshold", Q_ARG(float, threshold), Q_ARG(bool, false)); + setNoiseReductionThresholdSetting.set(threshold); + changed = true; + } + }); + if (changed) { + emit noiseReductionThresholdChanged(threshold); + } +} + bool Audio::warnWhenMutedEnabled() const { return resultWithReadLock([&] { return _enableWarnWhenMuted; diff --git a/interface/src/scripting/Audio.h b/interface/src/scripting/Audio.h index 74d85f0107..bb8a92aa73 100644 --- a/interface/src/scripting/Audio.h +++ b/interface/src/scripting/Audio.h @@ -30,7 +30,7 @@ class Audio : public AudioScriptingInterface, protected ReadWriteLockable { Q_OBJECT SINGLETON_DEPENDENCY - /**jsdoc + /*@jsdoc * The Audio API provides facilities to interact with audio inputs and outputs and to play sounds. * * @namespace Audio @@ -50,6 +50,11 @@ class Audio : public AudioScriptingInterface, protected ReadWriteLockable { * @property {boolean} noiseReduction - true if noise reduction is enabled, otherwise false. When * enabled, the input audio signal is blocked (fully attenuated) when it falls below an adaptive threshold set just * above the noise floor. + * @property {boolean} noiseReductionAutomatic - true if audio input noise reduction automatic mode is enabled, + * false if in manual mode. Manual mode allows you to use Audio.noiseReductionThreshold + * to set a manual sensitivity for the noise gate. + * @property {number} noiseReductionThreshold - Sets the noise gate threshold before your mic audio is transmitted. + * (Applies only if Audio.noiseReductionAutomatic is false.) * @property {number} inputVolume - Adjusts the volume of the input audio, range 0.01.0. * If set to a value, the resulting value depends on the input device: for example, the volume can't be changed on some * devices, and others might only support values of 0.0 and 1.0. @@ -92,6 +97,8 @@ class Audio : public AudioScriptingInterface, protected ReadWriteLockable { Q_PROPERTY(bool muted READ isMuted WRITE setMuted NOTIFY mutedChanged) Q_PROPERTY(bool noiseReduction READ noiseReductionEnabled WRITE enableNoiseReduction NOTIFY noiseReductionChanged) + Q_PROPERTY(bool noiseReductionAutomatic READ noiseReductionAutomatic WRITE enableNoiseReductionAutomatic NOTIFY noiseReductionAutomaticChanged) + Q_PROPERTY(float noiseReductionThreshold READ getNoiseReductionThreshold WRITE setNoiseReductionThreshold NOTIFY noiseReductionThresholdChanged) Q_PROPERTY(bool warnWhenMuted READ warnWhenMutedEnabled WRITE enableWarnWhenMuted NOTIFY warnWhenMutedChanged) Q_PROPERTY(bool acousticEchoCancellation READ acousticEchoCancellationEnabled WRITE enableAcousticEchoCancellation NOTIFY acousticEchoCancellationChanged) @@ -124,6 +131,7 @@ public: bool isMuted() const; bool noiseReductionEnabled() const; + bool noiseReductionAutomatic() const; bool warnWhenMutedEnabled() const; bool acousticEchoCancellationEnabled() const; float getInputVolume() const; @@ -153,7 +161,7 @@ public: void saveData(); void loadData(); - /**jsdoc + /*@jsdoc * @function Audio.setInputDevice * @param {object} device - Device. * @param {boolean} isHMD - Is HMD. @@ -161,7 +169,7 @@ public: */ Q_INVOKABLE void setInputDevice(const HifiAudioDeviceInfo& device, bool isHMD); - /**jsdoc + /*@jsdoc * @function Audio.setOutputDevice * @param {object} device - Device. * @param {boolean} isHMD - Is HMD. @@ -169,7 +177,7 @@ public: */ Q_INVOKABLE void setOutputDevice(const HifiAudioDeviceInfo& device, bool isHMD); - /**jsdoc + /*@jsdoc * Enables or disables reverberation. Reverberation is done by the client on the post-mix audio. The reverberation options * come from either the domain's audio zone configured on the server or settings scripted by * {@link Audio.setReverbOptions|setReverbOptions}. @@ -202,21 +210,21 @@ public: * }, 8000); */ Q_INVOKABLE void setReverb(bool enable); - /**jsdoc + /*@jsdoc * Configures reverberation options. Use {@link Audio.setReverb|setReverb} to enable or disable reverberation. * @function Audio.setReverbOptions * @param {AudioEffectOptions} options - The reverberation options. */ Q_INVOKABLE void setReverbOptions(const AudioEffectOptions* options); - /**jsdoc + /*@jsdoc * Sets the gain (relative volume) that avatars' voices are played at. This gain is used at the server. * @function Audio.setAvatarGain * @param {number} gain - The avatar gain (dB) at the server. */ Q_INVOKABLE void setAvatarGain(float gain); - /**jsdoc + /*@jsdoc * Gets the gain (relative volume) that avatars' voices are played at. This gain is used at the server. * @function Audio.getAvatarGain * @returns {number} The avatar gain (dB) at the server. @@ -229,49 +237,63 @@ public: */ Q_INVOKABLE float getAvatarGain(); - /**jsdoc + /*@jsdoc * Sets the gain (relative volume) that environment sounds from the server are played at. * @function Audio.setInjectorGain * @param {number} gain - The injector gain (dB) at the server. */ Q_INVOKABLE void setInjectorGain(float gain); - /**jsdoc + /*@jsdoc * Gets the gain (relative volume) that environment sounds from the server are played at. * @function Audio.getInjectorGain * @returns {number} The injector gain (dB) at the server. */ Q_INVOKABLE float getInjectorGain(); - /**jsdoc + /*@jsdoc * Sets the gain (relative volume) that environment sounds from the client are played at. * @function Audio.setLocalInjectorGain * @param {number} gain - The injector gain (dB) in the client. */ Q_INVOKABLE void setLocalInjectorGain(float gain); - /**jsdoc + /*@jsdoc * Gets the gain (relative volume) that environment sounds from the client are played at. * @function Audio.getLocalInjectorGain * @returns {number} The injector gain (dB) in the client. */ Q_INVOKABLE float getLocalInjectorGain(); - /**jsdoc + /*@jsdoc * Sets the gain (relative volume) that system sounds are played at. * @function Audio.setSystemInjectorGain * @param {number} gain - The injector gain (dB) in the client. */ Q_INVOKABLE void setSystemInjectorGain(float gain); - /**jsdoc + /*@jsdoc * Gets the gain (relative volume) that system sounds are played at. * @function Audio.getSystemInjectorGain * @returns {number} The injector gain (dB) in the client. */ Q_INVOKABLE float getSystemInjectorGain(); + + /*@jsdoc + * Sets the noise gate threshold before your mic audio is transmitted. (Applies only if Audio.noiseReductionAutomatic is false.) + * @function Audio.setNoiseReductionThreshold + * @param {number} threshold - The level that your input must surpass to be transmitted. 0.0 (open the gate completely) – 1.0 + */ + Q_INVOKABLE void setNoiseReductionThreshold(float threshold); - /**jsdoc + /*@jsdoc + * Gets the noise reduction threshold. + * @function Audio.getNoiseReductionThreshold + * @returns {number} The noise reduction threshold. 0.01.0 + */ + Q_INVOKABLE float getNoiseReductionThreshold(); + + /*@jsdoc * Starts making an audio recording of the audio being played in-world (i.e., not local-only audio) to a file in WAV format. * @function Audio.startRecording * @param {string} filename - The path and name of the file to make the recording in. Should have a .wav @@ -292,20 +314,20 @@ public: */ Q_INVOKABLE bool startRecording(const QString& filename); - /**jsdoc + /*@jsdoc * Finishes making an audio recording started with {@link Audio.startRecording|startRecording}. * @function Audio.stopRecording */ Q_INVOKABLE void stopRecording(); - /**jsdoc + /*@jsdoc * Checks whether an audio recording is currently being made. * @function Audio.getRecording * @returns {boolean} true if an audio recording is currently being made, otherwise false. */ Q_INVOKABLE bool getRecording(); - /**jsdoc + /*@jsdoc * Sets the output volume gain that will be used when the user is holding the push-to-talk key. * Should be negative. * @function Audio.setPushingToTalkOutputGainDesktop @@ -313,7 +335,7 @@ public: */ Q_INVOKABLE void setPushingToTalkOutputGainDesktop(float gain); - /**jsdoc + /*@jsdoc * Gets the output volume gain that is used when the user is holding the push-to-talk key. * Should be negative. * @function Audio.getPushingToTalkOutputGainDesktop @@ -323,14 +345,14 @@ public: signals: - /**jsdoc + /*@jsdoc * @function Audio.nop * @returns {Signal} * @deprecated This signal is deprecated and will be removed. */ void nop(); - /**jsdoc + /*@jsdoc * Triggered when the audio input is muted or unmuted for the current context (desktop or HMD). * @function Audio.mutedChanged * @param {boolean} isMuted - true if the audio input is muted for the current context (desktop or HMD), @@ -343,7 +365,7 @@ signals: */ void mutedChanged(bool isMuted); - /**jsdoc + /*@jsdoc * Triggered when desktop audio input is muted or unmuted. * @function Audio.mutedDesektopChanged * @param {boolean} isMuted - true if desktop audio input is muted, otherwise false. @@ -355,7 +377,7 @@ signals: */ void mutedDesktopChanged(bool isMuted); - /**jsdoc + /*@jsdoc * Triggered when HMD audio input is muted or unmuted. * @function Audio.mutedHMDChanged * @param {boolean} isMuted - true if HMD audio input is muted, otherwise false. @@ -363,7 +385,7 @@ signals: */ void mutedHMDChanged(bool isMuted); - /**jsdoc + /*@jsdoc * Triggered when push-to-talk is enabled or disabled for the current context (desktop or HMD). * @function Audio.pushToTalkChanged * @param {boolean} enabled - true if push-to-talk is enabled, otherwise false. @@ -375,7 +397,7 @@ signals: */ void pushToTalkChanged(bool enabled); - /**jsdoc + /*@jsdoc * Triggered when push-to-talk is enabled or disabled for desktop mode. * @function Audio.pushToTalkDesktopChanged * @param {boolean} enabled - true if push-to-talk is enabled for desktop mode, otherwise false. @@ -383,7 +405,7 @@ signals: */ void pushToTalkDesktopChanged(bool enabled); - /**jsdoc + /*@jsdoc * Triggered when push-to-talk is enabled or disabled for HMD mode. * @function Audio.pushToTalkHMDChanged * @param {boolean} enabled - true if push-to-talk is enabled for HMD mode, otherwise false. @@ -391,15 +413,32 @@ signals: */ void pushToTalkHMDChanged(bool enabled); - /**jsdoc + /*@jsdoc * Triggered when audio input noise reduction is enabled or disabled. * @function Audio.noiseReductionChanged * @param {boolean} isEnabled - true if audio input noise reduction is enabled, otherwise false. * @returns {Signal} */ void noiseReductionChanged(bool isEnabled); + + /*@jsdoc + * Triggered when the audio input noise reduction mode is changed. + * @function Audio.noiseReductionAutomaticChanged + * @param {boolean} isEnabled - true if audio input noise reduction automatic mode is enabled, false if in manual mode. + * @returns {Signal} + */ + void noiseReductionAutomaticChanged(bool isEnabled); + + /*@jsdoc + * Triggered when the audio input noise reduction threshold is changed. + * @function Audio.noiseReductionThresholdChanged + * @param {number} threshold - The threshold for the audio input noise reduction, range 0.0 (open the gate completely) – 1.0 + * (close the gate completely). + * @returns {Signal} + */ + void noiseReductionThresholdChanged(float threshold); - /**jsdoc + /*@jsdoc * Triggered when "warn when muted" is enabled or disabled. * @function Audio.warnWhenMutedChanged * @param {boolean} isEnabled - true if "warn when muted" is enabled, otherwise false. @@ -407,7 +446,7 @@ signals: */ void warnWhenMutedChanged(bool isEnabled); - /**jsdoc + /*@jsdoc * Triggered when acoustic echo cancellation is enabled or disabled. * @function Audio.acousticEchoCancellationChanged * @param {boolean} isEnabled - true if acoustic echo cancellation is enabled, otherwise false. @@ -415,7 +454,7 @@ signals: */ void acousticEchoCancellationChanged(bool isEnabled); - /**jsdoc + /*@jsdoc * Triggered when the input audio volume changes. * @function Audio.inputVolumeChanged * @param {number} volume - The requested volume to be applied to the audio input, range 0.0 – @@ -426,7 +465,7 @@ signals: */ void inputVolumeChanged(float volume); - /**jsdoc + /*@jsdoc * Triggered when the input audio level changes. * @function Audio.inputLevelChanged * @param {number} level - The loudness of the input audio, range 0.0 (no sound) – 1.0 (the @@ -435,7 +474,7 @@ signals: */ void inputLevelChanged(float level); - /**jsdoc + /*@jsdoc * Triggered when the clipping state of the input audio changes. * @function Audio.clippingChanged * @param {boolean} isClipping - true if the audio input is clipping, otherwise false. @@ -443,7 +482,7 @@ signals: */ void clippingChanged(bool isClipping); - /**jsdoc + /*@jsdoc * Triggered when the current context of the audio changes. * @function Audio.contextChanged * @param {string} context - The current context of the audio: either "Desktop" or "HMD". @@ -451,7 +490,7 @@ signals: */ void contextChanged(const QString& context); - /**jsdoc + /*@jsdoc * Triggered when the user starts or stops push-to-talk. * @function Audio.pushingToTalkChanged * @param {boolean} talking - true if started push-to-talk, false if stopped push-to-talk. @@ -459,7 +498,7 @@ signals: */ void pushingToTalkChanged(bool talking); - /**jsdoc + /*@jsdoc * Triggered when the avatar gain changes. * @function Audio.avatarGainChanged * @param {number} gain - The new avatar gain value (dB). @@ -467,7 +506,7 @@ signals: */ void avatarGainChanged(float gain); - /**jsdoc + /*@jsdoc * Triggered when the local injector gain changes. * @function Audio.localInjectorGainChanged * @param {number} gain - The new local injector gain value (dB). @@ -475,7 +514,7 @@ signals: */ void localInjectorGainChanged(float gain); - /**jsdoc + /*@jsdoc * Triggered when the server injector gain changes. * @function Audio.serverInjectorGainChanged * @param {number} gain - The new server injector gain value (dB). @@ -483,7 +522,7 @@ signals: */ void serverInjectorGainChanged(float gain); - /**jsdoc + /*@jsdoc * Triggered when the system injector gain changes. * @function Audio.systemInjectorGainChanged * @param {number} gain - The new system injector gain value (dB). @@ -491,7 +530,7 @@ signals: */ void systemInjectorGainChanged(float gain); - /**jsdoc + /*@jsdoc * Triggered when the push to talk gain changes. * @function Audio.pushingToTalkOutputGainDesktopChanged * @param {number} gain - The new output gain value (dB). @@ -501,7 +540,7 @@ signals: public slots: - /**jsdoc + /*@jsdoc * @function Audio.onContextChanged * @deprecated This function is deprecated and will be removed. */ @@ -512,6 +551,7 @@ public slots: private slots: void setMuted(bool muted); void enableNoiseReduction(bool enable); + void enableNoiseReductionAutomatic(bool enable); void enableWarnWhenMuted(bool enable); void enableAcousticEchoCancellation(bool enable); void setInputVolume(float volume); @@ -533,8 +573,10 @@ private: float _localInjectorGain { 0.0f }; // in dB float _systemInjectorGain { 0.0f }; // in dB float _pttOutputGainDesktop { 0.0f }; // in dB + float _noiseReductionThreshold { 0.1f }; // Match default value of AudioClient::_noiseReductionThreshold. bool _isClipping { false }; bool _enableNoiseReduction { true }; // Match default value of AudioClient::_isNoiseGateEnabled. + bool _noiseReductionAutomatic { true }; // Match default value of AudioClient::_noiseReductionAutomatic. bool _enableWarnWhenMuted { true }; bool _enableAcousticEchoCancellation { true }; // AudioClient::_isAECEnabled bool _contextIsHMD { false }; diff --git a/interface/src/scripting/ClipboardScriptingInterface.h b/interface/src/scripting/ClipboardScriptingInterface.h index 9660b2158b..41f50e3468 100644 --- a/interface/src/scripting/ClipboardScriptingInterface.h +++ b/interface/src/scripting/ClipboardScriptingInterface.h @@ -17,7 +17,7 @@ #include -/**jsdoc +/*@jsdoc * The Clipboard API enables you to export and import entities to and from JSON files. * * @namespace Clipboard @@ -32,7 +32,7 @@ public: ClipboardScriptingInterface(); public: - /**jsdoc + /*@jsdoc * Gets the extents of the entities held in the clipboard. * @function Clipboard.getContentsDimensions * @returns {Vec3} The extents of the content held in the clipboard. @@ -46,14 +46,14 @@ public: */ Q_INVOKABLE glm::vec3 getContentsDimensions(); - /**jsdoc + /*@jsdoc * Gets the largest dimension of the extents of the entities held in the clipboard. * @function Clipboard.getClipboardContentsLargestDimension * @returns {number} The largest dimension of the extents of the content held in the clipboard. */ Q_INVOKABLE float getClipboardContentsLargestDimension(); - /**jsdoc + /*@jsdoc * Imports entities from a JSON file into the clipboard. * @function Clipboard.importEntities * @param {string} filename - The path and name of the JSON file to import. @@ -73,7 +73,7 @@ public: */ Q_INVOKABLE bool importEntities(const QString& filename, const bool isObservable = true, const qint64 callerId = -1); - /**jsdoc + /*@jsdoc * Exports specified entities to a JSON file. * @function Clipboard.exportEntities * @param {string} filename - Path and name of the file to export the entities to. Should have the extension ".json". @@ -100,7 +100,7 @@ public: */ Q_INVOKABLE bool exportEntities(const QString& filename, const QVector& entityIDs); - /**jsdoc + /*@jsdoc * Exports all entities that have centers within a cube to a JSON file. * @function Clipboard.exportEntities * @variation 0 @@ -113,7 +113,7 @@ public: */ Q_INVOKABLE bool exportEntities(const QString& filename, float x, float y, float z, float scale); - /**jsdoc + /*@jsdoc * Pastes the contents of the clipboard into the domain. * @function Clipboard.pasteEntities * @param {Vec3} position - The position to paste the clipboard contents at. diff --git a/interface/src/scripting/ControllerScriptingInterface.h b/interface/src/scripting/ControllerScriptingInterface.h index f65791335d..175021e559 100644 --- a/interface/src/scripting/ControllerScriptingInterface.h +++ b/interface/src/scripting/ControllerScriptingInterface.h @@ -25,7 +25,7 @@ class ScriptEngine; -/**jsdoc +/*@jsdoc * The Controller API provides facilities to interact with computer and controller hardware. * *

Facilities

@@ -265,7 +265,7 @@ public: public slots: - /**jsdoc + /*@jsdoc * Disables default Interface actions for a particular key event. * @function Controller.captureKeyEvents * @param {KeyEvent} event - Details of the key event to be captured. The key property must be specified. The @@ -284,7 +284,7 @@ public slots: */ virtual void captureKeyEvents(const KeyEvent& event); - /**jsdoc + /*@jsdoc * Re-enables default Interface actions for a particular key event that has been disabled using * {@link Controller.captureKeyEvents|captureKeyEvents}. * @function Controller.releaseKeyEvents @@ -293,7 +293,7 @@ public slots: */ virtual void releaseKeyEvents(const KeyEvent& event); - /**jsdoc + /*@jsdoc * Disables default Interface actions for a joystick. * @function Controller.captureJoystick * @param {number} joystickID - The integer ID of the joystick. @@ -301,7 +301,7 @@ public slots: */ virtual void captureJoystick(int joystickIndex); - /**jsdoc + /*@jsdoc * Re-enables default Interface actions for a joystick that has been disabled using * {@link Controller.captureJoystick|captureJoystick}. * @function Controller.releaseJoystick @@ -310,7 +310,7 @@ public slots: */ virtual void releaseJoystick(int joystickIndex); - /**jsdoc + /*@jsdoc * Disables {@link Entities.mousePressOnEntity} and {@link Entities.mouseDoublePressOnEntity} events on entities. * @function Controller.captureEntityClickEvents * @example
@@ -328,7 +328,7 @@ public slots: */ virtual void captureEntityClickEvents(); - /**jsdoc + /*@jsdoc * Re-enables {@link Entities.mousePressOnEntity} and {@link Entities.mouseDoublePressOnEntity} events on entities that were * disabled using {@link Controller.captureEntityClickEvents|captureEntityClickEvents}. * @function Controller.releaseEntityClickEvents @@ -336,14 +336,14 @@ public slots: virtual void releaseEntityClickEvents(); - /**jsdoc + /*@jsdoc * Gets the dimensions of the Interface window's interior if in desktop mode or the HUD surface if in HMD mode. * @function Controller.getViewportDimensions * @returns {Vec2} The dimensions of the Interface window interior if in desktop mode or HUD surface if in HMD mode. */ virtual glm::vec2 getViewportDimensions() const; - /**jsdoc + /*@jsdoc * Gets the recommended area to position UI on the HUD surface if in HMD mode or Interface's window interior if in desktop * mode. * @function Controller.getRecommendedHUDRect @@ -351,7 +351,7 @@ public slots: */ virtual QVariant getRecommendedHUDRect() const; - /**jsdoc + /*@jsdoc * Enables or disables the virtual game pad that is displayed on certain devices (e.g., Android). * @function Controller.setVPadEnabled * @param {boolean} enable - If true then the virtual game pad doesn't work, otherwise it does work provided @@ -360,14 +360,14 @@ public slots: */ virtual void setVPadEnabled(bool enable); - /**jsdoc + /*@jsdoc * Shows or hides the virtual game pad that is displayed on certain devices (e.g., Android). * @function Controller.setVPadHidden * @param {boolean} hidden - If true then the virtual game pad is hidden, otherwise it is shown. */ virtual void setVPadHidden(bool hidden); // Call it when a window should hide it - /**jsdoc + /*@jsdoc * Sets the amount of extra margin between the virtual game pad that is displayed on certain devices (e.g., Android) and * the bottom of the display. * @function Controller.setVPadExtraBottomMargin @@ -376,7 +376,7 @@ public slots: virtual void setVPadExtraBottomMargin(int margin); signals: - /**jsdoc + /*@jsdoc * Triggered when a keyboard key is pressed. * @function Controller.keyPressEvent * @param {KeyEvent} event - Details of the key press. @@ -388,7 +388,7 @@ signals: */ void keyPressEvent(const KeyEvent& event); - /**jsdoc + /*@jsdoc * Triggered when a keyboard key is released from being pressed. * @function Controller.keyReleaseEvent * @param {KeyEvent} event - Details of the key release. @@ -396,7 +396,7 @@ signals: */ void keyReleaseEvent(const KeyEvent& event); - /**jsdoc + /*@jsdoc * Triggered when the mouse moves. * @function Controller.mouseMoveEvent * @param {MouseEvent} event - Details of the mouse movement. @@ -408,7 +408,7 @@ signals: */ void mouseMoveEvent(const MouseEvent& event); - /**jsdoc + /*@jsdoc * Triggered when a mouse button is pressed. * @function Controller.mousePressEvent * @param {MouseEvent} event - Details of the button press. @@ -416,7 +416,7 @@ signals: */ void mousePressEvent(const MouseEvent& event); - /**jsdoc + /*@jsdoc * Triggered when a mouse button is double-pressed. * @function Controller.mouseDoublePressEvent * @param {MouseEvent} event - Details of the button double-press. @@ -424,7 +424,7 @@ signals: */ void mouseDoublePressEvent(const MouseEvent& event); - /**jsdoc + /*@jsdoc * Triggered when a mouse button is released from being pressed. * @function Controller.mouseReleaseEvent * @param {MouseEvent} event - Details of the button release. @@ -432,7 +432,7 @@ signals: */ void mouseReleaseEvent(const MouseEvent& event); - /**jsdoc + /*@jsdoc * Triggered when a touch event starts in the Interface window on a touch-enabled display or device. * @function Controller.touchBeginEvent * @param {TouchEvent} event - Details of the touch begin. @@ -444,7 +444,7 @@ signals: */ void touchBeginEvent(const TouchEvent& event); - /**jsdoc + /*@jsdoc * Triggered when a touch event ends in the Interface window on a touch-enabled display or device. * @function Controller.touchEndEvent * @param {TouchEvent} event - Details of the touch end. @@ -452,7 +452,7 @@ signals: */ void touchEndEvent(const TouchEvent& event); - /**jsdoc + /*@jsdoc * Triggered when a touch event update occurs in the Interface window on a touch-enabled display or device. * @function Controller.touchUpdateEvent * @param {TouchEvent} event - Details of the touch update. @@ -460,7 +460,7 @@ signals: */ void touchUpdateEvent(const TouchEvent& event); - /**jsdoc + /*@jsdoc * Triggered when the mouse wheel is rotated. * @function Controller.wheelEvent * @param {WheelEvent} event - Details of the wheel movement. diff --git a/interface/src/scripting/DesktopScriptingInterface.cpp b/interface/src/scripting/DesktopScriptingInterface.cpp index e527561b05..cec701c911 100644 --- a/interface/src/scripting/DesktopScriptingInterface.cpp +++ b/interface/src/scripting/DesktopScriptingInterface.cpp @@ -22,7 +22,7 @@ #include #include -/**jsdoc +/*@jsdoc * The possible docking locations of an InteractiveWindow. * @typedef {object} InteractiveWindow.DockAreas * @property {InteractiveWindow.DockArea} TOP - Dock to the top edge of the Interface window. @@ -37,7 +37,7 @@ static const QVariantMap DOCK_AREA { { "RIGHT", DockArea::RIGHT } }; -/**jsdoc +/*@jsdoc * The possible relative position anchors of an InteractiveWindow relative to the Interface window. * @typedef {object} InteractiveWindow.RelativePositionAnchors * @property {InteractiveWindow.RelativePositionAnchor} NO_ANCHOR - Position is not relative to any part of the Interface @@ -70,7 +70,7 @@ int DesktopScriptingInterface::getHeight() { return size.height(); } -/**jsdoc +/*@jsdoc * The possible display modes for an InteractiveWindow. * @typedef {object} InteractiveWindow.PresentationModes * @property {InteractiveWindow.PresentationMode} VIRTUAL - The window is displayed inside Interface: in the desktop window in diff --git a/interface/src/scripting/DesktopScriptingInterface.h b/interface/src/scripting/DesktopScriptingInterface.h index e57d7a6805..28d5f8d444 100644 --- a/interface/src/scripting/DesktopScriptingInterface.h +++ b/interface/src/scripting/DesktopScriptingInterface.h @@ -19,7 +19,7 @@ #include "ui/InteractiveWindow.h" -/**jsdoc +/*@jsdoc * The Desktop API provides the dimensions of the computer screen, sets the opacity of the HUD surface, and * enables QML and HTML windows to be shown inside or outside of Interface. * @@ -60,14 +60,14 @@ class DesktopScriptingInterface : public QObject, public Dependency { public: DesktopScriptingInterface(QObject* parent= nullptr, bool restricted = false); - /**jsdoc + /*@jsdoc * Sets the opacity of the HUD surface. * @function Desktop.setHUDAlpha * @param {number} alpha - The opacity, 0.0 – 1.0. */ Q_INVOKABLE void setHUDAlpha(float alpha); - /**jsdoc + /*@jsdoc * Opens a QML window within Interface: in the Interface window in desktop mode or on the HUD surface in HMD mode. If a * window of the specified name already exists, it is shown, otherwise a new window is created from the QML. * @function Desktop.show @@ -78,7 +78,7 @@ public: */ Q_INVOKABLE void show(const QString& path, const QString& title); - /**jsdoc + /*@jsdoc * Creates a new window that can be displayed either within Interface or as a separate desktop window. * @function Desktop.createWindow * @param {string} url - The QML file that specifies the window content. The QML file can use a WebView diff --git a/interface/src/scripting/DialogsManagerScriptingInterface.h b/interface/src/scripting/DialogsManagerScriptingInterface.h index ee1baeecf5..41d348f460 100644 --- a/interface/src/scripting/DialogsManagerScriptingInterface.h +++ b/interface/src/scripting/DialogsManagerScriptingInterface.h @@ -14,7 +14,7 @@ #include -/**jsdoc +/*@jsdoc * The DialogsMamnager API provides facilities to work with some key dialogs. * * @namespace DialogsManager @@ -30,33 +30,33 @@ public: DialogsManagerScriptingInterface(); static DialogsManagerScriptingInterface* getInstance(); - /**jsdoc + /*@jsdoc * Currently performs no action. * @function DialogsManager.showFeed */ Q_INVOKABLE void showFeed(); public slots: - /**jsdoc + /*@jsdoc * Shows the "Goto" dialog. * @function DialogsManager.showAddressBar */ void showAddressBar(); - /**jsdoc + /*@jsdoc * Hides the "Goto" dialog. * @function DialogsManager.hideAddressBar */ void hideAddressBar(); - /**jsdoc + /*@jsdoc * Shows the login dialog. * @function DialogsManager.showLoginDialog */ void showLoginDialog(); signals: - /**jsdoc + /*@jsdoc * Triggered when the "Goto" dialog is opened or closed. *

Warning: Currently isn't always triggered.

* @function DialogsManager.addressBarShown diff --git a/interface/src/scripting/GooglePolyScriptingInterface.h b/interface/src/scripting/GooglePolyScriptingInterface.h index ad44ad6223..693b07f18e 100644 --- a/interface/src/scripting/GooglePolyScriptingInterface.h +++ b/interface/src/scripting/GooglePolyScriptingInterface.h @@ -15,7 +15,7 @@ #include #include -/**jsdoc +/*@jsdoc * The GooglePoly API allows you to interact with Google Poly models direct from inside High Fidelity. * @namespace GooglePoly * @@ -32,13 +32,13 @@ public: public slots: - /**jsdoc + /*@jsdoc * @function GooglePoly.setAPIKey * @param {string} key */ void setAPIKey(const QString& key); - /**jsdoc + /*@jsdoc * @function GooglePoly.getAssetList * @param {string} keyword * @param {string} category @@ -47,7 +47,7 @@ public slots: */ QString getAssetList(const QString& keyword, const QString& category, const QString& format); - /**jsdoc + /*@jsdoc * @function GooglePoly.getFBX * @param {string} keyword * @param {string} category @@ -55,7 +55,7 @@ public slots: */ QString getFBX(const QString& keyword, const QString& category); - /**jsdoc + /*@jsdoc * @function GooglePoly.getOBJ * @param {string} keyword * @param {string} category @@ -63,7 +63,7 @@ public slots: */ QString getOBJ(const QString& keyword, const QString& category); - /**jsdoc + /*@jsdoc * @function GooglePoly.getBlocks * @param {string} keyword * @param {string} category @@ -71,7 +71,7 @@ public slots: */ QString getBlocks(const QString& keyword, const QString& category); - /**jsdoc + /*@jsdoc * @function GooglePoly.getGLTF * @param {string} keyword * @param {string} category @@ -79,7 +79,7 @@ public slots: */ QString getGLTF(const QString& keyword, const QString& category); - /**jsdoc + /*@jsdoc * @function GooglePoly.getGLTF2 * @param {string} keyword * @param {string} category @@ -87,7 +87,7 @@ public slots: */ QString getGLTF2(const QString& keyword, const QString& category); - /**jsdoc + /*@jsdoc * @function GooglePoly.getTilt * @param {string} keyword * @param {string} category @@ -95,7 +95,7 @@ public slots: */ QString getTilt(const QString& keyword, const QString& category); - /**jsdoc + /*@jsdoc * @function GooglePoly.getModelInfo * @param {string} input * @returns {string} diff --git a/interface/src/scripting/HMDScriptingInterface.h b/interface/src/scripting/HMDScriptingInterface.h index 30a1353d81..7790c482fa 100644 --- a/interface/src/scripting/HMDScriptingInterface.h +++ b/interface/src/scripting/HMDScriptingInterface.h @@ -24,7 +24,7 @@ class QScriptEngine; #include -/**jsdoc +/*@jsdoc * The HMD API provides access to the HMD used in VR display mode. * * @namespace HMD @@ -116,7 +116,7 @@ class HMDScriptingInterface : public AbstractHMDScriptingInterface, public Depen public: - /**jsdoc + /*@jsdoc * Calculates the intersection of a ray with the HUD overlay. * @function HMD.calculateRayUICollisionPoint * @param {Vec3} position - The origin of the ray. @@ -144,7 +144,7 @@ public: glm::vec3 calculateParabolaUICollisionPoint(const glm::vec3& position, const glm::vec3& velocity, const glm::vec3& acceleration, float& parabolicDistance) const; - /**jsdoc + /*@jsdoc * Gets the 2D HUD overlay coordinates of a 3D point on the HUD overlay. * 2D HUD overlay coordinates are pixels with the origin at the top left of the overlay. * @function HMD.overlayFromWorldPoint @@ -170,7 +170,7 @@ public: */ Q_INVOKABLE glm::vec2 overlayFromWorldPoint(const glm::vec3& position) const; - /**jsdoc + /*@jsdoc * Gets the 3D world coordinates of a 2D point on the HUD overlay. * 2D HUD overlay coordinates are pixels with the origin at the top left of the overlay. * @function HMD.worldPointFromOverlay @@ -179,7 +179,7 @@ public: */ Q_INVOKABLE glm::vec3 worldPointFromOverlay(const glm::vec2& overlay) const; - /**jsdoc + /*@jsdoc * Gets the 2D point on the HUD overlay represented by given spherical coordinates. * 2D HUD overlay coordinates are pixels with the origin at the top left of the overlay. * Spherical coordinates are polar coordinates in radians with { x: 0, y: 0 } being the center of the HUD @@ -190,7 +190,7 @@ public: */ Q_INVOKABLE glm::vec2 sphericalToOverlay(const glm::vec2 & sphericalPos) const; - /**jsdoc + /*@jsdoc * Gets the spherical coordinates of a 2D point on the HUD overlay. * 2D HUD overlay coordinates are pixels with the origin at the top left of the overlay. * Spherical coordinates are polar coordinates in radians with { x: 0, y: 0 } being the center of the HUD @@ -201,21 +201,21 @@ public: */ Q_INVOKABLE glm::vec2 overlayToSpherical(const glm::vec2 & overlayPos) const; - /**jsdoc + /*@jsdoc * Recenters the HMD HUD to the current HMD position and orientation. * @function HMD.centerUI */ Q_INVOKABLE void centerUI(); - /**jsdoc + /*@jsdoc * Gets the name of the HMD audio input device. * @function HMD.preferredAudioInput * @returns {string} The name of the HMD audio input device if in HMD mode, otherwise an empty string. */ Q_INVOKABLE QString preferredAudioInput() const; - /**jsdoc + /*@jsdoc * Gets the name of the HMD audio output device. * @function HMD.preferredAudioOutput * @returns {string} The name of the HMD audio output device if in HMD mode, otherwise an empty string. @@ -223,7 +223,7 @@ public: Q_INVOKABLE QString preferredAudioOutput() const; - /**jsdoc + /*@jsdoc * Checks whether there is an HMD available. * @function HMD.isHMDAvailable * @param {string} [name=""] - The name of the HMD to check for, e.g., "Oculus Rift". The name is the same as @@ -237,7 +237,7 @@ public: */ Q_INVOKABLE bool isHMDAvailable(const QString& name = ""); - /**jsdoc + /*@jsdoc * Checks whether there is an HMD head controller available. * @function HMD.isHeadControllerAvailable * @param {string} [name=""] - The name of the HMD head controller to check for, e.g., "Oculus". If no name is @@ -251,7 +251,7 @@ public: */ Q_INVOKABLE bool isHeadControllerAvailable(const QString& name = ""); - /**jsdoc + /*@jsdoc * Checks whether there are HMD hand controllers available. * @function HMD.isHandControllerAvailable * @param {string} [name=""] - The name of the HMD hand controller to check for, e.g., "Oculus". If no name is @@ -265,7 +265,7 @@ public: */ Q_INVOKABLE bool isHandControllerAvailable(const QString& name = ""); - /**jsdoc + /*@jsdoc * Checks whether there are specific HMD controllers available. * @function HMD.isSubdeviceContainingNameAvailable * @param {string} name - The name of the HMD controller to check for, e.g., "OculusTouch". @@ -277,7 +277,7 @@ public: */ Q_INVOKABLE bool isSubdeviceContainingNameAvailable(const QString& name); - /**jsdoc + /*@jsdoc * Signals that models of the HMD hand controllers being used should be displayed. The models are displayed at their actual, * real-world locations. * @function HMD.requestShowHandControllers @@ -289,14 +289,14 @@ public: */ Q_INVOKABLE void requestShowHandControllers(); - /**jsdoc + /*@jsdoc * Signals that it is no longer necessary to display models of the HMD hand controllers being used. If no other scripts * want the models displayed then they are no longer displayed. * @function HMD.requestHideHandControllers */ Q_INVOKABLE void requestHideHandControllers(); - /**jsdoc + /*@jsdoc * Checks whether any script wants models of the HMD hand controllers displayed. Requests are made and canceled using * {@link HMD.requestShowHandControllers|requestShowHandControllers} and * {@link HMD.requestHideHandControllers|requestHideHandControllers}. @@ -306,14 +306,14 @@ public: Q_INVOKABLE bool shouldShowHandControllers() const; - /**jsdoc + /*@jsdoc * Causes the borders in HUD windows to be enlarged when the laser intersects them in HMD mode. By default, borders are not * enlarged. * @function HMD.activateHMDHandMouse */ Q_INVOKABLE void activateHMDHandMouse(); - /**jsdoc + /*@jsdoc * Causes the border in HUD windows to no longer be enlarged when the laser intersects them in HMD mode. By default, * borders are not enlarged. * @function HMD.deactivateHMDHandMouse @@ -321,7 +321,7 @@ public: Q_INVOKABLE void deactivateHMDHandMouse(); - /**jsdoc + /*@jsdoc * Suppresses the activation of the HMD-provided keyboard, if any. Successful calls should be balanced with a call to * {@link HMD.unsuppressKeyboard|unsuppressKeyboard} within a reasonable amount of time. * @function HMD.suppressKeyboard @@ -336,14 +336,14 @@ public: /// call to unsuppressKeyboard() within a reasonable amount of time Q_INVOKABLE bool suppressKeyboard(); - /**jsdoc + /*@jsdoc * Unsuppresses the activation of the HMD-provided keyboard, if any. * @function HMD.unsuppressKeyboard */ /// Enable the keyboard following a suppressKeyboard call Q_INVOKABLE void unsuppressKeyboard(); - /**jsdoc + /*@jsdoc * Checks whether the HMD-provided keyboard, if any, is visible. * @function HMD.isKeyboardVisible * @returns {boolean} true if the current HMD provides a keyboard and it is visible, otherwise @@ -352,13 +352,13 @@ public: /// Query the display plugin to determine the current VR keyboard visibility Q_INVOKABLE bool isKeyboardVisible(); - /**jsdoc + /*@jsdoc * Closes the tablet if it is open. * @function HMD.closeTablet */ Q_INVOKABLE void closeTablet(); - /**jsdoc + /*@jsdoc * Opens the tablet if the tablet is used in the current display mode and it isn't already showing, and sets the tablet to * contextual mode if requested. In contextual mode, the page displayed on the tablet is wholly controlled by script (i.e., * the user cannot navigate to another). @@ -391,7 +391,7 @@ public: void setVisionSqueezeTurningYFactor(float value); signals: - /**jsdoc + /*@jsdoc * Triggered when a request to show or hide models of the HMD hand controllers is made using * {@link HMD.requestShowHandControllers|requestShowHandControllers} or * {@link HMD.requestHideHandControllers|requestHideHandControllers}. @@ -410,7 +410,7 @@ signals: */ bool shouldShowHandControllersChanged(); - /**jsdoc + /*@jsdoc * Triggered when the tablet is shown or hidden. * @function HMD.showTabletChanged * @param {boolean} showTablet - true if the tablet is showing, otherwise false. @@ -418,7 +418,7 @@ signals: */ void showTabletChanged(bool showTablet); - /**jsdoc + /*@jsdoc * Triggered when the ability to display the mini tablet has changed. * @function HMD.miniTabletEnabledChanged * @param {boolean} enabled - true if the mini tablet is enabled to be displayed, otherwise false. @@ -426,7 +426,7 @@ signals: */ bool miniTabletEnabledChanged(bool enabled); - /**jsdoc + /*@jsdoc * Triggered when the altering the mode for going into an away state when the interface focus is lost in VR. * @function HMD.awayStateWhenFocusLostInVRChanged * @param {boolean} enabled - true if the setting to go into an away state in VR when the interface focus is lost is enabled, otherwise false. @@ -437,14 +437,14 @@ signals: public: HMDScriptingInterface(); - /**jsdoc + /*@jsdoc * Gets the position on the HUD overlay that your HMD is looking at, in HUD coordinates. * @function HMD.getHUDLookAtPosition2D * @returns {Vec2} The position on the HUD overlay that your HMD is looking at, in pixels. */ static QScriptValue getHUDLookAtPosition2D(QScriptContext* context, QScriptEngine* engine); - /**jsdoc + /*@jsdoc * Gets the position on the HUD overlay that your HMD is looking at, in world coordinates. * @function HMD.getHUDLookAtPosition3D * @returns {Vec3} The position on the HUD overlay the your HMD is looking at, in world coordinates. diff --git a/interface/src/scripting/KeyboardScriptingInterface.h b/interface/src/scripting/KeyboardScriptingInterface.h index dc680b05cf..196c55ffa4 100644 --- a/interface/src/scripting/KeyboardScriptingInterface.h +++ b/interface/src/scripting/KeyboardScriptingInterface.h @@ -17,7 +17,7 @@ #include "DependencyManager.h" -/**jsdoc +/*@jsdoc * The Keyboard API provides facilities to use an in-world, virtual keyboard. When enabled, this keyboard is * displayed instead of the 2D keyboard that raises at the bottom of the tablet or Web entities when a text input field has * focus and you're in HMD mode. @@ -48,7 +48,7 @@ public: KeyboardScriptingInterface() = default; ~KeyboardScriptingInterface() = default; - /**jsdoc + /*@jsdoc * Loads a JSON file that defines the virtual keyboard's layout. The default JSON file used is * {@link https://github.com/highfidelity/hifi/blob/master/interface/resources/config/keyboard.json|https://github.com/highfidelity/hifi/.../keyboard.json}. * @function Keyboard.loadKeyboardFile @@ -56,45 +56,45 @@ public: */ Q_INVOKABLE void loadKeyboardFile(const QString& string); - /**jsdoc + /*@jsdoc * Enables the left mallet so that it is displayed when in HMD mode. * @function Keyboard.enableLeftMallet */ Q_INVOKABLE void enableLeftMallet(); - /**jsdoc + /*@jsdoc * Enables the right mallet so that it is displayed when in HMD mode. * @function Keyboard.enableRightMallet */ Q_INVOKABLE void enableRightMallet(); - /**jsdoc + /*@jsdoc * Disables the left mallet so that it is not displayed when in HMD mode. * @function Keyboard.disableLeftMallet */ Q_INVOKABLE void disableLeftMallet(); - /**jsdoc + /*@jsdoc * Disables the right mallet so that it is not displayed when in HMD mode. * @function Keyboard.disableRightMallet */ Q_INVOKABLE void disableRightMallet(); - /**jsdoc + /*@jsdoc * Configures the virtual keyboard to recognize a ray pointer as the left hand's laser. * @function Keyboard.setLeftHandLaser * @param {number} leftHandLaser - The ID of a ray pointer created by {@link Pointers.createPointer}. */ Q_INVOKABLE void setLeftHandLaser(unsigned int leftHandLaser); - /**jsdoc + /*@jsdoc * Configures the virtual keyboard to recognize a ray pointer as the right hand's laser. * @function Keyboard.setRightHandLaser * @param {number} rightHandLaser - The ID of a ray pointer created by {@link Pointers.createPointer}. */ Q_INVOKABLE void setRightHandLaser(unsigned int rightHandLaser); - /**jsdoc + /*@jsdoc * Checks whether an entity is part of the virtual keyboard. * @function Keyboard.containsID * @param {Uuid} entityID - The entity ID. diff --git a/interface/src/scripting/MenuScriptingInterface.h b/interface/src/scripting/MenuScriptingInterface.h index 110df8dd06..83dda80bf8 100644 --- a/interface/src/scripting/MenuScriptingInterface.h +++ b/interface/src/scripting/MenuScriptingInterface.h @@ -17,7 +17,7 @@ class MenuItemProperties; -/**jsdoc +/*@jsdoc * The Menu API provides access to the menu that is displayed at the top of the window on a user's desktop and in * the tablet when the "MENU" button is pressed. * @@ -57,7 +57,7 @@ private slots: void menuItemTriggered(); public slots: - /**jsdoc + /*@jsdoc * Adds a new top-level menu. * @function Menu.addMenu * @param {string} menuName - Name that will be displayed for the menu. Nested menus can be specified using the @@ -73,7 +73,7 @@ public slots: */ void addMenu(const QString& menuName, const QString& grouping = QString()); - /**jsdoc + /*@jsdoc * Removes a top-level menu. * @function Menu.removeMenu * @param {string} menuName - Name of the menu to remove. @@ -83,7 +83,7 @@ public slots: */ void removeMenu(const QString& menuName); - /**jsdoc + /*@jsdoc * Checks whether a top-level menu exists. * @function Menu.menuExists * @param {string} menuName - Name of the menu to check exists. @@ -95,7 +95,7 @@ public slots: */ bool menuExists(const QString& menuName); - /**jsdoc + /*@jsdoc * Adds a separator with an unclickable label below it. The separator will be placed at the bottom of the menu. To add a * separator at a specific point in the menu, use {@link Menu.addMenuItem} with {@link Menu.MenuItemProperties} instead. * @function Menu.addSeparator @@ -106,7 +106,7 @@ public slots: */ void addSeparator(const QString& menuName, const QString& separatorName); - /**jsdoc + /*@jsdoc * Removes a separator from a menu. * @function Menu.removeSeparator * @param {string} menuName - Name of the menu to remove the separator from. @@ -116,7 +116,7 @@ public slots: */ void removeSeparator(const QString& menuName, const QString& separatorName); - /**jsdoc + /*@jsdoc * Adds a new menu item to a menu. The menu item is specified using {@link Menu.MenuItemProperties}. * @function Menu.addMenuItem * @param {Menu.MenuItemProperties} properties - Properties of the menu item to create. @@ -130,7 +130,7 @@ public slots: */ void addMenuItem(const MenuItemProperties& properties); - /**jsdoc + /*@jsdoc * Adds a new menu item to a menu. The new item is added at the end of the menu. * @function Menu.addMenuItem * @variation 0 @@ -143,7 +143,7 @@ public slots: void addMenuItem(const QString& menuName, const QString& menuitem, const QString& shortcutKey); void addMenuItem(const QString& menuName, const QString& menuitem); - /**jsdoc + /*@jsdoc * Removes a menu item from a menu. * @function Menu.removeMenuItem * @param {string} menuName - Name of the menu to remove a menu item from. @@ -153,7 +153,7 @@ public slots: */ void removeMenuItem(const QString& menuName, const QString& menuitem); - /**jsdoc + /*@jsdoc * Checks whether a menu item exists. * @function Menu.menuItemExists * @param {string} menuName - Name of the menu that the menu item is in. @@ -166,7 +166,7 @@ public slots: */ bool menuItemExists(const QString& menuName, const QString& menuitem); - /**jsdoc + /*@jsdoc * Checks whether a checkable menu item is checked. * @function Menu.isOptionChecked * @param {string} menuOption - The name of the menu item. @@ -176,7 +176,7 @@ public slots: */ bool isOptionChecked(const QString& menuOption); - /**jsdoc + /*@jsdoc * Sets a checkable menu item as checked or unchecked. * @function Menu.setIsOptionChecked * @param {string} menuOption - The name of the menu item to modify. @@ -187,7 +187,7 @@ public slots: */ void setIsOptionChecked(const QString& menuOption, bool isChecked); - /**jsdoc + /*@jsdoc * Triggers a menu item as if the user clicked on it. * @function Menu.triggerOption * @param {string} menuOption - The name of the menu item to trigger. @@ -196,7 +196,7 @@ public slots: */ void triggerOption(const QString& menuOption); - /**jsdoc + /*@jsdoc * Checks whether a menu or menu item is enabled. If disabled, the item is grayed out and unusable. * Menus are enabled by default. * @function Menu.isMenuEnabled @@ -207,7 +207,7 @@ public slots: */ bool isMenuEnabled(const QString& menuName); - /**jsdoc + /*@jsdoc * Sets a menu or menu item to be enabled or disabled. If disabled, the item is grayed out and unusable. * @function Menu.setMenuEnabled * @param {string} menuName - The name of the menu or menu item to modify. @@ -219,7 +219,7 @@ public slots: void setMenuEnabled(const QString& menuName, bool isEnabled); signals: - /**jsdoc + /*@jsdoc * Triggered when a menu item is clicked or triggered by {@link Menu.triggerOption}. * @function Menu.menuItemEvent * @param {string} menuItem - Name of the menu item that was clicked or triggered. diff --git a/interface/src/scripting/PerformanceScriptingInterface.h b/interface/src/scripting/PerformanceScriptingInterface.h index 8a7e403e5d..d5048115c7 100644 --- a/interface/src/scripting/PerformanceScriptingInterface.h +++ b/interface/src/scripting/PerformanceScriptingInterface.h @@ -18,7 +18,7 @@ #include "../RefreshRateManager.h" -/**jsdoc +/*@jsdoc * The Performance API provides control and information on graphics performance settings. * * @namespace Performance @@ -37,7 +37,7 @@ class PerformanceScriptingInterface : public QObject { public: - /**jsdoc + /*@jsdoc *

Graphics performance presets.

*
Disable entity click events for a short period.
* @@ -63,7 +63,7 @@ public: }; Q_ENUM(PerformancePreset) - /**jsdoc + /*@jsdoc *

Refresh rate profile.

*
* @@ -93,21 +93,21 @@ public: public slots: - /**jsdoc + /*@jsdoc * Sets graphics performance to a preset. * @function Performance.setPerformancePreset * @param {Performance.PerformancePreset} performancePreset - The graphics performance preset to to use. */ void setPerformancePreset(PerformancePreset performancePreset); - /**jsdoc + /*@jsdoc * Gets the current graphics performance preset in use. * @function Performance.getPerformancePreset * @returns {Performance.PerformancePreset} The current graphics performance preset in use. */ PerformancePreset getPerformancePreset() const; - /**jsdoc + /*@jsdoc * Gets the names of the graphics performance presets. * @function Performance.getPerformancePresetNames * @returns {string[]} The names of the graphics performance presets. The array index values correspond to @@ -116,21 +116,21 @@ public slots: QStringList getPerformancePresetNames() const; - /**jsdoc + /*@jsdoc * Sets the curfrent refresh rate profile. * @function Performance.setRefreshRateProfile * @param {Performance.RefreshRateProfile} refreshRateProfile - The refresh rate profile. */ void setRefreshRateProfile(RefreshRateProfile refreshRateProfile); - /**jsdoc + /*@jsdoc * Gets the current refresh rate profile in use. * @function Performance.getRefreshRateProfile * @returns {Performance.RefreshRateProfile} The refresh rate profile. */ RefreshRateProfile getRefreshRateProfile() const; - /**jsdoc + /*@jsdoc * Gets the names of the refresh rate profiles. * @function Performance.getRefreshRateProfileNames * @returns {string[]} The names of the refresh rate profiles. The array index values correspond to @@ -139,7 +139,7 @@ public slots: QStringList getRefreshRateProfileNames() const; - /**jsdoc + /*@jsdoc * Gets the current target refresh rate, in Hz, per the current refresh rate profile and refresh rate regime if in desktop * mode; a higher rate if in VR mode. * @function Performance.getActiveRefreshRate @@ -147,14 +147,14 @@ public slots: */ int getActiveRefreshRate() const; - /**jsdoc + /*@jsdoc * Gets the current user experience mode. * @function Performance.getUXMode * @returns {UXMode} The current user experience mode. */ RefreshRateManager::UXMode getUXMode() const; - /**jsdoc + /*@jsdoc * Gets the current refresh rate regime that's in effect. * @function Performance.getRefreshRateRegime * @returns {RefreshRateRegime} The current refresh rate regime. @@ -163,7 +163,7 @@ public slots: signals: - /**jsdoc + /*@jsdoc * Triggered when the performance preset or refresh rate profile is changed. * @function Performance.settingsChanged * @returns {Signal} diff --git a/interface/src/scripting/PlatformInfoScriptingInterface.h b/interface/src/scripting/PlatformInfoScriptingInterface.h index 25cdc99577..71b54f95fd 100644 --- a/interface/src/scripting/PlatformInfoScriptingInterface.h +++ b/interface/src/scripting/PlatformInfoScriptingInterface.h @@ -14,7 +14,7 @@ class QScriptValue; -/**jsdoc +/*@jsdoc * The PlatformInfo API provides information about the hardware platform being used. * * @namespace PlatformInfo @@ -31,7 +31,7 @@ public: PlatformInfoScriptingInterface(); virtual ~PlatformInfoScriptingInterface(); - /**jsdoc + /*@jsdoc *

The platform tier of a computer is an indication of its rendering capability.

*
* @@ -56,13 +56,13 @@ public: Q_ENUM(PlatformTier); public slots: - /**jsdoc + /*@jsdoc * @function PlatformInfo.getInstance * @deprecated This function is deprecated and will be removed. */ static PlatformInfoScriptingInterface* getInstance(); - /**jsdoc + /*@jsdoc * Gets the operating system type. * @function PlatformInfo.getOperatingSystemType * @returns {string} The operating system type: "WINDOWS", "MACOS", or "UNKNOWN". @@ -71,7 +71,7 @@ public slots: */ QString getOperatingSystemType(); - /**jsdoc + /*@jsdoc * Gets information on the CPU model. * @function PlatformInfo.getCPUBrand * @returns {string} Information on the CPU. @@ -80,7 +80,7 @@ public slots: */ QString getCPUBrand(); - /**jsdoc + /*@jsdoc * Gets the number of logical CPU cores. * @function PlatformInfo.getNumLogicalCores * @returns {number} The number of logical CPU cores. @@ -89,7 +89,7 @@ public slots: */ unsigned int getNumLogicalCores(); - /**jsdoc + /*@jsdoc * Gets the total amount of usable physical memory, in MB. * @function PlatformInfo.getTotalSystemMemoryMB * @returns {number} The total system memory in megabytes. @@ -98,7 +98,7 @@ public slots: */ int getTotalSystemMemoryMB(); - /**jsdoc + /*@jsdoc * Gets the model of the graphics card currently being used. * @function PlatformInfo.getGraphicsCardType * @returns {string} The model of the graphics card currently being used. @@ -109,21 +109,21 @@ public slots: */ QString getGraphicsCardType(); - /**jsdoc + /*@jsdoc * Checks whether Oculus Touch controllers are connected. * @function PlatformInfo.hasRiftControllers * @returns {boolean} true if Oculus Touch controllers are connected, false if they aren't. */ bool hasRiftControllers(); - /**jsdoc + /*@jsdoc * Checks whether Vive controllers are connected. * @function PlatformInfo.hasViveControllers * @returns {boolean} true if Vive controllers are connected, false if they aren't. */ bool hasViveControllers(); - /**jsdoc + /*@jsdoc * Checks whether HTML on 3D surfaces (e.g., Web entities) is supported. * @function PlatformInfo.has3DHTML * @returns {boolean} true if the current display supports HTML on 3D surfaces, false if it @@ -131,28 +131,28 @@ public slots: */ bool has3DHTML(); - /**jsdoc + /*@jsdoc * Checks whether Interface is running on a stand-alone HMD device (CPU incorporated into the HMD display). * @function PlatformInfo.isStandalone * @returns {boolean} true if Interface is running on a stand-alone HMD device, false if it isn't. */ bool isStandalone(); - /**jsdoc + /*@jsdoc * Gets the number of CPUs. * @function PlatformInfo.getNumCPUs * @returns {number} The number of CPUs. */ int getNumCPUs(); - /**jsdoc + /*@jsdoc * Gets the index number of the master CPU. * @function PlatformInfo.getMasterCPU * @returns {number} The index of the master CPU. */ int getMasterCPU(); - /**jsdoc + /*@jsdoc * Gets the platform description of a CPU. * @function PlatformInfo.getCPU * @param {number} index - The index number of the CPU. @@ -167,21 +167,21 @@ public slots: */ QString getCPU(int index); - /**jsdoc + /*@jsdoc * Gets the number of GPUs. * @function PlatformInfo.getNumGPUs * @returns {number} The number of GPUs. */ int getNumGPUs(); - /**jsdoc + /*@jsdoc * Gets the index number of the master GPU. * @function PlatformInfo.getMasterGPU * @returns {number} The index of the master GPU. */ int getMasterGPU(); - /**jsdoc + /*@jsdoc * Gets the platform description of a GPU. * @param {number} index - The index number of the GPU. * @function PlatformInfo.getGPU @@ -196,21 +196,21 @@ public slots: */ QString getGPU(int index); - /**jsdoc + /*@jsdoc * Gets the number of displays. * @function PlatformInfo.getNumDisplays * @returns {number} The number of displays. */ int getNumDisplays(); - /**jsdoc + /*@jsdoc * Gets the index number of the master display. * @function PlatformInfo.getMasterDisplay * @returns {number} The index of the master display. */ int getMasterDisplay(); - /**jsdoc + /*@jsdoc * Gets the platform description of a display. * @param {number} index - The index number of the display. * @function PlatformInfo.getDisplay @@ -225,7 +225,7 @@ public slots: */ QString getDisplay(int index); - /**jsdoc + /*@jsdoc * Gets the platform description of computer memory. * @function PlatformInfo.getMemory * @returns {string} The computer's {@link PlatformInfo.MemoryDescription|MemoryDescription} information as a JSON string. @@ -234,21 +234,21 @@ public slots: */ QString getMemory(); - /**jsdoc + /*@jsdoc * Gets the platform description of the computer. * @function PlatformInfo.getComputer * @returns {string} The {@link PlatformInfo.ComputerDescription|ComputerDescription} information as a JSON string. */ QString getComputer(); - /**jsdoc + /*@jsdoc * Gets the complete description of the computer as a whole. * @function PlatformInfo.getPlatform * @returns {string} The {@link PlatformInfo.PlatformDescription|PlatformDescription} information as a JSON string. */ QString getPlatform(); - /**jsdoc + /*@jsdoc * Gets the platform tier of the computer, profiled at Interface start-up. * @function PlatformInfo.getTierProfiled * @returns {PlatformInfo.PlatformTier} The platform tier of the computer. @@ -259,14 +259,14 @@ public slots: */ PlatformTier getTierProfiled(); - /**jsdoc + /*@jsdoc * Gets the names of the possible platform tiers, per {@link PlatformInfo.PlatformTier}. * @function PlatformInfo.getPlatformTierNames * @returns {string[]} The names of the possible platform tiers. */ QStringList getPlatformTierNames(); - /**jsdoc + /*@jsdoc * Gets whether the current hardware can use deferred rendering. * @function PlatformInfo.isRenderMethodDeferredCapable * @returns {boolean} true if the current hardware can use deferred rendering, false if it can't. diff --git a/interface/src/scripting/RatesScriptingInterface.h b/interface/src/scripting/RatesScriptingInterface.h index 6feef94d17..3ac6dd3191 100644 --- a/interface/src/scripting/RatesScriptingInterface.h +++ b/interface/src/scripting/RatesScriptingInterface.h @@ -14,7 +14,7 @@ #include -/**jsdoc +/*@jsdoc * The Rates API provides some information on current rendering performance. * * @namespace Rates diff --git a/interface/src/scripting/RenderScriptingInterface.h b/interface/src/scripting/RenderScriptingInterface.h index 1c2443144a..97b736259b 100644 --- a/interface/src/scripting/RenderScriptingInterface.h +++ b/interface/src/scripting/RenderScriptingInterface.h @@ -14,7 +14,7 @@ #include "RenderForward.h" -/**jsdoc +/*@jsdoc * The Render API enables you to configure the graphics engine. * * @namespace Render @@ -43,7 +43,7 @@ public: static RenderScriptingInterface* getInstance(); - /**jsdoc + /*@jsdoc *

The rendering method is specified by the following values:

*
* @@ -73,7 +73,7 @@ public: void loadSettings(); public slots: - /**jsdoc + /*@jsdoc * Gets the configuration for a rendering job by name. *

Warning: For internal, debugging purposes. Subject to change.

* @function Render.getConfig @@ -83,7 +83,7 @@ public slots: QObject* getConfig(const QString& name) { return qApp->getRenderEngine()->getConfiguration()->getConfig(name); } - /**jsdoc + /*@jsdoc * Gets the render method being used. * @function Render.getRenderMethod * @returns {Render.RenderMethod} The render method being used. @@ -93,14 +93,14 @@ public slots: */ RenderMethod getRenderMethod() const; - /**jsdoc + /*@jsdoc * Sets the render method to use. * @function Render.setRenderMethod * @param {Render.RenderMethod} renderMethod - The render method to use. */ void setRenderMethod(RenderMethod renderMethod); - /**jsdoc + /*@jsdoc * Gets the names of the possible render methods, per {@link Render.RenderMethod}. * @function Render.getRenderMethodNames * @returns {string[]} The names of the possible render methods. @@ -114,56 +114,56 @@ public slots: QStringList getRenderMethodNames() const; - /**jsdoc + /*@jsdoc * Gets whether or not shadows are enabled. * @function Render.getShadowsEnabled * @returns {boolean} true if shadows are enabled, false if they're disabled. */ bool getShadowsEnabled() const; - /**jsdoc + /*@jsdoc * Sets whether or not shadows are enabled. * @function Render.setShadowsEnabled * @param {boolean} enabled - true to enable shadows, false to disable. */ void setShadowsEnabled(bool enabled); - /**jsdoc + /*@jsdoc * Gets whether or not ambient occlusion is enabled. * @function Render.getAmbientOcclusionEnabled * @returns {boolean} true if ambient occlusion is enabled, false if it's disabled. */ bool getAmbientOcclusionEnabled() const; - /**jsdoc + /*@jsdoc * Sets whether or not ambient occlusion is enabled. * @function Render.setAmbientOcclusionEnabled * @param {boolean} enabled - true to enable ambient occlusion, false to disable. */ void setAmbientOcclusionEnabled(bool enabled); - /**jsdoc + /*@jsdoc * Gets whether or not anti-aliasing is enabled. * @function Render.getAntialiasingEnabled * @returns {boolean} true if anti-aliasing is enabled, false if it's disabled. */ bool getAntialiasingEnabled() const; - /**jsdoc + /*@jsdoc * Sets whether or not anti-aliasing is enabled. * @function Render.setAntialiasingEnabled * @param {boolean} enabled - true to enable anti-aliasing, false to disable. */ void setAntialiasingEnabled(bool enabled); - /**jsdoc + /*@jsdoc * Gets the view port resolution scale. * @function Render.getViewportResolutionScale * @returns {number} The view port resolution scale, > 0.0. */ float getViewportResolutionScale() const; - /**jsdoc + /*@jsdoc * Sets the view port resolution scale. * @function Render.setViewportResolutionScale * @param {number} resolutionScale - The view port resolution scale to set, > 0.0. @@ -172,7 +172,7 @@ public slots: signals: - /**jsdoc + /*@jsdoc * Triggered when one of the Render API's properties changes. * @function Render.settingsChanged * @returns {Signal} diff --git a/interface/src/scripting/SelectionScriptingInterface.cpp b/interface/src/scripting/SelectionScriptingInterface.cpp index 32f837668d..b56c109b95 100644 --- a/interface/src/scripting/SelectionScriptingInterface.cpp +++ b/interface/src/scripting/SelectionScriptingInterface.cpp @@ -43,7 +43,7 @@ bool GameplayObjects::removeFromGameplayObjects(const EntityItemID& entityID) { SelectionScriptingInterface::SelectionScriptingInterface() { } -/**jsdoc +/*@jsdoc *

The type of a specific item in a selection list.

*
* @@ -245,7 +245,7 @@ void SelectionScriptingInterface::printList(const QString& listName) { } } -/**jsdoc +/*@jsdoc * A selection list. * @typedef {object} Selection.SelectedItemsList * @property {Uuid[]} avatars - The IDs of the avatars in the selection list. @@ -439,7 +439,7 @@ bool SelectionHighlightStyle::fromVariantMap(const QVariantMap& properties) { return true; } -/**jsdoc +/*@jsdoc * The highlighting style of a selection list. * @typedef {object} Selection.HighlightStyle * @property {Color} outlineUnoccludedColor=255,178,51 - Unoccluded outline color. diff --git a/interface/src/scripting/SelectionScriptingInterface.h b/interface/src/scripting/SelectionScriptingInterface.h index f477a25b42..f13d8d2427 100644 --- a/interface/src/scripting/SelectionScriptingInterface.h +++ b/interface/src/scripting/SelectionScriptingInterface.h @@ -76,7 +76,7 @@ protected: render::HighlightStyle _style; }; -/**jsdoc +/*@jsdoc * The Selection API provides a means of grouping together and highlighting avatars and entities in named lists. * * @namespace Selection @@ -124,7 +124,7 @@ class SelectionScriptingInterface : public QObject, public Dependency { public: SelectionScriptingInterface(); - /**jsdoc + /*@jsdoc * Gets the names of all current selection lists. * @function Selection.getListNames * @returns {string[]} The names of all current selection lists. @@ -133,7 +133,7 @@ public: */ Q_INVOKABLE QStringList getListNames() const; - /**jsdoc + /*@jsdoc * Deletes a selection list. * @function Selection.removeListFromMap * @param {string} listName - The name of the selection list to delete. @@ -141,7 +141,7 @@ public: */ Q_INVOKABLE bool removeListFromMap(const QString& listName); - /**jsdoc + /*@jsdoc * Adds an item to a selection list. The list is created if it doesn't exist. * @function Selection.addToSelectedItemsList * @param {string} listName - The name of the selection list to add the item to. @@ -152,7 +152,7 @@ public: */ Q_INVOKABLE bool addToSelectedItemsList(const QString& listName, const QString& itemType, const QUuid& id); - /**jsdoc + /*@jsdoc * Removes an item from a selection list. * @function Selection.removeFromSelectedItemsList * @param {string} listName - The name of the selection list to remove the item from. @@ -163,7 +163,7 @@ public: */ Q_INVOKABLE bool removeFromSelectedItemsList(const QString& listName, const QString& itemType, const QUuid& id); - /**jsdoc + /*@jsdoc * Removes all items from a selection list. * @function Selection.clearSelectedItemsList * @param {string} listName - The name of the selection list. @@ -171,14 +171,14 @@ public: */ Q_INVOKABLE bool clearSelectedItemsList(const QString& listName); - /**jsdoc + /*@jsdoc * Prints the list of avatars and entities in a selection to the program log (but not the Script Log window). * @function Selection.printList * @param {string} listName - The name of the selection list. */ Q_INVOKABLE void printList(const QString& listName); - /**jsdoc + /*@jsdoc * Gets the list of avatars and entities in a selection list. * @function Selection.getSelectedItemsList * @param {string} listName - The name of the selection list. @@ -186,14 +186,14 @@ public: */ Q_INVOKABLE QVariantMap getSelectedItemsList(const QString& listName) const; - /**jsdoc + /*@jsdoc * Gets the names of all current selection lists that have highlighting enabled. * @function Selection.getHighlightedListNames * @returns {string[]} The names of the selection lists that currently have highlighting enabled. */ Q_INVOKABLE QStringList getHighlightedListNames() const; - /**jsdoc + /*@jsdoc * Enables highlighting for a selection list. All items in or subsequently added to the list are displayed with the * highlight effect specified. The method can be called multiple times with different values in the style to modify the * highlighting. @@ -205,7 +205,7 @@ public: */ Q_INVOKABLE bool enableListHighlight(const QString& listName, const QVariantMap& highlightStyle); - /**jsdoc + /*@jsdoc * Disables highlighting for a selection list. *

Note: This function implicitly calls {@link Selection.disableListToScene|disableListToScene}.

* @function Selection.disableListHighlight @@ -214,7 +214,7 @@ public: */ Q_INVOKABLE bool disableListHighlight(const QString& listName); - /**jsdoc + /*@jsdoc * Enables scene selection for a selection list. All items in or subsequently added to the list are sent to a scene * selection in the rendering engine for debugging purposes. * @function Selection.enableListToScene @@ -223,7 +223,7 @@ public: */ Q_INVOKABLE bool enableListToScene(const QString& listName); - /**jsdoc + /*@jsdoc * Disables scene selection for a selection list. * @function Selection.disableListToScene * @param {string} listName - The name of the selection list. @@ -231,7 +231,7 @@ public: */ Q_INVOKABLE bool disableListToScene(const QString& listName); - /**jsdoc + /*@jsdoc * Gets the current highlighting style for a selection list. * @function Selection.getListHighlightStyle * @param {string} listName - The name of the selection list. @@ -248,7 +248,7 @@ public: void onSelectedItemsListChanged(const QString& listName); signals: - /**jsdoc + /*@jsdoc * Triggered when a selection list's content changes or the list is deleted. * @function Selection.selectedItemsListChanged * @param {string} listName - The name of the selection list that changed. diff --git a/interface/src/scripting/SettingsScriptingInterface.h b/interface/src/scripting/SettingsScriptingInterface.h index f321c41e76..c51161b642 100644 --- a/interface/src/scripting/SettingsScriptingInterface.h +++ b/interface/src/scripting/SettingsScriptingInterface.h @@ -15,7 +15,7 @@ #include #include -/**jsdoc +/*@jsdoc * The Settings API provides a facility to store and retrieve values that persist between Interface runs. * * @namespace Settings @@ -32,7 +32,7 @@ public: public slots: - /**jsdoc + /*@jsdoc * Retrieves the value from a named setting. * @function Settings.getValue * @param {string} key - The name of the setting. @@ -49,7 +49,7 @@ public slots: QVariant getValue(const QString& setting); QVariant getValue(const QString& setting, const QVariant& defaultValue); - /**jsdoc + /*@jsdoc * Stores a value in a named setting. If the setting already exists, its value is overwritten. If the value is * null or undefined, the setting is deleted. * @function Settings.setValue diff --git a/interface/src/scripting/TestScriptingInterface.h b/interface/src/scripting/TestScriptingInterface.h index dffda3ece0..329f2a87c1 100644 --- a/interface/src/scripting/TestScriptingInterface.h +++ b/interface/src/scripting/TestScriptingInterface.h @@ -25,64 +25,64 @@ public: public slots: static TestScriptingInterface* getInstance(); - /**jsdoc + /*@jsdoc * Exits the application * @function Test.quit */ void quit(); - /**jsdoc + /*@jsdoc * Waits for all texture transfers to be complete * @function Test.waitForTextureIdle */ void waitForTextureIdle(); - /**jsdoc + /*@jsdoc * Waits for all pending downloads to be complete * @function Test.waitForDownloadIdle */ void waitForDownloadIdle(); - /**jsdoc + /*@jsdoc * Waits for all file parsing operations to be complete * @function Test.waitForProcessingIdle */ void waitForProcessingIdle(); - /**jsdoc + /*@jsdoc * Waits for all pending downloads, parsing and texture transfers to be complete * @function Test.waitIdle */ void waitIdle(); - /**jsdoc + /*@jsdoc * Waits for establishment of connection to server * @function Test.waitForConnection * @param {int} maxWaitMs [default=10000] - Number of milliseconds to wait */ bool waitForConnection(qint64 maxWaitMs = 10000); - /**jsdoc + /*@jsdoc * Waits a specific number of milliseconds * @function Test.wait * @param {int} milliseconds - Number of milliseconds to wait */ void wait(int milliseconds); - /**jsdoc + /*@jsdoc * Waits for all pending downloads, parsing and texture transfers to be complete * @function Test.loadTestScene * @param {string} sceneFile - URL of scene to load */ bool loadTestScene(QString sceneFile); - /**jsdoc + /*@jsdoc * Clears all caches * @function Test.clear */ void clear(); - /**jsdoc + /*@jsdoc * Start recording Chrome compatible tracing events * logRules can be used to specify a set of logging category rules to limit what gets captured * @function Test.startTracing @@ -90,7 +90,7 @@ public slots: */ bool startTracing(QString logrules = ""); - /**jsdoc + /*@jsdoc * Stop recording Chrome compatible tracing events and serialize recorded events to a file * Using a filename with a .gz extension will automatically compress the output file * @function Test.stopTracing @@ -99,14 +99,14 @@ public slots: */ bool stopTracing(QString filename); - /**jsdoc + /*@jsdoc * Starts a specific trace event * @function Test.startTraceEvent * @param {string} name - Name of event */ void startTraceEvent(QString name); - /**jsdoc + /*@jsdoc * Stop a specific name event * Using a filename with a .gz extension will automatically compress the output file * @function Test.endTraceEvent @@ -114,14 +114,14 @@ public slots: */ void endTraceEvent(QString name); - /**jsdoc + /*@jsdoc * Write detailed timing stats of next physics stepSimulation() to filename * @function Test.savePhysicsSimulationStats * @param {string} filename - Name of file to save to */ void savePhysicsSimulationStats(QString filename); - /**jsdoc + /*@jsdoc * Profiles a specific function * @function Test.savePhysicsSimulationStats * @param {string} name - Name used to reference the function @@ -129,13 +129,13 @@ public slots: */ Q_INVOKABLE void profileRange(const QString& name, QScriptValue function); - /**jsdoc + /*@jsdoc * Clear all caches (menu command Reload Content) * @function Test.clearCaches */ void clearCaches(); - /**jsdoc + /*@jsdoc * Save a JSON object to a file in the test results location * @function Test.saveObject * @param {string} name - Name of the object @@ -143,34 +143,34 @@ public slots: */ void saveObject(QVariant v, const QString& filename); - /**jsdoc + /*@jsdoc * Maximizes the window * @function Test.showMaximized */ void showMaximized(); - /**jsdoc + /*@jsdoc * Values higher than 0 will create replicas of other-avatars when entering a domain for testing purpouses * @function Test.setOtherAvatarsReplicaCount * @param {number} count - Number of replicas we want to create */ Q_INVOKABLE void setOtherAvatarsReplicaCount(int count); - /**jsdoc + /*@jsdoc * Return the number of replicas that are being created of other-avatars when entering a domain * @function Test.getOtherAvatarsReplicaCount * @returns {number} Current number of replicas of other-avatars. */ Q_INVOKABLE int getOtherAvatarsReplicaCount(); - /**jsdoc + /*@jsdoc * Set number of cycles texture size is required to be stable * @function Test.setMinimumGPUTextureMemStabilityCount * @param {number} count - Number of cycles to wait */ Q_INVOKABLE void setMinimumGPUTextureMemStabilityCount(int count); - /**jsdoc + /*@jsdoc * Check whether all textures have been loaded. * @function Test.isTextureLoadingComplete * @returns {boolean} true texture memory usage is not increasing diff --git a/interface/src/scripting/WalletScriptingInterface.h b/interface/src/scripting/WalletScriptingInterface.h index 849caa8427..12c8dd6fc9 100644 --- a/interface/src/scripting/WalletScriptingInterface.h +++ b/interface/src/scripting/WalletScriptingInterface.h @@ -29,7 +29,7 @@ public: CheckoutProxy(QObject* qmlObject, QObject* parent = nullptr); }; -/**jsdoc +/*@jsdoc * The WalletScriptingInterface API provides functions related to the user's wallet and verification of certified * avatar entities. * @@ -54,13 +54,13 @@ public: WalletScriptingInterface(); - /**jsdoc + /*@jsdoc * Checks and updates the user's wallet status. * @function WalletScriptingInterface.refreshWalletStatus */ Q_INVOKABLE void refreshWalletStatus(); - /**jsdoc + /*@jsdoc * Gets the current status of the user's wallet. * @function WalletScriptingInterface.getWalletStatus * @returns {WalletScriptingInterface.WalletStatus} @@ -70,7 +70,7 @@ public: */ Q_INVOKABLE uint getWalletStatus() { return _walletStatus; } - /**jsdoc + /*@jsdoc * Check that a certified avatar entity is owned by the avatar whose entity it is. The result of the check is provided via * the {@link WalletScriptingInterface.ownershipVerificationSuccess|ownershipVerificationSuccess} and * {@link WalletScriptingInterface.ownershipVerificationFailed|ownershipVerificationFailed} signals. @@ -117,7 +117,7 @@ public: signals: - /**jsdoc + /*@jsdoc * Triggered when the user's wallet status changes. * @function WalletScriptingInterface.walletStatusChanged * @returns {Signal} @@ -128,14 +128,14 @@ signals: */ void walletStatusChanged(); - /**jsdoc + /*@jsdoc * Triggered when the user's limited commerce status changes. * @function WalletScriptingInterface.limitedCommerceChanged * @returns {Signal} */ void limitedCommerceChanged(); - /**jsdoc + /*@jsdoc * Triggered when the user rezzes a certified entity but the user's wallet is not ready. So the certified location of the * entity cannot be updated in the metaverse. * @function WalletScriptingInterface.walletNotSetup @@ -143,7 +143,7 @@ signals: */ void walletNotSetup(); - /**jsdoc + /*@jsdoc * Triggered when a certified avatar entity's ownership check requested via * {@link WalletScriptingInterface.proveAvatarEntityOwnershipVerification|proveAvatarEntityOwnershipVerification} or * {@link ContextOverlay.requestOwnershipVerification} succeeds. @@ -153,7 +153,7 @@ signals: */ void ownershipVerificationSuccess(const QUuid& entityID); - /**jsdoc + /*@jsdoc * Triggered when a certified avatar entity's ownership check requested via * {@link WalletScriptingInterface.proveAvatarEntityOwnershipVerification|proveAvatarEntityOwnershipVerification} or * {@link ContextOverlay.requestOwnershipVerification} fails. diff --git a/interface/src/scripting/WindowScriptingInterface.cpp b/interface/src/scripting/WindowScriptingInterface.cpp index 98335e5d3a..c8714e2a8f 100644 --- a/interface/src/scripting/WindowScriptingInterface.cpp +++ b/interface/src/scripting/WindowScriptingInterface.cpp @@ -517,7 +517,7 @@ int WindowScriptingInterface::openMessageBox(QString title, QString text, int bu return createMessageBox(title, text, buttons, defaultButton); } -/**jsdoc +/*@jsdoc *

The buttons that may be included in a message box created by {@link Window.openMessageBox|openMessageBox} are defined by * numeric values: *

diff --git a/interface/src/scripting/WindowScriptingInterface.h b/interface/src/scripting/WindowScriptingInterface.h index 86d0f400ea..ae3aa4a141 100644 --- a/interface/src/scripting/WindowScriptingInterface.h +++ b/interface/src/scripting/WindowScriptingInterface.h @@ -22,7 +22,7 @@ #include -/**jsdoc +/*@jsdoc * The Window API provides various facilities not covered elsewhere, including: window dimensions, window focus, * camera view, announcements, user connections, common dialog boxes, snapshots, file import, domain navigation, domain changes, * domain physics, OS clipboard, build number. @@ -64,27 +64,27 @@ public: public slots: - /**jsdoc + /*@jsdoc * Checks whether the Interface window has focus. * @function Window.hasFocus * @returns {boolean} true if the Interface window has focus, false if it doesn't. */ QScriptValue hasFocus(); - /**jsdoc + /*@jsdoc * Makes the Interface window have focus. On Windows, if Interface doesn't already have focus, the task bar icon flashes to * indicate that Interface wants attention but focus isn't taken away from the application that the user is using. * @function Window.setFocus */ void setFocus(); - /**jsdoc + /*@jsdoc * Raises the Interface window if it is minimized. If raised, the window gains focus. * @function Window.raise */ void raise(); - /**jsdoc + /*@jsdoc * Displays a dialog with the specified message and an "OK" button. The dialog is non-modal; the script continues without * waiting for a user response. * @function Window.alert @@ -95,7 +95,7 @@ public slots: */ void alert(const QString& message = ""); - /**jsdoc + /*@jsdoc * Prompts the user to confirm something. Displays a modal dialog with a message plus "Yes" and "No" buttons. * @function Window.confirm * @param {string} [message=""] - The question to display. @@ -106,7 +106,7 @@ public slots: */ QScriptValue confirm(const QString& message = ""); - /**jsdoc + /*@jsdoc * Prompts the user to enter some text. Displays a modal dialog with a message and a text box, plus "OK" and "Cancel" * buttons. * @function Window.prompt @@ -123,7 +123,7 @@ public slots: */ QScriptValue prompt(const QString& message, const QString& defaultText); - /**jsdoc + /*@jsdoc * Prompts the user to enter some text. Displays a non-modal dialog with a message and a text box, plus "OK" and "Cancel" * buttons. A {@link Window.promptTextChanged|promptTextChanged} signal is emitted when the user OKs the dialog; no signal * is emitted if the user cancels the dialog. @@ -141,7 +141,7 @@ public slots: */ void promptAsync(const QString& message = "", const QString& defaultText = ""); - /**jsdoc + /*@jsdoc * Prompts the user to choose a directory. Displays a modal dialog that navigates the directory tree. * @function Window.browseDir * @param {string} [title=""] - The title to display at the top of the dialog. @@ -153,7 +153,7 @@ public slots: */ QScriptValue browseDir(const QString& title = "", const QString& directory = ""); - /**jsdoc + /*@jsdoc * Prompts the user to choose a directory. Displays a non-modal dialog that navigates the directory tree. A * {@link Window.browseDirChanged|browseDirChanged} signal is emitted when a directory is chosen; no signal is emitted if * the user cancels the dialog. @@ -171,7 +171,7 @@ public slots: */ void browseDirAsync(const QString& title = "", const QString& directory = ""); - /**jsdoc + /*@jsdoc * Prompts the user to choose a file. Displays a modal dialog that navigates the directory tree. * @function Window.browse * @param {string} [title=""] - The title to display at the top of the dialog. @@ -185,7 +185,7 @@ public slots: */ QScriptValue browse(const QString& title = "", const QString& directory = "", const QString& nameFilter = ""); - /**jsdoc + /*@jsdoc * Prompts the user to choose a file. Displays a non-modal dialog that navigates the directory tree. A * {@link Window.browseChanged|browseChanged} signal is emitted when a file is chosen; no signal is emitted if the user * cancels the dialog. @@ -205,7 +205,7 @@ public slots: */ void browseAsync(const QString& title = "", const QString& directory = "", const QString& nameFilter = ""); - /**jsdoc + /*@jsdoc * Prompts the user to specify the path and name of a file to save to. Displays a modal dialog that navigates the directory * tree and allows the user to type in a file name. * @function Window.save @@ -221,7 +221,7 @@ public slots: */ QScriptValue save(const QString& title = "", const QString& directory = "", const QString& nameFilter = ""); - /**jsdoc + /*@jsdoc * Prompts the user to specify the path and name of a file to save to. Displays a non-modal dialog that navigates the * directory tree and allows the user to type in a file name. A {@link Window.saveFileChanged|saveFileChanged} signal is * emitted when a file is specified; no signal is emitted if the user cancels the dialog. @@ -241,7 +241,7 @@ public slots: */ void saveAsync(const QString& title = "", const QString& directory = "", const QString& nameFilter = ""); - /**jsdoc + /*@jsdoc * Prompts the user to choose an Asset Server item. Displays a modal dialog that navigates the tree of assets on the Asset * Server. * @function Window.browseAssets @@ -256,7 +256,7 @@ public slots: */ QScriptValue browseAssets(const QString& title = "", const QString& directory = "", const QString& nameFilter = ""); - /**jsdoc + /*@jsdoc * Prompts the user to choose an Asset Server item. Displays a non-modal dialog that navigates the tree of assets on the * Asset Server. An {@link Window.assetsDirChanged|assetsDirChanged} signal is emitted when an asset is chosen; no signal is * emitted if the user cancels the dialog. @@ -276,7 +276,7 @@ public slots: */ void browseAssetsAsync(const QString& title = "", const QString& directory = "", const QString& nameFilter = ""); - /**jsdoc + /*@jsdoc * Opens the Asset Browser dialog. If a file to upload is specified, the user is prompted to enter the folder and name to * map the file to on the asset server. * @function Window.showAssetServer @@ -288,35 +288,35 @@ public slots: */ void showAssetServer(const QString& upload = ""); - /**jsdoc + /*@jsdoc * Gets Interface's build number. * @function Window.checkVersion * @returns {string} Interface's build number. */ QString checkVersion(); - /**jsdoc + /*@jsdoc * Gets Interface's user agent. * @function Window.getUserAgent * @returns {string} Interface's user agent. */ QString getUserAgent(); - /**jsdoc + /*@jsdoc * Gets the signature for Interface's protocol version. * @function Window.protocolSignature * @returns {string} A string uniquely identifying the version of the metaverse protocol that Interface is using. */ QString protocolSignature(); - /**jsdoc + /*@jsdoc * Copies text to the operating system's clipboard. * @function Window.copyToClipboard * @param {string} text - The text to copy to the operating system's clipboard. */ void copyToClipboard(const QString& text); - /**jsdoc + /*@jsdoc * Takes a snapshot of the current Interface view from the primary camera. When a still image only is captured, * {@link Window.stillSnapshotTaken|stillSnapshotTaken} is emitted; when a still image plus moving images are captured, * {@link Window.processingGifStarted|processingGifStarted} and {@link Window.processingGifCompleted|processingGifCompleted} @@ -364,7 +364,7 @@ public slots: */ void takeSnapshot(bool notify = true, bool includeAnimated = false, float aspectRatio = 0.0f, const QString& filename = QString()); - /**jsdoc + /*@jsdoc * Takes a still snapshot of the current view from the secondary camera that can be set up through the {@link Render} API. *

Snapshots are saved to the path specified in Settings > General > Snapshots, which can be accessed via the * {@link Snapshot} API.

@@ -379,7 +379,7 @@ public slots: */ void takeSecondaryCameraSnapshot(const bool& notify = true, const QString& filename = QString()); - /**jsdoc + /*@jsdoc * Takes a 360° snapshot at a given position for the secondary camera. The secondary camera does not need to have been * set up. *

Snapshots are saved to the path specified in Settings > General > Snapshots, which can be accessed via the @@ -398,7 +398,7 @@ public slots: */ void takeSecondaryCamera360Snapshot(const glm::vec3& cameraPosition, const bool& cubemapOutputFormat = false, const bool& notify = true, const QString& filename = QString()); - /**jsdoc + /*@jsdoc * Emits a {@link Window.connectionAdded|connectionAdded} or a {@link Window.connectionError|connectionError} signal that * indicates whether or not a user connection was successfully made using the Web API. * @function Window.makeConnection @@ -408,7 +408,7 @@ public slots: */ void makeConnection(bool success, const QString& userNameOrError); - /**jsdoc + /*@jsdoc * Displays a notification message. Notifications are displayed in panels by the default script, nofications.js. An * {@link Window.announcement|announcement} signal is emitted when this function is called. * @function Window.displayAnnouncement @@ -424,7 +424,7 @@ public slots: */ void displayAnnouncement(const QString& message); - /**jsdoc + /*@jsdoc * Prepares a snapshot ready for sharing. A {@link Window.snapshotShared|snapshotShared} signal is emitted when the snapshot * has been prepared. * @function Window.shareSnapshot @@ -433,7 +433,7 @@ public slots: */ void shareSnapshot(const QString& path, const QUrl& href = QUrl("")); - /**jsdoc + /*@jsdoc * Checks to see if physics is active for you in the domain you're visiting - there is a delay between your arrival at a * domain and physics becoming active for you in that domain. * @function Window.isPhysicsEnabled @@ -456,7 +456,7 @@ public slots: */ bool isPhysicsEnabled(); - /**jsdoc + /*@jsdoc * Sets what to show on the PC display. For entity camera view, the entity camera is configured using * {@link Camera.setCameraEntity} and {@link Camera|Camera.mode}. * @function Window.setDisplayTexture @@ -465,7 +465,7 @@ public slots: */ bool setDisplayTexture(const QString& name); - /**jsdoc + /*@jsdoc * Checks if a 2D point is within the desktop window if in desktop mode, or the drawable area of the HUD overlay if in HMD * mode. * @function Window.isPointOnDesktopWindow @@ -474,21 +474,21 @@ public slots: */ bool isPointOnDesktopWindow(QVariant point); - /**jsdoc + /*@jsdoc * Gets the size of the drawable area of the Interface window if in desktop mode or the HMD rendering surface if in HMD mode. * @function Window.getDeviceSize * @returns {Vec2} The width and height of the Interface window or HMD rendering surface, in pixels. */ glm::vec2 getDeviceSize() const; - /**jsdoc + /*@jsdoc * Gets the last domain connection error when a connection is refused. * @function Window.getLastDomainConnectionError * @returns {Window.ConnectionRefusedReason} Integer number that enumerates the last domain connection refused. */ int getLastDomainConnectionError() const; - /**jsdoc + /*@jsdoc * Opens a non-modal message box that can have a variety of button combinations. See also, * {@link Window.updateMessageBox|updateMessageBox} and {@link Window.closeMessageBox|closeMessageBox}. * @function Window.openMessageBox @@ -520,7 +520,7 @@ public slots: */ int openMessageBox(QString title, QString text, int buttons, int defaultButton); - /**jsdoc + /*@jsdoc * Opens a URL in the Interface window or other application, depending on the URL's scheme. The following schemes are * supported: *

    @@ -534,7 +534,7 @@ public slots: */ void openUrl(const QUrl& url); - /**jsdoc + /*@jsdoc * Opens an Android activity and optionally return back to the scene when the activity is completed. Android only. * @function Window.openAndroidActivity * @param {string} activityName - The name of the activity to open: one of "Home", "Login", or @@ -544,7 +544,7 @@ public slots: */ void openAndroidActivity(const QString& activityName, const bool backToScene); - /**jsdoc + /*@jsdoc * Updates the content of a message box that was opened with {@link Window.openMessageBox|openMessageBox}. * @function Window.updateMessageBox * @param {number} id - The ID of the message box. @@ -556,28 +556,28 @@ public slots: */ void updateMessageBox(int id, QString title, QString text, int buttons, int defaultButton); - /**jsdoc + /*@jsdoc * Closes a message box that was opened with {@link Window.openMessageBox|openMessageBox}. * @function Window.closeMessageBox * @param {number} id - The ID of the message box. */ void closeMessageBox(int id); - /**jsdoc + /*@jsdoc * @function Window.domainLoadingProgress * @returns {number} Progress. * @deprecated This function is deprecated and will be removed. */ float domainLoadingProgress(); - /**jsdoc + /*@jsdoc * Gets the number of display plugins currently available. * @function Window.getDisplayPluginCount * @returns {number} The number of display plugins currently available. */ int getDisplayPluginCount(); - /**jsdoc + /*@jsdoc * Gets the name of a display plugin. * @function Window.getDisplayPluginName * @param {number} index - The index of the display plugin. Must be less than the value returned by @@ -590,7 +590,7 @@ public slots: */ QString getDisplayPluginName(int index); - /**jsdoc + /*@jsdoc * Checks whether a display plugin is an HMD. * @function Window.isDisplayPluginHmd * @param {number} index - The index of the display plugin. Must be less than the value returned by @@ -599,7 +599,7 @@ public slots: */ bool isDisplayPluginHmd(int index); - /**jsdoc + /*@jsdoc * Gets the index of the currently active display plugin. * @function Window.getActiveDisplayPlugin * @returns {number} The index of the currently active display plugin. The first display plugin has an index of @@ -607,7 +607,7 @@ public slots: */ int getActiveDisplayPlugin(); - /**jsdoc + /*@jsdoc * Sets the currently active display plugin. * @function Window.setActiveDisplayPlugin * @param {number} index - The index of the display plugin. Must be less than the value returned by @@ -615,7 +615,7 @@ public slots: */ void setActiveDisplayPlugin(int index); - /**jsdoc + /*@jsdoc * Opens an Interface web browser window. * @function Window.openWebBrowser * @param {string} [url=""] - The URL of the web page to display. @@ -630,7 +630,7 @@ private slots: signals: - /**jsdoc + /*@jsdoc * Triggered when you change the domain you're visiting. *

    Warning: Is not emitted if you go to a domain that isn't running.

    * @function Window.domainChanged @@ -645,7 +645,7 @@ signals: */ void domainChanged(QUrl domainURL); - /**jsdoc + /*@jsdoc * Triggered when you try to navigate to a *.json, *.svo, or *.svo.json URL in a Web browser within Interface. * @function Window.svoImportRequested * @param {string} url - The URL of the file to import. @@ -653,7 +653,7 @@ signals: */ void svoImportRequested(const QString& url); - /**jsdoc + /*@jsdoc * Triggered when you try to visit a domain but are refused connection. * @function Window.domainConnectionRefused * @param {string} reasonMessage - A description of the refusal. @@ -663,7 +663,7 @@ signals: */ void domainConnectionRefused(const QString& reasonMessage, int reasonCode, const QString& extraInfo); - /**jsdoc + /*@jsdoc * Triggered when you try to visit a domain but are redirected into the error state. * @function Window.redirectErrorStateChanged * @param {boolean} isInErrorState - true if the user has been redirected to the error URL, false @@ -672,7 +672,7 @@ signals: */ void redirectErrorStateChanged(bool isInErrorState); - /**jsdoc + /*@jsdoc * Triggered when the interstitial mode changes. * @function Window.interstitialModeChanged * @param {boolean} interstitialMode - true if the interstitial graphics are displayed when the domain is @@ -681,7 +681,7 @@ signals: */ void interstitialModeChanged(bool interstitialMode); - /**jsdoc + /*@jsdoc * Triggered when a still snapshot has been taken by calling {@link Window.takeSnapshot|takeSnapshot} with * includeAnimated = false or {@link Window.takeSecondaryCameraSnapshot|takeSecondaryCameraSnapshot}. * @function Window.stillSnapshotTaken @@ -692,7 +692,7 @@ signals: */ void stillSnapshotTaken(const QString& pathStillSnapshot, bool notify); - /**jsdoc + /*@jsdoc * Triggered when a still 360° snapshot has been taken by calling * {@link Window.takeSecondaryCamera360Snapshot|takeSecondaryCamera360Snapshot}. * @function Window.snapshot360Taken @@ -703,7 +703,7 @@ signals: */ void snapshot360Taken(const QString& path360Snapshot, bool notify); - /**jsdoc + /*@jsdoc * Triggered when a snapshot submitted via {@link Window.shareSnapshot|shareSnapshot} is ready for sharing. The snapshot * may then be shared via the {@link Account.metaverseServerURL} Web API. * @function Window.snapshotShared @@ -714,7 +714,7 @@ signals: */ void snapshotShared(bool isError, const QString& reply); - /**jsdoc + /*@jsdoc * Triggered when the snapshot images have been captured by {@link Window.takeSnapshot|takeSnapshot} and the GIF is * starting to be processed. * @function Window.processingGifStarted @@ -723,7 +723,7 @@ signals: */ void processingGifStarted(const QString& pathStillSnapshot); - /**jsdoc + /*@jsdoc * Triggered when a GIF has been prepared of the snapshot images captured by {@link Window.takeSnapshot|takeSnapshot}. * @function Window.processingGifCompleted * @param {string} pathAnimatedSnapshot - The path and name of the moving snapshot GIF file. @@ -732,7 +732,7 @@ signals: void processingGifCompleted(const QString& pathAnimatedSnapshot); - /**jsdoc + /*@jsdoc * Triggered when you've successfully made a user connection. * @function Window.connectionAdded * @param {string} message - A description of the success. @@ -740,7 +740,7 @@ signals: */ void connectionAdded(const QString& connectionName); - /**jsdoc + /*@jsdoc * Triggered when you failed to make a user connection. * @function Window.connectionError * @param {string} message - A description of the error. @@ -748,7 +748,7 @@ signals: */ void connectionError(const QString& errorString); - /**jsdoc + /*@jsdoc * Triggered when a message is announced by {@link Window.displayAnnouncement|displayAnnouncement}. * @function Window.announcement * @param {string} message - The message text. @@ -757,7 +757,7 @@ signals: void announcement(const QString& message); - /**jsdoc + /*@jsdoc * Triggered when the user closes a message box that was opened with {@link Window.openMessageBox|openMessageBox}. * @function Window.messageBoxClosed * @param {number} id - The ID of the message box that was closed. @@ -767,7 +767,7 @@ signals: */ void messageBoxClosed(int id, int button); - /**jsdoc + /*@jsdoc * Triggered when the user chooses a directory in a {@link Window.browseDirAsync|browseDirAsync} dialog. * @function Window.browseDirChanged * @param {string} directory - The directory the user chose in the dialog. @@ -775,7 +775,7 @@ signals: */ void browseDirChanged(QString browseDir); - /**jsdoc + /*@jsdoc * Triggered when the user chooses an asset in a {@link Window.browseAssetsAsync|browseAssetsAsync} dialog. * @function Window.assetsDirChanged * @param {string} asset - The path and name of the asset the user chose in the dialog. @@ -783,7 +783,7 @@ signals: */ void assetsDirChanged(QString assetsDir); - /**jsdoc + /*@jsdoc * Triggered when the user specifies a file in a {@link Window.saveAsync|saveAsync} dialog. * @function Window.saveFileChanged * @param {string} filename - The path and name of the file that the user specified in the dialog. @@ -791,7 +791,7 @@ signals: */ void saveFileChanged(QString filename); - /**jsdoc + /*@jsdoc * Triggered when the user chooses a file in a {@link Window.browseAsync|browseAsync} dialog. * @function Window.browseChanged * @param {string} filename - The path and name of the file the user chose in the dialog. @@ -799,7 +799,7 @@ signals: */ void browseChanged(QString filename); - /**jsdoc + /*@jsdoc * Triggered when the user OKs a {@link Window.promptAsync|promptAsync} dialog. * @function Window.promptTextChanged * @param {string} text - The text the user entered in the dialog. @@ -808,7 +808,7 @@ signals: void promptTextChanged(QString text); - /**jsdoc + /*@jsdoc * Triggered when the position or size of the Interface window changes. * @function Window.geometryChanged * @param {Rect} geometry - The position and size of the drawable area of the Interface window. @@ -823,7 +823,7 @@ signals: void geometryChanged(QRect geometry); - /**jsdoc + /*@jsdoc * Triggered when "minimized" state of the Interface window changes. * @function Window.minimizedChanged * @param {boolean} isMinimized - true if the Interface window is minimized, false if it isn't. diff --git a/interface/src/ui/AvatarInputs.h b/interface/src/ui/AvatarInputs.h index 3b0e57d037..ba9d06c11b 100644 --- a/interface/src/ui/AvatarInputs.h +++ b/interface/src/ui/AvatarInputs.h @@ -23,7 +23,7 @@ class AvatarInputs : public QObject { Q_OBJECT HIFI_QML_DECL - /**jsdoc + /*@jsdoc * The AvatarInputs API provides facilities to manage user inputs. * * @namespace AvatarInputs @@ -61,7 +61,7 @@ class AvatarInputs : public QObject { public: static AvatarInputs* getInstance(); - /**jsdoc + /*@jsdoc * Converts non-linear audio loudness to a linear audio level. * @function AvatarInputs.loudnessToAudioLevel * @param {number} loudness - The non-linear audio loudness. @@ -78,7 +78,7 @@ public: public slots: - /**jsdoc + /*@jsdoc * Sets whether or not the microphone mute button and audio level meter is shown. * @function AvatarInputs.setShowAudioTools * @param {boolean} showAudioTools - true to show the microphone mute button and audio level meter, @@ -86,7 +86,7 @@ public slots: */ void setShowAudioTools(bool showAudioTools); - /**jsdoc + /*@jsdoc * Sets whether or not the privacy shield button is shown. * @function AvatarInputs.setShowBubbleTools * @param {boolean} showBubbleTools - true to show the privacy shield button, false to hide it. @@ -95,28 +95,28 @@ public slots: signals: - /**jsdoc + /*@jsdoc * Triggered when webcam face tracking is enabled or disabled. * @deprecated This signal is deprecated and has been removed. * @function AvatarInputs.cameraEnabledChanged * @returns {Signal} */ - /**jsdoc + /*@jsdoc * Triggered when webcam face tracking is muted (temporarily disabled) or unmuted. * @deprecated This signal is deprecated and has been removed. * @function AvatarInputs.cameraMutedChanged * @returns {Signal} */ - /**jsdoc + /*@jsdoc * Triggered when the display mode changes between desktop and HMD. * @function AvatarInputs.isHMDChanged * @returns {Signal} */ void isHMDChanged(); - /**jsdoc + /*@jsdoc * Triggered when the visibility of the microphone mute button and audio level meter changes. * @function AvatarInputs.showAudioToolsChanged * @param {boolean} show - true if the microphone mute button and audio level meter are shown, @@ -125,7 +125,7 @@ signals: */ void showAudioToolsChanged(bool show); - /**jsdoc + /*@jsdoc * Triggered when the visibility of the privacy shield button changes. * @function AvatarInputs.showBubbleToolsChanged * @param {boolean} show - true if the privacy shield UI button is shown, false if @@ -134,7 +134,7 @@ signals: */ void showBubbleToolsChanged(bool show); - /**jsdoc + /*@jsdoc * Triggered when another user enters the privacy shield. * @function AvatarInputs.avatarEnteredIgnoreRadius * @param {QUuid} avatarID - The session ID of the user that entered the privacy shield. @@ -146,7 +146,7 @@ signals: */ void avatarEnteredIgnoreRadius(QUuid avatarID); - /**jsdoc + /*@jsdoc * Triggered when another user leaves the privacy shield. *

    Note: Currently doesn't work.

    * @function AvatarInputs.avatarLeftIgnoreRadius @@ -156,7 +156,7 @@ signals: */ void avatarLeftIgnoreRadius(QUuid avatarID); - /**jsdoc + /*@jsdoc * Triggered when the privacy shield is enabled or disabled. * @function AvatarInputs.ignoreRadiusEnabledChanged * @param {boolean} enabled - true if the privacy shield is enabled, false if it is disabled. @@ -164,7 +164,7 @@ signals: */ void ignoreRadiusEnabledChanged(bool enabled); - /**jsdoc + /*@jsdoc * Triggered when another user enters the privacy shield. * @function AvatarInputs.enteredIgnoreRadiusChanged * @returns {Signal} @@ -173,13 +173,13 @@ signals: protected: - /**jsdoc + /*@jsdoc * Resets sensors, audio, avatar animations, and the avatar rig. * @function AvatarInputs.resetSensors */ Q_INVOKABLE void resetSensors(); - /**jsdoc + /*@jsdoc * Toggles the muting (temporary disablement) of webcam face tracking on/off. *

    Deprecated: This function is deprecated and has been removed.

    * @function AvatarInputs.toggleCameraMute diff --git a/interface/src/ui/InteractiveWindow.cpp b/interface/src/ui/InteractiveWindow.cpp index daf80acf00..d1bdbb1652 100644 --- a/interface/src/ui/InteractiveWindow.cpp +++ b/interface/src/ui/InteractiveWindow.cpp @@ -128,7 +128,7 @@ void InteractiveWindow::emitMainWindowResizeEvent() { emit qApp->getWindow()->windowGeometryChanged(qApp->getWindow()->geometry()); } -/**jsdoc +/*@jsdoc * Property values used when creating an InteractiveWindow. * @typedef {object} InteractiveWindow.WindowProperties * @property {string} [title="InteractiveWindow] - The title of the window. @@ -151,7 +151,7 @@ void InteractiveWindow::emitMainWindowResizeEvent() { * pixels. Excludes the window frame. * @property {boolean} [isFullScreenWindow] - true to make the window full screen. */ -/**jsdoc +/*@jsdoc *

    A set of flags customizing InteractiveWindow controls. The value is constructed by using the | * (bitwise OR) operator on the individual flag values..

    *
@@ -212,7 +212,7 @@ InteractiveWindow::InteractiveWindow(const QString& sourceUrl, const QVariantMap //add any whitelisted callbacks OffscreenUi::applyWhiteList(sourceUrl, quickView->rootContext()); - /**jsdoc + /*@jsdoc * Configures how a NATIVE window is displayed. * @typedef {object} InteractiveWindow.PresentationWindowInfo * @property {InteractiveWindow.DockArea} dockArea - The edge of the Interface window to dock to. diff --git a/interface/src/ui/InteractiveWindow.h b/interface/src/ui/InteractiveWindow.h index 7c8897059f..744875fef5 100644 --- a/interface/src/ui/InteractiveWindow.h +++ b/interface/src/ui/InteractiveWindow.h @@ -55,7 +55,7 @@ signals: namespace InteractiveWindowEnums { Q_NAMESPACE - /**jsdoc + /*@jsdoc *

A set of flags controlling InteractiveWindow behavior. The value is constructed by using the * | (bitwise OR) operator on the individual flag values.

*
@@ -76,7 +76,7 @@ namespace InteractiveWindowEnums { }; Q_ENUM_NS(InteractiveWindowFlags); - /**jsdoc + /*@jsdoc *

A display mode for an InteractiveWindow.

*
* @@ -97,7 +97,7 @@ namespace InteractiveWindowEnums { }; Q_ENUM_NS(InteractiveWindowPresentationMode); - /**jsdoc + /*@jsdoc *

A docking location of an InteractiveWindow.

*
* @@ -120,7 +120,7 @@ namespace InteractiveWindowEnums { }; Q_ENUM_NS(DockArea); - /**jsdoc + /*@jsdoc *

The anchor for a relative position of an InteractiveWindow.

*
* @@ -150,7 +150,7 @@ namespace InteractiveWindowEnums { using namespace InteractiveWindowEnums; -/**jsdoc +/*@jsdoc * An InteractiveWindow can display either inside Interface or in its own window separate from the Interface * window. The window content is defined by a QML file, which can optionally include a WebView control that embeds * an HTML web page. (The WebView control is defined by a "WebView.qml" file included in the Interface install.) @@ -229,7 +229,7 @@ private: public slots: - /**jsdoc + /*@jsdoc * Sends a message to the QML page. To receive the message, the QML page must implement a function: *
function fromScript(message) {
      *   ...
@@ -278,7 +278,7 @@ public slots:
     // Scripts can use this to send a message to the QML object
     void sendToQml(const QVariant& message);
 
-    /**jsdoc
+    /*@jsdoc
      * Sends a message to an embedded HTML web page. To receive the message, the HTML page's script must connect to the 
      * EventBridge that is automatically provided for the script:
      * 
EventBridge.scriptEventReceived.connect(function(message) {
@@ -290,26 +290,26 @@ public slots:
     // QmlWindow content may include WebView requiring EventBridge.
     void emitScriptEvent(const QVariant& scriptMessage);
 
-    /**jsdoc
+    /*@jsdoc
      * @function InteractiveWindow.emitWebEvent
      * @param {object|string} message - Message.
      * @deprecated This function is deprecated and will be removed.
      */
     void emitWebEvent(const QVariant& webMessage);
 
-    /**jsdoc
+    /*@jsdoc
      * Closes the window. It can then no longer be used.
      * @function InteractiveWindow.close
      */
     Q_INVOKABLE void close();
 
-    /**jsdoc
+    /*@jsdoc
      * Makes the window visible and raises it to the top.
      * @function InteractiveWindow.show
      */
     Q_INVOKABLE void show();
 
-    /**jsdoc
+    /*@jsdoc
      * Raises the window to the top.
      * @function InteractiveWindow.raise
      */
@@ -317,49 +317,49 @@ public slots:
 
 signals:
 
-    /**jsdoc
+    /*@jsdoc
      * Triggered when the window is made visible or invisible, or is closed.
      * @function InteractiveWindow.visibleChanged
      * @returns {Signal}
      */
     void visibleChanged();
 
-    /**jsdoc
+    /*@jsdoc
      * Triggered when the window's position changes.
      * @function InteractiveWindow.positionChanged
      * @returns {Signal}
      */
     void positionChanged();
 
-    /**jsdoc
+    /*@jsdoc
      * Triggered when the window's size changes.
      * @function InteractiveWindow.sizeChanged
      * @returns {Signal}
      */
     void sizeChanged();
 
-    /**jsdoc
+    /*@jsdoc
      * Triggered when the window's presentation mode changes.
      * @function InteractiveWindow.presentationModeChanged
      * @returns {Signal}
      */
     void presentationModeChanged();
 
-    /**jsdoc
+    /*@jsdoc
      * Triggered when window's title changes.
      * @function InteractiveWindow.titleChanged
      * @returns {Signal}
      */
     void titleChanged();
 
-    /**jsdoc
+    /*@jsdoc
      * Triggered when the window is closed.
      * @function InteractiveWindow.closed
      * @returns {Signal}
      */
     void closed();
 
-    /**jsdoc
+    /*@jsdoc
      * Triggered when a message from the QML page is received. The QML page can send a message (string or object) by calling:
      * 
sendToScript(message);
* @function InteractiveWindow.fromQml @@ -369,7 +369,7 @@ signals: // Scripts can connect to this signal to receive messages from the QML object void fromQml(const QVariant& message); - /**jsdoc + /*@jsdoc * @function InteractiveWindow.scriptEventReceived * @param {object} message - Message. * @returns {Signal} @@ -378,7 +378,7 @@ signals: // InteractiveWindow content may include WebView requiring EventBridge. void scriptEventReceived(const QVariant& message); - /**jsdoc + /*@jsdoc * Triggered when a message from an embedded HTML web page is received. The HTML web page can send a message by calling: *
EventBridge.emitWebEvent(message);
* @function InteractiveWindow.webEventReceived @@ -388,7 +388,7 @@ signals: void webEventReceived(const QVariant& message); protected slots: - /**jsdoc + /*@jsdoc * @function InteractiveWindow.qmlToScript * @param {object} message - Message. * @deprecated This method is deprecated and will be removed. diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index 9c53060f31..c2f1abdd94 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -250,9 +250,9 @@ void setupPreferences() { { auto getter = []()->bool { return !Menu::getInstance()->isOptionChecked(MenuOption::DisableActivityLogger); }; auto setter = [](bool value) { Menu::getInstance()->setIsOptionChecked(MenuOption::DisableActivityLogger, !value); }; - preferences->addPreference(new CheckPreference("Privacy", "Send data - High Fidelity uses information provided by your " + preferences->addPreference(new CheckPreference("Privacy", "Send data - Vircadia uses information provided by your " "client to improve the product through the logging of errors, tracking of usage patterns, " - "installation and system details. By allowing High Fidelity to collect this information " + "installation and system details. By allowing Vircadia to collect this information " "you are helping to improve the product. ", getter, setter)); } @@ -362,10 +362,10 @@ void setupPreferences() { auto getter = [myAvatar]()->float { return qApp->getCamera().getSensitivity(); }; auto setter = [myAvatar](float value) { qApp->getCamera().setSensitivity(value); }; auto preference = new SpinnerSliderPreference(VR_MOVEMENT, "Camera Sensitivity", getter, setter); - preference->setMin(0.01f); + preference->setMin(0.1f); preference->setMax(5.0f); - preference->setStep(0.1); - preference->setDecimals(2); + preference->setStep(0.1f); + preference->setDecimals(1); preferences->addPreference(preference); } { @@ -385,7 +385,7 @@ void setupPreferences() { preference->setMin(6.0f); preference->setMax(30.0f); preference->setStep(1); - preference->setDecimals(2); + preference->setDecimals(0); preferences->addPreference(preference); } { @@ -465,8 +465,8 @@ void setupPreferences() { auto preference = new SpinnerPreference(VR_MOVEMENT, "User real-world height (meters)", getter, setter); preference->setMin(1.0f); preference->setMax(2.2f); - preference->setDecimals(3); - preference->setStep(0.001f); + preference->setDecimals(2); + preference->setStep(0.01f); preferences->addPreference(preference); } @@ -478,7 +478,7 @@ void setupPreferences() { preference->setMin(1.0f); preference->setMax(360.0f); preference->setStep(1); - preference->setDecimals(1); + preference->setDecimals(0); preferences->addPreference(preference); } { @@ -488,7 +488,7 @@ void setupPreferences() { preference->setMin(1.0f); preference->setMax(360.0f); preference->setStep(1); - preference->setDecimals(1); + preference->setDecimals(0); preferences->addPreference(preference); } diff --git a/interface/src/ui/Snapshot.cpp b/interface/src/ui/Snapshot.cpp index 4882d6e5da..6266e24d40 100644 --- a/interface/src/ui/Snapshot.cpp +++ b/interface/src/ui/Snapshot.cpp @@ -47,7 +47,7 @@ const QString FILENAME_PATH_FORMAT = "vircadia-snap-by-%1-on-%2.jpg"; const QString DATETIME_FORMAT = "yyyy-MM-dd_hh-mm-ss"; const QString SNAPSHOTS_DIRECTORY = "Snapshots"; -const QString URL = "highfidelity_url"; +const QString URL = "vircadia_url"; static const int SNAPSHOT_360_TIMER_INTERVAL = 350; static const QList SUPPORTED_IMAGE_FORMATS = { "jpg", "jpeg", "png" }; diff --git a/interface/src/ui/Snapshot.h b/interface/src/ui/Snapshot.h index 73c5a8e3c5..9cff0a6f8b 100644 --- a/interface/src/ui/Snapshot.h +++ b/interface/src/ui/Snapshot.h @@ -37,7 +37,7 @@ private: }; -/**jsdoc +/*@jsdoc * The Snapshot API provides access to the path that snapshots are saved to. This path is that provided in * Settings > General > Snapshots. Snapshots may be taken using Window API functions such as * {@link Window.takeSnapshot}. @@ -67,7 +67,7 @@ public: signals: - /**jsdoc + /*@jsdoc * Triggered when the path that snapshots are saved to is changed. * @function Snapshot.snapshotLocationSet * @param {string} location - The new snapshots location. @@ -82,14 +82,14 @@ signals: public slots: - /**jsdoc + /*@jsdoc * Gets the path that snapshots are saved to. * @function Snapshot.getSnapshotsLocation * @returns {string} The path to save snapshots to. */ Q_INVOKABLE QString getSnapshotsLocation(); - /**jsdoc + /*@jsdoc * Sets the path that snapshots are saved to. * @function Snapshot.setSnapshotsLocation * @param {String} location - The path to save snapshots to. diff --git a/interface/src/ui/Stats.h b/interface/src/ui/Stats.h index ebd65de612..a3366904bd 100644 --- a/interface/src/ui/Stats.h +++ b/interface/src/ui/Stats.h @@ -23,7 +23,7 @@ public: \ private: \ type _##name{ initialValue }; -/**jsdoc +/*@jsdoc * The Stats API provides statistics on Interface and domain operation, per the statistics overlay. * *

Note: This API is primarily an internal diagnostics tool and is provided "as is".

@@ -626,7 +626,7 @@ public: public slots: - /**jsdoc + /*@jsdoc * Updates statistics to make current values available to scripts even though the statistics overlay may not be displayed. * (Many statistics values are normally updated only if the statistics overlay is displayed.) *

Note: Not all statistics values are updated when the statistics overlay isn't displayed or @@ -655,364 +655,364 @@ signals: // Signals for properties... - /**jsdoc + /*@jsdoc * Triggered when the value of the expanded property changes. * @function Stats.expandedChanged * @returns {Signal} */ void expandedChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the timingExpanded property changes. * @function Stats.timingExpandedChanged * @returns {Signal} */ void timingExpandedChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the serverCount property changes. * @function Stats.serverCountChanged * @returns {Signal} */ void serverCountChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the renderrate property changes. * @function Stats.renderrateChanged * @returns {Signal} */ void renderrateChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the presentrate property changes. * @function Stats.presentrateChanged * @returns {Signal} */ void presentrateChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the stutterrate property changes. * @function Stats.stutterrateChanged * @returns {Signal} */ void stutterrateChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the appdropped property changes. * @function Stats.appdroppedChanged * @returns {Signal} */ void appdroppedChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the longsubmits property changes. * @function Stats.longsubmitsChanged * @returns {Signal} */ void longsubmitsChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the longrenders property changes. * @function Stats.longrendersChanged * @returns {Signal} */ void longrendersChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the longframes property changes. * @function Stats.longframesChanged * @returns {Signal} */ void longframesChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the presentnewrate property changes. * @function Stats.presentnewrateChanged * @returns {Signal} */ void presentnewrateChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the presentdroprate property changes. * @function Stats.presentdroprateChanged * @returns {Signal} */ void presentdroprateChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the gameLoopRate property changes. * @function Stats.gameLoopRateChanged * @returns {Signal} */ void gameLoopRateChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the avatarCount property changes. * @function Stats.avatarCountChanged * @returns {Signal} */ void avatarCountChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the refreshRateTarget property changes. * @function Stats.refreshRateTargetChanged * @returns {Signal} */ void refreshRateTargetChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the refreshRateMode property changes. * @function Stats.refreshRateModeChanged * @returns {Signal} */ void refreshRateModeChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the refreshRateRegime property changes. * @function Stats.refreshRateRegimeChanged * @returns {Signal} */ void refreshRateRegimeChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the uxMode property changes. * @function Stats.uxModeChanged * @returns {Signal} */ void uxModeChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the heroAvatarCount property changes. * @function Stats.heroAvatarCountChanged * @returns {Signal} */ void heroAvatarCountChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the physicsObjectCount property changes. * @function Stats.physicsObjectCountChanged * @returns {Signal} */ void physicsObjectCountChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the updatedAvatarCount property changes. * @function Stats.updatedAvatarCountChanged * @returns {Signal} */ void updatedAvatarCountChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the updatedHeroAvatarCount property changes. * @function Stats.updatedHeroAvatarCountChanged * @returns {Signal} */ void updatedHeroAvatarCountChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the notUpdatedAvatarCount property changes. * @function Stats.notUpdatedAvatarCountChanged * @returns {Signal} */ void notUpdatedAvatarCountChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the packetInCount property changes. * @function Stats.packetInCountChanged * @returns {Signal} */ void packetInCountChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the packetOutCount property changes. * @function Stats.packetOutCountChanged * @returns {Signal} */ void packetOutCountChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the mbpsIn property changes. * @function Stats.mbpsInChanged * @returns {Signal} */ void mbpsInChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the mbpsOut property changes. * @function Stats.mbpsOutChanged * @returns {Signal} */ void mbpsOutChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the assetMbpsIn property changes. * @function Stats.assetMbpsInChanged * @returns {Signal} */ void assetMbpsInChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the assetMbpsOut property changes. * @function Stats.assetMbpsOutChanged * @returns {Signal} */ void assetMbpsOutChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the audioPing property changes. * @function Stats.audioPingChanged * @returns {Signal} */ void audioPingChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the avatarPing property changes. * @function Stats.avatarPingChanged * @returns {Signal} */ void avatarPingChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the entitiesPing property changes. * @function Stats.entitiesPingChanged * @returns {Signal} */ void entitiesPingChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the assetPing property changes. * @function Stats.assetPingChanged * @returns {Signal} */ void assetPingChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the messagePing property changes. * @function Stats.messagePingChanged * @returns {Signal} */ void messagePingChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the position property changes. * @function Stats.positionChanged * @returns {Signal} */ void positionChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the speed property changes. * @function Stats.speedChanged * @returns {Signal} */ void speedChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the yaw property changes. * @function Stats.yawChanged * @returns {Signal} */ void yawChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the avatarMixerInKbps property changes. * @function Stats.avatarMixerInKbpsChanged * @returns {Signal} */ void avatarMixerInKbpsChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the avatarMixerInPps property changes. * @function Stats.avatarMixerInPpsChanged * @returns {Signal} */ void avatarMixerInPpsChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the avatarMixerOutKbps property changes. * @function Stats.avatarMixerOutKbpsChanged * @returns {Signal} */ void avatarMixerOutKbpsChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the avatarMixerOutPps property changes. * @function Stats.avatarMixerOutPpsChanged * @returns {Signal} */ void avatarMixerOutPpsChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the myAvatarSendRate property changes. * @function Stats.myAvatarSendRateChanged * @returns {Signal} */ void myAvatarSendRateChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the audioMixerInKbps property changes. * @function Stats.audioMixerInKbpsChanged * @returns {Signal} */ void audioMixerInKbpsChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the audioMixerInPps property changes. * @function Stats.audioMixerInPpsChanged * @returns {Signal} */ void audioMixerInPpsChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the audioMixerOutKbps property changes. * @function Stats.audioMixerOutKbpsChanged * @returns {Signal} */ void audioMixerOutKbpsChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the audioMixerOutPps property changes. * @function Stats.audioMixerOutPpsChanged * @returns {Signal} */ void audioMixerOutPpsChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the audioMixerKbps property changes. * @function Stats.audioMixerKbpsChanged * @returns {Signal} */ void audioMixerKbpsChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the audioMixerPps property changes. * @function Stats.audioMixerPpsChanged * @returns {Signal} */ void audioMixerPpsChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the audioOutboundPPS property changes. * @function Stats.audioOutboundPPSChanged * @returns {Signal} */ void audioOutboundPPSChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the audioSilentOutboundPPS property changes. * @function Stats.audioSilentOutboundPPSChanged * @returns {Signal} */ void audioSilentOutboundPPSChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the audioInboundPPS property changes. * @function Stats.audioInboundPPSChanged * @returns {Signal} */ void audioInboundPPSChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the audioAudioInboundPPS property changes. * @function Stats.audioAudioInboundPPSChanged * @returns {Signal} @@ -1021,504 +1021,504 @@ signals: */ void audioAudioInboundPPSChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the audioSilentInboundPPS property changes. * @function Stats.audioSilentInboundPPSChanged * @returns {Signal} */ void audioSilentInboundPPSChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the audioPacketLoss property changes. * @function Stats.audioPacketLossChanged * @returns {Signal} */ void audioPacketLossChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the audioCodec property changes. * @function Stats.audioCodecChanged * @returns {Signal} */ void audioCodecChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the audioNoiseGate property changes. * @function Stats.audioNoiseGateChanged * @returns {Signal} */ void audioNoiseGateChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the audioInjectors property changes. * @function Stats.audioInjectorsChanged * @returns {Signal} */ void audioInjectorsChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the entityPacketsInKbps property changes. * @function Stats.entityPacketsInKbpsChanged * @returns {Signal} */ void entityPacketsInKbpsChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the downloads property changes. * @function Stats.downloadsChanged * @returns {Signal} */ void downloadsChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the downloadLimit property changes. * @function Stats.downloadLimitChanged * @returns {Signal} */ void downloadLimitChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the downloadsPending property changes. * @function Stats.downloadsPendingChanged * @returns {Signal} */ void downloadsPendingChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the downloadUrls property changes. * @function Stats.downloadUrlsChanged * @returns {Signal} */ void downloadUrlsChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the processing property changes. * @function Stats.processingChanged * @returns {Signal} */ void processingChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the processingPending property changes. * @function Stats.processingPendingChanged * @returns {Signal} */ void processingPendingChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the triangles property changes. * @function Stats.trianglesChanged * @returns {Signal} */ void trianglesChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the drawcalls property changes. * @function Stats.drawcallsChanged * @returns {Signal} */ void drawcallsChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the materialSwitches property changes. * @function Stats.materialSwitchesChanged * @returns {Signal} */ void materialSwitchesChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the itemConsidered property changes. * @function Stats.itemConsideredChanged * @returns {Signal} */ void itemConsideredChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the itemOutOfView property changes. * @function Stats.itemOutOfViewChanged * @returns {Signal} */ void itemOutOfViewChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the itemTooSmall property changes. * @function Stats.itemTooSmallChanged * @returns {Signal} */ void itemTooSmallChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the itemRendered property changes. * @function Stats.itemRenderedChanged * @returns {Signal} */ void itemRenderedChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the shadowConsidered property changes. * @function Stats.shadowConsideredChanged * @returns {Signal} */ void shadowConsideredChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the shadowOutOfView property changes. * @function Stats.shadowOutOfViewChanged * @returns {Signal} */ void shadowOutOfViewChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the shadowTooSmall property changes. * @function Stats.shadowTooSmallChanged * @returns {Signal} */ void shadowTooSmallChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the shadowRendered property changes. * @function Stats.shadowRenderedChanged * @returns {Signal} */ void shadowRenderedChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the sendingMode property changes. * @function Stats.sendingModeChanged * @returns {Signal} */ void sendingModeChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the packetStats property changes. * @function Stats.packetStatsChanged * @returns {Signal} */ void packetStatsChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the lodAngle property changes. * @function Stats.lodAngleChanged * @returns {Signal} */ void lodAngleChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the lodTargetFramerate property changes. * @function Stats.lodTargetFramerateChanged * @returns {Signal} */ void lodTargetFramerateChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the lodStatus property changes. * @function Stats.lodStatusChanged * @returns {Signal} */ void lodStatusChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the numEntityUpdates property changes. * @function Stats.numEntityUpdatesChanged * @returns {Signal} */ void numEntityUpdatesChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the numNeededEntityUpdates property changes. * @function Stats.numNeededEntityUpdatesChanged * @returns {Signal} */ void numNeededEntityUpdatesChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the timingStats property changes. * @function Stats.timingStatsChanged * @returns {Signal} */ void timingStatsChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the gameUpdateStats property changes. * @function Stats.gameUpdateStatsChanged * @returns {Signal} */ void gameUpdateStatsChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the serverElements property changes. * @function Stats.serverElementsChanged * @returns {Signal} */ void serverElementsChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the serverInternal property changes. * @function Stats.serverInternalChanged * @returns {Signal} */ void serverInternalChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the serverLeaves property changes. * @function Stats.serverLeavesChanged * @returns {Signal} */ void serverLeavesChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the localElements property changes. * @function Stats.localElementsChanged * @returns {Signal} */ void localElementsChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the localInternal property changes. * @function Stats.localInternalChanged * @returns {Signal} */ void localInternalChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the localLeaves property changes. * @function Stats.localLeavesChanged * @returns {Signal} */ void localLeavesChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the rectifiedTextureCount property changes. * @function Stats.rectifiedTextureCountChanged * @returns {Signal} */ void rectifiedTextureCountChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the decimatedTextureCount property changes. * @function Stats.decimatedTextureCountChanged * @returns {Signal} */ void decimatedTextureCountChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the gpuBuffers property changes. * @function Stats.gpuBuffersChanged * @returns {Signal} */ void gpuBuffersChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the gpuBufferMemory property changes. * @function Stats.gpuBufferMemoryChanged * @returns {Signal} */ void gpuBufferMemoryChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the gpuTextures property changes. * @function Stats.gpuTexturesChanged * @returns {Signal} */ void gpuTexturesChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the glContextSwapchainMemory property changes. * @function Stats.glContextSwapchainMemoryChanged * @returns {Signal} */ void glContextSwapchainMemoryChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the qmlTextureMemory property changes. * @function Stats.qmlTextureMemoryChanged * @returns {Signal} */ void qmlTextureMemoryChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the texturePendingTransfers property changes. * @function Stats.texturePendingTransfersChanged * @returns {Signal} */ void texturePendingTransfersChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the gpuTextureMemory property changes. * @function Stats.gpuTextureMemoryChanged * @returns {Signal} */ void gpuTextureMemoryChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the gpuTextureResidentMemory property changes. * @function Stats.gpuTextureResidentMemoryChanged * @returns {Signal} */ void gpuTextureResidentMemoryChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the gpuTextureFramebufferMemory property changes. * @function Stats.gpuTextureFramebufferMemoryChanged * @returns {Signal} */ void gpuTextureFramebufferMemoryChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the gpuTextureResourceMemory property changes. * @function Stats.gpuTextureResourceMemoryChanged * @returns {Signal} */ void gpuTextureResourceMemoryChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the gpuTextureResourceIdealMemory property changes. * @function Stats.gpuTextureResourceIdealMemoryChanged * @returns {Signal} */ void gpuTextureResourceIdealMemoryChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the gpuTextureResourcePopulatedMemory property changes. * @function Stats.gpuTextureResourcePopulatedMemoryChanged * @returns {Signal} */ void gpuTextureResourcePopulatedMemoryChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the gpuTextureExternalMemory property changes. * @function Stats.gpuTextureExternalMemoryChanged * @returns {Signal} */ void gpuTextureExternalMemoryChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the gpuTextureMemoryPressureState property changes. * @function Stats.gpuTextureMemoryPressureStateChanged * @returns {Signal} */ void gpuTextureMemoryPressureStateChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the gpuFreeMemory property changes. * @function Stats.gpuFreeMemoryChanged * @returns {Signal} */ void gpuFreeMemoryChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the gpuFrameSize property changes. * @function Stats.gpuFrameSizeChanged * @returns {Signal} */ void gpuFrameSizeChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the gpuFrameTime property changes. * @function Stats.gpuFrameTimeChanged * @returns {Signal} */ void gpuFrameTimeChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the gpuFrameTimePerPixel property changes. * @function Stats.gpuFrameTimePerPixelChanged * @returns {Signal} */ void gpuFrameTimePerPixelChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the batchFrameTime property changes. * @function Stats.batchFrameTimeChanged * @returns {Signal} */ void batchFrameTimeChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the engineFrameTime property changes. * @function Stats.engineFrameTimeChanged * @returns {Signal} */ void engineFrameTimeChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the avatarSimulationTime property changes. * @function Stats.avatarSimulationTimeChanged * @returns {Signal} */ void avatarSimulationTimeChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the stylusPicksCount property changes. * @function Stats.stylusPicksCountChanged * @returns {Signal} */ void stylusPicksCountChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the rayPicksCount property changes. * @function Stats.rayPicksCountChanged * @returns {Signal} */ void rayPicksCountChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the parabolaPicksCount property changes. * @function Stats.parabolaPicksCountChanged * @returns {Signal} */ void parabolaPicksCountChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the collisionPicksCount property changes. * @function Stats.collisionPicksCountChanged * @returns {Signal} */ void collisionPicksCountChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the stylusPicksUpdated property changes. * @function Stats.stylusPicksUpdatedChanged * @returns {Signal} */ void stylusPicksUpdatedChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the rayPicksUpdated property changes. * @function Stats.rayPicksUpdatedChanged * @returns {Signal} */ void rayPicksUpdatedChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the parabolaPicksUpdated property changes. * @function Stats.parabolaPicksUpdatedChanged * @returns {Signal} */ void parabolaPicksUpdatedChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the collisionPicksUpdated property changes. * @function Stats.collisionPicksUpdatedChanged * @returns {Signal} */ void collisionPicksUpdatedChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the mainThreadQueueDepth property changes. * @function Stats.mainThreadQueueDepthChanged * @returns {Signal} */ void mainThreadQueueDepthChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the nodeListThreadQueueDepth property changes. * @function Stats.nodeListThreadQueueDepth * @returns {Signal} */ void nodeListThreadQueueDepthChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the eventQueueDebuggingOn property changes. * @function Stats.eventQueueDebuggingOnChanged * @returns {Signal} @@ -1528,7 +1528,7 @@ signals: // Stats.qml signals: shouldn't be in the API. - /**jsdoc + /*@jsdoc * Triggered when the value of the bgColor property changes. * @function Stats.bgColorChanged * @returns {Signal} @@ -1538,7 +1538,7 @@ signals: // QQuickItem signals: shouldn't be in the API. - /**jsdoc + /*@jsdoc * Triggered when the value of the activeFocus property changes. * @function Stats.activeFocusChanged * @param {boolean} activeFocus - Active focus. @@ -1546,7 +1546,7 @@ signals: * @deprecated This signal is deprecated and will be removed. */ - /**jsdoc + /*@jsdoc * Triggered when the value of the activeFocusOnTab property changes. * @function Stats.activeFocusOnTabChanged * @param {boolean} activeFocusOnTab - Active focus on tab. @@ -1554,7 +1554,7 @@ signals: * @deprecated This signal is deprecated and will be removed. */ - /**jsdoc + /*@jsdoc * Triggered when the value of the antialiasing property changes. * @function Stats.antialiasingChanged * @param {boolean} antialiasing - Antialiasing. @@ -1562,7 +1562,7 @@ signals: * @deprecated This signal is deprecated and will be removed. */ - /**jsdoc + /*@jsdoc * Triggered when the value of the baselineOffset property changes. * @function Stats.baselineOffsetChanged * @param {number} baselineOffset - Baseline offset. @@ -1570,14 +1570,14 @@ signals: * @deprecated This signal is deprecated and will be removed. */ - /**jsdoc + /*@jsdoc * Triggered when the value of the children property changes. * @function Stats.childrenChanged * @returns {Signal} * @deprecated This signal is deprecated and will be removed. */ - /**jsdoc + /*@jsdoc * Triggered when the position and size of the rectangle containing the children changes. * @function Stats.childrenRectChanged * @param {Rect} childrenRect - Children rect. @@ -1586,7 +1586,7 @@ signals: */ - /**jsdoc + /*@jsdoc * Triggered when the value of the clip property changes. * @function Stats.clipChanged * @param {boolean} clip - Clip. @@ -1594,21 +1594,21 @@ signals: * @deprecated This signal is deprecated and will be removed. */ - /**jsdoc + /*@jsdoc * Triggered when the value of the containmentMask property changes. * @function Stats.containmentMaskChanged * @returns {Signal} * @deprecated This signal is deprecated and will be removed. */ - /**jsdoc + /*@jsdoc * Triggered when the value of the enabled property changes. * @function Stats.enabledChanged * @returns {Signal} * @deprecated This signal is deprecated and will be removed. */ - /**jsdoc + /*@jsdoc * Triggered when the value of the focus property changes. * @function Stats.focusChanged * @param {boolean} focus - Focus. @@ -1616,35 +1616,35 @@ signals: * @deprecated This signal is deprecated and will be removed. */ - /**jsdoc + /*@jsdoc * Triggered when the value of the height property changes. * @function Stats.heightChanged * @returns {Signal} * @deprecated This signal is deprecated and will be removed. */ - /**jsdoc + /*@jsdoc * Triggered when the value of the implicitHeight property changes. * @function Stats.implicitHeightChanged * @returns {Signal} * @deprecated This signal is deprecated and will be removed. */ - /**jsdoc + /*@jsdoc * Triggered when the value of the implicitWidth property changes. * @function Stats.implicitWidthChanged * @returns {Signal} * @deprecated This signal is deprecated and will be removed. */ - /**jsdoc + /*@jsdoc * Triggered when the value of the opacity property changes. * @function Stats.opacityChanged * @returns {Signal} * @deprecated This signal is deprecated and will be removed. */ - /**jsdoc + /*@jsdoc * Triggered when the parent item changes. * @function Stats.parentChanged * @param {object} parent - Parent. @@ -1652,21 +1652,21 @@ signals: * @deprecated This signal is deprecated and will be removed. */ - /**jsdoc + /*@jsdoc * Triggered when the value of the rotation property changes. * @function Stats.rotationChanged * @returns {Signal} * @deprecated This signal is deprecated and will be removed. */ - /**jsdoc + /*@jsdoc * Triggered when the value of the scale property changes. * @function Stats.scaleChanged * @returns {Signal} * @deprecated This signal is deprecated and will be removed. */ - /**jsdoc + /*@jsdoc * Triggered when the value of the smooth property changes. * @function Stats.smoothChanged * @param {boolean} smooth - Smooth. @@ -1674,7 +1674,7 @@ signals: * @deprecated This signal is deprecated and will be removed. */ - /**jsdoc + /*@jsdoc * Triggered when the value of the state property changes. * @function Stats.stateChanged * @paramm {string} state - State. @@ -1682,7 +1682,7 @@ signals: * @deprecated This signal is deprecated and will be removed. */ - /**jsdoc + /*@jsdoc * Triggered when the value of the transformOrigin property changes. * @function Stats.transformOriginChanged * @param {number} transformOrigin - Transformm origin. @@ -1690,28 +1690,28 @@ signals: * @deprecated This signal is deprecated and will be removed. */ - /**jsdoc + /*@jsdoc * Triggered when the value of the visibleChanged property changes. * @function Stats.visibleChanged * @returns {Signal} * @deprecated This signal is deprecated and will be removed. */ - /**jsdoc + /*@jsdoc * Triggered when the list of visible children changes. * @function Stats.visibleChildrenChanged * @returns {Signal} * @deprecated This signal is deprecated and will be removed. */ - /**jsdoc + /*@jsdoc * Triggered when the value of the width property changes. * @function Stats.widthChanged * @returns {Signal} * @deprecated This signal is deprecated and will be removed. */ - /**jsdoc + /*@jsdoc * Triggered when the stats window changes. * @function Stats.windowChanged * @param {object} window - Window. @@ -1719,21 +1719,21 @@ signals: * @deprecated This signal is deprecated and will be removed. */ - /**jsdoc + /*@jsdoc * Triggered when the value of the x property changes. * @function Stats.xChanged * @returns {Signal} * @deprecated This signal is deprecated and will be removed. */ - /**jsdoc + /*@jsdoc * Triggered when the value of the y property changes. * @function Stats.yChanged * @returns {Signal} * @deprecated This signal is deprecated and will be removed. */ - /**jsdoc + /*@jsdoc * Triggered when the value of the z property changes. * @function Stats.zChanged * @returns {Signal} @@ -1743,7 +1743,7 @@ signals: // QQuickItem methods: shouldn't be in the API. - /**jsdoc + /*@jsdoc * @function Stats.childAt * @param {number} x - X. * @param {number} y - Y. @@ -1751,20 +1751,20 @@ signals: * @deprecated This method is deprecated and will be removed. */ - /**jsdoc + /*@jsdoc * @function Stats.contains * @param {Vec2} point - Point * @returns {boolean} * @deprecated This method is deprecated and will be removed. */ - /**jsdoc + /*@jsdoc * @function Stats.forceActiveFocus * @param {number} [reason=7] - Reason * @deprecated This method is deprecated and will be removed. */ - /**jsdoc + /*@jsdoc * @function Stats.grabToImage * @param {object} callback - Callback. * @param {Size} [targetSize=0,0] - Target size. @@ -1772,38 +1772,38 @@ signals: * @deprecated This method is deprecated and will be removed. */ - /**jsdoc + /*@jsdoc * @function Stats.mapFromGlobal * @param {object} global - Global. * @deprecated This method is deprecated and will be removed. */ - /**jsdoc + /*@jsdoc * @function Stats.mapFromItem * @param {object} item - Item. * @deprecated This method is deprecated and will be removed. */ - /**jsdoc + /*@jsdoc * @function Stats.mapToGlobal * @param {object} global - Global. * @deprecated This method is deprecated and will be removed. */ - /**jsdoc + /*@jsdoc * @function Stats.mapToItem * @param {object} item - Item * @deprecated This method is deprecated and will be removed. */ - /**jsdoc + /*@jsdoc * @function Stats.nextItemInFocusChain * @param {boolean} [forward=true] - Forward. * @returns {object} * @deprecated This method is deprecated and will be removed. */ - /**jsdoc + /*@jsdoc * @function Stats.update * @deprecated This method is deprecated and will be removed. */ diff --git a/interface/src/ui/overlays/ContextOverlayInterface.h b/interface/src/ui/overlays/ContextOverlayInterface.h index 5d11b254fc..b3bf15d523 100644 --- a/interface/src/ui/overlays/ContextOverlayInterface.h +++ b/interface/src/ui/overlays/ContextOverlayInterface.h @@ -29,7 +29,7 @@ #include "EntityTree.h" #include "ContextOverlayLogging.h" -/**jsdoc +/*@jsdoc * The ContextOverlay API manages the "i" proof-of-provenance context overlay that appears on Marketplace items * when a user right-clicks them. * @@ -61,7 +61,7 @@ class ContextOverlayInterface : public QObject, public Dependency { public: ContextOverlayInterface(); - /**jsdoc + /*@jsdoc * Gets the ID of the entity that the context overlay is currently displayed for. * @function ContextOverlay.getCurrentEntityWithContextOverlay * @returns {Uuid} - The ID of the entity that the context overlay is currently displayed for, null if the @@ -76,7 +76,7 @@ public: bool getIsInMarketplaceInspectionMode() { return _isInMarketplaceInspectionMode; } void setIsInMarketplaceInspectionMode(bool mode) { _isInMarketplaceInspectionMode = mode; } - /**jsdoc + /*@jsdoc * Initiates a check on an avatar entity belongs to the user wearing it. The result is returned via * {@link WalletScriptingInterface.ownershipVerificationSuccess} or * {@link WalletScriptingInterface.ownershipVerificationFailed}. @@ -90,7 +90,7 @@ public: EntityPropertyFlags getEntityPropertyFlags() { return _entityPropertyFlags; } signals: - /**jsdoc + /*@jsdoc * Triggered when the user clicks on the context overlay. * @function ContextOverlay.contextOverlayClicked * @param {Uuid} id - The ID of the entity that the context overlay is for. @@ -104,7 +104,7 @@ signals: public slots: - /**jsdoc + /*@jsdoc * @function ContextOverlay.clickDownOnEntity * @param {Uuid} id - Entity ID. * @param {PointerEvent} event - Pointer event. @@ -113,7 +113,7 @@ public slots: // FIXME: Method shouldn't be in the API. void clickDownOnEntity(const EntityItemID& entityItemID, const PointerEvent& event); - /**jsdoc + /*@jsdoc * @function ContextOverlay.mouseReleaseOnEntity * @param {Uuid} id - Entity ID. * @param {PointerEvent} event - Pointer event. @@ -122,7 +122,7 @@ public slots: // FIXME: Method shouldn't be in the API. void mouseReleaseOnEntity(const EntityItemID& entityItemID, const PointerEvent& event); - /**jsdoc + /*@jsdoc * Displays or deletes the context overlay as appropriate for the target entity and a pointer event: the context overlay * must be enabled and the pointer event must be a right-click; if so, then any current context overlay is deleted, and if * the target entity should have a context overlay then it is displayed. @@ -134,7 +134,7 @@ public slots: */ bool createOrDestroyContextOverlay(const EntityItemID& entityItemID, const PointerEvent& event); - /**jsdoc + /*@jsdoc * Deletes the context overlay and removes the entity highlight, if shown. * @function ContextOverlay.destroyContextOverlay * @param {Uuid} entityID - The ID of the entity. @@ -145,7 +145,7 @@ public slots: bool destroyContextOverlay(const EntityItemID& entityItemID, const PointerEvent& event); bool destroyContextOverlay(const EntityItemID& entityItemID); - /**jsdoc + /*@jsdoc * @function ContextOverlay.contextOverlays_hoverEnterOverlay * @param {Uuid} id - Overlay ID. * @param {PointerEvent} event - Pointer event. @@ -154,7 +154,7 @@ public slots: // FIXME: Method shouldn't be in the API. void contextOverlays_hoverEnterOverlay(const QUuid& id, const PointerEvent& event); - /**jsdoc + /*@jsdoc * @function ContextOverlay.contextOverlays_hoverLeaveOverlay * @param {Uuid} id - Overlay ID. * @param {PointerEvent} event - Pointer event. @@ -163,7 +163,7 @@ public slots: // FIXME: Method shouldn't be in the API. void contextOverlays_hoverLeaveOverlay(const QUuid& id, const PointerEvent& event); - /**jsdoc + /*@jsdoc * @function ContextOverlay.contextOverlays_hoverEnterEntity * @param {Uuid} id - Entity ID. * @param {PointerEvent} event - Pointer event. @@ -172,7 +172,7 @@ public slots: // FIXME: Method shouldn't be in the API. void contextOverlays_hoverEnterEntity(const EntityItemID& entityID, const PointerEvent& event); - /**jsdoc + /*@jsdoc * @function ContextOverlay.contextOverlays_hoverLeaveEntity * @param {Uuid} id - Entity ID. * @param {PointerEvent} event - Pointer event. @@ -181,7 +181,7 @@ public slots: // FIXME: Method shouldn't be in the API. void contextOverlays_hoverLeaveEntity(const EntityItemID& entityID, const PointerEvent& event); - /**jsdoc + /*@jsdoc * Checks with a context overlay should be displayed for an entity — in particular, whether the item has a non-empty * certificate ID. * @function ContextOverlay.contextOverlayFilterPassed diff --git a/interface/src/ui/overlays/Overlay2D.cpp b/interface/src/ui/overlays/Overlay2D.cpp index 91c7198e49..c75eba052a 100644 --- a/interface/src/ui/overlays/Overlay2D.cpp +++ b/interface/src/ui/overlays/Overlay2D.cpp @@ -25,7 +25,7 @@ AABox Overlay2D::getBounds() const { // JSDoc for copying to @typedefs of overlay types that inherit Overlay2D. // QmlOverlay-derived classes don't support getProperty(). -/**jsdoc +/*@jsdoc * @property {Rect} bounds - The position and size of the rectangle. Write-only. * @property {number} x - Integer left, x-coordinate value = bounds.x. Write-only. * @property {number} y - Integer top, y-coordinate value = bounds.y. Write-only. diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index e9e310e68b..071da3696d 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -1329,7 +1329,7 @@ QVector Overlays::findOverlays(const glm::vec3& center, float radius) { return result; } -/**jsdoc +/*@jsdoc *

An overlay may be one of the following types:

*
* @@ -1397,7 +1397,7 @@ QVector Overlays::findOverlays(const glm::vec3& center, float radius) { * @typedef {string} Overlays.OverlayType */ -/**jsdoc +/*@jsdoc * Different overlay types have different properties: some common to all overlays (listed in the table) and some specific to * each {@link Overlays.OverlayType|OverlayType} (linked to below). *

3D overlays are local entities, internally, so they also support the relevant entity's properties.

@@ -1422,7 +1422,7 @@ QVector Overlays::findOverlays(const glm::vec3& center, float radius) { * @see {@link Overlays.OverlayProperties-Circle3D|OverlayProperties-Circle3D} — Deprecated. */ -/**jsdoc +/*@jsdoc * The "image" {@link Overlays.OverlayType|OverlayType} is for 2D images. * It has properties in addition to the common {@link Overlays.OverlayProperties|OverlayProperties}. * @typedef {object} Overlays.OverlayProperties-Image @@ -1442,7 +1442,7 @@ QVector Overlays::findOverlays(const glm::vec3& center, float radius) { * 1.0. Write-only. */ -/**jsdoc +/*@jsdoc * The "text" {@link Overlays.OverlayType|OverlayType} is for 2D text. * It has properties in addition to the common {@link Overlays.OverlayProperties|OverlayProperties}. * @typedef {object} Overlays.OverlayProperties-Text @@ -1468,7 +1468,7 @@ QVector Overlays::findOverlays(const glm::vec3& center, float radius) { * Write-only. */ -/**jsdoc +/*@jsdoc * The "rectangle" {@link Overlays.OverlayType|OverlayType} is for 2D rectangles. * It has properties in addition to the common {@link Overlays.OverlayProperties|OverlayProperties}. * @typedef {object} Overlays.OverlayProperties-Rectangle @@ -1487,7 +1487,7 @@ QVector Overlays::findOverlays(const glm::vec3& center, float radius) { * Write-only. */ -/**jsdoc +/*@jsdoc * The "cube" {@link Overlays.OverlayType|OverlayType} is for 3D cubes. * It has properties in addition to the common {@link Overlays.OverlayProperties|OverlayProperties}. * It additionally has properties per the {@link Entities.EntityProperties-Box|Box} entity. @@ -1535,7 +1535,7 @@ QVector Overlays::findOverlays(const glm::vec3& center, float radius) { * than a joint. */ -/**jsdoc +/*@jsdoc * The "sphere" {@link Overlays.OverlayType|OverlayType} is for 3D spheres. * It has properties in addition to the common {@link Overlays.OverlayProperties|OverlayProperties}. * It additionally has properties per the {@link Entities.EntityProperties-Sphere|Sphere} entity. @@ -1583,7 +1583,7 @@ QVector Overlays::findOverlays(const glm::vec3& center, float radius) { * than a joint. */ -/**jsdoc +/*@jsdoc * The "rectangle3D" {@link Overlays.OverlayType|OverlayType} is for 3D rectangles. * It has properties in addition to the common {@link Overlays.OverlayProperties|OverlayProperties}. * It additionally has properties per the {@link Entities.EntityProperties-Shape|Shape} entity, with the shape @@ -1632,7 +1632,7 @@ QVector Overlays::findOverlays(const glm::vec3& center, float radius) { * than a joint. */ -/**jsdoc +/*@jsdoc *

A "shape" {@link Overlays.OverlayType|OverlayType} may display as one of the following geometrical * shapes:

*
@@ -1659,7 +1659,7 @@ QVector Overlays::findOverlays(const glm::vec3& center, float radius) { * @typedef {string} Overlays.Shape */ -/**jsdoc +/*@jsdoc * The "shape" {@link Overlays.OverlayType|OverlayType} is for 3D shapes. * It has properties in addition to the common {@link Overlays.OverlayProperties|OverlayProperties}. * It additionally has properties per the {@link Entities.EntityProperties-Shape|Shape} entity. @@ -1709,7 +1709,7 @@ QVector Overlays::findOverlays(const glm::vec3& center, float radius) { * @property {Overlays.Shape} shape=Hexagon - The geometrical shape of the overlay. */ -/**jsdoc +/*@jsdoc * The "model" {@link Overlays.OverlayType|OverlayType} is for 3D models. * It has properties in addition to the common {@link Overlays.OverlayProperties|OverlayProperties}. * It additionally has properties per the {@link Entities.EntityProperties-Model|Model} entity. @@ -1750,7 +1750,7 @@ QVector Overlays::findOverlays(const glm::vec3& center, float radius) { * @property {Entities.AnimationProperties} animationSettings - An animation to play on the model. */ -/**jsdoc +/*@jsdoc * The "text3D" {@link Overlays.OverlayType|OverlayType} is for 3D text. * It has properties in addition to the common {@link Overlays.OverlayProperties|OverlayProperties}. * It additionally has properties per the {@link Entities.EntityProperties-Text|Text} entity. @@ -1796,7 +1796,7 @@ QVector Overlays::findOverlays(const glm::vec3& center, float radius) { * than a joint. */ -/**jsdoc +/*@jsdoc * The "image3D" {@link Overlays.OverlayType|OverlayType} is for 3D images. * It has properties in addition to the common {@link Overlays.OverlayProperties|OverlayProperties}. * It additionally has properties per the {@link Entities.EntityProperties-Image|Image} entity. @@ -1842,7 +1842,7 @@ QVector Overlays::findOverlays(const glm::vec3& center, float radius) { * @property {string} url - The URL of the image to display. */ -/**jsdoc +/*@jsdoc * The "web3d" {@link Overlays.OverlayType|OverlayType} is for 3D web surfaces. * It has properties in addition to the common {@link Overlays.OverlayProperties|OverlayProperties}. * It additionally has properties per the {@link Entities.EntityProperties-Web|Web} entity. @@ -1888,7 +1888,7 @@ QVector Overlays::findOverlays(const glm::vec3& center, float radius) { * @property {string} url - The URL of the web page to display. */ -/**jsdoc +/*@jsdoc * The "line3d" {@link Overlays.OverlayType|OverlayType} is for 3D lines. * It has properties in addition to the common {@link Overlays.OverlayProperties|OverlayProperties}. * It additionally has properties per the {@link Entities.EntityProperties-PolyLine|PolyLine} entity. @@ -1956,7 +1956,7 @@ QVector Overlays::findOverlays(const glm::vec3& center, float radius) { * property to retrieve its value instead.

*/ -/**jsdoc +/*@jsdoc * The "grid" {@link Overlays.OverlayType|OverlayType} is for 3D grids. * It has properties in addition to the common {@link Overlays.OverlayProperties|OverlayProperties}. * It additionally has properties per the {@link Entities.EntityProperties-Grid|Grid} entity. @@ -2000,7 +2000,7 @@ QVector Overlays::findOverlays(const glm::vec3& center, float radius) { * than a joint. */ -/**jsdoc +/*@jsdoc * The "circle3d" {@link Overlays.OverlayType|OverlayType} is for 3D circles. * It has properties in addition to the common {@link Overlays.OverlayProperties|OverlayProperties}. * It additionally has properties per the {@link Entities.EntityProperties-Gizmo|Gizmo} entity, with the diff --git a/interface/src/ui/overlays/Overlays.h b/interface/src/ui/overlays/Overlays.h index a6d4414bec..b7e471bb1a 100644 --- a/interface/src/ui/overlays/Overlays.h +++ b/interface/src/ui/overlays/Overlays.h @@ -30,7 +30,7 @@ class PickRay; -/**jsdoc +/*@jsdoc * The result of a {@link PickRay} search using {@link Overlays.findRayIntersection|findRayIntersection}. * @typedef {object} Overlays.RayToOverlayIntersectionResult * @property {boolean} intersects - true if the {@link PickRay} intersected with a 3D overlay, otherwise @@ -67,7 +67,7 @@ public: QVariantMap extraInfo; }; -/**jsdoc +/*@jsdoc * The Overlays API provides facilities to create and interact with overlays. These are 2D and 3D objects visible * only to yourself and that aren't persisted to the domain. They are used for UI. * @@ -123,7 +123,7 @@ public: mutable QScriptEngine _scriptEngine; public slots: - /**jsdoc + /*@jsdoc * Adds an overlay to the scene. * @function Overlays.addOverlay * @param {Overlays.OverlayType} type - The type of the overlay to add. @@ -139,7 +139,7 @@ public slots: */ QUuid addOverlay(const QString& type, const QVariant& properties); - /**jsdoc + /*@jsdoc * Creates a clone of an existing overlay (or entity). *

Note: For cloning behavior of 3D overlays and entities, see {@link Entities.cloneEntity}.

* @function Overlays.cloneOverlay @@ -148,7 +148,7 @@ public slots: */ QUuid cloneOverlay(const QUuid& id); - /**jsdoc + /*@jsdoc * Edits an overlay's (or entity's) properties. * @function Overlays.editOverlay * @param {Uuid} id - The ID of the overlay (or entity) to edit. @@ -170,7 +170,7 @@ public slots: */ bool editOverlay(const QUuid& id, const QVariant& properties); - /**jsdoc + /*@jsdoc * Edits the properties of multiple overlays (or entities). * @function Overlays.editOverlays * @param propertiesById {object.} - An object with overlay (or entity) IDs as keys and @@ -198,14 +198,14 @@ public slots: */ bool editOverlays(const QVariant& propertiesById); - /**jsdoc + /*@jsdoc * Deletes an overlay (or entity). * @function Overlays.deleteOverlay * @param {Uuid} id - The ID of the overlay (or entity) to delete. */ void deleteOverlay(const QUuid& id); - /**jsdoc + /*@jsdoc * Gets the type of an overlay. * @function Overlays.getOverlayType * @param {Uuid} id - The ID of the overlay to get the type of. @@ -222,7 +222,7 @@ public slots: */ QString getOverlayType(const QUuid& id); - /**jsdoc + /*@jsdoc * Gets an overlay's (or entity's) script object. In particular, this is useful for accessing a * {@link Overlays.OverlayProperties-Web3D|"web3d"} overlay's EventBridge script object to * exchange messages with the web page script. @@ -292,7 +292,7 @@ public slots: */ QObject* getOverlayObject(const QUuid& id); - /**jsdoc + /*@jsdoc * Gets the ID of the 2D overlay at a particular point on the desktop screen or HUD surface. * @function Overlays.getOverlayAtPoint * @param {Vec2} point - The point to check for an overlay. @@ -311,7 +311,7 @@ public slots: */ QUuid getOverlayAtPoint(const glm::vec2& point); - /**jsdoc + /*@jsdoc * Gets a specified property value of a 3D overlay (or entity). *

Note: 2D overlays' property values cannot be retrieved.

* @function Overlays.getProperty @@ -331,7 +331,7 @@ public slots: */ QVariant getProperty(const QUuid& id, const QString& property); - /**jsdoc + /*@jsdoc * Gets specified property values of a 3D overlay (or entity). *

Note: 2D overlays' property values cannot be retrieved.

* @function Overlays.getProperties @@ -351,7 +351,7 @@ public slots: */ QVariantMap getProperties(const QUuid& id, const QStringList& properties); - /**jsdoc + /*@jsdoc * Gets the values of multiple overlays' (or entities') properties. * @function Overlays.getOverlaysProperties * @param propertiesById {object.>} - An object with overlay (or entity) IDs as keys and arrays of the @@ -379,7 +379,7 @@ public slots: */ QVariantMap getOverlaysProperties(const QVariant& overlaysProperties); - /**jsdoc + /*@jsdoc * Finds the closest 3D overlay (or local entity) intersected by a {@link PickRay}. * @function Overlays.findRayIntersection * @param {PickRay} pickRay - The PickRay to use for finding overlays. @@ -416,7 +416,7 @@ public slots: bool visibleOnly = false, bool collidableOnly = false); - /**jsdoc + /*@jsdoc * Gets a list of visible 3D overlays (local entities) with bounding boxes that touch a search sphere. * @function Overlays.findOverlays * @param {Vec3} center - The center of the search sphere. @@ -444,7 +444,7 @@ public slots: */ QVector findOverlays(const glm::vec3& center, float radius); - /**jsdoc + /*@jsdoc * Checks whether an overlay's (or entity's) assets have been loaded. For example, for an * {@link Overlays.OverlayProperties-Image|"image"} overlay, the result indicates whether its image has been * loaded. @@ -464,7 +464,7 @@ public slots: */ bool isLoaded(const QUuid& id); - /**jsdoc + /*@jsdoc * Calculates the size of some text in a text overlay (or entity). The overlay (or entity) need not be set visible. *

Note: The size of text in a 3D overlay (or entity) cannot be calculated immediately after the * overlay (or entity) is created; a short delay is required while the overlay (or entity) finishes being created.

@@ -489,21 +489,21 @@ public slots: */ QSizeF textSize(const QUuid& id, const QString& text); - /**jsdoc + /*@jsdoc * Gets the width of the Interface window or HUD surface. * @function Overlays.width * @returns {number} The width, in pixels, of the Interface window if in desktop mode or the HUD surface if in HMD mode. */ float width(); - /**jsdoc + /*@jsdoc * Gets the height of the Interface window or HUD surface. * @function Overlays.height * @returns {number} The height, in pixels, of the Interface window if in desktop mode or the HUD surface if in HMD mode. */ float height(); - /**jsdoc + /*@jsdoc * Checks if an overlay (or entity) exists. * @function Overlays.isAddedOverlay * @param {Uuid} id - The ID of the overlay (or entity) to check. @@ -511,7 +511,7 @@ public slots: */ bool isAddedOverlay(const QUuid& id); - /**jsdoc + /*@jsdoc * Generates a mouse press event on an overlay (or local entity). * @function Overlays.sendMousePressOnOverlay * @param {Uuid} id - The ID of the overlay (or local entity) to generate a mouse press event on. @@ -551,7 +551,7 @@ public slots: */ void sendMousePressOnOverlay(const QUuid& id, const PointerEvent& event); - /**jsdoc + /*@jsdoc * Generates a mouse release event on an overlay (or local entity). * @function Overlays.sendMouseReleaseOnOverlay * @param {Uuid} id - The ID of the overlay (or local entity) to generate a mouse release event on. @@ -559,7 +559,7 @@ public slots: */ void sendMouseReleaseOnOverlay(const QUuid& id, const PointerEvent& event); - /**jsdoc + /*@jsdoc * Generates a mouse move event on an overlay (or local entity). * @function Overlays.sendMouseMoveOnOverlay * @param {Uuid} id - The ID of the overlay (or local entity) to generate a mouse move event on. @@ -567,7 +567,7 @@ public slots: */ void sendMouseMoveOnOverlay(const QUuid& id, const PointerEvent& event); - /**jsdoc + /*@jsdoc * Generates a hover enter event on an overlay (or local entity). * @function Overlays.sendHoverEnterOverlay * @param {Uuid} id - The ID of the overlay (or local entity) to generate a hover enter event on. @@ -575,7 +575,7 @@ public slots: */ void sendHoverEnterOverlay(const QUuid& id, const PointerEvent& event); - /**jsdoc + /*@jsdoc * Generates a hover over event on an overlay (or entity). * @function Overlays.sendHoverOverOverlay * @param {Uuid} id - The ID of the overlay (or local entity) to generate a hover over event on. @@ -583,7 +583,7 @@ public slots: */ void sendHoverOverOverlay(const QUuid& id, const PointerEvent& event); - /**jsdoc + /*@jsdoc * Generates a hover leave event on an overlay (or local entity). * @function Overlays.sendHoverLeaveOverlay * @param {Uuid} id - The ID of the overlay (or local entity) to generate a hover leave event on. @@ -591,7 +591,7 @@ public slots: */ void sendHoverLeaveOverlay(const QUuid& id, const PointerEvent& event); - /**jsdoc + /*@jsdoc * Gets the ID of the {@link Overlays.OverlayProperties-Web3D|"web3d"} overlay * ({@link Entities.EntityProperties-Web|Web} entity) that has keyboard focus. * @function Overlays.getKeyboardFocusOverlay @@ -600,7 +600,7 @@ public slots: */ QUuid getKeyboardFocusOverlay() { return DependencyManager::get()->getKeyboardFocusEntity(); } - /**jsdoc + /*@jsdoc * Sets the {@link Overlays.OverlayProperties-Web3D|"web3d"} overlay * ({@link Entities.EntityProperties-Web|Web} entity) that has keyboard focus. * @function Overlays.setKeyboardFocusOverlay @@ -611,7 +611,7 @@ public slots: void setKeyboardFocusOverlay(const QUuid& id) { DependencyManager::get()->setKeyboardFocusEntity(id); } signals: - /**jsdoc + /*@jsdoc * Triggered when an overlay (or entity) is deleted. * @function Overlays.overlayDeleted * @param {Uuid} id - The ID of the overlay (or entity) that was deleted. @@ -634,7 +634,7 @@ signals: */ void overlayDeleted(const QUuid& id); - /**jsdoc + /*@jsdoc * Triggered when a mouse press event occurs on an overlay. Only occurs for 3D overlays (unless you use * {@link Overlays.sendMousePressOnOverlay|sendMousePressOnOverlay} for a 2D overlay). * @function Overlays.mousePressOnOverlay @@ -658,7 +658,7 @@ signals: */ void mousePressOnOverlay(const QUuid& id, const PointerEvent& event); - /**jsdoc + /*@jsdoc * Triggered when a mouse double press event occurs on an overlay. Only occurs for 3D overlays. * @function Overlays.mouseDoublePressOnOverlay * @param {Uuid} id - The ID of the overlay the mouse double press event occurred on. @@ -667,7 +667,7 @@ signals: */ void mouseDoublePressOnOverlay(const QUuid& id, const PointerEvent& event); - /**jsdoc + /*@jsdoc * Triggered when a mouse release event occurs on an overlay. Only occurs for 3D overlays (unless you use * {@link Overlays.sendMouseReleaseOnOverlay|sendMouseReleaseOnOverlay} for a 2D overlay). * @function Overlays.mouseReleaseOnOverlay @@ -677,7 +677,7 @@ signals: */ void mouseReleaseOnOverlay(const QUuid& id, const PointerEvent& event); - /**jsdoc + /*@jsdoc * Triggered when a mouse move event occurs on an overlay. Only occurs for 3D overlays (unless you use * {@link Overlays.sendMouseMoveOnOverlay|sendMouseMoveOnOverlay} for a 2D overlay). * @function Overlays.mouseMoveOnOverlay @@ -687,21 +687,21 @@ signals: */ void mouseMoveOnOverlay(const QUuid& id, const PointerEvent& event); - /**jsdoc + /*@jsdoc * Triggered when a mouse press event occurs on something other than a 3D overlay. * @function Overlays.mousePressOffOverlay * @returns {Signal} */ void mousePressOffOverlay(); - /**jsdoc + /*@jsdoc * Triggered when a mouse double press event occurs on something other than a 3D overlay. * @function Overlays.mouseDoublePressOffOverlay * @returns {Signal} */ void mouseDoublePressOffOverlay(); - /**jsdoc + /*@jsdoc * Triggered when a mouse cursor starts hovering over an overlay. Only occurs for 3D overlays (unless you use * {@link Overlays.sendHoverEnterOverlay|sendHoverEnterOverlay} for a 2D overlay). * @function Overlays.hoverEnterOverlay @@ -723,7 +723,7 @@ signals: */ void hoverEnterOverlay(const QUuid& id, const PointerEvent& event); - /**jsdoc + /*@jsdoc * Triggered when a mouse cursor continues hovering over an overlay. Only occurs for 3D overlays (unless you use * {@link Overlays.sendHoverOverOverlay|sendHoverOverOverlay} for a 2D overlay). * @function Overlays.hoverOverOverlay @@ -733,7 +733,7 @@ signals: */ void hoverOverOverlay(const QUuid& id, const PointerEvent& event); - /**jsdoc + /*@jsdoc * Triggered when a mouse cursor finishes hovering over an overlay. Only occurs for 3D overlays (unless you use * {@link Overlays.sendHoverLeaveOverlay|sendHoverLeaveOverlay} for a 2D overlay). * @function Overlays.hoverLeaveOverlay diff --git a/libraries/animation/CMakeLists.txt b/libraries/animation/CMakeLists.txt index 1ab54ed342..d962d9e222 100644 --- a/libraries/animation/CMakeLists.txt +++ b/libraries/animation/CMakeLists.txt @@ -1,6 +1,6 @@ set(TARGET_NAME animation) setup_hifi_library(Network Script) -link_hifi_libraries(shared graphics fbx) +link_hifi_libraries(shared graphics model-serializers) include_hifi_library_headers(networking) include_hifi_library_headers(gpu) include_hifi_library_headers(hfm) diff --git a/libraries/animation/src/AnimInverseKinematics.cpp b/libraries/animation/src/AnimInverseKinematics.cpp index 2fd52ee036..095e8333ee 100644 --- a/libraries/animation/src/AnimInverseKinematics.cpp +++ b/libraries/animation/src/AnimInverseKinematics.cpp @@ -22,6 +22,7 @@ #include "AnimationLogging.h" #include "CubicHermiteSpline.h" #include "AnimUtil.h" +#include "AnimSkeleton.h" static const int MAX_TARGET_MARKERS = 30; static const float JOINT_CHAIN_INTERP_TIME = 0.5f; @@ -66,7 +67,7 @@ AnimInverseKinematics::IKTargetVar::IKTargetVar(const QString& jointNameIn, cons poleVectorVar(poleVectorVarIn), weight(weightIn), numFlexCoefficients(flexCoefficientsIn.size()), - jointIndex(-1) + jointIndex(AnimSkeleton::INVALID_JOINT_INDEX) { numFlexCoefficients = std::min(numFlexCoefficients, (size_t)MAX_FLEX_COEFFICIENTS); for (size_t i = 0; i < numFlexCoefficients; i++) { @@ -172,14 +173,14 @@ bool debounceJointWarnings() { void AnimInverseKinematics::computeTargets(const AnimVariantMap& animVars, std::vector& targets, const AnimPoseVec& underPoses) { - _hipsTargetIndex = -1; + _hipsTargetIndex = AnimSkeleton::INVALID_JOINT_INDEX; targets.reserve(_targetVarVec.size()); for (auto& targetVar : _targetVarVec) { // update targetVar jointIndex cache - if (targetVar.jointIndex == -1) { + if (targetVar.jointIndex == AnimSkeleton::INVALID_JOINT_INDEX) { int jointIndex = _skeleton->nameToJointIndex(targetVar.jointName); if (jointIndex >= 0) { // this targetVar has a valid joint --> cache the indices @@ -190,7 +191,7 @@ void AnimInverseKinematics::computeTargets(const AnimVariantMap& animVars, std:: } IKTarget target; - if (targetVar.jointIndex != -1) { + if (targetVar.jointIndex != AnimSkeleton::INVALID_JOINT_INDEX) { target.setType(animVars.lookup(targetVar.typeVar, (int)IKTarget::Type::RotationAndPosition)); target.setIndex(targetVar.jointIndex); if (target.getType() != IKTarget::Type::Unknown) { @@ -329,7 +330,7 @@ void AnimInverseKinematics::solve(const AnimContext& context, const std::vector< // update the absolutePoses for (int i = 0; i < (int)_relativePoses.size(); ++i) { auto parentIndex = _skeleton->getParentIndex((int)i); - if (parentIndex != -1) { + if (parentIndex != AnimSkeleton::INVALID_JOINT_INDEX) { absolutePoses[i] = absolutePoses[parentIndex] * _relativePoses[i]; } } @@ -351,12 +352,12 @@ void AnimInverseKinematics::solve(const AnimContext& context, const std::vector< // finally set the relative rotation of each tip to agree with absolute target rotation for (auto& target: targets) { int tipIndex = target.getIndex(); - int parentIndex = (tipIndex >= 0) ? _skeleton->getParentIndex(tipIndex) : -1; + int parentIndex = (tipIndex >= 0) ? _skeleton->getParentIndex(tipIndex) : AnimSkeleton::INVALID_JOINT_INDEX; int chainIndex = targetToChainMap[tipIndex]; bool needsInterpolation = _prevJointChainInfoVec[chainIndex].timer > 0.0f; float alpha = needsInterpolation ? getInterpolationAlpha(_prevJointChainInfoVec[chainIndex].timer) : 0.0f; // update rotationOnly targets that don't lie on the ik chain of other ik targets. - if (parentIndex != -1 && !_rotationAccumulators[tipIndex].isDirty() && + if (parentIndex != AnimSkeleton::INVALID_JOINT_INDEX && !_rotationAccumulators[tipIndex].isDirty() && (target.getType() == IKTarget::Type::RotationOnly || target.getType() == IKTarget::Type::Unknown)) { if (target.getType() == IKTarget::Type::RotationOnly) { const glm::quat& targetRotation = target.getRotation(); @@ -434,11 +435,11 @@ void AnimInverseKinematics::solveTargetWithCCD(const AnimContext& context, const int tipIndex = target.getIndex(); int pivotIndex = _skeleton->getParentIndex(tipIndex); - if (pivotIndex == -1 || pivotIndex == _hipsIndex) { + if (pivotIndex == AnimSkeleton::INVALID_JOINT_INDEX || pivotIndex == _hipsIndex) { return; } int pivotsParentIndex = _skeleton->getParentIndex(pivotIndex); - if (pivotsParentIndex == -1) { + if (pivotsParentIndex == AnimSkeleton::INVALID_JOINT_INDEX) { // TODO?: handle case where tip's parent is root? return; } @@ -485,7 +486,7 @@ void AnimInverseKinematics::solveTargetWithCCD(const AnimContext& context, const chainDepth++; // descend toward root, pivoting each joint to get tip closer to target position - while (pivotIndex != _hipsIndex && pivotsParentIndex != -1) { + while (pivotIndex != _hipsIndex && pivotsParentIndex != AnimSkeleton::INVALID_JOINT_INDEX) { assert(chainDepth < jointChainInfoOut.jointInfoVec.size()); @@ -579,12 +580,12 @@ void AnimInverseKinematics::solveTargetWithCCD(const AnimContext& context, const if (target.getPoleVectorEnabled()) { int topJointIndex = target.getIndex(); int midJointIndex = _skeleton->getParentIndex(topJointIndex); - if (midJointIndex != -1) { + if (midJointIndex != AnimSkeleton::INVALID_JOINT_INDEX) { int baseJointIndex = _skeleton->getParentIndex(midJointIndex); - if (baseJointIndex != -1) { + if (baseJointIndex != AnimSkeleton::INVALID_JOINT_INDEX) { int baseParentJointIndex = _skeleton->getParentIndex(baseJointIndex); AnimPose topPose, midPose, basePose; - int topChainIndex = -1, baseChainIndex = -1; + int topChainIndex = AnimSkeleton::INVALID_JOINT_INDEX, baseChainIndex = AnimSkeleton::INVALID_JOINT_INDEX; const size_t MAX_CHAIN_DEPTH = 30; AnimPose postAbsPoses[MAX_CHAIN_DEPTH]; AnimPose accum = absolutePoses[_hipsIndex]; @@ -756,7 +757,7 @@ void AnimInverseKinematics::computeAndCacheSplineJointInfosForIKTarget(const Ani int index = target.getIndex(); int endIndex = _skeleton->getParentIndex(_hipsIndex); - while (index != endIndex) { + while (index != endIndex && index != AnimSkeleton::INVALID_JOINT_INDEX) { AnimPose defaultPose = _skeleton->getAbsoluteDefaultPose(index); float ratio = glm::dot(defaultPose.trans() - basePose.trans(), baseToTipNormal) / baseToTipLength; @@ -1460,7 +1461,7 @@ void AnimInverseKinematics::setSkeletonInternal(AnimSkeleton::ConstPointer skele // invalidate all targetVars for (auto& targetVar: _targetVarVec) { - targetVar.jointIndex = -1; + targetVar.jointIndex = AnimSkeleton::INVALID_JOINT_INDEX; } for (auto& accumulator: _rotationAccumulators) { @@ -1480,18 +1481,18 @@ void AnimInverseKinematics::setSkeletonInternal(AnimSkeleton::ConstPointer skele if (_hipsIndex >= 0) { _hipsParentIndex = _skeleton->getParentIndex(_hipsIndex); } else { - _hipsParentIndex = -1; + _hipsParentIndex = AnimSkeleton::INVALID_JOINT_INDEX; } _leftHandIndex = _skeleton->nameToJointIndex("LeftHand"); _rightHandIndex = _skeleton->nameToJointIndex("RightHand"); } else { clearConstraints(); - _headIndex = -1; - _hipsIndex = -1; - _hipsParentIndex = -1; - _leftHandIndex = -1; - _rightHandIndex = -1; + _headIndex = AnimSkeleton::INVALID_JOINT_INDEX; + _hipsIndex = AnimSkeleton::INVALID_JOINT_INDEX; + _hipsParentIndex = AnimSkeleton::INVALID_JOINT_INDEX; + _leftHandIndex = AnimSkeleton::INVALID_JOINT_INDEX; + _rightHandIndex = AnimSkeleton::INVALID_JOINT_INDEX; } } @@ -1531,7 +1532,7 @@ void AnimInverseKinematics::debugDrawRelativePoses(const AnimContext& context) c // draw line to parent int parentIndex = _skeleton->getParentIndex(i); - if (parentIndex != -1) { + if (parentIndex != AnimSkeleton::INVALID_JOINT_INDEX) { glm::vec3 parentPos = transformPoint(geomToWorldMatrix, poses[parentIndex].trans()); DebugDraw::getInstance().drawRay(pos, parentPos, GRAY); } @@ -1580,7 +1581,7 @@ void AnimInverseKinematics::debugDrawIKChain(const JointChainInfo& jointChainInf DebugDraw::getInstance().drawRay(pos, pos + AXIS_LENGTH * zAxis, BLUE); // draw line to parent - if (parentIndex != -1) { + if (parentIndex != AnimSkeleton::INVALID_JOINT_INDEX) { glm::vec3 parentPos = transformPoint(geomToWorldMatrix, poses[parentIndex].trans()); glm::vec4 color = GRAY; @@ -1629,13 +1630,13 @@ void AnimInverseKinematics::debugDrawConstraints(const AnimContext& context) con // draw line to parent int parentIndex = _skeleton->getParentIndex(i); - if (parentIndex != -1) { + if (parentIndex != AnimSkeleton::INVALID_JOINT_INDEX) { glm::vec3 parentPos = transformPoint(geomToWorldMatrix, poses[parentIndex].trans()); DebugDraw::getInstance().drawRay(pos, parentPos, GRAY); } glm::quat parentAbsRot; - if (parentIndex != -1) { + if (parentIndex != AnimSkeleton::INVALID_JOINT_INDEX) { parentAbsRot = poses[parentIndex].rot(); } @@ -1733,7 +1734,7 @@ void AnimInverseKinematics::preconditionRelativePosesToAvoidLimbLock(const AnimC const float MIN_AXIS_LENGTH = 1.0e-4f; for (auto& target : targets) { - if (target.getIndex() != -1 && target.getType() == IKTarget::Type::RotationAndPosition) { + if (target.getIndex() != AnimSkeleton::INVALID_JOINT_INDEX && target.getType() == IKTarget::Type::RotationAndPosition) { for (int i = 0; i < NUM_LIMBS; i++) { if (limbs[i].first == target.getIndex()) { int tipIndex = limbs[i].first; diff --git a/libraries/animation/src/AnimInverseKinematics.h b/libraries/animation/src/AnimInverseKinematics.h index aa7e8fb69e..dd26294bcd 100644 --- a/libraries/animation/src/AnimInverseKinematics.h +++ b/libraries/animation/src/AnimInverseKinematics.h @@ -59,7 +59,7 @@ public: float getMaxErrorOnLastSolve() { return _maxErrorOnLastSolve; } - /**jsdoc + /*@jsdoc *

Specifies the initial conditions of the IK solver.

*
* diff --git a/libraries/animation/src/AnimOverlay.h b/libraries/animation/src/AnimOverlay.h index d5e114a2d2..cf6fb8375a 100644 --- a/libraries/animation/src/AnimOverlay.h +++ b/libraries/animation/src/AnimOverlay.h @@ -24,7 +24,7 @@ class AnimOverlay : public AnimNode { public: friend class AnimTests; - /**jsdoc + /*@jsdoc *

Specifies sets of joints.

*
* diff --git a/libraries/animation/src/AnimSkeleton.cpp b/libraries/animation/src/AnimSkeleton.cpp index b26d00d8d0..bd338aae4a 100644 --- a/libraries/animation/src/AnimSkeleton.cpp +++ b/libraries/animation/src/AnimSkeleton.cpp @@ -66,7 +66,7 @@ int AnimSkeleton::nameToJointIndex(const QString& jointName) const { if (_jointIndicesByName.end() != itr) { return itr.value(); } - return -1; + return INVALID_JOINT_INDEX; } int AnimSkeleton::getNumJoints() const { @@ -80,7 +80,7 @@ int AnimSkeleton::getChainDepth(int jointIndex) const { do { chainDepth++; index = _parentIndices[index]; - } while (index != -1); + } while (index != INVALID_JOINT_INDEX); return chainDepth; } else { return 0; @@ -108,7 +108,7 @@ const AnimPose& AnimSkeleton::getPostRotationPose(int jointIndex) const { std::vector AnimSkeleton::getChildrenOfJoint(int jointIndex) const { // Children and grandchildren, etc. std::vector result; - if (jointIndex != -1) { + if (jointIndex != INVALID_JOINT_INDEX) { for (int i = jointIndex + 1; i < (int)_parentIndices.size(); i++) { if (_parentIndices[i] == jointIndex || (std::find(result.begin(), result.end(), _parentIndices[i]) != result.end())) { result.push_back(i); @@ -135,7 +135,7 @@ void AnimSkeleton::convertRelativePosesToAbsolute(AnimPoseVec& poses) const { int lastIndex = std::min((int)poses.size(), _jointsSize); for (int i = 0; i < lastIndex; ++i) { int parentIndex = _parentIndices[i]; - if (parentIndex != -1) { + if (parentIndex != INVALID_JOINT_INDEX) { poses[i] = poses[parentIndex] * poses[i]; } } @@ -146,7 +146,7 @@ void AnimSkeleton::convertAbsolutePosesToRelative(AnimPoseVec& poses) const { int lastIndex = std::min((int)poses.size(), _jointsSize); for (int i = lastIndex - 1; i >= 0; --i) { int parentIndex = _parentIndices[i]; - if (parentIndex != -1) { + if (parentIndex != INVALID_JOINT_INDEX) { poses[i] = poses[parentIndex].inverse() * poses[i]; } } @@ -157,7 +157,7 @@ void AnimSkeleton::convertRelativeRotationsToAbsolute(std::vector& ro int lastIndex = std::min((int)rotations.size(), _jointsSize); for (int i = 0; i < lastIndex; ++i) { int parentIndex = _parentIndices[i]; - if (parentIndex != -1) { + if (parentIndex != INVALID_JOINT_INDEX) { rotations[i] = rotations[parentIndex] * rotations[i]; } } @@ -168,7 +168,7 @@ void AnimSkeleton::convertAbsoluteRotationsToRelative(std::vector& ro int lastIndex = std::min((int)rotations.size(), _jointsSize); for (int i = lastIndex - 1; i >= 0; --i) { int parentIndex = _parentIndices[i]; - if (parentIndex != -1) { + if (parentIndex != INVALID_JOINT_INDEX) { rotations[i] = glm::inverse(rotations[parentIndex]) * rotations[i]; } } @@ -280,7 +280,7 @@ void AnimSkeleton::buildSkeletonFromJoints(const std::vector& joints, // so we can restore them after a future mirror operation _nonMirroredIndices.push_back(i); } - int mirrorJointIndex = -1; + int mirrorJointIndex = INVALID_JOINT_INDEX; if (_joints[i].name.startsWith("Left")) { QString mirrorJointName = QString(_joints[i].name).replace(0, 4, "Right"); mirrorJointIndex = nameToJointIndex(mirrorJointName); @@ -350,7 +350,7 @@ std::vector AnimSkeleton::lookUpJointIndices(const std::vector& jo result.reserve(jointNames.size()); for (auto& name : jointNames) { int index = nameToJointIndex(name); - if (index == -1) { + if (index == INVALID_JOINT_INDEX) { qWarning(animation) << "AnimSkeleton::lookUpJointIndices(): could not find bone with name " << name; } result.push_back(index); diff --git a/libraries/animation/src/AnimSkeleton.h b/libraries/animation/src/AnimSkeleton.h index efc1c1599f..e36ceb4042 100644 --- a/libraries/animation/src/AnimSkeleton.h +++ b/libraries/animation/src/AnimSkeleton.h @@ -30,6 +30,8 @@ public: const QString& getJointName(int jointIndex) const; int getNumJoints() const; int getChainDepth(int jointIndex) const; + + static const int INVALID_JOINT_INDEX { -1 }; // the default poses are the orientations of the joints on frame 0. const AnimPose& getRelativeDefaultPose(int jointIndex) const; diff --git a/libraries/animation/src/AnimationCacheScriptingInterface.h b/libraries/animation/src/AnimationCacheScriptingInterface.h index fc31ecaa2b..f07e9aeebd 100644 --- a/libraries/animation/src/AnimationCacheScriptingInterface.h +++ b/libraries/animation/src/AnimationCacheScriptingInterface.h @@ -24,7 +24,7 @@ class AnimationCacheScriptingInterface : public ScriptableResourceCache, public // Properties are copied over from ResourceCache (see ResourceCache.h for reason). - /**jsdoc + /*@jsdoc * The AnimationCache API manages animation cache resources. * * @namespace AnimationCache @@ -52,7 +52,7 @@ class AnimationCacheScriptingInterface : public ScriptableResourceCache, public public: AnimationCacheScriptingInterface(); - /**jsdoc + /*@jsdoc * Gets information about an animation resource. * @function AnimationCache.getAnimation * @param {string} url - The URL of the animation. diff --git a/libraries/animation/src/AnimationObject.h b/libraries/animation/src/AnimationObject.h index 40fd534a71..466deb5e96 100644 --- a/libraries/animation/src/AnimationObject.h +++ b/libraries/animation/src/AnimationObject.h @@ -19,7 +19,7 @@ class QScriptEngine; -/**jsdoc +/*@jsdoc * Information about an animation resource, created by {@link AnimationCache.getAnimation}. * * @class AnimationObject @@ -42,14 +42,14 @@ class AnimationObject : public QObject, protected QScriptable { public: - /**jsdoc + /*@jsdoc * Gets the names of the joints that are animated. * @function AnimationObject.getJointNames * @returns {string[]} The names of the joints that are animated. */ Q_INVOKABLE QStringList getJointNames() const; - /**jsdoc + /*@jsdoc * Gets the frames in the animation. * @function AnimationObject.getFrames * @returns {AnimationFrameObject[]} The frames in the animation. @@ -57,7 +57,7 @@ public: Q_INVOKABLE QVector getFrames() const; }; -/**jsdoc +/*@jsdoc * Joint rotations in one frame of an {@link AnimationObject}. * * @class AnimationFrameObject @@ -78,7 +78,7 @@ class AnimationFrameObject : public QObject, protected QScriptable { public: - /**jsdoc + /*@jsdoc * Gets the joint rotations in the animation frame. * @function AnimationFrameObject.getRotations * @returns {Quat[]} The joint rotations in the animation frame. diff --git a/libraries/animation/src/IKTarget.h b/libraries/animation/src/IKTarget.h index a56f5578b3..3592769506 100644 --- a/libraries/animation/src/IKTarget.h +++ b/libraries/animation/src/IKTarget.h @@ -16,7 +16,7 @@ const float HACK_HMD_TARGET_WEIGHT = 8.0f; class IKTarget { public: - /**jsdoc + /*@jsdoc *

An IK target type.

*
* diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index 6dc378a32f..ba042d31a8 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -89,7 +89,7 @@ static const QString MAIN_STATE_MACHINE_RIGHT_HAND_ROTATION("mainStateMachineRig static const QString MAIN_STATE_MACHINE_RIGHT_HAND_POSITION("mainStateMachineRightHandPosition"); -/**jsdoc +/*@jsdoc *

An AnimStateDictionary object may have the following properties. It may also have other properties, set by * scripts.

*

Warning: These properties are subject to change. diff --git a/libraries/audio-client/src/AudioClient.cpp b/libraries/audio-client/src/AudioClient.cpp index 2600097c3b..38635870fd 100644 --- a/libraries/audio-client/src/AudioClient.cpp +++ b/libraries/audio-client/src/AudioClient.cpp @@ -1266,7 +1266,7 @@ void AudioClient::processWebrtcNearEnd(int16_t* samples, int numFrames, int numC void AudioClient::handleLocalEchoAndReverb(QByteArray& inputByteArray) { // If there is server echo, reverb will be applied to the recieved audio stream so no need to have it here. bool hasReverb = _reverb || _receivedAudioStream.hasReverb(); - if ((_muted && !_shouldEchoLocally) || !_audioOutput || (!_shouldEchoLocally && !hasReverb)) { + if ((_muted && !_shouldEchoLocally) || !_audioOutput || (!_shouldEchoLocally && !hasReverb) || !_audioGateOpen) { return; } @@ -1342,6 +1342,13 @@ void AudioClient::handleLocalEchoAndReverb(QByteArray& inputByteArray) { } } +float AudioClient::loudnessToLevel(float loudness) { + float level = loudness * (1 / 32768.0f); // level in [0, 1] + level = 6.02059991f * fastLog2f(level); // convert to dBFS + level = (level + 48.0f) * (1 / 42.0f); // map [-48, -6] dBFS to [0, 1] + return glm::clamp(level, 0.0f, 1.0f); +} + void AudioClient::handleAudioInput(QByteArray& audioBuffer) { if (!_audioPaused) { @@ -1352,9 +1359,14 @@ void AudioClient::handleAudioInput(QByteArray& audioBuffer) { int numSamples = audioBuffer.size() / AudioConstants::SAMPLE_SIZE; int numFrames = numSamples / (_isStereoInput ? AudioConstants::STEREO : AudioConstants::MONO); - if (_isNoiseGateEnabled) { + if (_isNoiseGateEnabled && _isNoiseReductionAutomatic) { // The audio gate includes DC removal audioGateOpen = _audioGate->render(samples, samples, numFrames); + } else if (_isNoiseGateEnabled && !_isNoiseReductionAutomatic && + loudnessToLevel(_lastSmoothedRawInputLoudness) >= _noiseReductionThreshold) { + audioGateOpen = _audioGate->removeDC(samples, samples, numFrames); + } else if (_isNoiseGateEnabled && !_isNoiseReductionAutomatic) { + audioGateOpen = false; } else { audioGateOpen = _audioGate->removeDC(samples, samples, numFrames); } @@ -1750,6 +1762,24 @@ void AudioClient::setNoiseReduction(bool enable, bool emitSignal) { } } +void AudioClient::setNoiseReductionAutomatic(bool enable, bool emitSignal) { + if (_isNoiseReductionAutomatic != enable) { + _isNoiseReductionAutomatic = enable; + if (emitSignal) { + emit noiseReductionAutomaticChanged(_isNoiseReductionAutomatic); + } + } +} + +void AudioClient::setNoiseReductionThreshold(float threshold, bool emitSignal) { + if (_noiseReductionThreshold != threshold) { + _noiseReductionThreshold = threshold; + if (emitSignal) { + emit noiseReductionThresholdChanged(_noiseReductionThreshold); + } + } +} + void AudioClient::setWarnWhenMuted(bool enable, bool emitSignal) { if (_warnWhenMuted != enable) { _warnWhenMuted = enable; diff --git a/libraries/audio-client/src/AudioClient.h b/libraries/audio-client/src/AudioClient.h index 09abb2c356..a5de9bd4ca 100644 --- a/libraries/audio-client/src/AudioClient.h +++ b/libraries/audio-client/src/AudioClient.h @@ -217,6 +217,12 @@ public slots: void setNoiseReduction(bool isNoiseGateEnabled, bool emitSignal = true); bool isNoiseReductionEnabled() const { return _isNoiseGateEnabled; } + + void setNoiseReductionAutomatic(bool isNoiseGateAutomatic, bool emitSignal = true); + bool isNoiseReductionAutomatic() const { return _isNoiseReductionAutomatic; } + + void setNoiseReductionThreshold(float noiseReductionThreshold, bool emitSignal = true); + float noiseReductionThreshold() const { return _noiseReductionThreshold; } void setWarnWhenMuted(bool isNoiseGateEnabled, bool emitSignal = true); bool isWarnWhenMutedEnabled() const { return _warnWhenMuted; } @@ -265,6 +271,8 @@ signals: void inputVolumeChanged(float volume); void muteToggled(bool muted); void noiseReductionChanged(bool noiseReductionEnabled); + void noiseReductionAutomaticChanged(bool noiseReductionAutomatic); + void noiseReductionThresholdChanged(bool noiseReductionThreshold); void warnWhenMutedChanged(bool warnWhenMutedEnabled); void acousticEchoCancellationChanged(bool acousticEchoCancellationEnabled); void mutedByMixer(); @@ -310,6 +318,8 @@ private: friend class CheckDevicesThread; friend class LocalInjectorsThread; + float loudnessToLevel(float loudness); + // background tasks void checkDevices(); void checkPeakValues(); @@ -397,6 +407,8 @@ private: bool _shouldEchoLocally{ false }; bool _shouldEchoToServer{ false }; bool _isNoiseGateEnabled{ true }; + bool _isNoiseReductionAutomatic{ true }; + float _noiseReductionThreshold{ 0.1f }; bool _warnWhenMuted; bool _isAECEnabled{ true }; diff --git a/libraries/audio-client/src/AudioIOStats.h b/libraries/audio-client/src/AudioIOStats.h index 9265ae3062..215a4e5414 100644 --- a/libraries/audio-client/src/AudioIOStats.h +++ b/libraries/audio-client/src/AudioIOStats.h @@ -39,7 +39,7 @@ class MixedProcessedAudioStream; class AudioStreamStatsInterface : public QObject { Q_OBJECT - /**jsdoc + /*@jsdoc * Statistics for an audio stream. * *

Provided in properties of the {@link AudioStats} API.

@@ -88,7 +88,7 @@ class AudioStreamStatsInterface : public QObject { * Read-only. */ - /**jsdoc + /*@jsdoc * Triggered when the ratio of the total number of audio packets lost to the total number of audio packets expected changes. * @function AudioStats.AudioStreamStats.lossRateChanged * @param {number} lossRate - The ratio of the total number of audio packets lost to the total number of audio packets @@ -97,7 +97,7 @@ class AudioStreamStatsInterface : public QObject { */ AUDIO_PROPERTY(float, lossRate) - /**jsdoc + /*@jsdoc * Triggered when the total number of audio packets lost changes. * @function AudioStats.AudioStreamStats.lossCountChanged * @param {number} lossCount - The total number of audio packets lost. @@ -105,7 +105,7 @@ class AudioStreamStatsInterface : public QObject { */ AUDIO_PROPERTY(float, lossCount) - /**jsdoc + /*@jsdoc * Triggered when the ratio of the number of audio packets lost to the number of audio packets expected since the previous * statistic changes. * @function AudioStats.AudioStreamStats.lossRateWindowChanged @@ -115,7 +115,7 @@ class AudioStreamStatsInterface : public QObject { */ AUDIO_PROPERTY(float, lossRateWindow) - /**jsdoc + /*@jsdoc * Triggered when the number of audio packets lost since the previous statistic changes. * @function AudioStats.AudioStreamStats.lossCountWindowChanged * @param {number} lossCountWindow - The number of audio packets lost since the previous statistic. @@ -123,7 +123,7 @@ class AudioStreamStatsInterface : public QObject { */ AUDIO_PROPERTY(float, lossCountWindow) - /**jsdoc + /*@jsdoc * Triggered when the desired number of audio frames for the jitter buffer changes. * @function AudioStats.AudioStreamStats.framesDesiredChanged * @param {number} framesDesired - The desired number of audio frames for the jitter buffer. @@ -131,7 +131,7 @@ class AudioStreamStatsInterface : public QObject { */ AUDIO_PROPERTY(int, framesDesired) - /**jsdoc + /*@jsdoc * Triggered when the number of audio frames containing data available changes. * @function AudioStats.AudioStreamStats.framesAvailableChanged * @param {number} framesAvailable - The number of audio frames containing data available. @@ -139,7 +139,7 @@ class AudioStreamStatsInterface : public QObject { */ AUDIO_PROPERTY(int, framesAvailable) - /**jsdoc + /*@jsdoc * Triggered when the time-weighted average of audio frames containing data available changes. * @function AudioStats.AudioStreamStats.framesAvailableAvgChanged * @param {number} framesAvailableAvg - The time-weighted average of audio frames containing data available. @@ -147,7 +147,7 @@ class AudioStreamStatsInterface : public QObject { */ AUDIO_PROPERTY(int, framesAvailableAvg) - /**jsdoc + /*@jsdoc * Triggered when the duration of audio waiting to be played changes. * @function AudioStats.AudioStreamStats.unplayedMsMaxChanged * @param {number} unplayedMsMax - The duration of audio waiting to be played, in ms. @@ -155,7 +155,7 @@ class AudioStreamStatsInterface : public QObject { */ AUDIO_PROPERTY(float, unplayedMsMax) - /**jsdoc + /*@jsdoc * Triggered when the total number of times that audio frames have not been available for processing changes. * @function AudioStats.AudioStreamStats.starveCountChanged * @param {number} starveCount - The total number of times that audio frames have not been available for processing. @@ -163,7 +163,7 @@ class AudioStreamStatsInterface : public QObject { */ AUDIO_PROPERTY(int, starveCount) - /**jsdoc + /*@jsdoc * Triggered when the most recenbernumber of consecutive times that audio frames have not been available for processing * changes. * @function AudioStats.AudioStreamStats.lastStarveDurationCountChanged @@ -173,7 +173,7 @@ class AudioStreamStatsInterface : public QObject { */ AUDIO_PROPERTY(int, lastStarveDurationCount) - /**jsdoc + /*@jsdoc * Triggered when the number of silent or old audio frames dropped changes. * @function AudioStats.AudioStreamStats.dropCountChanged * @param {number} dropCount - The number of silent or old audio frames dropped. @@ -181,7 +181,7 @@ class AudioStreamStatsInterface : public QObject { */ AUDIO_PROPERTY(int, dropCount) - /**jsdoc + /*@jsdoc * Triggered when the number of times that the audio ring buffer has overflowed changes. * @function AudioStats.AudioStreamStats.overflowCountChanged * @param {number} overflowCount - The number of times that the audio ring buffer has overflowed. @@ -189,7 +189,7 @@ class AudioStreamStatsInterface : public QObject { */ AUDIO_PROPERTY(int, overflowCount) - /**jsdoc + /*@jsdoc * Triggered when the overall maximum time between data packets changes. * @function AudioStats.AudioStreamStats.timegapMsMaxChanged * @param {number} timegapMsMax - The overall maximum time between data packets, in ms. @@ -197,7 +197,7 @@ class AudioStreamStatsInterface : public QObject { */ AUDIO_PROPERTY(quint64, timegapMsMax) - /**jsdoc + /*@jsdoc * Triggered when the overall average time between data packets changes. * @function AudioStats.AudioStreamStats.timegapMsAvgChanged * @param {number} timegapMsAvg - The overall average time between data packets, in ms. @@ -205,7 +205,7 @@ class AudioStreamStatsInterface : public QObject { */ AUDIO_PROPERTY(quint64, timegapMsAvg) - /**jsdoc + /*@jsdoc * Triggered when the recent maximum time between data packets changes. * @function AudioStats.AudioStreamStats.timegapMsMaxWindowChanged * @param {number} timegapMsMaxWindow - The recent maximum time between data packets, in ms. @@ -213,7 +213,7 @@ class AudioStreamStatsInterface : public QObject { */ AUDIO_PROPERTY(quint64, timegapMsMaxWindow) - /**jsdoc + /*@jsdoc * Triggered when the recent average time between data packets changes. * @function AudioStats.AudioStreamStats.timegapMsAvgWindowChanged * @param {number} timegapMsAvgWindow - The recent average time between data packets, in ms. @@ -232,7 +232,7 @@ private: class AudioStatsInterface : public QObject { Q_OBJECT - /**jsdoc + /*@jsdoc * The AudioStats API provides statistics of the client and mixer audio. * * @namespace AudioStats @@ -268,7 +268,7 @@ class AudioStatsInterface : public QObject { * Read-only. */ - /**jsdoc + /*@jsdoc * Triggered when the ping time to the audio mixer changes. * @function AudioStats.pingMsChanged * @param {number} pingMs - The ping time to the audio mixer, in ms. @@ -277,7 +277,7 @@ class AudioStatsInterface : public QObject { AUDIO_PROPERTY(float, pingMs); - /**jsdoc + /*@jsdoc * Triggered when the maximum duration of a block of audio data recently read from the microphone changes. * @function AudioStats.inputReadMsMaxChanged * @param {number} inputReadMsMax - The maximum duration of a block of audio data recently read from the microphone, in ms. @@ -285,7 +285,7 @@ class AudioStatsInterface : public QObject { */ AUDIO_PROPERTY(float, inputReadMsMax); - /**jsdoc + /*@jsdoc * Triggered when the maximum duration of microphone audio recently in the input buffer waiting to be played changes. * @function AudioStats.inputUnplayedMsMaxChanged * @param {number} inputUnplayedMsMax - The maximum duration of microphone audio recently in the input buffer waiting to be @@ -294,7 +294,7 @@ class AudioStatsInterface : public QObject { */ AUDIO_PROPERTY(float, inputUnplayedMsMax); - /**jsdoc + /*@jsdoc * Triggered when the maximum duration of output audio recently in the output buffer waiting to be played changes. * @function AudioStats.outputUnplayedMsMaxChanged * @param {number} outputUnplayedMsMax - The maximum duration of output audio recently in the output buffer waiting to be @@ -304,7 +304,7 @@ class AudioStatsInterface : public QObject { AUDIO_PROPERTY(float, outputUnplayedMsMax); - /**jsdoc + /*@jsdoc * Triggered when the overall maximum time between sending data packets to the audio mixer changes. * @function AudioStats.sentTimegapMsMaxChanged * @param {number} sentTimegapMsMax - The overall maximum time between sending data packets to the audio mixer, in ms. @@ -312,7 +312,7 @@ class AudioStatsInterface : public QObject { */ AUDIO_PROPERTY(quint64, sentTimegapMsMax); - /**jsdoc + /*@jsdoc * Triggered when the overall average time between sending data packets to the audio mixer changes. * @function AudioStats.sentTimegapMsAvgChanged * @param {number} sentTimegapMsAvg - The overall average time between sending data packets to the audio mixer, in ms. @@ -320,7 +320,7 @@ class AudioStatsInterface : public QObject { */ AUDIO_PROPERTY(quint64, sentTimegapMsAvg); - /**jsdoc + /*@jsdoc * Triggered when the recent maximum time between sending data packets to the audio mixer changes. * @function AudioStats.sentTimegapMsMaxWindowChanged * @param {number} sentTimegapMsMaxWindow - The recent maximum time between sending data packets to the audio mixer, in ms. @@ -328,7 +328,7 @@ class AudioStatsInterface : public QObject { */ AUDIO_PROPERTY(quint64, sentTimegapMsMaxWindow); - /**jsdoc + /*@jsdoc * Triggered when the recent average time between sending data packets to the audio mixer changes. * @function AudioStats.sentTimegapMsAvgWindowChanged * @param {number} sentTimegapMsAvgWindow - The recent average time between sending data packets to the audio mixer, in @@ -358,21 +358,21 @@ public: signals: - /**jsdoc + /*@jsdoc * Triggered when the mixer's stream statistics have been updated. * @function AudioStats.mixerStreamChanged * @returns {Signal} */ void mixerStreamChanged(); - /**jsdoc + /*@jsdoc * Triggered when the client's stream statisticss have been updated. * @function AudioStats.clientStreamChanged * @returns {Signal} */ void clientStreamChanged(); - /**jsdoc + /*@jsdoc * Triggered when the injector streams' statistics have been updated. *

Note: The injector streams' statistics are currently not provided.

* @function AudioStats.injectorStreamsChanged diff --git a/libraries/audio/src/AudioEffectOptions.cpp b/libraries/audio/src/AudioEffectOptions.cpp index 873ce7df87..186689d2b4 100644 --- a/libraries/audio/src/AudioEffectOptions.cpp +++ b/libraries/audio/src/AudioEffectOptions.cpp @@ -58,7 +58,7 @@ static void setOption(QScriptValue arguments, const QString name, float defaultV variable = arguments.property(name).isNumber() ? (float)arguments.property(name).toNumber() : defaultValue; } -/**jsdoc +/*@jsdoc * Reverberation options that can be used to initialize an {@link AudioEffectOptions} object when created. * @typedef {object} AudioEffectOptions.ReverbOptions * @property {number} bandwidth=10000 - The corner frequency (Hz) of the low-pass filter at reverb input. diff --git a/libraries/audio/src/AudioEffectOptions.h b/libraries/audio/src/AudioEffectOptions.h index 48fe44feb5..14b39e0f33 100644 --- a/libraries/audio/src/AudioEffectOptions.h +++ b/libraries/audio/src/AudioEffectOptions.h @@ -15,7 +15,7 @@ #include #include -/**jsdoc +/*@jsdoc * Audio effect options used by the {@link Audio} API. * *

Create using new AudioEffectOptions(...).

diff --git a/libraries/audio/src/AudioHRTF.cpp b/libraries/audio/src/AudioHRTF.cpp index be7fecb450..fa8665d1a9 100644 --- a/libraries/audio/src/AudioHRTF.cpp +++ b/libraries/audio/src/AudioHRTF.cpp @@ -91,8 +91,8 @@ static const float azimuthTable[NAZIMUTH][3] = { // A first-order shelving filter is used to minimize the disturbance in ITD. // // Loosely based on data from S. Spagnol, "Distance rendering and perception of nearby virtual sound sources -// with a near-field filter model, Applied Acoustics (2017) -// +// with a near-field filter model," Applied Acoustics (2017) +// static const int NNEARFIELD = 9; static const float nearFieldTable[NNEARFIELD][3] = { // { b0, b1, a1 } { 0.008410604f, -0.000262748f, -0.991852144f }, // gain = 1/256 @@ -388,7 +388,12 @@ void crossfade_4x2_AVX2(float* src, float* dst, const float* win, int numFrames) void interpolate_AVX2(const float* src0, const float* src1, float* dst, float frac, float gain); static void FIR_1x4(float* src, float* dst0, float* dst1, float* dst2, float* dst3, float coef[4][HRTF_TAPS], int numFrames) { +#ifndef STACK_PROTECTOR + // Enabling -fstack-protector on gcc causes an undefined reference to FIR_1x4_AVX512 here static auto f = cpuSupportsAVX512() ? FIR_1x4_AVX512 : (cpuSupportsAVX2() ? FIR_1x4_AVX2 : FIR_1x4_SSE); +#else + static auto f = cpuSupportsAVX2() ? FIR_1x4_AVX2 : FIR_1x4_SSE; +#endif (*f)(src, dst0, dst1, dst2, dst3, coef, numFrames); // dispatch } diff --git a/libraries/audio/src/AudioInjectorOptions.cpp b/libraries/audio/src/AudioInjectorOptions.cpp index cb7da4de33..39b807fd76 100644 --- a/libraries/audio/src/AudioInjectorOptions.cpp +++ b/libraries/audio/src/AudioInjectorOptions.cpp @@ -47,7 +47,7 @@ QScriptValue injectorOptionsToScriptValue(QScriptEngine* engine, const AudioInje return obj; } -/**jsdoc +/*@jsdoc * Configures where and how an audio injector plays its audio. * @typedef {object} AudioInjector.AudioInjectorOptions * @property {Vec3} position=Vec3.ZERO - The position in the domain to play the sound. diff --git a/libraries/audio/src/Sound.h b/libraries/audio/src/Sound.h index 205e1cba33..bfa682845a 100644 --- a/libraries/audio/src/Sound.h +++ b/libraries/audio/src/Sound.h @@ -120,7 +120,7 @@ private: typedef QSharedPointer SharedSoundPointer; -/**jsdoc +/*@jsdoc * An audio resource, created by {@link SoundCache.getSound}, to be played back using {@link Audio.playSound}. *

Supported formats:

*
    @@ -155,7 +155,7 @@ public: bool isReady() const { return _sound ? _sound->isReady() : false; } float getDuration() { return _sound ? _sound->getDuration() : 0.0f; } -/**jsdoc +/*@jsdoc * Triggered when the sound has been downloaded and is ready to be played. * @function SoundObject.ready * @returns {Signal} diff --git a/libraries/audio/src/SoundCacheScriptingInterface.h b/libraries/audio/src/SoundCacheScriptingInterface.h index 28425f0406..41ad7b6938 100644 --- a/libraries/audio/src/SoundCacheScriptingInterface.h +++ b/libraries/audio/src/SoundCacheScriptingInterface.h @@ -24,7 +24,7 @@ class SoundCacheScriptingInterface : public ScriptableResourceCache, public Depe // Properties are copied over from ResourceCache (see ResourceCache.h for reason). - /**jsdoc + /*@jsdoc * The SoundCache API manages sound cache resources. * * @namespace SoundCache @@ -53,7 +53,7 @@ class SoundCacheScriptingInterface : public ScriptableResourceCache, public Depe public: SoundCacheScriptingInterface(); - /**jsdoc + /*@jsdoc * Loads the content of an audio file into a {@link SoundObject}, ready for playback by {@link Audio.playSound}. * @function SoundCache.getSound * @param {string} url - The URL of the audio file to load — Web, ATP, or file. See {@link SoundObject} for supported diff --git a/libraries/avatars-renderer/CMakeLists.txt b/libraries/avatars-renderer/CMakeLists.txt index deba2913c1..0175d1113a 100644 --- a/libraries/avatars-renderer/CMakeLists.txt +++ b/libraries/avatars-renderer/CMakeLists.txt @@ -4,7 +4,7 @@ link_hifi_libraries(shared shaders gpu graphics animation material-networking mo include_hifi_library_headers(avatars) include_hifi_library_headers(networking) include_hifi_library_headers(hfm) -include_hifi_library_headers(fbx) +include_hifi_library_headers(model-serializers) include_hifi_library_headers(recording) include_hifi_library_headers(ktx) include_hifi_library_headers(procedural) diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index f361e15999..b2d6a6260b 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -531,7 +531,7 @@ void Avatar::relayJointDataToChildren() { _reconstructSoftEntitiesJointMap = false; } -/**jsdoc +/*@jsdoc *

    An avatar has different types of data simulated at different rates, in Hz.

    * *
@@ -1444,9 +1444,7 @@ int Avatar::getJointIndex(const QString& name) const { } withValidJointIndicesCache([&]() { - if (_modelJointIndicesCache.contains(name)) { - result = _modelJointIndicesCache.value(name) - 1; - } + result = _modelJointIndicesCache.value(name, result + 1) - 1; }); return result; } @@ -1920,7 +1918,7 @@ void Avatar::setParentJointIndex(quint16 parentJointIndex) { } } -/**jsdoc +/*@jsdoc * Information about a joint in an avatar's skeleton hierarchy. * @typedef {object} SkeletonJoint * @property {string} name - Joint name. diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h index 4fc9c25595..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 @@ -204,29 +205,29 @@ public: std::vector getSkeletonDefaultData(); - /**jsdoc + /*@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}. */ Q_INVOKABLE virtual glm::quat getDefaultJointRotation(int index) const; - /**jsdoc + /*@jsdoc * 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; - /**jsdoc + /*@jsdoc * Gets the default joint rotations in avatar coordinates. * The default pose of the avatar is defined by the position and orientation of all bones * in the avatar's model file. Typically this is a T-pose. @@ -240,7 +241,7 @@ public: */ Q_INVOKABLE virtual glm::quat getAbsoluteDefaultJointRotationInObjectFrame(int index) const; - /**jsdoc + /*@jsdoc * Gets the default joint translations in avatar coordinates. * The default pose of the avatar is defined by the position and orientation of all bones * in the avatar's model file. Typically this is a T-pose. @@ -259,7 +260,7 @@ public: virtual glm::quat getAbsoluteJointRotationInObjectFrame(int index) const override; virtual glm::vec3 getAbsoluteJointTranslationInObjectFrame(int index) const override; - /**jsdoc + /*@jsdoc * Sets the rotation of a joint relative to the avatar. *

Warning: Not able to be used in the MyAvatar API.

* @function MyAvatar.setAbsoluteJointRotationInObjectFrame @@ -269,7 +270,7 @@ public: */ virtual bool setAbsoluteJointRotationInObjectFrame(int index, const glm::quat& rotation) override { return false; } - /**jsdoc + /*@jsdoc * Sets the translation of a joint relative to the avatar. *

Warning: Not able to be used in the MyAvatar API.

* @function MyAvatar.setAbsoluteJointTranslationInObjectFrame @@ -282,8 +283,8 @@ public: virtual float getSpine2SplineRatio() const { return _spine2SplineRatio; } // 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 + /*@jsdoc + * 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. @@ -292,8 +293,8 @@ 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 + /*@jsdoc + * 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. @@ -302,8 +303,8 @@ 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 + /*@jsdoc + * 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. @@ -312,8 +313,8 @@ 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 + /*@jsdoc + * 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. @@ -322,8 +323,8 @@ 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 + /*@jsdoc + * 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. @@ -332,8 +333,8 @@ 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 + /*@jsdoc + * 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. @@ -350,8 +351,8 @@ 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, + /*@jsdoc + * 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. @@ -366,8 +367,8 @@ 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, + /*@jsdoc + * 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. @@ -378,7 +379,7 @@ public: virtual glm::vec3 getSkeletonPosition() const; - /**jsdoc + /*@jsdoc * Gets the position of a joint in the current avatar. * @function MyAvatar.getJointPosition * @param {number} index - The index of the joint. @@ -386,7 +387,7 @@ public: */ Q_INVOKABLE glm::vec3 getJointPosition(int index) const; - /**jsdoc + /*@jsdoc * Gets the position of a joint in the current avatar. * @function MyAvatar.getJointPosition * @param {string} name - The name of the joint. @@ -396,7 +397,7 @@ public: */ Q_INVOKABLE glm::vec3 getJointPosition(const QString& name) const; - /**jsdoc + /*@jsdoc * Gets the position of the current avatar's neck in world coordinates. * @function MyAvatar.getNeckPosition * @returns {Vec3} The position of the neck in world coordinates. @@ -405,7 +406,7 @@ public: */ Q_INVOKABLE glm::vec3 getNeckPosition() const; - /**jsdoc + /*@jsdoc * Gets the current acceleration of the avatar. * @function MyAvatar.getAcceleration * @returns {Vec3} The current acceleration of the avatar. @@ -431,7 +432,7 @@ public: void getCapsule(glm::vec3& start, glm::vec3& end, float& radius); float computeMass(); - /**jsdoc + /*@jsdoc * Gets the position of the current avatar's feet (or rather, bottom of its collision capsule) in world coordinates. * @function MyAvatar.getWorldFeetPosition * @returns {Vec3} The position of the avatar's feet in world coordinates. @@ -441,7 +442,7 @@ public: void setPositionViaScript(const glm::vec3& position) override; void setOrientationViaScript(const glm::quat& orientation) override; - /**jsdoc + /*@jsdoc * Gets the ID of the entity or avatar that the avatar is parented to. * @function MyAvatar.getParentID * @returns {Uuid} The ID of the entity or avatar that the avatar is parented to. {@link Uuid(0)|Uuid.NULL} if not parented. @@ -449,35 +450,35 @@ public: // This calls through to the SpatiallyNestable versions, but is here to expose these to JavaScript. Q_INVOKABLE virtual const QUuid getParentID() const override { return SpatiallyNestable::getParentID(); } - /**jsdoc + /*@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. Q_INVOKABLE virtual void setParentID(const QUuid& parentID) override; - /**jsdoc + /*@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. + /*@jsdoc + * 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. Q_INVOKABLE virtual void setParentJointIndex(quint16 parentJointIndex) override; - /**jsdoc + /*@jsdoc * Gets information on all the joints in the avatar's skeleton. * @function MyAvatar.getSkeleton * @returns {SkeletonJoint[]} Information about each joint in the avatar's skeleton. @@ -497,7 +498,7 @@ public: void setTargetScale(float targetScale) override; float getTargetScale() const { return _targetScale; } - /**jsdoc + /*@jsdoc * @function MyAvatar.getSimulationRate * @param {AvatarSimulationRate} [rateName=""] - Rate name. * @returns {number} Simulation rate in Hz. @@ -556,8 +557,8 @@ public: uint32_t appendSubMetaItems(render::ItemIDs& subItems); signals: - /**jsdoc - * Triggered when the avatar's target scale is changed. The target scale is the desired scale of the avatar without any + /*@jsdoc + * 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. @@ -570,7 +571,7 @@ public slots: // FIXME - these should be migrated to use Pose data instead // thread safe, will return last valid palm from cache - /**jsdoc + /*@jsdoc * Gets the position of the left palm in world coordinates. * @function MyAvatar.getLeftPalmPosition * @returns {Vec3} The position of the left palm in world coordinates. @@ -579,7 +580,7 @@ public slots: */ glm::vec3 getLeftPalmPosition() const; - /**jsdoc + /*@jsdoc * Gets the rotation of the left palm in world coordinates. * @function MyAvatar.getLeftPalmRotation * @returns {Quat} The rotation of the left palm in world coordinates. @@ -588,7 +589,7 @@ public slots: */ glm::quat getLeftPalmRotation() const; - /**jsdoc + /*@jsdoc * Gets the position of the right palm in world coordinates. * @function MyAvatar.getRightPalmPosition * @returns {Vec3} The position of the right palm in world coordinates. @@ -597,7 +598,7 @@ public slots: */ glm::vec3 getRightPalmPosition() const; - /**jsdoc + /*@jsdoc * Get the rotation of the right palm in world coordinates. * @function MyAvatar.getRightPalmRotation * @returns {Quat} The rotation of the right palm in world coordinates. @@ -606,7 +607,7 @@ public slots: */ glm::quat getRightPalmRotation() const; - /**jsdoc + /*@jsdoc * @function MyAvatar.setModelURLFinished * @param {boolean} success * @deprecated This function is deprecated and will be removed. @@ -614,14 +615,14 @@ public slots: // hooked up to Model::setURLFinished signal void setModelURLFinished(bool success); - /**jsdoc + /*@jsdoc * @function MyAvatar.rigReady * @deprecated This function is deprecated and will be removed. */ // Hooked up to Model::rigReady signal void rigReady(); - /**jsdoc + /*@jsdoc * @function MyAvatar.rigReset * @deprecated This function is deprecated and will be removed. */ @@ -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 0b89e9d59e..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 @@ -16,7 +17,7 @@ #include "Avatar.h" -/**jsdoc +/*@jsdoc * Information about an avatar. * *

Create using {@link MyAvatar.getTargetAvatar} or {@link AvatarList.getAvatar}.

@@ -84,31 +85,31 @@ public: public slots: - /**jsdoc + /*@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; - /**jsdoc + /*@jsdoc * 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; - /**jsdoc + /*@jsdoc * Gets the offset applied to the avatar for rendering. * @function ScriptAvatar.getSkeletonOffset * @returns {Vec3} The skeleton offset if avatar data are available, otherwise {@link Vec3(0)|Vec3.ZERO}. @@ -116,16 +117,16 @@ public slots: glm::vec3 getSkeletonOffset() const; - /**jsdoc + /*@jsdoc * 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; - /**jsdoc + /*@jsdoc * Gets the position of a joint in the current avatar. * @function ScriptAvatar.getJointPosition * @param {string} name - The name of the joint. @@ -134,7 +135,7 @@ public slots: */ glm::vec3 getJointPosition(const QString& name) const; - /**jsdoc + /*@jsdoc * Gets the position of the current avatar's neck in world coordinates. * @function ScriptAvatar.getNeckPosition * @returns {Vec3} The position of the neck in world coordinates, or {@link Vec3(0)|Vec3.ZERO} if avatar data aren't @@ -143,7 +144,7 @@ public slots: glm::vec3 getNeckPosition() const; - /**jsdoc + /*@jsdoc * Gets the current acceleration of the avatar. * @function ScriptAvatar.getAcceleration * @returns {Vec3} The current acceleration of the avatar, or {@link Vec3(0)|Vec3.ZERO} if avatar data aren't available.. @@ -151,25 +152,25 @@ public slots: glm::vec3 getAcceleration() const; - /**jsdoc + /*@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; - /**jsdoc + /*@jsdoc * 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; - /**jsdoc + /*@jsdoc * Gets information on all the joints in the avatar's skeleton. * @function ScriptAvatar.getSkeleton * @returns {SkeletonJoint[]} Information about each joint in the avatar's skeleton. @@ -177,7 +178,7 @@ public slots: QVariantList getSkeleton() const; - /**jsdoc + /*@jsdoc * @function ScriptAvatar.getSimulationRate * @param {AvatarSimulationRate} [rateName=""] - Rate name. * @returns {number} Simulation rate in Hz, or 0.0 if avatar data aren't available. @@ -186,23 +187,23 @@ public slots: float getSimulationRate(const QString& rateName = QString("")) const; - /**jsdoc + /*@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; - /**jsdoc + /*@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; - /**jsdoc + /*@jsdoc * Gets the position of the right palm in world coordinates. * @function ScriptAvatar.getLeftPalmPosition * @returns {Vec3} The position of the right palm in world coordinates, or {@link Vec3(0)|Vec3.ZERO} if avatar data aren't @@ -210,7 +211,7 @@ public slots: */ glm::vec3 getRightPalmPosition() const; - /**jsdoc + /*@jsdoc * Gets the rotation of the right palm in world coordinates. * @function ScriptAvatar.getLeftPalmRotation * @returns {Quat} The rotation of the right palm in world coordinates, or {@link Quat(0)|Quat.IDENTITY} if the avatar data diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index adb7222ee3..cfea4fedd5 100755 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -1491,7 +1491,7 @@ int AvatarData::parseDataFromBuffer(const QByteArray& buffer) { return numBytesRead; } -/**jsdoc +/*@jsdoc *

The avatar mixer data comprises different types of data, with the data rates of each being tracked in kbps.

* *
@@ -1596,7 +1596,7 @@ float AvatarData::getDataRate(const QString& rateName) const { return 0.0f; } -/**jsdoc +/*@jsdoc *

The avatar mixer data comprises different types of data updated at different rates, in Hz.

* *
@@ -1938,6 +1938,10 @@ void AvatarData::clearJointsData() { } int AvatarData::getFauxJointIndex(const QString& name) const { + static constexpr QChar fauxJointFirstChar('_');// The first character of all the faux joint names. + if (!name.startsWith(fauxJointFirstChar)) { + return -1; + }; if (name == "_SENSOR_TO_WORLD_MATRIX") { return SENSOR_TO_WORLD_MATRIX_INDEX; } @@ -2246,7 +2250,7 @@ void AvatarData::processTraitInstance(AvatarTraits::TraitType traitType, void AvatarData::processDeletedTraitInstance(AvatarTraits::TraitType traitType, AvatarTraits::TraitInstanceID instanceID) { if (traitType == AvatarTraits::AvatarEntity) { - clearAvatarEntity(instanceID); + clearAvatarEntityInternal(instanceID); } else if (traitType == AvatarTraits::Grab) { clearAvatarGrabData(instanceID); } @@ -2922,7 +2926,7 @@ glm::vec3 AvatarData::getAbsoluteJointTranslationInObjectFrame(int index) const return glm::vec3(); } -/**jsdoc +/*@jsdoc * Information on an attachment worn by the avatar. * @typedef {object} AttachmentData * @property {string} modelUrl - The URL of the glTF, FBX, or OBJ model file. glTF models may be in JSON or binary format @@ -3034,6 +3038,10 @@ void AvatarData::updateAvatarEntity(const QUuid& entityID, const QByteArray& ent void AvatarData::clearAvatarEntity(const QUuid& entityID, bool requiresRemovalFromTree) { // NOTE: requiresRemovalFromTree is unused + clearAvatarEntityInternal(entityID); +} + +void AvatarData::clearAvatarEntityInternal(const QUuid& entityID) { bool removedEntity = false; _avatarEntitiesLock.withWriteLock([this, &removedEntity, &entityID] { removedEntity = _packedAvatarEntityData.remove(entityID); @@ -3046,6 +3054,24 @@ void AvatarData::clearAvatarEntity(const QUuid& entityID, bool requiresRemovalFr } } +void AvatarData::clearAvatarEntities() { + QList avatarEntityIDs; + _avatarEntitiesLock.withReadLock([&] { + avatarEntityIDs = _packedAvatarEntityData.keys(); + }); + for (const auto& entityID : avatarEntityIDs) { + clearAvatarEntityInternal(entityID); + } +} + +QList AvatarData::getAvatarEntityIDs() const { + QList avatarEntityIDs; + _avatarEntitiesLock.withReadLock([&] { + avatarEntityIDs = _packedAvatarEntityData.keys(); + }); + return avatarEntityIDs; +} + AvatarEntityMap AvatarData::getAvatarEntityData() const { // overridden where needed // NOTE: the return value is expected to be a map of unfortunately-formatted-binary-blobs @@ -3100,7 +3126,7 @@ glm::mat4 AvatarData::getControllerRightHandMatrix() const { return _controllerRightHandMatrixCache.get(); } -/**jsdoc +/*@jsdoc * Information about a ray-to-avatar intersection. * @typedef {object} RayToAvatarIntersectionResult * @property {boolean} intersects - true if an avatar is intersected, false if it isn't. @@ -3156,7 +3182,7 @@ float AvatarData::_avatarSortCoefficientSize { 8.0f }; float AvatarData::_avatarSortCoefficientCenter { 0.25f }; float AvatarData::_avatarSortCoefficientAge { 1.0f }; -/**jsdoc +/*@jsdoc * An object with the UUIDs of avatar entities as keys and avatar entity properties objects as values. * @typedef {Object.} AvatarEntityMap */ diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index 2e25c9559c..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 @@ -114,7 +115,7 @@ const int PROCEDURAL_BLINK_FACE_MOVEMENT = 10; // 11th bit const int COLLIDE_WITH_OTHER_AVATARS = 11; // 12th bit const int HAS_HERO_PRIORITY = 12; // 13th bit (be scared) -/**jsdoc +/*@jsdoc *

The pointing state of the hands is specified by the following values:

*
* @@ -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) @@ -712,7 +713,7 @@ public: void setHasAudioEnabledFaceMovement(bool hasAudioEnabledFaceMovement); bool getHasAudioEnabledFaceMovement() const; - /**jsdoc + /*@jsdoc * Gets the minimum scale allowed for this avatar in the current domain. * This value can change as the user changes avatars or when changing domains. * @function Avatar.getDomainMinScale @@ -720,7 +721,7 @@ public: */ Q_INVOKABLE float getDomainMinScale() const; - /**jsdoc + /*@jsdoc * Gets the maximum scale allowed for this avatar in the current domain. * This value can change as the user changes avatars or when changing domains. * @function Avatar.getDomainMaxScale @@ -736,7 +737,7 @@ public: // not all subclasses of AvatarData have access to this data. virtual bool canMeasureEyeHeight() const { return false; } - /**jsdoc + /*@jsdoc * Gets the current eye height of the avatar. * This height is only an estimate and might be incorrect for avatars that are missing standard joints. * @function Avatar.getEyeHeight @@ -744,7 +745,7 @@ public: */ Q_INVOKABLE virtual float getEyeHeight() const { return _targetScale * getUnscaledEyeHeight(); } - /**jsdoc + /*@jsdoc * Gets the current height of the avatar. * This height is only an estimate and might be incorrect for avatars that are missing standard joints. * @function Avatar.getHeight @@ -757,15 +758,15 @@ public: void setDomainMinimumHeight(float domainMinimumHeight); 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 + /*@jsdoc + * 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. */ Q_INVOKABLE void setHandState(char s) { _handState = s; } - /**jsdoc + /*@jsdoc * Gets 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.getHandState @@ -775,7 +776,7 @@ public: const QVector& getRawJointData() const { return _jointData; } - /**jsdoc + /*@jsdoc * Sets joint translations and rotations from raw joint data. * @function Avatar.setRawJointData * @param {JointData[]} data - The raw joint data. @@ -783,13 +784,13 @@ public: */ Q_INVOKABLE void setRawJointData(QVector data); - /**jsdoc + /*@jsdoc * 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. @@ -814,12 +815,12 @@ public: */ Q_INVOKABLE virtual void setJointData(int index, const glm::quat& rotation, const glm::vec3& translation); - /**jsdoc + /*@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. @@ -827,13 +828,13 @@ public: */ Q_INVOKABLE virtual void setJointRotation(int index, const glm::quat& rotation); - /**jsdoc + /*@jsdoc * 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. @@ -841,8 +842,8 @@ 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 + /*@jsdoc + * 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 @@ -850,7 +851,7 @@ public: */ Q_INVOKABLE virtual void clearJointData(int index); - /**jsdoc + /*@jsdoc * Checks that the data for a joint are valid. * @function Avatar.isJointDataValid * @param {number} index - The index of the joint. @@ -858,33 +859,33 @@ 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. + /*@jsdoc + * 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. */ Q_INVOKABLE virtual glm::quat getJointRotation(int index) const; - /**jsdoc + /*@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. */ Q_INVOKABLE virtual glm::vec3 getJointTranslation(int index) const; - /**jsdoc + /*@jsdoc * 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. @@ -893,12 +894,12 @@ public: */ Q_INVOKABLE virtual void setJointData(const QString& name, const glm::quat& rotation, const glm::vec3& translation); - /**jsdoc + /*@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. @@ -926,23 +927,23 @@ public: */ Q_INVOKABLE virtual void setJointRotation(const QString& name, const glm::quat& rotation); - /**jsdoc + /*@jsdoc * 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. * MyAvatar.setJointTranslation("Neck", Vec3.multiply(2, MyAvatar.getJointTranslation("Neck"))); - * + * * // Restore your avatar's neck after 5s. * Script.setTimeout(function () { * MyAvatar.clearJointData("Neck"); @@ -952,8 +953,8 @@ 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 + /*@jsdoc + * 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 @@ -971,7 +972,7 @@ public: */ Q_INVOKABLE virtual void clearJointData(const QString& name); - /**jsdoc + /*@jsdoc * Checks if the data for a joint are valid. * @function Avatar.isJointDataValid * @param {string} name - The name of the joint. @@ -979,9 +980,9 @@ 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. + /*@jsdoc + * 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. @@ -992,11 +993,11 @@ public: */ Q_INVOKABLE virtual glm::quat getJointRotation(const QString& name) const; - /**jsdoc + /*@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.

+ * 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. @@ -1007,10 +1008,10 @@ public: */ Q_INVOKABLE virtual glm::vec3 getJointTranslation(const QString& name) const; - /**jsdoc + /*@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
* print(JSON.stringify(MyAvatar.getJointRotations())); @@ -1019,18 +1020,18 @@ public: */ Q_INVOKABLE virtual QVector getJointRotations() const; - /**jsdoc + /*@jsdoc * Gets 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.

* @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; - /**jsdoc + /*@jsdoc * Sets the rotations of all joints in the current avatar. Each joint's rotation is relative to its parent joint. *

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, @@ -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
@@ -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 + + /*@jsdoc + * 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 + /*@jsdoc + * 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
@@ -1106,8 +1107,8 @@ 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 + /*@jsdoc + * 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. @@ -1120,7 +1121,7 @@ public: /// Returns the index of the joint with the specified name, or -1 if not found/unknown. Q_INVOKABLE virtual int getJointIndex(const QString& name) const; - /**jsdoc + /*@jsdoc * Gets the names of all the joints in the current avatar. * @function Avatar.getJointNames * @returns {string[]} The joint names. @@ -1132,13 +1133,13 @@ public: Q_INVOKABLE virtual QStringList getJointNames() const; - /**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. + /*@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. * @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 * MyAvatar.hasScriptedBlendshapes = true; @@ -1149,7 +1150,7 @@ public: Q_INVOKABLE void setBlendshape(QString name, float val) { _headData->setBlendshape(name, val); } - /**jsdoc + /*@jsdoc * Gets information about the models currently attached to your avatar. * @function Avatar.getAttachmentsVariant * @returns {AttachmentData[]} Information about all models attached to your avatar. @@ -1158,9 +1159,9 @@ public: // FIXME: Can this name be improved? Can it be deprecated? Q_INVOKABLE virtual QVariantList getAttachmentsVariant() const; - /**jsdoc + /*@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. @@ -1171,7 +1172,7 @@ public: virtual void storeAvatarEntityDataPayload(const QUuid& entityID, const QByteArray& payload); - /**jsdoc + /*@jsdoc * @function Avatar.updateAvatarEntity * @param {Uuid} entityID - The entity ID. * @param {ArrayBuffer} entityData - Entity data. @@ -1179,7 +1180,7 @@ public: */ Q_INVOKABLE virtual void updateAvatarEntity(const QUuid& entityID, const QByteArray& entityData); - /**jsdoc + /*@jsdoc * @function Avatar.clearAvatarEntity * @param {Uuid} entityID - The entity ID. * @param {boolean} [requiresRemovalFromTree=true] - unused @@ -1187,13 +1188,20 @@ public: */ Q_INVOKABLE virtual void clearAvatarEntity(const QUuid& entityID, bool requiresRemovalFromTree = true); - /**jsdoc - * Enables blend shapes set using {@link Avatar.setBlendshape} or {@link MyAvatar.setBlendshape} to be transmitted to other + // FIXME: Rename to clearAvatarEntity() once the API call is removed. + virtual void clearAvatarEntityInternal(const QUuid& entityID); + + void clearAvatarEntities(); + + QList getAvatarEntityIDs() const; + + /*@jsdoc + * 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); } @@ -1236,7 +1244,7 @@ public: const QString& getSessionDisplayName() const { return _sessionDisplayName; } bool getLookAtSnappingEnabled() const { return _lookAtSnappingEnabled; } - /**jsdoc + /*@jsdoc * Sets the avatar's skeleton model. * @function Avatar.setSkeletonModelURL * @param {string} url - The avatar's FST file. @@ -1250,7 +1258,7 @@ public: } virtual bool isCertifyFailed() const { return _verificationFailed; } - /**jsdoc + /*@jsdoc * Gets information about the models currently attached to your avatar. * @function Avatar.getAttachmentData * @returns {AttachmentData[]} Information about all models attached to your avatar. @@ -1265,9 +1273,9 @@ public: */ Q_INVOKABLE virtual QVector getAttachmentData() const; - /**jsdoc + /*@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 @@ -1289,23 +1297,23 @@ public: */ Q_INVOKABLE virtual void setAttachmentData(const QVector& attachmentData); - /**jsdoc + /*@jsdoc * 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. @@ -1333,21 +1341,21 @@ public: float scale = 1.0f, bool isSoft = false, bool allowDuplicates = false, bool useSaved = true); - /**jsdoc + /*@jsdoc * 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. */ Q_INVOKABLE virtual void detachOne(const QString& modelURL, const QString& jointName = QString()); - /**jsdoc + /*@jsdoc * 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. */ @@ -1387,7 +1395,7 @@ public: AABox getGlobalBoundingBox() const { return AABox(_globalPosition + _globalBoundingBoxOffset - _globalBoundingBoxDimensions, _globalBoundingBoxDimensions); } AABox getDefaultBubbleBox() const; - /**jsdoc + /*@jsdoc * @comment Documented in derived classes' JSDoc because implementations are different. */ // Get avatar entity data with all property values. Used in API. @@ -1396,7 +1404,7 @@ public: // Get avatar entity data with non-default property values. Used internally. virtual AvatarEntityMap getAvatarEntityDataNonDefault() const; - /**jsdoc + /*@jsdoc * @comment Documented in derived classes' JSDoc because implementations are different. */ Q_INVOKABLE virtual void setAvatarEntityData(const AvatarEntityMap& avatarEntityData); @@ -1404,10 +1412,10 @@ public: void setAvatarEntityDataChanged(bool value) { _avatarEntityDataChanged = value; } AvatarEntityIDs getAndClearRecentlyRemovedIDs(); - /**jsdoc + /*@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
* var sensorToWorldMatrix = MyAvatar.getSensorToWorldMatrix(); @@ -1421,16 +1429,16 @@ public: // thread safe Q_INVOKABLE glm::mat4 getSensorToWorldMatrix() const; - /**jsdoc + /*@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 Q_INVOKABLE float getSensorToWorldScale() const; - /**jsdoc + /*@jsdoc * Gets the rotation and translation of the left hand controller relative to the avatar. * @function Avatar.getControllerLeftHandMatrix * @returns {Mat4} The rotation and translation of the left hand controller relative to the avatar. @@ -1446,7 +1454,7 @@ public: // thread safe Q_INVOKABLE glm::mat4 getControllerLeftHandMatrix() const; - /**jsdoc + /*@jsdoc * Gets the rotation and translation of the right hand controller relative to the avatar. * @function Avatar.getControllerRightHandMatrix * @returns {Mat4} The rotation and translation of the right hand controller relative to the avatar. @@ -1455,7 +1463,7 @@ public: Q_INVOKABLE glm::mat4 getControllerRightHandMatrix() const; - /**jsdoc + /*@jsdoc * Gets the amount of avatar mixer data being generated by the avatar. * @function Avatar.getDataRate * @param {AvatarDataRate} [rateName=""] - The type of avatar mixer data to get the data rate of. @@ -1463,7 +1471,7 @@ public: */ Q_INVOKABLE float getDataRate(const QString& rateName = QString("")) const; - /**jsdoc + /*@jsdoc * Gets the update rate of avatar mixer data being generated by the avatar. * @function Avatar.getUpdateRate * @param {AvatarUpdateRate} [rateName=""] - The type of avatar mixer data to get the update rate of. @@ -1515,7 +1523,7 @@ public: signals: - /**jsdoc + /*@jsdoc * Triggered when the avatar's displayName property value changes. * @function Avatar.displayNameChanged * @returns {Signal} @@ -1528,7 +1536,7 @@ signals: */ void displayNameChanged(); - /**jsdoc + /*@jsdoc * Triggered when the avatar's sessionDisplayName property value changes. * @function Avatar.sessionDisplayNameChanged * @returns {Signal} @@ -1541,7 +1549,7 @@ signals: */ void sessionDisplayNameChanged(); - /**jsdoc + /*@jsdoc * Triggered when the avatar's model (i.e., skeletonModelURL property value) changes. * @function Avatar.skeletonModelURLChanged * @returns {Signal} @@ -1554,7 +1562,7 @@ signals: */ void skeletonModelURLChanged(); - /**jsdoc + /*@jsdoc * Triggered when the avatar's lookAtSnappingEnabled property value changes. * @function Avatar.lookAtSnappingChanged * @param {boolean} enabled - true if look-at snapping is enabled, false if not. @@ -1568,7 +1576,7 @@ signals: */ void lookAtSnappingChanged(bool enabled); - /**jsdoc + /*@jsdoc * Triggered when the avatar's sessionUUID property value changes. * @function Avatar.sessionUUIDChanged * @returns {Signal} @@ -1583,7 +1591,7 @@ signals: public slots: -/**jsdoc +/*@jsdoc * @function Avatar.sendAvatarDataPacket * @param {boolean} [sendAll=false] - Send all. * @returns {number} @@ -1591,14 +1599,14 @@ public slots: */ virtual int sendAvatarDataPacket(bool sendAll = false); - /**jsdoc + /*@jsdoc * @function Avatar.sendIdentityPacket * @returns {number} * @deprecated This function is deprecated and will be removed. */ int sendIdentityPacket(); - /**jsdoc + /*@jsdoc * @function Avatar.setSessionUUID * @param {Uuid} sessionUUID - Session UUID. * @deprecated This function is deprecated and will be removed. @@ -1615,7 +1623,7 @@ public slots: } - /**jsdoc + /*@jsdoc * Gets the rotation of a joint relative to the avatar. *

Warning: Not able to be used in the Avatar API.

* @function Avatar.getAbsoluteJointRotationInObjectFrame @@ -1624,7 +1632,7 @@ public slots: */ virtual glm::quat getAbsoluteJointRotationInObjectFrame(int index) const override; - /**jsdoc + /*@jsdoc * Gets the translation of a joint relative to the avatar. *

Warning: Not able to be used in the Avatar API.

* @function Avatar.getAbsoluteJointTranslationInObjectFrame @@ -1633,7 +1641,7 @@ public slots: */ virtual glm::vec3 getAbsoluteJointTranslationInObjectFrame(int index) const override; - /**jsdoc + /*@jsdoc * Sets the rotation of a joint relative to the avatar. *

Warning: Not able to be used in the Avatar API.

* @function Avatar.setAbsoluteJointRotationInObjectFrame @@ -1643,7 +1651,7 @@ public slots: */ virtual bool setAbsoluteJointRotationInObjectFrame(int index, const glm::quat& rotation) override { return false; } - /**jsdoc + /*@jsdoc * Sets the translation of a joint relative to the avatar. *

Warning: Not able to be used in the Avatar API.

* @function Avatar.setAbsoluteJointTranslationInObjectFrame @@ -1653,8 +1661,8 @@ 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 + /*@jsdoc + * 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. @@ -1666,7 +1674,7 @@ public slots: */ float getTargetScale() const { return _targetScale; } // why is this a slot? - /**jsdoc + /*@jsdoc * @function Avatar.resetLastSent * @deprecated This function is deprecated and will be removed. */ @@ -1696,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/AvatarHashMap.h b/libraries/avatars/src/AvatarHashMap.h index e12e5b4649..dcb0604e50 100644 --- a/libraries/avatars/src/AvatarHashMap.h +++ b/libraries/avatars/src/AvatarHashMap.h @@ -35,7 +35,7 @@ const int CLIENT_TO_AVATAR_MIXER_BROADCAST_FRAMES_PER_SECOND = 50; const quint64 MIN_TIME_BETWEEN_MY_AVATAR_DATA_SENDS = USECS_PER_SECOND / CLIENT_TO_AVATAR_MIXER_BROADCAST_FRAMES_PER_SECOND; -/**jsdoc +/*@jsdoc * The AvatarList API provides information about avatars within the current domain. * *

Warning: An API named "AvatarList" is also provided for Interface, client entity, and avatar @@ -80,7 +80,7 @@ public: // Currently, your own avatar will be included as the null avatar id. - /**jsdoc + /*@jsdoc * Gets the IDs of all avatars in the domain. *

Warning: If the AC script is acting as an avatar (i.e., Agent.isAvatar == true) the * avatar's ID is NOT included in results.

@@ -92,7 +92,7 @@ public: */ Q_INVOKABLE QVector getAvatarIdentifiers(); - /**jsdoc + /*@jsdoc * Gets the IDs of all avatars within a specified distance from a point. *

Warning: If the AC script is acting as an avatar (i.e., Agent.isAvatar == true) the * avatar's ID is NOT included in results.

@@ -107,7 +107,7 @@ public: */ Q_INVOKABLE QVector getAvatarsInRange(const glm::vec3& position, float rangeMeters) const; - /**jsdoc + /*@jsdoc * Gets information about an avatar. * @function AvatarList.getAvatar * @param {Uuid} avatarID - The ID of the avatar. @@ -126,7 +126,7 @@ public: signals: - /**jsdoc + /*@jsdoc * Triggered when an avatar arrives in the domain. * @function AvatarList.avatarAddedEvent * @param {Uuid} sessionUUID - The ID of the avatar that arrived in the domain. @@ -140,7 +140,7 @@ signals: */ void avatarAddedEvent(const QUuid& sessionUUID); - /**jsdoc + /*@jsdoc * Triggered when an avatar leaves the domain. * @function AvatarList.avatarRemovedEvent * @param {Uuid} sessionUUID - The ID of the avatar that left the domain. @@ -154,7 +154,7 @@ signals: */ void avatarRemovedEvent(const QUuid& sessionUUID); - /**jsdoc + /*@jsdoc * Triggered when an avatar's session ID changes. * @function AvatarList.avatarSessionChangedEvent * @param {Uuid} newSessionUUID - The new session ID. @@ -171,7 +171,7 @@ signals: public slots: - /**jsdoc + /*@jsdoc * Checks whether there is an avatar within a specified distance from a point. * @function AvatarList.isAvatarInRange * @param {string} position - The test position. @@ -183,7 +183,7 @@ public slots: protected slots: - /**jsdoc + /*@jsdoc * @function AvatarList.sessionUUIDChanged * @param {Uuid} sessionUUID - New session ID. * @param {Uuid} oldSessionUUID - Old session ID. @@ -191,7 +191,7 @@ protected slots: */ void sessionUUIDChanged(const QUuid& sessionUUID, const QUuid& oldUUID); - /**jsdoc + /*@jsdoc * @function AvatarList.processAvatarDataPacket * @param {object} message - Message. * @param {object} sendingNode - Sending node. @@ -199,7 +199,7 @@ protected slots: */ void processAvatarDataPacket(QSharedPointer message, SharedNodePointer sendingNode); - /**jsdoc + /*@jsdoc * @function AvatarList.processAvatarIdentityPacket * @param {object} message - Message. * @param {object} sendingNode - Sending node. @@ -207,7 +207,7 @@ protected slots: */ void processAvatarIdentityPacket(QSharedPointer message, SharedNodePointer sendingNode); - /**jsdoc + /*@jsdoc * @function AvatarList.processBulkAvatarTraits * @param {object} message - Message. * @param {object} sendingNode - Sending node. @@ -215,7 +215,7 @@ protected slots: */ void processBulkAvatarTraits(QSharedPointer message, SharedNodePointer sendingNode); - /**jsdoc + /*@jsdoc * @function AvatarList.processKillAvatar * @param {object} message - Message. * @param {object} sendingNode - Sending node. diff --git a/libraries/avatars/src/ScriptAvatarData.h b/libraries/avatars/src/ScriptAvatarData.h index 290e8c178a..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 @@ -107,7 +108,7 @@ public: // QString getSkeletonModelURLFromScript() const; - /**jsdoc + /*@jsdoc * Gets 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 ScriptAvatar.getHandState @@ -115,79 +116,79 @@ public: */ Q_INVOKABLE char getHandState() const; - /**jsdoc + /*@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; - /**jsdoc + /*@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.

+ * 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 + /*@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; - /**jsdoc + /*@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.

+ * 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; - /**jsdoc + /*@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; - /**jsdoc + /*@jsdoc * Gets the translations of all joints in the avatar. Each joint's translation is relative to its parent joint, in * 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; - /**jsdoc + /*@jsdoc * 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; - /**jsdoc + /*@jsdoc * Gets the joint index for a named joint. The joint index value is the position of the joint in the array returned by * {@linkScriptAvatar.getJointNames}. * @function ScriptAvatar.getJointIndex @@ -196,17 +197,17 @@ public: */ Q_INVOKABLE int getJointIndex(const QString& name) const; - /**jsdoc + /*@jsdoc * Gets the names of all the joints in the avatar. * @function ScriptAvatar.getJointNames * @returns {string[]} The joint names, or [] if the avatar data aren't available. */ Q_INVOKABLE QStringList getJointNames() const; - /**jsdoc + /*@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,33 +229,33 @@ public: glm::mat4 getSensorToWorldMatrix() const; glm::mat4 getControllerLeftHandMatrix() const; glm::mat4 getControllerRightHandMatrix() const; - + bool getHasPriority() const; signals: - /**jsdoc + /*@jsdoc * Triggered when the avatar's displayName property value changes. * @function ScriptAvatar.displayNameChanged * @returns {Signal} */ void displayNameChanged(); - /**jsdoc + /*@jsdoc * Triggered when the avatar's sessionDisplayName property value changes. * @function ScriptAvatar.sessionDisplayNameChanged * @returns {Signal} */ void sessionDisplayNameChanged(); - /**jsdoc + /*@jsdoc * Triggered when the avatar's model (i.e., skeletonModelURL property value) changes. * @function ScriptAvatar.skeletonModelURLChanged * @returns {Signal} */ void skeletonModelURLChanged(); - /**jsdoc + /*@jsdoc * Triggered when the avatar's lookAtSnappingEnabled property value changes. * @function ScriptAvatar.lookAtSnappingChanged * @param {boolean} enabled - true if look-at snapping is enabled, false if not. @@ -264,20 +265,20 @@ signals: public slots: - /**jsdoc + /*@jsdoc * 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; - /**jsdoc + /*@jsdoc * 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/baking/CMakeLists.txt b/libraries/baking/CMakeLists.txt index 4350f386ab..12fb192877 100644 --- a/libraries/baking/CMakeLists.txt +++ b/libraries/baking/CMakeLists.txt @@ -1,7 +1,7 @@ set(TARGET_NAME baking) setup_hifi_library(Concurrent) -link_hifi_libraries(shared shaders graphics networking procedural graphics-scripting ktx image fbx model-baker task) +link_hifi_libraries(shared shaders graphics networking procedural graphics-scripting ktx image model-serializers model-baker task) include_hifi_library_headers(gpu) include_hifi_library_headers(hfm) -include_hifi_library_headers(material-networking) \ No newline at end of file +include_hifi_library_headers(material-networking) diff --git a/libraries/baking/src/TextureBaker.cpp b/libraries/baking/src/TextureBaker.cpp index d70c6586b7..d9b63d6b7a 100644 --- a/libraries/baking/src/TextureBaker.cpp +++ b/libraries/baking/src/TextureBaker.cpp @@ -168,20 +168,20 @@ void TextureBaker::processTexture() { gpu::BackendTarget::GLES32 }}; for (auto target : BACKEND_TARGETS) { - auto processedTexture = image::processImage(buffer, _textureURL.toString().toStdString(), image::ColorChannel::NONE, - ABSOLUTE_MAX_TEXTURE_NUM_PIXELS, _textureType, true, - target, _abortProcessing); - if (!processedTexture) { + auto processedTextureAndSize = image::processImage(buffer, _textureURL.toString().toStdString(), image::ColorChannel::NONE, + ABSOLUTE_MAX_TEXTURE_NUM_PIXELS, _textureType, true, + target, _abortProcessing); + if (!processedTextureAndSize.first) { handleError("Could not process texture " + _textureURL.toString()); return; } - processedTexture->setSourceHash(hash); + processedTextureAndSize.first->setSourceHash(hash); if (shouldStop()) { return; } - auto memKTX = gpu::Texture::serialize(*processedTexture); + auto memKTX = gpu::Texture::serialize(*processedTextureAndSize.first, processedTextureAndSize.second); if (!memKTX) { handleError("Could not serialize " + _textureURL.toString() + " to KTX"); return; @@ -211,19 +211,19 @@ void TextureBaker::processTexture() { // Uncompressed KTX if (_textureType == image::TextureUsage::Type::SKY_TEXTURE || _textureType == image::TextureUsage::Type::AMBIENT_TEXTURE) { buffer->reset(); - auto processedTexture = image::processImage(std::move(buffer), _textureURL.toString().toStdString(), image::ColorChannel::NONE, - ABSOLUTE_MAX_TEXTURE_NUM_PIXELS, _textureType, false, gpu::BackendTarget::GL45, _abortProcessing); - if (!processedTexture) { + auto processedTextureAndSize = image::processImage(std::move(buffer), _textureURL.toString().toStdString(), image::ColorChannel::NONE, + ABSOLUTE_MAX_TEXTURE_NUM_PIXELS, _textureType, false, gpu::BackendTarget::GL45, _abortProcessing); + if (!processedTextureAndSize.first) { handleError("Could not process texture " + _textureURL.toString()); return; } - processedTexture->setSourceHash(hash); + processedTextureAndSize.first->setSourceHash(hash); if (shouldStop()) { return; } - auto memKTX = gpu::Texture::serialize(*processedTexture); + auto memKTX = gpu::Texture::serialize(*processedTextureAndSize.first, processedTextureAndSize.second); if (!memKTX) { handleError("Could not serialize " + _textureURL.toString() + " to KTX"); return; diff --git a/libraries/controllers/src/controllers/Actions.cpp b/libraries/controllers/src/controllers/Actions.cpp index 2edd1adfeb..5f95cff76b 100644 --- a/libraries/controllers/src/controllers/Actions.cpp +++ b/libraries/controllers/src/controllers/Actions.cpp @@ -33,7 +33,7 @@ namespace controller { return std::make_shared(input); } - /**jsdoc + /*@jsdoc *

The Controller.Actions object has properties representing predefined actions on the user's avatar and * Interface. The property values are integer IDs, uniquely identifying each action. Read-only.

*

These actions can be used as end points in the routes of a {@link MappingObject}. The data item routed to each action diff --git a/libraries/controllers/src/controllers/InputDevice.h b/libraries/controllers/src/controllers/InputDevice.h index 95d0524a4a..31143c9b4a 100644 --- a/libraries/controllers/src/controllers/InputDevice.h +++ b/libraries/controllers/src/controllers/InputDevice.h @@ -32,7 +32,7 @@ namespace controller { class Endpoint; using EndpointPointer = std::shared_ptr; -/**jsdoc +/*@jsdoc *

Some controller actions may be associated with one or both hands:

*
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
Report the rotations of all your avatar's joints.Set your avatar to its default T-pose then rotate its right arm.
* Avatar in T-pose
Set your avatar to it's default T-pose for a while.Open your avatar's mouth wide.Report the sensor to world matrix.
* @@ -52,7 +52,7 @@ enum Hand { BOTH }; -/**jsdoc +/*@jsdoc *

The Controller.Hardware object has properties representing standard and hardware-specific controller and * computer outputs, plus predefined actions on Interface and the user's avatar. Read-only.

*

The outputs can be mapped to actions or functions in a {@link RouteObject} mapping. Additionally, hardware-specific @@ -118,7 +118,7 @@ public: const QString& getName() const { return _name; } // By default, Input Devices do not support haptics - virtual bool triggerHapticPulse(float strength, float duration, controller::Hand hand) { return false; } + virtual bool triggerHapticPulse(float strength, float duration, uint16_t index) { return false; } // Update call MUST be called once per simulation loop // It takes care of updating the action states and deltas diff --git a/libraries/controllers/src/controllers/Pose.cpp b/libraries/controllers/src/controllers/Pose.cpp index 6df4b4af81..75f747deaa 100644 --- a/libraries/controllers/src/controllers/Pose.cpp +++ b/libraries/controllers/src/controllers/Pose.cpp @@ -30,7 +30,7 @@ namespace controller { velocity == right.getVelocity() && angularVelocity == right.getAngularVelocity(); } - /**jsdoc + /*@jsdoc * The pose of a joint or other item relative to the world or a parent. * @typedef {object} Pose * @property {Vec3} translation - Translation. diff --git a/libraries/controllers/src/controllers/ScriptingInterface.cpp b/libraries/controllers/src/controllers/ScriptingInterface.cpp index fd32b2eb43..e9a831859d 100644 --- a/libraries/controllers/src/controllers/ScriptingInterface.cpp +++ b/libraries/controllers/src/controllers/ScriptingInterface.cpp @@ -134,13 +134,13 @@ namespace controller { return DependencyManager::get()->getActionNames(); } - bool ScriptingInterface::triggerHapticPulse(float strength, float duration, controller::Hand hand) const { - return DependencyManager::get()->triggerHapticPulse(strength, duration, hand); + bool ScriptingInterface::triggerHapticPulse(float strength, float duration, uint16_t index) const { + return DependencyManager::get()->triggerHapticPulse(strength, duration, index); } - bool ScriptingInterface::triggerShortHapticPulse(float strength, controller::Hand hand) const { + bool ScriptingInterface::triggerShortHapticPulse(float strength, uint16_t index) const { const float SHORT_HAPTIC_DURATION_MS = 250.0f; - return DependencyManager::get()->triggerHapticPulse(strength, SHORT_HAPTIC_DURATION_MS, hand); + return DependencyManager::get()->triggerHapticPulse(strength, SHORT_HAPTIC_DURATION_MS, index); } void ScriptingInterface::startInputRecording() { @@ -189,13 +189,13 @@ namespace controller { emit inputDeviceRunningChanged(deviceName, isRunning); } - bool ScriptingInterface::triggerHapticPulseOnDevice(unsigned int device, float strength, float duration, controller::Hand hand) const { - return DependencyManager::get()->triggerHapticPulseOnDevice(device, strength, duration, hand); + bool ScriptingInterface::triggerHapticPulseOnDevice(unsigned int device, float strength, float duration, uint16_t index) const { + return DependencyManager::get()->triggerHapticPulseOnDevice(device, strength, duration, index); } - bool ScriptingInterface::triggerShortHapticPulseOnDevice(unsigned int device, float strength, controller::Hand hand) const { + bool ScriptingInterface::triggerShortHapticPulseOnDevice(unsigned int device, float strength, uint16_t index) const { const float SHORT_HAPTIC_DURATION_MS = 250.0f; - return DependencyManager::get()->triggerHapticPulseOnDevice(device, strength, SHORT_HAPTIC_DURATION_MS, hand); + return DependencyManager::get()->triggerHapticPulseOnDevice(device, strength, SHORT_HAPTIC_DURATION_MS, index); } void ScriptingInterface::updateMaps() { diff --git a/libraries/controllers/src/controllers/ScriptingInterface.h b/libraries/controllers/src/controllers/ScriptingInterface.h index a1875c7fe8..7ea4814faf 100644 --- a/libraries/controllers/src/controllers/ScriptingInterface.h +++ b/libraries/controllers/src/controllers/ScriptingInterface.h @@ -72,7 +72,7 @@ namespace controller { ScriptingInterface(); virtual ~ScriptingInterface() {}; - /**jsdoc + /*@jsdoc * Gets a list of all available actions. * @function Controller.getAllActions * @returns {Action[]} All available actions. @@ -81,7 +81,7 @@ namespace controller { // FIXME: This function causes a JavaScript crash: https://highfidelity.manuscript.com/f/cases/edit/13921 Q_INVOKABLE QVector getAllActions(); - /**jsdoc + /*@jsdoc * Gets a list of all available inputs for a hardware device. * @function Controller.getAvailableInputs * @param {number} deviceID - Integer ID of the hardware device. @@ -91,7 +91,7 @@ namespace controller { // FIXME: This function causes a JavaScript crash: https://highfidelity.manuscript.com/f/cases/edit/13922 Q_INVOKABLE QVector getAvailableInputs(unsigned int device); - /**jsdoc + /*@jsdoc * Finds the name of a particular controller from its device ID. * @function Controller.getDeviceName * @param {number} deviceID - The integer ID of the device. @@ -105,7 +105,7 @@ namespace controller { */ Q_INVOKABLE QString getDeviceName(unsigned int device); - /**jsdoc + /*@jsdoc * Gets the current value of an action. * @function Controller.getActionValue * @param {number} actionID - The integer ID of the action. @@ -120,7 +120,7 @@ namespace controller { */ Q_INVOKABLE float getActionValue(int action); - /**jsdoc + /*@jsdoc * Finds the ID of a specific controller from its device name. * @function Controller.findDevice * @param {string} deviceName - The name of the device to find. @@ -131,7 +131,7 @@ namespace controller { */ Q_INVOKABLE int findDevice(QString name); - /**jsdoc + /*@jsdoc * Gets the names of all currently available controller devices plus "Actions", "Application", and "Standard". * @function Controller.getDeviceNames * @returns {string[]} An array of device names. @@ -142,7 +142,7 @@ namespace controller { */ Q_INVOKABLE QVector getDeviceNames(); - /**jsdoc + /*@jsdoc * Finds the ID of an action from its name. * @function Controller.findAction * @param {string} actionName - The name of the action: one of the {@link Controller.Actions} property names. @@ -155,7 +155,7 @@ namespace controller { */ Q_INVOKABLE int findAction(QString actionName); - /**jsdoc + /*@jsdoc * Gets the names of all actions available as properties of {@link Controller.Actions}. * @function Controller.getActionNames * @returns {string[]} An array of action names. @@ -166,7 +166,7 @@ namespace controller { */ Q_INVOKABLE QVector getActionNames() const; - /**jsdoc + /*@jsdoc * Gets the value of a controller button or axis output. Note: Also gets the value of a controller axis output. * @function Controller.getValue * @param {number} source - The {@link Controller.Standard} or {@link Controller.Hardware} item. @@ -185,7 +185,7 @@ namespace controller { */ Q_INVOKABLE float getValue(const int& source) const; - /**jsdoc + /*@jsdoc * Gets the value of a controller axis output. Note: Also gets the value of a controller button output. * @function Controller.getAxisValue * @param {number} source - The {@link Controller.Standard} or {@link Controller.Hardware} item. @@ -195,7 +195,7 @@ namespace controller { // TODO: getAxisValue() should use const int& parameter? Or others shouldn't? Q_INVOKABLE float getAxisValue(int source) const; - /**jsdoc + /*@jsdoc * Gets the value of a controller pose output. * @function Controller.getPoseValue * @param {number} source - The {@link Controller.Standard} or {@link Controller.Hardware} pose output. @@ -207,35 +207,44 @@ namespace controller { */ Q_INVOKABLE Pose getPoseValue(const int& source) const; - /**jsdoc + /*@jsdoc * Triggers a haptic pulse on connected and enabled devices that have the capability. * @function Controller.triggerHapticPulse * @param {number} strength - The strength of the haptic pulse, range 0.01.0. * @param {number} duration - The duration of the haptic pulse, in milliseconds. - * @param {Controller.Hand} [hand=2] - The hand or hands to trigger the haptic pulse on. + * @param {number} [index=2] - The index on devices on which to trigger the haptic pulse. The meaning of each index + * will vary by device. For example, for hand controllers, index = 0 is the left hand, + * index = 1 is the right hand, and index = 2 is both hands. For other devices, + * such as haptic vests, index will have a different meaning, defined by the input device. * @example

* var HAPTIC_STRENGTH = 0.5; * var HAPTIC_DURATION = 10; * var RIGHT_HAND = 1; * Controller.triggerHapticPulse(HAPTIC_STRENGTH, HAPTIC_DURATION, RIGHT_HAND); */ - Q_INVOKABLE bool triggerHapticPulse(float strength, float duration, controller::Hand hand = BOTH) const; + Q_INVOKABLE bool triggerHapticPulse(float strength, float duration, uint16_t index = 2) const; - /**jsdoc + /*@jsdoc * Triggers a 250ms haptic pulse on connected and enabled devices that have the capability. * @function Controller.triggerShortHapticPulse * @param {number} strength - The strength of the haptic pulse, range 0.01.0. - * @param {Controller.Hand} [hand=2] - The hand or hands to trigger the haptic pulse on. + * @param {number} [index=2] - The index on devices on which to trigger the haptic pulse. The meaning of each index + * will vary by device. For example, for hand controllers, index = 0 is the left hand, + * index = 1 is the right hand, and index = 2 is both hands. For other devices, + * such as haptic vests, index will have a different meaning, defined by the input device. */ - Q_INVOKABLE bool triggerShortHapticPulse(float strength, controller::Hand hand = BOTH) const; + Q_INVOKABLE bool triggerShortHapticPulse(float strength, uint16_t index = 2) const; - /**jsdoc + /*@jsdoc * Triggers a haptic pulse on a particular device if connected and enabled and it has the capability. * @function Controller.triggerHapticPulseOnDevice * @param {number} deviceID - The ID of the device to trigger the haptic pulse on. * @param {number} strength - The strength of the haptic pulse, range 0.01.0. * @param {number} duration - The duration of the haptic pulse, in milliseconds. - * @param {Controller.Hand} [hand=2] - The hand or hands to trigger the haptic pulse on. + * @param {number} [index=2] - The index on this device on which to trigger the haptic pulse. The meaning of each index + * will vary by device. For example, for hand controllers, index = 0 is the left hand, + * index = 1 is the right hand, and index = 2 is both hands. For other devices, + * such as haptic vests, index will have a different meaning, defined by the input device. * @example * var HAPTIC_STRENGTH = 0.5; * var deviceID = Controller.findDevice("OculusTouch"); @@ -243,21 +252,22 @@ namespace controller { * var RIGHT_HAND = 1; * Controller.triggerHapticPulseOnDevice(deviceID, HAPTIC_STRENGTH, HAPTIC_DURATION, RIGHT_HAND); */ - Q_INVOKABLE bool triggerHapticPulseOnDevice(unsigned int device, float strength, float duration, - controller::Hand hand = BOTH) const; + Q_INVOKABLE bool triggerHapticPulseOnDevice(unsigned int device, float strength, float duration, + uint16_t index = 2) const; - /**jsdoc + /*@jsdoc * Triggers a 250ms haptic pulse on a particular device if connected and enabled and it has the capability. * @function Controller.triggerShortHapticPulseOnDevice * @param {number} deviceID - The ID of the device to trigger the haptic pulse on. * @param {number} strength - The strength of the haptic pulse, range 0.01.0. - * @param {Controller.Hand} [hand=2] - The hand or hands to trigger the haptic pulse on. + * @param {number} [index=2] - The index on this device on which to trigger the haptic pulse. The meaning of each index + * will vary by device. For example, for hand controllers, index = 0 is the left hand, + * index = 1 is the right hand, and index = 2 is both hands. For other devices, + * such as haptic vests, index will have a different meaning, defined by the input device. */ - Q_INVOKABLE bool triggerShortHapticPulseOnDevice(unsigned int device, float strength, controller::Hand hand = BOTH) - const; + Q_INVOKABLE bool triggerShortHapticPulseOnDevice(unsigned int device, float strength, uint16_t index = 2) const; - - /**jsdoc + /*@jsdoc * Creates a new controller mapping. Routes can then be added to the mapping using {@link MappingObject} methods and * routed to Standard controls, Actions, or script functions using {@link RouteObject} * methods. The mapping can then be enabled using {@link Controller.enableMapping|enableMapping} for it to take effect. @@ -278,7 +288,7 @@ namespace controller { */ Q_INVOKABLE QObject* newMapping(const QString& mappingName = QUuid::createUuid().toString()); - /**jsdoc + /*@jsdoc * Enables or disables a controller mapping. When enabled, the routes in the mapping have effect. * @function Controller.enableMapping * @param {string} mappingName - The name of the mapping. @@ -286,14 +296,14 @@ namespace controller { */ Q_INVOKABLE void enableMapping(const QString& mappingName, bool enable = true); - /**jsdoc + /*@jsdoc * Disables a controller mapping. When disabled, the routes in the mapping have no effect. * @function Controller.disableMapping * @param {string} mappingName - The name of the mapping. */ Q_INVOKABLE void disableMapping(const QString& mappingName) { enableMapping(mappingName, false); } - /**jsdoc + /*@jsdoc * Creates a new controller mapping from a {@link Controller.MappingJSON|MappingJSON} string. Use * {@link Controller.enableMapping|enableMapping} to enable the mapping for it to take effect. * @function Controller.parseMapping @@ -316,7 +326,7 @@ namespace controller { */ Q_INVOKABLE QObject* parseMapping(const QString& json); - /**jsdoc + /*@jsdoc * Creates a new controller mapping from a {@link Controller.MappingJSON|MappingJSON} JSON file at a URL. Use * {@link Controller.enableMapping|enableMapping} to enable the mapping for it to take effect. *

Warning: This function is not yet implemented; it doesn't load a mapping and just returns @@ -328,7 +338,7 @@ namespace controller { Q_INVOKABLE QObject* loadMapping(const QString& jsonUrl); - /**jsdoc + /*@jsdoc * Gets the {@link Controller.Hardware} property tree. Calling this function is the same as using the {@link Controller} * property, Controller.Hardware. * @function Controller.getHardware @@ -336,7 +346,7 @@ namespace controller { */ Q_INVOKABLE const QVariantMap getHardware() { return _hardware; } - /**jsdoc + /*@jsdoc * Gets the {@link Controller.Actions} property tree. Calling this function is the same as using the {@link Controller} * property, Controller.Actions. * @function Controller.getActions @@ -344,7 +354,7 @@ namespace controller { */ Q_INVOKABLE const QVariantMap getActions() { return _actions; } //undefined - /**jsdoc + /*@jsdoc * Gets the {@link Controller.Standard} property tree. Calling this function is the same as using the {@link Controller} * property, Controller.Standard. * @function Controller.getStandard @@ -353,7 +363,7 @@ namespace controller { Q_INVOKABLE const QVariantMap getStandard() { return _standard; } - /**jsdoc + /*@jsdoc * Starts making a recording of currently active controllers. * @function Controller.startInputRecording * @example

@@ -373,13 +383,13 @@ namespace controller { */ Q_INVOKABLE void startInputRecording(); - /**jsdoc + /*@jsdoc * Stops making a recording started by {@link Controller.startInputRecording|startInputRecording}. * @function Controller.stopInputRecording */ Q_INVOKABLE void stopInputRecording(); - /**jsdoc + /*@jsdoc * Plays back the current recording from the beginning. The current recording may have been recorded by * {@link Controller.startInputRecording|startInputRecording} and * {@link Controller.stopInputRecording|stopInputRecording}, or loaded by @@ -402,13 +412,13 @@ namespace controller { */ Q_INVOKABLE void startInputPlayback(); - /**jsdoc + /*@jsdoc * Stops play back of a recording started by {@link Controller.startInputPlayback|startInputPlayback}. * @function Controller.stopInputPlayback */ Q_INVOKABLE void stopInputPlayback(); - /**jsdoc + /*@jsdoc * Saves the current recording to a file. The current recording may have been recorded by * {@link Controller.startInputRecording|startInputRecording} and * {@link Controller.stopInputRecording|stopInputRecording}, or loaded by @@ -418,21 +428,21 @@ namespace controller { */ Q_INVOKABLE void saveInputRecording(); - /**jsdoc + /*@jsdoc * Loads an input recording, ready for play back. * @function Controller.loadInputRecording * @param {string} file - The path to the recording file, prefixed by "file:///". */ Q_INVOKABLE void loadInputRecording(const QString& file); - /**jsdoc + /*@jsdoc * Gets the directory in which input recordings are saved. * @function Controller.getInputRecorderSaveDirectory * @returns {string} The directory in which input recordings are saved. */ Q_INVOKABLE QString getInputRecorderSaveDirectory(); - /**jsdoc + /*@jsdoc * Gets the names of all the active and running (enabled) input devices. * @function Controller.getRunningInputDevices * @returns {string[]} The list of current active and running input devices. @@ -448,7 +458,7 @@ namespace controller { public slots: - /**jsdoc + /*@jsdoc * Disables processing of mouse "move", "press", "double-press", and "release" events into * {@link Controller.Hardware|Controller.Hardware.Keyboard} outputs. * @function Controller.captureMouseEvents @@ -476,7 +486,7 @@ namespace controller { */ virtual void captureMouseEvents() { _mouseCaptured = true; } - /**jsdoc + /*@jsdoc * Enables processing of mouse "move", "press", "double-press", and "release" events into * {@link Controller.Hardware-Keyboard|Controller.Hardware.Keyboard} outputs that were disabled using * {@link Controller.captureMouseEvents|captureMouseEvents}. @@ -485,7 +495,7 @@ namespace controller { virtual void releaseMouseEvents() { _mouseCaptured = false; } - /**jsdoc + /*@jsdoc * Disables processing of touch "begin", "update", and "end" events into * {@link Controller.Hardware|Controller.Hardware.Keyboard}, * {@link Controller.Hardware|Controller.Hardware.Touchscreen}, and @@ -494,7 +504,7 @@ namespace controller { */ virtual void captureTouchEvents() { _touchCaptured = true; } - /**jsdoc + /*@jsdoc * Enables processing of touch "begin", "update", and "end" events into * {@link Controller.Hardware|Controller.Hardware.Keyboard}, * {@link Controller.Hardware|Controller.Hardware.Touchscreen}, and @@ -505,14 +515,14 @@ namespace controller { virtual void releaseTouchEvents() { _touchCaptured = false; } - /**jsdoc + /*@jsdoc * Disables processing of mouse wheel rotation events into {@link Controller.Hardware|Controller.Hardware.Keyboard} * outputs. * @function Controller.captureWheelEvents */ virtual void captureWheelEvents() { _wheelCaptured = true; } - /**jsdoc + /*@jsdoc * Enables processing of mouse wheel rotation events into {@link Controller.Hardware|Controller.Hardware.Keyboard} * outputs that wer disabled using {@link Controller.captureWheelEvents|captureWheelEvents}. * @function Controller.releaseWheelEvents @@ -520,7 +530,7 @@ namespace controller { virtual void releaseWheelEvents() { _wheelCaptured = false; } - /**jsdoc + /*@jsdoc * Disables translating and rotating the user's avatar in response to keyboard and controller controls. * @function Controller.captureActionEvents * @example @@ -534,14 +544,14 @@ namespace controller { */ virtual void captureActionEvents() { _actionsCaptured = true; } - /**jsdoc + /*@jsdoc * Enables translating and rotating the user's avatar in response to keyboard and controller controls that were disabled * using {@link Controller.captureActionEvents|captureActionEvents}. * @function Controller.releaseActionEvents */ virtual void releaseActionEvents() { _actionsCaptured = false; } - /**jsdoc + /*@jsdoc * @function Controller.updateRunningInputDevices * @param {string} deviceName - Device name. * @param {boolean} isRunning - Is running. @@ -551,7 +561,7 @@ namespace controller { void updateRunningInputDevices(const QString& deviceName, bool isRunning, const QStringList& runningDevices); signals: - /**jsdoc + /*@jsdoc * Triggered when an action occurs. * @function Controller.actionEvent * @param {number} actionID - The ID of the action, per {@link Controller.findAction|findAction}. @@ -576,7 +586,7 @@ namespace controller { */ void actionEvent(int action, float state); - /**jsdoc + /*@jsdoc * Triggered when there is a new controller input event. * @function Controller.inputEvent * @param {number} action - The input action, per {@link Controller.Standard}. @@ -600,7 +610,7 @@ namespace controller { */ void inputEvent(int action, float state); - /**jsdoc + /*@jsdoc * Triggered when a device is registered or unregistered by a plugin. Not all plugins generate * hardwareChanged events: for example, connecting or disconnecting a mouse will not generate an event but * connecting or disconnecting an Xbox controller will. @@ -609,7 +619,7 @@ namespace controller { */ void hardwareChanged(); - /**jsdoc + /*@jsdoc * Triggered when an input device starts or stops being active and running (enabled). For example, enabling or * disabling the LeapMotion in Settings > Controls > Calibration will trigger this signal. * @function Controller.inputDeviceRunningChanged diff --git a/libraries/controllers/src/controllers/StandardController.cpp b/libraries/controllers/src/controllers/StandardController.cpp index 41835223ea..9bf10753fe 100644 --- a/libraries/controllers/src/controllers/StandardController.cpp +++ b/libraries/controllers/src/controllers/StandardController.cpp @@ -27,7 +27,7 @@ void StandardController::focusOutEvent() { _buttonPressedMap.clear(); }; -/**jsdoc +/*@jsdoc *

The Controller.Standard object has properties representing standard controller outputs. Those for physical * controllers are based on the XBox controller, with aliases for PlayStation. The property values are integer IDs, uniquely * identifying each output. Read-only.

diff --git a/libraries/controllers/src/controllers/UserInputMapper.cpp b/libraries/controllers/src/controllers/UserInputMapper.cpp index 604a4f9c73..6333792b3f 100755 --- a/libraries/controllers/src/controllers/UserInputMapper.cpp +++ b/libraries/controllers/src/controllers/UserInputMapper.cpp @@ -365,19 +365,19 @@ Pose UserInputMapper::getPoseState(Action action) const { } -bool UserInputMapper::triggerHapticPulse(float strength, float duration, controller::Hand hand) { +bool UserInputMapper::triggerHapticPulse(float strength, float duration, uint16_t index) { Locker locker(_lock); bool toReturn = false; for (const auto& device : _registeredDevices) { - toReturn = device.second->triggerHapticPulse(strength, duration, hand) || toReturn; + toReturn = device.second->triggerHapticPulse(strength, duration, index) || toReturn; } return toReturn; } -bool UserInputMapper::triggerHapticPulseOnDevice(uint16 deviceID, float strength, float duration, controller::Hand hand) { +bool UserInputMapper::triggerHapticPulseOnDevice(uint16 deviceID, float strength, float duration, uint16_t index) { Locker locker(_lock); if (_registeredDevices.find(deviceID) != _registeredDevices.end()) { - return _registeredDevices[deviceID]->triggerHapticPulse(strength, duration, hand); + return _registeredDevices[deviceID]->triggerHapticPulse(strength, duration, index); } return false; } diff --git a/libraries/controllers/src/controllers/UserInputMapper.h b/libraries/controllers/src/controllers/UserInputMapper.h index 79fcf6e64c..ee8b34193f 100644 --- a/libraries/controllers/src/controllers/UserInputMapper.h +++ b/libraries/controllers/src/controllers/UserInputMapper.h @@ -91,8 +91,8 @@ namespace controller { void setActionState(Action action, float value, bool valid = true); void deltaActionState(Action action, float delta, bool valid = true); void setActionState(Action action, const Pose& value) { _poseStates[toInt(action)] = value; } - bool triggerHapticPulse(float strength, float duration, controller::Hand hand); - bool triggerHapticPulseOnDevice(uint16 deviceID, float strength, float duration, controller::Hand hand); + bool triggerHapticPulse(float strength, float duration, uint16_t index); + bool triggerHapticPulseOnDevice(uint16 deviceID, float strength, float duration, uint16_t index); static Input makeStandardInput(controller::StandardButtonChannel button); static Input makeStandardInput(controller::StandardAxisChannel axis); diff --git a/libraries/controllers/src/controllers/impl/MappingBuilderProxy.h b/libraries/controllers/src/controllers/impl/MappingBuilderProxy.h index 9dafc03f1f..8d1fb21610 100644 --- a/libraries/controllers/src/controllers/impl/MappingBuilderProxy.h +++ b/libraries/controllers/src/controllers/impl/MappingBuilderProxy.h @@ -24,7 +24,7 @@ namespace controller { class ScriptingInterface; class UserInputMapper; -/**jsdoc +/*@jsdoc *

A {@link Controller} mapping object that can contain a set of routes that map:

*
Trigger a haptic pulse on the right hand.Trigger a haptic pulse on an Oculus Touch controller.Make a controller recording.Disable avatar translation and rotation for a short period.
* diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 6e761698c9..73fa44ba09 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -1772,13 +1772,11 @@ bool EntityItem::contains(const glm::vec3& point) const { ShapeType shapeType = getShapeType(); if (shapeType == SHAPE_TYPE_SPHERE) { - // SPHERE case is special: - // anything with shapeType == SPHERE must collide as a bounding sphere in the world-frame regardless of dimensions - // therefore we must do math using an unscaled localPoint relative to sphere center glm::vec3 dimensions = getScaledDimensions(); - glm::vec3 localPoint = point - (getWorldPosition() + getWorldOrientation() * (dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint()) + getPivot())); - const float HALF_SQUARED = 0.25f; - return glm::length2(localPoint) < HALF_SQUARED * glm::length2(dimensions); + if (dimensions.x == dimensions.y && dimensions.y == dimensions.z) { + glm::vec3 localPoint = point - (getWorldPosition() + getWorldOrientation() * (dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint()) + getPivot())); + return glm::length2(localPoint) < glm::length2(0.5f * dimensions.x); + } } // we transform into the "normalized entity-frame" where the bounding box is centered on the origin @@ -1805,6 +1803,7 @@ bool EntityItem::contains(const glm::vec3& point) const { localPoint = glm::abs(localPoint); return glm::all(glm::lessThanEqual(localPoint, glm::vec3(NORMALIZED_HALF_SIDE))); } + case SHAPE_TYPE_SPHERE: case SHAPE_TYPE_ELLIPSOID: { // since we've transformed into the normalized space this is just a sphere-point intersection test return glm::length2(localPoint) <= NORMALIZED_RADIUS_SQUARED; diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index ebb06eac43..ed396f88c9 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -664,7 +664,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { return changedProperties; } -/**jsdoc +/*@jsdoc * Different entity types have different properties: some common to all entities (listed in the table) and some specific to * each {@link Entities.EntityType|EntityType} (linked to below). * @@ -723,7 +723,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { * * @property {Vec3} naturalPosition=0,0,0 - The center of the entity's unscaled mesh model if it has one, otherwise * {@link Vec3(0)|Vec3.ZERO}. Read-only. - * @property {Vec3} naturalDimensions - The dimensions of the entity's unscaled mesh model if it has one, otherwise + * @property {Vec3} naturalDimensions - The dimensions of the entity's unscaled mesh model or image if it has one, otherwise * {@link Vec3(0)|Vec3.ONE}. Read-only. * * @property {Vec3} velocity=0,0,0 - The linear velocity of the entity in m/s with respect to world coordinates. @@ -871,7 +871,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { * @see {@link Entities.EntityProperties-Zone|EntityProperties-Zone} */ -/**jsdoc +/*@jsdoc * The "Box" {@link Entities.EntityType|EntityType} is the same as the "Shape" * {@link Entities.EntityType|EntityType} except that its shape value is always set to "Cube" * when the entity is created. If its shape property value is subsequently changed then the entity's @@ -882,7 +882,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { * @see {@link Entities.EntityProperties-Shape|EntityProperties-Shape} */ -/**jsdoc +/*@jsdoc * The "Light" {@link Entities.EntityType|EntityType} adds local lighting effects. It has properties in addition * to the common {@link Entities.EntityProperties|EntityProperties}. * @@ -911,7 +911,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { * }); */ -/**jsdoc +/*@jsdoc * The "Line" {@link Entities.EntityType|EntityType} draws thin, straight lines between a sequence of two or more * points. It has properties in addition to the common {@link Entities.EntityProperties|EntityProperties}. *

Deprecated: Use {@link Entities.EntityProperties-PolyLine|PolyLine} entities instead.

@@ -939,7 +939,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { * }); */ -/**jsdoc +/*@jsdoc * The "Material" {@link Entities.EntityType|EntityType} modifies existing materials on entities and avatars. It * has properties in addition to the common {@link Entities.EntityProperties|EntityProperties}. *

To apply a material to an entity, set the material entity's parentID property to the entity ID. @@ -1006,7 +1006,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { * }); */ -/**jsdoc +/*@jsdoc * The "Model" {@link Entities.EntityType|EntityType} displays a glTF, FBX, or OBJ model. When adding an entity, * if no dimensions value is specified then the model is automatically sized to its * {@link Entities.EntityProperties|naturalDimensions}. It has properties in addition to the common @@ -1078,7 +1078,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { * }); */ -/**jsdoc +/*@jsdoc * The "ParticleEffect" {@link Entities.EntityType|EntityType} displays a particle system that can be used to * simulate things such as fire, smoke, snow, magic spells, etc. The particles emanate from an ellipsoid or part thereof. * It has properties in addition to the common {@link Entities.EntityProperties|EntityProperties}. @@ -1195,7 +1195,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { * }); */ -/**jsdoc +/*@jsdoc * The "PolyLine" {@link Entities.EntityType|EntityType} draws textured, straight lines between a sequence of * points. It has properties in addition to the common {@link Entities.EntityProperties|EntityProperties}. * @@ -1245,7 +1245,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { * }); */ -/**jsdoc +/*@jsdoc * The "PolyVox" {@link Entities.EntityType|EntityType} displays a set of textured voxels. * It has properties in addition to the common {@link Entities.EntityProperties|EntityProperties}. * If you have two or more neighboring PolyVox entities of the same size abutting each other, you can display them as joined by @@ -1299,7 +1299,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { * Entities.setVoxelSphere(polyVox, position, 0.8, 255); */ -/**jsdoc +/*@jsdoc * The "Shape" {@link Entities.EntityType|EntityType} displays an entity of a specified shape. * It has properties in addition to the common {@link Entities.EntityProperties|EntityProperties}. * @@ -1320,7 +1320,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { * }); */ -/**jsdoc +/*@jsdoc * The "Sphere" {@link Entities.EntityType|EntityType} is the same as the "Shape" * {@link Entities.EntityType|EntityType} except that its shape value is always set to "Sphere" * when the entity is created. If its shape property value is subsequently changed then the entity's @@ -1331,7 +1331,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { * @see {@link Entities.EntityProperties-Shape|EntityProperties-Shape} */ -/**jsdoc +/*@jsdoc * The "Text" {@link Entities.EntityType|EntityType} displays a 2D rectangle of text in the domain. * It has properties in addition to the common {@link Entities.EntityProperties|EntityProperties}. * @@ -1377,7 +1377,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { * }); */ -/**jsdoc +/*@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 @@ -1431,7 +1431,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { * }); */ -/**jsdoc +/*@jsdoc * The "Zone" {@link Entities.EntityType|EntityType} is a volume of lighting effects and avatar permissions. * Avatar interaction events such as {@link Entities.enterEntity} are also often used with a Zone entity. It has properties in * addition to the common {@link Entities.EntityProperties|EntityProperties}. @@ -1497,7 +1497,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { * }); */ -/**jsdoc +/*@jsdoc * The "Image" {@link Entities.EntityType|EntityType} displays an image on a 2D rectangle in the domain. * It has properties in addition to the common {@link Entities.EntityProperties|EntityProperties}. * @@ -1532,7 +1532,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { * }); */ -/**jsdoc +/*@jsdoc * The "Grid" {@link Entities.EntityType|EntityType} displays a grid on a 2D plane. * It has properties in addition to the common {@link Entities.EntityProperties|EntityProperties}. * @@ -1560,7 +1560,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { * }); */ -/**jsdoc +/*@jsdoc * The "Gizmo" {@link Entities.EntityType|EntityType} displays an entity that could be used as UI. * It has properties in addition to the common {@link Entities.EntityProperties|EntityProperties}. * @@ -1944,7 +1944,7 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool _ring.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties); } - /**jsdoc + /*@jsdoc * The axis-aligned bounding box of an entity. * @typedef {object} Entities.BoundingBox * @property {Vec3} brn - The bottom right near (minimum axes values) corner of the AA box. @@ -1979,7 +1979,7 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool QScriptValue renderInfo = engine->newObject(); - /**jsdoc + /*@jsdoc * Information on how an entity is rendered. Properties are only filled in for Model entities; other * entity types have an empty object, {}. * @typedef {object} Entities.RenderInfo @@ -3006,7 +3006,7 @@ bool EntityItemProperties::getPropertyInfo(const QString& propertyName, EntityPr return false; } -/**jsdoc +/*@jsdoc * Information about an entity property. * @typedef {object} Entities.EntityPropertyInfo * @property {number} propertyEnum - The internal number of the property. diff --git a/libraries/entities/src/EntityScriptServerLogClient.h b/libraries/entities/src/EntityScriptServerLogClient.h index 6d3dec16e2..62b76f8870 100644 --- a/libraries/entities/src/EntityScriptServerLogClient.h +++ b/libraries/entities/src/EntityScriptServerLogClient.h @@ -16,7 +16,7 @@ #include -/**jsdoc +/*@jsdoc * The EntityScriptServerLog API makes server log file output written by server entity scripts available to client * scripts. * @@ -34,7 +34,7 @@ public: signals: - /**jsdoc + /*@jsdoc * Triggered when one or more lines are written to the server log by server entity scripts. * @function EntityScriptServerLog.receivedNewLogLines * @param {string} logLines - The server log lines written by server entity scripts. If there are multiple lines they are diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index 36beb9f0d3..90c521215e 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -57,6 +57,7 @@ EntityScriptingInterface::EntityScriptingInterface(bool bidOnSimulationOwnership connect(nodeList.data(), &NodeList::canRezTmpCertifiedChanged, this, &EntityScriptingInterface::canRezTmpCertifiedChanged); connect(nodeList.data(), &NodeList::canWriteAssetsChanged, this, &EntityScriptingInterface::canWriteAssetsChanged); connect(nodeList.data(), &NodeList::canGetAndSetPrivateUserDataChanged, this, &EntityScriptingInterface::canGetAndSetPrivateUserDataChanged); + connect(nodeList.data(), &NodeList::canRezAvatarEntitiesChanged, this, &EntityScriptingInterface::canRezAvatarEntitiesChanged); auto& packetReceiver = nodeList->getPacketReceiver(); packetReceiver.registerListener(PacketType::EntityScriptCallMethod, @@ -114,6 +115,11 @@ bool EntityScriptingInterface::canGetAndSetPrivateUserData() { return nodeList->getThisNodeCanGetAndSetPrivateUserData(); } +bool EntityScriptingInterface::canRezAvatarEntities() { + auto nodeList = DependencyManager::get(); + return nodeList->getThisNodeCanRezAvatarEntities(); +} + void EntityScriptingInterface::setEntityTree(EntityTreePointer elementTree) { if (_entityTree) { disconnect(_entityTree.get(), &EntityTree::addingEntityPointer, this, &EntityScriptingInterface::onAddingEntity); @@ -481,6 +487,15 @@ QUuid EntityScriptingInterface::addEntityInternal(const EntityItemProperties& pr _activityTracking.addedEntityCount++; + auto nodeList = DependencyManager::get(); + + if (entityHostType == entity::HostType::AVATAR && !nodeList->getThisNodeCanRezAvatarEntities()) { + qCDebug(entities) << "Ignoring addEntity() because don't have canRezAvatarEntities permission on domain"; + // Only need to intercept methods that may add an avatar entity because avatar entities are removed from the tree when + // the user doesn't have canRezAvatarEntities permission. + return QUuid(); + } + EntityItemProperties propertiesWithSimID = properties; propertiesWithSimID.setEntityHostType(entityHostType); if (entityHostType == entity::HostType::AVATAR) { @@ -493,7 +508,6 @@ QUuid EntityScriptingInterface::addEntityInternal(const EntityItemProperties& pr } // the created time will be set in EntityTree::addEntity by recordCreationTime() - auto nodeList = DependencyManager::get(); auto sessionID = nodeList->getSessionUUID(); propertiesWithSimID.setLastEditedBy(sessionID); @@ -1002,7 +1016,7 @@ void EntityScriptingInterface::deleteEntity(const QUuid& id) { for (auto entity : entitiesToDeleteImmediately) { if (entity->isMyAvatarEntity()) { - getEntityPacketSender()->getMyAvatar()->clearAvatarEntity(entity->getID(), false); + getEntityPacketSender()->getMyAvatar()->clearAvatarEntityInternal(entity->getID()); } } } diff --git a/libraries/entities/src/EntityScriptingInterface.h b/libraries/entities/src/EntityScriptingInterface.h index 14d853fbaf..5db278f51e 100644 --- a/libraries/entities/src/EntityScriptingInterface.h +++ b/libraries/entities/src/EntityScriptingInterface.h @@ -57,7 +57,7 @@ private: QPointer _engine; }; -/**jsdoc +/*@jsdoc * The result of a {@link Entities.findRayIntersection|findRayIntersection} search using a {@link PickRay}. * @typedef {object} Entities.RayToEntityIntersectionResult * @property {boolean} intersects - true if the {@link PickRay} intersected an entity, false if it @@ -101,7 +101,7 @@ public: QVariantMap extraInfo; }; -/**jsdoc +/*@jsdoc * The Entities API provides facilities to create and interact with entities. Entities are 2D or 3D objects * displayed in-world. Depending on their {@link Entities.EntityHostType|EntityHostType}, they may persist in the domain as * "domain" entities, travel to different domains with a user as "avatar" entities, or be visible only to an individual user as @@ -192,7 +192,7 @@ public: ParabolaToEntityIntersectionResult evalParabolaIntersectionVector(const PickParabola& parabola, PickFilter searchFilter, const QVector& entityIdsToInclude, const QVector& entityIdsToDiscard); - /**jsdoc + /*@jsdoc * Gets the properties of multiple entities. * @function Entities.getMultipleEntityProperties * @param {Uuid[]} entityIDs - The IDs of the entities to get the properties of. @@ -215,7 +215,7 @@ public: public slots: - /**jsdoc + /*@jsdoc * Checks whether or not the script can change the locked property of entities. Locked entities have their * locked property set to true and cannot be edited or deleted. * @function Entities.canAdjustLocks @@ -230,7 +230,7 @@ public slots: */ Q_INVOKABLE bool canAdjustLocks(); - /**jsdoc + /*@jsdoc * Checks whether or not the script can rez (create) new entities in the domain. * @function Entities.canRez * @returns {boolean} true if the domain server will allow the script to rez (create) new entities, otherwise @@ -238,7 +238,7 @@ public slots: */ Q_INVOKABLE bool canRez(); - /**jsdoc + /*@jsdoc * Checks whether or not the script can rez (create) new temporary entities in the domain. Temporary entities are entities * with a finite lifetime property value set. * @function Entities.canRezTmp @@ -247,7 +247,7 @@ public slots: */ Q_INVOKABLE bool canRezTmp(); - /**jsdoc + /*@jsdoc * Checks whether or not the script can rez (create) new certified entities in the domain. Certified entities are entities * that have PoP certificates. * @function Entities.canRezCertified @@ -256,7 +256,7 @@ public slots: */ Q_INVOKABLE bool canRezCertified(); - /**jsdoc + /*@jsdoc * Checks whether or not the script can rez (create) new temporary certified entities in the domain. Temporary entities are * entities with a finite lifetime property value set. Certified entities are entities that have PoP * certificates. @@ -266,7 +266,7 @@ public slots: */ Q_INVOKABLE bool canRezTmpCertified(); - /**jsdoc + /*@jsdoc * Checks whether or not the script can make changes to the asset server's assets. * @function Entities.canWriteAssets * @returns {boolean} true if the domain server will allow the script to make changes to the asset server's @@ -274,7 +274,7 @@ public slots: */ Q_INVOKABLE bool canWriteAssets(); - /**jsdoc + /*@jsdoc * Checks whether or not the script can replace the domain's content set. * @function Entities.canReplaceContent * @returns {boolean} true if the domain server will allow the script to replace the domain's content set, @@ -282,15 +282,23 @@ public slots: */ Q_INVOKABLE bool canReplaceContent(); - /**jsdoc + /*@jsdoc * Checks whether or not the script can get and set the privateUserData property of entities. * @function Entities.canGetAndSetPrivateUserData * @returns {boolean} true if the domain server will allow the script to get and set the * privateUserData property of entities, otherwise false. */ Q_INVOKABLE bool canGetAndSetPrivateUserData(); + + /*@jsdoc + * Checks whether or not the script can rez avatar entities. + * @function Entities.canRezAvatarEntities + * @returns {boolean} true if the domain server will allow the script to rez avatar entities, + * otherwise false. + */ + Q_INVOKABLE bool canRezAvatarEntities(); - /**jsdoc + /*@jsdoc *

How an entity is hosted and sent to others for display.

*
* @@ -311,7 +319,7 @@ public slots: * @typedef {string} Entities.EntityHostType */ - /**jsdoc + /*@jsdoc * Adds a new domain, avatar, or local entity. * @function Entities.addEntity * @param {Entities.EntityProperties} properties - The properties of the entity to create. @@ -340,7 +348,7 @@ public slots: return addEntityInternal(properties, entityHostType); } - /**jsdoc + /*@jsdoc * Adds a new avatar entity ({@link Entities.EntityProperties|entityHostType} property is * "avatar") or domain entity ({@link Entities.EntityProperties|entityHostType} property is * "domain"). @@ -361,7 +369,7 @@ public slots: Q_INVOKABLE QUuid addModelEntity(const QString& name, const QString& modelUrl, const QString& textures, const QString& shapeType, bool dynamic, bool collisionless, bool grabbable, const glm::vec3& position, const glm::vec3& gravity); - /**jsdoc + /*@jsdoc * Creates a clone of an entity. The clone has the same properties as the original except that: it has a modified * name property, clone-related properties are set per the original entity's clone-related * {@link Entities.EntityProperties|properties} (e.g., cloneLifetime), and its clone-related properties are @@ -376,7 +384,7 @@ public slots: */ Q_INVOKABLE QUuid cloneEntity(const QUuid& entityID); - /**jsdoc + /*@jsdoc * Gets an entity's property values. * @function Entities.getEntityProperties * @param {Uuid} entityID - The ID of the entity to get the properties of. @@ -399,7 +407,7 @@ public slots: Q_INVOKABLE EntityItemProperties getEntityProperties(const QUuid& entityID); Q_INVOKABLE EntityItemProperties getEntityProperties(const QUuid& entityID, EntityPropertyFlags desiredProperties); - /**jsdoc + /*@jsdoc * Edits an entity, changing one or more of its property values. * @function Entities.editEntity * @param {Uuid} entityID - The ID of the entity to edit. @@ -426,7 +434,7 @@ public slots: */ Q_INVOKABLE QUuid editEntity(const QUuid& entityID, const EntityItemProperties& properties); - /**jsdoc + /*@jsdoc * Deletes an entity. * @function Entities.deleteEntity * @param {Uuid} entityID - The ID of the entity to delete. @@ -444,7 +452,7 @@ public slots: */ Q_INVOKABLE void deleteEntity(const QUuid& entityID); - /**jsdoc + /*@jsdoc * Gets an entity's type. * @function Entities.getEntityType * @param {Uuid} id - The ID of the entity to get the type of. @@ -452,7 +460,7 @@ public slots: */ Q_INVOKABLE QString getEntityType(const QUuid& entityID); - /**jsdoc + /*@jsdoc * Gets an entity's script object. In particular, this is useful for accessing a {@link Entities.EntityProperties-Web|Web} * entity's HTML EventBridge script object to exchange messages with the web page script. *

To send a message from an Interface script to a Web entity over its event bridge:

@@ -524,7 +532,7 @@ public slots: */ Q_INVOKABLE QObject* getEntityObject(const QUuid& id); - /**jsdoc + /*@jsdoc * Checks whether an entity's assets have been loaded. For example, for an Model entity the result indicates * whether its textures have been loaded. * @function Entities.isLoaded @@ -533,7 +541,7 @@ public slots: */ Q_INVOKABLE bool isLoaded(const QUuid& id); - /**jsdoc + /*@jsdoc * Checks if there is an entity with a specified ID. * @function Entities.isAddedEntity * @param {Uuid} id - The ID to check. @@ -541,7 +549,7 @@ public slots: */ Q_INVOKABLE bool isAddedEntity(const QUuid& id); - /**jsdoc + /*@jsdoc * Calculates the size of some text in a {@link Entities.EntityProperties-Text|Text} entity. The entity need not be set * visible. *

Note: The size of text in a Text entity cannot be calculated immediately after the @@ -554,7 +562,7 @@ public slots: */ Q_INVOKABLE QSizeF textSize(const QUuid& id, const QString& text); - /**jsdoc + /*@jsdoc * Calls a method in a client entity script from an Interface, avatar, or client entity script, or calls a method in a * server entity script from a server entity script. The entity script method must be exposed as a property in the target * entity script. Additionally, if calling a server entity script, the server entity script must include the method's name @@ -588,7 +596,7 @@ public slots: */ Q_INVOKABLE void callEntityMethod(const QUuid& entityID, const QString& method, const QStringList& params = QStringList()); - /**jsdoc + /*@jsdoc * Calls a method in a server entity script from an Interface, avatar, or client entity script. The server entity script * method must be exposed as a property in the target server entity script. Additionally, the server entity script must * include the method's name in an exposed property called remotelyCallable that is an array of method names @@ -625,7 +633,7 @@ public slots: */ Q_INVOKABLE void callEntityServerMethod(const QUuid& entityID, const QString& method, const QStringList& params = QStringList()); - /**jsdoc + /*@jsdoc * Calls a method in a specific user's client entity script from a server entity script. The entity script method must be * exposed as a property in the target client entity script. Additionally, the client entity script must * include the method's name in an exposed property called remotelyCallable that is an array of method names @@ -694,7 +702,7 @@ public slots: Q_INVOKABLE void callEntityClientMethod(const QUuid& clientSessionID, const QUuid& entityID, const QString& method, const QStringList& params = QStringList()); - /**jsdoc + /*@jsdoc * Finds the domain or avatar entity with a position closest to a specified point and within a specified radius. * @function Entities.findClosestEntity * @param {Vec3} center - The point about which to search. @@ -708,7 +716,7 @@ public slots: /// this function will not find any models in script engine contexts which don't have access to models Q_INVOKABLE QUuid findClosestEntity(const glm::vec3& center, float radius) const; - /**jsdoc + /*@jsdoc * Finds all domain and avatar entities that intersect a sphere. *

Note: Server entity scripts only find entities that have a server entity script * running in them or a parent entity. You can apply a dummy script to entities that you want found in a search.

@@ -724,7 +732,7 @@ public slots: /// this function will not find any models in script engine contexts which don't have access to models Q_INVOKABLE QVector findEntities(const glm::vec3& center, float radius) const; - /**jsdoc + /*@jsdoc * Finds all domain and avatar entities whose axis-aligned boxes intersect a search axis-aligned box. *

Note: Server entity scripts only find entities that have a server entity script * running in them or a parent entity. You can apply a dummy script to entities that you want found in a search.

@@ -737,7 +745,7 @@ public slots: /// this function will not find any models in script engine contexts which don't have access to models Q_INVOKABLE QVector findEntitiesInBox(const glm::vec3& corner, const glm::vec3& dimensions) const; - /**jsdoc + /*@jsdoc * Finds all domain and avatar entities whose axis-aligned boxes intersect a search frustum. *

Note: Server entity scripts only find entities that have a server entity script * running in them or a parent entity. You can apply a dummy script to entities that you want found in a search.

@@ -754,7 +762,7 @@ public slots: /// this function will not find any models in script engine contexts which don't have access to entities Q_INVOKABLE QVector findEntitiesInFrustum(QVariantMap frustum) const; - /**jsdoc + /*@jsdoc * Finds all domain and avatar entities of a particular type that intersect a sphere. *

Note: Server entity scripts only find entities that have a server entity script * running in them or a parent entity. You can apply a dummy script to entities that you want found in a search.

@@ -771,7 +779,7 @@ public slots: /// this function will not find any entities in script engine contexts which don't have access to entities Q_INVOKABLE QVector findEntitiesByType(const QString entityType, const glm::vec3& center, float radius) const; - /**jsdoc + /*@jsdoc * Finds all domain and avatar entities with a particular name that intersect a sphere. *

Note: Server entity scripts only find entities that have a server entity script * running in them or a parent entity. You can apply a dummy script to entities that you want found in a search.

@@ -790,7 +798,7 @@ public slots: Q_INVOKABLE QVector findEntitiesByName(const QString entityName, const glm::vec3& center, float radius, bool caseSensitiveSearch = false) const; - /**jsdoc + /*@jsdoc * Finds the first avatar or domain entity intersected by a {@link PickRay}. Light and Zone * entities are not intersected unless they've been configured as pickable using * {@link Entities.setLightsArePickable|setLightsArePickable} and {@link Entities.setZonesArePickable|setZonesArePickable}, @@ -829,7 +837,7 @@ public slots: const QScriptValue& entityIdsToInclude = QScriptValue(), const QScriptValue& entityIdsToDiscard = QScriptValue(), bool visibleOnly = false, bool collidableOnly = false) const; - /**jsdoc + /*@jsdoc * Reloads an entity's server entity script such that the latest version re-downloaded. * @function Entities.reloadServerScripts * @param {Uuid} entityID - The ID of the entity to reload the server entity script of. @@ -838,14 +846,14 @@ public slots: */ Q_INVOKABLE bool reloadServerScripts(const QUuid& entityID); - /**jsdoc + /*@jsdoc * Gets the status of a server entity script attached to an entity. * @function Entities.getServerScriptStatus * @param {Uuid} entityID - The ID of the entity to get the server entity script status of. * @param {Entities~getServerScriptStatusCallback} callback - The function to call upon completion. * @returns {boolean} true always. */ - /**jsdoc + /*@jsdoc * Called when a {@link Entities.getServerScriptStatus} call is complete. * @callback Entities~getServerScriptStatusCallback * @param {boolean} success - true if the server entity script status could be obtained, otherwise @@ -857,7 +865,7 @@ public slots: */ Q_INVOKABLE bool getServerScriptStatus(const QUuid& entityID, QScriptValue callback); - /**jsdoc + /*@jsdoc * Gets metadata for certain entity properties such as script and serverScripts. * @function Entities.queryPropertyMetadata * @param {Uuid} entityID - The ID of the entity to get the metadata for. @@ -867,7 +875,7 @@ public slots: * false. * @throws Throws an error if property is not handled yet or callback is not a function. */ - /**jsdoc + /*@jsdoc * Gets metadata for certain entity properties such as script and serverScripts. * @function Entities.queryPropertyMetadata * @param {Uuid} entityID - The ID of the entity to get the metadata for. @@ -878,7 +886,7 @@ public slots: * false. * @throws Throws an error if property is not handled yet or callback is not a function. */ - /**jsdoc + /*@jsdoc * Called when a {@link Entities.queryPropertyMetadata} call is complete. * @callback Entities~queryPropertyMetadataCallback * @param {string} error - undefined if there was no error, otherwise an error message. @@ -889,7 +897,7 @@ public slots: QScriptValue methodOrName = QScriptValue()); - /**jsdoc + /*@jsdoc * Sets whether or not ray picks intersect the bounding box of {@link Entities.EntityProperties-Light|Light} entities. By * default, Light entities are not intersected. The setting lasts for the Interface session. Ray picks are performed using * {@link Entities.findRayIntersection|findRayIntersection}, or the {@link Picks} API. @@ -900,7 +908,7 @@ public slots: // FIXME move to a renderable entity interface Q_INVOKABLE void setLightsArePickable(bool value); - /**jsdoc + /*@jsdoc * Gets whether or not ray picks intersect the bounding box of {@link Entities.EntityProperties-Light|Light} entities. Ray * picks are performed using {@link Entities.findRayIntersection|findRayIntersection}, or the {@link Picks} API. * @function Entities.getLightsArePickable @@ -910,7 +918,7 @@ public slots: // FIXME move to a renderable entity interface Q_INVOKABLE bool getLightsArePickable() const; - /**jsdoc + /*@jsdoc * Sets whether or not ray picks intersect the bounding box of {@link Entities.EntityProperties-Zone|Zone} entities. By * default, Zone entities are not intersected. The setting lasts for the Interface session. Ray picks are performed using * {@link Entities.findRayIntersection|findRayIntersection}, or the {@link Picks} API. @@ -921,7 +929,7 @@ public slots: // FIXME move to a renderable entity interface Q_INVOKABLE void setZonesArePickable(bool value); - /**jsdoc + /*@jsdoc * Gets whether or not ray picks intersect the bounding box of {@link Entities.EntityProperties-Zone|Zone} entities. Ray * picks are performed using {@link Entities.findRayIntersection|findRayIntersection}, or the {@link Picks} API. * @function Entities.getZonesArePickable @@ -931,7 +939,7 @@ public slots: // FIXME move to a renderable entity interface Q_INVOKABLE bool getZonesArePickable() const; - /**jsdoc + /*@jsdoc * Sets whether or not {@link Entities.EntityProperties-Zone|Zone} entities' boundaries should be drawn. Currently not * used. * @function Entities.setDrawZoneBoundaries @@ -941,7 +949,7 @@ public slots: // FIXME move to a renderable entity interface Q_INVOKABLE void setDrawZoneBoundaries(bool value); - /**jsdoc + /*@jsdoc * Gets whether or not {@link Entities.EntityProperties-Zone|Zone} entities' boundaries should be drawn. Currently * not used. * @function Entities.getDrawZoneBoundaries @@ -952,7 +960,7 @@ public slots: Q_INVOKABLE bool getDrawZoneBoundaries() const; - /**jsdoc + /*@jsdoc * Sets the values of all voxels in a spherical portion of a {@link Entities.EntityProperties-PolyVox|PolyVox} entity. * @function Entities.setVoxelSphere * @param {Uuid} entityID - The ID of the {@link Entities.EntityProperties-PolyVox|PolyVox} entity. @@ -973,7 +981,7 @@ public slots: // FIXME move to a renderable entity interface Q_INVOKABLE bool setVoxelSphere(const QUuid& entityID, const glm::vec3& center, float radius, int value); - /**jsdoc + /*@jsdoc * Sets the values of all voxels in a capsule-shaped portion of a {@link Entities.EntityProperties-PolyVox|PolyVox} entity. * @function Entities.setVoxelCapsule * @param {Uuid} entityID - The ID of the {@link Entities.EntityProperties-PolyVox|PolyVox} entity. @@ -997,7 +1005,7 @@ public slots: // FIXME move to a renderable entity interface Q_INVOKABLE bool setVoxelCapsule(const QUuid& entityID, const glm::vec3& start, const glm::vec3& end, float radius, int value); - /**jsdoc + /*@jsdoc * Sets the value of a particular voxel in a {@link Entities.EntityProperties-PolyVox|PolyVox} entity. * @function Entities.setVoxel * @param {Uuid} entityID - The ID of the {@link Entities.EntityProperties-PolyVox|PolyVox} entity. @@ -1019,7 +1027,7 @@ public slots: // FIXME move to a renderable entity interface Q_INVOKABLE bool setVoxel(const QUuid& entityID, const glm::vec3& position, int value); - /**jsdoc + /*@jsdoc * Sets the values of all voxels in a {@link Entities.EntityProperties-PolyVox|PolyVox} entity. * @function Entities.setAllVoxels * @param {Uuid} entityID - The ID of the {@link Entities.EntityProperties-PolyVox|PolyVox} entity. @@ -1037,7 +1045,7 @@ public slots: // FIXME move to a renderable entity interface Q_INVOKABLE bool setAllVoxels(const QUuid& entityID, int value); - /**jsdoc + /*@jsdoc * Sets the values of all voxels in a cubic portion of a {@link Entities.EntityProperties-PolyVox|PolyVox} entity. * @function Entities.setVoxelsInCuboid * @param {Uuid} entityID - The ID of the {@link Entities.EntityProperties-PolyVox|PolyVox} entity. @@ -1062,7 +1070,7 @@ public slots: // FIXME move to a renderable entity interface Q_INVOKABLE bool setVoxelsInCuboid(const QUuid& entityID, const glm::vec3& lowPosition, const glm::vec3& cuboidSize, int value); - /**jsdoc + /*@jsdoc * Converts voxel coordinates in a {@link Entities.EntityProperties-PolyVox|PolyVox} entity to world coordinates. Voxel * coordinates are relative to the minimum axes values corner of the entity with a scale of Vec3.ONE being the * dimensions of each voxel. @@ -1097,7 +1105,7 @@ public slots: // FIXME move to a renderable entity interface Q_INVOKABLE glm::vec3 voxelCoordsToWorldCoords(const QUuid& entityID, glm::vec3 voxelCoords); - /**jsdoc + /*@jsdoc * Converts world coordinates to voxel coordinates in a {@link Entities.EntityProperties-PolyVox|PolyVox} entity. Voxel * coordinates are relative to the minimum axes values corner of the entity, with a scale of Vec3.ONE being * the dimensions of each voxel. @@ -1111,7 +1119,7 @@ public slots: // FIXME move to a renderable entity interface Q_INVOKABLE glm::vec3 worldCoordsToVoxelCoords(const QUuid& entityID, glm::vec3 worldCoords); - /**jsdoc + /*@jsdoc * Converts voxel coordinates in a {@link Entities.EntityProperties-PolyVox|PolyVox} entity to local coordinates. Local * coordinates are relative to the minimum axes value corner of the entity, with the scale being the same as world * coordinates. Voxel coordinates are relative to the minimum axes values corner of the entity, with a scale of @@ -1135,7 +1143,7 @@ public slots: // FIXME move to a renderable entity interface Q_INVOKABLE glm::vec3 voxelCoordsToLocalCoords(const QUuid& entityID, glm::vec3 voxelCoords); - /**jsdoc + /*@jsdoc * Converts local coordinates to voxel coordinates in a {@link Entities.EntityProperties-PolyVox|PolyVox} entity. Local * coordinates are relative to the minimum axes value corner of the entity, with the scale being the same as world * coordinates. Voxel coordinates are relative to the minimum axes values corner of the entity, with a scale of @@ -1150,7 +1158,7 @@ public slots: // FIXME move to a renderable entity interface Q_INVOKABLE glm::vec3 localCoordsToVoxelCoords(const QUuid& entityID, glm::vec3 localCoords); - /**jsdoc + /*@jsdoc * Sets all the points in a {@link Entities.EntityProperties-Line|Line} entity. * @function Entities.setAllPoints * @param {Uuid} entityID - The ID of the {@link Entities.EntityProperties-Line|Line} entity. @@ -1186,7 +1194,7 @@ public slots: */ Q_INVOKABLE bool setAllPoints(const QUuid& entityID, const QVector& points); - /**jsdoc + /*@jsdoc * Appends a point to a {@link Entities.EntityProperties-Line|Line} entity. * @function Entities.appendPoint * @param {Uuid} entityID - The ID of the {@link Entities.EntityProperties-Line|Line} entity. @@ -1218,7 +1226,7 @@ public slots: */ Q_INVOKABLE bool appendPoint(const QUuid& entityID, const glm::vec3& point); - /**jsdoc + /*@jsdoc * Dumps debug information about all entities in Interface's local in-memory tree of entities it knows about to the program * log. * @function Entities.dumpTree @@ -1226,7 +1234,7 @@ public slots: Q_INVOKABLE void dumpTree() const; - /**jsdoc + /*@jsdoc * Adds an action to an entity. An action is registered with the physics engine and is applied every physics simulation * step. Any entity may have more than one action associated with it, but only as many as will fit in an entity's * {@link Entities.EntityProperties|actionData} property. @@ -1254,7 +1262,7 @@ public slots: */ Q_INVOKABLE QUuid addAction(const QString& actionTypeString, const QUuid& entityID, const QVariantMap& arguments); - /**jsdoc + /*@jsdoc * Updates an entity action. * @function Entities.updateAction * @param {Uuid} entityID - The ID of the entity with the action to update. @@ -1264,7 +1272,7 @@ public slots: */ Q_INVOKABLE bool updateAction(const QUuid& entityID, const QUuid& actionID, const QVariantMap& arguments); - /**jsdoc + /*@jsdoc * Deletes an action from an entity. * @function Entities.deleteAction * @param {Uuid} entityID - The ID of entity to delete the action from. @@ -1273,7 +1281,7 @@ public slots: */ Q_INVOKABLE bool deleteAction(const QUuid& entityID, const QUuid& actionID); - /**jsdoc + /*@jsdoc * Gets the IDs of the actions that are associated with an entity. * @function Entities.getActionIDs * @param {Uuid} entityID - The entity to get the action IDs for. @@ -1281,7 +1289,7 @@ public slots: */ Q_INVOKABLE QVector getActionIDs(const QUuid& entityID); - /**jsdoc + /*@jsdoc * Gets the arguments of an action. * @function Entities.getActionArguments * @param {Uuid} entityID - The ID of the entity with the action. @@ -1291,7 +1299,7 @@ public slots: Q_INVOKABLE QVariantMap getActionArguments(const QUuid& entityID, const QUuid& actionID); - /**jsdoc + /*@jsdoc * Gets the translation of a joint in a {@link Entities.EntityProperties-Model|Model} entity relative to the entity's * position and orientation. * @function Entities.getAbsoluteJointTranslationInObjectFrame @@ -1304,7 +1312,7 @@ public slots: // FIXME move to a renderable entity interface Q_INVOKABLE glm::vec3 getAbsoluteJointTranslationInObjectFrame(const QUuid& entityID, int jointIndex); - /**jsdoc + /*@jsdoc * Gets the index of the parent joint of a joint in a {@link Entities.EntityProperties-Model|Model} entity. * @function Entities.getJointParent * @param {Uuid} entityID - The ID of the entity. @@ -1313,7 +1321,7 @@ public slots: */ Q_INVOKABLE int getJointParent(const QUuid& entityID, int index); - /**jsdoc + /*@jsdoc * Gets the rotation of a joint in a {@link Entities.EntityProperties-Model|Model} entity relative to the entity's * position and orientation. * @function Entities.getAbsoluteJointRotationInObjectFrame @@ -1343,7 +1351,7 @@ public slots: // FIXME move to a renderable entity interface Q_INVOKABLE glm::quat getAbsoluteJointRotationInObjectFrame(const QUuid& entityID, int jointIndex); - /**jsdoc + /*@jsdoc * Sets the translation of a joint in a {@link Entities.EntityProperties-Model|Model} entity relative to the entity's * position and orientation. * @function Entities.setAbsoluteJointTranslationInObjectFrame @@ -1357,7 +1365,7 @@ public slots: // FIXME move to a renderable entity interface Q_INVOKABLE bool setAbsoluteJointTranslationInObjectFrame(const QUuid& entityID, int jointIndex, glm::vec3 translation); - /**jsdoc + /*@jsdoc * Sets the rotation of a joint in a {@link Entities.EntityProperties-Model|Model} entity relative to the entity's position * and orientation. * @function Entities.setAbsoluteJointRotationInObjectFrame @@ -1389,7 +1397,7 @@ public slots: Q_INVOKABLE bool setAbsoluteJointRotationInObjectFrame(const QUuid& entityID, int jointIndex, glm::quat rotation); - /**jsdoc + /*@jsdoc * Gets the local translation of a joint in a {@link Entities.EntityProperties-Model|Model} entity. * @function Entities.getLocalJointTranslation * @param {Uuid} entityID - The ID of the entity. @@ -1400,7 +1408,7 @@ public slots: // FIXME move to a renderable entity interface Q_INVOKABLE glm::vec3 getLocalJointTranslation(const QUuid& entityID, int jointIndex); - /**jsdoc + /*@jsdoc * Gets the local rotation of a joint in a {@link Entities.EntityProperties-Model|Model} entity. * @function Entities.getLocalJointRotation * @param {Uuid} entityID - The ID of the entity. @@ -1426,7 +1434,7 @@ public slots: // FIXME move to a renderable entity interface Q_INVOKABLE glm::quat getLocalJointRotation(const QUuid& entityID, int jointIndex); - /**jsdoc + /*@jsdoc * Sets the local translation of a joint in a {@link Entities.EntityProperties-Model|Model} entity. * @function Entities.setLocalJointTranslation * @param {Uuid} entityID - The ID of the entity. @@ -1439,7 +1447,7 @@ public slots: // FIXME move to a renderable entity interface Q_INVOKABLE bool setLocalJointTranslation(const QUuid& entityID, int jointIndex, glm::vec3 translation); - /**jsdoc + /*@jsdoc * Sets the local rotation of a joint in a {@link Entities.EntityProperties-Model|Model} entity. * @function Entities.setLocalJointRotation * @param {Uuid} entityID - The ID of the entity. @@ -1469,7 +1477,7 @@ public slots: Q_INVOKABLE bool setLocalJointRotation(const QUuid& entityID, int jointIndex, glm::quat rotation); - /**jsdoc + /*@jsdoc * Sets the local translations of joints in a {@link Entities.EntityProperties-Model|Model} entity. * @function Entities.setLocalJointTranslations * @param {Uuid} entityID - The ID of the entity. @@ -1481,7 +1489,7 @@ public slots: // FIXME move to a renderable entity interface Q_INVOKABLE bool setLocalJointTranslations(const QUuid& entityID, const QVector& translations); - /**jsdoc + /*@jsdoc * Sets the local rotations of joints in a {@link Entities.EntityProperties-Model|Model} entity. * @function Entities.setLocalJointRotations * @param {Uuid} entityID - The ID of the entity. @@ -1523,7 +1531,7 @@ public slots: // FIXME move to a renderable entity interface Q_INVOKABLE bool setLocalJointRotations(const QUuid& entityID, const QVector& rotations); - /**jsdoc + /*@jsdoc * Sets the local rotations and translations of joints in a {@link Entities.EntityProperties-Model|Model} entity. This is * the same as calling both {@link Entities.setLocalJointRotations|setLocalJointRotations} and * {@link Entities.setLocalJointTranslations|setLocalJointTranslations} at the same time. @@ -1541,7 +1549,7 @@ public slots: const QVector& translations); - /**jsdoc + /*@jsdoc * Gets the index of a named joint in a {@link Entities.EntityProperties-Model|Model} entity. * @function Entities.getJointIndex * @param {Uuid} entityID - The ID of the entity. @@ -1567,7 +1575,7 @@ public slots: // FIXME move to a renderable entity interface Q_INVOKABLE int getJointIndex(const QUuid& entityID, const QString& name); - /**jsdoc + /*@jsdoc * Gets the names of all the joints in a {@link Entities.EntityProperties-Model|Model} entity. * @function Entities.getJointNames * @param {Uuid} entityID - The ID of the {@link Entities.EntityProperties-Model|Model} entity. @@ -1593,7 +1601,7 @@ public slots: Q_INVOKABLE QStringList getJointNames(const QUuid& entityID); - /**jsdoc + /*@jsdoc * Gets the IDs of entities and avatars that are directly parented to an entity or avatar model. To get all descendants, * you can recurse on the IDs returned. * @function Entities.getChildrenIDs @@ -1624,7 +1632,7 @@ public slots: */ Q_INVOKABLE QVector getChildrenIDs(const QUuid& parentID); - /**jsdoc + /*@jsdoc * Gets the IDs of entities and avatars that are directly parented to an entity or avatar model's joint. To get all * descendants, you can use {@link Entities.getChildrenIDs|getChildrenIDs} to recurse on the IDs returned. * @function Entities.getChildrenIDsOfJoint @@ -1662,7 +1670,7 @@ public slots: */ Q_INVOKABLE QVector getChildrenIDsOfJoint(const QUuid& parentID, int jointIndex); - /**jsdoc + /*@jsdoc * Checks whether an entity has an entity as an ancestor (parent, parent's parent, etc.). * @function Entities.isChildOfParent * @param {Uuid} childID - The ID of the child entity to test for being a child, grandchild, etc. @@ -1691,7 +1699,7 @@ public slots: */ Q_INVOKABLE bool isChildOfParent(const QUuid& childID, const QUuid& parentID); - /**jsdoc + /*@jsdoc * Gets the type — entity or avatar — of an in-world item. * @function Entities.getNestableType * @param {Uuid} id - The ID of the item to get the type of. @@ -1708,14 +1716,14 @@ public slots: */ Q_INVOKABLE QString getNestableType(const QUuid& id); - /**jsdoc + /*@jsdoc * Gets the ID of the {@link Entities.EntityProperties-Web|Web} entity that has keyboard focus. * @function Entities.getKeyboardFocusEntity * @returns {Uuid} The ID of the {@link Entities.EntityProperties-Web|Web} entity that has focus, if any, otherwise null. */ Q_INVOKABLE QUuid getKeyboardFocusEntity() const; - /**jsdoc + /*@jsdoc * Sets the {@link Entities.EntityProperties-Web|Web} entity that has keyboard focus. * @function Entities.setKeyboardFocusEntity * @param {Uuid} id - The ID of the {@link Entities.EntityProperties-Web|Web} entity to set keyboard focus to. Use @@ -1723,7 +1731,7 @@ public slots: */ Q_INVOKABLE void setKeyboardFocusEntity(const QUuid& id); - /**jsdoc + /*@jsdoc * Emits a {@link Entities.mousePressOnEntity|mousePressOnEntity} event. * @function Entities.sendMousePressOnEntity * @param {Uuid} entityID - The ID of the entity to emit the event for. @@ -1731,7 +1739,7 @@ public slots: */ Q_INVOKABLE void sendMousePressOnEntity(const EntityItemID& id, const PointerEvent& event); - /**jsdoc + /*@jsdoc * Emits a {@link Entities.mouseMoveOnEntity|mouseMoveOnEntity} event. * @function Entities.sendMouseMoveOnEntity * @param {Uuid} entityID - The ID of the entity to emit the event for. @@ -1739,7 +1747,7 @@ public slots: */ Q_INVOKABLE void sendMouseMoveOnEntity(const EntityItemID& id, const PointerEvent& event); - /**jsdoc + /*@jsdoc * Emits a {@link Entities.mouseReleaseOnEntity|mouseReleaseOnEntity} event. * @function Entities.sendMouseReleaseOnEntity * @param {Uuid} entityID - The ID of the entity to emit the event for. @@ -1747,7 +1755,7 @@ public slots: */ Q_INVOKABLE void sendMouseReleaseOnEntity(const EntityItemID& id, const PointerEvent& event); - /**jsdoc + /*@jsdoc * Emits a {@link Entities.clickDownOnEntity|clickDownOnEntity} event. * @function Entities.sendClickDownOnEntity * @param {Uuid} entityID - The ID of the entity to emit the event for. @@ -1755,7 +1763,7 @@ public slots: */ Q_INVOKABLE void sendClickDownOnEntity(const EntityItemID& id, const PointerEvent& event); - /**jsdoc + /*@jsdoc * Emits a {@link Entities.holdingClickOnEntity|holdingClickOnEntity} event. * @function Entities.sendHoldingClickOnEntity * @param {Uuid} entityID - The ID of the entity to emit the event for. @@ -1763,7 +1771,7 @@ public slots: */ Q_INVOKABLE void sendHoldingClickOnEntity(const EntityItemID& id, const PointerEvent& event); - /**jsdoc + /*@jsdoc * Emits a {@link Entities.clickReleaseOnEntity|clickReleaseOnEntity} event. * @function Entities.sendClickReleaseOnEntity * @param {Uuid} entityID - The ID of the entity to emit the event for. @@ -1771,7 +1779,7 @@ public slots: */ Q_INVOKABLE void sendClickReleaseOnEntity(const EntityItemID& id, const PointerEvent& event); - /**jsdoc + /*@jsdoc * Emits a {@link Entities.hoverEnterEntity|hoverEnterEntity} event. * @function Entities.sendHoverEnterEntity * @param {Uuid} entityID - The ID of the entity to emit the event for. @@ -1779,7 +1787,7 @@ public slots: */ Q_INVOKABLE void sendHoverEnterEntity(const EntityItemID& id, const PointerEvent& event); - /**jsdoc + /*@jsdoc * Emits a {@link Entities.hoverOverEntity|hoverOverEntity} event. * @function Entities.sendHoverOverEntity * @param {Uuid} entityID - The ID of the entity to emit the event for. @@ -1787,7 +1795,7 @@ public slots: */ Q_INVOKABLE void sendHoverOverEntity(const EntityItemID& id, const PointerEvent& event); - /**jsdoc + /*@jsdoc * Emits a {@link Entities.hoverLeaveEntity|hoverLeaveEntity} event. * @function Entities.sendHoverLeaveEntity * @param {Uuid} entityID - The ID of the entity to emit the event for. @@ -1795,7 +1803,7 @@ public slots: */ Q_INVOKABLE void sendHoverLeaveEntity(const EntityItemID& id, const PointerEvent& event); - /**jsdoc + /*@jsdoc * Checks whether an entity wants hand controller pointer events. For example, a {@link Entities.EntityProperties-Web|Web} * entity does but a {@link Entities.EntityProperties-Shape|Shape} entity doesn't. * @function Entities.wantsHandControllerPointerEvents @@ -1805,7 +1813,7 @@ public slots: */ Q_INVOKABLE bool wantsHandControllerPointerEvents(const QUuid& id); - /**jsdoc + /*@jsdoc * Sends a message to a {@link Entities.EntityProperties-Web|Web} entity's HTML page. To receive the message, the web * page's script must connect to the EventBridge that is automatically provided to the script: *
EventBridge.scriptEventReceived.connect(function(message) {
@@ -1866,7 +1874,7 @@ public slots:
      */
     Q_INVOKABLE void emitScriptEvent(const EntityItemID& entityID, const QVariant& message);
 
-    /**jsdoc
+    /*@jsdoc
      * Checks whether an axis-aligned box and a capsule intersect.
      * @function Entities.AABoxIntersectsCapsule
      * @param {Vec3} brn - The bottom right near (minimum axes values) corner of the AA box.
@@ -1879,7 +1887,7 @@ public slots:
     Q_INVOKABLE bool AABoxIntersectsCapsule(const glm::vec3& low, const glm::vec3& dimensions,
                                             const glm::vec3& start, const glm::vec3& end, float radius);
 
-    /**jsdoc
+    /*@jsdoc
      * Gets the meshes in a {@link Entities.EntityProperties-Model|Model} or {@link Entities.EntityProperties-PolyVox|PolyVox} 
      * entity.
      * @function Entities.getMeshes
@@ -1888,7 +1896,7 @@ public slots:
      * @deprecated This function is deprecated and will be removed. It no longer works for Model entities. Use the 
      *     {@link Graphics} API instead.
      */
-     /**jsdoc
+     /*@jsdoc
       * Called when a {@link Entities.getMeshes} call is complete.
       * @callback Entities~getMeshesCallback
       * @param {MeshProxy[]} meshes - If success is true, a {@link MeshProxy} per mesh in the 
@@ -1901,7 +1909,7 @@ public slots:
     // FIXME move to a renderable entity interface
     Q_INVOKABLE void getMeshes(const QUuid& entityID, QScriptValue callback);
 
-    /**jsdoc
+    /*@jsdoc
      * Gets the object to world transform, excluding scale, of an entity.
      * @function Entities.getEntityTransform
      * @param {Uuid} entityID - The ID of the entity.
@@ -1929,7 +1937,7 @@ public slots:
      */
     Q_INVOKABLE glm::mat4 getEntityTransform(const QUuid& entityID);
 
-    /**jsdoc
+    /*@jsdoc
      * Gets the object to parent transform, excluding scale, of an entity.
      * @function Entities.getEntityLocalTransform
      * @param {Uuid} entityID - The ID of the entity.
@@ -1965,7 +1973,7 @@ public slots:
     Q_INVOKABLE glm::mat4 getEntityLocalTransform(const QUuid& entityID);
 
 
-    /**jsdoc
+    /*@jsdoc
      * Converts a position in world coordinates to a position in an avatar, entity, or joint's local coordinates.
      * @function Entities.worldToLocalPosition
      * @param {Vec3} worldPosition - The world position to convert.
@@ -2001,7 +2009,7 @@ public slots:
      */
     Q_INVOKABLE glm::vec3 worldToLocalPosition(glm::vec3 worldPosition, const QUuid& parentID,
                                                int parentJointIndex = -1, bool scalesWithParent = false);
-    /**jsdoc
+    /*@jsdoc
      * Converts a rotation or orientation in world coordinates to rotation in an avatar, entity, or joint's local coordinates.
      * @function Entities.worldToLocalRotation
      * @param {Quat} worldRotation - The world rotation to convert.
@@ -2013,7 +2021,7 @@ public slots:
      */
     Q_INVOKABLE glm::quat worldToLocalRotation(glm::quat worldRotation, const QUuid& parentID,
                                                int parentJointIndex = -1, bool scalesWithParent = false);
-    /**jsdoc
+    /*@jsdoc
      * Converts a velocity in world coordinates to a velocity in an avatar, entity, or joint's local coordinates.
      * @function Entities.worldToLocalVelocity
      * @param {Vec3} worldVelocity - The world velocity to convert.
@@ -2026,7 +2034,7 @@ public slots:
      */
     Q_INVOKABLE glm::vec3 worldToLocalVelocity(glm::vec3 worldVelocity, const QUuid& parentID,
                                                int parentJointIndex = -1, bool scalesWithParent = false);
-    /**jsdoc
+    /*@jsdoc
      * Converts a Euler angular velocity in world coordinates to an angular velocity in an avatar, entity, or joint's local 
      * coordinates.
      * @function Entities.worldToLocalAngularVelocity
@@ -2040,7 +2048,7 @@ public slots:
      */
     Q_INVOKABLE glm::vec3 worldToLocalAngularVelocity(glm::vec3 worldAngularVelocity, const QUuid& parentID,
                                                       int parentJointIndex = -1, bool scalesWithParent = false);
-    /**jsdoc
+    /*@jsdoc
      * Converts dimensions in world coordinates to dimensions in an avatar or entity's local coordinates.
      * @function Entities.worldToLocalDimensions
      * @param {Vec3} worldDimensions - The world dimensions to convert.
@@ -2052,7 +2060,7 @@ public slots:
      */
     Q_INVOKABLE glm::vec3 worldToLocalDimensions(glm::vec3 worldDimensions, const QUuid& parentID,
                                                  int parentJointIndex = -1, bool scalesWithParent = false);
-    /**jsdoc
+    /*@jsdoc
      * Converts a position in an avatar, entity, or joint's local coordinate to a position in world coordinates.
      * @function Entities.localToWorldPosition
      * @param {Vec3} localPosition - The local position to convert.
@@ -2065,7 +2073,7 @@ public slots:
      */
     Q_INVOKABLE glm::vec3 localToWorldPosition(glm::vec3 localPosition, const QUuid& parentID,
                                                int parentJointIndex = -1, bool scalesWithParent = false);
-    /**jsdoc
+    /*@jsdoc
      * Converts a rotation or orientation in an avatar, entity, or joint's local coordinate to a rotation in world coordinates.
      * @function Entities.localToWorldRotation
      * @param {Quat} localRotation - The local rotation to convert.
@@ -2077,7 +2085,7 @@ public slots:
      */
     Q_INVOKABLE glm::quat localToWorldRotation(glm::quat localRotation, const QUuid& parentID,
                                                int parentJointIndex = -1, bool scalesWithParent = false);
-    /**jsdoc
+    /*@jsdoc
      * Converts a velocity in an avatar, entity, or joint's local coordinate to a velocity in world coordinates.
      * @function Entities.localToWorldVelocity
      * @param {Vec3} localVelocity - The local velocity to convert.
@@ -2090,7 +2098,7 @@ public slots:
      */
     Q_INVOKABLE glm::vec3 localToWorldVelocity(glm::vec3 localVelocity, const QUuid& parentID,
                                                int parentJointIndex = -1, bool scalesWithParent = false);
-    /**jsdoc
+    /*@jsdoc
      * Converts a Euler angular velocity in an avatar, entity, or joint's local coordinate to an angular velocity in world 
      * coordinates.
      * @function Entities.localToWorldAngularVelocity
@@ -2104,7 +2112,7 @@ public slots:
      */
     Q_INVOKABLE glm::vec3 localToWorldAngularVelocity(glm::vec3 localAngularVelocity, const QUuid& parentID,
                                                       int parentJointIndex = -1, bool scalesWithParent = false);
-    /**jsdoc
+    /*@jsdoc
      * Converts dimensions in an avatar or entity's local coordinates to dimensions in world coordinates.
      * @function Entities.localToWorldDimensions
      * @param {Vec3} localDimensions - The local dimensions to convert.
@@ -2118,7 +2126,7 @@ public slots:
                                                  int parentJointIndex = -1, bool scalesWithParent = false);
 
 
-    /**jsdoc
+    /*@jsdoc
      * Gets the static certificate for an entity. The static certificate contains static properties of the item which cannot
      * be altered.
      * @function Entities.getStaticCertificateJSON
@@ -2127,7 +2135,7 @@ public slots:
      */
     Q_INVOKABLE QString getStaticCertificateJSON(const QUuid& entityID);
 
-    /**jsdoc
+    /*@jsdoc
      * Verifies the entity's proof of provenance, i.e., that the entity's certificateID property was produced by
      * High Fidelity signing the entity's static certificate JSON.
      * @function Entities.verifyStaticCertificateProperties
@@ -2137,7 +2145,7 @@ public slots:
      */
     Q_INVOKABLE bool verifyStaticCertificateProperties(const QUuid& entityID);
 
-    /**jsdoc
+    /*@jsdoc
      * Gets information about an entity property, including a minimum to maximum range for some numerical properties.
      * @function Entities.getPropertyInfo
      * @param {string} propertyName - The name of the property to get the information for.
@@ -2149,7 +2157,7 @@ public slots:
     Q_INVOKABLE const EntityPropertyInfo getPropertyInfo(const QString& propertyName) const;
 
 signals:
-    /**jsdoc
+    /*@jsdoc
      * Triggered on the client that is the physics simulation owner during the collision of two entities. Note: Isn't triggered
      * for a collision with an avatar.
      * 

See also, {@link Entities|Entity Methods} and {@link Script.addEventHandler}.

@@ -2191,7 +2199,7 @@ signals: */ void collisionWithEntity(const EntityItemID& idA, const EntityItemID& idB, const Collision& collision); - /**jsdoc + /*@jsdoc * Triggered when your ability to change the locked property of entities changes. * @function Entities.canAdjustLocksChanged * @param {boolean} canAdjustLocks - true if the script can change the locked property of an @@ -2205,7 +2213,7 @@ signals: */ void canAdjustLocksChanged(bool canAdjustLocks); - /**jsdoc + /*@jsdoc * Triggered when your ability to rez (create) entities changes. * @function Entities.canRezChanged * @param {boolean} canRez - true if the script can rez (create) entities, false if it can't. @@ -2213,7 +2221,7 @@ signals: */ void canRezChanged(bool canRez); - /**jsdoc + /*@jsdoc * Triggered when your ability to rez (create) temporary entities changes. Temporary entities are entities with a finite * lifetime property value set. * @function Entities.canRezTmpChanged @@ -2223,7 +2231,7 @@ signals: */ void canRezTmpChanged(bool canRezTmp); - /**jsdoc + /*@jsdoc * Triggered when your ability to rez (create) certified entities changes. Certified entities are entities that have PoP * certificates. * @function Entities.canRezCertifiedChanged @@ -2233,7 +2241,7 @@ signals: */ void canRezCertifiedChanged(bool canRezCertified); - /**jsdoc + /*@jsdoc * Triggered when your ability to rez (create) temporary certified entities changes. Temporary entities are entities with a * finite lifetime property value set. Certified entities are entities that have PoP certificates. * @function Entities.canRezTmpCertifiedChanged @@ -2243,7 +2251,7 @@ signals: */ void canRezTmpCertifiedChanged(bool canRezTmpCertified); - /**jsdoc + /*@jsdoc * Triggered when your ability to make changes to the asset server's assets changes. * @function Entities.canWriteAssetsChanged * @param {boolean} canWriteAssets - true if the script can change the asset server's assets, @@ -2252,17 +2260,26 @@ signals: */ void canWriteAssetsChanged(bool canWriteAssets); - /**jsdoc + /*@jsdoc * Triggered when your ability to get and set private user data changes. * @function Entities.canGetAndSetPrivateUserDataChanged - * @param {boolean} canGetAndSetPrivateUserData - true if the script change the privateUserData + * @param {boolean} canGetAndSetPrivateUserData - true if the script can change the privateUserData * property of an entity, false if it can't. * @returns {Signal} */ void canGetAndSetPrivateUserDataChanged(bool canGetAndSetPrivateUserData); + + /*@jsdoc + * Triggered when your ability to use avatar entities is changed. + * @function Entities.canRezAvatarEntitiesChanged + * @param {boolean} canRezAvatarEntities - true if the script can change edit avatar entities, + * false if it can't. + * @returns {Signal} + */ + void canRezAvatarEntitiesChanged(bool canRezAvatarEntities); - /**jsdoc + /*@jsdoc * Triggered when a mouse button is clicked while the mouse cursor is on an entity, or a controller trigger is fully * pressed while its laser is on an entity. *

See also, {@link Entities|Entity Methods} and {@link Script.addEventHandler}.

@@ -2279,7 +2296,7 @@ signals: */ void mousePressOnEntity(const EntityItemID& entityItemID, const PointerEvent& event); - /**jsdoc + /*@jsdoc * Triggered when a mouse button is double-clicked while the mouse cursor is on an entity. * @function Entities.mouseDoublePressOnEntity * @param {Uuid} entityID - The ID of the entity that was double-pressed on. @@ -2288,7 +2305,7 @@ signals: */ void mouseDoublePressOnEntity(const EntityItemID& entityItemID, const PointerEvent& event); - /**jsdoc + /*@jsdoc * Repeatedly triggered while the mouse cursor or controller laser moves on an entity. *

See also, {@link Entities|Entity Methods} and {@link Script.addEventHandler}.

* @function Entities.mouseMoveOnEntity @@ -2298,7 +2315,7 @@ signals: */ void mouseMoveOnEntity(const EntityItemID& entityItemID, const PointerEvent& event); - /**jsdoc + /*@jsdoc * Triggered when a mouse button is released after clicking on an entity or the controller trigger is partly or fully * released after pressing on an entity, even if the mouse pointer or controller laser has moved off the entity. *

See also, {@link Entities|Entity Methods} and {@link Script.addEventHandler}.

@@ -2309,7 +2326,7 @@ signals: */ void mouseReleaseOnEntity(const EntityItemID& entityItemID, const PointerEvent& event); - /**jsdoc + /*@jsdoc * Triggered when a mouse button is clicked while the mouse cursor is not on an entity. * @function Entities.mousePressOffEntity * @param {PointerEvent} event - Details of the event. @@ -2317,7 +2334,7 @@ signals: */ void mousePressOffEntity(); - /**jsdoc + /*@jsdoc * Triggered when a mouse button is double-clicked while the mouse cursor is not on an entity. * @function Entities.mouseDoublePressOffEntity * @param {PointerEvent} event - Details of the event. @@ -2326,7 +2343,7 @@ signals: void mouseDoublePressOffEntity(); - /**jsdoc + /*@jsdoc * Triggered when a mouse button is clicked while the mouse cursor is on an entity. Note: Not triggered by controllers. *

See also, {@link Entities|Entity Methods} and {@link Script.addEventHandler}.

* @function Entities.clickDownOnEntity @@ -2359,7 +2376,7 @@ signals: */ void clickDownOnEntity(const EntityItemID& entityItemID, const PointerEvent& event); - /**jsdoc + /*@jsdoc * Repeatedly triggered while a mouse button continues to be held after clicking an entity, even if the mouse cursor has * moved off the entity. Note: Not triggered by controllers. *

See also, {@link Entities|Entity Methods} and {@link Script.addEventHandler}.

@@ -2370,7 +2387,7 @@ signals: */ void holdingClickOnEntity(const EntityItemID& entityItemID, const PointerEvent& event); - /**jsdoc + /*@jsdoc * Triggered when a mouse button is released after clicking on an entity, even if the mouse cursor has moved off the * entity. Note: Not triggered by controllers. *

See also, {@link Entities|Entity Methods} and {@link Script.addEventHandler}.

@@ -2381,7 +2398,7 @@ signals: */ void clickReleaseOnEntity(const EntityItemID& entityItemID, const PointerEvent& event); - /**jsdoc + /*@jsdoc * Triggered when the mouse cursor or controller laser starts hovering on an entity. *

See also, {@link Entities|Entity Methods} and {@link Script.addEventHandler}.

* @function Entities.hoverEnterEntity @@ -2391,7 +2408,7 @@ signals: */ void hoverEnterEntity(const EntityItemID& entityItemID, const PointerEvent& event); - /**jsdoc + /*@jsdoc * Repeatedly triggered when the mouse cursor or controller laser moves while hovering over an entity. *

See also, {@link Entities|Entity Methods} and {@link Script.addEventHandler}.

* @function Entities.hoverOverEntity @@ -2401,7 +2418,7 @@ signals: */ void hoverOverEntity(const EntityItemID& entityItemID, const PointerEvent& event); - /**jsdoc + /*@jsdoc * Triggered when the mouse cursor or controller laser stops hovering over an entity. *

See also, {@link Entities|Entity Methods} and {@link Script.addEventHandler}.

* @function Entities.hoverLeaveEntity @@ -2412,7 +2429,7 @@ signals: void hoverLeaveEntity(const EntityItemID& entityItemID, const PointerEvent& event); - /**jsdoc + /*@jsdoc * Triggered when an avatar enters an entity. * Note: At the initial loading of the script, if the avatar is already present inside the entity, it might be too late * to catch this event when the script runs, so it won't trigger. The {@link Entities.preload|preload} signal can be used to handle those cases. @@ -2423,7 +2440,7 @@ signals: */ void enterEntity(const EntityItemID& entityItemID); - /**jsdoc + /*@jsdoc * Triggered when an avatar leaves an entity. *

See also, {@link Entities|Entity Methods} and {@link Script.addEventHandler}.

* @function Entities.leaveEntity @@ -2433,7 +2450,7 @@ signals: void leaveEntity(const EntityItemID& entityItemID); - /**jsdoc + /*@jsdoc * Triggered when an entity is deleted. * @function Entities.deletingEntity * @param {Uuid} entityID - The ID of the entity deleted. @@ -2445,7 +2462,7 @@ signals: */ void deletingEntity(const EntityItemID& entityID); - /**jsdoc + /*@jsdoc * Triggered when an entity is added to Interface's local in-memory tree of entities it knows about. This may occur when * entities are loaded upon visiting a domain, when the user rotates their view so that more entities become visible, and * when any type of entity is created (e.g., by {@link Entities.addEntity|addEntity}). @@ -2459,7 +2476,7 @@ signals: */ void addingEntity(const EntityItemID& entityID); - /**jsdoc + /*@jsdoc * Triggered when a "wearable" entity is deleted, for example when removing a "wearable" from your avatar. * @function Entities.deletingWearable * @param {Uuid} entityID - The ID of the "wearable" entity deleted. @@ -2471,7 +2488,7 @@ signals: */ void deletingWearable(const EntityItemID& entityID); - /**jsdoc + /*@jsdoc * Triggered when a "wearable" entity is added to Interface's local in-memory tree of entities it knows about, for example * when adding a "wearable" to your avatar. * @function Entities.addingWearable @@ -2484,7 +2501,7 @@ signals: */ void addingWearable(const EntityItemID& entityID); - /**jsdoc + /*@jsdoc * Triggered when you disconnect from a domain, at which time Interface's local in-memory tree of entities that it knows * about is cleared. * @function Entities.clearingEntities @@ -2496,7 +2513,7 @@ signals: */ void clearingEntities(); - /**jsdoc + /*@jsdoc * Triggered when a script in a {@link Entities.EntityProperties-Web|Web} entity's HTML sends an event over the entity's * HTML event bridge. The HTML web page can send a message by calling: *
EventBridge.emitWebEvent(message);
diff --git a/libraries/entities/src/EntityTypes.h b/libraries/entities/src/EntityTypes.h index 7f72c3f761..441e77fccd 100644 --- a/libraries/entities/src/EntityTypes.h +++ b/libraries/entities/src/EntityTypes.h @@ -35,7 +35,7 @@ typedef EntityItemPointer (*EntityTypeFactory)(const EntityItemID& entityID, con class EntityTypes { public: - /**jsdoc + /*@jsdoc *

An entity may be one of the following types:

*
* diff --git a/libraries/entities/src/GrabPropertyGroup.h b/libraries/entities/src/GrabPropertyGroup.h index 9fa58273be..6f0bc9d48b 100644 --- a/libraries/entities/src/GrabPropertyGroup.h +++ b/libraries/entities/src/GrabPropertyGroup.h @@ -40,7 +40,7 @@ static const glm::vec3 INITIAL_EQUIPPABLE_INDICATOR_SCALE { glm::vec3(1.0f) }; static const glm::vec3 INITIAL_EQUIPPABLE_INDICATOR_OFFSET { glm::vec3(0.0f) }; -/**jsdoc +/*@jsdoc * Grabbing behavior is defined by the following properties: * * @typedef {object} Entities.Grab diff --git a/libraries/entities/src/HazePropertyGroup.h b/libraries/entities/src/HazePropertyGroup.h index 59a36b6f7f..2828692a78 100644 --- a/libraries/entities/src/HazePropertyGroup.h +++ b/libraries/entities/src/HazePropertyGroup.h @@ -42,7 +42,7 @@ static const float INITIAL_KEY_LIGHT_ALTITUDE{ 200.0f }; // FIXME: Document hazeAttenuationKeyLight, hazeKeyLightRange, and hazeKeyLightAltitude once they're working and are provided // in the Create app's UI. -/**jsdoc +/*@jsdoc * Haze is defined by the following properties: * @typedef {object} Entities.Haze * diff --git a/libraries/entities/src/ImageEntityItem.cpp b/libraries/entities/src/ImageEntityItem.cpp index afa6d9ae69..41cdde7676 100644 --- a/libraries/entities/src/ImageEntityItem.cpp +++ b/libraries/entities/src/ImageEntityItem.cpp @@ -34,6 +34,7 @@ EntityItemProperties ImageEntityItem::getProperties(const EntityPropertyFlags& d COPY_ENTITY_PROPERTY_TO_PROPERTIES(alpha, getAlpha); withReadLock([&] { _pulseProperties.getProperties(properties); + properties.setNaturalDimensions(_naturalDimensions); }); COPY_ENTITY_PROPERTY_TO_PROPERTIES(imageURL, getImageURL); @@ -217,4 +218,10 @@ PulsePropertyGroup ImageEntityItem::getPulseProperties() const { return resultWithReadLock([&] { return _pulseProperties; }); -} \ No newline at end of file +} + +void ImageEntityItem::setNaturalDimension(const glm::vec3& naturalDimensions) const { + withWriteLock([&] { + _naturalDimensions = naturalDimensions; + }); +} diff --git a/libraries/entities/src/ImageEntityItem.h b/libraries/entities/src/ImageEntityItem.h index 4f7aac0c13..0cc4eae05a 100644 --- a/libraries/entities/src/ImageEntityItem.h +++ b/libraries/entities/src/ImageEntityItem.h @@ -63,6 +63,8 @@ public: PulsePropertyGroup getPulseProperties() const; + void setNaturalDimension(const glm::vec3& naturalDimensions) const; + protected: glm::u8vec3 _color; float _alpha; @@ -72,6 +74,8 @@ protected: bool _emissive { false }; bool _keepAspectRatio { true }; QRect _subImage; + + mutable glm::vec3 _naturalDimensions; }; #endif // hifi_ImageEntityItem_h diff --git a/libraries/entities/src/KeyLightPropertyGroup.h b/libraries/entities/src/KeyLightPropertyGroup.h index 6441c30d50..f65c6b6fb9 100644 --- a/libraries/entities/src/KeyLightPropertyGroup.h +++ b/libraries/entities/src/KeyLightPropertyGroup.h @@ -27,7 +27,7 @@ class OctreePacketData; class EntityTreeElementExtraEncodeData; class ReadBitstreamToTreeParams; -/**jsdoc +/*@jsdoc * A key light is defined by the following properties: * @typedef {object} Entities.KeyLight * @property {Color} color=255,255,255 - The color of the light. diff --git a/libraries/entities/src/PolyVoxEntityItem.h b/libraries/entities/src/PolyVoxEntityItem.h index 3e3fe0b18c..163e03cd55 100644 --- a/libraries/entities/src/PolyVoxEntityItem.h +++ b/libraries/entities/src/PolyVoxEntityItem.h @@ -62,7 +62,7 @@ class PolyVoxEntityItem : public EntityItem { virtual int getOnCount() const { return 0; } - /**jsdoc + /*@jsdoc *

The surface of a {@link Entities.EntityProperties-PolyVox|PolyVox} entity may be one of the following styles:

*
* diff --git a/libraries/entities/src/PulsePropertyGroup.h b/libraries/entities/src/PulsePropertyGroup.h index 634ab654a7..665713d128 100644 --- a/libraries/entities/src/PulsePropertyGroup.h +++ b/libraries/entities/src/PulsePropertyGroup.h @@ -25,7 +25,7 @@ class EncodeBitstreamParams; class OctreePacketData; class ReadBitstreamToTreeParams; -/**jsdoc +/*@jsdoc * A color and alpha pulse that an entity may have. * @typedef {object} Entities.Pulse * @property {number} min=0 - The minimum value of the pulse multiplier. diff --git a/libraries/entities/src/RingGizmoPropertyGroup.h b/libraries/entities/src/RingGizmoPropertyGroup.h index 1f23152fc7..1d315622eb 100644 --- a/libraries/entities/src/RingGizmoPropertyGroup.h +++ b/libraries/entities/src/RingGizmoPropertyGroup.h @@ -24,7 +24,7 @@ class ReadBitstreamToTreeParams; using u8vec3Color = glm::u8vec3; -/**jsdoc +/*@jsdoc * A {@link Entities.EntityProperties-Gizmo|ring Gizmo} entity is defined by the following properties: * @typedef {object} Entities.RingGizmo * diff --git a/libraries/entities/src/ShapeEntityItem.cpp b/libraries/entities/src/ShapeEntityItem.cpp index 4349eefd2d..6d802fb512 100644 --- a/libraries/entities/src/ShapeEntityItem.cpp +++ b/libraries/entities/src/ShapeEntityItem.cpp @@ -21,7 +21,7 @@ namespace entity { - /**jsdoc + /*@jsdoc *

A "Shape", "Box", or "Sphere" {@link Entities.EntityType|EntityType} may * display as one of the following geometrical shapes:

*
@@ -339,7 +339,7 @@ bool ShapeEntityItem::findDetailedParabolaIntersection(const glm::vec3& origin, bool ShapeEntityItem::getRotateForPicking() const { auto shape = getShape(); - return getBillboardMode() != BillboardMode::NONE && (_shape < entity::Shape::Cube || _shape > entity::Shape::Icosahedron); + return getBillboardMode() != BillboardMode::NONE && (shape < entity::Shape::Cube || shape > entity::Shape::Icosahedron); } void ShapeEntityItem::debugDump() const { diff --git a/libraries/entities/src/SkyboxPropertyGroup.h b/libraries/entities/src/SkyboxPropertyGroup.h index 0c128aa730..36cea0a52a 100644 --- a/libraries/entities/src/SkyboxPropertyGroup.h +++ b/libraries/entities/src/SkyboxPropertyGroup.h @@ -29,7 +29,7 @@ class OctreePacketData; class EntityTreeElementExtraEncodeData; class ReadBitstreamToTreeParams; -/**jsdoc +/*@jsdoc * A skybox is defined by the following properties: * @typedef {object} Entities.Skybox * @property {Color} color=0,0,0 - Sets the color of the sky if url is "", otherwise modifies the diff --git a/libraries/entities/src/ZoneEntityItem.cpp b/libraries/entities/src/ZoneEntityItem.cpp index 3eabfb4f1e..abccdf7167 100644 --- a/libraries/entities/src/ZoneEntityItem.cpp +++ b/libraries/entities/src/ZoneEntityItem.cpp @@ -270,7 +270,6 @@ void ZoneEntityItem::debugDump() const { } void ZoneEntityItem::setShapeType(ShapeType type) { - ShapeType oldShapeType = _shapeType; switch(type) { case SHAPE_TYPE_NONE: case SHAPE_TYPE_CAPSULE_X: @@ -288,7 +287,12 @@ void ZoneEntityItem::setShapeType(ShapeType type) { default: break; } - _shapeType = type; + + ShapeType oldShapeType; + withWriteLock([&] { + oldShapeType = _shapeType; + _shapeType = type; + }); if (type == SHAPE_TYPE_COMPOUND) { if (type != oldShapeType) { @@ -300,16 +304,21 @@ void ZoneEntityItem::setShapeType(ShapeType type) { } ShapeType ZoneEntityItem::getShapeType() const { - return _shapeType; + return resultWithReadLock([&] { + return _shapeType; + }); } void ZoneEntityItem::setCompoundShapeURL(const QString& url) { - QString oldCompoundShapeURL = _compoundShapeURL; + QString oldCompoundShapeURL; + ShapeType shapeType; withWriteLock([&] { + oldCompoundShapeURL = _compoundShapeURL; _compoundShapeURL = url; + shapeType = _shapeType; }); if (oldCompoundShapeURL != url) { - if (_shapeType == SHAPE_TYPE_COMPOUND) { + if (shapeType == SHAPE_TYPE_COMPOUND) { fetchCollisionGeometryResource(); } else { _shapeResource.reset(); @@ -333,7 +342,7 @@ bool ZoneEntityItem::findDetailedParabolaIntersection(const glm::vec3& origin, c bool ZoneEntityItem::contains(const glm::vec3& point) const { GeometryResource::Pointer resource = _shapeResource; - if (_shapeType == SHAPE_TYPE_COMPOUND && resource) { + if (getShapeType() == SHAPE_TYPE_COMPOUND && resource) { if (resource->isLoaded()) { const HFMModel& hfmModel = resource->getHFMModel(); diff --git a/libraries/gpu-gl/CMakeLists.txt b/libraries/gpu-gl/CMakeLists.txt index 01f097df87..de651e5116 100644 --- a/libraries/gpu-gl/CMakeLists.txt +++ b/libraries/gpu-gl/CMakeLists.txt @@ -1,9 +1,9 @@ set(TARGET_NAME gpu-gl) setup_hifi_library(Concurrent) link_hifi_libraries(shared gl gpu gpu-gl-common shaders) -if (UNIX) +if (UNIX AND NOT VIRCADIA_THREAD_DEBUGGING) target_link_libraries(${TARGET_NAME} pthread) -endif(UNIX) +endif(UNIX AND NOT VIRCADIA_THREAD_DEBUGGING) GroupSources("src") set(OpenGL_GL_PREFERENCE "LEGACY") diff --git a/libraries/gpu/src/gpu/Texture.h b/libraries/gpu/src/gpu/Texture.h index 750141ecf6..12896aca7b 100755 --- a/libraries/gpu/src/gpu/Texture.h +++ b/libraries/gpu/src/gpu/Texture.h @@ -584,11 +584,11 @@ public: ExternalUpdates getUpdates() const; // Serialize a texture into a KTX file - static ktx::KTXUniquePointer serialize(const Texture& texture); + static ktx::KTXUniquePointer serialize(const Texture& texture, const glm::ivec2& originalSize); - static TexturePointer build(const ktx::KTXDescriptor& descriptor); - static TexturePointer unserialize(const std::string& ktxFile); - static TexturePointer unserialize(const cache::FilePointer& cacheEntry, const std::string& source = std::string()); + static std::pair build(const ktx::KTXDescriptor& descriptor); + static std::pair unserialize(const std::string& ktxFile); + static std::pair unserialize(const cache::FilePointer& cacheEntry, const std::string& source = std::string()); static bool evalKTXFormat(const Element& mipFormat, const Element& texelFormat, ktx::Header& header); static bool evalTextureFormat(const ktx::Header& header, Element& mipFormat, Element& texelFormat); diff --git a/libraries/gpu/src/gpu/Texture_ktx.cpp b/libraries/gpu/src/gpu/Texture_ktx.cpp index a5cea3e60e..c4b674a917 100644 --- a/libraries/gpu/src/gpu/Texture_ktx.cpp +++ b/libraries/gpu/src/gpu/Texture_ktx.cpp @@ -13,6 +13,7 @@ #include "Texture.h" #include +#include #include @@ -30,15 +31,16 @@ struct GPUKTXPayload { using Version = uint8; static const std::string KEY; - static const Version CURRENT_VERSION { 1 }; + static const Version CURRENT_VERSION { 2 }; static const size_t PADDING { 2 }; - static const size_t SIZE { sizeof(Version) + sizeof(Sampler::Desc) + sizeof(uint32) + sizeof(TextureUsageType) + PADDING }; - static_assert(GPUKTXPayload::SIZE == 36, "Packing size may differ between platforms"); + static const size_t SIZE { sizeof(Version) + sizeof(Sampler::Desc) + sizeof(uint32) + sizeof(TextureUsageType) + sizeof(glm::ivec2) + PADDING }; + static_assert(GPUKTXPayload::SIZE == 44, "Packing size may differ between platforms"); static_assert(GPUKTXPayload::SIZE % 4 == 0, "GPUKTXPayload is not 4 bytes aligned"); Sampler::Desc _samplerDesc; Texture::Usage _usage; TextureUsageType _usageType; + glm::ivec2 _originalSize { 0, 0 }; Byte* serialize(Byte* data) const { *(Version*)data = CURRENT_VERSION; @@ -56,26 +58,22 @@ struct GPUKTXPayload { memcpy(data, &_usageType, sizeof(TextureUsageType)); data += sizeof(TextureUsageType); + memcpy(data, glm::value_ptr(_originalSize), sizeof(glm::ivec2)); + data += sizeof(glm::ivec2); + return data + PADDING; } bool unserialize(const Byte* data, size_t size) { - if (size != SIZE) { + Version version = *(const Version*)data; + data += sizeof(Version); + + if (version > CURRENT_VERSION) { + // If we try to load a version that we don't know how to parse, + // it will render incorrectly return false; } - Version version = *(const Version*)data; - if (version != CURRENT_VERSION) { - glm::vec4 borderColor(1.0f); - if (memcmp(&borderColor, data, sizeof(glm::vec4)) == 0) { - memcpy(this, data, sizeof(GPUKTXPayload)); - return true; - } else { - return false; - } - } - data += sizeof(Version); - memcpy(&_samplerDesc, data, sizeof(Sampler::Desc)); data += sizeof(Sampler::Desc); @@ -87,6 +85,13 @@ struct GPUKTXPayload { data += sizeof(uint32); memcpy(&_usageType, data, sizeof(TextureUsageType)); + data += sizeof(TextureUsageType); + + if (version >= 2) { + memcpy(&_originalSize, data, sizeof(glm::ivec2)); + data += sizeof(glm::ivec2); + } + return true; } @@ -382,7 +387,7 @@ void Texture::setKtxBacking(const cache::FilePointer& cacheEntry) { } -ktx::KTXUniquePointer Texture::serialize(const Texture& texture) { +ktx::KTXUniquePointer Texture::serialize(const Texture& texture, const glm::ivec2& originalSize) { ktx::Header header; // From texture format to ktx format description @@ -459,6 +464,7 @@ ktx::KTXUniquePointer Texture::serialize(const Texture& texture) { gpuKeyval._samplerDesc = texture.getSampler().getDesc(); gpuKeyval._usage = texture.getUsage(); gpuKeyval._usageType = texture.getUsageType(); + gpuKeyval._originalSize = originalSize; Byte keyvalPayload[GPUKTXPayload::SIZE]; gpuKeyval.serialize(keyvalPayload); @@ -514,19 +520,19 @@ ktx::KTXUniquePointer Texture::serialize(const Texture& texture) { return ktxBuffer; } -TexturePointer Texture::build(const ktx::KTXDescriptor& descriptor) { +std::pair Texture::build(const ktx::KTXDescriptor& descriptor) { Format mipFormat = Format::COLOR_BGRA_32; Format texelFormat = Format::COLOR_SRGBA_32; const auto& header = descriptor.header; if (!Texture::evalTextureFormat(header, mipFormat, texelFormat)) { - return nullptr; + return { nullptr, { 0, 0 } }; } // Find Texture Type based on dimensions Type type = TEX_1D; if (header.pixelWidth == 0) { - return nullptr; + return { nullptr, { 0, 0 } }; } else if (header.pixelHeight == 0) { type = TEX_1D; } else if (header.pixelDepth == 0) { @@ -569,39 +575,39 @@ TexturePointer Texture::build(const ktx::KTXDescriptor& descriptor) { texture->overrideIrradiance(std::make_shared(irradianceKtxKeyValue._irradianceSH)); } - return texture; + return { texture, gpuktxKeyValue._originalSize }; } -TexturePointer Texture::unserialize(const cache::FilePointer& cacheEntry, const std::string& source) { +std::pair Texture::unserialize(const cache::FilePointer& cacheEntry, const std::string& source) { std::unique_ptr ktxPointer = ktx::KTX::create(std::make_shared(cacheEntry->getFilepath().c_str())); if (!ktxPointer) { - return nullptr; + return { nullptr, { 0, 0 } }; } - auto texture = build(ktxPointer->toDescriptor()); - if (texture) { - texture->setKtxBacking(cacheEntry); - if (texture->source().empty()) { - texture->setSource(source); + auto textureAndSize = build(ktxPointer->toDescriptor()); + if (textureAndSize.first) { + textureAndSize.first->setKtxBacking(cacheEntry); + if (textureAndSize.first->source().empty()) { + textureAndSize.first->setSource(source); } } - return texture; + return { textureAndSize.first, textureAndSize.second }; } -TexturePointer Texture::unserialize(const std::string& ktxfile) { +std::pair Texture::unserialize(const std::string& ktxfile) { std::unique_ptr ktxPointer = ktx::KTX::create(std::make_shared(ktxfile.c_str())); if (!ktxPointer) { - return nullptr; + return { nullptr, { 0, 0 } }; } - auto texture = build(ktxPointer->toDescriptor()); - if (texture) { - texture->setKtxBacking(ktxfile); - texture->setSource(ktxfile); + auto textureAndSize = build(ktxPointer->toDescriptor()); + if (textureAndSize.first) { + textureAndSize.first->setKtxBacking(ktxfile); + textureAndSize.first->setSource(ktxfile); } - return texture; + return { textureAndSize.first, textureAndSize.second }; } bool Texture::evalKTXFormat(const Element& mipFormat, const Element& texelFormat, ktx::Header& header) { diff --git a/libraries/graphics-scripting/CMakeLists.txt b/libraries/graphics-scripting/CMakeLists.txt index 9bb34adda1..3542704fc8 100644 --- a/libraries/graphics-scripting/CMakeLists.txt +++ b/libraries/graphics-scripting/CMakeLists.txt @@ -1,4 +1,4 @@ set(TARGET_NAME graphics-scripting) setup_hifi_library() -link_hifi_libraries(shared networking graphics fbx image material-networking model-networking script-engine) +link_hifi_libraries(shared networking graphics model-serializers image material-networking model-networking script-engine) include_hifi_library_headers(gpu) diff --git a/libraries/graphics-scripting/src/graphics-scripting/Forward.h b/libraries/graphics-scripting/src/graphics-scripting/Forward.h index 29f8079422..8804b63de9 100644 --- a/libraries/graphics-scripting/src/graphics-scripting/Forward.h +++ b/libraries/graphics-scripting/src/graphics-scripting/Forward.h @@ -76,7 +76,7 @@ namespace scriptable { graphics::MaterialKey key { 0 }; }; - /**jsdoc + /*@jsdoc * A material layer. * @typedef {object} Graphics.MaterialLayer * @property {Graphics.Material} material - The layer's material. @@ -108,7 +108,7 @@ namespace scriptable { ScriptableMeshBase& operator=(const ScriptableMeshBase& view); virtual ~ScriptableMeshBase(); - /**jsdoc + /*@jsdoc * @function GraphicsMesh.getMeshPointer * @deprecated This method is deprecated and will be removed. * @returns {undefined} @@ -116,7 +116,7 @@ namespace scriptable { // scriptable::MeshPointer is not registered as a JavaScript type. Q_INVOKABLE const scriptable::MeshPointer getMeshPointer() const { return weakMesh.lock(); } - /**jsdoc + /*@jsdoc * @function GraphicsMesh.getModelProviderPointer * @deprecated This method is deprecated and will be removed. * @returns {undefined} @@ -124,7 +124,7 @@ namespace scriptable { // scriptable::ModelProviderPointer is not registered as a JavaScript type. Q_INVOKABLE const scriptable::ModelProviderPointer getModelProviderPointer() const { return provider.lock(); } - /**jsdoc + /*@jsdoc * @function GraphicsMesh.getModelBasePointer * @deprecated This method is deprecated and will be removed. * @returns {undefined} diff --git a/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingInterface.cpp b/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingInterface.cpp index a27eff9cbe..ea0c5392c0 100644 --- a/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingInterface.cpp +++ b/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingInterface.cpp @@ -167,7 +167,7 @@ scriptable::ScriptableMeshPointer GraphicsScriptingInterface::newMesh(const QVar // TODO: this is bare-bones way for now to improvise a new mesh from the scripting side // in the future we want to support a formal C++ structure data type here instead - /**jsdoc + /*@jsdoc * IFS (Indexed-Face Set) data defining a mesh. * @typedef {object} Graphics.IFSData * @property {string} [name=""] - Mesh name. (Useful for debugging.) @@ -355,7 +355,7 @@ namespace scriptable { qScriptValueToSequence(array, result); } - /**jsdoc + /*@jsdoc * A material in a {@link GraphicsModel}. * @typedef {object} Graphics.Material * @property {string} name - The name of the material. diff --git a/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingInterface.h b/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingInterface.h index 0f24ae8461..beb5b340e8 100644 --- a/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingInterface.h +++ b/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingInterface.h @@ -22,7 +22,7 @@ #include "RegisteredMetaTypes.h" -/**jsdoc +/*@jsdoc * The Graphics API enables you to access and manipulate avatar, entity, and overlay models in the rendered scene. * This includes getting mesh and material information for applying {@link Entities.EntityProperties-Material|Material} * entities. @@ -42,7 +42,7 @@ public: GraphicsScriptingInterface(QObject* parent = nullptr); public slots: - /**jsdoc + /*@jsdoc * Gets a handle to the model data used for displaying an avatar, 3D entity, or 3D overlay. *

Note: The model data may be used for more than one instance of the item displayed in the scene.

* @function Graphics.getModel @@ -65,7 +65,7 @@ public slots: */ scriptable::ScriptableModelPointer getModel(const QUuid& uuid); - /**jsdoc + /*@jsdoc * Updates the model for an avatar, 3D entity, or 3D overlay in the rendered scene. * @function Graphics.updateModel * @param {Uuid} id - The ID of the avatar, 3D entity, or 3D overlay to update. @@ -74,7 +74,7 @@ public slots: */ bool updateModel(const QUuid& uuid, const scriptable::ScriptableModelPointer& model); - /**jsdoc + /*@jsdoc * Checks whether the model for an avatar, entity, or overlay can be updated in the rendered scene. Only avatars, * "Model" entities and "model" overlays can have their meshes updated. * @function Graphics.canUpdateModel @@ -107,7 +107,7 @@ public slots: */ bool canUpdateModel(const QUuid& uuid, int meshIndex = -1, int partNumber = -1); - /**jsdoc + /*@jsdoc * Creates a new graphics model from meshes. * @function Graphics.newModel * @param {GraphicsMesh[]} meshes - The meshes to include in the model. @@ -115,7 +115,7 @@ public slots: */ scriptable::ScriptableModelPointer newModel(const scriptable::ScriptableMeshes& meshes); - /**jsdoc + /*@jsdoc * Creates a new graphics mesh. * @function Graphics.newMesh * @param {Graphics.IFSData} ifsMeshData - Index-Faced Set (IFS) data defining the mesh. @@ -130,7 +130,7 @@ public slots: bool updateMeshPart(scriptable::ScriptableMeshPointer mesh, scriptable::ScriptableMeshPartPointer part); #endif - /**jsdoc + /*@jsdoc * Exports a model to OBJ format. * @function Graphics.exportModelToOBJ * @param {GraphicsModel} model - The model to export. diff --git a/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingUtil.cpp b/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingUtil.cpp index 92dddc953e..2db34258c9 100644 --- a/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingUtil.cpp +++ b/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingUtil.cpp @@ -37,7 +37,7 @@ QVariant toVariant(const Extents& box) { }; } -/**jsdoc +/*@jsdoc * The extents of a mesh. * @typedef {object} Graphics.MeshExtents * @property {Vec3} brn - The bottom right near (minimum axes values) corner of the enclosing box. @@ -56,7 +56,7 @@ QVariant toVariant(const AABox& box) { }; } -/**jsdoc +/*@jsdoc * Details of a buffer element's format. * @typedef {object} Graphics.BufferElementFormat * @property {string} type - Type. diff --git a/libraries/graphics-scripting/src/graphics-scripting/ScriptableMesh.cpp b/libraries/graphics-scripting/src/graphics-scripting/ScriptableMesh.cpp index 3de5119fa7..f7d40f19f2 100644 --- a/libraries/graphics-scripting/src/graphics-scripting/ScriptableMesh.cpp +++ b/libraries/graphics-scripting/src/graphics-scripting/ScriptableMesh.cpp @@ -127,7 +127,7 @@ int scriptable::ScriptableMesh::getSlotNumber(const QString& attributeName) cons return -1; } -/**jsdoc +/*@jsdoc * Details of buffer's format. * @typedef {object} Graphics.BufferFormat * @property {number} slot - Slot. @@ -257,7 +257,7 @@ bool scriptable::ScriptableMesh::setVertexProperty(glm::uint32 vertexIndex, cons return buffer_helpers::setValue(bufferView, vertexIndex, value); } -/**jsdoc +/*@jsdoc * Called for each vertex when {@link GraphicsMesh.updateVertexAttributes} is called. * @callback GraphicsMesh~forEachVertextCallback * @param {Object} attributes - The attributes of the vertex. @@ -292,7 +292,7 @@ glm::uint32 scriptable::ScriptableMesh::forEachVertex(QScriptValue _callback) { return numProcessed; } -/**jsdoc +/*@jsdoc * Called for each vertex when {@link GraphicsMesh.updateVertexAttributes} is called. The value returned by the script function * should be the modified attributes to update the vertex with, or false to not update the particular vertex. * @callback GraphicsMesh~updateVertexAttributesCallback diff --git a/libraries/graphics-scripting/src/graphics-scripting/ScriptableMesh.h b/libraries/graphics-scripting/src/graphics-scripting/ScriptableMesh.h index 0e7eecc03b..a6ebbe8536 100644 --- a/libraries/graphics-scripting/src/graphics-scripting/ScriptableMesh.h +++ b/libraries/graphics-scripting/src/graphics-scripting/ScriptableMesh.h @@ -28,7 +28,7 @@ #include namespace scriptable { - /**jsdoc + /*@jsdoc * A handle to in-memory mesh data in a {@link GraphicsModel}. * *

Create using the {@link Graphics} API, {@link GraphicsModel.cloneModel}, or {@link GraphicsMesh.cloneMesh}.

@@ -107,7 +107,7 @@ namespace scriptable { public slots: - /**jsdoc + /*@jsdoc * Gets the model the mesh is part of. *

Currently doesn't work.

* @function GraphicsMesh.getParentModel @@ -115,14 +115,14 @@ namespace scriptable { */ const scriptable::ScriptableModelPointer getParentModel() const { return qobject_cast(model); } - /**jsdoc + /*@jsdoc * Gets the vertex indices. * @function GraphicsMesh.getIndices * @returns {number[]} The vertex indices. */ QVector getIndices() const; - /**jsdoc + /*@jsdoc * Gets the indices of nearby vertices. * @function GraphicsMesh.findNearbyVertexIndices * @param {Vec3} origin - The search position, in model coordinates. @@ -132,7 +132,7 @@ namespace scriptable { */ QVector findNearbyVertexIndices(const glm::vec3& origin, float epsilon = 1e-6) const; - /**jsdoc + /*@jsdoc * Adds an attribute for all vertices. * @function GraphicsMesh.addAttribute * @param {Graphics.BufferTypeName} name - The name of the attribute. @@ -142,7 +142,7 @@ namespace scriptable { */ glm::uint32 addAttribute(const QString& attributeName, const QVariant& defaultValue = QVariant()); - /**jsdoc + /*@jsdoc * Sets the value of an attribute for all vertices. * @function GraphicsMesh.fillAttribute * @param {Graphics.BufferTypeName} name - The name of the attribute. The attribute is added to the vertices if not @@ -153,7 +153,7 @@ namespace scriptable { */ glm::uint32 fillAttribute(const QString& attributeName, const QVariant& value); - /**jsdoc + /*@jsdoc * Removes an attribute from all vertices. *

Note: The "position" attribute cannot be removed.

* @function GraphicsMesh.removeAttribute @@ -162,7 +162,7 @@ namespace scriptable { */ bool removeAttribute(const QString& attributeName); - /**jsdoc + /*@jsdoc * Gets the value of an attribute for all vertices. * @function GraphicsMesh.queryVertexAttributes * @param {Graphics.BufferTypeName} name - The name of the attribute to get the vertex values of. @@ -171,7 +171,7 @@ namespace scriptable { */ QVariantList queryVertexAttributes(QVariant selector) const; - /**jsdoc + /*@jsdoc * Gets the attributes and attribute values of a vertex. * @function GraphicsMesh.getVertexAttributes * @param {number} index - The vertex to get the attributes for. @@ -180,7 +180,7 @@ namespace scriptable { */ QVariantMap getVertexAttributes(glm::uint32 vertexIndex) const; - /**jsdoc + /*@jsdoc * Updates attribute values of a vertex. * @function GraphicsMesh.setVertexAttributes * @param {number} index - The vertex to set the attributes for. @@ -194,7 +194,7 @@ namespace scriptable { // @borrows jsdoc from GraphicsMesh bool setVertexAttributes(glm::uint32 vertexIndex, const QVariantMap& attributeValues); - /**jsdoc + /*@jsdoc * Gets the value of a vertex's attribute. * @function GraphicsMesh.getVertexProperty * @param {number} index - The vertex index. @@ -205,7 +205,7 @@ namespace scriptable { */ QVariant getVertexProperty(glm::uint32 vertexIndex, const QString& attributeName) const; - /**jsdoc + /*@jsdoc * Sets the value of a vertex's attribute. * @function GraphicsMesh.setVertexProperty * @param {number} index - The vertex index. @@ -217,7 +217,7 @@ namespace scriptable { */ bool setVertexProperty(glm::uint32 vertexIndex, const QString& attributeName, const QVariant& value); - /**jsdoc + /*@jsdoc * Makes a copy of the mesh. * @function GraphicsMesh.cloneMesh * @returns {GraphicsMesh} A copy of the mesh. @@ -226,7 +226,7 @@ namespace scriptable { // QScriptEngine-specific wrappers - /**jsdoc + /*@jsdoc * Updates vertex attributes by calling a function for each vertex. The function can return modified attributes to * update the vertex with. * @function GraphicsMesh.updateVertexAttributes @@ -235,7 +235,7 @@ namespace scriptable { */ glm::uint32 updateVertexAttributes(QScriptValue callback); - /**jsdoc + /*@jsdoc * Calls a function for each vertex. * @function GraphicsMesh.forEachVertex * @param {GraphicsMesh~forEachVertexCallback} callback - The function to call for each vertex. @@ -243,7 +243,7 @@ namespace scriptable { */ glm::uint32 forEachVertex(QScriptValue callback); - /**jsdoc + /*@jsdoc * Checks if an index is valid and, optionally, that vertex has a particular attribute. * @function GraphicsMesh.isValidIndex * @param {number} index - The index to check. diff --git a/libraries/graphics-scripting/src/graphics-scripting/ScriptableMeshPart.h b/libraries/graphics-scripting/src/graphics-scripting/ScriptableMeshPart.h index 878b239f3d..716081a4b8 100644 --- a/libraries/graphics-scripting/src/graphics-scripting/ScriptableMeshPart.h +++ b/libraries/graphics-scripting/src/graphics-scripting/ScriptableMeshPart.h @@ -10,7 +10,7 @@ #include "ScriptableMesh.h" namespace scriptable { - /**jsdoc + /*@jsdoc * A handle to in-memory mesh part data in a {@link GraphicsModel}. * *

Create using the {@link Graphics} API, {@link GraphicsModel.cloneModel}, {@link GraphicsMesh.cloneMesh}, or @@ -83,14 +83,14 @@ namespace scriptable { public slots: - /**jsdoc + /*@jsdoc * Gets the vertex indices. * @function GraphicsMeshPart.getIndices * @returns {number[]} The vertex indices. */ QVector getIndices() const; - /**jsdoc + /*@jsdoc * Sets the vertex indices. * @function GraphicsMeshPart.setIndices * @param {number[]} indices - The vertex indices. @@ -99,7 +99,7 @@ namespace scriptable { */ bool setIndices(const QVector& indices); - /**jsdoc + /*@jsdoc * Gets the indices of nearby vertices in the mesh part. * @function GraphicsMeshPart.findNearbyPartVertexIndices * @param {Vec3} origin - The search position, in model coordinates. @@ -109,7 +109,7 @@ namespace scriptable { */ QVector findNearbyPartVertexIndices(const glm::vec3& origin, float epsilon = 1e-6) const; - /**jsdoc + /*@jsdoc * Gets the value of an attribute for all vertices in the whole mesh (i.e., parent and mesh parts). * @function GraphicsMeshPArt.queryVertexAttributes * @param {Graphics.BufferTypeName} name - The name of the attribute to get the vertex values of. @@ -124,7 +124,7 @@ namespace scriptable { // @borrows jsdoc from GraphicsMesh. bool setVertexAttributes(glm::uint32 vertexIndex, const QVariantMap& attributeValues); - /**jsdoc + /*@jsdoc * Gets the value of a vertex's attribute. * @function GraphicsMeshPart.getVertexProperty * @param {number} index - The vertex index. @@ -135,7 +135,7 @@ namespace scriptable { */ QVariant getVertexProperty(glm::uint32 vertexIndex, const QString& attributeName) const; - /**jsdoc + /*@jsdoc * Sets the value of a vertex's attribute. * @function GraphicsMeshPart.setVertexProperty * @param {number} index - The vertex index. @@ -147,7 +147,7 @@ namespace scriptable { */ bool setVertexProperty(glm::uint32 vertexIndex, const QString& attributeName, const QVariant& attributeValues); - /**jsdoc + /*@jsdoc * Gets the vertex indices that make up a face. * @function GraphicsMeshPart.getFace * @param {number} index - The index of the face. @@ -155,7 +155,7 @@ namespace scriptable { */ QVector getFace(glm::uint32 faceIndex) const; - /**jsdoc + /*@jsdoc * Scales the mesh to so that it's maximum model coordinate dimension is a specified length. * @function GraphicsMeshPart.scaleToFit * @param {number} scale - The target dimension. @@ -163,7 +163,7 @@ namespace scriptable { */ QVariantMap scaleToFit(float unitScale); - /**jsdoc + /*@jsdoc * Translates the mesh part. * @function GraphicsMeshPart.translate * @param {Vec3} translation - The translation to apply, in model coordinates. @@ -171,7 +171,7 @@ namespace scriptable { */ QVariantMap translate(const glm::vec3& translation); - /**jsdoc + /*@jsdoc * Scales the mesh part. * @function GraphicsMeshPart.scale * @param {Vec3} scale - The scale to apply in each model coordinate direction. @@ -180,7 +180,7 @@ namespace scriptable { */ QVariantMap scale(const glm::vec3& scale, const glm::vec3& origin = glm::vec3(NAN)); - /**jsdoc + /*@jsdoc * Rotates the mesh part, using Euler angles. * @function GraphicsMeshPart.rotateDegrees * @param {Vec3} eulerAngles - The rotation to perform, in mesh coordinates, as Euler angles in degrees. @@ -190,7 +190,7 @@ namespace scriptable { */ QVariantMap rotateDegrees(const glm::vec3& eulerAngles, const glm::vec3& origin = glm::vec3(NAN)); - /**jsdoc + /*@jsdoc * Rotates the mesh part, using a quaternion. * @function GraphicsMeshPart.rotate * @param {Quat} rotation - The rotation to perform, in model coordinates. @@ -200,7 +200,7 @@ namespace scriptable { */ QVariantMap rotate(const glm::quat& rotation, const glm::vec3& origin = glm::vec3(NAN)); - /**jsdoc + /*@jsdoc * Scales, rotates, and translates the mesh. * @function GraphicsMeshPart.transform * @param {Mat4} transform - The scale, rotate, and translate transform to apply. @@ -211,7 +211,7 @@ namespace scriptable { // @borrows jsdoc from GraphicsMesh. glm::uint32 addAttribute(const QString& attributeName, const QVariant& defaultValue = QVariant()); - /**jsdoc + /*@jsdoc * Sets the value of an attribute for all vertices in the whole mesh (i.e., parent and mesh parts). * @function GraphicsMeshPart.fillAttribute * @param {Graphics.BufferTypeName} name - The name of the attribute. The attribute is added to the vertices if not @@ -222,7 +222,7 @@ namespace scriptable { */ glm::uint32 fillAttribute(const QString& attributeName, const QVariant& value); - /**jsdoc + /*@jsdoc * Removes an attribute from all vertices in the whole mesh (i.e., parent and mesh parts). *

Note: The "position" attribute cannot be removed.

* @function GraphicsMeshPArt.removeAttribute @@ -231,7 +231,7 @@ namespace scriptable { */ bool removeAttribute(const QString& attributeName); - /**jsdoc + /*@jsdoc * Deduplicates vertices. * @function GraphicsMeshPart.dedupeVertices * @param {number} [epsilon=1e-6] - The deduplicadtion distance. If a pair of vertices is within this distance of each @@ -240,14 +240,14 @@ namespace scriptable { */ bool dedupeVertices(float epsilon = 1e-6); - /**jsdoc + /*@jsdoc * Gets the parent mesh. * @function GraphicsMeshPart.getParentMesh * @returns {GraphicsMesh} The parent mesh. */ scriptable::ScriptableMeshPointer getParentMesh() const { return parentMesh; } - /**jsdoc + /*@jsdoc * Replaces a mesh part with a copy of another mesh part. * @function GraphicsMeshPart.replaceMeshPartData * @param {GrphicsMeshPart} source - The mesh part to copy. @@ -258,14 +258,14 @@ namespace scriptable { */ bool replaceMeshPartData(scriptable::ScriptableMeshPartPointer source, const QVector& attributeNames = QVector()); - /**jsdoc + /*@jsdoc * Makes a copy of the mesh part. * @function GraphicsMeshPart.cloneMeshPart * @returns {GraphicsMeshPart} A copy of the mesh part. */ scriptable::ScriptableMeshPartPointer cloneMeshPart(); - /**jsdoc + /*@jsdoc * Exports the mesh part to OBJ format. * @function GraphicsMeshPart.toOBJ * @returns {string} The OBJ format representation of the mesh part. @@ -275,7 +275,7 @@ namespace scriptable { // QScriptEngine-specific wrappers - /**jsdoc + /*@jsdoc * Updates vertex attributes by calling a function for each vertex in the whole mesh (i.e., the parent and * mesh parts). The function can return modified attributes to update the vertex with. * @function GraphicsMeshPart.updateVertexAttributes @@ -284,7 +284,7 @@ namespace scriptable { */ glm::uint32 updateVertexAttributes(QScriptValue callback); - /**jsdoc + /*@jsdoc * Calls a function for each vertex in the whole mesh (i.e., parent and mesh parts). * @function GraphicsMeshPArt.forEachVertex * @param {GraphicsMesh~forEachVertexCallback} callback - The function to call for each vertex. @@ -292,7 +292,7 @@ namespace scriptable { */ glm::uint32 forEachVertex(QScriptValue callback); - /**jsdoc + /*@jsdoc * Checks if an index is valid and, optionally, that vertex has a particular attribute. * @function GraphicsMeshPart.isValidIndex * @param {number} index - The index to check. diff --git a/libraries/graphics-scripting/src/graphics-scripting/ScriptableModel.h b/libraries/graphics-scripting/src/graphics-scripting/ScriptableModel.h index a6f135c321..637b537800 100644 --- a/libraries/graphics-scripting/src/graphics-scripting/ScriptableModel.h +++ b/libraries/graphics-scripting/src/graphics-scripting/ScriptableModel.h @@ -16,7 +16,7 @@ namespace scriptable { using ScriptableMeshes = QVector; - /**jsdoc + /*@jsdoc * A handle to in-memory model data such as may be used in displaying avatars, 3D entities, or 3D overlays in the rendered * scene. Changes made to the model are visible only to yourself; they are not persisted. *

Note: The model may be used for more than one instance of an item displayed in the scene. Modifying the model updates @@ -72,7 +72,7 @@ namespace scriptable { public slots: - /**jsdoc + /*@jsdoc * Makes a copy of the model. * @function GraphicsModel.cloneModel * @param {object} [options] - Not used. @@ -80,7 +80,7 @@ namespace scriptable { */ scriptable::ScriptableModelPointer cloneModel(const QVariantMap& options = QVariantMap()); - /**jsdoc + /*@jsdoc * Gets a string description of the model. * @function GraphicsModel.toString * @returns {string} A string description of the model. diff --git a/libraries/graphics/src/graphics/BufferViewHelpers.cpp b/libraries/graphics/src/graphics/BufferViewHelpers.cpp index 88caa3cea4..75110838eb 100644 --- a/libraries/graphics/src/graphics/BufferViewHelpers.cpp +++ b/libraries/graphics/src/graphics/BufferViewHelpers.cpp @@ -34,7 +34,7 @@ namespace buffer_helpers { const std::array XYZW = { { "x", "y", "z", "w" } }; const std::array ZERO123 = { { "0", "1", "2", "3" } }; -/**jsdoc +/*@jsdoc *

The type name of a graphics buffer.

*
* @@ -56,7 +56,7 @@ const std::array ZERO123 = { { "0", "1", "2", "3" } }; *
* @typedef {string} Graphics.BufferTypeName */ -/**jsdoc +/*@jsdoc *

The type of a graphics buffer value as accessed by JavaScript.

* * diff --git a/libraries/graphics/src/graphics/GpuHelpers.cpp b/libraries/graphics/src/graphics/GpuHelpers.cpp index dd911e33c2..f119cac4c3 100644 --- a/libraries/graphics/src/graphics/GpuHelpers.cpp +++ b/libraries/graphics/src/graphics/GpuHelpers.cpp @@ -8,7 +8,7 @@ #include "GpuHelpers.h" -/**jsdoc +/*@jsdoc *

The interpretation of mesh elements.

*
* diff --git a/libraries/image/src/image/TextureProcessing.cpp b/libraries/image/src/image/TextureProcessing.cpp index 53991ae431..1b45fc1bae 100644 --- a/libraries/image/src/image/TextureProcessing.cpp +++ b/libraries/image/src/image/TextureProcessing.cpp @@ -338,9 +338,9 @@ void mapToRedChannel(Image& image, ColorChannel sourceChannel) { } } -gpu::TexturePointer processImage(std::shared_ptr content, const std::string& filename, ColorChannel sourceChannel, - int maxNumPixels, TextureUsage::Type textureType, - bool compress, BackendTarget target, const std::atomic& abortProcessing) { +std::pair processImage(std::shared_ptr content, const std::string& filename, ColorChannel sourceChannel, + int maxNumPixels, TextureUsage::Type textureType, + bool compress, BackendTarget target, const std::atomic& abortProcessing) { Image image = processRawImageData(*content.get(), filename); // Texture content can take up a lot of memory. Here we release our ownership of that content @@ -354,7 +354,7 @@ gpu::TexturePointer processImage(std::shared_ptr content, const std:: if (imageWidth == 0 || imageHeight == 0 || image.getFormat() == Image::Format_Invalid) { QString reason(image.getFormat() == Image::Format_Invalid ? "(Invalid Format)" : "(Size is invalid)"); qCWarning(imagelogging) << "Failed to load:" << qPrintable(reason); - return nullptr; + return { nullptr, { imageWidth, imageHeight } }; } // Validate the image is less than _maxNumPixels, and downscale if necessary @@ -378,7 +378,7 @@ gpu::TexturePointer processImage(std::shared_ptr content, const std:: auto loader = TextureUsage::getTextureLoaderForType(textureType); auto texture = loader(std::move(image), filename, compress, target, abortProcessing); - return texture; + return { texture, { imageWidth, imageHeight } }; } Image processSourceImage(Image&& srcImage, bool cubemap, BackendTarget target) { diff --git a/libraries/image/src/image/TextureProcessing.h b/libraries/image/src/image/TextureProcessing.h index 326ec700a9..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,17 +24,17 @@ 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); namespace TextureUsage { -/**jsdoc +/*@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, @@ -121,9 +122,9 @@ gpu::TexturePointer processCubeTextureColorFromImage(Image&& srcImage, const std const QStringList getSupportedFormats(); -gpu::TexturePointer processImage(std::shared_ptr content, const std::string& url, ColorChannel sourceChannel, - int maxNumPixels, TextureUsage::Type textureType, - bool compress, gpu::BackendTarget target, const std::atomic& abortProcessing = false); +std::pair processImage(std::shared_ptr content, const std::string& url, ColorChannel sourceChannel, + int maxNumPixels, TextureUsage::Type textureType, + bool compress, gpu::BackendTarget target, const std::atomic& abortProcessing = false); void convertToTextureWithMips(gpu::Texture* texture, Image&& image, gpu::BackendTarget target, const std::atomic& abortProcessing = false, int face = -1); void convertToTexture(gpu::Texture* texture, Image&& image, gpu::BackendTarget target, const std::atomic& abortProcessing = false, int face = -1, int mipLevel = 0); diff --git a/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.cpp b/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.cpp index c7c5543d44..88994ddd92 100755 --- a/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.cpp +++ b/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.cpp @@ -310,7 +310,7 @@ controller::Input KeyboardMouseDevice::InputDevice::makeInput(KeyboardMouseDevic return controller::Input(_deviceID, button, controller::ChannelType::BUTTON); } -/**jsdoc +/*@jsdoc *

The Controller.Hardware.Keyboard object has properties representing keyboard, mouse, and display touch * events. The property values are integer IDs, uniquely identifying each output. Read-only.

*

These events can be mapped to actions or functions or Controller.Standard items in a {@link RouteObject} diff --git a/libraries/input-plugins/src/input-plugins/TouchscreenVirtualPadDevice.cpp b/libraries/input-plugins/src/input-plugins/TouchscreenVirtualPadDevice.cpp index 6bb743bad0..6ba2d0eeea 100644 --- a/libraries/input-plugins/src/input-plugins/TouchscreenVirtualPadDevice.cpp +++ b/libraries/input-plugins/src/input-plugins/TouchscreenVirtualPadDevice.cpp @@ -199,7 +199,7 @@ void TouchscreenVirtualPadDevice::InputDevice::update(float deltaTime, const con _axisStateMap.clear(); } -bool TouchscreenVirtualPadDevice::InputDevice::triggerHapticPulse(float strength, float duration, controller::Hand hand) { +bool TouchscreenVirtualPadDevice::InputDevice::triggerHapticPulse(float strength, float duration, uint16_t index) { auto& virtualPadManager = VirtualPad::Manager::instance(); virtualPadManager.requestHapticFeedback((int) duration); return true; diff --git a/libraries/input-plugins/src/input-plugins/TouchscreenVirtualPadDevice.h b/libraries/input-plugins/src/input-plugins/TouchscreenVirtualPadDevice.h index 8c276fb66b..1fa46f8a24 100644 --- a/libraries/input-plugins/src/input-plugins/TouchscreenVirtualPadDevice.h +++ b/libraries/input-plugins/src/input-plugins/TouchscreenVirtualPadDevice.h @@ -71,7 +71,7 @@ protected: virtual controller::Input::NamedVector getAvailableInputs() const override; virtual QString getDefaultMappingConfig() const override; - virtual bool triggerHapticPulse(float strength, float duration, controller::Hand hand) override; + virtual bool triggerHapticPulse(float strength, float duration, uint16_t index) override; virtual void update(float deltaTime, const controller::InputCalibrationData& inputCalibrationData) override; virtual void focusOutEvent() override; diff --git a/libraries/material-networking/src/material-networking/KTXCache.cpp b/libraries/material-networking/src/material-networking/KTXCache.cpp index edb09addb8..5a5a94dcc9 100644 --- a/libraries/material-networking/src/material-networking/KTXCache.cpp +++ b/libraries/material-networking/src/material-networking/KTXCache.cpp @@ -19,7 +19,7 @@ using FilePointer = cache::FilePointer; // Whenever a change is made to the serialized format for the KTX cache that isn't backward compatible, // this value should be incremented. This will force the KTX cache to be wiped -const int KTXCache::CURRENT_VERSION = 0x01; +const int KTXCache::CURRENT_VERSION = 0x02; const int KTXCache::INVALID_VERSION = 0x00; const char* KTXCache::SETTING_VERSION_NAME = "hifi.ktx.cache_version"; diff --git a/libraries/material-networking/src/material-networking/TextureCache.cpp b/libraries/material-networking/src/material-networking/TextureCache.cpp index 459eaff2a4..8c44379dd5 100644 --- a/libraries/material-networking/src/material-networking/TextureCache.cpp +++ b/libraries/material-networking/src/material-networking/TextureCache.cpp @@ -65,7 +65,7 @@ const std::string TextureCache::KTX_DIRNAME{ "ktx_cache" }; #endif const std::string TextureCache::KTX_EXT { "ktx" }; -/**jsdoc +/*@jsdoc *

The views that may be visible on the PC display.

*
ValueNameDescription
* @@ -272,23 +272,24 @@ NetworkTexturePointer TextureCache::getTexture(const QUrl& url, image::TextureUs return ResourceCache::getResource(modifiedUrl, QUrl(), &extra, std::hash()(extra)).staticCast(); } -gpu::TexturePointer TextureCache::getTextureByHash(const std::string& hash) { - std::weak_ptr weakPointer; +std::pair TextureCache::getTextureByHash(const std::string& hash) { + std::pair weakPointer; { std::unique_lock lock(_texturesByHashesMutex); weakPointer = _texturesByHashes[hash]; } - return weakPointer.lock(); + return { weakPointer.first.lock(), weakPointer.second }; } -gpu::TexturePointer TextureCache::cacheTextureByHash(const std::string& hash, const gpu::TexturePointer& texture) { - gpu::TexturePointer result; +std::pair TextureCache::cacheTextureByHash(const std::string& hash, const std::pair& textureAndSize) { + std::pair result; { std::unique_lock lock(_texturesByHashesMutex); - result = _texturesByHashes[hash].lock(); - if (!result) { - _texturesByHashes[hash] = texture; - result = texture; + auto& value = _texturesByHashes[hash]; + result = { value.first.lock(), value.second }; + if (!result.first) { + _texturesByHashes[hash] = textureAndSize; + result = textureAndSize; } } return result; @@ -625,7 +626,7 @@ void NetworkTexture::makeLocalRequest() { ktxDescriptor = std::make_shared(ktxFile->toDescriptor()); } - gpu::TexturePointer texture; + std::pair textureAndSize; if (ktxDescriptor) { std::string hash; // Create bare ktx in memory @@ -643,18 +644,18 @@ void NetworkTexture::makeLocalRequest() { } auto textureCache = DependencyManager::get(); - texture = textureCache->getTextureByHash(hash); - if (!texture) { - texture = gpu::Texture::build(*ktxDescriptor); - if (texture) { - texture->setKtxBacking(path.toStdString()); - texture->setSource(path.toStdString()); - texture = textureCache->cacheTextureByHash(hash, texture); + textureAndSize = textureCache->getTextureByHash(hash); + if (!textureAndSize.first) { + textureAndSize = gpu::Texture::build(*ktxDescriptor); + if (textureAndSize.first) { + textureAndSize.first->setKtxBacking(path.toStdString()); + textureAndSize.first->setSource(path.toStdString()); + textureAndSize = textureCache->cacheTextureByHash(hash, textureAndSize); } } } - if (!texture) { + if (!textureAndSize.first) { qCDebug(networking).noquote() << "Failed load local KTX from" << path; QMetaObject::invokeMethod(this, "setImage", Q_ARG(gpu::TexturePointer, nullptr), @@ -664,11 +665,11 @@ void NetworkTexture::makeLocalRequest() { } _ktxResourceState = PENDING_MIP_REQUEST; - _lowestKnownPopulatedMip = texture->minAvailableMipLevel(); + _lowestKnownPopulatedMip = textureAndSize.first->minAvailableMipLevel(); QMetaObject::invokeMethod(this, "setImage", - Q_ARG(gpu::TexturePointer, texture), - Q_ARG(int, texture->getWidth()), - Q_ARG(int, texture->getHeight())); + Q_ARG(gpu::TexturePointer, textureAndSize.first), + Q_ARG(int, textureAndSize.second.x), + Q_ARG(int, textureAndSize.second.y)); } @@ -977,22 +978,22 @@ void NetworkTexture::handleFinishedInitialLoad() { auto textureCache = DependencyManager::get(); - gpu::TexturePointer texture = textureCache->getTextureByHash(hash); + std::pair textureAndSize = textureCache->getTextureByHash(hash); - if (!texture) { + if (!textureAndSize.first) { auto ktxFile = textureCache->_ktxCache->getFile(hash); if (ktxFile) { - texture = gpu::Texture::unserialize(ktxFile); - if (texture) { - texture = textureCache->cacheTextureByHash(hash, texture); - if (texture->source().empty()) { - texture->setSource(url.toString().toStdString()); + textureAndSize = gpu::Texture::unserialize(ktxFile); + if (textureAndSize.first) { + textureAndSize = textureCache->cacheTextureByHash(hash, textureAndSize); + if (textureAndSize.first->source().empty()) { + textureAndSize.first->setSource(url.toString().toStdString()); } } } } - if (!texture) { + if (!textureAndSize.first) { auto memKtx = ktx::KTX::createBare(*header, keyValues); if (!memKtx) { qWarning() << " Ktx could not be created, bailing"; @@ -1019,9 +1020,9 @@ void NetworkTexture::handleFinishedInitialLoad() { auto newKtxDescriptor = memKtx->toDescriptor(); - texture = gpu::Texture::build(newKtxDescriptor); - texture->setKtxBacking(file); - texture->setSource(filename); + textureAndSize = gpu::Texture::build(newKtxDescriptor); + textureAndSize.first->setKtxBacking(file); + textureAndSize.first->setSource(filename); auto& images = originalKtxDescriptor->images; size_t imageSizeRemaining = ktxHighMipData.size(); @@ -1034,7 +1035,7 @@ void NetworkTexture::handleFinishedInitialLoad() { break; } ktxData -= image._imageSize; - texture->assignStoredMip(static_cast(level), image._imageSize, ktxData); + textureAndSize.first->assignStoredMip(static_cast(level), image._imageSize, ktxData); ktxData -= ktx::IMAGE_SIZE_WIDTH; imageSizeRemaining -= (image._imageSize + ktx::IMAGE_SIZE_WIDTH); } @@ -1042,13 +1043,13 @@ void NetworkTexture::handleFinishedInitialLoad() { // We replace the texture with the one stored in the cache. This deals with the possible race condition of two different // images with the same hash being loaded concurrently. Only one of them will make it into the cache by hash first and will // be the winner - texture = textureCache->cacheTextureByHash(filename, texture); + textureAndSize = textureCache->cacheTextureByHash(filename, textureAndSize); } QMetaObject::invokeMethod(resource.data(), "setImage", - Q_ARG(gpu::TexturePointer, texture), - Q_ARG(int, texture->getWidth()), - Q_ARG(int, texture->getHeight())); + Q_ARG(gpu::TexturePointer, textureAndSize.first), + Q_ARG(int, textureAndSize.second.x), + Q_ARG(int, textureAndSize.second.y)); QMetaObject::invokeMethod(resource.data(), "startRequestForNextMipLevel"); }); @@ -1238,15 +1239,15 @@ void ImageReader::read() { auto textureCache = DependencyManager::get(); if (textureCache) { // If we already have a live texture with the same hash, use it - auto texture = textureCache->getTextureByHash(hash); + auto textureAndSize = textureCache->getTextureByHash(hash); // If there is no live texture, check if there's an existing KTX file - if (!texture) { + if (!textureAndSize.first) { auto ktxFile = textureCache->_ktxCache->getFile(hash); if (ktxFile) { - texture = gpu::Texture::unserialize(ktxFile, _url.toString().toStdString()); - if (texture) { - texture = textureCache->cacheTextureByHash(hash, texture); + textureAndSize = gpu::Texture::unserialize(ktxFile, _url.toString().toStdString()); + if (textureAndSize.first) { + textureAndSize = textureCache->cacheTextureByHash(hash, textureAndSize); } else { qCWarning(materialnetworking) << "Invalid cached KTX " << _url << " under hash " << hash.c_str() << ", recreating..."; } @@ -1255,17 +1256,17 @@ void ImageReader::read() { // If we found the texture either because it's in use or via KTX deserialization, // set the image and return immediately. - if (texture) { + if (textureAndSize.first) { QMetaObject::invokeMethod(resource.data(), "setImage", - Q_ARG(gpu::TexturePointer, texture), - Q_ARG(int, texture->getWidth()), - Q_ARG(int, texture->getHeight())); + Q_ARG(gpu::TexturePointer, textureAndSize.first), + Q_ARG(int, textureAndSize.second.x), + Q_ARG(int, textureAndSize.second.y)); return; } } // Proccess new texture - gpu::TexturePointer texture; + std::pair textureAndSize; { PROFILE_RANGE_EX(resource_parse_image_raw, __FUNCTION__, 0xffff0000, 0); @@ -1278,23 +1279,23 @@ void ImageReader::read() { constexpr bool shouldCompress = false; #endif auto target = getBackendTarget(); - texture = image::processImage(std::move(buffer), _url.toString().toStdString(), _sourceChannel, _maxNumPixels, networkTexture->getTextureType(), shouldCompress, target); + textureAndSize = image::processImage(std::move(buffer), _url.toString().toStdString(), _sourceChannel, _maxNumPixels, networkTexture->getTextureType(), shouldCompress, target); - if (!texture) { + if (!textureAndSize.first) { QMetaObject::invokeMethod(resource.data(), "setImage", - Q_ARG(gpu::TexturePointer, texture), + Q_ARG(gpu::TexturePointer, textureAndSize.first), Q_ARG(int, 0), Q_ARG(int, 0)); return; } - texture->setSourceHash(hash); - texture->setFallbackTexture(networkTexture->getFallbackTexture()); + textureAndSize.first->setSourceHash(hash); + textureAndSize.first->setFallbackTexture(networkTexture->getFallbackTexture()); } // Save the image into a KTXFile - if (texture && textureCache) { - auto memKtx = gpu::Texture::serialize(*texture); + if (textureAndSize.first && textureCache) { + auto memKtx = gpu::Texture::serialize(*textureAndSize.first, textureAndSize.second); // Move the texture into a memory mapped file if (memKtx) { @@ -1303,20 +1304,20 @@ void ImageReader::read() { auto& ktxCache = textureCache->_ktxCache; auto file = ktxCache->writeFile(data, KTXCache::Metadata(hash, length)); if (file) { - texture->setKtxBacking(file); + textureAndSize.first->setKtxBacking(file); } } // We replace the texture with the one stored in the cache. This deals with the possible race condition of two different // images with the same hash being loaded concurrently. Only one of them will make it into the cache by hash first and will // be the winner - texture = textureCache->cacheTextureByHash(hash, texture); + textureAndSize = textureCache->cacheTextureByHash(hash, textureAndSize); } QMetaObject::invokeMethod(resource.data(), "setImage", - Q_ARG(gpu::TexturePointer, texture), - Q_ARG(int, texture->getWidth()), - Q_ARG(int, texture->getHeight())); + Q_ARG(gpu::TexturePointer, textureAndSize.first), + Q_ARG(int, textureAndSize.second.x), + Q_ARG(int, textureAndSize.second.y)); } NetworkTexturePointer TextureCache::getResourceTexture(const QUrl& resourceTextureUrl) { diff --git a/libraries/material-networking/src/material-networking/TextureCache.h b/libraries/material-networking/src/material-networking/TextureCache.h index 40b3d1e124..069c5d15f5 100644 --- a/libraries/material-networking/src/material-networking/TextureCache.h +++ b/libraries/material-networking/src/material-networking/TextureCache.h @@ -188,8 +188,8 @@ public: const QByteArray& content = QByteArray(), int maxNumPixels = ABSOLUTE_MAX_TEXTURE_NUM_PIXELS, image::ColorChannel sourceChannel = image::ColorChannel::NONE); - gpu::TexturePointer getTextureByHash(const std::string& hash); - gpu::TexturePointer cacheTextureByHash(const std::string& hash, const gpu::TexturePointer& texture); + std::pair getTextureByHash(const std::string& hash); + std::pair cacheTextureByHash(const std::string& hash, const std::pair& textureAndSize); NetworkTexturePointer getResourceTexture(const QUrl& resourceTextureUrl); const gpu::FramebufferPointer& getHmdPreviewFramebuffer(int width, int height); @@ -233,7 +233,7 @@ private: std::shared_ptr _ktxCache { std::make_shared(KTX_DIRNAME, KTX_EXT) }; // Map from image hashes to texture weak pointers - std::unordered_map> _texturesByHashes; + std::unordered_map, glm::ivec2>> _texturesByHashes; std::mutex _texturesByHashesMutex; gpu::TexturePointer _permutationNormalTexture; diff --git a/libraries/material-networking/src/material-networking/TextureCacheScriptingInterface.h b/libraries/material-networking/src/material-networking/TextureCacheScriptingInterface.h index 5ff15c03d9..992a4a5423 100644 --- a/libraries/material-networking/src/material-networking/TextureCacheScriptingInterface.h +++ b/libraries/material-networking/src/material-networking/TextureCacheScriptingInterface.h @@ -24,7 +24,7 @@ class TextureCacheScriptingInterface : public ScriptableResourceCache, public De // Properties are copied over from ResourceCache (see ResourceCache.h for reason). - /**jsdoc + /*@jsdoc * The TextureCache API manages texture cache resources. * * @namespace TextureCache @@ -51,7 +51,7 @@ class TextureCacheScriptingInterface : public ScriptableResourceCache, public De public: TextureCacheScriptingInterface(); - /**jsdoc + /*@jsdoc * Prefetches a texture resource of specific type. * @function TextureCache.prefetch * @variation 0 @@ -64,7 +64,7 @@ public: Q_INVOKABLE ScriptableResource* prefetch(const QUrl& url, int type, int maxNumPixels = ABSOLUTE_MAX_TEXTURE_NUM_PIXELS); signals: - /**jsdoc + /*@jsdoc * @function TextureCache.spectatorCameraFramebufferReset * @returns {Signal} * @deprecated This signal is deprecated and will be removed. diff --git a/libraries/midi/src/Midi.cpp b/libraries/midi/src/Midi.cpp index 25689e8bd3..02d47198e9 100644 --- a/libraries/midi/src/Midi.cpp +++ b/libraries/midi/src/Midi.cpp @@ -266,7 +266,7 @@ void Midi::MidiCleanup() { } #endif -/**jsdoc +/*@jsdoc * A MIDI message. *

Warning: The status property is NOT a MIDI status value.

* @typedef {object} Midi.MidiMessage @@ -280,7 +280,7 @@ void Midi::MidiCleanup() { * @property {number} bend - Pitch bend: -81928191. * @property {number} program - Program change: 0127. */ -/**jsdoc +/*@jsdoc * An integer DWORD (unsigned 32 bit) message with bits having values as follows: *
* @@ -302,7 +302,7 @@ void Midi::MidiCleanup() { *

The number in the first bit of each byte denotes whether it is a command (1) or data (0). * @typedef {number} Midi.RawMidiMessage */ -/**jsdoc +/*@jsdoc *

A MIDI status value. The following MIDI status values are supported:

*
* diff --git a/libraries/midi/src/Midi.h b/libraries/midi/src/Midi.h index e2b84ec333..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 @@ -20,10 +21,10 @@ #include #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. +/*@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. * *

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: @@ -56,7 +57,7 @@ private: signals: - /**jsdoc + /*@jsdoc * Triggered when a connected device sends an output. * @function Midi.midiNote * @param {Midi.MidiMessage} message - The MIDI message. @@ -65,7 +66,7 @@ signals: */ void midiNote(QVariantMap eventData); - /**jsdoc + /*@jsdoc * Triggered when a connected device sends an output. * @function Midi.midiMessage * @param {Midi.MidiMessage} message - The MIDI message. @@ -73,7 +74,7 @@ signals: */ void midiMessage(QVariantMap eventData); - /**jsdoc + /*@jsdoc * Triggered when the system detects there was a reset such as when a device is plugged in or unplugged. * @function Midi.midiReset * @returns {Signal} @@ -82,7 +83,7 @@ signals: public slots: - /**jsdoc + /*@jsdoc * Sends a raw MIDI packet to a particular device. * @function Midi.sendRawDword * @param {number} device - Integer device number. @@ -90,7 +91,7 @@ public slots: */ Q_INVOKABLE void sendRawDword(int device, int raw); - /**jsdoc + /*@jsdoc * Sends a MIDI message to a particular device. * @function Midi.sendMidiMessage * @param {number} device - Integer device number. @@ -102,7 +103,7 @@ public slots: */ Q_INVOKABLE void sendMidiMessage(int device, int channel, int type, int note, int velocity); - /**jsdoc + /*@jsdoc * Plays a note on all connected devices. * @function Midi.playMidiNote * @param {MidiStatus} status - Note status. @@ -111,19 +112,19 @@ public slots: */ Q_INVOKABLE void playMidiNote(int status, int note, int velocity); - /**jsdoc + /*@jsdoc * Turns off all notes on all connected MIDI devices. * @function Midi.allNotesOff */ Q_INVOKABLE void allNotesOff(); - /**jsdoc + /*@jsdoc * Cleans up and rediscovers attached MIDI devices. * @function Midi.resetDevices */ Q_INVOKABLE void resetDevices(); - /**jsdoc + /*@jsdoc * Gets a list of MIDI input or output devices. * @function Midi.listMidiDevices * @param {boolean} output - true to list output devices, false to list input devices. @@ -131,7 +132,7 @@ public slots: */ Q_INVOKABLE QStringList listMidiDevices(bool output); - /**jsdoc + /*@jsdoc * Blocks a MIDI device's input or output. * @function Midi.blockMidiDevice * @param {string} name - The name of the MIDI device to block. @@ -139,7 +140,7 @@ public slots: */ Q_INVOKABLE void blockMidiDevice(QString name, bool output); - /**jsdoc + /*@jsdoc * Unblocks a MIDI device's input or output. * @function Midi.unblockMidiDevice * @param {string} name- The name of the MIDI device to unblock. @@ -147,76 +148,76 @@ public slots: */ Q_INVOKABLE void unblockMidiDevice(QString name, bool output); - /**jsdoc + /*@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); - /**jsdoc + /*@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 - /**jsdoc + /*@jsdoc * Enables or disables note off events. * @function Midi.typeNoteOffEnable * @param {boolean} enable - true to enable, false to disable. */ Q_INVOKABLE void typeNoteOffEnable(bool enable); - /**jsdoc + /*@jsdoc * Enables or disables note on events. * @function Midi.typeNoteOnEnable * @param {boolean} enable - true to enable, false to disable. */ Q_INVOKABLE void typeNoteOnEnable(bool enable); - /**jsdoc + /*@jsdoc * Enables or disables poly key pressure events. * @function Midi.typePolyKeyPressureEnable * @param {boolean} enable - true to enable, false to disable. */ Q_INVOKABLE void typePolyKeyPressureEnable(bool enable); - /**jsdoc + /*@jsdoc * Enables or disables control change events. * @function Midi.typeControlChangeEnable * @param {boolean} enable - true to enable, false to disable. */ Q_INVOKABLE void typeControlChangeEnable(bool enable); - /**jsdoc + /*@jsdoc * Enables or disables program change events. * @function Midi.typeProgramChangeEnable * @param {boolean} enable - true to enable, false to disable. */ Q_INVOKABLE void typeProgramChangeEnable(bool enable); - /**jsdoc + /*@jsdoc * Enables or disables channel pressure events. * @function Midi.typeChanPressureEnable * @param {boolean} enable - true to enable, false to disable. */ Q_INVOKABLE void typeChanPressureEnable(bool enable); - /**jsdoc + /*@jsdoc * Enables or disables pitch bend events. * @function Midi.typePitchBendEnable * @param {boolean} enable - true to enable, false to disable. */ Q_INVOKABLE void typePitchBendEnable(bool enable); - /**jsdoc + /*@jsdoc * Enables or disables system message events. * @function Midi.typeSystemMessageEnable * @param {boolean} enable - true to enable, false to disable. diff --git a/libraries/model-networking/CMakeLists.txt b/libraries/model-networking/CMakeLists.txt index b71d125586..9a7ce47b8e 100644 --- a/libraries/model-networking/CMakeLists.txt +++ b/libraries/model-networking/CMakeLists.txt @@ -1,9 +1,9 @@ set(TARGET_NAME model-networking) setup_hifi_library() -link_hifi_libraries(shared shaders networking graphics fbx procedural model-baker) +link_hifi_libraries(shared shaders networking graphics model-serializers procedural model-baker) include_hifi_library_headers(hfm) include_hifi_library_headers(task) include_hifi_library_headers(gpu) include_hifi_library_headers(image) include_hifi_library_headers(ktx) -include_hifi_library_headers(material-networking) \ No newline at end of file +include_hifi_library_headers(material-networking) diff --git a/libraries/model-networking/src/model-networking/ModelCacheScriptingInterface.h b/libraries/model-networking/src/model-networking/ModelCacheScriptingInterface.h index d83b853b01..9ac009dfbf 100644 --- a/libraries/model-networking/src/model-networking/ModelCacheScriptingInterface.h +++ b/libraries/model-networking/src/model-networking/ModelCacheScriptingInterface.h @@ -24,7 +24,7 @@ class ModelCacheScriptingInterface : public ScriptableResourceCache, public Depe // Properties are copied over from ResourceCache (see ResourceCache.h for reason). - /**jsdoc + /*@jsdoc * The ModelCache API manages model cache resources. * * @namespace ModelCache diff --git a/libraries/fbx/CMakeLists.txt b/libraries/model-serializers/CMakeLists.txt similarity index 79% rename from libraries/fbx/CMakeLists.txt rename to libraries/model-serializers/CMakeLists.txt index 2006d23c60..76775896dc 100644 --- a/libraries/fbx/CMakeLists.txt +++ b/libraries/model-serializers/CMakeLists.txt @@ -1,4 +1,4 @@ -set(TARGET_NAME fbx) +set(TARGET_NAME model-serializers) setup_hifi_library() link_hifi_libraries(shared graphics networking image hfm) diff --git a/libraries/fbx/src/FBX.h b/libraries/model-serializers/src/FBX.h similarity index 97% rename from libraries/fbx/src/FBX.h rename to libraries/model-serializers/src/FBX.h index 362ae93e99..3c4234e14b 100644 --- a/libraries/fbx/src/FBX.h +++ b/libraries/model-serializers/src/FBX.h @@ -1,6 +1,6 @@ // // FBX.h -// libraries/fbx/src +// libraries/model-serializers/src // // Created by Ryan Huffman on 9/5/17. // Copyright 2017 High Fidelity, Inc. diff --git a/libraries/fbx/src/FBXSerializer.cpp b/libraries/model-serializers/src/FBXSerializer.cpp similarity index 99% rename from libraries/fbx/src/FBXSerializer.cpp rename to libraries/model-serializers/src/FBXSerializer.cpp index 9c700be607..a18e305a80 100644 --- a/libraries/fbx/src/FBXSerializer.cpp +++ b/libraries/model-serializers/src/FBXSerializer.cpp @@ -1,6 +1,6 @@ // // FBXSerializer.cpp -// libraries/fbx/src +// libraries/model-serializers/src // // Created by Andrzej Kapolka on 9/18/13. // Copyright 2013 High Fidelity, Inc. @@ -404,7 +404,7 @@ HFMModel* FBXSerializer::extractHFMModel(const hifi::VariantHash& mapping, const QVector blendshapes; QHash fbxModels; - QHash clusters; + QHash clusters; QHash animationCurves; QHash typeFlags; @@ -1236,7 +1236,7 @@ HFMModel* FBXSerializer::extractHFMModel(const hifi::VariantHash& mapping, const // models with clusters must be parented to the cluster top // Unless the model is a root node. bool isARootNode = !modelIDs.contains(_connectionParentMap.value(fbxModel.key())); - if (!isARootNode) { + if (!isARootNode) { foreach(const QString& deformerID, _connectionChildMap.values(fbxModel.key())) { foreach(const QString& clusterID, _connectionChildMap.values(deformerID)) { if (!clusters.contains(clusterID)) { diff --git a/libraries/fbx/src/FBXSerializer.h b/libraries/model-serializers/src/FBXSerializer.h similarity index 99% rename from libraries/fbx/src/FBXSerializer.h rename to libraries/model-serializers/src/FBXSerializer.h index 7d41f98444..e528885754 100644 --- a/libraries/fbx/src/FBXSerializer.h +++ b/libraries/model-serializers/src/FBXSerializer.h @@ -1,6 +1,6 @@ // // FBXSerializer.h -// libraries/fbx/src +// libraries/model-serializers/src // // Created by Andrzej Kapolka on 9/18/13. // Copyright 2013 High Fidelity, Inc. @@ -69,7 +69,7 @@ public: useMaterial(true), isDefault(true) {} - + TextureParam(const TextureParam& src) : cropping(src.cropping), UVSet(src.UVSet), @@ -81,7 +81,7 @@ public: useMaterial(src.useMaterial), isDefault(src.isDefault) {} - + }; class MaterialParam { diff --git a/libraries/fbx/src/FBXSerializer_Material.cpp b/libraries/model-serializers/src/FBXSerializer_Material.cpp similarity index 99% rename from libraries/fbx/src/FBXSerializer_Material.cpp rename to libraries/model-serializers/src/FBXSerializer_Material.cpp index 8b170eba1b..81f9ca45e3 100644 --- a/libraries/fbx/src/FBXSerializer_Material.cpp +++ b/libraries/model-serializers/src/FBXSerializer_Material.cpp @@ -1,6 +1,6 @@ // // FBXSerializer_Material.cpp -// interface/src/fbx +// libraries/model-serializers/src // // Created by Sam Gateau on 8/27/2015. // Copyright 2015 High Fidelity, Inc. diff --git a/libraries/fbx/src/FBXSerializer_Mesh.cpp b/libraries/model-serializers/src/FBXSerializer_Mesh.cpp similarity index 99% rename from libraries/fbx/src/FBXSerializer_Mesh.cpp rename to libraries/model-serializers/src/FBXSerializer_Mesh.cpp index f74a960dc8..8d270d8320 100644 --- a/libraries/fbx/src/FBXSerializer_Mesh.cpp +++ b/libraries/model-serializers/src/FBXSerializer_Mesh.cpp @@ -1,6 +1,6 @@ // // FBXSerializer_Mesh.cpp -// interface/src/fbx +// libraries/model-serializers/src // // Created by Sam Gateau on 8/27/2015. // Copyright 2015 High Fidelity, Inc. @@ -106,7 +106,7 @@ void appendIndex(MeshData& data, QVector& indices, int index, bool deduplic } Vertex vertex; vertex.originalIndex = vertexIndex; - + glm::vec3 position; if (vertexIndex < data.vertices.size()) { position = data.vertices.at(vertexIndex); @@ -114,7 +114,7 @@ void appendIndex(MeshData& data, QVector& indices, int index, bool deduplic glm::vec3 normal; int normalIndex = data.normalsByVertex ? vertexIndex : index; - if (data.normalIndices.isEmpty()) { + if (data.normalIndices.isEmpty()) { if (normalIndex < data.normals.size()) { normal = data.normals.at(normalIndex); } @@ -130,7 +130,7 @@ void appendIndex(MeshData& data, QVector& indices, int index, bool deduplic bool hasColors = (data.colors.size() > 0); if (hasColors) { int colorIndex = data.colorsByVertex ? vertexIndex : index; - if (data.colorIndices.isEmpty()) { + if (data.colorIndices.isEmpty()) { if (colorIndex < data.colors.size()) { color = data.colors.at(colorIndex); } @@ -152,7 +152,7 @@ void appendIndex(MeshData& data, QVector& indices, int index, bool deduplic vertex.texCoord = data.texCoords.at(texCoordIndex); } } - + bool hasMoreTexcoords = (data.attributes.size() > 1); if (hasMoreTexcoords) { if (data.attributes[1].texCoordIndices.empty()) { @@ -222,7 +222,7 @@ ExtractedMesh FBXSerializer::extractMesh(const FBXNode& object, unsigned int& me } else if (subdata.name == "MappingInformationType" && subdata.properties.at(0) == BY_VERTICE) { data.normalsByVertex = true; - + } else if (subdata.name == "ReferenceInformationType" && subdata.properties.at(0) == INDEX_TO_DIRECT) { indexToDirect = true; } @@ -242,7 +242,7 @@ ExtractedMesh FBXSerializer::extractMesh(const FBXNode& object, unsigned int& me } else if (subdata.name == "MappingInformationType" && subdata.properties.at(0) == BY_VERTICE) { data.colorsByVertex = true; - + } else if (subdata.name == "ReferenceInformationType" && subdata.properties.at(0) == INDEX_TO_DIRECT) { indexToDirect = true; } @@ -264,7 +264,7 @@ ExtractedMesh FBXSerializer::extractMesh(const FBXNode& object, unsigned int& me qCDebug(modelformat) << "LayerElementColor has an average value of 0.0f... let's forget it."; } #endif - + } else if (child.name == "LayerElementUV") { if (child.properties.at(0).toInt() == 0) { AttributeData attrib; @@ -278,7 +278,7 @@ ExtractedMesh FBXSerializer::extractMesh(const FBXNode& object, unsigned int& me attrib.texCoordIndices = getIntVector(subdata); } else if (subdata.name == "Name") { attrib.name = subdata.properties.at(0).toString(); - } + } #if defined(DEBUG_FBXSERIALIZER) else { int unknown = 0; @@ -579,6 +579,6 @@ ExtractedMesh FBXSerializer::extractMesh(const FBXNode& object, unsigned int& me } } } - + return data.extracted; } diff --git a/libraries/fbx/src/FBXSerializer_Node.cpp b/libraries/model-serializers/src/FBXSerializer_Node.cpp similarity index 99% rename from libraries/fbx/src/FBXSerializer_Node.cpp rename to libraries/model-serializers/src/FBXSerializer_Node.cpp index a2772d02d7..f662f10c1a 100644 --- a/libraries/fbx/src/FBXSerializer_Node.cpp +++ b/libraries/model-serializers/src/FBXSerializer_Node.cpp @@ -1,6 +1,6 @@ // // FBXSerializer_Node.cpp -// interface/src/fbx +// libraries/model-serializers/src // // Created by Sam Gateau on 8/27/2015. // Copyright 2015 High Fidelity, Inc. @@ -183,7 +183,7 @@ FBXNode parseBinaryFBXNode(QDataStream& in, int& position, bool has64BitPosition // FBX 2016 and beyond uses 64bit positions in the node headers, pre-2016 used 32bit values // our code generally doesn't care about the size that much, so we will use 64bit values - // from here on out, but if the file is an older format we read the stream into temp 32bit + // from here on out, but if the file is an older format we read the stream into temp 32bit // values and then assign to our actual 64bit values. if (has64BitPositions) { in >> endOffset; @@ -335,8 +335,8 @@ FBXNode parseTextFBXNode(Tokenizer& tokenizer) { if ((token = tokenizer.nextToken()) == ':') { tokenizer.ungetChar(':'); tokenizer.pushBackToken(Tokenizer::DATUM_TOKEN); - return node; - + return node; + } else { tokenizer.pushBackToken(token); node.properties.append(datum); diff --git a/libraries/fbx/src/FBXToJSON.cpp b/libraries/model-serializers/src/FBXToJSON.cpp similarity index 98% rename from libraries/fbx/src/FBXToJSON.cpp rename to libraries/model-serializers/src/FBXToJSON.cpp index 195b7f5f90..f7431e1f61 100644 --- a/libraries/fbx/src/FBXToJSON.cpp +++ b/libraries/model-serializers/src/FBXToJSON.cpp @@ -1,6 +1,6 @@ // // FBXToJSON.cpp -// libraries/fbx/src +// libraries/model-serializers/src // // Created by Simon Walton on 5/4/2018. // Copyright 2018 High Fidelity, Inc. @@ -61,7 +61,7 @@ FBXToJSON& FBXToJSON::operator<<(const FBXNode& fbxNode) { case QMetaType::QByteArray: *this << '"' << stringEscape(prop.toByteArray().toStdString()) << '"'; break; - + default: if (prop.canConvert>()) { *this << prop.value>(); @@ -95,7 +95,7 @@ FBXToJSON& FBXToJSON::operator<<(const FBXNode& fbxNode) { string FBXToJSON::stringEscape(const string& in) { string out; out.reserve(in.length()); - + for (unsigned char inChar: in) { if (inChar == '"') { out.append(R"(\")"); diff --git a/libraries/fbx/src/FBXToJSON.h b/libraries/model-serializers/src/FBXToJSON.h similarity index 95% rename from libraries/fbx/src/FBXToJSON.h rename to libraries/model-serializers/src/FBXToJSON.h index e6b8efe51d..f36235abca 100644 --- a/libraries/fbx/src/FBXToJSON.h +++ b/libraries/model-serializers/src/FBXToJSON.h @@ -1,6 +1,6 @@ // // FBXToJSON.h -// libraries/fbx/src +// libraries/model-serializers/src // // Created by Simon Walton on 5/4/2018. // Copyright 2018 High Fidelity, Inc. diff --git a/libraries/fbx/src/FBXWriter.cpp b/libraries/model-serializers/src/FBXWriter.cpp similarity index 99% rename from libraries/fbx/src/FBXWriter.cpp rename to libraries/model-serializers/src/FBXWriter.cpp index 4504898e32..efc94461aa 100644 --- a/libraries/fbx/src/FBXWriter.cpp +++ b/libraries/model-serializers/src/FBXWriter.cpp @@ -1,6 +1,6 @@ // // FBXWriter.cpp -// libraries/fbx/src +// libraries/model-serializers/src // // Created by Ryan Huffman on 9/5/17. // Copyright 2017 High Fidelity, Inc. diff --git a/libraries/fbx/src/FBXWriter.h b/libraries/model-serializers/src/FBXWriter.h similarity index 94% rename from libraries/fbx/src/FBXWriter.h rename to libraries/model-serializers/src/FBXWriter.h index f20d208cb1..f7f4e647c6 100644 --- a/libraries/fbx/src/FBXWriter.h +++ b/libraries/model-serializers/src/FBXWriter.h @@ -1,6 +1,6 @@ // // FBXWriter.h -// libraries/fbx/src +// libraries/model-serializers/src // // Created by Ryan Huffman on 9/5/17. // Copyright 2017 High Fidelity, Inc. diff --git a/libraries/fbx/src/FST.cpp b/libraries/model-serializers/src/FST.cpp similarity index 100% rename from libraries/fbx/src/FST.cpp rename to libraries/model-serializers/src/FST.cpp diff --git a/libraries/fbx/src/FST.h b/libraries/model-serializers/src/FST.h similarity index 100% rename from libraries/fbx/src/FST.h rename to libraries/model-serializers/src/FST.h diff --git a/libraries/fbx/src/FSTReader.cpp b/libraries/model-serializers/src/FSTReader.cpp similarity index 100% rename from libraries/fbx/src/FSTReader.cpp rename to libraries/model-serializers/src/FSTReader.cpp diff --git a/libraries/fbx/src/FSTReader.h b/libraries/model-serializers/src/FSTReader.h similarity index 100% rename from libraries/fbx/src/FSTReader.h rename to libraries/model-serializers/src/FSTReader.h diff --git a/libraries/fbx/src/GLTFSerializer.cpp b/libraries/model-serializers/src/GLTFSerializer.cpp similarity index 96% rename from libraries/fbx/src/GLTFSerializer.cpp rename to libraries/model-serializers/src/GLTFSerializer.cpp index d4e2833784..9b0145c112 100755 --- a/libraries/fbx/src/GLTFSerializer.cpp +++ b/libraries/model-serializers/src/GLTFSerializer.cpp @@ -1,6 +1,6 @@ // // GLTFSerializer.cpp -// libraries/fbx/src +// libraries/model-serializers/src // // Created by Luis Cuenca on 8/30/17. // Copyright 2017 High Fidelity, Inc. @@ -148,7 +148,7 @@ bool GLTFSerializer::getObjectArrayVal(const QJsonObject& object, const QString& } hifi::ByteArray GLTFSerializer::setGLBChunks(const hifi::ByteArray& data) { - int byte = 4; + int byte = 4; int jsonStart = data.indexOf("JSON", Qt::CaseSensitive); int binStart = data.indexOf("BIN", Qt::CaseSensitive); int jsonLength, binLength; @@ -271,7 +271,7 @@ bool GLTFSerializer::setAsset(const QJsonObject& object) { QJsonObject jsAsset; bool isAssetDefined = getObjectVal(object, "asset", jsAsset, _file.defined); if (isAssetDefined) { - if (!getStringVal(jsAsset, "version", _file.asset.version, + if (!getStringVal(jsAsset, "version", _file.asset.version, _file.asset.defined) || _file.asset.version != "2.0") { return false; } @@ -318,7 +318,7 @@ GLTFAccessor::GLTFAccessorSparse GLTFSerializer::createAccessorSparse(const QJso bool GLTFSerializer::addAccessor(const QJsonObject& object) { GLTFAccessor accessor; - + getIntVal(object, "bufferView", accessor.bufferView, accessor.defined); getIntVal(object, "byteOffset", accessor.byteOffset, accessor.defined); getIntVal(object, "componentType", accessor.componentType, accessor.defined); @@ -344,7 +344,7 @@ bool GLTFSerializer::addAccessor(const QJsonObject& object) { bool GLTFSerializer::addAnimation(const QJsonObject& object) { GLTFAnimation animation; - + QJsonArray channels; if (getObjectArrayVal(object, "channels", channels, animation.defined)) { foreach(const QJsonValue & v, channels) { @@ -355,7 +355,7 @@ bool GLTFSerializer::addAnimation(const QJsonObject& object) { if (getObjectVal(v.toObject(), "target", jsChannel, channel.defined)) { getIntVal(jsChannel, "node", channel.target.node, channel.target.defined); getIntVal(jsChannel, "path", channel.target.path, channel.target.defined); - } + } } } } @@ -374,7 +374,7 @@ bool GLTFSerializer::addAnimation(const QJsonObject& object) { } } } - + _file.animations.push_back(animation); return true; @@ -382,20 +382,20 @@ bool GLTFSerializer::addAnimation(const QJsonObject& object) { bool GLTFSerializer::addBufferView(const QJsonObject& object) { GLTFBufferView bufferview; - + getIntVal(object, "buffer", bufferview.buffer, bufferview.defined); getIntVal(object, "byteLength", bufferview.byteLength, bufferview.defined); getIntVal(object, "byteOffset", bufferview.byteOffset, bufferview.defined); getIntVal(object, "target", bufferview.target, bufferview.defined); - + _file.bufferviews.push_back(bufferview); - + return true; } bool GLTFSerializer::addBuffer(const QJsonObject& object) { GLTFBuffer buffer; - + getIntVal(object, "byteLength", buffer.byteLength, buffer.defined); if (_url.path().endsWith("glb")) { @@ -411,13 +411,13 @@ bool GLTFSerializer::addBuffer(const QJsonObject& object) { } } _file.buffers.push_back(buffer); - + return true; } bool GLTFSerializer::addCamera(const QJsonObject& object) { GLTFCamera camera; - + QJsonObject jsPerspective; QJsonObject jsOrthographic; QString type; @@ -437,15 +437,15 @@ bool GLTFSerializer::addCamera(const QJsonObject& object) { } else if (getStringVal(object, "type", type, camera.defined)) { camera.type = getCameraType(type); } - + _file.cameras.push_back(camera); - + return true; } bool GLTFSerializer::addImage(const QJsonObject& object) { GLTFImage image; - + QString mime; getStringVal(object, "uri", image.uri, image.defined); if (image.uri.contains("data:image/png;base64,")) { @@ -455,9 +455,9 @@ bool GLTFSerializer::addImage(const QJsonObject& object) { } if (getStringVal(object, "mimeType", mime, image.defined)) { image.mimeType = getImageMimeType(mime); - } + } getIntVal(object, "bufferView", image.bufferView, image.defined); - + _file.images.push_back(image); return true; @@ -489,20 +489,20 @@ bool GLTFSerializer::addMaterial(const QJsonObject& object) { getDoubleVal(object, "alphaCutoff", material.alphaCutoff, material.defined); QJsonObject jsMetallicRoughness; if (getObjectVal(object, "pbrMetallicRoughness", jsMetallicRoughness, material.defined)) { - getDoubleArrayVal(jsMetallicRoughness, "baseColorFactor", - material.pbrMetallicRoughness.baseColorFactor, + getDoubleArrayVal(jsMetallicRoughness, "baseColorFactor", + material.pbrMetallicRoughness.baseColorFactor, material.pbrMetallicRoughness.defined); - getIndexFromObject(jsMetallicRoughness, "baseColorTexture", - material.pbrMetallicRoughness.baseColorTexture, + getIndexFromObject(jsMetallicRoughness, "baseColorTexture", + material.pbrMetallicRoughness.baseColorTexture, material.pbrMetallicRoughness.defined); - getDoubleVal(jsMetallicRoughness, "metallicFactor", - material.pbrMetallicRoughness.metallicFactor, + getDoubleVal(jsMetallicRoughness, "metallicFactor", + material.pbrMetallicRoughness.metallicFactor, material.pbrMetallicRoughness.defined); - getDoubleVal(jsMetallicRoughness, "roughnessFactor", - material.pbrMetallicRoughness.roughnessFactor, + getDoubleVal(jsMetallicRoughness, "roughnessFactor", + material.pbrMetallicRoughness.roughnessFactor, material.pbrMetallicRoughness.defined); - getIndexFromObject(jsMetallicRoughness, "metallicRoughnessTexture", - material.pbrMetallicRoughness.metallicRoughnessTexture, + getIndexFromObject(jsMetallicRoughness, "metallicRoughnessTexture", + material.pbrMetallicRoughness.metallicRoughnessTexture, material.pbrMetallicRoughness.defined); } _file.materials.push_back(material); @@ -524,7 +524,7 @@ bool GLTFSerializer::addMesh(const QJsonObject& object) { getIntVal(jsPrimitive, "mode", primitive.mode, primitive.defined); getIntVal(jsPrimitive, "indices", primitive.indices, primitive.defined); getIntVal(jsPrimitive, "material", primitive.material, primitive.defined); - + QJsonObject jsAttributes; if (getObjectVal(jsPrimitive, "attributes", jsAttributes, primitive.defined)) { QStringList attrKeys = jsAttributes.keys(); @@ -550,7 +550,7 @@ bool GLTFSerializer::addMesh(const QJsonObject& object) { primitive.targets.push_back(target); } } - } + } mesh.primitives.push_back(primitive); } } @@ -561,8 +561,8 @@ bool GLTFSerializer::addMesh(const QJsonObject& object) { if (getObjectVal(object, "extras", jsExtras, mesh.defined)) { QJsonArray jsTargetNames; if (getObjectArrayVal(jsExtras, "targetNames", jsTargetNames, extras.defined)) { - foreach (const QJsonValue& tarName, jsTargetNames) { - extras.targetNames.push_back(tarName.toString()); + foreach (const QJsonValue& tarName, jsTargetNames) { + extras.targetNames.push_back(tarName.toString()); } } mesh.extras = extras; @@ -575,7 +575,7 @@ bool GLTFSerializer::addMesh(const QJsonObject& object) { bool GLTFSerializer::addNode(const QJsonObject& object) { GLTFNode node; - + getStringVal(object, "name", node.name, node.defined); getIntVal(object, "camera", node.camera, node.defined); getIntVal(object, "mesh", node.mesh, node.defined); @@ -630,10 +630,10 @@ bool GLTFSerializer::addSkin(const QJsonObject& object) { } bool GLTFSerializer::addTexture(const QJsonObject& object) { - GLTFTexture texture; + GLTFTexture texture; getIntVal(object, "sampler", texture.sampler, texture.defined); getIntVal(object, "source", texture.source, texture.defined); - + _file.textures.push_back(texture); return true; @@ -646,8 +646,8 @@ bool GLTFSerializer::parseGLTF(const hifi::ByteArray& data) { if (_url.path().endsWith("glb") && data.indexOf("glTF") == 0 && data.contains("JSON")) { jsonChunk = setGLBChunks(data); - } - + } + QJsonDocument d = QJsonDocument::fromJson(jsonChunk); QJsonObject jsFile = d.object(); @@ -769,7 +769,7 @@ bool GLTFSerializer::parseGLTF(const hifi::ByteArray& data) { } } } - } + } return success; } @@ -789,13 +789,13 @@ glm::mat4 GLTFSerializer::getModelTransform(const GLTFNode& node) { s = glm::scale(s, scale); tmat = s * tmat; } - + if (node.defined["rotation"] && node.rotation.size() == 4) { //quat(x,y,z,w) to quat(w,x,y,z) glm::quat rotquat = glm::quat(node.rotation[3], node.rotation[0], node.rotation[1], node.rotation[2]); tmat = glm::mat4_cast(rotquat) * tmat; } - + if (node.defined["translation"] && node.translation.size() == 3) { glm::vec3 trans = glm::vec3(node.translation[0], node.translation[1], node.translation[2]); glm::mat4 t = glm::mat4(1.0); @@ -842,7 +842,7 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::VariantHash& sortedNodes.push_back(nodecount); ++nodecount; } - + // Build transforms nodecount = 0; @@ -965,8 +965,8 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::VariantHash& std::vector& value = inverseBindValues[s]; int matrixCount = 16 * matrixIndex; jointInverseBindTransforms[jointIndex] = - glm::mat4(value[matrixCount], value[matrixCount + 1], value[matrixCount + 2], value[matrixCount + 3], - value[matrixCount + 4], value[matrixCount + 5], value[matrixCount + 6], value[matrixCount + 7], + glm::mat4(value[matrixCount], value[matrixCount + 1], value[matrixCount + 2], value[matrixCount + 3], + value[matrixCount + 4], value[matrixCount + 5], value[matrixCount + 6], value[matrixCount + 7], value[matrixCount + 8], value[matrixCount + 9], value[matrixCount + 10], value[matrixCount + 11], value[matrixCount + 12], value[matrixCount + 13], value[matrixCount + 14], value[matrixCount + 15]); } else { @@ -1008,7 +1008,7 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::VariantHash& setHFMMaterial(hfmMaterial, _file.materials[i]); } - + // Build meshes nodecount = 0; hfmModel.meshExtents.reset(); @@ -1061,7 +1061,7 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::VariantHash& qWarning(modelformat) << "Indices accessor index is out of bounds for model " << _url; continue; } - + GLTFAccessor& indicesAccessor = _file.accessors[indicesAccessorIdx]; // Buffers @@ -1404,7 +1404,7 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::VariantHash& if (colors.size() == partVerticesCount * colorStride) { for (int n = 0; n < colors.size(); n += colorStride) { - mesh.colors.push_back(glm::vec3(colors[n], colors[n + 1], colors[n + 2])); + mesh.colors.push_back(ColorUtils::tosRGBVec3(glm::vec3(colors[n], colors[n + 1], colors[n + 2]))); } } else { if (meshAttributes.contains("COLOR_0")) { @@ -1550,7 +1550,6 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::VariantHash& typedef QPair WeightedIndex; hifi::VariantHash blendshapeMappings = mapping.value("bs").toHash(); QMultiHash blendshapeIndices; - for (int i = 0;; ++i) { auto blendshapeName = QString(BLENDSHAPE_NAMES[i]); if (blendshapeName.isEmpty()) { @@ -1561,7 +1560,7 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::VariantHash& // Use blendshape from mapping. foreach(const QVariant& mapping, mappings) { auto blendshapeMapping = mapping.toList(); - blendshapeIndices.insert(blendshapeMapping.at(0).toString(), + blendshapeIndices.insert(blendshapeMapping.at(0).toString(), WeightedIndex(i, blendshapeMapping.at(1).toFloat())); } } else { @@ -1572,6 +1571,32 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::VariantHash& } } + // If an FST isn't being used and the model is likely from ReadyPlayerMe, add blendshape synonyms. + auto fileTargetNames = _file.meshes[node.mesh].extras.targetNames; + bool likelyReadyPlayerMeFile = + fileTargetNames.contains("browOuterUpLeft") + && fileTargetNames.contains("browInnerUp") + && fileTargetNames.contains("browDownLeft") + && fileTargetNames.contains("eyeBlinkLeft") + && fileTargetNames.contains("eyeWideLeft") + && fileTargetNames.contains("mouthLeft") + && fileTargetNames.contains("viseme_O") + && fileTargetNames.contains("mouthShrugLower"); + if (blendshapeMappings.count() == 0 && likelyReadyPlayerMeFile) { + QHash>::const_iterator synonym + = READYPLAYERME_BLENDSHAPES_MAP.constBegin(); + while (synonym != READYPLAYERME_BLENDSHAPES_MAP.constEnd()) { + if (fileTargetNames.contains(synonym.key())) { + auto blendshape = BLENDSHAPE_LOOKUP_MAP.find(synonym.value().first); + if (blendshape != BLENDSHAPE_LOOKUP_MAP.end()) { + blendshapeIndices.insert(synonym.key(), + WeightedIndex(blendshape.value(), synonym.value().second)); + } + } + ++synonym; + } + } + // Create blendshapes. if (!blendshapeIndices.isEmpty()) { mesh.blendshapes.resize((int)Blendshapes::BlendshapeCount); @@ -1627,7 +1652,7 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::VariantHash& glm::vec3 transformedVertex = glm::vec3(globalTransforms[nodeIndex] * glm::vec4(vertex, 1.0f)); mesh.meshExtents.addPoint(transformedVertex); hfmModel.meshExtents.addPoint(transformedVertex); - } + } } // Mesh extents must be at least a minimum size, in particular for blendshapes to work on planar meshes. @@ -1664,7 +1689,7 @@ std::unique_ptr GLTFSerializer::getFactory() const { HFMModel::Pointer GLTFSerializer::read(const hifi::ByteArray& data, const hifi::VariantHash& mapping, const hifi::URL& url) { _url = url; - + // Normalize url for local files hifi::URL normalizeUrl = DependencyManager::get()->normalizeURL(_url); if (normalizeUrl.scheme().isEmpty() || (normalizeUrl.scheme() == "file")) { @@ -1699,7 +1724,7 @@ bool GLTFSerializer::readBinary(const QString& url, hifi::ByteArray& outdata) { hifi::URL binaryUrl = _url.resolved(url); std::tie(success, outdata) = requestData(binaryUrl); } - + return success; } @@ -1732,7 +1757,7 @@ std::tuple GLTFSerializer::requestData(hifi::URL& url) { } hifi::ByteArray GLTFSerializer::requestEmbeddedData(const QString& url) { - QString binaryUrl = url.split(",")[1]; + QString binaryUrl = url.split(",")[1]; return binaryUrl.isEmpty() ? hifi::ByteArray() : QByteArray::fromBase64(binaryUrl.toUtf8()); } @@ -1764,7 +1789,7 @@ QNetworkReply* GLTFSerializer::request(hifi::URL& url, bool isTest) { HFMTexture GLTFSerializer::getHFMTexture(const GLTFTexture& texture) { HFMTexture fbxtex = HFMTexture(); fbxtex.texcoordSet = 0; - + if (texture.defined["source"]) { QString url = _file.images[texture.source].uri; @@ -1775,7 +1800,7 @@ HFMTexture GLTFSerializer::getHFMTexture(const GLTFTexture& texture) { if (_url.path().endsWith("glb") && !_glbBinary.isEmpty()) { int bufferView = _file.images[texture.source].bufferView; - + GLTFBufferView& imagesBufferview = _file.bufferviews[bufferView]; int offset = imagesBufferview.byteOffset; int length = imagesBufferview.byteLength; @@ -1785,7 +1810,7 @@ HFMTexture GLTFSerializer::getHFMTexture(const GLTFTexture& texture) { } if (url.contains("data:image/jpeg;base64,") || url.contains("data:image/png;base64,")) { - fbxtex.content = requestEmbeddedData(url); + fbxtex.content = requestEmbeddedData(url); } } return fbxtex; @@ -1815,12 +1840,12 @@ void GLTFSerializer::setHFMMaterial(HFMMaterial& hfmMat, const GLTFMaterial& mat hfmMat.emissiveTexture = getHFMTexture(_file.textures[material.emissiveTexture]); hfmMat.useEmissiveMap = true; } - + if (material.defined["normalTexture"]) { hfmMat.normalTexture = getHFMTexture(_file.textures[material.normalTexture]); hfmMat.useNormalMap = true; } - + if (material.defined["occlusionTexture"]) { hfmMat.occlusionTexture = getHFMTexture(_file.textures[material.occlusionTexture]); hfmMat.useOcclusionMap = true; @@ -1848,7 +1873,7 @@ void GLTFSerializer::setHFMMaterial(HFMMaterial& hfmMat, const GLTFMaterial& mat if (material.pbrMetallicRoughness.defined["roughnessFactor"]) { hfmMat._material->setRoughness(material.pbrMetallicRoughness.roughnessFactor); } - if (material.pbrMetallicRoughness.defined["baseColorFactor"] && + if (material.pbrMetallicRoughness.defined["baseColorFactor"] && material.pbrMetallicRoughness.baseColorFactor.size() == 4) { glm::vec3 dcolor = glm::vec3(material.pbrMetallicRoughness.baseColorFactor[0], material.pbrMetallicRoughness.baseColorFactor[1], @@ -1863,8 +1888,8 @@ void GLTFSerializer::setHFMMaterial(HFMMaterial& hfmMat, const GLTFMaterial& mat template bool GLTFSerializer::readArray(const hifi::ByteArray& bin, int byteOffset, int count, - QVector& outarray, int accessorType) { - + QVector& outarray, int accessorType, bool normalized) { + QDataStream blobstream(bin); blobstream.setByteOrder(QDataStream::LittleEndian); blobstream.setVersion(QDataStream::Qt_5_9); @@ -1899,12 +1924,22 @@ bool GLTFSerializer::readArray(const hifi::ByteArray& bin, int byteOffset, int c blobstream.setDevice(nullptr); return false; } + + float scale = 1.0f; // Normalized output values should always be floats. + if (normalized) { + scale = (float)(std::numeric_limits::max)(); + } + for (int i = 0; i < count; ++i) { for (int j = 0; j < bufferCount; ++j) { if (!blobstream.atEnd()) { T value; blobstream >> value; - outarray.push_back(value); + if (normalized) { + outarray.push_back(std::max((float)value / scale, -1.0f)); + } else { + outarray.push_back(value); + } } else { blobstream.setDevice(nullptr); return false; @@ -1917,24 +1952,24 @@ bool GLTFSerializer::readArray(const hifi::ByteArray& bin, int byteOffset, int c } template bool GLTFSerializer::addArrayOfType(const hifi::ByteArray& bin, int byteOffset, int count, - QVector& outarray, int accessorType, int componentType) { - + QVector& outarray, int accessorType, int componentType, bool normalized) { + switch (componentType) { case GLTFAccessorComponentType::BYTE: {} case GLTFAccessorComponentType::UNSIGNED_BYTE: { - return readArray(bin, byteOffset, count, outarray, accessorType); + return readArray(bin, byteOffset, count, outarray, accessorType, normalized); } case GLTFAccessorComponentType::SHORT: { - return readArray(bin, byteOffset, count, outarray, accessorType); + return readArray(bin, byteOffset, count, outarray, accessorType, normalized); } case GLTFAccessorComponentType::UNSIGNED_INT: { - return readArray(bin, byteOffset, count, outarray, accessorType); + return readArray(bin, byteOffset, count, outarray, accessorType, normalized); } case GLTFAccessorComponentType::UNSIGNED_SHORT: { - return readArray(bin, byteOffset, count, outarray, accessorType); + return readArray(bin, byteOffset, count, outarray, accessorType, normalized); } case GLTFAccessorComponentType::FLOAT: { - return readArray(bin, byteOffset, count, outarray, accessorType); + return readArray(bin, byteOffset, count, outarray, accessorType, normalized); } } return false; @@ -1951,11 +1986,11 @@ bool GLTFSerializer::addArrayFromAccessor(GLTFAccessor& accessor, QVector& ou int accBoffset = accessor.defined["byteOffset"] ? accessor.byteOffset : 0; success = addArrayOfType(buffer.blob, bufferview.byteOffset + accBoffset, accessor.count, outarray, accessor.type, - accessor.componentType); + accessor.componentType, accessor.normalized); } else { for (int i = 0; i < accessor.count; ++i) { T value; - memset(&value, 0, sizeof(T)); // Make sure the dummy array is initalised to zero. + memset(&value, 0, sizeof(T)); // Make sure the dummy array is initialized to zero. outarray.push_back(value); } } @@ -1971,7 +2006,7 @@ bool GLTFSerializer::addArrayFromAccessor(GLTFAccessor& accessor, QVector& ou success = addArrayOfType(sparseIndicesBuffer.blob, sparseIndicesBufferview.byteOffset + accSIBoffset, accessor.sparse.count, out_sparse_indices_array, GLTFAccessorType::SCALAR, - accessor.sparse.indices.componentType); + accessor.sparse.indices.componentType, false); if (success) { QVector out_sparse_values_array; @@ -1981,11 +2016,12 @@ bool GLTFSerializer::addArrayFromAccessor(GLTFAccessor& accessor, QVector& ou int accSVBoffset = accessor.sparse.values.defined["byteOffset"] ? accessor.sparse.values.byteOffset : 0; success = addArrayOfType(sparseValuesBuffer.blob, sparseValuesBufferview.byteOffset + accSVBoffset, - accessor.sparse.count, out_sparse_values_array, accessor.type, accessor.componentType); + accessor.sparse.count, out_sparse_values_array, accessor.type, accessor.componentType, + accessor.normalized); if (success) { for (int i = 0; i < accessor.sparse.count; ++i) { - if ((i * 3) + 2 < out_sparse_values_array.size()) { + if ((i * 3) + 2 < out_sparse_values_array.size()) { if ((out_sparse_indices_array[i] * 3) + 2 < outarray.length()) { for (int j = 0; j < 3; ++j) { outarray[(out_sparse_indices_array[i] * 3) + j] = out_sparse_values_array[(i * 3) + j]; @@ -2007,8 +2043,8 @@ bool GLTFSerializer::addArrayFromAccessor(GLTFAccessor& accessor, QVector& ou return success; } -void GLTFSerializer::retriangulate(const QVector& inIndices, const QVector& in_vertices, - const QVector& in_normals, QVector& outIndices, +void GLTFSerializer::retriangulate(const QVector& inIndices, const QVector& in_vertices, + const QVector& in_normals, QVector& outIndices, QVector& out_vertices, QVector& out_normals) { for (int i = 0; i < inIndices.size(); i = i + 3) { diff --git a/libraries/fbx/src/GLTFSerializer.h b/libraries/model-serializers/src/GLTFSerializer.h similarity index 98% rename from libraries/fbx/src/GLTFSerializer.h rename to libraries/model-serializers/src/GLTFSerializer.h index 79524ea7ff..3ce38ead5e 100755 --- a/libraries/fbx/src/GLTFSerializer.h +++ b/libraries/model-serializers/src/GLTFSerializer.h @@ -1,6 +1,6 @@ // // GLTFSerializer.h -// libraries/fbx/src +// libraries/model-serializers/src // // Created by Luis Cuenca on 8/30/17. // Copyright 2017 High Fidelity, Inc. @@ -343,7 +343,7 @@ struct GLTFCamera { QString name; GLTFCameraPerspective perspective; //required (or) GLTFCameraOrthographic orthographic; //required (or) - int type; + int type; QMap defined; void dump() { if (defined["name"]) { @@ -519,7 +519,7 @@ struct GLTFAccessor { QMap defined; void dump() { - + } }; int bufferView; @@ -527,7 +527,7 @@ struct GLTFAccessor { int componentType; //required int count; //required int type; //required - bool normalized{ false }; + bool normalized { false }; QVector max; QVector min; GLTFAccessorSparse sparse; @@ -778,26 +778,26 @@ private: bool buildGeometry(HFMModel& hfmModel, const hifi::VariantHash& mapping, const hifi::URL& url); bool parseGLTF(const hifi::ByteArray& data); - - bool getStringVal(const QJsonObject& object, const QString& fieldname, + + bool getStringVal(const QJsonObject& object, const QString& fieldname, QString& value, QMap& defined); - bool getBoolVal(const QJsonObject& object, const QString& fieldname, + bool getBoolVal(const QJsonObject& object, const QString& fieldname, bool& value, QMap& defined); - bool getIntVal(const QJsonObject& object, const QString& fieldname, + bool getIntVal(const QJsonObject& object, const QString& fieldname, int& value, QMap& defined); - bool getDoubleVal(const QJsonObject& object, const QString& fieldname, + bool getDoubleVal(const QJsonObject& object, const QString& fieldname, double& value, QMap& defined); - bool getObjectVal(const QJsonObject& object, const QString& fieldname, + bool getObjectVal(const QJsonObject& object, const QString& fieldname, QJsonObject& value, QMap& defined); - bool getIntArrayVal(const QJsonObject& object, const QString& fieldname, + bool getIntArrayVal(const QJsonObject& object, const QString& fieldname, QVector& values, QMap& defined); - bool getDoubleArrayVal(const QJsonObject& object, const QString& fieldname, + bool getDoubleArrayVal(const QJsonObject& object, const QString& fieldname, QVector& values, QMap& defined); - bool getObjectArrayVal(const QJsonObject& object, const QString& fieldname, + bool getObjectArrayVal(const QJsonObject& object, const QString& fieldname, QJsonArray& objects, QMap& defined); hifi::ByteArray setGLBChunks(const hifi::ByteArray& data); - + graphics::MaterialKey::OpacityMapMode getMaterialAlphaMode(const QString& type); int getAccessorType(const QString& type); int getAnimationSamplerInterpolation(const QString& interpolation); @@ -805,7 +805,7 @@ private: int getImageMimeType(const QString& mime); int getMeshPrimitiveRenderingMode(const QString& type); - bool getIndexFromObject(const QJsonObject& object, const QString& field, + bool getIndexFromObject(const QJsonObject& object, const QString& field, int& outidx, QMap& defined); bool setAsset(const QJsonObject& object); @@ -832,17 +832,17 @@ private: template bool readArray(const hifi::ByteArray& bin, int byteOffset, int count, - QVector& outarray, int accessorType); + QVector& outarray, int accessorType, bool normalized); template bool addArrayOfType(const hifi::ByteArray& bin, int byteOffset, int count, - QVector& outarray, int accessorType, int componentType); + QVector& outarray, int accessorType, int componentType, bool normalized); template bool addArrayFromAccessor(GLTFAccessor& accessor, QVector& outarray); - void retriangulate(const QVector& in_indices, const QVector& in_vertices, - const QVector& in_normals, QVector& out_indices, + void retriangulate(const QVector& in_indices, const QVector& in_vertices, + const QVector& in_normals, QVector& out_indices, QVector& out_vertices, QVector& out_normals); std::tuple requestData(hifi::URL& url); @@ -857,4 +857,4 @@ private: void glTFDebugDump(); }; -#endif // hifi_GLTFSerializer_h \ No newline at end of file +#endif // hifi_GLTFSerializer_h diff --git a/libraries/fbx/src/OBJSerializer.cpp b/libraries/model-serializers/src/OBJSerializer.cpp similarity index 99% rename from libraries/fbx/src/OBJSerializer.cpp rename to libraries/model-serializers/src/OBJSerializer.cpp index 416f343a47..7acc663828 100644 --- a/libraries/fbx/src/OBJSerializer.cpp +++ b/libraries/model-serializers/src/OBJSerializer.cpp @@ -1,6 +1,6 @@ // // OBJSerializer.cpp -// libraries/fbx/src/ +// libraries/model-serializers/src // // Created by Seth Alves on 3/7/15. // Copyright 2013 High Fidelity, Inc. @@ -15,7 +15,7 @@ #include "OBJSerializer.h" #include // .obj files are not locale-specific. The C/ASCII charset applies. -#include +#include #include #include @@ -263,16 +263,16 @@ void OBJSerializer::parseMaterialLibrary(QIODevice* device) { default: materials[matName] = currentMaterial; #ifdef WANT_DEBUG - qCDebug(modelformat) << + qCDebug(modelformat) << "OBJSerializer Last material illumination model:" << currentMaterial.illuminationModel << - " shininess:" << currentMaterial.shininess << + " shininess:" << currentMaterial.shininess << " opacity:" << currentMaterial.opacity << - " diffuse color:" << currentMaterial.diffuseColor << - " specular color:" << currentMaterial.specularColor << - " emissive color:" << currentMaterial.emissiveColor << - " diffuse texture:" << currentMaterial.diffuseTextureFilename << - " specular texture:" << currentMaterial.specularTextureFilename << - " emissive texture:" << currentMaterial.emissiveTextureFilename << + " diffuse color:" << currentMaterial.diffuseColor << + " specular color:" << currentMaterial.specularColor << + " emissive color:" << currentMaterial.emissiveColor << + " diffuse texture:" << currentMaterial.diffuseTextureFilename << + " specular texture:" << currentMaterial.specularTextureFilename << + " emissive texture:" << currentMaterial.emissiveTextureFilename << " bump texture:" << currentMaterial.bumpTextureFilename << " opacity texture:" << currentMaterial.opacityTextureFilename; #endif @@ -352,7 +352,7 @@ void OBJSerializer::parseMaterialLibrary(QIODevice* device) { } } } -} +} void OBJSerializer::parseTextureLine(const hifi::ByteArray& textureLine, hifi::ByteArray& filename, OBJMaterialTextureOptions& textureOptions) { // Texture options reference http://paulbourke.net/dataformats/mtl/ @@ -803,7 +803,7 @@ HFMModel::Pointer OBJSerializer::read(const hifi::ByteArray& data, const hifi::V n0 = checked_at(normals, face.normalIndices[0]); n1 = checked_at(normals, face.normalIndices[1]); n2 = checked_at(normals, face.normalIndices[2]); - } else { + } else { // generate normals from triangle plane if not provided n0 = n1 = n2 = glm::cross(v1 - v0, v2 - v0); } @@ -932,7 +932,7 @@ HFMModel::Pointer OBJSerializer::read(const hifi::ByteArray& data, const hifi::V bool applyNonMetallic = false; bool fresnelOn = false; - // Illumination model reference http://paulbourke.net/dataformats/mtl/ + // Illumination model reference http://paulbourke.net/dataformats/mtl/ switch (objMaterial.illuminationModel) { case 0: // Color on and Ambient off // We don't support ambient = do nothing? @@ -976,7 +976,7 @@ HFMModel::Pointer OBJSerializer::read(const hifi::ByteArray& data, const hifi::V case 10: // Casts shadows onto invisible surfaces // Do nothing? break; - } + } if (applyTransparency) { hfmMaterial.opacity = std::max(hfmMaterial.opacity, ILLUMINATION_MODEL_MIN_OPACITY); diff --git a/libraries/fbx/src/OBJSerializer.h b/libraries/model-serializers/src/OBJSerializer.h similarity index 99% rename from libraries/fbx/src/OBJSerializer.h rename to libraries/model-serializers/src/OBJSerializer.h index 6fdd95e2c3..20633e90e4 100644 --- a/libraries/fbx/src/OBJSerializer.h +++ b/libraries/model-serializers/src/OBJSerializer.h @@ -1,6 +1,6 @@ // // OBJSerializer.h -// libraries/fbx/src/ +// libraries/model-serializers/src // // Created by Seth Alves on 3/6/15. // Copyright 2015 High Fidelity, Inc. @@ -93,7 +93,7 @@ class OBJSerializer: public QObject, public HFMSerializer { // QObject so we can public: MediaType getMediaType() const override; std::unique_ptr getFactory() const override; - + typedef QVector FaceGroup; QVector vertices; QVector vertexColors; @@ -102,7 +102,7 @@ public: QVector faceGroups; QString currentMaterialName; QHash materials; - + HFMModel::Pointer read(const hifi::ByteArray& data, const hifi::VariantHash& mapping, const hifi::URL& url = hifi::URL()) override; private: diff --git a/libraries/fbx/src/OBJWriter.cpp b/libraries/model-serializers/src/OBJWriter.cpp similarity index 99% rename from libraries/fbx/src/OBJWriter.cpp rename to libraries/model-serializers/src/OBJWriter.cpp index b2e191bcbf..dec35c7aac 100644 --- a/libraries/fbx/src/OBJWriter.cpp +++ b/libraries/model-serializers/src/OBJWriter.cpp @@ -1,6 +1,6 @@ // // OBJWriter.cpp -// libraries/fbx/src/ +// libraries/model-serializers/src // // Created by Seth Alves on 2017-1-27. // Copyright 2017 High Fidelity, Inc. diff --git a/libraries/fbx/src/OBJWriter.h b/libraries/model-serializers/src/OBJWriter.h similarity index 94% rename from libraries/fbx/src/OBJWriter.h rename to libraries/model-serializers/src/OBJWriter.h index 536e8cf837..34f6d93658 100644 --- a/libraries/fbx/src/OBJWriter.h +++ b/libraries/model-serializers/src/OBJWriter.h @@ -1,6 +1,6 @@ // // OBJWriter.h -// libraries/fbx/src/ +// libraries/model-serializers/src // // Created by Seth Alves on 2017-1-27. // Copyright 2017 High Fidelity, Inc. diff --git a/libraries/networking/src/AddressManager.cpp b/libraries/networking/src/AddressManager.cpp index 94bcb718d3..f0fa1365c4 100644 --- a/libraries/networking/src/AddressManager.cpp +++ b/libraries/networking/src/AddressManager.cpp @@ -4,6 +4,7 @@ // // Created by Stephen Birarda on 2014-09-10. // Copyright 2014 High Fidelity, Inc. +// Copyright 2020 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,11 +36,11 @@ const QString REDIRECT_HIFI_ADDRESS = NetworkingConstants::REDIRECT_HIFI_ADDRESS const QString ADDRESS_MANAGER_SETTINGS_GROUP = "AddressManager"; const QString SETTINGS_CURRENT_ADDRESS_KEY = "address"; -const QString DEFAULT_VIRCADIA_ADDRESS = (!BuildInfo::INITIAL_STARTUP_LOCATION.isEmpty()) - ? BuildInfo::INITIAL_STARTUP_LOCATION +const QString DEFAULT_VIRCADIA_ADDRESS = (!BuildInfo::PRELOADED_STARTUP_LOCATION.isEmpty()) + ? BuildInfo::PRELOADED_STARTUP_LOCATION : NetworkingConstants::DEFAULT_VIRCADIA_ADDRESS; -const QString DEFAULT_HOME_ADDRESS = (!BuildInfo::INITIAL_STARTUP_LOCATION.isEmpty()) - ? BuildInfo::INITIAL_STARTUP_LOCATION +const QString DEFAULT_HOME_ADDRESS = (!BuildInfo::PRELOADED_STARTUP_LOCATION.isEmpty()) + ? BuildInfo::PRELOADED_STARTUP_LOCATION : NetworkingConstants::DEFAULT_VIRCADIA_ADDRESS; Setting::Handle currentAddressHandle(QStringList() << ADDRESS_MANAGER_SETTINGS_GROUP << "address", DEFAULT_VIRCADIA_ADDRESS); @@ -414,6 +415,8 @@ void AddressManager::handleLookupString(const QString& lookupString, bool fromSu QString sanitizedString = lookupString.trimmed(); if (!sanitizedString.isEmpty()) { + resetConfirmConnectWithoutAvatarEntities(); + // make this a valid hifi URL and handle it off to handleUrl handleUrl(sanitizedString, fromSuggestions ? Suggestions : UserInput); } @@ -873,6 +876,11 @@ bool AddressManager::setDomainInfo(const QUrl& domainURL, LookupTrigger trigger) return emitHostChanged; } +void AddressManager::goToEntry(LookupTrigger trigger) { + resetConfirmConnectWithoutAvatarEntities(); + handleUrl(DEFAULT_VIRCADIA_ADDRESS, trigger); +} + void AddressManager::goToUser(const QString& username, bool shouldMatchOrientation) { QString formattedUsername = QUrl::toPercentEncoding(username); @@ -889,6 +897,11 @@ void AddressManager::goToUser(const QString& username, bool shouldMatchOrientati QByteArray(), nullptr, requestParams); } +void AddressManager::goToLastAddress() { + resetConfirmConnectWithoutAvatarEntities(); + handleUrl(_lastVisitedURL, LookupTrigger::AttemptedRefresh); +} + bool AddressManager::canGoBack() const { return (_backStack.size() > 0); } @@ -1023,3 +1036,10 @@ QString AddressManager::getPlaceName() const { } return QString(); } + +void AddressManager::resetConfirmConnectWithoutAvatarEntities() { + DomainHandler& domainHandler = DependencyManager::get()->getDomainHandler(); + if (!domainHandler.isConnected()) { + domainHandler.resetConfirmConnectWithoutAvatarEntities(); + } +} diff --git a/libraries/networking/src/AddressManager.h b/libraries/networking/src/AddressManager.h index daca6d3392..31ef16a377 100644 --- a/libraries/networking/src/AddressManager.h +++ b/libraries/networking/src/AddressManager.h @@ -31,7 +31,7 @@ const QString INDEX_PATH = "/"; const QString GET_PLACE = "/api/v1/places/%1"; -/**jsdoc +/*@jsdoc * The location API provides facilities related to your current location in the metaverse. * *

Getter/Setter

@@ -68,7 +68,7 @@ const QString GET_PLACE = "/api/v1/places/%1"; * Read-only. */ -/**jsdoc +/*@jsdoc * The AddressManager API provides facilities related to your current location in the metaverse. * * @namespace AddressManager @@ -142,7 +142,7 @@ public: using PositionGetter = std::function; using OrientationGetter = std::function; - /**jsdoc + /*@jsdoc *

The reasons for an address lookup via the metaverse API are defined by numeric values:

*
* @@ -245,19 +245,19 @@ public: QUrl getDomainURL() { return _domainURL; } public slots: - /**jsdoc + /*@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 {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 + /*@jsdoc * 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 @@ -272,19 +272,19 @@ public slots: bool goToViewpointForPath(const QString& viewpointString, const QString& pathString) { return handleViewpoint(viewpointString, false, DomainPathResponse, false, pathString); } - /**jsdoc + /*@jsdoc * Takes you back to the previous location in your navigation history, if there is one. * @function location.goBack */ void goBack(); - /**jsdoc + /*@jsdoc * Takes you forward to the next location in your navigation history, if there is one. * @function location.goForward */ void goForward(); - /**jsdoc + /*@jsdoc * Takes you to the local Sandbox server that's running on the same PC as Interface. * @function location.goToLocalSandbox * @param {string} [path=""] - The position and orientation to go to (e.g., "/0,0,0"). @@ -295,17 +295,15 @@ public slots: handleUrl(SANDBOX_HIFI_ADDRESS + path, trigger); } - /**jsdoc + /*@jsdoc * Takes you to the default "welcome" metaverse address. * @function location.goToEntry * @param {location.LookupTrigger} trigger=StartupFromSettings - The reason for the function call. Helps ensure that user's * location history is correctly maintained. */ - void goToEntry(LookupTrigger trigger = LookupTrigger::StartupFromSettings) { - handleUrl(DEFAULT_VIRCADIA_ADDRESS, trigger); - } + void goToEntry(LookupTrigger trigger = LookupTrigger::StartupFromSettings); - /**jsdoc + /*@jsdoc * Takes you to the specified user's location. * @function location.goToUser * @param {string} username - The user's username. @@ -314,20 +312,20 @@ public slots: */ void goToUser(const QString& username, bool shouldMatchOrientation = true); - /**jsdoc + /*@jsdoc * Takes you to the last address tried. This will be the last URL tried from location.handleLookupString. * @function location.goToLastAddress */ - void goToLastAddress() { handleUrl(_lastVisitedURL, LookupTrigger::AttemptedRefresh); } + void goToLastAddress(); - /**jsdoc + /*@jsdoc * Checks if going back to the previous location is possible. * @function location.canGoBack * @returns {boolean} true if going back is possible, false if it isn't. */ bool canGoBack() const; - /**jsdoc + /*@jsdoc * Refreshes the current address, e.g., after connecting to a domain in order to position the user to the desired location. * @function location.refreshPreviousLookup * @deprecated This function is deprecated and will be removed. @@ -336,27 +334,27 @@ public slots: // functions and signals that should be exposed are moved to a scripting interface class. void refreshPreviousLookup(); - /**jsdoc + /*@jsdoc * Updates your current metaverse location in Interface's {@link Settings} file as your last-known address. This can be used * to ensure that you start up at that address if you exit Interface without a later address automatically being saved. * @function location.storeCurrentAddress */ void storeCurrentAddress(); - /**jsdoc + /*@jsdoc * Copies your current metaverse address (i.e., location.href property value) to the OS clipboard. * @function location.copyAddress */ void copyAddress(); - /**jsdoc + /*@jsdoc * Copies your current metaverse location and orientation (i.e., location.pathname property value) to the OS * clipboard. * @function location.copyPath */ void copyPath(); - /**jsdoc + /*@jsdoc * Retrieves and remembers the place name for the given domain ID if the place name is not already known. * @function location.lookupShareableNameForDomainID * @param {Uuid} domainID - The UUID of the domain. @@ -367,7 +365,7 @@ public slots: void lookupShareableNameForDomainID(const QUuid& domainID); signals: - /**jsdoc + /*@jsdoc * Triggered when looking up the details of a metaverse user or location to go to has completed (successfully or * unsuccessfully). * @function location.lookupResultsFinished @@ -375,7 +373,7 @@ signals: */ void lookupResultsFinished(); - /**jsdoc + /*@jsdoc * 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 @@ -383,7 +381,7 @@ signals: */ void lookupResultIsOffline(); - /**jsdoc + /*@jsdoc * Triggered when looking up the details of a metaverse user or location to go to has completed and the domain or user could * not be found. * @function location.lookupResultIsNotFound @@ -391,17 +389,17 @@ signals: */ void lookupResultIsNotFound(); - /**jsdoc - * Triggered when a request is made to go to an IP address. + /*@jsdoc + * 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. void possibleDomainChangeRequired(QUrl domainURL, QUuid domainID); - /**jsdoc + /*@jsdoc * Triggered when a request is made to go to a named domain or user. * @function location.possibleDomainChangeRequiredViaICEForID * @param {string} iceServerHostName - IP address of the ICE server. @@ -411,7 +409,7 @@ signals: // No example because this function isn't typically used in scripts. void possibleDomainChangeRequiredViaICEForID(const QString& iceServerHostname, const QUuid& domainID); - /**jsdoc + /*@jsdoc * Triggered when an attempt is made to send your avatar to a specified position on the current domain. For example, when * you change domains or enter a position to go to in the "Goto" dialog. * @function location.locationChangeRequired @@ -437,7 +435,7 @@ signals: bool hasOrientationChange, const glm::quat& newOrientation, bool shouldFaceLocation); - /**jsdoc + /*@jsdoc * Triggered when an attempt is made to send your avatar to a new named path on the domain (set in the domain server's * settings). For example, when you enter a "/" followed by the path's name in the "GOTO" dialog. * @function location.pathChangeRequired @@ -452,7 +450,7 @@ signals: */ void pathChangeRequired(const QString& newPath); - /**jsdoc + /*@jsdoc * Triggered when you navigate to a new domain. * @function location.hostChanged * @param {string} hostname - The new domain's host name. @@ -466,7 +464,7 @@ signals: */ void hostChanged(const QString& newHost); - /**jsdoc + /*@jsdoc * 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 @@ -482,7 +480,7 @@ signals: */ void goBackPossible(bool isPossible); - /**jsdoc + /*@jsdoc * Triggered when there's a change in whether or not there's a forward location that can be navigated to using * {@link location.goForward|goForward}. (Reflects changes in the state of the "Goto" dialog's forward arrow.) * @function location.goForwardPossible @@ -527,6 +525,8 @@ private: void addCurrentAddressToHistory(LookupTrigger trigger); + void resetConfirmConnectWithoutAvatarEntities(); + QUrl _domainURL; QUrl _lastVisitedURL; diff --git a/libraries/networking/src/AssetClient.cpp b/libraries/networking/src/AssetClient.cpp index bbd743cf95..9c0bb846f7 100644 --- a/libraries/networking/src/AssetClient.cpp +++ b/libraries/networking/src/AssetClient.cpp @@ -89,7 +89,7 @@ namespace { const QString& CACHE_ERROR_MESSAGE{ "AssetClient::Error: %1 %2" }; } -/**jsdoc +/*@jsdoc * Cache status value returned by {@link Assets.getCacheStatus}. * @typedef {object} Assets.GetCacheStatusResult * @property {string} cacheDirectory - The path of the cache directory. @@ -117,7 +117,7 @@ MiniPromise::Promise AssetClient::cacheInfoRequestAsync(MiniPromise::Promise def return deferred; } -/**jsdoc +/*@jsdoc * Information on an asset in the cache. Value returned by {@link Assets.queryCacheMeta} and included in the data returned by * {@link Assets.loadFromCache}. * @typedef {object} Assets.CacheItemMetaData @@ -227,7 +227,7 @@ namespace { } } -/**jsdoc +/*@jsdoc * Last-modified and expiry times for a cache item. * @typedef {object} Assets.SaveToCacheHeaders * @property {string} [expires] - The date and time the cache value expires, in the format: @@ -235,7 +235,7 @@ namespace { * @property {string} [last-modified] - The date and time the cache value was last modified, in the format: * "ddd, dd MMM yyyy HH:mm:ss". The default value is the current date and time. */ -/**jsdoc +/*@jsdoc * Information on saving asset data to the cache with {@link Assets.saveToCache}. * @typedef {object} Assets.SaveToCacheResult * @property {number} [byteLength] - The size of the cached data, in bytes. diff --git a/libraries/networking/src/BaseAssetScriptingInterface.cpp b/libraries/networking/src/BaseAssetScriptingInterface.cpp index 2a98dbf3c3..d7d14496ba 100644 --- a/libraries/networking/src/BaseAssetScriptingInterface.cpp +++ b/libraries/networking/src/BaseAssetScriptingInterface.cpp @@ -68,7 +68,7 @@ Promise BaseAssetScriptingInterface::queryCacheMeta(const QUrl& url) { return assetClient()->queryCacheMetaAsync(url, makePromise(__FUNCTION__)); } -/**jsdoc +/*@jsdoc * Data and information returned by {@link Assets.loadFromCache}. * @typedef {object} Assets.LoadFromCacheResult * @property {number} [byteLength] - The number of bytes in the retrieved data. diff --git a/libraries/networking/src/BaseAssetScriptingInterface.h b/libraries/networking/src/BaseAssetScriptingInterface.h index 7d118e1979..31aad21ba2 100644 --- a/libraries/networking/src/BaseAssetScriptingInterface.h +++ b/libraries/networking/src/BaseAssetScriptingInterface.h @@ -25,7 +25,7 @@ class BaseAssetScriptingInterface : public QObject { Q_OBJECT public: - /**jsdoc + /*@jsdoc *

Types of response that {@link Assets.decompressData}, {@link Assets.getAsset}, or {@link Assets.loadFromCache} may * provide.

*
@@ -48,7 +48,7 @@ public: public slots: - /**jsdoc + /*@jsdoc * Checks whether a string is a valid path. Note: A valid path must start with a "/". * @function Assets.isValidPath * @param {string} path - The path to check. @@ -56,7 +56,7 @@ public slots: */ bool isValidPath(QString input) { return AssetUtils::isValidPath(input); } - /**jsdoc + /*@jsdoc * Checks whether a string is a valid path and filename. Note: A valid path and filename must start with a "/" * but must not end with a "/". * @function Assets.isValidFilePath @@ -65,7 +65,7 @@ public slots: */ bool isValidFilePath(QString input) { return AssetUtils::isValidFilePath(input); } - /**jsdoc + /*@jsdoc * Gets the normalized ATP URL for a path or hash: ensures that it has "atp:" at the start. * @function Assets.getATPUrl * @param {string} url - The URL to normalize. @@ -73,7 +73,7 @@ public slots: */ QUrl getATPUrl(QString input) { return AssetUtils::getATPUrl(input); } - /**jsdoc + /*@jsdoc * Gets the SHA256 hexadecimal hash portion of an asset server URL. * @function Assets.extractAssetHash * @param {string} url - The URL to get the SHA256 hexadecimal hash from. @@ -81,7 +81,7 @@ public slots: */ QString extractAssetHash(QString input) { return AssetUtils::extractAssetHash(input); } - /**jsdoc + /*@jsdoc * Checks whether a string is a valid SHA256 hexadecimal hash, i.e., 64 hexadecimal characters. * @function Assets.isValidHash * @param {string} hash - The hash to check. @@ -89,7 +89,7 @@ public slots: */ bool isValidHash(QString input) { return AssetUtils::isValidHash(input); } - /**jsdoc + /*@jsdoc * Calculates the SHA256 hash of given data. * @function Assets.hashData * @param {string|ArrayBuffer} data - The data to calculate the hash of. @@ -97,7 +97,7 @@ public slots: */ QByteArray hashData(const QByteArray& data) { return AssetUtils::hashData(data); } - /**jsdoc + /*@jsdoc * Calculates the SHA256 hash of given data, in hexadecimal format. * @function Assets.hashDataHex * @param {string|ArrayBuffer} data - The data to calculate the hash of. diff --git a/libraries/networking/src/DomainHandler.cpp b/libraries/networking/src/DomainHandler.cpp index 6a47d74864..5a1d8fb4a0 100644 --- a/libraries/networking/src/DomainHandler.cpp +++ b/libraries/networking/src/DomainHandler.cpp @@ -126,6 +126,8 @@ void DomainHandler::hardReset(QString reason) { emit resetting(); softReset(reason); + _haveAskedConnectWithoutAvatarEntities = false; + _canConnectWithoutAvatarEntities = false; _isInErrorState = false; emit redirectErrorStateChanged(_isInErrorState); @@ -364,10 +366,14 @@ void DomainHandler::setIsConnected(bool isConnected) { _lastDomainConnectionError = -1; emit connectedToDomain(_domainURL); + // 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()) { // we've connected to new domain - time to ask it for global settings requestDomainSettings(); } + */ } else { emit disconnectedFromDomain(); @@ -375,6 +381,24 @@ void DomainHandler::setIsConnected(bool isConnected) { } } +void DomainHandler::setCanConnectWithoutAvatarEntities(bool canConnect) { + _canConnectWithoutAvatarEntities = canConnect; + _haveAskedConnectWithoutAvatarEntities = true; +} + +bool DomainHandler::canConnectWithoutAvatarEntities() { + if (!_canConnectWithoutAvatarEntities && !_haveAskedConnectWithoutAvatarEntities) { + if (_isConnected) { + // Already connected so don't ask. (Permission removed from user while in the domain.) + setCanConnectWithoutAvatarEntities(true); + } else { + // Ask whether to connect to the domain. + emit confirmConnectWithoutAvatarEntities(); + } + } + return _canConnectWithoutAvatarEntities; +} + void DomainHandler::connectedToServerless(std::map namedPaths) { _namedPaths = namedPaths; setIsConnected(true); diff --git a/libraries/networking/src/DomainHandler.h b/libraries/networking/src/DomainHandler.h index 56d32d8609..a56d3162bd 100644 --- a/libraries/networking/src/DomainHandler.h +++ b/libraries/networking/src/DomainHandler.h @@ -98,6 +98,7 @@ public: Node::LocalID getLocalID() const { return _localID; } void setLocalID(Node::LocalID localID) { _localID = localID; } + QString getScheme() const { return _domainURL.scheme(); } QString getHostname() const { return _domainURL.host(); } QUrl getErrorDomainURL(){ return _errorDomainURL; } @@ -133,6 +134,9 @@ public: bool isConnected() const { return _isConnected; } void setIsConnected(bool isConnected); + void setCanConnectWithoutAvatarEntities(bool canConnect); + bool canConnectWithoutAvatarEntities(); + bool isServerless() const { return _domainURL.scheme() != URL_SCHEME_HIFI; } bool getInterstitialModeEnabled() const; void setInterstitialModeEnabled(bool enableInterstitialMode); @@ -159,7 +163,11 @@ public: bool checkInPacketTimeout(); void clearPendingCheckins() { _checkInPacketsSinceLastReply = 0; } - /**jsdoc + void resetConfirmConnectWithoutAvatarEntities() { + _haveAskedConnectWithoutAvatarEntities = false; + } + + /*@jsdoc *

The reasons that you may be refused connection to a domain are defined by numeric values:

*
* @@ -252,6 +260,7 @@ signals: void completedSocketDiscovery(); void resetting(); + void confirmConnectWithoutAvatarEntities(); void connectedToDomain(QUrl domainURL); void disconnectedFromDomain(); @@ -287,6 +296,8 @@ private: HifiSockAddr _iceServerSockAddr; NetworkPeer _icePeer; bool _isConnected { false }; + bool _haveAskedConnectWithoutAvatarEntities { false }; + bool _canConnectWithoutAvatarEntities { false }; bool _isInErrorState { false }; QJsonObject _settingsObject; QString _pendingPath; diff --git a/libraries/networking/src/ExternalResource.h b/libraries/networking/src/ExternalResource.h index fa6eb85cfe..edba0b458b 100644 --- a/libraries/networking/src/ExternalResource.h +++ b/libraries/networking/src/ExternalResource.h @@ -42,7 +42,7 @@ public: static ExternalResource* getInstance(); ~ExternalResource(){}; - /**jsdoc + /*@jsdoc *

An external resource bucket.

*

The original High Fidelity used "Public", "Content", and "MPAssets" Amazon S3 buckets. The intention is that the * community-run versions of these will keep the original data and structure, and any new additions will be made to @@ -56,7 +56,7 @@ public: * @property {Script.ResourceBucket} HF_Marketplace - Assets that used to be in the High Fidelity's mpassets * Amazon S3 bucket. (High Fidelity marketplace.) */ - /**jsdoc + /*@jsdoc *

An external resource bucket.

*
* diff --git a/libraries/networking/src/FingerprintUtils.cpp b/libraries/networking/src/FingerprintUtils.cpp index 216e0f28dd..cab8cde832 100644 --- a/libraries/networking/src/FingerprintUtils.cpp +++ b/libraries/networking/src/FingerprintUtils.cpp @@ -17,6 +17,9 @@ #include #include #include +#include +#include +#include #ifdef Q_OS_WIN #include @@ -29,29 +32,83 @@ #include #endif //Q_OS_MAC +// Number of iterations to apply to the hash, for stretching. +// The number is arbitrary and has the only purpose of slowing down brute-force +// attempts. The number here should be low enough not to cause any trouble for +// low-end hardware. +// +// Changing this results in different hardware IDs being computed. +static const int HASH_ITERATIONS = 65535; + +// Salt string for the hardware ID, makes our IDs unique to our project. +// Changing this results in different hardware IDs being computed. +static const QByteArray HASH_SALT{"Vircadia"}; + static const QString FALLBACK_FINGERPRINT_KEY = "fallbackFingerprint"; QUuid FingerprintUtils::_machineFingerprint { QUuid() }; QString FingerprintUtils::getMachineFingerprintString() { - QString uuidString; + QCryptographicHash hash(QCryptographicHash::Keccak_256); + #ifdef Q_OS_LINUX - // sadly need to be root to get smbios guid from linux, so - // for now lets do nothing. + // As per the documentation: + // https://man7.org/linux/man-pages/man5/machine-id.5.html + // + // we use the machine id as a base, but add an application-specific key to it. + // If machine-id isn't available, we try hardware networking devices instead. + + QFile machineIdFile("/etc/machine-id"); + if (!machineIdFile.open(QIODevice::ReadOnly | QIODevice::Text)) { + // No machine ID, probably no systemd. + qCWarning(networking) << "Failed to open /etc/machine-id"; + + QDir netDevicesDir("/sys/class/net"); + QFileInfoList netDevicesInfo = netDevicesDir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot, QDir::Name); + + if (netDevicesInfo.empty()) { + // Let getMachineFingerprint handle this contingency + qCWarning(networking) << "Failed to find any hardware networking devices"; + return QUuid().toString(); + } + + for(auto& fileInfo : netDevicesInfo) { + + if (fileInfo.isSymLink() && fileInfo.symLinkTarget().contains("virtual")) { + // symlink points to something like: + // ../../devices/virtual/net/lo + // these are not real devices and have random IDs, so we + // don't care about them. + continue; + } + + QFile addressFile(fileInfo.filePath() + "/address"); + if (addressFile.open(QIODevice::ReadOnly | QIODevice::Text)) { + qCDebug(networking) << "Adding contents of " << addressFile.fileName(); + hash.addData(addressFile.readAll()); + } else { + qCWarning(networking) << "Failed to read " << addressFile.fileName(); + } + } + } else { + QByteArray data = machineIdFile.readAll(); + hash.addData(data); + } + #endif //Q_OS_LINUX #ifdef Q_OS_MAC io_registry_entry_t ioRegistryRoot = IORegistryEntryFromPath(kIOMasterPortDefault, "IOService:/"); CFStringRef uuidCf = (CFStringRef) IORegistryEntryCreateCFProperty(ioRegistryRoot, CFSTR(kIOPlatformUUIDKey), kCFAllocatorDefault, 0); IOObjectRelease(ioRegistryRoot); - uuidString = QString::fromCFString(uuidCf); + hash.addData(QString::fromCFString(uuidCf).toUtf8()); CFRelease(uuidCf); - qCDebug(networking) << "Mac serial number: " << uuidString; #endif //Q_OS_MAC #ifdef Q_OS_WIN HKEY cryptoKey; - + bool success = false; + // try and open the key that contains the machine GUID if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Cryptography", 0, KEY_READ, &cryptoKey) == ERROR_SUCCESS) { DWORD type; @@ -68,7 +125,8 @@ QString FingerprintUtils::getMachineFingerprintString() { if (RegQueryValueEx(cryptoKey, MACHINE_GUID_KEY, NULL, NULL, reinterpret_cast(&machineGUID[0]), &guidSize) == ERROR_SUCCESS) { - uuidString = QString::fromStdString(machineGUID); + hash.addData(QString::fromStdString(machineGUID).toUtf8()); + success = true; } } } @@ -76,10 +134,43 @@ QString FingerprintUtils::getMachineFingerprintString() { RegCloseKey(cryptoKey); } + if (!success) { + // Let getMachineFingerprint handle this contingency + return QUuid().toString(); + } #endif //Q_OS_WIN - return uuidString; + // Makes this hash unique to us + hash.addData(HASH_SALT); + // Stretching + for (int i = 0; i < HASH_ITERATIONS; i++) { + hash.addData(hash.result()); + } + + QByteArray result = hash.result(); + result.resize(128 / 8); // GUIDs are 128 bit numbers + + // Set UUID version to 4, ensuring it's a valid UUID + result[6] = (result[6] & 0x0F) | 0x40; + + // Of course, Qt couldn't be nice and just parse something like: + // 1b1b9d6d45c2473bac13dc3011ff58d6 + // + // So we have to turn it into: + // {1b1b9d6d-45c2-473b-ac13-dc3011ff58d6} + + QString uuidString = result.toHex(); + uuidString.insert(20, '-'); + uuidString.insert(16, '-'); + uuidString.insert(12, '-'); + uuidString.insert(8, '-'); + uuidString.prepend("{"); + uuidString.append("}"); + + qCDebug(networking) << "Final machine fingerprint:" << uuidString; + + return uuidString; } QUuid FingerprintUtils::getMachineFingerprint() { diff --git a/libraries/networking/src/LimitedNodeList.cpp b/libraries/networking/src/LimitedNodeList.cpp index 3da5b53dcb..653611ae8c 100644 --- a/libraries/networking/src/LimitedNodeList.cpp +++ b/libraries/networking/src/LimitedNodeList.cpp @@ -198,6 +198,10 @@ void LimitedNodeList::setPermissions(const NodePermissions& newPermissions) { newPermissions.can(NodePermissions::Permission::canGetAndSetPrivateUserData)) { emit canGetAndSetPrivateUserDataChanged(_permissions.can(NodePermissions::Permission::canGetAndSetPrivateUserData)); } + if (originalPermissions.can(NodePermissions::Permission::canRezAvatarEntities) != + newPermissions.can(NodePermissions::Permission::canRezAvatarEntities)) { + emit canRezAvatarEntitiesChanged(_permissions.can(NodePermissions::Permission::canRezAvatarEntities)); + } } void LimitedNodeList::setSocketLocalPort(quint16 socketLocalPort) { diff --git a/libraries/networking/src/LimitedNodeList.h b/libraries/networking/src/LimitedNodeList.h index 59d18fe047..189f3e1b08 100644 --- a/libraries/networking/src/LimitedNodeList.h +++ b/libraries/networking/src/LimitedNodeList.h @@ -133,6 +133,7 @@ public: bool getThisNodeCanKick() const { return _permissions.can(NodePermissions::Permission::canKick); } bool getThisNodeCanReplaceContent() const { return _permissions.can(NodePermissions::Permission::canReplaceDomainContent); } bool getThisNodeCanGetAndSetPrivateUserData() const { return _permissions.can(NodePermissions::Permission::canGetAndSetPrivateUserData); } + bool getThisNodeCanRezAvatarEntities() const { return _permissions.can(NodePermissions::Permission::canRezAvatarEntities); } quint16 getSocketLocalPort() const { return _nodeSocket.localPort(); } Q_INVOKABLE void setSocketLocalPort(quint16 socketLocalPort); @@ -390,6 +391,7 @@ signals: void canKickChanged(bool canKick); void canReplaceContentChanged(bool canReplaceContent); void canGetAndSetPrivateUserDataChanged(bool canGetAndSetPrivateUserData); + void canRezAvatarEntitiesChanged(bool canRezAvatarEntities); protected slots: void connectedForLocalSocketTest(); diff --git a/libraries/networking/src/MessagesClient.h b/libraries/networking/src/MessagesClient.h index 7f2714e5ea..db2085da5a 100644 --- a/libraries/networking/src/MessagesClient.h +++ b/libraries/networking/src/MessagesClient.h @@ -23,7 +23,7 @@ #include "Node.h" #include "ReceivedMessage.h" -/**jsdoc +/*@jsdoc *

The Messages API enables text and data to be sent between scripts over named "channels". A channel can have * an arbitrary name to help separate messaging between different sets of scripts.

* @@ -51,7 +51,7 @@ public: void startThread(); - /**jsdoc + /*@jsdoc * Sends a text message on a channel. * @function Messages.sendMessage * @param {string} channel - The channel to send the message on. @@ -89,7 +89,7 @@ public: */ Q_INVOKABLE void sendMessage(QString channel, QString message, bool localOnly = false); - /**jsdoc + /*@jsdoc * Sends a text message locally on a channel. * This is the same as calling {@link Messages.sendMessage|sendMessage} with localOnly == true. * @function Messages.sendLocalMessage @@ -98,7 +98,7 @@ public: */ Q_INVOKABLE void sendLocalMessage(QString channel, QString message); - /**jsdoc + /*@jsdoc * Sends a data message on a channel. * @function Messages.sendData * @param {string} channel - The channel to send the data on. @@ -145,7 +145,7 @@ public: */ Q_INVOKABLE void sendData(QString channel, QByteArray data, bool localOnly = false); - /**jsdoc + /*@jsdoc * Subscribes the scripting environment — Interface, the entity script server, or assignment client instance — * to receive messages on a specific channel. This means, for example, that if there are two Interface scripts that * subscribe to different channels, both scripts will receive messages on both channels. @@ -154,7 +154,7 @@ public: */ Q_INVOKABLE void subscribe(QString channel); - /**jsdoc + /*@jsdoc * Unsubscribes the scripting environment from receiving messages on a specific channel. * @function Messages.unsubscribe * @param {string} channel - The channel to unsubscribe from. @@ -168,7 +168,7 @@ public: static std::unique_ptr encodeMessagesDataPacket(QString channel, QByteArray data, QUuid senderID); signals: - /**jsdoc + /*@jsdoc * Triggered when a text message is received. * @function Messages.messageReceived * @param {string} channel - The channel that the message was sent on. This can be used to filter out messages not relevant @@ -182,7 +182,7 @@ signals: */ void messageReceived(QString channel, QString message, QUuid senderUUID, bool localOnly); - /**jsdoc + /*@jsdoc * Triggered when a data message is received. * @function Messages.dataReceived * @param {string} channel - The channel that the message was sent on. This can be used to filter out messages not relevant diff --git a/libraries/networking/src/NetworkingConstants.h b/libraries/networking/src/NetworkingConstants.h index ccdb9ea75c..d5ad90a6f4 100644 --- a/libraries/networking/src/NetworkingConstants.h +++ b/libraries/networking/src/NetworkingConstants.h @@ -26,7 +26,7 @@ namespace NetworkingConstants { // 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/69.0.3497.113"; + const QString WEB_ENGINE_VERSION = "Chrome/83.0.4103.122"; // For now we only have one Metaverse server. const QUrl METAVERSE_SERVER_URL_STABLE { "https://metaverse.vircadia.com/live" }; diff --git a/libraries/networking/src/Node.h b/libraries/networking/src/Node.h index 07c599913b..7435ebaaf8 100644 --- a/libraries/networking/src/Node.h +++ b/libraries/networking/src/Node.h @@ -84,6 +84,7 @@ public: bool getCanKick() const { return _permissions.can(NodePermissions::Permission::canKick); } bool getCanReplaceContent() const { return _permissions.can(NodePermissions::Permission::canReplaceDomainContent); } bool getCanGetAndSetPrivateUserData() const { return _permissions.can(NodePermissions::Permission::canGetAndSetPrivateUserData); } + bool getCanRezAvatarEntities() const { return _permissions.can(NodePermissions::Permission::canRezAvatarEntities); } using NodesIgnoredPair = std::pair, bool>; diff --git a/libraries/networking/src/NodeList.cpp b/libraries/networking/src/NodeList.cpp index a523a7ff36..a975302699 100644 --- a/libraries/networking/src/NodeList.cpp +++ b/libraries/networking/src/NodeList.cpp @@ -42,6 +42,7 @@ #include "udt/PacketHeaders.h" #include "SharedUtil.h" #include +#include using namespace std::chrono; @@ -94,6 +95,12 @@ NodeList::NodeList(char newOwnerType, int socketListenPort, int dtlsListenPort) // send a ping punch immediately connect(&_domainHandler, &DomainHandler::icePeerSocketsReceived, this, &NodeList::pingPunchForDomainServer); + // FIXME: Can remove this temporary work-around in version 2021.2.0. (New protocol version implies a domain server upgrade.) + // Adjust our canRezAvatarEntities permissions on older domains that do not have this setting. + // DomainServerList and DomainSettings packets can come in either order so need to adjust with both occurrences. + auto nodeList = DependencyManager::get(); + connect(&_domainHandler, &DomainHandler::settingsReceived, this, &NodeList::adjustCanRezAvatarEntitiesPerSettings); + auto accountManager = DependencyManager::get(); // assume that we may need to send a new DS check in anytime a new keypair is generated @@ -726,6 +733,11 @@ void NodeList::processDomainServerList(QSharedPointer message) // pull the permissions/right/privileges for this node out of the stream NodePermissions newPermissions; packetStream >> newPermissions; + // FIXME: Can remove this temporary work-around in version 2021.2.0. (New protocol version implies a domain server upgrade.) + // Adjust our canRezAvatarEntities permissions on older domains that do not have this setting. + // DomainServerList and DomainSettings packets can come in either order so need to adjust with both occurrences. + bool adjustedPermissions = adjustCanRezAvatarEntitiesPermissions(_domainHandler.getSettingsObject(), newPermissions, false); + // Is packet authentication enabled? bool isAuthenticated; packetStream >> isAuthenticated; @@ -781,7 +793,7 @@ void NodeList::processDomainServerList(QSharedPointer message) DependencyManager::get()->flagTimeForConnectionStep(LimitedNodeList::ConnectionStep::ReceiveDSList); if (_domainHandler.isConnected() && _domainHandler.getUUID() != domainUUID) { - // Recieved packet from different domain. + // Received packet from different domain. qWarning() << "IGNORING DomainList packet from" << domainUUID << "while connected to" << _domainHandler.getUUID() << ": sent " << pingLagTime << " msec ago."; qWarning(networking) << "DomainList request lag (interface->ds): " << domainServerRequestLag << "msec"; @@ -809,6 +821,23 @@ void NodeList::processDomainServerList(QSharedPointer message) setSessionLocalID(newLocalID); setSessionUUID(newUUID); + // 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()) { + // 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. + _domainHandler.requestDomainSettings(); + } + + // Don't continue login to the domain if have avatar entities and don't have permissions to rez them, unless user has OKed + // continuing login. + if (!newPermissions.can(NodePermissions::Permission::canRezAvatarEntities) + && (!adjustedPermissions || !_domainHandler.canConnectWithoutAvatarEntities())) { + return; + } + // if this was the first domain-server list from this domain, we've now connected if (!_domainHandler.isConnected()) { _domainHandler.setLocalID(domainLocalID); @@ -1263,17 +1292,19 @@ float NodeList::getInjectorGain() { return _injectorGain; } -void NodeList::kickNodeBySessionID(const QUuid& nodeID) { +void NodeList::kickNodeBySessionID(const QUuid& nodeID, unsigned int banFlags) { // send a request to domain-server to kick the node with the given session ID // the domain-server will handle the persistence of the kick (via username or IP) if (!nodeID.isNull() && getSessionUUID() != nodeID ) { if (getThisNodeCanKick()) { // setup the packet - auto kickPacket = NLPacket::create(PacketType::NodeKickRequest, NUM_BYTES_RFC4122_UUID, true); + auto kickPacket = NLPacket::create(PacketType::NodeKickRequest, NUM_BYTES_RFC4122_UUID + sizeof(int), true); // write the node ID to the packet kickPacket->write(nodeID.toRfc4122()); + // write the ban parameters to the packet + kickPacket->writePrimitive(banFlags); qCDebug(networking) << "Sending packet to kick node" << uuidStringWithoutCurlyBraces(nodeID); @@ -1368,3 +1399,35 @@ void NodeList::setRequestsDomainListData(bool isRequesting) { void NodeList::startThread() { moveToNewNamedThread(this, "NodeList Thread", QThread::TimeCriticalPriority); } + + +// FIXME: Can remove this work-around in version 2021.2.0. (New protocol version implies a domain server upgrade.) +bool NodeList::adjustCanRezAvatarEntitiesPermissions(const QJsonObject& domainSettingsObject, + NodePermissions& permissions, bool notify) { + + if (domainSettingsObject.isEmpty()) { + // Don't have enough information to adjust yet. + return false; // Failed to adjust. + } + + const double CANREZAVATARENTITIES_INTRODUCED_VERSION = 2.5; + auto version = domainSettingsObject.value("version"); + if (version.isUndefined() || version.isDouble() && version.toDouble() < CANREZAVATARENTITIES_INTRODUCED_VERSION) { + // On domains without the canRezAvatarEntities permission available, set it to the same as canConnectToDomain. + if (permissions.can(NodePermissions::Permission::canConnectToDomain)) { + if (!permissions.can(NodePermissions::Permission::canRezAvatarEntities)) { + permissions.set(NodePermissions::Permission::canRezAvatarEntities); + if (notify) { + emit canRezAvatarEntitiesChanged(permissions.can(NodePermissions::Permission::canRezAvatarEntities)); + } + } + } + } + + return true; // Successfully adjusted. +} + +// FIXME: Can remove this work-around in version 2021.2.0. (New protocol version implies a domain server upgrade.) +void NodeList::adjustCanRezAvatarEntitiesPerSettings(const QJsonObject& domainSettingsObject) { + adjustCanRezAvatarEntitiesPermissions(domainSettingsObject, _permissions, true); +} diff --git a/libraries/networking/src/NodeList.h b/libraries/networking/src/NodeList.h index 4954c53c84..59b3815fba 100644 --- a/libraries/networking/src/NodeList.h +++ b/libraries/networking/src/NodeList.h @@ -86,7 +86,7 @@ public: void setInjectorGain(float gain); float getInjectorGain(); - void kickNodeBySessionID(const QUuid& nodeID); + void kickNodeBySessionID(const QUuid& nodeID, unsigned int banFlags); void muteNodeBySessionID(const QUuid& nodeID); void requestUsernameFromSessionID(const QUuid& nodeID); bool getRequestsDomainListData() { return _requestsDomainListData; } @@ -123,6 +123,11 @@ public slots: void processUsernameFromIDReply(QSharedPointer message); + // FIXME: Can remove these work-arounds in version 2021.2.0. (New protocol version implies a domain server upgrade.) + bool adjustCanRezAvatarEntitiesPermissions(const QJsonObject& domainSettingsObject, NodePermissions& permissions, + bool notify); + void adjustCanRezAvatarEntitiesPerSettings(const QJsonObject& domainSettingsObject); + #if (PR_BUILD || DEV_BUILD) void toggleSendNewerDSConnectVersion(bool shouldSendNewerVersion) { _shouldSendNewerVersion = shouldSendNewerVersion; } #endif diff --git a/libraries/networking/src/NodePermissions.cpp b/libraries/networking/src/NodePermissions.cpp index e0de649c05..d96cdfcf06 100644 --- a/libraries/networking/src/NodePermissions.cpp +++ b/libraries/networking/src/NodePermissions.cpp @@ -57,6 +57,7 @@ NodePermissions::NodePermissions(QMap perms) { permissions = NodePermissions::Permissions(); permissions |= perms["id_can_connect"].toBool() ? Permission::canConnectToDomain : Permission::none; + permissions |= perms["id_can_rez_avatar_entities"].toBool() ? Permission::canRezAvatarEntities : Permission::none; permissions |= perms["id_can_adjust_locks"].toBool() ? Permission::canAdjustLocks : Permission::none; permissions |= perms["id_can_rez"].toBool() ? Permission::canRezPermanentEntities : Permission::none; permissions |= perms["id_can_rez_tmp"].toBool() ? Permission::canRezTemporaryEntities : Permission::none; @@ -67,7 +68,8 @@ NodePermissions::NodePermissions(QMap perms) { Permission::canConnectPastMaxCapacity : Permission::none; permissions |= perms["id_can_kick"].toBool() ? Permission::canKick : Permission::none; permissions |= perms["id_can_replace_content"].toBool() ? Permission::canReplaceDomainContent : Permission::none; - permissions |= perms["id_can_get_and_set_private_user_data"].toBool() ? Permission::canGetAndSetPrivateUserData : Permission::none; + permissions |= perms["id_can_get_and_set_private_user_data"].toBool() ? + Permission::canGetAndSetPrivateUserData : Permission::none; } QVariant NodePermissions::toVariant(QHash groupRanks) { @@ -86,6 +88,7 @@ QVariant NodePermissions::toVariant(QHash groupRanks) { } } values["id_can_connect"] = can(Permission::canConnectToDomain); + values["id_can_rez_avatar_entities"] = can(Permission::canRezAvatarEntities); values["id_can_adjust_locks"] = can(Permission::canAdjustLocks); values["id_can_rez"] = can(Permission::canRezPermanentEntities); values["id_can_rez_tmp"] = can(Permission::canRezTemporaryEntities); @@ -141,6 +144,9 @@ QDebug operator<<(QDebug debug, const NodePermissions& perms) { if (perms.can(NodePermissions::Permission::canConnectToDomain)) { debug << " connect"; } + if (perms.can(NodePermissions::Permission::canRezAvatarEntities)) { + debug << " rez-avatar-entities"; + } if (perms.can(NodePermissions::Permission::canAdjustLocks)) { debug << " locks"; } @@ -174,6 +180,7 @@ QDebug operator<<(QDebug debug, const NodePermissions& perms) { debug.nospace() << "]"; return debug.nospace(); } + QDebug operator<<(QDebug debug, const NodePermissionsPointer& perms) { if (perms) { return operator<<(debug, *perms.get()); diff --git a/libraries/networking/src/NodePermissions.h b/libraries/networking/src/NodePermissions.h index 82c008feef..e3bfc69d07 100644 --- a/libraries/networking/src/NodePermissions.h +++ b/libraries/networking/src/NodePermissions.h @@ -80,7 +80,8 @@ public: canReplaceDomainContent = 128, canRezPermanentCertifiedEntities = 256, canRezTemporaryCertifiedEntities = 512, - canGetAndSetPrivateUserData = 1024 + canGetAndSetPrivateUserData = 1024, + canRezAvatarEntities = 2048 }; Q_DECLARE_FLAGS(Permissions, Permission) Permissions permissions; diff --git a/libraries/networking/src/PacketReceiver.h b/libraries/networking/src/PacketReceiver.h index 071638cda9..4d2f11360e 100644 --- a/libraries/networking/src/PacketReceiver.h +++ b/libraries/networking/src/PacketReceiver.h @@ -85,9 +85,9 @@ private: class UnsourcedListenerReference : public ListenerReference { public: inline UnsourcedListenerReference(T* target, void (T::*slot)(QSharedPointer)); - virtual bool invokeDirectly(const QSharedPointer& receivedMessagePointer, const QSharedPointer& sourceNode); - virtual bool isSourced() const { return false; } - virtual QObject* getObject() const { return _target; } + virtual bool invokeDirectly(const QSharedPointer& receivedMessagePointer, const QSharedPointer& sourceNode) override; + virtual bool isSourced() const override { return false; } + virtual QObject* getObject() const override { return _target; } private: QPointer _target; @@ -98,9 +98,9 @@ private: class SourcedListenerReference : public ListenerReference { public: inline SourcedListenerReference(T* target, void (T::*slot)(QSharedPointer, QSharedPointer)); - virtual bool invokeDirectly(const QSharedPointer& receivedMessagePointer, const QSharedPointer& sourceNode); - virtual bool isSourced() const { return true; } - virtual QObject* getObject() const { return _target; } + virtual bool invokeDirectly(const QSharedPointer& receivedMessagePointer, const QSharedPointer& sourceNode) override; + virtual bool isSourced() const override { return true; } + virtual QObject* getObject() const override { return _target; } private: QPointer _target; diff --git a/libraries/networking/src/ResourceCache.cpp b/libraries/networking/src/ResourceCache.cpp index 4ba456d859..54297415c0 100644 --- a/libraries/networking/src/ResourceCache.cpp +++ b/libraries/networking/src/ResourceCache.cpp @@ -794,8 +794,6 @@ void Resource::handleReplyFinished() { { "size_mb", _bytesTotal / 1000000.0 } }); - setSize(_bytesTotal); - // Make sure we keep the Resource alive here auto self = _self.lock(); ResourceCache::requestCompleted(_self); @@ -809,6 +807,14 @@ void Resource::handleReplyFinished() { } auto data = _request->getData(); + if (_request->getUrl().scheme() == "qrc") { + // For resources under qrc://, there's no actual download being done, so + // handleDownloadProgress never gets called. We get the full length here + // at the end. + _bytesTotal = data.length(); + } + + setSize(_bytesTotal); emit loaded(data); downloadFinished(data); } else { diff --git a/libraries/networking/src/ResourceCache.h b/libraries/networking/src/ResourceCache.h index 4d5e8964ce..a49f5b3f61 100644 --- a/libraries/networking/src/ResourceCache.h +++ b/libraries/networking/src/ResourceCache.h @@ -90,7 +90,7 @@ private: /// Wrapper to expose resources to JS/QML class ScriptableResource : public QObject { - /**jsdoc + /*@jsdoc * Information about a cached resource. Created by {@link AnimationCache.prefetch}, {@link MaterialCache.prefetch}, * {@link ModelCache.prefetch}, {@link SoundCache.prefetch}, or {@link TextureCache.prefetch}. * @@ -112,7 +112,7 @@ class ScriptableResource : public QObject { public: - /**jsdoc + /*@jsdoc * The loading state of a resource. * @typedef {object} Resource.State * @property {number} QUEUED - The resource is queued up, waiting to be loaded. @@ -133,7 +133,7 @@ public: ScriptableResource(const QUrl& url); virtual ~ScriptableResource() = default; - /**jsdoc + /*@jsdoc * Releases the resource. * @function ResourceObject#release */ @@ -148,7 +148,7 @@ public: signals: - /**jsdoc + /*@jsdoc * Triggered when the resource's download progress changes. * @function ResourceObject#progressChanged * @param {number} bytesReceived - Bytes downloaded so far. @@ -157,7 +157,7 @@ signals: */ void progressChanged(uint64_t bytesReceived, uint64_t bytesTotal); - /**jsdoc + /*@jsdoc * Triggered when the resource's loading state changes. * @function ResourceObject#stateChanged * @param {Resource.State} state - New state. @@ -307,7 +307,7 @@ class ScriptableResourceCache : public QObject { // JSDoc 3.5.5 doesn't augment name spaces with @property definitions so the following properties JSDoc is copied to the // different exposed cache classes. - /**jsdoc + /*@jsdoc * @property {number} numTotal - Total number of total resources. Read-only. * @property {number} numCached - Total number of cached resource. Read-only. * @property {number} sizeTotal - Size in bytes of all resources. Read-only. @@ -318,7 +318,7 @@ class ScriptableResourceCache : public QObject { Q_PROPERTY(size_t sizeTotal READ getSizeTotalResources NOTIFY dirty) Q_PROPERTY(size_t sizeCached READ getSizeCachedResources NOTIFY dirty) - /**jsdoc + /*@jsdoc * @property {number} numGlobalQueriesPending - Total number of global queries pending (across all resource cache managers). * Read-only. * @property {number} numGlobalQueriesLoading - Total number of global queries loading (across all resource cache managers). @@ -330,7 +330,7 @@ class ScriptableResourceCache : public QObject { public: ScriptableResourceCache(QSharedPointer resourceCache); - /**jsdoc + /*@jsdoc * Gets the URLs of all resources in the cache. * @function ResourceCache.getResourceList * @returns {string[]} The URLs of all resources in the cache. @@ -342,14 +342,14 @@ public: */ Q_INVOKABLE QVariantList getResourceList(); - /**jsdoc + /*@jsdoc * @function ResourceCache.updateTotalSize * @param {number} deltaSize - Delta size. * @deprecated This function is deprecated and will be removed. */ Q_INVOKABLE void updateTotalSize(const qint64& deltaSize); - /**jsdoc + /*@jsdoc * Prefetches a resource. * @function ResourceCache.prefetch * @param {string} url - The URL of the resource to prefetch. @@ -386,7 +386,7 @@ public: signals: - /**jsdoc + /*@jsdoc * Triggered when the cache content has changed. * @function ResourceCache.dirty * @returns {Signal} diff --git a/libraries/networking/src/ResourceScriptingInterface.h b/libraries/networking/src/ResourceScriptingInterface.h index 73e2d8e29c..0dda8d9b2c 100644 --- a/libraries/networking/src/ResourceScriptingInterface.h +++ b/libraries/networking/src/ResourceScriptingInterface.h @@ -17,7 +17,7 @@ #include -/**jsdoc +/*@jsdoc * The Resources API enables the default location for different resource types to be overridden. * * @namespace Resources @@ -33,7 +33,7 @@ class ResourceScriptingInterface : public QObject, public Dependency { Q_OBJECT public: - /**jsdoc + /*@jsdoc * Overrides a path prefix with an alternative path. * @function Resources.overrideUrlPrefix * @param {string} prefix - The path prefix to override, e.g., "atp:/". @@ -41,7 +41,7 @@ public: */ Q_INVOKABLE void overrideUrlPrefix(const QString& prefix, const QString& replacement); - /**jsdoc + /*@jsdoc * Restores the default path for a specified prefix. * @function Resources.restoreUrlPrefix * @param {string} prefix - The prefix of the resource to restore the path for. diff --git a/libraries/networking/src/UserActivityLoggerScriptingInterface.h b/libraries/networking/src/UserActivityLoggerScriptingInterface.h index 1cda1235e9..ea01a8446c 100644 --- a/libraries/networking/src/UserActivityLoggerScriptingInterface.h +++ b/libraries/networking/src/UserActivityLoggerScriptingInterface.h @@ -4,6 +4,7 @@ // // Created by Ryan Huffman on 6/06/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 diff --git a/libraries/networking/src/udt/PacketHeaders.cpp b/libraries/networking/src/udt/PacketHeaders.cpp index 87bd7941d3..f7c1192886 100644 --- a/libraries/networking/src/udt/PacketHeaders.cpp +++ b/libraries/networking/src/udt/PacketHeaders.cpp @@ -24,7 +24,7 @@ int packetTypeMetaTypeId = qRegisterMetaType(); PacketVersion versionForPacketType(PacketType packetType) { switch (packetType) { - case PacketType::StunResponse: + case PacketType::DomainConnectRequestPending: // keeping the old version to maintain the protocol hash return 17; case PacketType::DomainList: return static_cast(DomainListVersion::HasConnectReason); diff --git a/libraries/networking/src/udt/PacketHeaders.h b/libraries/networking/src/udt/PacketHeaders.h index 1d96969035..819551045a 100644 --- a/libraries/networking/src/udt/PacketHeaders.h +++ b/libraries/networking/src/udt/PacketHeaders.h @@ -33,7 +33,7 @@ public: // This enum must hold 256 or fewer packet types (so the value is <= 255) since it is statically typed as a uint8_t enum class Value : uint8_t { Unknown, - StunResponse, + DomainConnectRequestPending, DomainList, Ping, PingReply, @@ -170,7 +170,7 @@ public: const static QSet getNonSourcedPackets() { const static QSet NON_SOURCED_PACKETS = QSet() - << PacketTypeEnum::Value::StunResponse << PacketTypeEnum::Value::CreateAssignment + << PacketTypeEnum::Value::DomainConnectRequestPending << PacketTypeEnum::Value::CreateAssignment << PacketTypeEnum::Value::RequestAssignment << PacketTypeEnum::Value::DomainServerRequireDTLS << PacketTypeEnum::Value::DomainConnectRequest << PacketTypeEnum::Value::DomainList << PacketTypeEnum::Value::DomainConnectionDenied << PacketTypeEnum::Value::DomainServerPathQuery diff --git a/libraries/octree/src/OctreeScriptingInterface.h b/libraries/octree/src/OctreeScriptingInterface.h index c7b0552511..41f722a95f 100644 --- a/libraries/octree/src/OctreeScriptingInterface.h +++ b/libraries/octree/src/OctreeScriptingInterface.h @@ -36,7 +36,7 @@ private slots: public slots: - /**jsdoc + /*@jsdoc * Sets the maximum number of entity packets that the client can send per second. * @function Entities.setPacketsPerSecond * @param {number} packetsPerSecond - Integer maximum number of entity packets that the client can send per second. @@ -44,7 +44,7 @@ public slots: /// set the max packets per second send rate void setPacketsPerSecond(int packetsPerSecond) { return _packetSender->setPacketsPerSecond(packetsPerSecond); } - /**jsdoc + /*@jsdoc * Gets the maximum number of entity packets that the client can send per second. * @function Entities.getPacketsPerSecond * @returns {number} Integer maximum number of entity packets that the client can send per second. @@ -52,7 +52,7 @@ public slots: /// get the max packets per second send rate int getPacketsPerSecond() const { return _packetSender->getPacketsPerSecond(); } - /**jsdoc + /*@jsdoc * Checks whether servers exist for the client to send entity packets to, i.e., whether you are connected to a domain and * its entity server is working. * @function Entities.serversExist @@ -62,7 +62,7 @@ public slots: /// does a server exist to send to bool serversExist() const { return _packetSender->serversExist(); } - /**jsdoc + /*@jsdoc * Checks whether the client has entity packets waiting to be sent. * @function Entities.hasPacketsToSend * @returns {boolean} true if the client has entity packets waiting to be sent, otherwise false. @@ -70,7 +70,7 @@ public slots: /// are there packets waiting in the send queue to be sent bool hasPacketsToSend() const { return _packetSender->hasPacketsToSend(); } - /**jsdoc + /*@jsdoc * Gets the number of entity packets the client has waiting to be sent. * @function Entities.packetsToSendCount * @returns {number} Integer number of entity packets the client has waiting to be sent. @@ -78,7 +78,7 @@ public slots: /// how many packets are there in the send queue waiting to be sent int packetsToSendCount() const { return (int)_packetSender->packetsToSendCount(); } - /**jsdoc + /*@jsdoc * Gets the entity packets per second send rate of the client over its lifetime. * @function Entities.getLifetimePPS * @returns {number} Entity packets per second send rate of the client over its lifetime. @@ -86,7 +86,7 @@ public slots: /// returns the packets per second send rate of this object over its lifetime float getLifetimePPS() const { return _packetSender->getLifetimePPS(); } - /**jsdoc + /*@jsdoc * Gets the entity bytes per second send rate of the client over its lifetime. * @function Entities.getLifetimeBPS * @returns {number} Entity bytes per second send rate of the client over its lifetime. @@ -94,7 +94,7 @@ public slots: /// returns the bytes per second send rate of this object over its lifetime float getLifetimeBPS() const { return _packetSender->getLifetimeBPS(); } - /**jsdoc + /*@jsdoc * Gets the entity packets per second queued rate of the client over its lifetime. * @function Entities.getLifetimePPSQueued * @returns {number} Entity packets per second queued rate of the client over its lifetime. @@ -102,7 +102,7 @@ public slots: /// returns the packets per second queued rate of this object over its lifetime float getLifetimePPSQueued() const { return _packetSender->getLifetimePPSQueued(); } - /**jsdoc + /*@jsdoc * Gets the entity bytes per second queued rate of the client over its lifetime. * @function Entities.getLifetimeBPSQueued * @returns {number} Entity bytes per second queued rate of the client over its lifetime. @@ -110,7 +110,7 @@ public slots: /// returns the bytes per second queued rate of this object over its lifetime float getLifetimeBPSQueued() const { return _packetSender->getLifetimeBPSQueued(); } - /**jsdoc + /*@jsdoc * Gets the lifetime of the client from the first entity packet sent until now, in microseconds. * @function Entities.getLifetimeInUsecs * @returns {number} Lifetime of the client from the first entity packet sent until now, in microseconds. @@ -118,7 +118,7 @@ public slots: /// returns lifetime of this object from first packet sent to now in usecs long long unsigned int getLifetimeInUsecs() const { return _packetSender->getLifetimeInUsecs(); } - /**jsdoc + /*@jsdoc * Gets the lifetime of the client from the first entity packet sent until now, in seconds. * @function Entities.getLifetimeInSeconds * @returns {number} Lifetime of the client from the first entity packet sent until now, in seconds. @@ -126,7 +126,7 @@ public slots: /// returns lifetime of this object from first packet sent to now in secs float getLifetimeInSeconds() const { return _packetSender->getLifetimeInSeconds(); } - /**jsdoc + /*@jsdoc * Gets the total number of entity packets sent by the client over its lifetime. * @function Entities.getLifetimePacketsSent * @returns {number} The total number of entity packets sent by the client over its lifetime. @@ -134,7 +134,7 @@ public slots: /// returns the total packets sent by this object over its lifetime long long unsigned int getLifetimePacketsSent() const { return _packetSender->getLifetimePacketsSent(); } - /**jsdoc + /*@jsdoc * Gets the total bytes of entity packets sent by the client over its lifetime. * @function Entities.getLifetimeBytesSent * @returns {number} The total bytes of entity packets sent by the client over its lifetime. @@ -142,7 +142,7 @@ public slots: /// returns the total bytes sent by this object over its lifetime long long unsigned int getLifetimeBytesSent() const { return _packetSender->getLifetimeBytesSent(); } - /**jsdoc + /*@jsdoc * Gets the total number of entity packets queued by the client over its lifetime. * @function Entities.getLifetimePacketsQueued * @returns {number} The total number of entity packets queued by the client over its lifetime. @@ -150,7 +150,7 @@ public slots: /// returns the total packets queued by this object over its lifetime long long unsigned int getLifetimePacketsQueued() const { return _packetSender->getLifetimePacketsQueued(); } - /**jsdoc + /*@jsdoc * Gets the total bytes of entity packets queued by the client over its lifetime. * @function Entities.getLifetimeBytesQueued * @returns {number} The total bytes of entity packets queued by the client over its lifetime. diff --git a/libraries/oculusMobilePlugin/src/OculusMobileControllerManager.cpp b/libraries/oculusMobilePlugin/src/OculusMobileControllerManager.cpp index 54a796954e..9566cf1b49 100644 --- a/libraries/oculusMobilePlugin/src/OculusMobileControllerManager.cpp +++ b/libraries/oculusMobilePlugin/src/OculusMobileControllerManager.cpp @@ -161,7 +161,7 @@ public: QString getDefaultMappingConfig() const override; void update(float deltaTime, const controller::InputCalibrationData& inputCalibrationData) override; void focusOutEvent() override; - bool triggerHapticPulse(float strength, float duration, controller::Hand hand) override; + bool triggerHapticPulse(float strength, float duration, uint16_t index) override; private: void handlePose(float deltaTime, const controller::InputCalibrationData& inputCalibrationData, @@ -516,12 +516,16 @@ void OculusMobileInputDevice::handleRotationForUntrackedHand(const controller::I pose = pose.transform(controllerToAvatar); } -bool OculusMobileInputDevice::triggerHapticPulse(float strength, float duration, controller::Hand hand) { +bool OculusMobileInputDevice::triggerHapticPulse(float strength, float duration, uint16_t index) { + if (index > 2) { + return false; + } + + controller::Hand hand = (controller::Hand)index; + Locker locker(_lock); bool success = true; - qDebug()<<"AAAA: Haptic duration %f " << duration; - if (hand == controller::BOTH || hand == controller::LEFT) { success &= _hands[0].setHapticFeedback(strength, duration); } @@ -531,7 +535,7 @@ bool OculusMobileInputDevice::triggerHapticPulse(float strength, float duration, return success; } -/**jsdoc +/*@jsdoc *

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

diff --git a/libraries/physics/CMakeLists.txt b/libraries/physics/CMakeLists.txt index c1410a6bfc..ad4900e4ba 100644 --- a/libraries/physics/CMakeLists.txt +++ b/libraries/physics/CMakeLists.txt @@ -12,7 +12,7 @@ include_hifi_library_headers(image) include_hifi_library_headers(ktx) include_hifi_library_headers(gpu) include_hifi_library_headers(hfm) -include_hifi_library_headers(fbx) +include_hifi_library_headers(model-serializers) include_hifi_library_headers(graphics) target_bullet() diff --git a/libraries/physics/src/CharacterController.cpp b/libraries/physics/src/CharacterController.cpp index 777a3d3f87..2eaf771ae2 100755 --- a/libraries/physics/src/CharacterController.cpp +++ b/libraries/physics/src/CharacterController.cpp @@ -696,10 +696,29 @@ void CharacterController::applyMotor(int index, btScalar dt, btVector3& worldVel return; } - // rotate into motor-frame + const bool motorHasRotation = !(motor.rotation == btQuaternion::getIdentity()); btVector3 axis = motor.rotation.getAxis(); btScalar angle = motor.rotation.getAngle(); - btVector3 velocity = worldVelocity.rotate(axis, -angle); + + // Rotate a vector from motor frame to world frame + auto rotateToWorldFrame = [&axis, &angle, &motorHasRotation](const btVector3 vectorInMotorFrame) { + if (motorHasRotation) { + return vectorInMotorFrame.rotate(axis, angle); + } else { + return vectorInMotorFrame; + } + }; + + // Rotate a vector from world frame to motor frame + auto rotateToMotorFrame = [&axis, &angle, &motorHasRotation](const btVector3 vectorInWorldFrame) { + if (motorHasRotation) { + return vectorInWorldFrame.rotate(axis, -angle); + } else { + return vectorInWorldFrame; + } + }; + + btVector3 velocity = rotateToMotorFrame(worldVelocity); int32_t collisionMask = computeCollisionMask(); if (collisionMask == BULLET_COLLISION_MASK_COLLISIONLESS || @@ -712,15 +731,15 @@ void CharacterController::applyMotor(int index, btScalar dt, btVector3& worldVel velocity += tau * (motor.velocity - velocity); // rotate back into world-frame - velocity = velocity.rotate(axis, angle); - _targetVelocity += (tau * motor.velocity).rotate(axis, angle); + velocity = rotateToWorldFrame(velocity); + _targetVelocity += rotateToWorldFrame(tau * motor.velocity); // store the velocity and weight velocities.push_back(velocity); weights.push_back(tau); } else { // compute local UP - btVector3 up = _currentUp.rotate(axis, -angle); + btVector3 up = rotateToMotorFrame(_currentUp); btVector3 motorVelocity = motor.velocity; // save these non-adjusted components for later @@ -729,7 +748,7 @@ void CharacterController::applyMotor(int index, btScalar dt, btVector3& worldVel if (_stepHeight > _minStepHeight && !_steppingUp) { // there is a step --> compute velocity direction to go over step - btVector3 motorVelocityWF = motorVelocity.rotate(axis, angle); + btVector3 motorVelocityWF = rotateToWorldFrame(motorVelocity); if (motorVelocityWF.dot(_stepNormal) < 0.0f) { // the motor pushes against step _steppingUp = true; @@ -764,8 +783,8 @@ void CharacterController::applyMotor(int index, btScalar dt, btVector3& worldVel } // add components back together and rotate into world-frame - velocity = (hVelocity + vVelocity).rotate(axis, angle); - _targetVelocity += maxTau * (hTargetVelocity + vTargetVelocity).rotate(axis, angle); + velocity = rotateToWorldFrame(hVelocity + vVelocity); + _targetVelocity += maxTau * rotateToWorldFrame(hTargetVelocity + vTargetVelocity); // store velocity and weights velocities.push_back(velocity); diff --git a/libraries/physics/src/ObjectActionOffset.cpp b/libraries/physics/src/ObjectActionOffset.cpp index 526eb9f000..4a35be4c09 100644 --- a/libraries/physics/src/ObjectActionOffset.cpp +++ b/libraries/physics/src/ObjectActionOffset.cpp @@ -142,7 +142,7 @@ bool ObjectActionOffset::updateArguments(QVariantMap arguments) { return true; } -/**jsdoc +/*@jsdoc * The "offset" {@link Entities.ActionType|ActionType} moves an entity so that it is a defined distance away from * a target point. * It has arguments in addition to the common {@link Entities.ActionArguments|ActionArguments}: diff --git a/libraries/physics/src/ObjectActionTractor.cpp b/libraries/physics/src/ObjectActionTractor.cpp index 4925faaf2a..a65c0aa66a 100644 --- a/libraries/physics/src/ObjectActionTractor.cpp +++ b/libraries/physics/src/ObjectActionTractor.cpp @@ -338,7 +338,7 @@ bool ObjectActionTractor::updateArguments(QVariantMap arguments) { return true; } -/**jsdoc +/*@jsdoc * The "tractor" {@link Entities.ActionType|ActionType} moves and rotates an entity to a target position and * orientation, optionally relative to another entity. * It has arguments in addition to the common {@link Entities.ActionArguments|ActionArguments}: diff --git a/libraries/physics/src/ObjectActionTravelOriented.cpp b/libraries/physics/src/ObjectActionTravelOriented.cpp index 025c74b96a..d547cf0afc 100644 --- a/libraries/physics/src/ObjectActionTravelOriented.cpp +++ b/libraries/physics/src/ObjectActionTravelOriented.cpp @@ -149,7 +149,7 @@ bool ObjectActionTravelOriented::updateArguments(QVariantMap arguments) { return true; } -/**jsdoc +/*@jsdoc * The "travel-oriented" {@link Entities.ActionType|ActionType} orients an entity to align with its direction of * travel. * It has arguments in addition to the common {@link Entities.ActionArguments|ActionArguments}: diff --git a/libraries/physics/src/ObjectConstraintBallSocket.cpp b/libraries/physics/src/ObjectConstraintBallSocket.cpp index 5b925c9e88..1498aec2b5 100644 --- a/libraries/physics/src/ObjectConstraintBallSocket.cpp +++ b/libraries/physics/src/ObjectConstraintBallSocket.cpp @@ -181,7 +181,7 @@ bool ObjectConstraintBallSocket::updateArguments(QVariantMap arguments) { return true; } -/**jsdoc +/*@jsdoc * The "ball-socket" {@link Entities.ActionType|ActionType} connects two entities with a ball and socket joint. * It has arguments in addition to the common {@link Entities.ActionArguments|ActionArguments}: * diff --git a/libraries/physics/src/ObjectConstraintConeTwist.cpp b/libraries/physics/src/ObjectConstraintConeTwist.cpp index 6763f82773..14d593618a 100644 --- a/libraries/physics/src/ObjectConstraintConeTwist.cpp +++ b/libraries/physics/src/ObjectConstraintConeTwist.cpp @@ -261,7 +261,7 @@ bool ObjectConstraintConeTwist::updateArguments(QVariantMap arguments) { return true; } -/**jsdoc +/*@jsdoc * The "cone-twist" {@link Entities.ActionType|ActionType} connects two entities with a joint that can move * through a cone and can twist. * It has arguments in addition to the common {@link Entities.ActionArguments|ActionArguments}: diff --git a/libraries/physics/src/ObjectConstraintHinge.cpp b/libraries/physics/src/ObjectConstraintHinge.cpp index 3059d82bf3..5bc4c21130 100644 --- a/libraries/physics/src/ObjectConstraintHinge.cpp +++ b/libraries/physics/src/ObjectConstraintHinge.cpp @@ -245,7 +245,7 @@ bool ObjectConstraintHinge::updateArguments(QVariantMap arguments) { return true; } -/**jsdoc +/*@jsdoc * The "hinge" {@link Entities.ActionType|ActionType} lets an entity pivot about an axis or connects two entities * with a hinge joint. * It has arguments in addition to the common {@link Entities.ActionArguments|ActionArguments}: diff --git a/libraries/physics/src/ObjectConstraintSlider.cpp b/libraries/physics/src/ObjectConstraintSlider.cpp index 11374298cf..c64de60da1 100644 --- a/libraries/physics/src/ObjectConstraintSlider.cpp +++ b/libraries/physics/src/ObjectConstraintSlider.cpp @@ -261,7 +261,7 @@ bool ObjectConstraintSlider::updateArguments(QVariantMap arguments) { return true; } -/**jsdoc +/*@jsdoc * The "slider" {@link Entities.ActionType|ActionType} lets an entity slide and rotate along an axis, or connects * two entities that slide and rotate along a shared axis. * It has arguments in addition to the common {@link Entities.ActionArguments|ActionArguments}: diff --git a/libraries/physics/src/ObjectDynamic.cpp b/libraries/physics/src/ObjectDynamic.cpp index 4f7feacbab..6759697832 100644 --- a/libraries/physics/src/ObjectDynamic.cpp +++ b/libraries/physics/src/ObjectDynamic.cpp @@ -93,7 +93,7 @@ bool ObjectDynamic::updateArguments(QVariantMap arguments) { return somethingChanged; } -/**jsdoc +/*@jsdoc * Different entity action types have different arguments: some common to all actions (listed in the table) and some specific * to each {@link Entities.ActionType|ActionType} (linked to below). * diff --git a/libraries/physics/src/ObjectMotionState.h b/libraries/physics/src/ObjectMotionState.h index 415b388e70..d543459cdd 100644 --- a/libraries/physics/src/ObjectMotionState.h +++ b/libraries/physics/src/ObjectMotionState.h @@ -29,7 +29,7 @@ enum PhysicsMotionType { MOTION_TYPE_KINEMATIC // keyframed motion }; -/**jsdoc +/*@jsdoc *

An entity's physics motion type may be one of the following:

*
* diff --git a/libraries/physics/src/ShapeFactory.cpp b/libraries/physics/src/ShapeFactory.cpp index ef5213df8f..5ac33f65bd 100644 --- a/libraries/physics/src/ShapeFactory.cpp +++ b/libraries/physics/src/ShapeFactory.cpp @@ -278,12 +278,6 @@ const btCollisionShape* ShapeFactory::createShapeFromInfo(const ShapeInfo& info) shape = new btBoxShape(glmToBullet(info.getHalfExtents())); } break; - case SHAPE_TYPE_SPHERE: { - glm::vec3 halfExtents = info.getHalfExtents(); - float radius = glm::max(halfExtents.x, glm::max(halfExtents.y, halfExtents.z)); - shape = new btSphereShape(radius); - } - break; case SHAPE_TYPE_MULTISPHERE: { std::vector positions; std::vector radiuses; @@ -297,6 +291,7 @@ const btCollisionShape* ShapeFactory::createShapeFromInfo(const ShapeInfo& info) shape->setMargin(MULTI_SPHERE_MARGIN); } break; + case SHAPE_TYPE_SPHERE: case SHAPE_TYPE_ELLIPSOID: { glm::vec3 halfExtents = info.getHalfExtents(); float radius = halfExtents.x; diff --git a/libraries/platform/src/platform/backend/Platform.cpp b/libraries/platform/src/platform/backend/Platform.cpp index 8b52b9cc29..5c128ba28f 100644 --- a/libraries/platform/src/platform/backend/Platform.cpp +++ b/libraries/platform/src/platform/backend/Platform.cpp @@ -10,7 +10,7 @@ #include "../Platform.h" #include "../PlatformKeys.h" -/**jsdoc +/*@jsdoc * Information on the computer platform as a whole. * @typedef {object} PlatformInfo.PlatformDescription * @property {PlatformInfo.ComputerDescription} computer - Information on the computer. @@ -24,7 +24,7 @@ namespace platform { namespace keys { const char* UNKNOWN = "UNKNOWN"; - /**jsdoc + /*@jsdoc * Information on a CPU. * @typedef {object} PlatformInfo.CPUDescription * @property {string} vendor - The CPU vendor (e.g., "Intel" or "AMD"). @@ -44,7 +44,7 @@ namespace platform { namespace keys { const char* isMaster = "isMaster"; } - /**jsdoc + /*@jsdoc * Information on a GPU. * @typedef {object} PlatformInfo.GPUDescription * @property {string} vendor - The GPU vendor (e.g., "NVIDIA", "AMD", or "Intel"). @@ -69,7 +69,7 @@ namespace platform { namespace keys { const char* isMaster = "isMaster"; } - /**jsdoc + /*@jsdoc * Information on a graphics API. * @typedef {object} PlatformInfo.GraphicsAPIDescription * @property {string} name - The name of the graphics API. @@ -82,7 +82,7 @@ namespace platform { namespace keys { * * @property {PlatformInfo.VulkanAPIDescription[]} [devices] - If a Vulkan API, then the devices provided in the API. */ - /**jsdoc + /*@jsdoc * Information on a Vulkan graphics API. * @typedef {object} PlatformInfo.VulkanAPIDescription * @property {string} @@ -95,13 +95,13 @@ namespace platform { namespace keys { * @property {PlatformInfo.VulkanQueueDescription[]} queues - The Vulkan queues available. * @property {PlatformInfo.VulkanHeapDescription[]} heaps - The Vulkan heaps available. */ - /**jsdoc + /*@jsdoc * Information on a Vulkan queue. * @typedef {object} PlatformInfo.VulkanQueueDescription * @property {string} flags - The Vulkan queue flags. * @property {number} count - The queue count. */ - /**jsdoc + /*@jsdoc * Information on a Vulkan heap. * @typedef {object} PlatformInfo.VulkanHeapDescription * @property {string} flags - The Vulkan heap flags. @@ -147,7 +147,7 @@ namespace platform { namespace keys { } } - /**jsdoc + /*@jsdoc * Information on a network card. * @typedef {object} PlatformInfo.NICDescription * @property {string} name - The name of the network card. @@ -158,7 +158,7 @@ namespace platform { namespace keys { const char* name = "name"; } - /**jsdoc + /*@jsdoc * Information on a display. * @typedef {object} PlatformInfo.DisplayDescription * @property {string} description - The display's description. @@ -196,7 +196,7 @@ namespace platform { namespace keys { const char* isMaster = "isMaster"; } - /**jsdoc + /*@jsdoc * Information on the computer's memory. * @typedef {object} PlatformInfo.MemoryDescription * @property {number} memTotal - The total amount of usable physical memory, in MB. @@ -205,7 +205,7 @@ namespace platform { namespace keys { const char* memTotal = "memTotal"; } - /**jsdoc + /*@jsdoc * Information on the computer. * @typedef {object} PlatformInfo.ComputerDescription * @property {PlatformInfo.ComputerOS} OS - The operating system. @@ -214,7 +214,7 @@ namespace platform { namespace keys { * @property {string} model - The computer model. * @property {PlatformInfo.PlatformTier} profileTier - The platform tier of the computer, profiled at Interface start-up. */ - /**jsdoc + /*@jsdoc *

The computer operating system.

*
* diff --git a/libraries/plugins/src/plugins/SteamClientPlugin.h b/libraries/plugins/src/plugins/SteamClientPlugin.h index e4d765882f..f3ae1193e8 100644 --- a/libraries/plugins/src/plugins/SteamClientPlugin.h +++ b/libraries/plugins/src/plugins/SteamClientPlugin.h @@ -40,7 +40,7 @@ public: virtual int getSteamVRBuildID() = 0; }; -/**jsdoc +/*@jsdoc * The Steam API provides facilities for working with the Steam version of Interface. * * @namespace Steam @@ -63,14 +63,14 @@ public: public slots: - /**jsdoc + /*@jsdoc * Gets whether Interface is running under Steam. * @function Steam.isRunning * @returns {boolean} true if Interface is running under Steam, false if it isn't. */ bool isRunning() const { return _plugin && _plugin->isRunning(); } - /**jsdoc + /*@jsdoc * Opens Steam's "Choose Friends to invite" dialog if Interface is running under Steam. * @function Steam.openInviteOverlay * @example diff --git a/libraries/pointers/src/Pick.h b/libraries/pointers/src/Pick.h index 9e6c5f9898..557fc93750 100644 --- a/libraries/pointers/src/Pick.h +++ b/libraries/pointers/src/Pick.h @@ -20,7 +20,7 @@ #include #include -/**jsdoc +/*@jsdoc *

The type of an intersection.

*
Invite Steam friends to join you in Vircadia.
* @@ -76,7 +76,7 @@ public: PickQuery(const PickFilter& filter, const float maxDistance, const bool enabled); virtual ~PickQuery() = default; - /**jsdoc + /*@jsdoc * The PickType API provides constant numeric values that represent different types of picks. * * @namespace PickType @@ -93,7 +93,7 @@ public: * collisions. */ - /**jsdoc + /*@jsdoc *

A type of pick.

*
* diff --git a/libraries/procedural/src/procedural/MaterialCacheScriptingInterface.h b/libraries/procedural/src/procedural/MaterialCacheScriptingInterface.h index 2e0d319b7a..d3d5846c67 100644 --- a/libraries/procedural/src/procedural/MaterialCacheScriptingInterface.h +++ b/libraries/procedural/src/procedural/MaterialCacheScriptingInterface.h @@ -23,7 +23,7 @@ class MaterialCacheScriptingInterface : public ScriptableResourceCache, public D // Properties are copied over from ResourceCache (see ResourceCache.h for reason). - /**jsdoc + /*@jsdoc * The MaterialCache API manages material cache resources. * * @namespace MaterialCache diff --git a/libraries/procedural/src/procedural/Procedural.h b/libraries/procedural/src/procedural/Procedural.h index a198017a99..3b50a34fa0 100644 --- a/libraries/procedural/src/procedural/Procedural.h +++ b/libraries/procedural/src/procedural/Procedural.h @@ -27,12 +27,12 @@ using UniformLambdas = std::list>; const size_t MAX_PROCEDURAL_TEXTURE_CHANNELS{ 4 }; -/**jsdoc +/*@jsdoc * An object containing user-defined uniforms for communicating data to shaders. * @typedef {object} ProceduralUniforms */ -/**jsdoc +/*@jsdoc * The data used to define a Procedural shader material. * @typedef {object} ProceduralData * @property {number} version=1 - The version of the procedural shader. diff --git a/libraries/procedural/src/procedural/ProceduralMaterialCache.cpp b/libraries/procedural/src/procedural/ProceduralMaterialCache.cpp index 4ce609fd35..58fec1f002 100644 --- a/libraries/procedural/src/procedural/ProceduralMaterialCache.cpp +++ b/libraries/procedural/src/procedural/ProceduralMaterialCache.cpp @@ -31,7 +31,7 @@ void NetworkMaterialResource::downloadFinished(const QByteArray& data) { finishedLoading(true); } -/**jsdoc +/*@jsdoc *

An RGB or SRGB color value.

*
* @@ -72,12 +72,12 @@ bool NetworkMaterialResource::parseJSONColor(const QJsonValue& array, glm::vec3& return false; } -/**jsdoc +/*@jsdoc * 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[]|string} materials - The details of the material or materials, or the ID of another - * material entity. + * Material entity. */ NetworkMaterialResource::ParsedMaterials NetworkMaterialResource::parseJSONMaterials(const QJsonDocument& materialJSON, const QUrl& baseUrl) { ParsedMaterials toReturn; @@ -123,7 +123,7 @@ NetworkMaterialResource::ParsedMaterials NetworkMaterialResource::parseMaterialF return toReturn; } -/**jsdoc +/*@jsdoc * A material used in a {@link Entities.MaterialResource|MaterialResource}. * @typedef {object} Entities.Material * @property {string} name="" - A name for the material. Supported by all material models. @@ -149,12 +149,14 @@ NetworkMaterialResource::ParsedMaterials NetworkMaterialResource::parseMaterialF * 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, or an entity ID. - * 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. - * 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. - * 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 a 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 a 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 a 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: *
    @@ -189,24 +191,27 @@ NetworkMaterialResource::ParsedMaterials NetworkMaterialResource::parseMaterialF * @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, or an entity ID. - * 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 a 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, or an entity ID. - * 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 a 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, or an entity ID. - * 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. 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. - * 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. 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. + * @property {string} normalMap - The URL of the normal texture image, or an entity ID. An entity ID may be that of an Image + * or a 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 a 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 a 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 a 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 a 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. diff --git a/libraries/render-utils/CMakeLists.txt b/libraries/render-utils/CMakeLists.txt index 833d78bb74..4c444bcd15 100644 --- a/libraries/render-utils/CMakeLists.txt +++ b/libraries/render-utils/CMakeLists.txt @@ -3,7 +3,7 @@ set(TARGET_NAME render-utils) # pull in the resources.qrc file qt5_add_resources(QT_RESOURCES_FILE "${CMAKE_CURRENT_SOURCE_DIR}/res/fonts/fonts.qrc") setup_hifi_library(Gui Network Qml Quick Script) -link_hifi_libraries(shared task ktx gpu shaders graphics graphics-scripting material-networking model-networking render animation fbx image procedural) +link_hifi_libraries(shared task ktx gpu shaders graphics graphics-scripting material-networking model-networking render animation model-serializers image procedural) include_hifi_library_headers(audio) include_hifi_library_headers(networking) include_hifi_library_headers(octree) diff --git a/libraries/render-utils/src/MeshPartPayload.h b/libraries/render-utils/src/MeshPartPayload.h index b5cff41bf8..1a3a898582 100644 --- a/libraries/render-utils/src/MeshPartPayload.h +++ b/libraries/render-utils/src/MeshPartPayload.h @@ -92,7 +92,7 @@ private: bool _cauterized { false }; bool _cullWithParent { false }; QVector _renderWithZones; - BillboardMode _billboardMode; + BillboardMode _billboardMode { BillboardMode::NONE }; uint64_t _created; Transform _localTransform; diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 9fa822994c..dd3bcd0587 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -443,7 +443,7 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g } } - /**jsdoc + /*@jsdoc * A submesh intersection point. * @typedef {object} SubmeshIntersection * @property {Vec3} worldIntersectionPoint - The intersection point in world coordinates. diff --git a/libraries/script-engine/CMakeLists.txt b/libraries/script-engine/CMakeLists.txt index 9052cb89e9..6def6c185f 100644 --- a/libraries/script-engine/CMakeLists.txt +++ b/libraries/script-engine/CMakeLists.txt @@ -7,7 +7,7 @@ if (NOT ANDROID) target_quazip() endif () -link_hifi_libraries(shared networking shaders material-networking model-networking recording avatars fbx entities controllers animation audio midi) +link_hifi_libraries(shared networking shaders material-networking model-networking recording avatars model-serializers entities controllers animation audio midi) include_hifi_library_headers(gl) include_hifi_library_headers(hfm) include_hifi_library_headers(gpu) 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.cpp b/libraries/script-engine/src/AssetScriptingInterface.cpp index f088ad7a38..8f97f1ce33 100644 --- a/libraries/script-engine/src/AssetScriptingInterface.cpp +++ b/libraries/script-engine/src/AssetScriptingInterface.cpp @@ -102,7 +102,7 @@ void AssetScriptingInterface::setMapping(QString path, QString hash, QScriptValu setMappingRequest->start(); } -/**jsdoc +/*@jsdoc * The success or failure of an {@link Assets.downloadData} call. * @typedef {object} Assets.DownloadDataError * @property {string} errorMessage - "" if the download was successful, otherwise a description of the error. @@ -244,7 +244,7 @@ void AssetScriptingInterface::deleteAsset(QScriptValue options, QScriptValue sco jsVerify(false, "TODO: deleteAsset API"); } -/**jsdoc +/*@jsdoc * Source and download options for {@link Assets.getAsset}. * @typedef {object} Assets.GetOptions * @property {boolean} [decompress=false] - true to gunzip decompress the downloaded data. Synonym: @@ -252,7 +252,7 @@ void AssetScriptingInterface::deleteAsset(QScriptValue options, QScriptValue sco * @property {Assets.ResponseType} [responseType="text"] - The desired result type. * @property {string} url - The mapped path or hash to download. May have a leading "atp:". */ -/**jsdoc +/*@jsdoc * Result value returned by {@link Assets.getAsset}. * @typedef {object} Assets.GetResult * @property {number} [byteLength] - The number of bytes in the downloaded content in response. @@ -320,12 +320,12 @@ void AssetScriptingInterface::getAsset(QScriptValue options, QScriptValue scope, } } -/**jsdoc +/*@jsdoc * Source options for {@link Assets.resolveAsset}. * @typedef {object} Assets.ResolveOptions * @property {string} url - The hash or path to resolve. May have a leading "atp:". */ -/**jsdoc +/*@jsdoc * Result value returned by {@link Assets.resolveAsset}. *

    Note: If resolving a hash, a file of that hash need not be present on the asset server for the hash to resolve.

    * @typedef {object} Assets.ResolveResult @@ -348,13 +348,13 @@ void AssetScriptingInterface::resolveAsset(QScriptValue options, QScriptValue sc jsPromiseReady(getAssetInfo(asset), scope, callback); } -/**jsdoc +/*@jsdoc * Content and decompression options for {@link Assets.decompressData}. * @typedef {object} Assets.DecompressOptions * @property {ArrayBuffer} data - The data to decompress. * @property {Assets.ResponseType} [responseType=text] - The type of decompressed data to return. */ -/**jsdoc +/*@jsdoc * Result value returned by {@link Assets.decompressData}. * @typedef {object} Assets.DecompressResult * @property {number} [byteLength] - The number of bytes in the decompressed data. @@ -388,7 +388,7 @@ namespace { const int32_t MAX_GZIP_COMPRESSION_LEVEL = 9; } -/**jsdoc +/*@jsdoc * Content and compression options for {@link Assets.compressData}. * @typedef {object} Assets.CompressOptions * @property {string|ArrayBuffer} data - The data to compress. @@ -396,7 +396,7 @@ namespace { * use the default gzip compression level, 0 means no compression, and 9 means maximum * compression. */ -/**jsdoc +/*@jsdoc * Result value returned by {@link Assets.compressData}. * @typedef {object} Assets.CompressResult * @property {number} [byteLength] - The number of bytes in the compressed data. @@ -412,7 +412,7 @@ void AssetScriptingInterface::compressData(QScriptValue options, QScriptValue sc jsPromiseReady(compressBytes(dataByteArray, level), scope, callback); } -/**jsdoc +/*@jsdoc * Content and upload options for {@link Assets.putAsset}. * @typedef {object} Assets.PutOptions * @property {boolean} [compress=false] - true to gzip compress the content for upload and storage, @@ -423,7 +423,7 @@ void AssetScriptingInterface::compressData(QScriptValue options, QScriptValue sc *

    Note: The asset server destroys any unmapped SHA256-named file at server restart. Either set the mapping path * with this property or use {@link Assets.setMapping} to set a path-to-hash mapping for the uploaded file.

    */ -/**jsdoc +/*@jsdoc * Result value returned by {@link Assets.putAsset}. * @typedef {object} Assets.PutResult * @property {number} [byteLength] - The number of bytes in the hash file stored on the asset server. @@ -483,7 +483,7 @@ void AssetScriptingInterface::putAsset(QScriptValue options, QScriptValue scope, } } -/**jsdoc +/*@jsdoc * Source for {@link Assets.queryCacheMeta}. * @typedef {object} Assets.QueryCacheMetaOptions * @property {string} url - The URL of the cached asset to get information on. Must start with "atp:" or @@ -495,7 +495,7 @@ void AssetScriptingInterface::queryCacheMeta(QScriptValue options, QScriptValue jsPromiseReady(Parent::queryCacheMeta(url), scope, callback); } -/**jsdoc +/*@jsdoc * Source and retrieval options for {@link Assets.loadFromCache}. * @typedef {object} Assets.LoadFromCacheOptions * @property {boolean} [decompress=false] - true to gunzip decompress the cached data. Synonym: @@ -538,7 +538,7 @@ bool AssetScriptingInterface::canWriteCacheValue(const QUrl& url) { return true; } -/**jsdoc +/*@jsdoc * The data to save to the cache and cache options for {@link Assets.saveToCache}. * @typedef {object} Assets.SaveToCacheOptions * @property {string|ArrayBuffer} data - The data to save to the cache. diff --git a/libraries/script-engine/src/AssetScriptingInterface.h b/libraries/script-engine/src/AssetScriptingInterface.h index 3ba7632cd0..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 @@ -24,7 +27,7 @@ #include #include -/**jsdoc +/*@jsdoc * The Assets API provides facilities for interacting with the domain's asset server and the client cache. *

    Assets are stored in the asset server in files with SHA256 names. These files are mapped to user-friendly URLs of the * format: atp:/path/filename. The assets may optionally be baked, in which case a request for the original @@ -41,20 +44,21 @@ * @hifi-server-entity * @hifi-assignment-client */ +/// Provides the Assets scripting API class AssetScriptingInterface : public BaseAssetScriptingInterface, QScriptable { Q_OBJECT public: using Parent = BaseAssetScriptingInterface; AssetScriptingInterface(QObject* parent = nullptr); - /**jsdoc + /*@jsdoc * Called when an {@link Assets.uploadData} call is complete. * @callback Assets~uploadDataCallback * @param {string} url - The raw URL of the file that the content is stored in, with atp: as the scheme and * the SHA256 hash as the filename (with no extension). * @param {string} hash - The SHA256 hash of the content. */ - /**jsdoc + /*@jsdoc * Uploads content to the asset server, storing it in a SHA256-named file. *

    Note: The asset server destroys any unmapped SHA256-named file at server restart. Use {@link Assets.setMapping} to * set a path-to-hash mapping for the new file.

    @@ -74,13 +78,13 @@ public: */ Q_INVOKABLE void uploadData(QString data, QScriptValue callback); - /**jsdoc + /*@jsdoc * Called when an {@link Assets.downloadData} call is complete. * @callback Assets~downloadDataCallback * @param {string} data - The content that was downloaded. * @param {Assets.DownloadDataError} error - The success or failure of the download. */ - /**jsdoc + /*@jsdoc * Downloads content from the asset server, from a SHA256-named file. * @function Assets.downloadData * @param {string} url - The raw URL of asset to download: atp: followed by the assets's SHA256 hash. @@ -110,12 +114,12 @@ public: */ Q_INVOKABLE void downloadData(QString url, QScriptValue callback); - /**jsdoc + /*@jsdoc * Called when an {@link Assets.setMapping} call is complete. * @callback Assets~setMappingCallback * @param {string} error - null if the path-to-hash mapping was set, otherwise a description of the error. */ - /**jsdoc + /*@jsdoc * Sets a path-to-hash mapping within the asset server. * @function Assets.setMapping * @param {string} path - A user-friendly path for the file in the asset server, without leading "atp:". @@ -124,13 +128,13 @@ public: */ Q_INVOKABLE void setMapping(QString path, QString hash, QScriptValue callback); - /**jsdoc + /*@jsdoc * Called when an {@link Assets.getMapping} call is complete. * @callback Assets~getMappingCallback * @param {string} error - null if the path was found, otherwise a description of the error. * @param {string} hash - The hash value if the path was found, "" if it wasn't. */ - /**jsdoc + /*@jsdoc * Gets the hash for a path within the asset server. The hash is for the unbaked or baked version of the * asset, according to the asset server setting for the particular path. * @function Assets.getMapping @@ -148,13 +152,13 @@ public: */ Q_INVOKABLE void getMapping(QString path, QScriptValue callback); - /**jsdoc + /*@jsdoc * Called when an {@link Assets.setBakingEnabled} call is complete. * @callback Assets~setBakingEnabledCallback * @param {string} error - null if baking was successfully enabled or disabled, otherwise a description of the * error. */ - /**jsdoc + /*@jsdoc * Sets whether or not to bake an asset in the asset server. * @function Assets.setBakingEnabled * @param {string} path - The path to a file in the asset server. @@ -172,7 +176,7 @@ public: Q_INVOKABLE void sendFakedHandshake(); #endif - /**jsdoc + /*@jsdoc * Details of a callback function. * @typedef {object} Assets.CallbackDetails * @property {object} scope - The scope that the callback function is defined in. This object is bound to @@ -184,13 +188,13 @@ public: * identifier, it must be a member of scope. */ - /**jsdoc + /*@jsdoc * Called when an {@link Assets.getAsset} call is complete. * @callback Assets~getAssetCallback * @param {string} error - null if the content was downloaded, otherwise a description of the error. * @param {Assets.GetResult} result - Information on and the content downloaded. */ - /**jsdoc + /*@jsdoc * Downloads content from the asset server. * @function Assets.getAsset * @param {string|Assets.GetOptions} source - What to download and download options. If a string, the mapped path or hash @@ -220,14 +224,14 @@ public: */ Q_INVOKABLE void getAsset(QScriptValue options, QScriptValue scope, QScriptValue callback = QScriptValue()); - /**jsdoc + /*@jsdoc * Called when an {@link Assets.putAsset} call is complete. * @callback Assets~putAssetCallback * @param {string} error - null if the content was uploaded and any path-to-hash mapping set, otherwise a * description of the error. * @param {Assets.PutResult} result - Information on the content uploaded. */ - /**jsdoc + /*@jsdoc * Uploads content to the asset server and sets a path-to-hash mapping. * @function Assets.putAsset * @param {string|Assets.PutOptions} options - The content to upload and upload options. If a string, the value of the @@ -257,14 +261,14 @@ public: */ Q_INVOKABLE void putAsset(QScriptValue options, QScriptValue scope, QScriptValue callback = QScriptValue()); - /**jsdoc + /*@jsdoc * Called when an {@link Assets.deleteAsset} call is complete. *

    Not implemented: This type is not implemented yet.

    * @callback Assets~deleteAssetCallback * @param {string} error - null if the content was deleted, otherwise a description of the error. * @param {Assets.DeleteResult} result - Information on the content deleted. */ - /**jsdoc + /*@jsdoc * Deletes content from the asset server. *

    Not implemented: This method is not implemented yet.

    * @function Assets.deleteAsset @@ -274,13 +278,13 @@ public: */ Q_INVOKABLE void deleteAsset(QScriptValue options, QScriptValue scope, QScriptValue callback = QScriptValue()); - /**jsdoc + /*@jsdoc * Called when an {@link Assets.resolveAsset} call is complete. * @callback Assets~resolveAssetCallback * @param {string} error - null if the asset hash or path was resolved, otherwise a description of the error. * @param {Assets.ResolveResult} result - Information on the hash or path resolved. */ - /**jsdoc + /*@jsdoc * Resolves and returns information on a hash or a path in the asset server. * @function Assets.resolveAsset * @param {string|Assets.ResolveOptions} source - The hash or path to resolve if a string, otherwise an object specifying @@ -308,13 +312,13 @@ public: */ Q_INVOKABLE void resolveAsset(QScriptValue options, QScriptValue scope, QScriptValue callback = QScriptValue()); - /**jsdoc + /*@jsdoc * Called when an {@link Assets.decompressData} call is complete. * @callback Assets~decompressDataCallback * @param {string} error - null if the data was successfully compressed, otherwise a description of the error. * @param {Assets.DecompressResult} result - Information on and the decompressed data. */ - /**jsdoc + /*@jsdoc * Decompresses data in memory using gunzip. * @function Assets.decompressData * @param {Assets.DecompressOptions} source - What to decompress and decompression options. @@ -329,13 +333,13 @@ public: */ Q_INVOKABLE void decompressData(QScriptValue options, QScriptValue scope, QScriptValue callback = QScriptValue()); - /**jsdoc + /*@jsdoc * Called when an {@link Assets.compressData} call is complete. * @callback Assets~compressDataCallback * @param {string} error - null if the data was successfully compressed, otherwise a description of the error. * @param {Assets.CompressResult} result - Information on and the compressed data. */ - /**jsdoc + /*@jsdoc * Compresses data in memory using gzip. * @function Assets.compressData * @param {string|ArrayBuffer|Assets.CompressOptions} source - What to compress and compression options. If a string or @@ -351,14 +355,14 @@ public: */ Q_INVOKABLE void compressData(QScriptValue options, QScriptValue scope, QScriptValue callback = QScriptValue()); - /**jsdoc + /*@jsdoc * Initializes the cache if it isn't already initialized. * @function Assets.initializeCache * @returns {boolean} true if the cache is initialized, false if it isn't. */ Q_INVOKABLE bool initializeCache(); - /**jsdoc + /*@jsdoc * Checks whether the script can write to the cache. * @function Assets.canWriteCacheValue * @param {string} url - Not used. @@ -369,14 +373,14 @@ public: */ Q_INVOKABLE bool canWriteCacheValue(const QUrl& url); - /**jsdoc + /*@jsdoc * Called when a {@link Assets.getCacheStatus} call is complete. * @callback Assets~getCacheStatusCallback * @param {string} error - null if the cache status was retrieved without error, otherwise a description of * the error. * @param {Assets.GetCacheStatusResult} result - Details of the current cache status. */ - /**jsdoc + /*@jsdoc * Gets the current cache status. * @function Assets.getCacheStatus * @param {object|Assets.CallbackDetails|Assets~getCacheStatusCallback} scopeOrCallback - If an object, then the scope that @@ -398,13 +402,13 @@ public: jsPromiseReady(Parent::getCacheStatus(), scope, callback); } - /**jsdoc + /*@jsdoc * Called when {@link Assets.queryCacheMeta} is complete. * @callback Assets~queryCacheMetaCallback * @param {string} error - null if the URL has a valid cache entry, otherwise a description of the error. * @param {Assets.CacheItemMetaData} result - Information on an asset in the cache. */ - /**jsdoc + /*@jsdoc * Gets information about the status of an asset in the cache. * @function Assets.queryCacheMeta * @param {string|Assets.QueryCacheMetaOptions} path - The URL of the cached asset to get information on if a string, @@ -436,14 +440,14 @@ public: */ Q_INVOKABLE void queryCacheMeta(QScriptValue options, QScriptValue scope, QScriptValue callback = QScriptValue()); - /**jsdoc + /*@jsdoc * Called when an {@link Assets.loadFromCache} call is complete. * @callback Assets~loadFromCacheCallback * @param {string} error - null if the cache item was successfully retrieved, otherwise a description of the * error. * @param {Assets.LoadFromCacheResult} result - Information on and the retrieved data. */ - /**jsdoc + /*@jsdoc * Retrieves data from the cache directly, without downloading it. * @function Assets.loadFromCache * @param {string|Assets.LoadFromCacheOptions} options - The URL of the asset to load from the cache if a string, otherwise @@ -476,14 +480,14 @@ public: */ Q_INVOKABLE void loadFromCache(QScriptValue options, QScriptValue scope, QScriptValue callback = QScriptValue()); - /**jsdoc + /*@jsdoc * Called when an {@link Assets.saveToCache} call is complete. * @callback Assets~saveToCacheCallback * @param {string} error - null if the asset data was successfully saved to the cache, otherwise a description * of the error. * @param {Assets.SaveToCacheResult} result - Information on the cached data. */ - /**jsdoc + /*@jsdoc * Saves asset data to the cache directly, without downloading it from a URL. *

    Note: Can only be used in Interface, avatar, and assignment client scripts.

    * @function Assets.saveToCache @@ -515,7 +519,7 @@ public: */ Q_INVOKABLE void saveToCache(QScriptValue options, QScriptValue scope, QScriptValue callback = QScriptValue()); - /**jsdoc + /*@jsdoc * Saves asset data to the cache directly, without downloading it from a URL. *

    Note: Can only be used in Interface, avatar, and assignment client scripts.

    * @function Assets.saveToCache @@ -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 0553679f8a..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 @@ -40,7 +44,7 @@ public: return _localAudioInterface->getAudioSolo().getUUIDs(); } - /**jsdoc + /*@jsdoc * Adds avatars to the audio solo list. If the audio solo list is not empty, only audio from the avatars in the list is * played. * @function Audio.addToSoloList @@ -77,7 +81,7 @@ public: _localAudioInterface->getAudioSolo().addUUIDs(uuidList); } - /**jsdoc + /*@jsdoc * Removes avatars from the audio solo list. If the audio solo list is not empty, only audio from the avatars in the list * is played. * @function Audio.removeFromSoloList @@ -87,7 +91,7 @@ public: _localAudioInterface->getAudioSolo().removeUUIDs(uuidList); } - /**jsdoc + /*@jsdoc * Clears the audio solo list. * @function Audio.resetSoloList */ @@ -95,7 +99,7 @@ public: _localAudioInterface->getAudioSolo().reset(); } - /**jsdoc + /*@jsdoc * Gets whether your microphone audio is echoed back to you from the server. When enabled, microphone audio is echoed only * if you're unmuted or are using push-to-talk. * @function Audio.getServerEcho @@ -104,7 +108,7 @@ public: */ Q_INVOKABLE bool getServerEcho(); - /**jsdoc + /*@jsdoc * Sets whether your microphone audio is echoed back to you from the server. When enabled, microphone audio is echoed * only if you're unmuted or are using push-to-talk. * @function Audio.setServerEcho @@ -113,14 +117,14 @@ public: */ Q_INVOKABLE void setServerEcho(bool serverEcho); - /**jsdoc + /*@jsdoc * Toggles the echoing of microphone audio back to you from the server. When enabled, microphone audio is echoed only if * you're unmuted or are using push-to-talk. * @function Audio.toggleServerEcho */ Q_INVOKABLE void toggleServerEcho(); - /**jsdoc + /*@jsdoc * Gets whether your microphone audio is echoed back to you by the client. When enabled, microphone audio is echoed * even if you're muted or not using push-to-talk. * @function Audio.getLocalEcho @@ -129,7 +133,7 @@ public: */ Q_INVOKABLE bool getLocalEcho(); - /**jsdoc + /*@jsdoc * Sets whether your microphone audio is echoed back to you by the client. When enabled, microphone audio is echoed * even if you're muted or not using push-to-talk. * @function Audio.setLocalEcho @@ -143,7 +147,7 @@ public: */ Q_INVOKABLE void setLocalEcho(bool localEcho); - /**jsdoc + /*@jsdoc * Toggles the echoing of microphone audio back to you by the client. When enabled, microphone audio is echoed even if * you're muted or not using push-to-talk. * @function Audio.toggleLocalEcho @@ -156,7 +160,7 @@ protected: // these methods are protected to stop C++ callers from calling, but invokable from script - /**jsdoc + /*@jsdoc * Starts playing or "injecting" the content of an audio file. The sound is played globally (sent to the audio * mixer) so that everyone hears it, unless the injectorOptions has localOnly set to * true in which case only the client hears the sound played. No sound is played if sent to the audio mixer @@ -191,7 +195,7 @@ protected: */ Q_INVOKABLE ScriptAudioInjector* playSound(SharedSoundPointer sound, const AudioInjectorOptions& injectorOptions = AudioInjectorOptions()); - /**jsdoc + /*@jsdoc * Starts playing the content of an audio file locally (isn't sent to the audio mixer). This is the same as calling * {@link Audio.playSound} with {@link AudioInjector.AudioInjectorOptions} localOnly set true and * the specified position. @@ -202,7 +206,7 @@ protected: */ Q_INVOKABLE ScriptAudioInjector* playSystemSound(SharedSoundPointer sound); - /**jsdoc + /*@jsdoc * Sets whether the audio input should be used in stereo. If the audio input doesn't support stereo then setting a value * of true has no effect. * @function Audio.setStereoInput @@ -210,7 +214,7 @@ protected: */ Q_INVOKABLE void setStereoInput(bool stereo); - /**jsdoc + /*@jsdoc * Gets whether the audio input is used in stereo. * @function Audio.isStereoInput * @returns {boolean} true if the audio input is used in stereo, otherwise false. @@ -219,7 +223,7 @@ protected: signals: - /**jsdoc + /*@jsdoc * Triggered when the client is muted by the mixer because their loudness value for the noise background has reached the * threshold set for the domain (in the server settings). * @function Audio.mutedByMixer @@ -227,7 +231,7 @@ signals: */ void mutedByMixer(); - /**jsdoc + /*@jsdoc * Triggered when the client is muted by the mixer because they're within a certain radius (50m) of someone who requested * the mute through Developer > Audio > Mute Environment. * @function Audio.environmentMuted @@ -235,21 +239,21 @@ signals: */ void environmentMuted(); - /**jsdoc + /*@jsdoc * Triggered when the client receives its first packet from the audio mixer. * @function Audio.receivedFirstPacket * @returns {Signal} */ void receivedFirstPacket(); - /**jsdoc + /*@jsdoc * Triggered when the client is disconnected from the audio mixer. * @function Audio.disconnected * @returns {Signal} */ void disconnected(); - /**jsdoc + /*@jsdoc * Triggered when the noise gate is opened. The input audio signal is no longer blocked (fully attenuated) because it has * risen above an adaptive threshold set just above the noise floor. Only occurs if Audio.noiseReduction is * true. @@ -258,7 +262,7 @@ signals: */ void noiseGateOpened(); - /**jsdoc + /*@jsdoc * Triggered when the noise gate is closed. The input audio signal is blocked (fully attenuated) because it has fallen * below an adaptive threshold set just above the noise floor. Only occurs if Audio.noiseReduction is * true. @@ -267,7 +271,7 @@ signals: */ void noiseGateClosed(); - /**jsdoc + /*@jsdoc * Triggered when a frame of audio input is processed. * @function Audio.inputReceived * @param {Int16Array} inputSamples - The audio input processed. @@ -275,7 +279,7 @@ signals: */ void inputReceived(const QByteArray& inputSamples); - /**jsdoc + /*@jsdoc * Triggered when the input audio use changes between mono and stereo. * @function Audio.isStereoInputChanged * @param {boolean} isStereo - true if the input audio is stereo, otherwise false. @@ -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 7eec44d103..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 @@ -26,7 +29,7 @@ #include #include -/**jsdoc +/*@jsdoc * The console API provides program logging facilities. * * @namespace console @@ -37,12 +40,12 @@ * @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: - /**jsdoc + /*@jsdoc * Logs an "INFO" message to the program log and triggers {@link Script.infoMessage}. * The message logged is "INFO -" followed by the message values separated by spaces. * @function console.info @@ -50,7 +53,7 @@ public: */ static QScriptValue info(QScriptContext* context, QScriptEngine* engine); - /**jsdoc + /*@jsdoc * Logs a message to the program log and triggers {@link Script.printedMessage}. * The message logged is the message values separated by spaces. *

    If a {@link console.group} is in effect, the message is indented by an amount proportional to the group level.

    @@ -68,7 +71,7 @@ public: */ static QScriptValue log(QScriptContext* context, QScriptEngine* engine); - /**jsdoc + /*@jsdoc * Logs a message to the program log and triggers {@link Script.printedMessage}. * The message logged is the message values separated by spaces. * @function console.debug @@ -76,7 +79,7 @@ public: */ static QScriptValue debug(QScriptContext* context, QScriptEngine* engine); - /**jsdoc + /*@jsdoc * Logs a "WARNING" message to the program log and triggers {@link Script.warningMessage}. * The message logged is "WARNING - " followed by the message values separated by spaces. * @function console.warn @@ -84,7 +87,7 @@ public: */ static QScriptValue warn(QScriptContext* context, QScriptEngine* engine); - /**jsdoc + /*@jsdoc * Logs an "ERROR" message to the program log and triggers {@link Script.errorMessage}. * The message logged is "ERROR - " followed by the message values separated by spaces. * @function console.error @@ -92,7 +95,7 @@ public: */ static QScriptValue error(QScriptContext* context, QScriptEngine* engine); - /**jsdoc + /*@jsdoc * A synonym of {@link console.error}. * Logs an "ERROR" message to the program log and triggers {@link Script.errorMessage}. * The message logged is "ERROR - " followed by the message values separated by spaces. @@ -101,7 +104,7 @@ public: */ static QScriptValue exception(QScriptContext* context, QScriptEngine* engine); - /**jsdoc + /*@jsdoc * Logs an "ERROR" message to the program log and triggers {@link Script.errorMessage}, if a test condition fails. * The message logged is "ERROR - Assertion failed : " followed by the message values separated by spaces. *

    Note: Script execution continues whether or not the test condition fails.

    @@ -124,7 +127,7 @@ public: // Note: Is registered in the script engine as "assert" static QScriptValue assertion(QScriptContext* context, QScriptEngine* engine); - /**jsdoc + /*@jsdoc * Logs a message to the program log and triggers {@link Script.printedMessage}, then starts indenting subsequent * {@link console.log} messages until a {@link console.groupEnd}. Groups may be nested. * @function console.group @@ -152,7 +155,7 @@ public: */ static QScriptValue group(QScriptContext* context, QScriptEngine* engine); - /**jsdoc + /*@jsdoc * Has the same behavior as {@link console.group}. * Logs a message to the program log and triggers {@link Script.printedMessage}, then starts indenting subsequent * {@link console.log} messages until a {@link console.groupEnd}. Groups may be nested. @@ -161,7 +164,7 @@ public: */ static QScriptValue groupCollapsed(QScriptContext* context, QScriptEngine* engine); - /**jsdoc + /*@jsdoc * Finishes a group of indented {@link console.log} messages. * @function console.groupEnd */ @@ -169,7 +172,7 @@ public: public slots: - /**jsdoc + /*@jsdoc * Starts a timer, logs a message to the program log, and triggers {@link Script.printedMessage}. The message logged has * the timer name and "Timer started". * @function console.time @@ -192,7 +195,7 @@ public slots: * // MyTimer: 1001ms */ void time(QString labelName); - /**jsdoc + /*@jsdoc * Finishes a timer, logs a message to the program log, and triggers {@link Script.printedMessage}. The message logged has * the timer name and the number of milliseconds since the timer was started. * @function console.timeEnd @@ -200,13 +203,13 @@ public slots: */ void timeEnd(QString labelName); - /**jsdoc + /*@jsdoc * Logs the JavaScript call stack at the point of call to the program log. * @function console.trace */ void trace(); - /**jsdoc + /*@jsdoc * Clears the Developer > Scripting > Script Log debug window. * @function console.clear */ @@ -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 ce93921403..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 @@ -16,7 +19,7 @@ #include #include -/**jsdoc +/*@jsdoc * The File API provides some facilities for working with the file system. * * @namespace File @@ -27,7 +30,7 @@ * @hifi-server-entity * @hifi-assignment-client */ - +/// Provides the File scripting API class FileScriptingInterface : public QObject { Q_OBJECT @@ -36,7 +39,7 @@ public: public slots: - /**jsdoc + /*@jsdoc * Extracts a filename from a URL, where the filename is specified in the query part of the URL as filename=. * @function File.convertUrlToPath * @param {string} url - The URL to extract the filename from. @@ -47,7 +50,7 @@ public slots: */ QString convertUrlToPath(QUrl url); - /**jsdoc + /*@jsdoc * Unzips a file in the local file system to a new, unique temporary directory. * @function File.runUnzip * @param {string} path - The path of the zip file in the local file system. May have a leading "file:///". @@ -79,7 +82,7 @@ public slots: */ void runUnzip(QString path, QUrl url, bool autoAdd, bool isZip, bool isBlocks); - /**jsdoc + /*@jsdoc * Creates a new, unique directory for temporary use. * @function File.getTempDir * @returns {string} The path of the newly created temporary directory. @@ -90,7 +93,7 @@ public slots: signals: - /**jsdoc + /*@jsdoc * Triggered when {@link File.runUnzip|runUnzip} completes. * @function File.unzipResult * @param {string} zipFile - The file that was unzipped. @@ -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.cpp b/libraries/script-engine/src/KeyEvent.cpp index b0e622a774..b565b1f3aa 100644 --- a/libraries/script-engine/src/KeyEvent.cpp +++ b/libraries/script-engine/src/KeyEvent.cpp @@ -150,7 +150,7 @@ KeyEvent::operator QKeySequence() const { return QKeySequence(resultCode); } -/**jsdoc +/*@jsdoc * A keyboard key event. * @typedef {object} KeyEvent * @property {number} key - The Qt keyboard code of the key pressed. For a list of keyboard codes, see 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 33fd889541..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 @@ -21,7 +24,7 @@ #include #include "RegisteredMetaTypes.h" -/**jsdoc +/*@jsdoc * The Mat4 API provides facilities for generating and using 4 x 4 matrices. These matrices are typically used to * represent transforms (scale, rotate, and translate) that convert one coordinate system into another, or perspective * transforms that convert 3D points into screen coordinates. @@ -35,14 +38,13 @@ * @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 public slots: - /**jsdoc + /*@jsdoc * Multiplies two matrices. * @function Mat4(0).multiply * @param {Mat4} m1 - The first matrix. @@ -52,7 +54,7 @@ public slots: glm::mat4 multiply(const glm::mat4& m1, const glm::mat4& m2) const; - /**jsdoc + /*@jsdoc * Creates a matrix that represents a rotation and translation. * @function Mat4(0).createFromRotAndTrans * @param {Quat} rot - The rotation. @@ -70,7 +72,7 @@ public slots: */ glm::mat4 createFromRotAndTrans(const glm::quat& rot, const glm::vec3& trans) const; - /**jsdoc + /*@jsdoc * Creates a matrix that represents a scale, rotation, and translation. * @function Mat4(0).createFromScaleRotAndTrans * @param {Vec3} scale - The scale. @@ -90,7 +92,7 @@ public slots: */ glm::mat4 createFromScaleRotAndTrans(const glm::vec3& scale, const glm::quat& rot, const glm::vec3& trans) const; - /**jsdoc + /*@jsdoc * Creates a matrix from columns of values. * @function Mat4(0).createFromColumns * @param {Vec4} col0 - Column 0 values. @@ -112,7 +114,7 @@ public slots: */ glm::mat4 createFromColumns(const glm::vec4& col0, const glm::vec4& col1, const glm::vec4& col2, const glm::vec4& col3) const; - /**jsdoc + /*@jsdoc * Creates a matrix from an array of values. * @function Mat4(0).createFromArray * @param {number[]} arr - The array of values, starting with column 0. @@ -134,7 +136,7 @@ public slots: glm::mat4 createFromArray(const QVector& floats) const; - /**jsdoc + /*@jsdoc * Extracts the translation from a matrix. * @function Mat4(0).extractTranslation * @param {Mat4} m - The matrix. @@ -151,7 +153,7 @@ public slots: */ glm::vec3 extractTranslation(const glm::mat4& m) const; - /**jsdoc + /*@jsdoc * Extracts the rotation from a matrix. * @function Mat4(0).extractRotation * @param {Mat4} m - The matrix. @@ -168,7 +170,7 @@ public slots: */ glm::quat extractRotation(const glm::mat4& m) const; - /**jsdoc + /*@jsdoc * Extracts the scale from a matrix. * @function Mat4(0).extractScale * @param {Mat4} m - The matrix. @@ -186,7 +188,7 @@ public slots: glm::vec3 extractScale(const glm::mat4& m) const; - /**jsdoc + /*@jsdoc * Transforms a point into a new coordinate system: the point value is scaled, rotated, and translated. * @function Mat4(0).transformPoint * @param {Mat4} m - The transform to the new coordinate system. @@ -205,7 +207,7 @@ public slots: */ glm::vec3 transformPoint(const glm::mat4& m, const glm::vec3& point) const; - /**jsdoc + /*@jsdoc * Transforms a vector into a new coordinate system: the vector is scaled and rotated. * @function Mat4(0).transformVector * @param {Mat4} m - The transform to the new coordinate system. @@ -225,7 +227,7 @@ public slots: glm::vec3 transformVector(const glm::mat4& m, const glm::vec3& vector) const; - /**jsdoc + /*@jsdoc * Calculates the inverse of a matrix. * @function Mat4(0).inverse * @param {Mat4} m - The matrix. @@ -246,7 +248,7 @@ public slots: glm::mat4 inverse(const glm::mat4& m) const; - /**jsdoc + /*@jsdoc * Gets the "forward" direction that the camera would face if its orientation was set to the rotation contained in a * matrix. The High Fidelity camera has axes x = right, y = up, -z = forward. *

    Synonym for {@link Mat4(0).getForward|getForward}.

    @@ -257,7 +259,7 @@ public slots: // redundant, calls getForward which better describes the returned vector as a direction glm::vec3 getFront(const glm::mat4& m) const { return getForward(m); } - /**jsdoc + /*@jsdoc * Gets the "forward" direction that the camera would face if its orientation was set to the rotation contained in a * matrix. The High Fidelity camera has axes x = right, y = up, -z = forward. * @function Mat4(0).getForward @@ -273,7 +275,7 @@ public slots: */ glm::vec3 getForward(const glm::mat4& m) const; - /**jsdoc + /*@jsdoc * Gets the "right" direction that the camera would have if its orientation was set to the rotation contained in a matrix. * The High Fidelity camera has axes x = right, y = up, -z = forward. * @function Mat4(0).getRight @@ -282,7 +284,7 @@ public slots: */ glm::vec3 getRight(const glm::mat4& m) const; - /**jsdoc + /*@jsdoc * Gets the "up" direction that the camera would have if its orientation was set to the rotation contained in a matrix. The * High Fidelity camera has axes x = right, y = up, -z = forward. * @function Mat4(0).getUp @@ -292,7 +294,7 @@ public slots: glm::vec3 getUp(const glm::mat4& m) const; - /**jsdoc + /*@jsdoc * Prints a matrix to the program log as a label followed by the matrix's values. * @function Mat4(0).print * @param {string} label - The label to print. @@ -321,3 +323,5 @@ public slots: }; #endif // hifi_Mat4_h + +/// @} diff --git a/libraries/script-engine/src/MenuItemProperties.cpp b/libraries/script-engine/src/MenuItemProperties.cpp index af9c4a3d0a..bff1609db5 100644 --- a/libraries/script-engine/src/MenuItemProperties.cpp +++ b/libraries/script-engine/src/MenuItemProperties.cpp @@ -50,7 +50,7 @@ QScriptValue menuItemPropertiesToScriptValue(QScriptEngine* engine, const MenuIt return obj; } -/**jsdoc +/*@jsdoc * A set of properties that can be passed to {@link Menu.addMenuItem} to create a new menu item. * * If none of the properties, position, beforeItem, afterItem, or grouping 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 39170bb370..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 @@ -17,7 +20,7 @@ #include class QScriptEngine; -/**jsdoc +/*@jsdoc * The Model API provides the ability to manipulate meshes. You can get the meshes for an entity using * {@link Entities.getMeshes}, or create a new mesh using {@link Model.newMesh}. *

    See also, the {@link Graphics} API.

    @@ -32,13 +35,14 @@ class QScriptEngine; * * @deprecated This API is deprecated. Use the {@link Graphics} API instead. */ +/// Provides the Model scripting interface class ModelScriptingInterface : public QObject { Q_OBJECT public: ModelScriptingInterface(QObject* parent); - /**jsdoc + /*@jsdoc * Exports meshes to an OBJ format model. * @function Model.meshToOBJ * @param {MeshProxy[]} meshes - The meshes to export. @@ -46,7 +50,7 @@ public: */ Q_INVOKABLE QString meshToOBJ(MeshProxyList in); - /**jsdoc + /*@jsdoc * Combines multiple meshes into one. * @function Model.appendMeshes * @param {MeshProxy[]} meshes - The meshes to combine. @@ -54,7 +58,7 @@ public: */ Q_INVOKABLE QScriptValue appendMeshes(MeshProxyList in); - /**jsdoc + /*@jsdoc * Transforms the vertices in a mesh. * @function Model.transformMesh * @param {Mat4} transform - The transform to apply. @@ -63,7 +67,7 @@ public: */ Q_INVOKABLE QScriptValue transformMesh(glm::mat4 transform, MeshProxy* meshProxy); - /**jsdoc + /*@jsdoc * Creates a new mesh. * @function Model.newMesh * @param {Vec3[]} vertices - The vertices in the mesh. @@ -75,7 +79,7 @@ public: const QVector& normals, const QVector& faces); - /**jsdoc + /*@jsdoc * Gets the number of vertices in a mesh. * @function Model.getVertexCount * @param {MeshProxy} mesh - The mesh to count the vertices in. @@ -83,7 +87,7 @@ public: */ Q_INVOKABLE QScriptValue getVertexCount(MeshProxy* meshProxy); - /**jsdoc + /*@jsdoc * Gets the position of a vertex in a mesh. * @function Model.getVertex * @param {MeshProxy} mesh - The mesh. @@ -97,3 +101,5 @@ private: }; #endif // hifi_ModelScriptingInterface_h + +/// @} diff --git a/libraries/script-engine/src/MouseEvent.cpp b/libraries/script-engine/src/MouseEvent.cpp index 1bace0425f..6adb39a29b 100644 --- a/libraries/script-engine/src/MouseEvent.cpp +++ b/libraries/script-engine/src/MouseEvent.cpp @@ -60,7 +60,7 @@ MouseEvent::MouseEvent(const QMouseEvent& event) : } } -/**jsdoc +/*@jsdoc * A controller mouse movement or button event. * @typedef {object} MouseEvent * @property {number} x - Integer x-coordinate of the event on the Interface window or HMD HUD. 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 c1eaa97797..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 @@ -22,7 +25,7 @@ #include -/**jsdoc +/*@jsdoc * A quaternion value. See also the {@link Quat(0)|Quat} API. * @typedef {object} Quat * @property {number} x - Imaginary component i. @@ -31,7 +34,7 @@ * @property {number} w - Real component. */ -/**jsdoc +/*@jsdoc * The Quat API provides facilities for generating and manipulating quaternions. * Quaternions should be used in preference to Euler angles wherever possible because quaternions don't suffer from the problem * of gimbal lock. @@ -51,15 +54,14 @@ * 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) public slots: - /**jsdoc + /*@jsdoc * Multiplies two quaternions. * @function Quat(0).multiply * @param {Quat} q1 - The first quaternion. @@ -74,7 +76,7 @@ public slots: */ glm::quat multiply(const glm::quat& q1, const glm::quat& q2); - /**jsdoc + /*@jsdoc * Normalizes a quaternion. * @function Quat(0).normalize * @param {Quat} q - The quaternion to normalize. @@ -90,7 +92,7 @@ public slots: */ glm::quat normalize(const glm::quat& q); - /**jsdoc + /*@jsdoc * Calculates the conjugate of a quaternion. For a unit quaternion, its conjugate is the same as its * {@link Quat(0).inverse|Quat.inverse}. * @function Quat(0).conjugate @@ -106,7 +108,7 @@ public slots: */ glm::quat conjugate(const glm::quat& q); - /**jsdoc + /*@jsdoc * Calculates a camera orientation given an eye position, point of interest, and "up" direction. The camera's negative * z-axis is the forward direction. The result has zero roll about its forward direction with respect to the given "up" * direction. @@ -122,7 +124,7 @@ public slots: */ glm::quat lookAt(const glm::vec3& eye, const glm::vec3& center, const glm::vec3& up); - /**jsdoc + /*@jsdoc * Calculates a camera orientation given an eye position and point of interest. The camera's negative z-axis is the forward * direction. The result has zero roll about its forward direction. * @function Quat(0).lookAtSimple @@ -138,7 +140,7 @@ public slots: */ glm::quat lookAtSimple(const glm::vec3& eye, const glm::vec3& center); - /**jsdoc + /*@jsdoc * Calculates the shortest rotation from a first vector onto a second. * @function Quat(0).rotationBetween * @param {Vec3} v1 - The first vector. @@ -155,7 +157,7 @@ public slots: */ glm::quat rotationBetween(const glm::vec3& v1, const glm::vec3& v2); - /**jsdoc + /*@jsdoc * Generates a quaternion from a {@link Vec3} of Euler angles in degrees. * @function Quat(0).fromVec3Degrees * @param {Vec3} vector - A vector of three Euler angles in degrees, the angles being the rotations about the x, y, and z @@ -169,7 +171,7 @@ public slots: */ glm::quat fromVec3Degrees(const glm::vec3& vec3); - /**jsdoc + /*@jsdoc * Generates a quaternion from a {@link Vec3} of Euler angles in radians. * @function Quat(0).fromVec3Radians * @param {Vec3} vector - A vector of three Euler angles in radians, the angles being the rotations about the x, y, and z @@ -180,7 +182,7 @@ public slots: */ glm::quat fromVec3Radians(const glm::vec3& vec3); - /**jsdoc + /*@jsdoc * Generates a quaternion from pitch, yaw, and roll values in degrees. * @function Quat(0).fromPitchYawRollDegrees * @param {number} pitch - The pitch angle in degrees. @@ -192,7 +194,7 @@ public slots: */ glm::quat fromPitchYawRollDegrees(float pitch, float yaw, float roll); - /**jsdoc + /*@jsdoc * Generates a quaternion from pitch, yaw, and roll values in radians. * @function Quat(0).fromPitchYawRollRadians * @param {number} pitch - The pitch angle in radians. @@ -204,7 +206,7 @@ public slots: */ glm::quat fromPitchYawRollRadians(float pitch, float yaw, float roll); - /**jsdoc + /*@jsdoc * Calculates the inverse of a quaternion. For a unit quaternion, its inverse is the same as its * {@link Quat(0).conjugate|Quat.conjugate}. * @function Quat(0).inverse @@ -220,7 +222,7 @@ public slots: */ glm::quat inverse(const glm::quat& q); - /**jsdoc + /*@jsdoc * Gets the "front" direction that the camera would face if its orientation was set to the quaternion value. * This is a synonym for {@link Quat(0).getForward|Quat.getForward}. * The Vircadia camera has axes x = right, y = up, -z = forward. @@ -230,7 +232,7 @@ public slots: */ glm::vec3 getFront(const glm::quat& orientation) { return getForward(orientation); } - /**jsdoc + /*@jsdoc * Gets the "forward" direction that the camera would face if its orientation was set to the quaternion value. * This is a synonym for {@link Quat(0).getFront|Quat.getFront}. * The Vircadia camera has axes x = right, y = up, -z = forward. @@ -243,7 +245,7 @@ public slots: */ glm::vec3 getForward(const glm::quat& orientation); - /**jsdoc + /*@jsdoc * Gets the "right" direction that the camera would have if its orientation was set to the quaternion value. * The Vircadia camera has axes x = right, y = up, -z = forward. * @function Quat(0).getRight @@ -252,7 +254,7 @@ public slots: */ glm::vec3 getRight(const glm::quat& orientation); - /**jsdoc + /*@jsdoc * Gets the "up" direction that the camera would have if its orientation was set to the quaternion value. * The Vircadia camera has axes x = right, y = up, -z = forward. * @function Quat(0).getUp @@ -261,7 +263,7 @@ public slots: */ glm::vec3 getUp(const glm::quat& orientation); - /**jsdoc + /*@jsdoc * Calculates the Euler angles for the quaternion, in degrees. (The "safe" in the name signifies that the angle results * will not be garbage even when the rotation is particularly difficult to decompose with pitches around +/-90 degrees.) * @function Quat(0).safeEulerAngles @@ -274,7 +276,7 @@ public slots: */ glm::vec3 safeEulerAngles(const glm::quat& orientation); - /**jsdoc + /*@jsdoc * Generates a quaternion given an angle to rotate through and an axis to rotate about. * @function Quat(0).angleAxis * @param {number} angle - The angle to rotate through, in degrees. @@ -287,7 +289,7 @@ public slots: */ glm::quat angleAxis(float angle, const glm::vec3& v); - /**jsdoc + /*@jsdoc * Gets the rotation axis for a quaternion. * @function Quat(0).axis * @param {Quat} q - The quaternion. @@ -301,7 +303,7 @@ public slots: */ glm::vec3 axis(const glm::quat& orientation); - /**jsdoc + /*@jsdoc * Gets the rotation angle for a quaternion. * @function Quat(0).angle * @param {Quat} q - The quaternion. @@ -317,7 +319,7 @@ public slots: // spherical linear interpolation // alpha: 0.0 to 1.0? - /**jsdoc + /*@jsdoc * Computes a spherical linear interpolation between two rotations, safely handling two rotations that are very similar. * See also, {@link Quat(0).slerp|Quat.slerp}. * @function Quat(0).mix @@ -337,7 +339,7 @@ public slots: */ glm::quat mix(const glm::quat& q1, const glm::quat& q2, float alpha); - /**jsdoc + /*@jsdoc * Computes a spherical linear interpolation between two rotations, for rotations that are not very similar. * See also, {@link Quat(0).mix|Quat.mix}. * @function Quat(0).slerp @@ -350,7 +352,7 @@ public slots: */ glm::quat slerp(const glm::quat& q1, const glm::quat& q2, float alpha); - /**jsdoc + /*@jsdoc * Computes a spherical quadrangle interpolation between two rotations along a path oriented toward two other rotations. * Equivalent to: Quat.slerp(Quat.slerp(q1, q2, alpha), Quat.slerp(s1, s2, alpha), 2 * alpha * (1.0 - alpha)). * @function Quat(0).squad @@ -365,7 +367,7 @@ public slots: */ glm::quat squad(const glm::quat& q1, const glm::quat& q2, const glm::quat& s1, const glm::quat& s2, float h); - /**jsdoc + /*@jsdoc * Calculates the dot product of two quaternions. The closer the quaternions are to each other the more non-zero the value * is (either positive or negative). Identical unit rotations have a dot product of +/-1. * @function Quat(0).dot @@ -386,7 +388,7 @@ public slots: */ float dot(const glm::quat& q1, const glm::quat& q2); - /**jsdoc + /*@jsdoc * Prints to the program log a text label followed by a quaternion's pitch, yaw, and roll Euler angles. * @function Quat(0).print * @param {string} label - The label to print. @@ -404,7 +406,7 @@ public slots: */ void print(const QString& label, const glm::quat& q, bool asDegrees = false); - /**jsdoc + /*@jsdoc * Tests whether two quaternions are equal. *

    Note: The quaternions must be exactly equal in order for true to be returned; it is * often better to use {@link Quat(0).dot|Quat.dot} and test for closeness to +/-1.

    @@ -426,7 +428,7 @@ public slots: */ bool equal(const glm::quat& q1, const glm::quat& q2); - /**jsdoc + /*@jsdoc * Cancels out the roll and pitch component of a quaternion so that its completely horizontal with a yaw pointing in the * given quaternion's direction. * @function Quat(0).cancelOutRollAndPitch @@ -446,7 +448,7 @@ public slots: */ glm::quat cancelOutRollAndPitch(const glm::quat& q); - /**jsdoc + /*@jsdoc * Cancels out the roll component of a quaternion so that its horizontal axis is level. * @function Quat(0).cancelOutRoll * @param {Quat} orientation - A quaternion representing an orientation. @@ -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 fd9c2d64e6..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 @@ -23,7 +26,7 @@ class QScriptEngine; class QScriptValue; -/**jsdoc +/*@jsdoc * The Recording API makes and plays back recordings of voice and avatar movements. Playback may be done on a * user's avatar or an assignment client agent (see the {@link Agent} API). * @@ -34,6 +37,7 @@ class QScriptValue; * @hifi-avatar * @hifi-assignment-client */ +/// Provides the Recording scripting interface class RecordingScriptingInterface : public QObject, public Dependency { Q_OBJECT @@ -42,14 +46,14 @@ public: public slots: - /**jsdoc + /*@jsdoc * Called when a {@link Recording.loadRecording} call is complete. * @callback Recording~loadRecordingCallback * @param {boolean} success - true if the recording has successfully been loaded, false if it * hasn't. * @param {string} url - The URL of the recording that was requested to be loaded. */ - /**jsdoc + /*@jsdoc * Loads a recording so that it is ready for playing. * @function Recording.loadRecording * @param {string} url - The ATP, HTTP, or file system URL of the recording to load. @@ -71,33 +75,33 @@ public slots: void loadRecording(const QString& url, QScriptValue callback = QScriptValue()); - /**jsdoc + /*@jsdoc * Starts playing the recording currently loaded or paused. * @function Recording.startPlaying */ void startPlaying(); - /**jsdoc + /*@jsdoc * Pauses playback of the recording currently playing. Use {@link Recording.startPlaying|startPlaying} to resume playback * or {@link Recording.stopPlaying|stopPlaying} to stop playback. * @function Recording.pausePlayer */ void pausePlayer(); - /**jsdoc + /*@jsdoc * Stops playing the recording currently playing or paused. * @function Recording.stopPlaying */ void stopPlaying(); - /**jsdoc + /*@jsdoc * Gets whether a recording is currently playing. * @function Recording.isPlaying * @returns {boolean} true if a recording is being played, false if one isn't. */ bool isPlaying() const; - /**jsdoc + /*@jsdoc * Gets whether recording playback is currently paused. * @function Recording.isPaused * @returns {boolean} true if recording playback is currently paused, false if it isn't. @@ -105,14 +109,14 @@ public slots: bool isPaused() const; - /**jsdoc + /*@jsdoc * Gets the current playback time in the loaded recording, in seconds. * @function Recording.playerElapsed * @returns {number} The current playback time in the loaded recording, in seconds. */ float playerElapsed() const; - /**jsdoc + /*@jsdoc * Gets the length of the loaded recording, in seconds. * @function Recording.playerLength * @returns {number} The length of the recording currently loaded, in seconds @@ -120,28 +124,28 @@ public slots: float playerLength() const; - /**jsdoc + /*@jsdoc * Sets the playback audio volume. * @function Recording.setPlayerVolume * @param {number} volume - The playback audio volume, range 0.01.0. */ void setPlayerVolume(float volume); - /**jsdoc + /*@jsdoc *

    Not implemented: This method is not implemented yet.

    * @function Recording.setPlayerAudioOffset * @param {number} audioOffset - Audio offset. */ void setPlayerAudioOffset(float audioOffset); - /**jsdoc + /*@jsdoc * Sets the current playback time in the loaded recording. * @function Recording.setPlayerTime * @param {number} time - The current playback time, in seconds. */ void setPlayerTime(float time); - /**jsdoc + /*@jsdoc * Sets whether playback should repeat in a loop. * @function Recording.setPlayerLoop * @param {boolean} loop - true if playback should repeat, false if it shouldn't. @@ -149,7 +153,7 @@ public slots: void setPlayerLoop(bool loop); - /**jsdoc + /*@jsdoc * Sets whether recording playback will use the display name that the recording was made with. * @function Recording.setPlayerUseDisplayName * @param {boolean} useDisplayName - true to have recording playback use the display name that the recording @@ -157,7 +161,7 @@ public slots: */ void setPlayerUseDisplayName(bool useDisplayName); - /**jsdoc + /*@jsdoc *

    Not used.

    * @function Recording.setPlayerUseAttachments * @param {boolean} useAttachments - Use attachments. @@ -165,7 +169,7 @@ public slots: */ void setPlayerUseAttachments(bool useAttachments); - /**jsdoc + /*@jsdoc *

    Not used.

    * @function Recording.setPlayerUseHeadModel * @param {boolean} useHeadModel - Use head model. @@ -173,7 +177,7 @@ public slots: */ void setPlayerUseHeadModel(bool useHeadModel); - /**jsdoc + /*@jsdoc * Sets whether recording playback will use the avatar model that the recording was made with. * @function Recording.setPlayerUseSkeletonModel * @param {boolean} useSkeletonModel - true to have recording playback use the avatar model that the recording @@ -181,7 +185,7 @@ public slots: */ void setPlayerUseSkeletonModel(bool useSkeletonModel); - /**jsdoc + /*@jsdoc * Sets whether recordings are played at the current avatar location or the recorded location. * @function Recording.setPlayFromCurrentLocation * @param {boolean} playFromCurrentLocation - true to play recordings at the current avatar location, @@ -190,7 +194,7 @@ public slots: void setPlayFromCurrentLocation(bool playFromCurrentLocation); - /**jsdoc + /*@jsdoc * Gets whether recording playback will use the display name that the recording was made with. * @function Recording.getPlayerUseDisplayName * @returns {boolean} true if recording playback will use the display name that the recording was made with, @@ -198,7 +202,7 @@ public slots: */ bool getPlayerUseDisplayName() { return _useDisplayName; } - /**jsdoc + /*@jsdoc *

    Not used.

    * @function Recording.getPlayerUseAttachments * @returns {boolean} Use attachments. @@ -206,7 +210,7 @@ public slots: */ bool getPlayerUseAttachments() { return _useAttachments; } - /**jsdoc + /*@jsdoc *

    Not used.

    * @function Recording.getPlayerUseHeadModel * @returns {boolean} Use head model. @@ -214,7 +218,7 @@ public slots: */ bool getPlayerUseHeadModel() { return _useHeadModel; } - /**jsdoc + /*@jsdoc * Gets whether recording playback will use the avatar model that the recording was made with. * @function Recording.getPlayerUseSkeletonModel * @returns {boolean} true if recording playback will use the avatar model that the recording was made with, @@ -222,7 +226,7 @@ public slots: */ bool getPlayerUseSkeletonModel() { return _useSkeletonModel; } - /**jsdoc + /*@jsdoc * Gets whether recordings are played at the current avatar location or the recorded location. * @function Recording.getPlayFromCurrentLocation * @returns {boolean} true if recordings are played at the current avatar location, false if @@ -231,13 +235,13 @@ public slots: bool getPlayFromCurrentLocation() { return _playFromCurrentLocation; } - /**jsdoc + /*@jsdoc * Starts making a recording. * @function Recording.startRecording */ void startRecording(); - /**jsdoc + /*@jsdoc * Stops making a recording. The recording may be saved using {@link Recording.saveRecording|saveRecording} or * {@link Recording.saveRecordingToAsset|saveRecordingToAsset}, or immediately played back with * {@link Recording.loadLastRecording|loadLastRecording}. @@ -245,7 +249,7 @@ public slots: */ void stopRecording(); - /**jsdoc + /*@jsdoc * Gets whether a recording is currently being made. * @function Recording.isRecording * @returns {boolean} true if a recording is currently being made, false if one isn't. @@ -253,7 +257,7 @@ public slots: bool isRecording() const; - /**jsdoc + /*@jsdoc * Gets the duration of the recording currently being made or recently made, in seconds. * @function Recording.recorderElapsed * @returns {number} The duration of the recording currently being made or recently made, in seconds. @@ -261,7 +265,7 @@ public slots: float recorderElapsed() const; - /**jsdoc + /*@jsdoc * Gets the default directory that recordings are saved in. * @function Recording.getDefaultRecordingSaveDirectory * @returns {string} The default recording save directory. @@ -270,7 +274,7 @@ public slots: */ QString getDefaultRecordingSaveDirectory(); - /**jsdoc + /*@jsdoc * Saves the most recently made recording to a file. * @function Recording.saveRecording * @param {string} filename - The path and name of the file to save the recording to. @@ -289,13 +293,13 @@ public slots: */ void saveRecording(const QString& filename); - /**jsdoc + /*@jsdoc * Called when a {@link Recording.saveRecordingToAsset} call is complete. * @callback Recording~saveRecordingToAssetCallback * @param {string} url - The URL of the recording stored in the asset server if successful, "" if * unsuccessful. The URL has atp: as the scheme and the SHA256 hash as the filename (with no extension). */ - /**jsdoc + /*@jsdoc * Saves the most recently made recording to the domain's asset server. * @function Recording.saveRecordingToAsset * @param {Recording~saveRecordingToAssetCallback} callback - The function to call upon completion. @@ -334,7 +338,7 @@ public slots: */ bool saveRecordingToAsset(QScriptValue getClipAtpUrl); - /**jsdoc + /*@jsdoc * Loads the most recently made recording and plays it back on your avatar. * @function Recording.loadLastRecording * @example
@@ -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 ce205bdf3c..6c65ed5244 100644 --- a/libraries/script-engine/src/SceneScriptingInterface.h +++ b/libraries/script-engine/src/SceneScriptingInterface.h @@ -9,13 +9,16 @@ // 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 #include #include -/**jsdoc +/*@jsdoc * The Scene API provides some control over what is rendered. * * @namespace Scene @@ -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 @@ -42,7 +46,7 @@ public: signals: - /**jsdoc + /*@jsdoc * Triggered when whether or not avatars are rendered changes. * @function Scene.shouldRenderAvatarsChanged * @param {boolean} shouldRenderAvatars - true if avatars are rendered, false if they aren't. @@ -54,7 +58,7 @@ signals: */ void shouldRenderAvatarsChanged(bool shouldRenderAvatars); - /**jsdoc + /*@jsdoc * Triggered when whether or not entities are rendered changes. * @function Scene.shouldRenderEntitiesChanged * @param {boolean} shouldRenderEntities - true if entities (domain, avatar, and local) are rendered, @@ -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 5f086019de..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 @@ -16,7 +19,7 @@ #include -/**jsdoc +/*@jsdoc * Plays or "injects" the content of an audio file. * *

Create using {@link Audio} API methods.

@@ -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 @@ -46,13 +50,13 @@ public: ~ScriptAudioInjector(); public slots: - /**jsdoc + /*@jsdoc * Stops current playback, if any, and starts playing from the beginning. * @function AudioInjector.restart */ void restart() { DependencyManager::get()->restart(_injector); } - /**jsdoc + /*@jsdoc * Stops audio playback. * @function AudioInjector.stop * @example
@@ -72,28 +76,28 @@ public slots: */ void stop() { DependencyManager::get()->stop(_injector); } - /**jsdoc + /*@jsdoc * Gets the current configuration of the audio injector. * @function AudioInjector.getOptions * @returns {AudioInjector.AudioInjectorOptions} Configuration of how the injector plays the audio. */ AudioInjectorOptions getOptions() const { return DependencyManager::get()->getOptions(_injector); } - /**jsdoc + /*@jsdoc * Configures how the injector plays the audio. * @function AudioInjector.setOptions * @param {AudioInjector.AudioInjectorOptions} options - Configuration of how the injector plays the audio. */ void setOptions(const AudioInjectorOptions& options) { DependencyManager::get()->setOptions(_injector, options); } - /**jsdoc + /*@jsdoc * Gets the loudness of the most recent frame of audio played. * @function AudioInjector.getLoudness * @returns {number} The loudness of the most recent frame of audio played, range 0.01.0. */ float getLoudness() const { return DependencyManager::get()->getLoudness(_injector); } - /**jsdoc + /*@jsdoc * Gets whether or not the audio is currently playing. * @function AudioInjector.isPlaying * @returns {boolean} true if the audio is currently playing, otherwise false. @@ -116,7 +120,7 @@ public slots: signals: - /**jsdoc + /*@jsdoc * Triggered when the audio has finished playing. * @function AudioInjector.finished * @returns {Signal} @@ -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 e553672b02..417e6d94e5 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -36,8 +36,6 @@ #include #include -#include - #include #include #include @@ -327,96 +325,6 @@ void ScriptEngine::disconnectNonEssentialSignals() { } } -void ScriptEngine::runDebuggable() { - static QMenuBar* menuBar { nullptr }; - static QMenu* scriptDebugMenu { nullptr }; - static size_t scriptMenuCount { 0 }; - if (!scriptDebugMenu) { - for (auto window : qApp->topLevelWidgets()) { - auto mainWindow = qobject_cast(window); - if (mainWindow) { - menuBar = mainWindow->menuBar(); - break; - } - } - if (menuBar) { - scriptDebugMenu = menuBar->addMenu("Script Debug"); - } - } - - init(); - _isRunning = true; - _debuggable = true; - _debugger = new QScriptEngineDebugger(this); - _debugger->attachTo(this); - - QMenu* parentMenu = scriptDebugMenu; - QMenu* scriptMenu { nullptr }; - if (parentMenu) { - ++scriptMenuCount; - scriptMenu = parentMenu->addMenu(_fileNameString); - scriptMenu->addMenu(_debugger->createStandardMenu(qApp->activeWindow())); - } else { - qWarning() << "Unable to add script debug menu"; - } - - QScriptValue result = evaluate(_scriptContents, _fileNameString); - - _lastUpdate = usecTimestampNow(); - QTimer* timer = new QTimer(this); - connect(this, &ScriptEngine::finished, [this, timer, parentMenu, scriptMenu] { - if (scriptMenu) { - parentMenu->removeAction(scriptMenu->menuAction()); - --scriptMenuCount; - if (0 == scriptMenuCount) { - menuBar->removeAction(scriptDebugMenu->menuAction()); - scriptDebugMenu = nullptr; - } - } - disconnect(timer); - }); - - connect(timer, &QTimer::timeout, [this, timer] { - if (_isFinished) { - if (!_isRunning) { - return; - } - stopAllTimers(); // make sure all our timers are stopped if the script is ending - - emit scriptEnding(); - emit finished(_fileNameString, qSharedPointerCast(sharedFromThis())); - _isRunning = false; - - emit runningStateChanged(); - emit doneRunning(); - - timer->deleteLater(); - return; - } - - qint64 now = usecTimestampNow(); - // we check for 'now' in the past in case people set their clock back - if (_lastUpdate < now) { - float deltaTime = (float)(now - _lastUpdate) / (float)USECS_PER_SECOND; - if (!(_isFinished || _isStopping)) { - emit update(deltaTime); - } - } - _lastUpdate = now; - - // only clear exceptions if we are not in the middle of evaluating - if (!isEvaluating() && hasUncaughtException()) { - qCWarning(scriptengine) << __FUNCTION__ << "---------- UNCAUGHT EXCEPTION --------"; - qCWarning(scriptengine) << "runDebuggable" << uncaughtException().toString(); - logException(__FUNCTION__); - clearExceptions(); - } - }); - - timer->start(10); -} - - void ScriptEngine::runInThread() { Q_ASSERT_X(!_isThreaded, "ScriptEngine::runInThread()", "runInThread should not be called more than once"); @@ -470,7 +378,10 @@ void ScriptEngine::waitTillDoneRunning(bool shutdown) { // We should never be waiting (blocking) on our own thread assert(workerThread != QThread::currentThread()); -#ifdef Q_OS_MAC +#if 0 + // 26 Feb 2021 - Disabled this OSX-specific code because it causes OSX to crash on shutdown; without this code, OSX + // doesn't crash on shutdown. Qt 5.12.3 and Qt 5.15.2. + // // On mac, don't call QCoreApplication::processEvents() here. This is to prevent // [NSApplication terminate:] from prematurely destroying the static destructors // while we are waiting for the scripts to shutdown. We will pump the message @@ -585,12 +496,6 @@ void ScriptEngine::loadURL(const QUrl& scriptURL, bool reload) { _scriptContents = scriptContents; - { - static const QString DEBUG_FLAG("#debug"); - if (QRegularExpression(DEBUG_FLAG).match(scriptContents).hasMatch()) { - _debuggable = true; - } - } emit scriptLoaded(url); }, reload, maxRetries); } @@ -672,7 +577,7 @@ static void scriptableResourceFromScriptValue(const QScriptValue& value, Scripta resource = static_cast(value.toQObject()); } -/**jsdoc +/*@jsdoc * The Resource API provides values that define the possible loading states of a resource. * * @namespace Resource @@ -794,7 +699,7 @@ void ScriptEngine::init() { QScriptValue webSocketConstructorValue = newFunction(WebSocketClass::constructor); globalObject().setProperty("WebSocket", webSocketConstructorValue); - /**jsdoc + /*@jsdoc * Prints a message to the program log and emits {@link Script.printedMessage}. * The message logged is the message values separated by spaces. *

Alternatively, you can use {@link Script.print} or one of the {@link console} API methods.

@@ -1094,7 +999,7 @@ void ScriptEngine::addEventHandler(const EntityItemID& entityID, const QString& // Two common cases of event handler, differing only in argument signature. - /**jsdoc + /*@jsdoc * Called when an entity event occurs on an entity as registered with {@link Script.addEventHandler}. * @callback Script~entityEventCallback * @param {Uuid} entityID - The ID of the entity the event has occured on. @@ -1106,7 +1011,7 @@ void ScriptEngine::addEventHandler(const EntityItemID& entityID, const QString& }; }; - /**jsdoc + /*@jsdoc * Called when a pointer event occurs on an entity as registered with {@link Script.addEventHandler}. * @callback Script~pointerEventCallback * @param {Uuid} entityID - The ID of the entity the event has occurred on. @@ -1121,7 +1026,7 @@ void ScriptEngine::addEventHandler(const EntityItemID& entityID, const QString& }; }; - /**jsdoc + /*@jsdoc * Called when a collision event occurs on an entity as registered with {@link Script.addEventHandler}. * @callback Script~collisionEventCallback * @param {Uuid} entityA - The ID of one entity in the collision. @@ -1136,7 +1041,7 @@ void ScriptEngine::addEventHandler(const EntityItemID& entityID, const QString& }; }; - /**jsdoc + /*@jsdoc *

The name of an entity event. When the entity event occurs, any function that has been registered for that event * via {@link Script.addEventHandler} is called with parameters per the entity event.

*
Make a 5 second recording and immediately play it back on your avatar.Stop playing a sound before it finishes.
@@ -2346,7 +2251,7 @@ void ScriptEngine::loadEntityScript(const EntityItemID& entityID, const QString& }, forceRedownload); } -/**jsdoc +/*@jsdoc * Triggered when the script starts for a user. See also, {@link Script.entityScriptPreloadFinished}. *

Note: Can only be connected to via this.preload = function (...) { ... } in the entity script.

*

Supported Script Types: Client Entity Scripts • Server Entity Scripts

@@ -2633,7 +2538,7 @@ void ScriptEngine::entityScriptContentAvailable(const EntityItemID& entityID, co emit entityScriptPreloadFinished(entityID); } -/**jsdoc +/*@jsdoc * Triggered when the script terminates for a user. *

Note: Can only be connected to via this.unoad = function () { ... } in the entity script.

*

Supported Script Types: Client Entity Scripts • Server Entity Scripts

diff --git a/libraries/script-engine/src/ScriptEngine.h b/libraries/script-engine/src/ScriptEngine.h index 1d85de4d94..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 @@ -50,8 +53,6 @@ #include "SettingHandle.h" #include "Profile.h" -class QScriptEngineDebugger; - static const QString NO_SCRIPT(""); static const int SCRIPT_FPS = 60; @@ -103,7 +104,7 @@ public: QUrl definingSandboxURL { QUrl("about:EntityScript") }; }; -/**jsdoc +/*@jsdoc * The Script API provides facilities for working with scripts. * * @namespace Script @@ -135,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) @@ -167,17 +169,14 @@ public: /// services before calling this. void runInThread(); - void runDebuggable(); - /// run the script in the callers thread, exit when stop() is called. void run(); QString getFilename() const; - QList getListOfEntityScriptIDs(); - /**jsdoc + /*@jsdoc * Stops and unloads the current script. *

Warning: If an assignment client script, the script gets restarted after stopping.

* @function Script.stop @@ -187,7 +186,7 @@ public: * Script.setInterval(function () { * print("Hello"); * }, 1000); - * + * * Script.setTimeout(function () { * Script.stop(true); * }, 5000); @@ -203,7 +202,7 @@ public: // NOTE - these are NOT intended to be public interfaces available to scripts, the are only Q_INVOKABLE so we can // properly ensure they are only called on the correct thread - /**jsdoc + /*@jsdoc * @function Script.registerGlobalObject * @param {string} name - Name. * @param {object} object - Object. @@ -212,7 +211,7 @@ public: /// registers a global object by name Q_INVOKABLE void registerGlobalObject(const QString& name, QObject* object); - /**jsdoc + /*@jsdoc * @function Script.registerGetterSetter * @param {string} name - Name. * @param {function} getter - Getter. @@ -224,7 +223,7 @@ public: Q_INVOKABLE void registerGetterSetter(const QString& name, QScriptEngine::FunctionSignature getter, QScriptEngine::FunctionSignature setter, const QString& parent = QString("")); - /**jsdoc + /*@jsdoc * @function Script.registerFunction * @param {string} name - Name. * @param {function} function - Function. @@ -234,7 +233,7 @@ public: /// register a global function Q_INVOKABLE void registerFunction(const QString& name, QScriptEngine::FunctionSignature fun, int numArguments = -1); - /**jsdoc + /*@jsdoc * @function Script.registerFunction * @param {string} parent - Parent. * @param {string} name - Name. @@ -246,7 +245,7 @@ public: Q_INVOKABLE void registerFunction(const QString& parent, const QString& name, QScriptEngine::FunctionSignature fun, int numArguments = -1); - /**jsdoc + /*@jsdoc * @function Script.registerEnum * @param {string} name - Name. * @param {object} enum - Enum. @@ -257,7 +256,7 @@ public: /// registers a global enum Q_INVOKABLE void registerEnum(const QString& enumName, QMetaEnum newEnum); - /**jsdoc + /*@jsdoc * @function Script.registerValue * @param {string} name - Name. * @param {object} value - Value. @@ -266,7 +265,7 @@ public: /// registers a global object by name Q_INVOKABLE void registerValue(const QString& valueName, QScriptValue value); - /**jsdoc + /*@jsdoc * @function Script.evaluate * @param {string} program - Program. * @param {string} filename - File name. @@ -277,7 +276,7 @@ public: /// evaluate some code in the context of the ScriptEngine and return the result Q_INVOKABLE QScriptValue evaluate(const QString& program, const QString& fileName, int lineNumber = 1); // this is also used by the script tool widget - /**jsdoc + /*@jsdoc * @function Script.evaluateInClosure * @param {object} locals - Locals. * @param {object} program - Program. @@ -292,7 +291,7 @@ public: void loadURL(const QUrl& scriptURL, bool reload); bool hasValidScriptSuffix(const QString& scriptFileName); - /**jsdoc + /*@jsdoc * Gets the context that the script is running in: Interface/avatar, client entity, server entity, or assignment client. * @function Script.getContext * @returns {string} The context that the script is running in: @@ -305,40 +304,40 @@ public: */ Q_INVOKABLE QString getContext() const; - /**jsdoc + /*@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; } - /**jsdoc + /*@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; - /**jsdoc + /*@jsdoc * Checks whether the script is running as a client entity script. * @function Script.isEntityClientScript * @returns {boolean} true if the script is running as a client entity script, false if it isn't. */ Q_INVOKABLE bool isEntityClientScript() const { return _context == ENTITY_CLIENT_SCRIPT; } - /**jsdoc + /*@jsdoc * Checks whether the script is running as a server entity script. * @function Script.isEntityServerScript * @returns {boolean} true if the script is running as a server entity script, false if it isn't. */ Q_INVOKABLE bool isEntityServerScript() const { return _context == ENTITY_SERVER_SCRIPT; } - /**jsdoc + /*@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; } @@ -346,13 +345,13 @@ public: //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // NOTE - these are intended to be public interfaces available to scripts - /**jsdoc + /*@jsdoc * Adds a function to the list of functions called when a particular event occurs on a particular entity. *

See also, the {@link Entities} API.

* @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({ @@ -361,16 +360,16 @@ 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); - /**jsdoc + /*@jsdoc * Removes a function from the list of functions called when an entity event occurs on a particular entity. *

See also, the {@link Entities} API.

* @function Script.removeEventHandler @@ -380,8 +379,8 @@ 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 + /*@jsdoc + * 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}.

@@ -402,24 +401,24 @@ 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 + /*@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 * 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()); - /**jsdoc + /*@jsdoc * Includes JavaScript from another file in the current script. If a callback is specified, the file is loaded and included * 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 @@ -442,18 +441,18 @@ 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. + /*@jsdoc + * 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); - /**jsdoc + /*@jsdoc * @function Script.resetModuleCache * @param {boolean} [deleteScriptCache=false] - Delete script cache. * @deprecated This function is deprecated and will be removed. @@ -466,7 +465,7 @@ public: QVariantMap fetchModuleSource(const QString& modulePath, const bool forceDownload = false); QScriptValue instantiateModule(const QScriptValue& module, const QString& sourceCode); - /**jsdoc + /*@jsdoc * Calls a function repeatedly, at a set interval. * @function Script.setInterval * @param {function} function - The function to call. This can be either the name of a function or an in-line definition. @@ -479,7 +478,7 @@ public: */ Q_INVOKABLE QObject* setInterval(const QScriptValue& function, int intervalMS); - /**jsdoc + /*@jsdoc * Calls a function once, after a delay. * @function Script.setTimeout * @param {function} function - The function to call. This can be either the name of a function or an in-line definition. @@ -492,7 +491,7 @@ public: */ Q_INVOKABLE QObject* setTimeout(const QScriptValue& function, int timeoutMS); - /**jsdoc + /*@jsdoc * Stops an interval timer set by {@link Script.setInterval|setInterval}. * @function Script.clearInterval * @param {object} timer - The interval timer to stop. @@ -510,7 +509,7 @@ public: */ Q_INVOKABLE void clearInterval(QObject* timer) { stopTimer(reinterpret_cast(timer)); } - /**jsdoc + /*@jsdoc * Stops a timeout timer set by {@link Script.setTimeout|setTimeout}. * @function Script.clearTimeout * @param {object} timer - The timeout timer to stop. @@ -525,7 +524,7 @@ public: */ Q_INVOKABLE void clearTimeout(QObject* timer) { stopTimer(reinterpret_cast(timer)); } - /**jsdoc + /*@jsdoc * Prints a message to the program log and emits {@link Script.printedMessage}. *

Alternatively, you can use {@link print} or one of the {@link console} API methods.

* @function Script.print @@ -533,7 +532,7 @@ public: */ Q_INVOKABLE void print(const QString& message); - /**jsdoc + /*@jsdoc * Resolves a relative path to an absolute path. The relative path is relative to the script's location. * @function Script.resolvePath * @param {string} path - The relative path to resolve. @@ -547,23 +546,23 @@ public: */ Q_INVOKABLE QUrl resolvePath(const QString& path) const; - /**jsdoc + /*@jsdoc * Gets the path to the resources directory for QML files. * @function Script.resourcesPath * @returns {string} The path to the resources directory for QML files. */ 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 + /*@jsdoc + * 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. */ 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 + /*@jsdoc + * 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. @@ -573,7 +572,7 @@ public: //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Entity Script Related methods - /**jsdoc + /*@jsdoc * Checks whether an entity has an entity script running. * @function Script.isEntityScriptRunning * @param {Uuid} entityID - The ID of the entity. @@ -587,7 +586,7 @@ public: QVariant cloneEntityScriptDetails(const EntityItemID& entityID); QFuture getLocalEntityScriptDetails(const EntityItemID& entityID) override; - /**jsdoc + /*@jsdoc * @function Script.loadEntityScript * @param {Uuid} entityID - Entity ID. * @param {string} script - Script. @@ -596,7 +595,7 @@ public: */ Q_INVOKABLE void loadEntityScript(const EntityItemID& entityID, const QString& entityScript, bool forceRedownload); - /**jsdoc + /*@jsdoc * @function Script.unloadEntityScript * @param {Uuid} entityID - Entity ID. * @param {boolean} [shouldRemoveFromMap=false] - Should remove from map. @@ -604,14 +603,14 @@ public: */ Q_INVOKABLE void unloadEntityScript(const EntityItemID& entityID, bool shouldRemoveFromMap = false); // will call unload method - /**jsdoc + /*@jsdoc * @function Script.unloadAllEntityScripts * @param {boolean} [blockingCall=false] - Wait for completion if call moved to another thread. * @deprecated This function is deprecated and will be removed. */ Q_INVOKABLE void unloadAllEntityScripts(bool blockingCall = false); - /**jsdoc + /*@jsdoc * Calls a method in an entity script. * @function Script.callEntityScriptMethod * @param {Uuid} entityID - The ID of the entity running the entity script. @@ -623,7 +622,7 @@ public: const QStringList& params = QStringList(), const QUuid& remoteCallerID = QUuid()) override; - /**jsdoc + /*@jsdoc * Calls a method in an entity script. * @function Script.callEntityScriptMethod * @param {Uuid} entityID - Entity ID. @@ -633,7 +632,7 @@ public: */ Q_INVOKABLE void callEntityScriptMethod(const EntityItemID& entityID, const QString& methodName, const PointerEvent& event); - /**jsdoc + /*@jsdoc * Calls a method in an entity script. * @function Script.callEntityScriptMethod * @param {Uuid} entityID - Entity ID. @@ -644,14 +643,14 @@ 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 + /*@jsdoc + * Manually runs the JavaScript garbage collector which reclaims memory by disposing of objects that are no longer * reachable. * @function Script.requestGarbageCollection */ Q_INVOKABLE void requestGarbageCollection() { collectGarbage(); } - /**jsdoc + /*@jsdoc * @function Script.generateUUID * @returns {Uuid} A new UUID. * @deprecated This function is deprecated and will be removed. Use {@link Uuid(0).generate|Uuid.generate} instead. @@ -668,8 +667,6 @@ public: // this is used by code in ScriptEngines.cpp during the "reload all" operation bool isStopping() const { return _isStopping; } - bool isDebuggable() const { return _debuggable; } - void disconnectNonEssentialSignals(); //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -697,14 +694,14 @@ public: void setScriptEngines(QSharedPointer& scriptEngines) { _scriptEngines = scriptEngines; } - /**jsdoc + /*@jsdoc * Gets the URL for an asset in an external resource bucket. (The location where the bucket is hosted may change over time * 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
@@ -716,7 +713,7 @@ public: public slots: - /**jsdoc + /*@jsdoc * @function Script.callAnimationStateHandler * @param {function} callback - Callback function. * @param {object} parameters - Parameters. @@ -727,7 +724,7 @@ public slots: */ void callAnimationStateHandler(QScriptValue callback, AnimVariantMap parameters, QStringList names, bool useNames, AnimVariantResultHandler resultHandler); - /**jsdoc + /*@jsdoc * @function Script.updateMemoryCost * @param {number} deltaSize - Delta size. * @deprecated This function is deprecated and will be removed. @@ -736,7 +733,7 @@ public slots: signals: - /**jsdoc + /*@jsdoc * @function Script.scriptLoaded * @param {string} filename - File name. * @returns {Signal} @@ -744,7 +741,7 @@ signals: */ void scriptLoaded(const QString& scriptFilename); - /**jsdoc + /*@jsdoc * @function Script.errorLoadingScript * @param {string} filename - File name. * @returns {Signal} @@ -752,7 +749,7 @@ signals: */ void errorLoadingScript(const QString& scriptFilename); - /**jsdoc + /*@jsdoc * Triggered frequently at a system-determined interval. * @function Script.update * @param {number} deltaTime - The time since the last update, in s. @@ -764,7 +761,7 @@ signals: */ void update(float deltaTime); - /**jsdoc + /*@jsdoc * Triggered when the script is stopping. * @function Script.scriptEnding * @returns {Signal} @@ -782,7 +779,7 @@ signals: */ void scriptEnding(); - /**jsdoc + /*@jsdoc * @function Script.finished * @param {string} filename - File name. * @param {object} engine - Engine. @@ -791,7 +788,7 @@ signals: */ void finished(const QString& fileNameString, ScriptEnginePointer); - /**jsdoc + /*@jsdoc * @function Script.cleanupMenuItem * @param {string} menuItem - Menu item. * @returns {Signal} @@ -799,9 +796,9 @@ 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 + /*@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 * {@link console.timeEnd}. * @function Script.printedMessage * @param {string} message - The message. @@ -810,8 +807,8 @@ 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 + /*@jsdoc + * 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. @@ -820,7 +817,7 @@ signals: */ void errorMessage(const QString& message, const QString& scriptName); - /**jsdoc + /*@jsdoc * Triggered when the script generates a warning or {@link console.warn} is called. * @function Script.warningMessage * @param {string} message - The warning message. @@ -829,7 +826,7 @@ signals: */ void warningMessage(const QString& message, const QString& scriptName); - /**jsdoc + /*@jsdoc * Triggered when the script generates an information message or {@link console.info} is called. * @function Script.infoMessage * @param {string} message - The information message. @@ -838,21 +835,21 @@ signals: */ void infoMessage(const QString& message, const QString& scriptName); - /**jsdoc + /*@jsdoc * Triggered when the running state of the script changes, e.g., from running to stopping. * @function Script.runningStateChanged * @returns {Signal} */ void runningStateChanged(); - /**jsdoc + /*@jsdoc * @function Script.clearDebugWindow * @returns {Signal} * @deprecated This signal is deprecated and will be removed. */ void clearDebugWindow(); - /**jsdoc + /*@jsdoc * @function Script.loadScript * @param {string} scriptName - Script name. * @param {boolean} isUserLoaded - Is user loaded. @@ -861,7 +858,7 @@ signals: */ void loadScript(const QString& scriptName, bool isUserLoaded); - /**jsdoc + /*@jsdoc * @function Script.reloadScript * @param {string} scriptName - Script name. * @param {boolean} isUserLoaded - Is user loaded. @@ -870,14 +867,14 @@ signals: */ void reloadScript(const QString& scriptName, bool isUserLoaded); - /**jsdoc + /*@jsdoc * Triggered when the script has stopped. * @function Script.doneRunning * @returns {Signal} */ void doneRunning(); - /**jsdoc + /*@jsdoc * @function Script.entityScriptDetailsUpdated * @returns {Signal} * @deprecated This signal is deprecated and will be removed. @@ -886,7 +883,7 @@ signals: // script is updated (goes from RUNNING to ERROR_RUNNING_SCRIPT, for example) void entityScriptDetailsUpdated(); - /**jsdoc + /*@jsdoc * Triggered when the script starts for the user. See also, {@link Entities.preload}. *

Supported Script Types: Client Entity Scripts • Server Entity Scripts

* @function Script.entityScriptPreloadFinished @@ -917,7 +914,7 @@ signals: protected: void init(); - /**jsdoc + /*@jsdoc * @function Script.executeOnScriptThread * @param {function} function - Function. * @param {ConnectionType} [type=2] - Connection type. @@ -925,7 +922,7 @@ protected: */ Q_INVOKABLE void executeOnScriptThread(std::function function, const Qt::ConnectionType& type = Qt::QueuedConnection ); - /**jsdoc + /*@jsdoc * @function Script._requireResolve * @param {string} module - Module. * @param {string} [relativeTo=""] - Relative to. @@ -951,7 +948,7 @@ protected: QHash _registeredHandlers; void forwardHandlerCall(const EntityItemID& entityID, const QString& eventName, QScriptValueList eventHanderArgs); - /**jsdoc + /*@jsdoc * @function Script.entityScriptContentAvailable * @param {Uuid} entityID - Entity ID. * @param {string} scriptOrURL - Path. @@ -983,8 +980,6 @@ protected: EntityScriptContentAvailableMap _contentAvailableQueue; bool _isThreaded { false }; - QScriptEngineDebugger* _debugger { nullptr }; - bool _debuggable { false }; qint64 _lastUpdate; QString _fileNameString; @@ -1021,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.cpp b/libraries/script-engine/src/ScriptEngines.cpp index 381d931620..62c215c7df 100644 --- a/libraries/script-engine/src/ScriptEngines.cpp +++ b/libraries/script-engine/src/ScriptEngines.cpp @@ -26,7 +26,6 @@ #define __LOC__ __FILE__ "(" __STR1__(__LINE__) ") : Warning Msg: " static const QString DESKTOP_LOCATION = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation); -static const bool HIFI_SCRIPT_DEBUGGABLES { true }; static const QString SETTINGS_KEY { "RunningScripts" }; static const QUrl DEFAULT_SCRIPTS_LOCATION { "file:///~//defaultScripts.js" }; @@ -68,6 +67,8 @@ void ScriptEngines::onErrorLoadingScript(const QString& url) { ScriptEngines::ScriptEngines(ScriptEngine::Context context, const QUrl& defaultScriptsOverride) : _context(context), _defaultScriptsOverride(defaultScriptsOverride) { + scriptGatekeeper.initialize(); + _scriptsModelFilter.setSourceModel(&_scriptsModel); _scriptsModelFilter.sort(0, Qt::AscendingOrder); _scriptsModelFilter.setDynamicSortFilter(true); @@ -191,7 +192,7 @@ void ScriptEngines::shutdownScripting() { qCDebug(scriptengine) << "DONE Stopping all scripts...."; } -/**jsdoc +/*@jsdoc * Information on a public script, i.e., a script that's included in the Interface installation. * @typedef {object} ScriptDiscoveryService.PublicScript * @property {string} name - The script's file name. @@ -234,7 +235,7 @@ QVariantList ScriptEngines::getPublic() { return getPublicChildNodes(NULL); } -/**jsdoc +/*@jsdoc * Information on a local script. * @typedef {object} ScriptDiscoveryService.LocalScript * @property {string} name - The script's file name. @@ -261,7 +262,7 @@ QVariantList ScriptEngines::getLocal() { return result; } -/**jsdoc +/*@jsdoc * Information on a running script. * @typedef {object} ScriptDiscoveryService.RunningScript * @property {boolean} local - true if the script is a local file (i.e., the scheme is "file"), false @@ -587,17 +588,7 @@ void ScriptEngines::launchScriptEngine(ScriptEnginePointer scriptEngine) { // register our application services and set it off on its own thread runScriptInitializers(scriptEngine); - - // FIXME disabling 'shift key' debugging for now. If you start up the application with - // the shift key held down, it triggers a deadlock because of script interfaces running - // on the main thread - auto const wantDebug = scriptEngine->isDebuggable(); // || (qApp->queryKeyboardModifiers() & Qt::ShiftModifier); - - if (HIFI_SCRIPT_DEBUGGABLES && wantDebug) { - scriptEngine->runDebuggable(); - } else { - scriptEngine->runInThread(); - } + scriptEngine->runInThread(); } void ScriptEngines::onScriptFinished(const QString& rawScriptURL, ScriptEnginePointer engine) { diff --git a/libraries/script-engine/src/ScriptEngines.h b/libraries/script-engine/src/ScriptEngines.h index df736e101d..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 @@ -24,10 +27,11 @@ #include "ScriptEngine.h" #include "ScriptsModel.h" #include "ScriptsModelFilter.h" +#include "ScriptGatekeeper.h" class ScriptEngine; -/**jsdoc +/*@jsdoc * The ScriptDiscoveryService API provides facilities to work with Interface scripts. * * @namespace ScriptDiscoveryService @@ -48,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 @@ -77,7 +81,7 @@ public: QString getDefaultScriptsLocation() const; - /**jsdoc + /*@jsdoc * Starts running an Interface script, if it isn't already running. The script is automatically loaded next time Interface * starts. *

This is a synonym for calling {@link ScriptDiscoveryService.loadScript|loadScript} with just the script URL.

@@ -89,7 +93,7 @@ public: */ Q_INVOKABLE void loadOneScript(const QString& scriptFilename); - /**jsdoc + /*@jsdoc * Starts running an Interface script, if it isn't already running. *

Supported Script Types: Interface Scripts • Avatar Scripts

*

See also, {@link Script.load}.

@@ -109,7 +113,7 @@ public: Q_INVOKABLE ScriptEnginePointer loadScript(const QUrl& scriptFilename = QString(), bool isUserLoaded = true, bool loadScriptFromEditor = false, bool activateMainWindow = false, bool reload = false, bool quitWhenFinished = false); - /**jsdoc + /*@jsdoc * Stops or restarts an Interface script. * @function ScriptDiscoveryService.stopScript * @param {string} url - The path and name of the script. If a local file, including the "file:///" scheme is @@ -122,13 +126,13 @@ public: Q_INVOKABLE bool stopScript(const QString& scriptHash, bool restart = false); - /**jsdoc + /*@jsdoc * Restarts all Interface, avatar, and client entity scripts after clearing the scripts cache. * @function ScriptDiscoveryService.reloadAllScripts */ Q_INVOKABLE void reloadAllScripts(); - /**jsdoc + /*@jsdoc * Stops or restarts all Interface scripts. The scripts cache is not cleared. If restarting, avatar and client entity * scripts are also restarted. * @function ScriptDiscoveryService.stopAllScripts @@ -137,7 +141,7 @@ public: Q_INVOKABLE void stopAllScripts(bool restart = false); - /**jsdoc + /*@jsdoc * Gets a list of all Interface scripts that are currently running. * @function ScriptDiscoveryService.getRunning * @returns {ScriptDiscoveryService.RunningScript[]} All Interface scripts that are currently running. @@ -150,7 +154,7 @@ public: */ Q_INVOKABLE QVariantList getRunning(); - /**jsdoc + /*@jsdoc * Gets a list of all script files that are in the default scripts directory of the Interface installation. * @function ScriptDiscoveryService.getPublic * @returns {ScriptDiscoveryService.PublicScript[]} All scripts in the "scripts" directory of the Interface @@ -158,7 +162,7 @@ public: */ Q_INVOKABLE QVariantList getPublic(); - /**jsdoc + /*@jsdoc * @function ScriptDiscoveryService.getLocal * @returns {ScriptDiscoveryService.LocalScript[]} Local scripts. * @deprecated This function is deprecated and will be removed. @@ -176,10 +180,12 @@ public: bool isStopped() const { return _isStopped; } void addScriptEngine(ScriptEnginePointer); + + ScriptGatekeeper scriptGatekeeper; signals: - /**jsdoc + /*@jsdoc * Triggered when the number of Interface scripts running changes. * @function ScriptDiscoveryService.scriptCountChanged * @returns {Signal} @@ -190,7 +196,7 @@ signals: */ void scriptCountChanged(); - /**jsdoc + /*@jsdoc * Triggered when Interface, avatar, and client entity scripts are restarting as a result of * {@link ScriptDiscoveryService.reloadAllScripts|reloadAllScripts} or * {@link ScriptDiscoveryService.stopAllScripts|stopAllScripts}. @@ -199,7 +205,7 @@ signals: */ void scriptsReloading(); - /**jsdoc + /*@jsdoc * Triggered when a script could not be loaded. * @function ScriptDiscoveryService.scriptLoadError * @param {string} url - The path and name of the script that could not be loaded. @@ -208,7 +214,7 @@ signals: */ void scriptLoadError(const QString& filename, const QString& error); - /**jsdoc + /*@jsdoc * Triggered when any script prints a message to the program log via {@link print}, {@link Script.print}, * {@link console.log}, or {@link console.debug}. * @function ScriptDiscoveryService.printedMessage @@ -218,7 +224,7 @@ signals: */ void printedMessage(const QString& message, const QString& engineName); - /**jsdoc + /*@jsdoc * Triggered when any script generates an error or {@link console.error} is called. * @function ScriptDiscoveryService.errorMessage * @param {string} message - The error message. @@ -227,7 +233,7 @@ signals: */ void errorMessage(const QString& message, const QString& engineName); - /**jsdoc + /*@jsdoc * Triggered when any script generates a warning or {@link console.warn} is called. * @function ScriptDiscoveryService.warningMessage * @param {string} message - The warning message. @@ -236,7 +242,7 @@ signals: */ void warningMessage(const QString& message, const QString& engineName); - /**jsdoc + /*@jsdoc * Triggered when any script generates an information message or {@link console.info} is called. * @function ScriptDiscoveryService.infoMessage * @param {string} message - The information message. @@ -245,7 +251,7 @@ signals: */ void infoMessage(const QString& message, const QString& engineName); - /**jsdoc + /*@jsdoc * @function ScriptDiscoveryService.errorLoadingScript * @param {string} url - URL. * @returns {Signal} @@ -254,7 +260,7 @@ signals: // Deprecated because never emitted. void errorLoadingScript(const QString& url); - /**jsdoc + /*@jsdoc * Triggered when the Debug Window is cleared. * @function ScriptDiscoveryService.clearDebugWindow * @returns {Signal} @@ -263,7 +269,7 @@ signals: public slots: - /**jsdoc + /*@jsdoc * @function ScriptDiscoveryService.onPrintedMessage * @param {string} message - Message. * @param {string} scriptName - Script name. @@ -272,7 +278,7 @@ public slots: // Deprecated because only use is to emit a signal. void onPrintedMessage(const QString& message, const QString& scriptName); - /**jsdoc + /*@jsdoc * @function ScriptDiscoveryService.onErrorMessage * @param {string} message - Message. * @param {string} scriptName - Script name. @@ -281,7 +287,7 @@ public slots: // Deprecated because only use is to emit a signal. void onErrorMessage(const QString& message, const QString& scriptName); - /**jsdoc + /*@jsdoc * @function ScriptDiscoveryService.onWarningMessage * @param {string} message - Message. * @param {string} scriptName - Script name. @@ -290,7 +296,7 @@ public slots: // Deprecated because only use is to emit a signal. void onWarningMessage(const QString& message, const QString& scriptName); - /**jsdoc + /*@jsdoc * @function ScriptDiscoveryService.onInfoMessage * @param {string} message - Message. * @param {string} scriptName - Script name. @@ -299,7 +305,7 @@ public slots: // Deprecated because only use is to emit a signal. void onInfoMessage(const QString& message, const QString& scriptName); - /**jsdoc + /*@jsdoc * @function ScriptDiscoveryService.onErrorLoadingScript * @param {string} url - URL. * @deprecated This function is deprecated and will be removed. @@ -307,7 +313,7 @@ public slots: // Deprecated because only use is to emit a signal. And it isn't used. void onErrorLoadingScript(const QString& url); - /**jsdoc + /*@jsdoc * @function ScriptDiscoveryService.onClearDebugWindow * @deprecated This function is deprecated and will be removed. */ @@ -316,7 +322,7 @@ public slots: protected slots: - /**jsdoc + /*@jsdoc * @function ScriptDiscoveryService.onScriptFinished * @param {string} scriptName - Script name. * @param {object} engine - Engine. @@ -359,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.cpp b/libraries/script-engine/src/ScriptGatekeeper.cpp new file mode 100644 index 0000000000..c223197a8c --- /dev/null +++ b/libraries/script-engine/src/ScriptGatekeeper.cpp @@ -0,0 +1,40 @@ +// +// ScriptGatekeeper.cpp +// libraries/script-engine/src +// +// Created by Kalila L. on Mar 7 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 "ScriptGatekeeper.h" + +#include "BuildInfo.h" +#include "SettingHandle.h" + +void ScriptGatekeeper::initialize() { + if (_initialized) { + return; + } + + QVariant rawCurrentWhitelistValues = Setting::Handle(SCRIPT_WHITELIST_ENTRIES_KEY).get(); + QString settingsSafeValues = rawCurrentWhitelistValues.toString(); + + Setting::Handle whitelistEnabled { SCRIPT_WHITELIST_ENABLED_KEY, false }; + Setting::Handle isFirstRun { Settings::firstRun, true }; + + QString preloadedVal = BuildInfo::PRELOADED_SCRIPT_WHITELIST; + + if (settingsSafeValues.isEmpty() && !preloadedVal.isEmpty() && isFirstRun.get()) { + // We assume that the whitelist should be enabled if a preloaded whitelist is attached, so we activate it if it's not already active. + if (!whitelistEnabled.get()) { + whitelistEnabled.set(true); + } + + Setting::Handle(SCRIPT_WHITELIST_ENTRIES_KEY).set(preloadedVal); + } + + _initialized = true; +} diff --git a/libraries/script-engine/src/ScriptGatekeeper.h b/libraries/script-engine/src/ScriptGatekeeper.h new file mode 100644 index 0000000000..71bce13193 --- /dev/null +++ b/libraries/script-engine/src/ScriptGatekeeper.h @@ -0,0 +1,35 @@ +// +// ScriptGatekeeper.h +// libraries/script-engine/src +// +// Created by Kalila L. on Mar 7 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 +// + +/// @addtogroup ScriptEngine +/// @{ + +#ifndef vircadia_ScriptGatekeeper_h +#define vircadia_ScriptGatekeeper_h + +#include + +/// Manages script whitelisting in a domain +class ScriptGatekeeper : public QObject { + Q_OBJECT +public: + void initialize(); + + QString SCRIPT_WHITELIST_ENABLED_KEY{ "private/whitelistEnabled" }; + QString SCRIPT_WHITELIST_ENTRIES_KEY{ "private/settingsSafeURLS" }; + +private: + bool _initialized { false }; +}; + +#endif // vircadia_ScriptGatekeeper_h + +/// @} diff --git a/libraries/script-engine/src/ScriptUUID.h b/libraries/script-engine/src/ScriptUUID.h index b667447aaa..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 @@ -18,7 +21,7 @@ #include #include -/**jsdoc +/*@jsdoc * The Uuid API provides facilities for working with UUIDs. * * @namespace Uuid @@ -32,14 +35,13 @@ * * @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. public slots: - /**jsdoc + /*@jsdoc * Generates a UUID from a string representation of the UUID. * @function Uuid(0).fromString * @param {string} string - A string representation of a UUID. The curly braces are optional. @@ -56,7 +58,7 @@ public slots: */ QUuid fromString(const QString& string); - /**jsdoc + /*@jsdoc * Generates a string representation of a UUID. However, because UUIDs are represented in JavaScript as strings, this is in * effect a no-op. * @function Uuid(0).toString @@ -65,7 +67,7 @@ public slots: */ QString toString(const QUuid& id); - /**jsdoc + /*@jsdoc * Generates a new UUID. * @function Uuid(0).generate * @returns {Uuid} A new UUID. @@ -76,7 +78,7 @@ public slots: */ QUuid generate(); - /**jsdoc + /*@jsdoc * Tests whether two UUIDs are equal. * @function Uuid(0).isEqual * @param {Uuid} idA - The first UUID to compare. @@ -91,7 +93,7 @@ public slots: */ bool isEqual(const QUuid& idA, const QUuid& idB); - /**jsdoc + /*@jsdoc * Tests whether a UUID is null. * @function Uuid(0).isNull * @param {Uuid} id - The UUID to test. @@ -109,7 +111,7 @@ public slots: */ bool isNull(const QUuid& id); - /**jsdoc + /*@jsdoc * Prints a UUID to the program log, as a text label followed by the UUID value. * @function Uuid(0).print * @param {string} label - The label to print. @@ -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 0412bbf0fe..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 @@ -35,6 +38,7 @@ public: void setParent(TreeNodeFolder* parent) { _parent = parent; } TreeNodeType getType() { return _type; } const QString& getName() { return _name; }; + virtual ~TreeNodeBase() = default; private: TreeNodeFolder* _parent; @@ -63,7 +67,7 @@ public: TreeNodeFolder(const QString& foldername, TreeNodeFolder* parent); }; -/**jsdoc +/*@jsdoc * Information on the scripts that are in the default scripts directory of the Interface installation. This is provided as a * property of {@link ScriptDiscoveryService}. * @@ -118,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: @@ -151,26 +156,26 @@ public: protected slots: - /**jsdoc + /*@jsdoc * @function ScriptsModel.updateScriptsLocation * @param {string} newPath - New path. * @deprecated This method is deprecated and will be removed from the API. */ void updateScriptsLocation(const QString& newPath); - /**jsdoc + /*@jsdoc * @function ScriptsModel.downloadFinished * @deprecated This method is deprecated and will be removed from the API. */ void downloadFinished(); - /**jsdoc + /*@jsdoc * @function ScriptsModel.reloadLocalFiles * @deprecated This method is deprecated and will be removed from the API. */ void reloadLocalFiles(); - /**jsdoc + /*@jsdoc * @function ScriptsModel.reloadDefaultFiles * @deprecated This method is deprecated and will be removed from the API. */ @@ -190,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 eb7495e7d4..7a52be76e4 100644 --- a/libraries/script-engine/src/ScriptsModelFilter.h +++ b/libraries/script-engine/src/ScriptsModelFilter.h @@ -9,13 +9,16 @@ // 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 #include "ScriptsModel.h" #include -/**jsdoc +/*@jsdoc * Sorted and filtered information on the scripts that are in the default scripts directory of the Interface installation. This * is provided as a property of {@link ScriptDiscoveryService}. * @@ -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.cpp b/libraries/script-engine/src/TouchEvent.cpp index 58ac9ec8c1..9e9f8bd34a 100644 --- a/libraries/script-engine/src/TouchEvent.cpp +++ b/libraries/script-engine/src/TouchEvent.cpp @@ -165,7 +165,7 @@ void TouchEvent::calculateMetaAttributes(const TouchEvent& other) { } } -/**jsdoc +/*@jsdoc * A display or device touch event. * @typedef {object} TouchEvent * @property {number} x - Integer x-coordinate of the average position of the touch events. 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.cpp b/libraries/script-engine/src/UsersScriptingInterface.cpp index 9beb52f20a..883c728c2f 100644 --- a/libraries/script-engine/src/UsersScriptingInterface.cpp +++ b/libraries/script-engine/src/UsersScriptingInterface.cpp @@ -4,6 +4,7 @@ // // Created by Stephen Birarda on 2016-07-11. // 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 @@ -51,15 +52,14 @@ float UsersScriptingInterface::getAvatarGain(const QUuid& nodeID) { return DependencyManager::get()->getAvatarGain(nodeID); } -void UsersScriptingInterface::kick(const QUuid& nodeID) { - +void UsersScriptingInterface::kick(const QUuid& nodeID, unsigned int banFlags) { if (_kickConfirmationOperator) { bool waitingForKickResponse = _kickResponseLock.resultWithReadLock([&] { return _waitingForKickResponse; }); if (getCanKick() && !waitingForKickResponse) { - _kickConfirmationOperator(nodeID); + _kickConfirmationOperator(nodeID, banFlags); } } else { - DependencyManager::get()->kickNodeBySessionID(nodeID); + DependencyManager::get()->kickNodeBySessionID(nodeID, banFlags); } } diff --git a/libraries/script-engine/src/UsersScriptingInterface.h b/libraries/script-engine/src/UsersScriptingInterface.h index 3b0666481a..8bca34ad0b 100644 --- a/libraries/script-engine/src/UsersScriptingInterface.h +++ b/libraries/script-engine/src/UsersScriptingInterface.h @@ -4,11 +4,15 @@ // // Created by Stephen Birarda on 2016-07-11. // 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 // +/// @addtogroup ScriptEngine +/// @{ + #pragma once #ifndef hifi_UsersScriptingInterface_h @@ -16,8 +20,9 @@ #include #include +#include -/**jsdoc +/*@jsdoc * The Users API provides features to regulate your interaction with other users. * * @namespace Users @@ -31,7 +36,12 @@ * false. Read-only. * @property {boolean} requestsDomainListData - true if the client requests extra data from the mixers (such as * positional data of an avatar they've ignored). Read-only. + * @property {BanFlags} NO_BAN - Do not ban user. Read-only. + * @property {BanFlags} BAN_BY_USERNAME - Ban user by username. Read-only. + * @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 @@ -39,9 +49,14 @@ class UsersScriptingInterface : public QObject, public Dependency { Q_PROPERTY(bool canKick READ getCanKick) Q_PROPERTY(bool requestsDomainListData READ getRequestsDomainListData WRITE setRequestsDomainListData) + Q_PROPERTY(unsigned int NO_BAN READ getNoBan CONSTANT) + Q_PROPERTY(unsigned int BAN_BY_USERNAME READ getBanByUsername CONSTANT) + Q_PROPERTY(unsigned int BAN_BY_FINGERPRINT READ getBanByFingerprint CONSTANT) + Q_PROPERTY(unsigned int BAN_BY_IP READ getBanByIP CONSTANT) + public: UsersScriptingInterface(); - void setKickConfirmationOperator(std::function kickConfirmationOperator) { + void setKickConfirmationOperator(std::function kickConfirmationOperator) { _kickConfirmationOperator = kickConfirmationOperator; } @@ -50,7 +65,7 @@ public: public slots: - /**jsdoc + /*@jsdoc * Ignores or un-ignores another avatar. Ignoring an avatar makes them disappear for you and you disappear for them. * @function Users.ignore * @param {Uuid} sessionID - The session ID of the avatar to ignore. @@ -70,7 +85,7 @@ public slots: */ void ignore(const QUuid& nodeID, bool ignoreEnabled = true); - /**jsdoc + /*@jsdoc * Gets whether or not you have ignored a particular avatar. * @function Users.getIgnoreStatus * @param {Uuid} sessionID - The session ID of the avatar to get the ignore status of. @@ -78,7 +93,7 @@ public slots: */ bool getIgnoreStatus(const QUuid& nodeID); - /**jsdoc + /*@jsdoc * Mutes or un-mutes another avatar. Muting makes you unable to hear them and them unable to hear you. * @function Users.personalMute * @param {Uuid} sessionID - The session ID of the avatar to mute. @@ -86,7 +101,7 @@ public slots: */ void personalMute(const QUuid& nodeID, bool muteEnabled = true); - /**jsdoc + /*@jsdoc * Gets whether or not you have muted a particular avatar. * @function Users.getPersonalMuteStatus * @param {Uuid} sessionID - The session ID of the avatar to get the mute status of. @@ -94,7 +109,7 @@ public slots: */ bool getPersonalMuteStatus(const QUuid& nodeID); - /**jsdoc + /*@jsdoc * Sets an avatar's gain (volume) for you and you only, or sets the master gain. * @function Users.setAvatarGain * @param {Uuid} nodeID - The session ID of the avatar to set the gain for, or null to set the master gain. @@ -102,7 +117,7 @@ public slots: */ void setAvatarGain(const QUuid& nodeID, float gain); - /**jsdoc + /*@jsdoc * Gets an avatar's gain (volume) for you and you only, or gets the master gain. * @function Users.getAvatarGain * @param {Uuid} nodeID - The session ID of the avatar to get the gain for, or null to get the master gain. @@ -110,16 +125,17 @@ public slots: */ float getAvatarGain(const QUuid& nodeID); - /**jsdoc - * Kicks and bans a user. This removes them from the server and prevents them from returning. The ban is by user name if - * available, or machine fingerprint otherwise. + /*@jsdoc + * Kicks and bans a user. This removes them from the server and prevents them from returning. The ban is by user name (if + * available) and by machine fingerprint. The ban functionality can be controlled with flags. *

This function only works if you're an administrator of the domain you're in.

* @function Users.kick * @param {Uuid} sessionID - The session ID of the user to kick and ban. + * @param {BanFlags} - Preferred ban flags. Bans a user by username (if available) and machine fingerprint by default. */ - void kick(const QUuid& nodeID); + void kick(const QUuid& nodeID, unsigned int banFlags = ModerationFlags::getDefaultBanFlags()); - /**jsdoc + /*@jsdoc * Mutes a user's microphone for everyone. The mute is not permanent: the user can unmute themselves. *

This function only works if you're an administrator of the domain you're in.

* @function Users.mute @@ -127,7 +143,7 @@ public slots: */ void mute(const QUuid& nodeID); - /**jsdoc + /*@jsdoc * Requests the user name and machine fingerprint associated with the given UUID. The user name is returned via a * {@link Users.usernameFromIDReply|usernameFromIDReply} signal. *

This function only works if you're an administrator of the domain you're in.

@@ -153,7 +169,7 @@ public slots: */ void requestUsernameFromID(const QUuid& nodeID); - /**jsdoc + /*@jsdoc * Gets whether the client can kick and ban users in the domain. * @function Users.getCanKick * @returns {boolean} true if the domain server allows the client to kick and ban users, otherwise @@ -161,25 +177,25 @@ public slots: */ bool getCanKick(); - /**jsdoc + /*@jsdoc * Toggles the state of the privacy shield. * @function Users.toggleIgnoreRadius */ void toggleIgnoreRadius(); - /**jsdoc + /*@jsdoc * Enables the privacy shield. * @function Users.enableIgnoreRadius */ void enableIgnoreRadius(); - /**jsdoc + /*@jsdoc * Disables the privacy shield. * @function Users.disableIgnoreRadius */ void disableIgnoreRadius(); - /**jsdoc + /*@jsdoc * Gets the status of the privacy shield. * @function Users.getIgnoreRadiusEnabled * @returns {boolean} true if the privacy shield is enabled, false if it is disabled. @@ -188,7 +204,7 @@ public slots: signals: - /**jsdoc + /*@jsdoc * Triggered when your ability to kick and ban users changes. * @function Users.canKickChanged * @param {boolean} canKick - true if you can kick and ban users, false if you can't. @@ -196,7 +212,7 @@ signals: */ void canKickChanged(bool canKick); - /**jsdoc + /*@jsdoc * Triggered when the privacy shield status changes. * @function Users.ignoreRadiusEnabledChanged * @param {boolean} isEnabled - true if the privacy shield is enabled, false if it isn't. @@ -204,14 +220,14 @@ signals: */ void ignoreRadiusEnabledChanged(bool isEnabled); - /**jsdoc + /*@jsdoc * Triggered when another user enters the privacy shield. * @function Users.enteredIgnoreRadius * @returns {Signal} */ void enteredIgnoreRadius(); - /**jsdoc + /*@jsdoc * Triggered in response to a {@link Users.requestUsernameFromID|requestUsernameFromID} call. Provides the user name and * machine fingerprint associated with a UUID. * @function Users.usernameFromIDReply @@ -225,7 +241,7 @@ signals: */ void usernameFromIDReply(const QString& nodeID, const QString& username, const QString& machineFingerprint, bool isAdmin); - /**jsdoc + /*@jsdoc * Triggered when a client has disconnected from the domain. * @function Users.avatarDisconnected * @param {Uuid} sessionID - The session ID of the client that has disconnected. @@ -237,7 +253,12 @@ private: bool getRequestsDomainListData(); void setRequestsDomainListData(bool requests); - std::function _kickConfirmationOperator; + static constexpr unsigned int getNoBan() { return ModerationFlags::BanFlags::NO_BAN; }; + static constexpr unsigned int getBanByUsername() { return ModerationFlags::BanFlags::BAN_BY_USERNAME; }; + static constexpr unsigned int getBanByFingerprint() { return ModerationFlags::BanFlags::BAN_BY_FINGERPRINT; }; + static constexpr unsigned int getBanByIP() { return ModerationFlags::BanFlags::BAN_BY_IP; }; + + std::function _kickConfirmationOperator; ReadWriteLockable _kickResponseLock; bool _waitingForKickResponse { false }; @@ -245,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 a8a8adece3..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 @@ -21,7 +24,7 @@ #include "GLMHelpers.h" -/**jsdoc +/*@jsdoc * The Vec3 API provides facilities for generating and manipulating 3-dimensional vectors. Vircadia uses a * right-handed Cartesian coordinate system where the y-axis is the "up" and the negative z-axis is the "front" direction. * Vircadia coordinate system @@ -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) @@ -97,7 +99,7 @@ class Vec3 : public QObject, protected QScriptable { public slots: - /**jsdoc + /*@jsdoc * Calculates the reflection of a vector in a plane. * @function Vec3(0).reflect * @param {Vec3} v - The vector to reflect. @@ -111,7 +113,7 @@ public slots: */ glm::vec3 reflect(const glm::vec3& v1, const glm::vec3& v2) { return glm::reflect(v1, v2); } - /**jsdoc + /*@jsdoc * Calculates the cross product of two vectors. * @function Vec3(0).cross * @param {Vec3} v1 - The first vector. @@ -125,7 +127,7 @@ public slots: */ glm::vec3 cross(const glm::vec3& v1, const glm::vec3& v2) { return glm::cross(v1, v2); } - /**jsdoc + /*@jsdoc * Calculates the dot product of two vectors. * @function Vec3(0).dot * @param {Vec3} v1 - The first vector. @@ -139,7 +141,7 @@ public slots: */ float dot(const glm::vec3& v1, const glm::vec3& v2) { return glm::dot(v1, v2); } - /**jsdoc + /*@jsdoc * Multiplies a vector by a scale factor. * @function Vec3(0).multiply * @param {Vec3} v - The vector. @@ -148,7 +150,7 @@ public slots: */ glm::vec3 multiply(const glm::vec3& v1, float f) { return v1 * f; } - /**jsdoc + /*@jsdoc * Multiplies a vector by a scale factor. * @function Vec3(0).multiply * @param {number} scale - The scale factor. @@ -157,7 +159,7 @@ public slots: */ glm::vec3 multiply(float f, const glm::vec3& v1) { return v1 * f; } - /**jsdoc + /*@jsdoc * Multiplies two vectors. * @function Vec3(0).multiplyVbyV * @param {Vec3} v1 - The first vector. @@ -172,7 +174,7 @@ public slots: */ glm::vec3 multiplyVbyV(const glm::vec3& v1, const glm::vec3& v2) { return v1 * v2; } - /**jsdoc + /*@jsdoc * Rotates a vector. * @function Vec3(0).multiplyQbyV * @param {Quat} q - The rotation to apply. @@ -186,7 +188,7 @@ public slots: */ glm::vec3 multiplyQbyV(const glm::quat& q, const glm::vec3& v) { return q * v; } - /**jsdoc + /*@jsdoc * Calculates the sum of two vectors. * @function Vec3(0).sum * @param {Vec3} v1 - The first vector. @@ -195,7 +197,7 @@ public slots: */ glm::vec3 sum(const glm::vec3& v1, const glm::vec3& v2) { return v1 + v2; } - /**jsdoc + /*@jsdoc * Calculates one vector subtracted from another. * @function Vec3(0).subtract * @param {Vec3} v1 - The first vector. @@ -204,7 +206,7 @@ public slots: */ glm::vec3 subtract(const glm::vec3& v1, const glm::vec3& v2) { return v1 - v2; } - /**jsdoc + /*@jsdoc * Calculates the length of a vector * @function Vec3(0).length * @param {Vec3} v - The vector. @@ -212,7 +214,7 @@ public slots: */ float length(const glm::vec3& v) { return glm::length(v); } - /**jsdoc + /*@jsdoc * Calculates the distance between two points. * @function Vec3(0).distance * @param {Vec3} p1 - The first point. @@ -230,7 +232,7 @@ public slots: */ float distance(const glm::vec3& v1, const glm::vec3& v2) { return glm::distance(v1, v2); } - /**jsdoc + /*@jsdoc * Calculates the angle of rotation from one vector onto another, with the sign depending on a reference vector. * @function Vec3(0).orientedAngle * @param {Vec3} v1 - The first vector. @@ -252,7 +254,7 @@ public slots: */ float orientedAngle(const glm::vec3& v1, const glm::vec3& v2, const glm::vec3& v3); - /**jsdoc + /*@jsdoc * Normalizes a vector so that its length is 1. * @function Vec3(0).normalize * @param {Vec3} v - The vector to normalize. @@ -265,7 +267,7 @@ public slots: */ glm::vec3 normalize(const glm::vec3& v) { return glm::normalize(v); }; - /**jsdoc + /*@jsdoc * Calculates a linear interpolation between two vectors. * @function Vec3(0).mix * @param {Vec3} v1 - The first vector. @@ -280,7 +282,7 @@ public slots: */ glm::vec3 mix(const glm::vec3& v1, const glm::vec3& v2, float m) { return glm::mix(v1, v2, m); } - /**jsdoc + /*@jsdoc * Prints the vector to the program log, as a text label followed by the vector value. * @function Vec3(0).print * @param {string} label - The label to print. @@ -292,7 +294,7 @@ public slots: */ void print(const QString& label, const glm::vec3& v); - /**jsdoc + /*@jsdoc * Tests whether two vectors are equal. *

Note: The vectors must be exactly equal in order for true to be returned; it is often * better to use {@link Vec3(0).withinEpsilon|withinEpsilon}.

@@ -313,7 +315,7 @@ public slots: */ bool equal(const glm::vec3& v1, const glm::vec3& v2) { return v1 == v2; } - /**jsdoc + /*@jsdoc * Tests whether two vectors are equal within a tolerance. *

Note: It is often better to use this function than {@link Vec3(0).equal|equal}.

* @function Vec3(0).withinEpsilon @@ -334,7 +336,7 @@ public slots: */ bool withinEpsilon(const glm::vec3& v1, const glm::vec3& v2, float epsilon); - /**jsdoc + /*@jsdoc * Calculates polar coordinates (elevation, azimuth, radius) that transform the unit z-axis vector onto a point. * @function Vec3(0).toPolar * @param {Vec3} p - The point to calculate the polar coordinates for. @@ -350,7 +352,7 @@ public slots: // FIXME misnamed, should be 'spherical' or 'euler' depending on the implementation glm::vec3 toPolar(const glm::vec3& v); - /**jsdoc + /*@jsdoc * Calculates the coordinates of a point from polar coordinate transformation of the unit z-axis vector. * @function Vec3(0).fromPolar * @param {Vec3} polar - The polar coordinates of a point: x elevation rotation about the x-axis in radians, @@ -364,7 +366,7 @@ public slots: // FIXME misnamed, should be 'spherical' or 'euler' depending on the implementation glm::vec3 fromPolar(const glm::vec3& polar); - /**jsdoc + /*@jsdoc * Calculates the unit vector corresponding to polar coordinates elevation and azimuth transformation of the unit z-axis * vector. * @function Vec3(0).fromPolar @@ -382,7 +384,7 @@ public slots: // FIXME misnamed, should be 'spherical' or 'euler' depending on the implementation glm::vec3 fromPolar(float elevation, float azimuth); - /**jsdoc + /*@jsdoc * Calculates the angle between two vectors. * @function Vec3(0).getAngle * @param {Vec3} v1 - The first vector. @@ -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 00d379aff4..a001e2b2c2 100644 --- a/libraries/script-engine/src/WebSocketClass.cpp +++ b/libraries/script-engine/src/WebSocketClass.cpp @@ -76,12 +76,12 @@ void WebSocketClass::close(QWebSocketProtocol::CloseCode closeCode, QString reas _webSocket->close(closeCode, reason); } -/**jsdoc +/*@jsdoc * Called when the connection closes. * @callback WebSocket~onCloseCallback * @param {WebSocket.CloseData} data - Information on the connection closure. */ -/**jsdoc +/*@jsdoc * Information on a connection being closed. * @typedef {object} WebSocket.CloseData * @property {WebSocket.CloseCode} code - The reason why the connection was closed. @@ -101,12 +101,12 @@ void WebSocketClass::handleOnClose() { } } -/**jsdoc +/*@jsdoc * Called when an error occurs. * @callback WebSocket~onErrorCallback * @param {WebSocket.SocketError} error - The error. */ -/**jsdoc +/*@jsdoc *

The type of socket error.

*
Report when a mouse press occurs on a particular entity.Include a script file asynchronously.Report the URL of a default particle.
* @@ -158,12 +158,12 @@ void WebSocketClass::handleOnError(QAbstractSocket::SocketError error) { } } -/**jsdoc - * Triggered when a message is received. +/*@jsdoc + * Called when a message is received. * @callback WebSocket~onMessageCallback * @param {WebSocket.MessageData} message - The message received. */ -/**jsdoc +/*@jsdoc * A message received on a WebSocket connection. * @typedef {object} WebSocket.MessageData * @property {string} data - The message content. @@ -197,7 +197,7 @@ void WebSocketClass::handleOnBinaryMessage(const QByteArray& message) { } } -/**jsdoc +/*@jsdoc * Called when the connection opens. * @callback WebSocket~onOpenCallback */ diff --git a/libraries/script-engine/src/WebSocketClass.h b/libraries/script-engine/src/WebSocketClass.h index 3430068eee..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 @@ -16,7 +19,7 @@ #include #include -/**jsdoc +/*@jsdoc * Provides a bi-directional, event-driven communication session between the script and another WebSocket connection. It is a * near-complete implementation of the WebSocket API described in the Mozilla docs: * https://developer.mozilla.org/en-US/docs/Web/API/WebSocket. @@ -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) @@ -105,7 +109,7 @@ public: static QScriptValue constructor(QScriptContext* context, QScriptEngine* engine); - /**jsdoc + /*@jsdoc * The state of a WebSocket connection. *
* @@ -178,20 +182,20 @@ public: public slots: - /**jsdoc + /*@jsdoc * Sends a message on the connection. * @function WebSocket.send * @param {string|object} message - The message to send. If an object, it is converted to a string. */ void send(QScriptValue message); - /**jsdoc + /*@jsdoc * Closes the connection. * @function WebSocket.close * @param {WebSocket.CloseCode} [closeCode=1000] - The reason for closing. * @param {string} [reason=""] - A description of the reason for closing. */ - /**jsdoc + /*@jsdoc * The reason why the connection was closed. *
* @@ -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 fff33d5bfb..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 @@ -17,7 +20,7 @@ #include #include "WebSocketClass.h" -/**jsdoc +/*@jsdoc * Manages {@link WebSocket}s in server entity and assignment client scripts. * *

Create using new WebSocketServer(...).

@@ -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) @@ -91,7 +95,7 @@ public: public slots: - /**jsdoc + /*@jsdoc * Closes all connections and closes the WebSocketServer. * @function WebSocketServer.close */ @@ -107,7 +111,7 @@ private slots: signals: - /**jsdoc + /*@jsdoc * Triggered when there is a new connection. * @function WebSocketServer.newConnection * @param {WebSocket} webSocket - The {@link WebSocket} for the new connection. @@ -118,3 +122,5 @@ signals: }; #endif // hifi_WebSocketServerClass_h + +/// @} diff --git a/libraries/script-engine/src/WheelEvent.cpp b/libraries/script-engine/src/WheelEvent.cpp index a0a897c991..565c2ddb50 100644 --- a/libraries/script-engine/src/WheelEvent.cpp +++ b/libraries/script-engine/src/WheelEvent.cpp @@ -53,7 +53,7 @@ WheelEvent::WheelEvent(const QWheelEvent& event) { isAlt = event.modifiers().testFlag(Qt::AltModifier); } -/**jsdoc +/*@jsdoc * A mouse wheel event. * @typedef {object} WheelEvent * @property {number} x - Integer x-coordinate of the event on the Interface window or HMD HUD. 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.cpp b/libraries/script-engine/src/XMLHttpRequestClass.cpp index 1a4ec52f73..e8acba8366 100644 --- a/libraries/script-engine/src/XMLHttpRequestClass.cpp +++ b/libraries/script-engine/src/XMLHttpRequestClass.cpp @@ -109,7 +109,7 @@ QScriptValue XMLHttpRequestClass::getResponseHeader(const QString& name) const { return QScriptValue::NullValue; } -/**jsdoc +/*@jsdoc * Called when the request's ready state changes. * @callback XMLHttpRequest~onReadyStateChangeCallback */ @@ -188,7 +188,7 @@ void XMLHttpRequestClass::doSend() { } } -/**jsdoc +/*@jsdoc * Called when the request times out. * @callback XMLHttpRequest~onTimeoutCallback */ diff --git a/libraries/script-engine/src/XMLHttpRequestClass.h b/libraries/script-engine/src/XMLHttpRequestClass.h index 3ab7d38dda..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 @@ -56,7 +59,7 @@ XMlHttpRequest.getAllResponseHeaders() function XMlHttpRequest.getResponseHeader(QString) function */ -/**jsdoc +/*@jsdoc * Provides a means to interact with web servers. It is a near-complete implementation of the XMLHttpRequest API described in * the Mozilla docs: * https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest. @@ -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) @@ -175,7 +179,7 @@ public: static const int MAXIMUM_REDIRECTS = 5; - /**jsdoc + /*@jsdoc *

The state of an XMLHttpRequest.

*
* @@ -228,13 +232,13 @@ public: public slots: - /**jsdoc + /*@jsdoc * Aborts the request. * @function XMLHttpRequest.abort */ void abort(); - /**jsdoc + /*@jsdoc * Sets the value of an HTTP request header. Must be called after {@link XMLHttpRequest.open} but before * {@link XMLHttpRequest.send}; * @function XMLHttpRequest.setRequestHeader @@ -243,7 +247,7 @@ public slots: */ void setRequestHeader(const QString& name, const QString& value); - /**jsdoc + /*@jsdoc * Initializes a request. * @function XMLHttpRequest.open * @param {string} method - The HTTP request method @@ -257,7 +261,7 @@ public slots: void open(const QString& method, const QString& url, bool async = true, const QString& username = "", const QString& password = ""); - /**jsdoc + /*@jsdoc * Sends the request to the server. * @function XMLHttpRequest.send * @param {*} [data] - The data to send. @@ -265,14 +269,14 @@ public slots: void send(); void send(const QScriptValue& data); - /**jsdoc + /*@jsdoc * Gets the response headers. * @function XMLHttpRequest.getAllResponseHeaders * @returns {string} The response headers, separated by "\n" characters. */ QScriptValue getAllResponseHeaders() const; - /**jsdoc + /*@jsdoc * Gets a response header. * @function XMLHttpRequest.getResponseHeader * @param {string} name - @@ -282,7 +286,7 @@ public slots: signals: - /**jsdoc + /*@jsdoc * Triggered when the request is complete — with or without error (incl. timeout). * @function XMLHttpRequest.requestComplete * @returns {Signal} @@ -310,7 +314,7 @@ private: QScriptValue _onReadyStateChange { QScriptValue::NullValue }; ReadyState _readyState { XMLHttpRequestClass::UNSENT }; - /**jsdoc + /*@jsdoc *

The type of network error.

*
* @@ -374,3 +378,5 @@ private slots: }; #endif // hifi_XMLHttpRequestClass_h + +/// @} diff --git a/libraries/shared/src/BaseScriptEngine.h b/libraries/shared/src/BaseScriptEngine.h index 443c7b0500..c917aa2722 100644 --- a/libraries/shared/src/BaseScriptEngine.h +++ b/libraries/shared/src/BaseScriptEngine.h @@ -31,7 +31,7 @@ public: BaseScriptEngine() {} - /**jsdoc + /*@jsdoc * @function Script.lintScript * @param {string} sourceCode - Source code. * @param {string} fileName - File name. @@ -41,7 +41,7 @@ public: */ Q_INVOKABLE QScriptValue lintScript(const QString& sourceCode, const QString& fileName, const int lineNumber = 1); - /**jsdoc + /*@jsdoc * @function Script.makeError * @param {object} [other] - Other. * @param {string} [type="Error"] - Error. @@ -50,7 +50,7 @@ public: */ Q_INVOKABLE QScriptValue makeError(const QScriptValue& other = QScriptValue(), const QString& type = "Error"); - /**jsdoc + /*@jsdoc * @function Script.formatExecption * @param {object} exception - Exception. * @param {boolean} inludeExtendeDetails - Include extended details. @@ -72,7 +72,7 @@ public: // helper to detect and log warnings when other code invokes QScriptEngine/BaseScriptEngine in thread-unsafe ways static bool IS_THREADSAFE_INVOCATION(const QThread *thread, const QString& method); signals: - /**jsdoc + /*@jsdoc * @function Script.signalHandlerException * @param {object} exception - Exception. * @returns {Signal} @@ -80,7 +80,7 @@ signals: */ // Script.signalHandlerException is exposed by QScriptEngine. - /**jsdoc + /*@jsdoc * Triggered when a script generates an unhandled exception. * @function Script.unhandledException * @param {object} exception - The details of the exception. diff --git a/libraries/shared/src/BillboardMode.h b/libraries/shared/src/BillboardMode.h index 4d123c0603..dd377cab31 100644 --- a/libraries/shared/src/BillboardMode.h +++ b/libraries/shared/src/BillboardMode.h @@ -16,7 +16,7 @@ #include "glm/glm.hpp" #include "glm/gtc/quaternion.hpp" -/**jsdoc +/*@jsdoc *

How an entity is billboarded.

*
* diff --git a/libraries/shared/src/BlendshapeConstants.cpp b/libraries/shared/src/BlendshapeConstants.cpp index 9035b10529..01f8c2db19 100644 --- a/libraries/shared/src/BlendshapeConstants.cpp +++ b/libraries/shared/src/BlendshapeConstants.cpp @@ -77,10 +77,47 @@ const char* BLENDSHAPE_NAMES[] = { "" }; -const QMap BLENDSHAPE_LOOKUP_MAP = [] { - QMap toReturn; +const QHash BLENDSHAPE_LOOKUP_MAP = [] { + QHash toReturn; for (int i = 0; i < (int)Blendshapes::BlendshapeCount; i++) { toReturn[BLENDSHAPE_NAMES[i]] = i; } return toReturn; }(); + +const QHash> READYPLAYERME_BLENDSHAPES_MAP = { + // ReadyPlayerMe blendshape default mapping. + { "mouthOpen", { "JawOpen", 1.0f } }, + { "eyeBlinkLeft", { "EyeBlink_L", 1.0f } }, + { "eyeBlinkRight", { "EyeBlink_R", 1.0f } }, + { "eyeSquintLeft", { "EyeSquint_L", 1.0f } }, + { "eyeSquintRight", { "EyeSquint_R", 1.0f } }, + { "eyeWideLeft", { "EyeOpen_L", 1.0f } }, + { "eyeWideRight", { "EyeOpen_R", 1.0f } }, + { "browDownLeft", { "BrowsD_L", 1.0f } }, + { "browDownRight", { "BrowsD_R", 1.0f } }, + { "browInnerUp", { "BrowsU_C", 1.0f } }, + { "browOuterUpLeft", { "BrowsU_L", 1.0f } }, + { "browOuterUpRight", { "BrowsU_R", 1.0f } }, + { "mouthFrownLeft", { "MouthFrown_L", 1.0f } }, + { "mouthFrownRight", { "MouthFrown_R", 1.0f } }, + { "mouthPucker", { "LipsPucker", 1.0f } }, + { "jawForward", { "JawFwd", 1.0f } }, + { "jawLeft", { "JawLeft", 1.0f } }, + { "jawRight", { "JawRight", 1.0f } }, + { "mouthLeft", { "MouthLeft", 1.0f } }, + { "mouthRight", { "MouthRight", 1.0f } }, + { "noseSneerLeft", { "NoseSneer_L", 1.0f } }, + { "noseSneerRight", { "NoseSneer_R", 1.0f } }, + { "mouthLowerDownLeft", { "MouthLowerDown_L", 1.0f } }, + { "mouthLowerDownRight", { "MouthLowerDown_R", 1.0f } }, + { "mouthShrugLower", { "MouthShrugLower", 1.0f } }, + { "mouthShrugUpper", { "MouthShrugUpper", 1.0f } }, + { "viseme_sil", { "MouthClose", 1.0f } }, + { "mouthSmile", { "MouthSmile_L", 1.0f } }, + { "mouthSmile", { "MouthSmile_R", 1.0f } }, + { "viseme_CH", { "LipsFunnel", 1.0f } }, + { "viseme_PP", { "LipsUpperClose", 1.0f } }, + { "mouthShrugLower", { "LipsLowerClose", 1.0f } }, + { "viseme_FF", { "Puff", 1.0f } } +}; diff --git a/libraries/shared/src/BlendshapeConstants.h b/libraries/shared/src/BlendshapeConstants.h index 1c37892088..5dd1f0abbb 100644 --- a/libraries/shared/src/BlendshapeConstants.h +++ b/libraries/shared/src/BlendshapeConstants.h @@ -12,14 +12,15 @@ #ifndef hifi_BlendshapeConstants_h #define hifi_BlendshapeConstants_h -#include +#include #include #include /// The names of the supported blendshapes, terminated with an empty string. extern const char* BLENDSHAPE_NAMES[]; -extern const QMap BLENDSHAPE_LOOKUP_MAP; +extern const QHash BLENDSHAPE_LOOKUP_MAP; +extern const QHash> READYPLAYERME_BLENDSHAPES_MAP; enum class Blendshapes : int { EyeBlink_L = 0, @@ -87,16 +88,6 @@ enum class Blendshapes : int { BlendshapeCount }; -enum class LegacyBlendshpaes : int { - JawChew, // not in ARKit - LipsUpperUp, // split in ARKit - LipsLowerDown, // split in ARKit - ChinLowerRaise, // not in ARKit - ChinUpperRaise, // not in ARKit - Sneer, // split in ARKit - LegacyBlendshapeCount -}; - // Original blendshapes were per Faceshift. // NEW in ARKit diff --git a/libraries/shared/src/BoxBase.h b/libraries/shared/src/BoxBase.h index 9bc2115d9e..1d64341740 100644 --- a/libraries/shared/src/BoxBase.h +++ b/libraries/shared/src/BoxBase.h @@ -18,7 +18,7 @@ #include #include -/**jsdoc +/*@jsdoc *

A BoxFace specifies the face of an axis-aligned (AA) box. *

* diff --git a/libraries/shared/src/ComponentMode.cpp b/libraries/shared/src/ComponentMode.cpp index 42ef820e2a..437af19886 100644 --- a/libraries/shared/src/ComponentMode.cpp +++ b/libraries/shared/src/ComponentMode.cpp @@ -8,7 +8,7 @@ #include "ComponentMode.h" -/**jsdoc +/*@jsdoc *

How an effect is applied in a {@link Entities.EntityProperties-Zone|Zone} entity.

*
* @@ -38,7 +38,7 @@ QString ComponentModeHelpers::getNameForComponentMode(ComponentMode mode) { return componentModeNames[(int)mode]; } -/**jsdoc +/*@jsdoc *

The priority of updates from avatars in a zone to other clients.

*
* diff --git a/libraries/shared/src/DebugDraw.h b/libraries/shared/src/DebugDraw.h index 9db48b759b..c5ba290514 100644 --- a/libraries/shared/src/DebugDraw.h +++ b/libraries/shared/src/DebugDraw.h @@ -21,7 +21,7 @@ #include #include -/**jsdoc +/*@jsdoc * The DebugDraw API renders debug markers and lines. These markers are only visible locally; they are not visible * to other users. * @@ -41,7 +41,7 @@ public: DebugDraw(); ~DebugDraw(); - /**jsdoc + /*@jsdoc * Draws a line in world space, visible for a single frame. To make the line visually persist, you need to repeatedly draw * it. * @function DebugDraw.drawRay @@ -60,7 +60,7 @@ public: */ Q_INVOKABLE void drawRay(const glm::vec3& start, const glm::vec3& end, const glm::vec4& color); - /**jsdoc + /*@jsdoc * Draws lines in world space, visible for a single frame. To make the lines visually persist, you need to repeatedly draw * them. *

Note: Currently doesn't work. @@ -86,7 +86,7 @@ public: Q_INVOKABLE void drawRays(const std::vector>& lines, const glm::vec4& color, const glm::vec3& translation = glm::vec3(0.0f, 0.0f, 0.0f), const glm::quat& rotation = glm::quat(1.0f, 0.0f, 0.0f, 0.0f)); - /**jsdoc + /*@jsdoc * Adds or updates a debug marker in world coordinates. This marker is drawn every frame until it is removed using * {@link DebugDraw.removeMarker|removeMarker}. If a world coordinates debug marker of the specified name * already exists, its parameters are updated. @@ -112,14 +112,14 @@ public: Q_INVOKABLE void addMarker(const QString& key, const glm::quat& rotation, const glm::vec3& position, const glm::vec4& color, float size = 1.0f); - /**jsdoc + /*@jsdoc * Removes a debug marker that was added in world coordinates. * @function DebugDraw.removeMarker * @param {string} key - The name of the world coordinates debug marker to remove. */ Q_INVOKABLE void removeMarker(const QString& key); - /**jsdoc + /*@jsdoc * Adds or updates a debug marker to the world in avatar coordinates. This marker is drawn every frame until it is removed * using {@link DebugDraw.removeMyAvatarMarker|removeMyAvatarMarker}. If an avatar coordinates debug marker of the * specified name already exists, its parameters are updated. The debug marker moves with your avatar. @@ -145,7 +145,7 @@ public: Q_INVOKABLE void addMyAvatarMarker(const QString& key, const glm::quat& rotation, const glm::vec3& position, const glm::vec4& color, float size = 1.0f); - /**jsdoc + /*@jsdoc * Removes a debug marker that was added in avatar coordinates. * @function DebugDraw.removeMyAvatarMarker * @param {string} key - The name of the avatar coordinates debug marker to remove. diff --git a/libraries/shared/src/GeometryUtil.h b/libraries/shared/src/GeometryUtil.h index d786d63980..dcfcbd2397 100644 --- a/libraries/shared/src/GeometryUtil.h +++ b/libraries/shared/src/GeometryUtil.h @@ -119,7 +119,7 @@ void swingTwistDecomposition(const glm::quat& rotation, glm::quat& swing, glm::quat& twist); -/**jsdoc +/*@jsdoc * A triangle in a mesh. * @typedef {object} Triangle * @property {Vec3} v0 - The position of vertex 0 in the triangle. diff --git a/libraries/shared/src/GizmoType.h b/libraries/shared/src/GizmoType.h index 20870158bc..ca091e63fe 100644 --- a/libraries/shared/src/GizmoType.h +++ b/libraries/shared/src/GizmoType.h @@ -11,7 +11,7 @@ #include "QString" -/**jsdoc +/*@jsdoc *

A {@link Entities.EntityProperties-Gizmo|Gizmo} entity may be one of the following types:

*
* diff --git a/libraries/shared/src/ModerationFlags.h b/libraries/shared/src/ModerationFlags.h new file mode 100644 index 0000000000..cf97f6249c --- /dev/null +++ b/libraries/shared/src/ModerationFlags.h @@ -0,0 +1,45 @@ +// +// ModerationFlags.h +// libraries/shared/src +// +// Created by Kalila L. on Mar 11 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 +// + +#ifndef vircadia_ModerationFlags_h +#define vircadia_ModerationFlags_h + +class ModerationFlags { +public: + + /*@jsdoc + *

A set of flags for moderation ban actions. The value is constructed by using the | (bitwise OR) operator on the + * individual flag values.

+ *
+ * + * + * + * + * + * + * + * + * + *
Flag NameValueDescription
NO_BAN0Don't ban user when kicking. This does not currently have an effect.
BAN_BY_USERNAME1Ban the person by their username.
BAN_BY_FINGERPRINT2Ban the person by their machine fingerprint.
BAN_BY_IP4Ban the person by their IP address.
+ * @typedef {number} BanFlags + */ + enum BanFlags + { + NO_BAN = 0, + BAN_BY_USERNAME = 1, + BAN_BY_FINGERPRINT = 2, + BAN_BY_IP = 4 + }; + + static constexpr unsigned int getDefaultBanFlags() { return (BanFlags::BAN_BY_USERNAME | BanFlags::BAN_BY_FINGERPRINT); }; +}; + +#endif // vircadia_ModerationFlags_h diff --git a/libraries/shared/src/PathUtils.h b/libraries/shared/src/PathUtils.h index 142cd7bfbc..41c2a6aef9 100644 --- a/libraries/shared/src/PathUtils.h +++ b/libraries/shared/src/PathUtils.h @@ -18,7 +18,7 @@ #include "DependencyManager.h" -/**jsdoc +/*@jsdoc * The Paths API provides absolute paths to the scripts and resources directories. * * @namespace Paths diff --git a/libraries/shared/src/PhysicsCollisionGroups.h b/libraries/shared/src/PhysicsCollisionGroups.h index 08fc5f5ac0..56e6dc21b4 100644 --- a/libraries/shared/src/PhysicsCollisionGroups.h +++ b/libraries/shared/src/PhysicsCollisionGroups.h @@ -71,7 +71,7 @@ const int32_t BULLET_COLLISION_MASK_DETAILED_RAY = BULLET_COLLISION_GROUP_DETAIL // COLLISIONLESS gets an empty mask. const int32_t BULLET_COLLISION_MASK_COLLISIONLESS = 0; -/**jsdoc +/*@jsdoc *

A collision may occur with the following types of items:

* * diff --git a/libraries/shared/src/PickFilter.h b/libraries/shared/src/PickFilter.h index d3d6673f50..1cc1a8b0b5 100644 --- a/libraries/shared/src/PickFilter.h +++ b/libraries/shared/src/PickFilter.h @@ -15,7 +15,7 @@ class PickFilter { public: - /**jsdoc + /*@jsdoc *

A set of flags for a pick filter. The value is constructed by using the | (bitwise OR) operator on the * individual flag values.

*
diff --git a/libraries/shared/src/PointerEvent.cpp b/libraries/shared/src/PointerEvent.cpp index 54374a934c..be237442c0 100644 --- a/libraries/shared/src/PointerEvent.cpp +++ b/libraries/shared/src/PointerEvent.cpp @@ -65,7 +65,7 @@ void PointerEvent::setButton(Button button) { _buttons |= button; } -/**jsdoc +/*@jsdoc * A 2D or 3D mouse or similar pointer event. * @typedef {object} PointerEvent * @property {string} type - The type of event: "Press", "DoublePress", "Release", or @@ -99,7 +99,7 @@ void PointerEvent::setButton(Button button) { * @property {KeyboardModifiers} keyboardModifiers - Integer value with bits set according to which keyboard modifier keys were * pressed when the event was generated. */ -/**jsdoc +/*@jsdoc *

A KeyboardModifiers value is used to specify which modifier keys on the keyboard are pressed. The value is the sum * (bitwise OR) of the relevant combination of values from the following table:

*
diff --git a/libraries/shared/src/Preferences.h b/libraries/shared/src/Preferences.h index 9147117792..a195dc457f 100644 --- a/libraries/shared/src/Preferences.h +++ b/libraries/shared/src/Preferences.h @@ -153,7 +153,7 @@ class FloatPreference : public Preference { Q_PROPERTY(float min READ getMin CONSTANT) Q_PROPERTY(float max READ getMax CONSTANT) Q_PROPERTY(float step READ getStep CONSTANT) - Q_PROPERTY(float decimals READ getDecimals CONSTANT) + Q_PROPERTY(uint decimals READ getDecimals CONSTANT) public: using Getter = std::function; @@ -194,10 +194,10 @@ protected: const Getter _getter; const Setter _setter; - float _decimals { 0 }; + uint _decimals { 0 }; float _min { 0 }; float _max { 1 }; - float _step { 0.1f }; + float _step { 1 }; }; class IntPreference : public Preference { diff --git a/libraries/shared/src/PrimitiveMode.h b/libraries/shared/src/PrimitiveMode.h index 421b940aa1..6dd65ec0c7 100644 --- a/libraries/shared/src/PrimitiveMode.h +++ b/libraries/shared/src/PrimitiveMode.h @@ -11,7 +11,7 @@ #include "QString" -/**jsdoc +/*@jsdoc *

How the geometry of an entity is rendered.

*
* diff --git a/libraries/shared/src/PulseMode.h b/libraries/shared/src/PulseMode.h index 4e398cbbaa..8d4c24b4be 100644 --- a/libraries/shared/src/PulseMode.h +++ b/libraries/shared/src/PulseMode.h @@ -11,7 +11,7 @@ #include "QString" -/**jsdoc +/*@jsdoc *

Pulse modes for color and alpha pulsing.

*
* diff --git a/libraries/shared/src/RegisteredMetaTypes.cpp b/libraries/shared/src/RegisteredMetaTypes.cpp index d47cc0769a..c8b03694eb 100644 --- a/libraries/shared/src/RegisteredMetaTypes.cpp +++ b/libraries/shared/src/RegisteredMetaTypes.cpp @@ -1084,7 +1084,7 @@ QScriptValue qColorToScriptValue(QScriptEngine* engine, const QColor& color) { return object; } -/**jsdoc +/*@jsdoc * An axis-aligned cube, defined as the bottom right near (minimum axes values) corner of the cube plus the dimension of its * sides. * @typedef {object} AACube @@ -1169,7 +1169,7 @@ void pickRayFromScriptValue(const QScriptValue& object, PickRay& pickRay) { } } -/**jsdoc +/*@jsdoc * Details of a collision between avatars and entities. * @typedef {object} Collision * @property {ContactEventType} type - The contact type of the collision event. @@ -1218,7 +1218,7 @@ void quuidFromScriptValue(const QScriptValue& object, QUuid& uuid) { uuid = fromString; } -/**jsdoc +/*@jsdoc * A 2D size value. * @typedef {object} Size * @property {number} height - The height value. @@ -1248,7 +1248,7 @@ AnimationDetails::AnimationDetails(QString role, QUrl url, float fps, float prio running(running), currentFrame(currentFrame), allowTranslation(allowTranslation) { } -/**jsdoc +/*@jsdoc * The details of an animation that is playing. * @typedef {object} Avatar.AnimationDetails * @property {string} role - Not used. @@ -1324,7 +1324,7 @@ void meshesFromScriptValue(const QScriptValue& value, MeshProxyList &out) { } -/**jsdoc +/*@jsdoc * A triangle in a mesh. * @typedef {object} MeshFace * @property {number[]} vertices - The indexes of the three vertices that make up the face. diff --git a/libraries/shared/src/RegisteredMetaTypes.h b/libraries/shared/src/RegisteredMetaTypes.h index 49a73d40c2..39245b5a49 100644 --- a/libraries/shared/src/RegisteredMetaTypes.h +++ b/libraries/shared/src/RegisteredMetaTypes.h @@ -46,7 +46,7 @@ Q_DECLARE_METATYPE(std::function); void registerMetaTypes(QScriptEngine* engine); // Mat4 -/**jsdoc +/*@jsdoc * A 4 x 4 matrix, typically containing a scale, rotation, and translation transform. See also the {@link Mat4(0)|Mat4} object. * * @typedef {object} Mat4 @@ -74,7 +74,7 @@ QVariant mat4ToVariant(const glm::mat4& mat4); glm::mat4 mat4FromVariant(const QVariant& object, bool& valid); glm::mat4 mat4FromVariant(const QVariant& object); -/**jsdoc +/*@jsdoc * A 2-dimensional vector. * * @typedef {object} Vec2 @@ -95,7 +95,7 @@ QVariant vec2ToVariant(const glm::vec2& vec2); glm::vec2 vec2FromVariant(const QVariant& object, bool& valid); glm::vec2 vec2FromVariant(const QVariant& object); -/**jsdoc +/*@jsdoc * A 3-dimensional vector. See also the {@link Vec3(0)|Vec3} object. * * @typedef {object} Vec3 @@ -123,7 +123,7 @@ QVariant vec3toVariant(const glm::vec3& vec3); glm::vec3 vec3FromVariant(const QVariant &object, bool& valid); glm::vec3 vec3FromVariant(const QVariant &object); -/**jsdoc +/*@jsdoc * A color vector. See also the {@link Vec3(0)|Vec3} object. * * @typedef {object} Color @@ -142,7 +142,7 @@ glm::vec3 vec3FromVariant(const QVariant &object); * Entities.editEntity(, { color: "red"}); // { red: 255, green: 0, blue: 0 } * Entities.editEntity(, { color: "#00FF00"}); // { red: 0, green: 255, blue: 0 } */ -/**jsdoc +/*@jsdoc * A color vector with real values. Values may also be null. See also the {@link Vec3(0)|Vec3} object. * * @typedef {object} ColorFloat @@ -170,7 +170,7 @@ QVariant u8vec3ColortoVariant(const glm::u8vec3& vec3); glm::u8vec3 u8vec3FromVariant(const QVariant &object, bool& valid); glm::u8vec3 u8vec3FromVariant(const QVariant &object); -/**jsdoc +/*@jsdoc * A 4-dimensional vector. * * @typedef {object} Vec4 @@ -193,7 +193,7 @@ QVariant quatToVariant(const glm::quat& quat); glm::quat quatFromVariant(const QVariant &object, bool& isValid); glm::quat quatFromVariant(const QVariant &object); -/**jsdoc +/*@jsdoc * Defines a rectangular portion of an image or screen, or similar. * @typedef {object} Rect * @property {number} x - Left, x-coordinate value. @@ -262,7 +262,7 @@ public: virtual QVariantMap toVariantMap() const = 0; }; -/**jsdoc +/*@jsdoc * A vector with a starting point. It is used, for example, when finding entities or avatars that lie under a mouse click or * intersect a laser beam. * @@ -295,7 +295,7 @@ Q_DECLARE_METATYPE(PickRay) QScriptValue pickRayToScriptValue(QScriptEngine* engine, const PickRay& pickRay); void pickRayFromScriptValue(const QScriptValue& object, PickRay& pickRay); -/**jsdoc +/*@jsdoc * The tip of a stylus. * * @typedef {object} StylusTip @@ -338,7 +338,7 @@ public: } }; -/**jsdoc +/*@jsdoc * A parabola defined by a starting point, initial velocity, and acceleration. It is used, for example, when finding entities or * avatars that intersect a parabolic beam. * @@ -428,7 +428,7 @@ public: } } - /**jsdoc + /*@jsdoc * A volume for checking collisions in the physics simulation. * @typedef {object} CollisionRegion * @property {Shape} shape - The collision region's shape and size. Dimensions are in world coordinates, but scale with the @@ -443,7 +443,7 @@ public: * masks overlap with the region's collision group are considered to be colliding with the region. */ - /**jsdoc + /*@jsdoc * A physical volume. * @typedef {object} Shape * @property {ShapeType} shapeType="none" - The type of shape. @@ -607,7 +607,7 @@ namespace std { #endif } -/**jsdoc +/*@jsdoc *

The type of a collision contact event.

*
* @@ -647,7 +647,7 @@ Q_DECLARE_METATYPE(Collision) QScriptValue collisionToScriptValue(QScriptEngine* engine, const Collision& collision); void collisionFromScriptValue(const QScriptValue &object, Collision& collision); -/**jsdoc +/*@jsdoc * UUIDs (Universally Unique IDentifiers) are used to uniquely identify entities, avatars, and the like. They are represented * in JavaScript as strings in the format, "{nnnnnnnn-nnnn-nnnn-nnnn-nnnnnnnnnnnn}", where the "n"s are * hexadecimal digits. @@ -690,7 +690,7 @@ namespace graphics { using MeshPointer = std::shared_ptr; -/**jsdoc +/*@jsdoc * A mesh, such as returned by {@link Entities.getMeshes} or {@link Model} API functions. * * @class MeshProxy @@ -710,14 +710,14 @@ class MeshProxy : public QObject { public: virtual MeshPointer getMeshPointer() const = 0; - /**jsdoc + /*@jsdoc * Gets the number of vertices in the mesh. * @function MeshProxy#getNumVertices * @returns {number} Integer number of vertices in the mesh. */ Q_INVOKABLE virtual int getNumVertices() const = 0; - /**jsdoc + /*@jsdoc * Gets the position of a vertex in the mesh. * @function MeshProxy#getPos * @param {number} index - Integer index of the vertex. diff --git a/libraries/shared/src/RenderLayer.h b/libraries/shared/src/RenderLayer.h index caa1e54f58..e0c249a001 100644 --- a/libraries/shared/src/RenderLayer.h +++ b/libraries/shared/src/RenderLayer.h @@ -11,7 +11,7 @@ #include "QString" -/**jsdoc +/*@jsdoc *

A layer in which an entity may be rendered.

*
* diff --git a/libraries/shared/src/ResourceRequestObserver.cpp b/libraries/shared/src/ResourceRequestObserver.cpp index 21f4d56173..3d44dc6979 100644 --- a/libraries/shared/src/ResourceRequestObserver.cpp +++ b/libraries/shared/src/ResourceRequestObserver.cpp @@ -16,7 +16,7 @@ #include #include -/**jsdoc +/*@jsdoc * Information about a resource request. * @typedef {object} ResourceRequestObserver.ResourceRequest * @property {string} url - The URL of the resource request. diff --git a/libraries/shared/src/ResourceRequestObserver.h b/libraries/shared/src/ResourceRequestObserver.h index 352f01c3a5..808b89c8b3 100644 --- a/libraries/shared/src/ResourceRequestObserver.h +++ b/libraries/shared/src/ResourceRequestObserver.h @@ -16,7 +16,7 @@ #include "DependencyManager.h" -/**jsdoc +/*@jsdoc * The ResourceRequestObserver API provides notifications when an observable resource request is made. * * @namespace ResourceRequestObserver @@ -33,7 +33,7 @@ public: void update(const QUrl& requestUrl, const qint64 callerId = -1, const QString& extra = ""); signals: - /**jsdoc + /*@jsdoc * Triggered when an observable resource request is made. * @function ResourceRequestObserver.resourceRequestEvent * @param {ResourceRequestObserver.ResourceRequest} request - Information about the resource request. diff --git a/libraries/shared/src/ShapeInfo.cpp b/libraries/shared/src/ShapeInfo.cpp index c60d1c2574..0f2bae1170 100644 --- a/libraries/shared/src/ShapeInfo.cpp +++ b/libraries/shared/src/ShapeInfo.cpp @@ -16,7 +16,7 @@ #include "HashKey.h" #include "NumericalConstants.h" // for MILLIMETERS_PER_METER -/**jsdoc +/*@jsdoc *

Defines the shape used for collisions or zones.

*
* @@ -115,12 +115,6 @@ void ShapeInfo::setParams(ShapeType type, const glm::vec3& halfExtents, QString case SHAPE_TYPE_HULL: case SHAPE_TYPE_MULTISPHERE: break; - case SHAPE_TYPE_SPHERE: { - float radius = glm::length(halfExtents) / SQUARE_ROOT_OF_3; - radius = glm::max(radius, MIN_HALF_EXTENT); - _halfExtents = glm::vec3(radius); - } - break; case SHAPE_TYPE_CIRCLE: { _halfExtents = glm::vec3(_halfExtents.x, MIN_HALF_EXTENT, _halfExtents.z); } @@ -228,6 +222,7 @@ float ShapeInfo::computeVolume() const { volume = 8.0f * _halfExtents.x * _halfExtents.y * _halfExtents.z; break; } + case SHAPE_TYPE_ELLIPSOID: case SHAPE_TYPE_SPHERE: { volume = 4.0f * PI * _halfExtents.x * _halfExtents.y * _halfExtents.z / 3.0f; break; diff --git a/libraries/shared/src/SpatiallyNestable.cpp b/libraries/shared/src/SpatiallyNestable.cpp index 670b03611b..69f3539152 100644 --- a/libraries/shared/src/SpatiallyNestable.cpp +++ b/libraries/shared/src/SpatiallyNestable.cpp @@ -1407,7 +1407,7 @@ SpatiallyNestablePointer SpatiallyNestable::findByID(QUuid id, bool& success) { return parentWP.lock(); } -/**jsdoc +/*@jsdoc *

An in-world item may be one of the following types:

*
* diff --git a/libraries/shared/src/TextAlignment.h b/libraries/shared/src/TextAlignment.h index 829b07dc36..b82d8e8c57 100644 --- a/libraries/shared/src/TextAlignment.h +++ b/libraries/shared/src/TextAlignment.h @@ -11,7 +11,7 @@ #include "QString" -/**jsdoc +/*@jsdoc *

A {@link Entities.EntityProperties-Text|Text} entity may use one of the following alignments:

*
* diff --git a/libraries/shared/src/TextEffect.h b/libraries/shared/src/TextEffect.h index 3e205f72fe..09affc1f4e 100644 --- a/libraries/shared/src/TextEffect.h +++ b/libraries/shared/src/TextEffect.h @@ -11,7 +11,7 @@ #include "QString" -/**jsdoc +/*@jsdoc *

A {@link Entities.EntityProperties-Text|Text} entity may use one of the following effects:

*
* diff --git a/libraries/shared/src/WebInputMode.h b/libraries/shared/src/WebInputMode.h index 4f43691ac9..a65ae1341c 100644 --- a/libraries/shared/src/WebInputMode.h +++ b/libraries/shared/src/WebInputMode.h @@ -11,7 +11,7 @@ #include "QString" -/**jsdoc +/*@jsdoc *

Specifies how a web surface processes events.

*
* diff --git a/libraries/shared/src/shared/Camera.cpp b/libraries/shared/src/shared/Camera.cpp index 85761e0d29..55ee69d08a 100644 --- a/libraries/shared/src/shared/Camera.cpp +++ b/libraries/shared/src/shared/Camera.cpp @@ -10,7 +10,7 @@ #include "Camera.h" -/**jsdoc +/*@jsdoc *

Camera modes affect the position of the camera and the controls for camera movement. The camera can be in one of the * following modes:

*
@@ -215,7 +215,7 @@ void Camera::loadViewFrustum(ViewFrustum& frustum) const { frustum.calculate(); } -/**jsdoc +/*@jsdoc * A ViewFrustum has a "keyhole" shape: a regular frustum for stuff that is visible plus a central sphere for stuff that is * nearby (for physics simulation). * diff --git a/libraries/shared/src/shared/Camera.h b/libraries/shared/src/shared/Camera.h index f494318c73..7247eb16a6 100644 --- a/libraries/shared/src/shared/Camera.h +++ b/libraries/shared/src/shared/Camera.h @@ -68,28 +68,28 @@ public: QVariantMap getViewFrustum(); public slots: - /**jsdoc + /*@jsdoc * Gets the current camera mode. You can also get the mode using the {@link Camera|Camera.mode} property. * @function Camera.getModeString * @returns {Camera.Mode} The current camera mode. */ QString getModeString() const; - /**jsdoc + /*@jsdoc * Sets the camera mode. You can also set the mode using the {@link Camera|Camera.mode} property. * @function Camera.setModeString * @param {Camera.Mode} mode - The mode to set the camera to. */ void setModeString(const QString& mode); - /**jsdoc + /*@jsdoc * Gets the current camera position. You can also get the position using the {@link Camera|Camera.position} property. * @function Camera.getPosition * @returns {Vec3} The current camera position. */ glm::vec3 getPosition() const { return _position; } - /**jsdoc + /*@jsdoc * Sets the camera position. You can also set the position using the {@link Camera|Camera.position} property. Only works if * the camera is in independent mode. * @function Camera.setPosition @@ -97,7 +97,7 @@ public slots: */ void setPosition(const glm::vec3& position); - /**jsdoc + /*@jsdoc * Gets the current camera orientation. You can also get the orientation using the {@link Camera|Camera.orientation} * property. * @function Camera.getOrientation @@ -105,7 +105,7 @@ public slots: */ glm::quat getOrientation() const { return _orientation; } - /**jsdoc + /*@jsdoc * Sets the camera orientation. You can also set the orientation using the {@link Camera|Camera.orientation} property. Only * works if the camera is in independent mode. * @function Camera.setOrientation @@ -113,7 +113,7 @@ public slots: */ void setOrientation(const glm::quat& orientation); - /**jsdoc + /*@jsdoc * Gets the current mouse capture state. * @function Camera.getCaptureMouse * @returns {boolean} true if the mouse is captured (is invisible and cannot leave the bounds of Interface, @@ -121,7 +121,7 @@ public slots: */ bool getCaptureMouse() const { return _captureMouse; } - /**jsdoc + /*@jsdoc * Sets the mouse capture state. When true, the mouse is invisible and cannot leave the bounds of * Interface, as long as Interface is the active window and no menu item is selected. When false, the mouse * behaves normally. @@ -130,21 +130,21 @@ public slots: */ void setCaptureMouse(bool captureMouse) { _captureMouse = captureMouse; emit captureMouseChanged(captureMouse); } - /**jsdoc + /*@jsdoc * Gets the current camera sensitivity. * @function Camera.getSensitivity * @returns {number} The current camera sensitivity. Must be positive. */ float getSensitivity() const { return _sensitivity; } - /**jsdoc + /*@jsdoc * Sets the camera sensitivity. Higher values mean that the camera will be more sensitive to mouse movements. * @function Camera.setSensitivity * @param {number} sensitivity - The desired camera sensitivity. Must be positive. */ void setSensitivity(float sensitivity) { _sensitivity = glm::max(0.0f, sensitivity); } - /**jsdoc + /*@jsdoc * Computes a {@link PickRay} based on the current camera configuration and the specified x, y position on the * screen. The {@link PickRay} can be used in functions such as {@link Entities.findRayIntersection} and * {@link Overlays.findRayIntersection}. @@ -165,7 +165,7 @@ public slots: */ virtual PickRay computePickRay(float x, float y) const = 0; - /**jsdoc + /*@jsdoc * Rotates the camera to look at the specified position. Only works if the camera is in independent mode. * @function Camera.lookAt * @param {Vec3} position - The position to look at. @@ -186,7 +186,7 @@ public slots: */ void lookAt(const glm::vec3& position); - /**jsdoc + /*@jsdoc * Sets the camera to continue looking at the specified position even while the camera moves. Only works if * the camera is in independent mode. * @function Camera.keepLookingAt @@ -194,14 +194,14 @@ public slots: */ void keepLookingAt(const glm::vec3& position); - /**jsdoc + /*@jsdoc * Stops the camera from continually looking at the position that was set with {@link Camera.keepLookingAt}. * @function Camera.stopLookingAt */ void stopLooking() { _isKeepLookingAt = false; } signals: - /**jsdoc + /*@jsdoc * Triggered when the camera mode changes. * @function Camera.modeUpdated * @param {Camera.Mode} newMode - The new camera mode. @@ -215,7 +215,7 @@ signals: */ void modeUpdated(const QString& newMode); - /**jsdoc + /*@jsdoc * Triggered when the camera mouse capture state changes. * @function Camera.captureMouseChanged * @param {boolean} newCaptureMouse - The new mouse capture state. diff --git a/libraries/task/src/task/Config.h b/libraries/task/src/task/Config.h index 7e6be9b53e..c4a7b8ebbe 100644 --- a/libraries/task/src/task/Config.h +++ b/libraries/task/src/task/Config.h @@ -91,7 +91,7 @@ public: using Config = JobConfig; }; -/**jsdoc +/*@jsdoc * @namespace Workload * * @hifi-interface @@ -132,14 +132,14 @@ public: virtual void setPresetList(const QJsonObject& object); - /**jsdoc + /*@jsdoc * @function Workload.toJSON * @returns {string} */ // This must be named toJSON to integrate with the global scripting JSON object Q_INVOKABLE QString toJSON() { return QJsonDocument(toJsonValue(*this).toObject()).toJson(QJsonDocument::Compact); } - /**jsdoc + /*@jsdoc * @function Workload.load * @param {object} map */ @@ -150,7 +150,7 @@ public: void setCPURunTime(const std::chrono::nanoseconds& runtime) { _msCPURunTime = std::chrono::duration(runtime).count(); emit newStats(); } double getCPURunTime() const { return _msCPURunTime; } - /**jsdoc + /*@jsdoc * @function Workload.getConfig * @param {string} name * @returns {object} @@ -173,19 +173,19 @@ public: } // Describe the node graph data connections of the associated Job/Task - /**jsdoc + /*@jsdoc * @function Workload.isTask * @returns {boolean} */ Q_INVOKABLE bool isTask() const { return _isTask; } - /**jsdoc + /*@jsdoc * @function Workload.isSwitch * @returns {boolean} */ Q_INVOKABLE bool isSwitch() const { return _isSwitch; } - /**jsdoc + /*@jsdoc * @function Workload.getSubConfigs * @returns {object[]} */ @@ -198,13 +198,13 @@ public: return returned; } - /**jsdoc + /*@jsdoc * @function Workload.getNumSubs * @returns {number} */ Q_INVOKABLE int getNumSubs() const { return getSubConfigs().size(); } - /**jsdoc + /*@jsdoc * @function Workload.getSubConfig * @param {number} index * @returns {object} @@ -224,32 +224,32 @@ public: public slots: - /**jsdoc + /*@jsdoc * @function Workload.load * @param {object} json */ void load(const QJsonObject& val) { qObjectFromJsonValue(val, *this); emit loaded(); } - /**jsdoc + /*@jsdoc * @function Workload.refresh */ void refresh(); signals: - /**jsdoc + /*@jsdoc * @function Workload.loaded * @returns {Signal} */ void loaded(); - /**jsdoc + /*@jsdoc * @function Workload.newStats * @returns {Signal} */ void newStats(); - /**jsdoc + /*@jsdoc * @function Workload.dirtyEnabled * @returns {Signal} */ diff --git a/libraries/ui/src/OffscreenUi.cpp b/libraries/ui/src/OffscreenUi.cpp index 26e77dcb5f..d5fa6609d4 100644 --- a/libraries/ui/src/OffscreenUi.cpp +++ b/libraries/ui/src/OffscreenUi.cpp @@ -32,7 +32,7 @@ #include #include "MainWindow.h" -/**jsdoc +/*@jsdoc * The OffscreenFlags API enables gamepad joystick navigation of UI. * *

This API currently has no effect and is not used.

@@ -78,14 +78,14 @@ public: signals: - /**jsdoc + /*@jsdoc * Triggered when the value of the navigationFocused property changes. * @function OffscreenFlags.navigationFocusedChanged * @returns {Signal} */ void navigationFocusedChanged(); - /**jsdoc + /*@jsdoc * Triggered when the value of the navigationFocusDisabled property changes. * @function OffscreenFlags.navigationFocusDisabledChanged * @returns {Signal} diff --git a/libraries/ui/src/QmlFragmentClass.h b/libraries/ui/src/QmlFragmentClass.h index ea80b2bd13..c76bb43513 100644 --- a/libraries/ui/src/QmlFragmentClass.h +++ b/libraries/ui/src/QmlFragmentClass.h @@ -27,7 +27,7 @@ public: QmlFragmentClass(bool restricted, QString id); - /**jsdoc + /*@jsdoc * Creates a new button, adds it to this and returns it. * @function QmlFragmentClass#addButton * @param properties {object} button properties diff --git a/libraries/ui/src/QmlWebWindowClass.h b/libraries/ui/src/QmlWebWindowClass.h index feca148614..384bdadfc4 100644 --- a/libraries/ui/src/QmlWebWindowClass.h +++ b/libraries/ui/src/QmlWebWindowClass.h @@ -11,7 +11,7 @@ #include "QmlWindowClass.h" -/**jsdoc +/*@jsdoc * A OverlayWebWindow displays an HTML window inside Interface. * *

Create using new OverlayWebWindow(...).

@@ -63,25 +63,25 @@ * @borrows OverlayWindow.qmlToScript as qmlToScript */ -/**jsdoc +/*@jsdoc * @function OverlayWebWindow.clearDebugWindow * @deprecated This method is deprecated and will be removed. */ -/**jsdoc +/*@jsdoc * @function OverlayWebWindow.sendToQML * @param {string | object} message - Message. * @deprecated This method is deprecated and will be removed. */ -/**jsdoc +/*@jsdoc * @function OverlayWebWindow.fromQML * @param {object} message - Message. * @returns {Signal} * @deprecated This signal is deprecated and will be removed. */ -/**jsdoc +/*@jsdoc * Sends a message to the HTML page. To receive the message, the HTML page's script must connect to the EventBridge * that is automatically provided for the script: *
EventBridge.scriptEventReceived.connect(function(message) {
@@ -127,7 +127,7 @@
  * 
  */
 
-/**jsdoc
+/*@jsdoc
  * Triggered when a message from the HTML page is received. The HTML page can send a message by calling:
  * 
EventBridge.emitWebEvent(message);
* @function OverlayWebWindow.webEventReceived @@ -156,21 +156,21 @@ public: public slots: - /**jsdoc + /*@jsdoc * Gets the URL of the HTML displayed. * @function OverlayWebWindow.getURL * @returns {string} - The URL of the HTML page displayed. */ QString getURL(); - /**jsdoc + /*@jsdoc * Loads HTML into the window, replacing current window content. * @function OverlayWebWindow.setURL * @param {string} url - The URL of the HTML to display. */ void setURL(const QString& url); - /**jsdoc + /*@jsdoc * Injects a script into the HTML page, replacing any currently injected script. * @function OverlayWebWindow.setScriptURL * @param {string} url - The URL of the script to inject. @@ -178,7 +178,7 @@ public slots: void setScriptURL(const QString& script); signals: - /**jsdoc + /*@jsdoc * Triggered when the window's URL changes. * @function OverlayWebWindow.urlChanged * @returns {Signal} diff --git a/libraries/ui/src/QmlWindowClass.cpp b/libraries/ui/src/QmlWindowClass.cpp index ae2292dc09..a19b9eb767 100644 --- a/libraries/ui/src/QmlWindowClass.cpp +++ b/libraries/ui/src/QmlWindowClass.cpp @@ -88,7 +88,7 @@ QmlWindowClass::QmlWindowClass(bool restricted) : _restricted(restricted) { } -/**jsdoc +/*@jsdoc * Properties used to initialize an {@link OverlayWindow} or {@link OverlayWebWindow}. * @typedef {object} OverlayWindow.Properties * @property {string} [title="WebWindow] - The window title. diff --git a/libraries/ui/src/QmlWindowClass.h b/libraries/ui/src/QmlWindowClass.h index 3a2f202bd3..e911afea6c 100644 --- a/libraries/ui/src/QmlWindowClass.h +++ b/libraries/ui/src/QmlWindowClass.h @@ -19,7 +19,7 @@ class QScriptEngine; class QScriptContext; -/**jsdoc +/*@jsdoc * A OverlayWindow displays a QML window inside Interface. * *

The QML can optionally include a WebView control that embeds an HTML-based windows. (The WebView @@ -66,7 +66,7 @@ public: QmlWindowClass(bool restricted); ~QmlWindowClass(); - /**jsdoc + /*@jsdoc * @function OverlayWindow.initQml * @param {OverlayWindow.Properties} properties - Properties. * @deprecated This method is deprecated and will be removed. @@ -80,14 +80,14 @@ public: public slots: - /**jsdoc + /*@jsdoc * Gets whether the window is shown or hidden. * @function OverlayWindow.isVisible * @returns {boolean} code>true if the window is shown, false if it is hidden. */ bool isVisible(); - /**jsdoc + /*@jsdoc * Shows or hides the window. * @function OverlayWindow.setVisible * @param {boolean} visible - code>true to show the window, false to hide it. @@ -95,21 +95,21 @@ public slots: void setVisible(bool visible); - /**jsdoc + /*@jsdoc * Gets the position of the window. * @function OverlayWindow.getPosition * @returns {Vec2} The position of the window, in pixels. */ glm::vec2 getPosition(); - /**jsdoc + /*@jsdoc * Sets the position of the window, from a {@link Vec2}. * @function OverlayWindow.setPosition * @param {Vec2} position - The position of the window, in pixels. */ void setPosition(const glm::vec2& position); - /**jsdoc + /*@jsdoc * Sets the position of the window, from a pair of numbers. * @function OverlayWindow.setPosition * @param {number} x - The x position of the window, in pixels. @@ -118,21 +118,21 @@ public slots: void setPosition(int x, int y); - /**jsdoc + /*@jsdoc * Gets the size of the window interior. * @function OverlayWindow.getSize * @returns {Vec2} The size of the window interior, in pixels. */ glm::vec2 getSize(); - /**jsdoc + /*@jsdoc * Sets the size of the window interior, from a {@link Vec2}. * @function OverlayWindow.setSize * @param {Vec2} size - The size of the window interior, in pixels. */ void setSize(const glm::vec2& size); - /**jsdoc + /*@jsdoc * Sets the size of the window interior, from a pair of numbers. * @function OverlayWindow.setSize * @param {number} width - The width of the window interior, in pixels. @@ -140,27 +140,27 @@ public slots: */ void setSize(int width, int height); - /**jsdoc + /*@jsdoc * Sets the window title. * @function OverlayWindow.setTitle * @param {string} title - The window title. */ void setTitle(const QString& title); - /**jsdoc + /*@jsdoc * Raises the window to the top. * @function OverlayWindow.raise */ Q_INVOKABLE void raise(); - /**jsdoc + /*@jsdoc * Closes the window. *

Note: The window also closes when the script ends.

* @function OverlayWindow.close */ Q_INVOKABLE void close(); - /**jsdoc + /*@jsdoc * @function OverlayWindow.getEventBridge * @returns {object} Object. * @deprecated This method is deprecated and will be removed. @@ -169,7 +169,7 @@ public slots: Q_INVOKABLE QObject* getEventBridge() { return this; }; - /**jsdoc + /*@jsdoc * Sends a message to the QML. To receive the message, the QML must implement a function: *
function fromScript(message) {
      *   ...
@@ -219,13 +219,13 @@ public slots:
     // Scripts can use this to send a message to the QML object
     void sendToQml(const QVariant& message);
 
-    /**jsdoc
+    /*@jsdoc
      * Calls a clearWindow() function if present in the QML.
      * @function OverlayWindow.clearDebugWindow
      */
     void clearDebugWindow();
 
-    /**jsdoc
+    /*@jsdoc
      * Sends a message to an embedded HTML web page. To receive the message, the HTML page's script must connect to the
      * EventBridge that is automatically provided for the script:
      * 
EventBridge.scriptEventReceived.connect(function(message) {
@@ -237,7 +237,7 @@ public slots:
     // QmlWindow content may include WebView requiring EventBridge.
     void emitScriptEvent(const QVariant& scriptMessage);
 
-    /**jsdoc
+    /*@jsdoc
      * @function OverlayWindow.emitWebEvent
      * @param {object|string} message - The message.
      * @deprecated This function is deprecated and will be removed.
@@ -246,28 +246,28 @@ public slots:
 
 signals:
 
-    /**jsdoc
+    /*@jsdoc
      * Triggered when the window is hidden or shown.
      * @function OverlayWindow.visibleChanged
      * @returns {Signal}
      */
     void visibleChanged();
 
-    /**jsdoc
+    /*@jsdoc
      * Triggered when the window changes position.
      * @function OverlayWindow.positionChanged
      * @returns {Signal}
      */
     void positionChanged();
 
-    /**jsdoc
+    /*@jsdoc
      * Triggered when the window changes size.
      * @function OverlayWindow.sizeChanged
      * @returns {Signal}
      */
     void sizeChanged();
 
-    /**jsdoc
+    /*@jsdoc
      * Triggered when the window changes position.
      * @function OverlayWindow.moved
      * @param {Vec2} position - The position of the window, in pixels.
@@ -275,7 +275,7 @@ signals:
      */
     void moved(glm::vec2 position);
 
-    /**jsdoc
+    /*@jsdoc
      * Triggered when the window changes size.
      * @function OverlayWindow.resized
      * @param {Size} size - The size of the window interior, in pixels.
@@ -283,14 +283,14 @@ signals:
      */
     void resized(QSizeF size);
 
-    /**jsdoc
+    /*@jsdoc
      * Triggered when the window is closed.
      * @function OverlayWindow.closed
      * @returns {Signal}
      */
     void closed();
 
-    /**jsdoc
+    /*@jsdoc
      * Triggered when a message from the QML page is received. The QML page can send a message (string or object) by calling:
      * 
sendToScript(message);
* @function OverlayWindow.fromQml @@ -301,7 +301,7 @@ signals: void fromQml(const QVariant& message); - /**jsdoc + /*@jsdoc * @function OverlayWindow.scriptEventReceived * @param {object} message - The message. * @returns {Signal} @@ -310,7 +310,7 @@ signals: // QmlWindow content may include WebView requiring EventBridge. void scriptEventReceived(const QVariant& message); - /**jsdoc + /*@jsdoc * Triggered when a message from an embedded HTML page is received. The HTML page can send a message by calling: *
EventBridge.emitWebEvent(message);
* @function OverlayWindow.webEventReceived @@ -321,7 +321,7 @@ signals: protected slots: - /**jsdoc + /*@jsdoc * @function OverlayWindow.hasMoved * @param {Vec2} position - Position. * @deprecated This method is deprecated and will be removed. @@ -329,14 +329,14 @@ protected slots: // Shouldn't be in the API: it is just connected to in order to emit a signal. void hasMoved(QVector2D); - /**jsdoc + /*@jsdoc * @function OverlayWindow.hasClosed * @deprecated This method is deprecated and will be removed. */ // Shouldn't be in the API: it is just connected to in order to emit a signal. void hasClosed(); - /**jsdoc + /*@jsdoc * @function OverlayWindow.qmlToScript * @param {object} message - Message. * @deprecated This method is deprecated and will be removed. diff --git a/libraries/ui/src/ui/TabletScriptingInterface.cpp b/libraries/ui/src/ui/TabletScriptingInterface.cpp index e80b11915a..82c9c43ce1 100644 --- a/libraries/ui/src/ui/TabletScriptingInterface.cpp +++ b/libraries/ui/src/ui/TabletScriptingInterface.cpp @@ -1013,7 +1013,7 @@ const QString OBJECT_NAME_KEY = "objectName"; const QString STABLE_ORDER_KEY = "stableOrder"; static int s_stableOrder = 1; -/**jsdoc +/*@jsdoc * Properties of a tablet button. * * @typedef {object} TabletButtonProxy.ButtonProperties diff --git a/libraries/ui/src/ui/TabletScriptingInterface.h b/libraries/ui/src/ui/TabletScriptingInterface.h index 5468ee18c3..0b1af6451a 100644 --- a/libraries/ui/src/ui/TabletScriptingInterface.h +++ b/libraries/ui/src/ui/TabletScriptingInterface.h @@ -38,7 +38,7 @@ class TabletButtonProxy; class QmlWindowClass; class OffscreenQmlSurface; -/**jsdoc +/*@jsdoc * The Tablet API provides the facilities to work with the system or other tablet. In toolbar mode (see Developer * > UI options), the tablet's menu buttons are displayed in a toolbar and other tablet content is displayed in a dialog. * @@ -50,7 +50,7 @@ class OffscreenQmlSurface; * @hifi-client-entity * @hifi-avatar */ -/**jsdoc +/*@jsdoc * The tabletInterface API provides the facilities to work with the system or other tablet. * * @namespace tabletInterface @@ -69,7 +69,7 @@ class TabletScriptingInterface : public QObject, public Dependency { Q_OBJECT public: - /**jsdoc + /*@jsdoc *

Standard tablet sounds.

*
* @@ -98,7 +98,7 @@ public: void setToolbarScriptingInterface(ToolbarScriptingInterface* toolbarScriptingInterface) { _toolbarScriptingInterface = toolbarScriptingInterface; } - /**jsdoc + /*@jsdoc * Gets an instance of a tablet. A new tablet is created if one with the specified name doesn't already exist. * @function Tablet.getTablet * @param {string} name - A unique name that identifies the tablet. @@ -111,7 +111,7 @@ public: void preloadSounds(); - /**jsdoc + /*@jsdoc * Plays a standard tablet sound. The sound is played locally (only the user running the script hears it) without a * position. * @function Tablet.playSound @@ -132,7 +132,7 @@ public: QObject* getFlags(); signals: - /**jsdoc + /*@jsdoc * Triggered when a tablet message or dialog is displayed on the tablet that needs the user's attention. *

Note: Only triggered if the script is running in the same script engine as the script that created * the tablet. By default, this means in scripts included as part of the default scripts.

@@ -154,7 +154,7 @@ protected: bool _toolbarMode { false }; }; -/**jsdoc +/*@jsdoc * Information on the buttons in the tablet main menu (toolbar in toolbar mode) for use in QML. Has properties and functions * per http://doc.qt.io/qt-5/qabstractlistmodel.html. * @typedef {object} TabletProxy.TabletButtonListModel @@ -210,7 +210,7 @@ private: Q_DECLARE_METATYPE(TabletButtonsProxyModel*); -/**jsdoc +/*@jsdoc * An instance of a tablet. In toolbar mode (see Developer > UI options), the tablet's menu buttons are displayed in a * toolbar and other tablet content is displayed in a dialog. * @@ -251,7 +251,7 @@ public: void setToolbarMode(bool toolbarMode); void unfocus(); - /**jsdoc + /*@jsdoc * Displays the tablet menu. The tablet is opened if it isn't already open. * @function TabletProxy#gotoMenuScreen * @param {string} [submenu=""] - The name of a submenu to display, if any. @@ -260,20 +260,20 @@ public: */ Q_INVOKABLE void gotoMenuScreen(const QString& submenu = ""); - /**jsdoc + /*@jsdoc * @function TabletProxy#initialScreen * @param {string} url - URL. * @deprecated This function is deprecated and will be removed. */ Q_INVOKABLE void initialScreen(const QVariant& url); - /**jsdoc + /*@jsdoc * Displays the tablet home screen, if the tablet is open. * @function TabletProxy#gotoHomeScreen */ Q_INVOKABLE void gotoHomeScreen(); - /**jsdoc + /*@jsdoc * Opens a web app or page in addition to any current app. In tablet mode, the app or page is displayed over the top of the * current app; in toolbar mode, the app is opened in a new window that replaces any current window open. If in tablet * mode, the app or page can be closed using {@link TabletProxy#returnToPreviousApp}. @@ -287,7 +287,7 @@ public: Q_INVOKABLE void gotoWebScreen(const QString& url); Q_INVOKABLE void gotoWebScreen(const QString& url, const QString& injectedJavaScriptUrl, bool loadOtherBase = false); - /**jsdoc + /*@jsdoc * Opens a QML app or dialog on the tablet. * @function TabletProxy#loadQMLSource * @param {string} path - The path of the QML app or dialog. @@ -296,28 +296,28 @@ public: */ Q_INVOKABLE void loadQMLSource(const QVariant& path, bool resizable = false); - /**jsdoc + /*@jsdoc * @function TabletProxy#loadQMLSourceImpl * @deprecated This function is deprecated and will be removed. */ // Internal function, do not call from scripts. Q_INVOKABLE void loadQMLSourceImpl(const QVariant& path, bool resizable, bool localSafeContext); - /**jsdoc + /*@jsdoc * @function TabletProxy#loadHTMLSourceOnTopImpl * @deprecated This function is deprecated and will be removed. */ // Internal function, do not call from scripts. Q_INVOKABLE void loadHTMLSourceOnTopImpl(const QString& url, const QString& injectedJavaScriptUrl, bool loadOtherBase, bool localSafeContext); - /**jsdoc + /*@jsdoc * @function TabletProxy#returnToPreviousAppImpl * @deprecated This function is deprecated and will be removed. */ // Internal function, do not call from scripts. Q_INVOKABLE void returnToPreviousAppImpl(bool localSafeContext); - /**jsdoc + /*@jsdoc * @function TabletProxy#loadQMLOnTopImpl * @deprecated This function is deprecated and will be removed. */ @@ -327,7 +327,7 @@ public: // FIXME: This currently relies on a script initializing the tablet (hence the bool denoting success); // it should be initialized internally so it cannot fail - /**jsdoc + /*@jsdoc * Displays a QML dialog over the top of the current dialog, without closing the current dialog. Use * {@link TabletProxy#popFromStack|popFromStack} to close the dialog. *

If the current dialog or its ancestors contain a QML StackView with objectName: "stack" and @@ -341,7 +341,7 @@ public: // edit.js provides an example of using this outside of main menu. Q_INVOKABLE bool pushOntoStack(const QVariant& path); - /**jsdoc + /*@jsdoc * Closes a QML dialog that was displayed using {@link Tablet#pushOntoStack|pushOntoStack} with a dialog implementing a QML * StackView; otherwise, no action is taken. *

If using a QML StackView, its popSource() function is called.

@@ -349,7 +349,7 @@ public: */ Q_INVOKABLE void popFromStack(); - /**jsdoc + /*@jsdoc * Opens a QML app or dialog in addition to any current app. In tablet mode, the app or dialog is displayed over the top of * the current app; in toolbar mode, the app or dialog is opened in a new window. If in tablet mode, the app can be closed * using {@link TabletProxy#returnToPreviousApp}. @@ -358,7 +358,7 @@ public: */ Q_INVOKABLE void loadQMLOnTop(const QVariant& path); - /**jsdoc + /*@jsdoc * Opens a web app or page in addition to any current app. In tablet mode, the app or page is displayed over the top of the * current app; in toolbar mode, the app is opened in a new window that replaces any current window open. If in tablet * mode, the app or page can be closed using {@link TabletProxy#returnToPreviousApp}. @@ -369,28 +369,28 @@ public: Q_INVOKABLE void loadWebScreenOnTop(const QVariant& url); Q_INVOKABLE void loadWebScreenOnTop(const QVariant& url, const QString& injectedJavaScriptUrl); - /**jsdoc + /*@jsdoc * Closes the current app and returns to the previous app, if in tablet mode and the current app was loaded using * {@link TabletProxy#loadQMLOnTop|loadQMLOnTop} or {@link TabletProxy#loadWebScreenOnTop|loadWebScreenOnTop}. * @function TabletProxy#returnToPreviousApp */ Q_INVOKABLE void returnToPreviousApp(); - /**jsdoc + /*@jsdoc * Checks if the tablet has a modal, non-modal, or message dialog open. * @function TabletProxy#isMessageDialogOpen * @returns {boolean} true if a modal, non-modal, or message dialog is open, false if there isn't. */ Q_INVOKABLE bool isMessageDialogOpen(); - /**jsdoc + /*@jsdoc * Closes any open modal, non-modal, or message dialog, opened by {@link Window.prompt}, {@link Window.promptAsync}, * {@link Window.openMessageBox}, or similar. * @function TabletProxy#closeDialog */ Q_INVOKABLE void closeDialog(); - /**jsdoc + /*@jsdoc * Adds a new button to the tablet menu. * @function TabletProxy#addButton * @param {TabletButtonProxy.ButtonProperties} properties - Button properties. @@ -410,14 +410,14 @@ public: //FIXME: UI_TABLET_HACK: enumerate the button properties when we figure out what they should be! Q_INVOKABLE TabletButtonProxy* addButton(const QVariant& properties); - /**jsdoc + /*@jsdoc * Removes a button from the tablet menu. * @function TabletProxy#removeButton * @param {TabletButtonProxy} button - The button to remove. */ Q_INVOKABLE void removeButton(TabletButtonProxy* tabletButtonProxy); - /**jsdoc + /*@jsdoc * Sends a message to the current web page. To receive the message, the web page's script must connect to the * EventBridge that is automatically provided to the script: *
EventBridge.scriptEventReceived.connect(function(message) {
@@ -434,7 +434,7 @@ public:
      */
     Q_INVOKABLE void emitScriptEvent(const QVariant& msg);
 
-    /**jsdoc
+    /*@jsdoc
      * Sends a message to the current QML page. To receive the message, the QML page must implement a function:
      * 
function fromScript(message) {
      *   ...
@@ -444,14 +444,14 @@ public:
      */
     Q_INVOKABLE void sendToQml(const QVariant& msg);
 
-    /**jsdoc
+    /*@jsdoc
      * Checks if the tablet is on the home screen.
      * @function TabletProxy#onHomeScreen
      * @returns {boolean} true if the tablet is on the home screen, false if it isn't.
      */
     Q_INVOKABLE bool onHomeScreen();
 
-    /**jsdoc
+    /*@jsdoc
      * Sets whether the tablet is displayed in landscape or portrait mode.
      * 

Note: The setting isn't used in toolbar mode.

* @function TabletProxy#setLandscape @@ -460,7 +460,7 @@ public: */ Q_INVOKABLE void setLandscape(bool landscape) { _landscape = landscape; } - /**jsdoc + /*@jsdoc * Gets whether the tablet is displayed in landscape or portrait mode. *

Note: The setting isn't used in toolbar mode.

* @function TabletProxy#getLandscape @@ -469,7 +469,7 @@ public: */ Q_INVOKABLE bool getLandscape() { return _landscape; } - /**jsdoc + /*@jsdoc * Checks if a path is the current app or dialog displayed. * @function TabletProxy#isPathLoaded * @param {string} path - The path to test. @@ -488,7 +488,7 @@ public: TabletButtonListModel* getButtons() { return &_buttons; } signals: - /**jsdoc + /*@jsdoc * Triggered when a message from the current HTML web page displayed on the tablet is received. The HTML web page can send * a message by calling: *
EventBridge.emitWebEvent(message);
@@ -498,7 +498,7 @@ signals: */ void webEventReceived(QVariant msg); - /**jsdoc + /*@jsdoc * Triggered when a message from the current QML page displayed on the tablet is received. The QML page can send a message * (string or object) by calling:
sendToScript(message);
* @function TabletProxy#fromQml @@ -507,7 +507,7 @@ signals: */ void fromQml(QVariant msg); - /**jsdoc + /*@jsdoc * Triggered when the tablet's screen changes. * @function TabletProxy#screenChanged * @param type {string} - The type of the new screen or change: "Home", "Menu", @@ -517,7 +517,7 @@ signals: */ void screenChanged(QVariant type, QVariant url); - /**jsdoc + /*@jsdoc * Triggered when the tablet is opened or closed. *

Note: Doesn't apply in toolbar mode.

* @function TabletProxy#tabletShownChanged @@ -525,7 +525,7 @@ signals: */ void tabletShownChanged(); - /**jsdoc + /*@jsdoc * Triggered when the tablet's toolbar mode changes. * @function TabletProxy#toolbarModeChanged * @returns {Signal} @@ -540,20 +540,20 @@ signals: protected slots: - /**jsdoc + /*@jsdoc * @function TabletProxy#desktopWindowClosed * @deprecated This function is deprecated and will be removed. */ void desktopWindowClosed(); - /**jsdoc + /*@jsdoc * @function TabletProxy#emitWebEvent * @param {object|string} message - Message * @deprecated This function is deprecated and will be removed. */ void emitWebEvent(const QVariant& msg); - /**jsdoc + /*@jsdoc * @function TabletProxy#onTabletShown * @deprecated This function is deprecated and will be removed. */ @@ -586,7 +586,7 @@ private: Q_DECLARE_METATYPE(TabletProxy*); -/**jsdoc +/*@jsdoc * A tablet button. In toolbar mode (Developer > UI > Tablet Becomes Toolbar), the tablet button is displayed on the * toolbar. * @@ -613,7 +613,7 @@ public: QUuid getUuid() const { return _uuid; } - /**jsdoc + /*@jsdoc * Gets the current values of the button's properties. Only properties that have been set during button creation or * subsequently edited are returned. * @function TabletButtonProxy#getProperties @@ -631,7 +631,7 @@ public: */ Q_INVOKABLE QVariantMap getProperties(); - /**jsdoc + /*@jsdoc * Changes the values of the button's properties. * @function TabletButtonProxy#editProperties * @param {TabletButtonProxy.ButtonProperties} properties - The properties to change. @@ -654,7 +654,7 @@ public: Q_INVOKABLE void editProperties(const QVariantMap& properties); signals: - /**jsdoc + /*@jsdoc * Triggered when the button is clicked. * @function TabletButtonProxy#clicked * @returns {Signal} @@ -672,7 +672,7 @@ signals: */ void clicked(); - /**jsdoc + /*@jsdoc * Triggered when a button's properties are changed. * @function TabletButtonProxy#propertiesChanged * @returns {Signal} diff --git a/libraries/ui/src/ui/ToolbarScriptingInterface.h b/libraries/ui/src/ui/ToolbarScriptingInterface.h index 746ba2894e..5cc847d442 100644 --- a/libraries/ui/src/ui/ToolbarScriptingInterface.h +++ b/libraries/ui/src/ui/ToolbarScriptingInterface.h @@ -38,7 +38,7 @@ protected: Q_DECLARE_METATYPE(ToolbarButtonProxy*); -/**jsdoc +/*@jsdoc * An instance of a toolbar. * *

Retrieve an existing toolbar or create a new toolbar using {@link Toolbars.getToolbar}.

@@ -55,7 +55,7 @@ class ToolbarProxy : public QmlWrapper { public: ToolbarProxy(QObject* qmlObject, QObject* parent = nullptr); - /**jsdoc + /*@jsdoc * Currently doesn't work. * @function ToolbarProxy#addButton * @param {object} properties - Button properties @@ -64,7 +64,7 @@ public: */ Q_INVOKABLE ToolbarButtonProxy* addButton(const QVariant& properties); - /**jsdoc + /*@jsdoc * Currently doesn't work. * @function ToolbarProxy#removeButton * @param {string} name - Button name. @@ -75,7 +75,7 @@ public: // QmlWrapper methods. - /**jsdoc + /*@jsdoc * Sets the value of a toolbar property. A property is added to the toolbar if the named property doesn't already * exist. * @function ToolbarProxy#writeProperty @@ -84,7 +84,7 @@ public: * @param {object} propertyValue - The value of the property. */ - /**jsdoc + /*@jsdoc * Sets the values of toolbar properties. A property is added to the toolbar if a named property doesn't already * exist. * @function ToolbarProxy#writeProperties @@ -92,14 +92,14 @@ public: * implementation of the toolbar. */ - /**jsdoc + /*@jsdoc * Gets the value of a toolbar property. * @function ToolbarProxy#readProperty * @param {string} propertyName - The property name. Toolbar properties are those in the QML implementation of the toolbar. * @returns {object} The value of the property if the property name is valid, otherwise undefined. */ - /**jsdoc + /*@jsdoc * Gets the values of toolbar properties. * @function ToolbarProxy#readProperties * @param {string[]} propertyList - The names of the properties to get the values of. Toolbar properties are those in the @@ -111,7 +111,7 @@ public: Q_DECLARE_METATYPE(ToolbarProxy*); -/**jsdoc +/*@jsdoc * The Toolbars API provides facilities to work with the system or other toolbar. * *

See also the {@link Tablet} API for use of the system tablet and toolbar in desktop and HMD modes.

@@ -126,7 +126,7 @@ class ToolbarScriptingInterface : public QObject, public Dependency { Q_OBJECT public: - /**jsdoc + /*@jsdoc * Gets an instance of a toolbar. A new toolbar is created if one with the specified name doesn't already exist. * @function Toolbars.getToolbar * @param {string} name - A unique name that identifies the toolbar. @@ -135,7 +135,7 @@ public: Q_INVOKABLE ToolbarProxy* getToolbar(const QString& toolbarId); signals: - /**jsdoc + /*@jsdoc * Triggered when the visibility of a toolbar changes. * @function Toolbars.toolbarVisibleChanged * @param {boolean} isVisible - true if the toolbar is visible, false if it is hidden. diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt index a72371f544..195021e2fe 100644 --- a/plugins/CMakeLists.txt +++ b/plugins/CMakeLists.txt @@ -47,11 +47,14 @@ endif() # server-side plugins set(DIR "pcmCodec") add_subdirectory(${DIR}) -set(DIR "hifiCodec") -add_subdirectory(${DIR}) set(DIR "opusCodec") add_subdirectory(${DIR}) +if (NOT CMAKE_SYSTEM_PROCESSOR STREQUAL "aarch64") + set(DIR "hifiCodec") + add_subdirectory(${DIR}) +endif() + # example plugins set(DIR "JSAPIExample") add_subdirectory(${DIR}) diff --git a/plugins/JSAPIExample/src/JSAPIExample.cpp b/plugins/JSAPIExample/src/JSAPIExample.cpp index 91aa8bd32a..4654279bec 100644 --- a/plugins/JSAPIExample/src/JSAPIExample.cpp +++ b/plugins/JSAPIExample/src/JSAPIExample.cpp @@ -77,7 +77,7 @@ namespace REPLACE_ME_WITH_UNIQUE_NAME { // (note: Qt script engines automatically look for a ".toString" method on native classes when coercing values to strings) QString toString() const { return QString("[%1 version=%2]").arg(objectName()).arg(_version); } - /**jsdoc + /*@jsdoc * Returns current microseconds (usecs) since Epoch. note: 1000usecs == 1ms * @example
* var expected = 1000; @@ -89,7 +89,7 @@ namespace REPLACE_ME_WITH_UNIQUE_NAME { */ QVariant now() const { return usecTimestampNow(); } - /**jsdoc + /*@jsdoc * Example of returning a JS Object key-value map * @example * print(JSON.stringify(JSAPIExample.zip(["a","b"], [1,2])); // { "a": 1, "b": 2 } @@ -102,7 +102,7 @@ namespace REPLACE_ME_WITH_UNIQUE_NAME { return out; } - /**jsdoc + /*@jsdoc * Example of returning a JS Array result * @example * print(JSON.stringify(JSAPIExample.values({ "a": 1, "b": 2 }))); // [1,2] @@ -112,7 +112,7 @@ namespace REPLACE_ME_WITH_UNIQUE_NAME { return values; } - /**jsdoc + /*@jsdoc * Another example of returning JS Array data * @example * print(JSON.stringify(JSAPIExample.seq(1,5)));// [1,2,3,4,5] @@ -125,7 +125,7 @@ namespace REPLACE_ME_WITH_UNIQUE_NAME { return out; } - /**jsdoc + /*@jsdoc * Example of returning arbitrary binary data from C++ (resulting in a JS ArrayBuffer) * see also: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer#Examples * @example 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/plugins/hifiSdl2/src/Joystick.cpp b/plugins/hifiSdl2/src/Joystick.cpp index ad0b459544..55a07e0ab9 100644 --- a/plugins/hifiSdl2/src/Joystick.cpp +++ b/plugins/hifiSdl2/src/Joystick.cpp @@ -72,7 +72,7 @@ void Joystick::handleButtonEvent(const SDL_ControllerButtonEvent& event) { } } -bool Joystick::triggerHapticPulse(float strength, float duration, controller::Hand hand) { +bool Joystick::triggerHapticPulse(float strength, float duration, uint16_t index) { if (SDL_HapticRumblePlay(_sdlHaptic, strength, duration) != 0) { return false; } diff --git a/plugins/hifiSdl2/src/Joystick.h b/plugins/hifiSdl2/src/Joystick.h index ae90470974..a839676468 100644 --- a/plugins/hifiSdl2/src/Joystick.h +++ b/plugins/hifiSdl2/src/Joystick.h @@ -39,7 +39,7 @@ public: virtual void update(float deltaTime, const controller::InputCalibrationData& inputCalibrationData) override; virtual void focusOutEvent() override; - bool triggerHapticPulse(float strength, float duration, controller::Hand hand) override; + bool triggerHapticPulse(float strength, float duration, uint16_t index) override; Joystick() : InputDevice("GamePad") {} ~Joystick(); diff --git a/plugins/oculus/src/OculusControllerManager.cpp b/plugins/oculus/src/OculusControllerManager.cpp index c1431fa4b2..8ab31b28c2 100644 --- a/plugins/oculus/src/OculusControllerManager.cpp +++ b/plugins/oculus/src/OculusControllerManager.cpp @@ -369,7 +369,13 @@ void OculusControllerManager::TouchDevice::handleRotationForUntrackedHand(const pose = pose.transform(controllerToAvatar); } -bool OculusControllerManager::TouchDevice::triggerHapticPulse(float strength, float duration, controller::Hand hand) { +bool OculusControllerManager::TouchDevice::triggerHapticPulse(float strength, float duration, uint16_t index) { + if (index > 2) { + return false; + } + + controller::Hand hand = (controller::Hand)index; + Locker locker(_lock); bool toReturn = true; ovr::withSession([&](ovrSession session) { @@ -408,7 +414,7 @@ void OculusControllerManager::TouchDevice::stopHapticPulse(bool leftHand) { }); } -/**jsdoc +/*@jsdoc *

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

*

These outputs can be mapped to actions or functions or Controller.Standard items in a {@link RouteObject} diff --git a/plugins/oculus/src/OculusControllerManager.h b/plugins/oculus/src/OculusControllerManager.h index 7d1d176a56..6a3a10f18a 100644 --- a/plugins/oculus/src/OculusControllerManager.h +++ b/plugins/oculus/src/OculusControllerManager.h @@ -76,7 +76,7 @@ private: void update(float deltaTime, const controller::InputCalibrationData& inputCalibrationData) override; void focusOutEvent() override; - bool triggerHapticPulse(float strength, float duration, controller::Hand hand) override; + bool triggerHapticPulse(float strength, float duration, uint16_t index) override; private: void stopHapticPulse(bool leftHand); diff --git a/plugins/openvr/CMakeLists.txt b/plugins/openvr/CMakeLists.txt index 9690ee3fb5..0b9358242d 100644 --- a/plugins/openvr/CMakeLists.txt +++ b/plugins/openvr/CMakeLists.txt @@ -10,9 +10,9 @@ if ((WIN32 OR UNIX AND NOT APPLE) AND NOT USE_GLES) set(TARGET_NAME openvr) setup_hifi_plugin(Gui Qml Multimedia) - link_hifi_libraries(shared task gl qml networking controllers ui + link_hifi_libraries(shared task gl qml networking controllers ui plugins display-plugins ui-plugins input-plugins script-engine - audio-client render-utils graphics shaders gpu render material-networking model-networking model-baker hfm fbx ktx image procedural ${PLATFORM_GL_BACKEND}) + audio-client render-utils graphics shaders gpu render material-networking model-networking model-baker hfm model-serializers ktx image procedural ${PLATFORM_GL_BACKEND}) include_hifi_library_headers(octree) target_openvr() diff --git a/plugins/openvr/src/ViveControllerManager.cpp b/plugins/openvr/src/ViveControllerManager.cpp index ac41502a38..b6a117f3ac 100644 --- a/plugins/openvr/src/ViveControllerManager.cpp +++ b/plugins/openvr/src/ViveControllerManager.cpp @@ -1561,7 +1561,13 @@ void ViveControllerManager::InputDevice::handlePoseEvent(float deltaTime, const _poseStateMap[isLeftHand ? controller::LEFT_HAND : controller::RIGHT_HAND] = pose.transform(controllerToAvatar); } -bool ViveControllerManager::InputDevice::triggerHapticPulse(float strength, float duration, controller::Hand hand) { +bool ViveControllerManager::InputDevice::triggerHapticPulse(float strength, float duration, uint16_t index) { + if (index > 2) { + return false; + } + + controller::Hand hand = (controller::Hand)index; + Locker locker(_lock); if (hand == controller::BOTH || hand == controller::LEFT) { if (strength == 0.0f) { @@ -1810,7 +1816,7 @@ void ViveControllerManager::InputDevice::setConfigFromString(const QString& valu } } -/**jsdoc +/*@jsdoc *

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

*

These outputs can be mapped to actions or functions or Controller.Standard items in a {@link RouteObject} diff --git a/plugins/openvr/src/ViveControllerManager.h b/plugins/openvr/src/ViveControllerManager.h index 956b2b5eaf..1b8c2a2ec5 100644 --- a/plugins/openvr/src/ViveControllerManager.h +++ b/plugins/openvr/src/ViveControllerManager.h @@ -112,7 +112,7 @@ private: QString getDefaultMappingConfig() const override; void update(float deltaTime, const controller::InputCalibrationData& inputCalibrationData) override; void focusOutEvent() override; - bool triggerHapticPulse(float strength, float duration, controller::Hand hand) override; + bool triggerHapticPulse(float strength, float duration, uint16_t index) override; void hapticsHelper(float deltaTime, bool leftHand); void calibrateOrUncalibrate(const controller::InputCalibrationData& inputCalibration); void calibrate(const controller::InputCalibrationData& inputCalibration); 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/screenshare/package-lock.json b/screenshare/package-lock.json index 4d0fea0805..6bb34b21a5 100644 --- a/screenshare/package-lock.json +++ b/screenshare/package-lock.json @@ -71,9 +71,9 @@ } }, "@types/node": { - "version": "12.19.9", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.19.9.tgz", - "integrity": "sha512-yj0DOaQeUrk3nJ0bd3Y5PeDRJ6W0r+kilosLA+dzF3dola/o9hxhMSg2sFvVcA2UHS5JSOsZp4S0c1OEXc4m1Q==", + "version": "12.19.15", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.19.15.tgz", + "integrity": "sha512-lowukE3GUI+VSYSu6VcBXl14d61Rp5hA1D+61r16qnwC0lYNSqdxcvRh0pswejorHfS+HgwBasM8jLXz0/aOsw==", "dev": true }, "ansi-styles": { @@ -365,9 +365,9 @@ "dev": true }, "electron": { - "version": "7.2.4", - "resolved": "https://registry.npmjs.org/electron/-/electron-7.2.4.tgz", - "integrity": "sha512-Z+R692uTzXgP8AHrabE+kkrMlQJ6pnAYoINenwj9QSqaD2YbO8IuXU9DMCcUY0+VpA91ee09wFZJNUKYPMnCKg==", + "version": "9.4.0", + "resolved": "https://registry.npmjs.org/electron/-/electron-9.4.0.tgz", + "integrity": "sha512-hOC4q0jkb+UDYZRy8vrZ1IANnq+jznZnbkD62OEo06nU+hIbp2IrwDRBNuSLmQ3cwZMVir0WSIA1qEVK0PkzGA==", "dev": true, "requires": { "@electron/get": "^1.0.1", @@ -783,9 +783,9 @@ "dev": true }, "hosted-git-info": { - "version": "2.8.5", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.5.tgz", - "integrity": "sha512-kssjab8CvdXfcXMXVcvsXum4Hwdq9XGtRD3TteMEvEbq0LXyiNQr6AprqKqfeaDXze7SxWvRxdpwE6ku7ikLkg==", + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", "dev": true }, "http-cache-semantics": { @@ -940,9 +940,9 @@ } }, "normalize-url": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.0.tgz", - "integrity": "sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ==", + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz", + "integrity": "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==", "dev": true }, "once": { @@ -1330,9 +1330,9 @@ "dev": true }, "y18n": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", - "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==" + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.1.tgz", + "integrity": "sha512-wNcy4NvjMYL8gogWWYAO7ZFWFfHcbdbE57tZO8e4cbpj8tfUcwrwqSl3ad8HxpYWCdXcJUCeKKZS62Av1affwQ==" }, "yargs": { "version": "14.2.0", diff --git a/screenshare/package.json b/screenshare/package.json index e92e20a073..07d461f252 100644 --- a/screenshare/package.json +++ b/screenshare/package.json @@ -18,7 +18,7 @@ }, "homepage": "https://github.com/highfidelity/hifi#readme", "devDependencies": { - "electron": "^7.2.4", + "electron": "^9.4.0", "electron-packager": "^14.0.6" }, "dependencies": { diff --git a/scripts/communityScripts/chat/FloofChat.js b/scripts/communityScripts/chat/FloofChat.js index 1208a36e5f..26ab0d04e7 100644 --- a/scripts/communityScripts/chat/FloofChat.js +++ b/scripts/communityScripts/chat/FloofChat.js @@ -61,8 +61,8 @@ var settingsRoot = "FloofChat"; var vircadiaGotoUrl = "https://metaverse.vircadia.com/interim/d-goto/app/goto.json"; var gotoJSONUrl = Settings.getValue(settingsRoot + "/gotoJSONUrl", vircadiaGotoUrl); -var muted = Settings.getValue(settingsRoot + "/muted", {"Local": false, "Domain": false, "Grid": true}); -var mutedAudio = Settings.getValue(settingsRoot + "/mutedAudio", {"Local": false, "Domain": false, "Grid": true}); +var muted = Settings.getValue(settingsRoot + "/muted", {"Local": false, "Domain": true, "Grid": true}); +var mutedAudio = Settings.getValue(settingsRoot + "/mutedAudio", {"Local": false, "Domain": true, "Grid": true}); var notificationSound = SoundCache.getSound(Script.resolvePath("resources/bubblepop.wav")); var ws; diff --git a/scripts/system/create/assets/images/processing.gif b/scripts/system/create/assets/images/processing.gif new file mode 100644 index 0000000000..94d1486b0a Binary files /dev/null and b/scripts/system/create/assets/images/processing.gif differ diff --git a/scripts/system/create/edit.js b/scripts/system/create/edit.js index 9bd0147002..614bd5fd59 100644 --- a/scripts/system/create/edit.js +++ b/scripts/system/create/edit.js @@ -35,7 +35,8 @@ Script.include([ "../libraries/gridTool.js", "entityList/entityList.js", "entitySelectionTool/entitySelectionTool.js", - "audioFeedback/audioFeedback.js" + "audioFeedback/audioFeedback.js", + "modules/brokenURLReport.js" ]); var CreateWindow = Script.require('./modules/createWindow.js'); @@ -112,6 +113,9 @@ var hmdMultiSelectMode = false; var expectingRotateAsClickedSurface = false; var keepSelectedOnNextClick = false; +var copiedPosition; +var copiedRotation; + var cameraManager = new CameraManager(); var grid = new Grid(); @@ -2612,6 +2616,46 @@ var PropertiesTool = function (opts) { Entities.reloadServerScripts(selectionManager.selections[i]); } } + } else if (data.action === "copyPosition") { + if (selectionManager.selections.length === 1) { + selectionManager.saveProperties(); + properties = selectionManager.savedProperties[selectionManager.selections[0]]; + copiedPosition = properties.position; + Window.copyToClipboard(JSON.stringify(copiedPosition)); + } + } else if (data.action === "copyRotation") { + if (selectionManager.selections.length === 1) { + selectionManager.saveProperties(); + properties = selectionManager.savedProperties[selectionManager.selections[0]]; + copiedRotation = properties.rotation; + Window.copyToClipboard(JSON.stringify(copiedRotation)); + } + } else if (data.action === "pastePosition") { + if (copiedPosition !== undefined && selectionManager.selections.length > 0 && SelectionManager.hasUnlockedSelection()) { + selectionManager.saveProperties(); + for (i = 0; i < selectionManager.selections.length; i++) { + Entities.editEntity(selectionManager.selections[i], { + position: copiedPosition + }); + } + pushCommandForSelections(); + selectionManager._update(false, this); + } else { + audioFeedback.rejection(); + } + } else if (data.action === "pasteRotation") { + if (copiedRotation !== undefined && selectionManager.selections.length > 0 && SelectionManager.hasUnlockedSelection()) { + selectionManager.saveProperties(); + for (i = 0; i < selectionManager.selections.length; i++) { + Entities.editEntity(selectionManager.selections[i], { + rotation: copiedRotation + }); + } + pushCommandForSelections(); + selectionManager._update(false, this); + } else { + audioFeedback.rejection(); + } } } else if (data.type === "propertiesPageReady") { updateSelections(true); diff --git a/scripts/system/create/entityList/entityList.js b/scripts/system/create/entityList/entityList.js index 5119d7d3da..02cd9a14ca 100644 --- a/scripts/system/create/entityList/entityList.js +++ b/scripts/system/create/entityList/entityList.js @@ -413,12 +413,14 @@ EntityListTool = function(shouldUseEditTabletApp) { alignGridToSelection(); } else if (data.type === 'alignGridToAvatar') { alignGridToAvatar(); + } else if (data.type === 'brokenURLReport') { + brokenURLReport(selectionManager.selections); } else if (data.type === 'toggleGridVisibility') { toggleGridVisibility(); } else if (data.type === 'toggleSnapToGrid') { - that.toggleSnapToGrid(); + that.toggleSnapToGrid(); } - + }; webView.webEventReceived.connect(onWebEventReceived); diff --git a/scripts/system/create/entityList/html/entityList.html b/scripts/system/create/entityList/html/entityList.html index e054ca121b..75b172e201 100644 --- a/scripts/system/create/entityList/html/entityList.html +++ b/scripts/system/create/entityList/html/entityList.html @@ -308,7 +308,14 @@

- + + + diff --git a/scripts/system/create/entityList/html/js/entityList.js b/scripts/system/create/entityList/html/js/entityList.js index d21e65d47d..e3526296d9 100644 --- a/scripts/system/create/entityList/html/js/entityList.js +++ b/scripts/system/create/entityList/html/js/entityList.js @@ -273,6 +273,7 @@ let elEntityTable, elSnapToGridActivatorCaption, elAlignGridToSelection, elAlignGridToAvatar, + elBrokenURLReport, elFilterTypeMultiselectBox, elFilterTypeText, elFilterTypeOptions, @@ -359,7 +360,8 @@ function loaded() { elSnapToGridActivator = document.getElementById("snapToGridActivator"); elSnapToGridActivatorCaption = document.getElementById("snapToGridActivatorCaption"); elAlignGridToSelection = document.getElementById("alignGridToSelection"); - elAlignGridToAvatar = document.getElementById("alignGridToAvatar"); + elAlignGridToAvatar = document.getElementById("alignGridToAvatar"); + elBrokenURLReport = document.getElementById("brokenURLReport"); elFilterTypeMultiselectBox = document.getElementById("filter-type-multiselect-box"); elFilterTypeText = document.getElementById("filter-type-text"); elFilterTypeOptions = document.getElementById("filter-type-options"); @@ -597,7 +599,11 @@ function loaded() { elAlignGridToAvatar.onclick = function () { EventBridge.emitWebEvent(JSON.stringify({ type: "alignGridToAvatar" })); closeAllEntityListMenu(); - }; + }; + elBrokenURLReport.onclick = function () { + EventBridge.emitWebEvent(JSON.stringify({ type: "brokenURLReport" })); + closeAllEntityListMenu(); + }; elToggleSpaceMode.onclick = function() { EventBridge.emitWebEvent(JSON.stringify({ type: "toggleSpaceMode" })); }; diff --git a/scripts/system/create/entityProperties/html/js/entityProperties.js b/scripts/system/create/entityProperties/html/js/entityProperties.js index 68e3fdc7c3..65e14d7203 100644 --- a/scripts/system/create/entityProperties/html/js/entityProperties.js +++ b/scripts/system/create/entityProperties/html/js/entityProperties.js @@ -292,7 +292,7 @@ const GROUPS = [ { label: "Shape Type", type: "dropdown", - options: { "box": "Box", "sphere": "Sphere", "ellipsoid": "Ellipsoid", + options: { "box": "Box", "sphere": "Sphere", "cylinder-y": "Cylinder", "compound": "Use Compound Shape URL" }, propertyID: "zoneShapeType", propertyName: "shapeType", // actual entity property name @@ -1352,6 +1352,12 @@ const GROUPS = [ propertyID: "localPosition", spaceMode: PROPERTY_SPACE_MODE.LOCAL, }, + { + type: "buttons", + buttons: [ { id: "copyPosition", label: "Copy Position", className: "secondary", onClick: copyPositionProperty }, + { id: "pastePosition", label: "Paste Position", className: "secondary", onClick: pastePositionProperty } ], + propertyID: "copyPastePosition" + }, { label: "Rotation", type: "vec3", @@ -1374,6 +1380,12 @@ const GROUPS = [ propertyID: "localRotation", spaceMode: PROPERTY_SPACE_MODE.LOCAL, }, + { + type: "buttons", + buttons: [ { id: "copyRotation", label: "Copy Rotation", className: "secondary", onClick: copyRotationProperty }, + { id: "pasteRotation", label: "Paste Rotation", className: "secondary", onClick: pasteRotationProperty } ], + propertyID: "copyPasteRotation" + }, { label: "Dimensions", type: "vec3", @@ -1851,6 +1863,24 @@ function setPropertyVisibility(property, visible) { property.elContainer.style.display = visible ? null : "none"; } +function setCopyPastePositionAndRotationAvailability (selectionLength, islocked) { + if (selectionLength === 1) { + $('#property-copyPastePosition-button-copyPosition').attr('disabled', false); + $('#property-copyPasteRotation-button-copyRotation').attr('disabled', false); + } else { + $('#property-copyPastePosition-button-copyPosition').attr('disabled', true); + $('#property-copyPasteRotation-button-copyRotation').attr('disabled', true); + } + + if (selectionLength > 0 && !islocked) { + $('#property-copyPastePosition-button-pastePosition').attr('disabled', false); + $('#property-copyPasteRotation-button-pasteRotation').attr('disabled', false); + } else { + $('#property-copyPastePosition-button-pastePosition').attr('disabled', true); + $('#property-copyPasteRotation-button-pasteRotation').attr('disabled', true); + } +} + function resetProperties() { for (let propertyID in properties) { let property = properties[propertyID]; @@ -3216,6 +3246,33 @@ function copySkyboxURLToAmbientURL() { updateProperty("ambientLight.ambientURL", skyboxURL, false); } +function copyPositionProperty() { + EventBridge.emitWebEvent(JSON.stringify({ + type: "action", + action: "copyPosition" + })); +} + +function pastePositionProperty() { + EventBridge.emitWebEvent(JSON.stringify({ + type: "action", + action: "pastePosition" + })); +} + +function copyRotationProperty() { + EventBridge.emitWebEvent(JSON.stringify({ + type: "action", + action: "copyRotation" + })); +} + +function pasteRotationProperty() { + EventBridge.emitWebEvent(JSON.stringify({ + type: "action", + action: "pasteRotation" + })); +} /** * USER DATA FUNCTIONS @@ -3637,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) { @@ -3740,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 === "") { @@ -3748,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); @@ -3951,7 +4019,7 @@ function handleEntitySelectionUpdate(selections, isPropertiesToolUpdate) { selectedEntityIDs = new Set(selections.map(selection => selection.id)); const multipleSelections = currentSelections.length > 1; const hasSelectedEntityChanged = !areSetsEqual(selectedEntityIDs, previouslySelectedEntityIDs); - + requestZoneList(); if (selections.length === 0) { @@ -3975,6 +4043,8 @@ function handleEntitySelectionUpdate(selections, isPropertiesToolUpdate) { showSaveMaterialDataButton(); showNewJSONMaterialEditorButton(); + setCopyPastePositionAndRotationAvailability (selections.length, true); + disableProperties(); } else { if (!isPropertiesToolUpdate && !hasSelectedEntityChanged && document.hasFocus()) { @@ -4005,10 +4075,12 @@ function handleEntitySelectionUpdate(selections, isPropertiesToolUpdate) { if (lockedMultiValue.isMultiDiffValue || lockedMultiValue.value) { disableProperties(); getPropertyInputElement('locked').removeAttribute('disabled'); + setCopyPastePositionAndRotationAvailability (selections.length, true); } else { enableProperties(); disableSaveUserDataButton(); disableSaveMaterialDataButton(); + setCopyPastePositionAndRotationAvailability (selections.length, false); } const certificateIDMultiValue = getMultiplePropertyValue('certificateID'); @@ -4438,6 +4510,7 @@ function loaded() { }); updateVisibleSpaceModeProperties(); + requestZoneList(); if (window.EventBridge !== undefined) { EventBridge.scriptEventReceived.connect(function(data) { diff --git a/scripts/system/create/modules/brokenURLReport.html b/scripts/system/create/modules/brokenURLReport.html new file mode 100644 index 0000000000..6720bf29a2 --- /dev/null +++ b/scripts/system/create/modules/brokenURLReport.html @@ -0,0 +1,102 @@ + + + + + + + + +
+
+

+
+
+ Testing in progress... +

+
+ +
+
+ + + diff --git a/scripts/system/create/modules/brokenURLReport.js b/scripts/system/create/modules/brokenURLReport.js new file mode 100644 index 0000000000..c3a6eba8cd --- /dev/null +++ b/scripts/system/create/modules/brokenURLReport.js @@ -0,0 +1,393 @@ +// +// brokenURLReport.js +// +// Created by Alezia Kurdis on February 22, 2021. +// Copyright 2021 Vircadia contributors. +// +// This script reports broken URLs to the Create Application. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +var brokenURLReportHttpRequest; +var brokenURLReportUrlList = []; +var brokenURLReportInvalideUrlList = []; +var brokenURLReportProcessedUrlNo = 0; +var brokenURLReportUrlEntry; +var brokenURLReportMessageBox; +var brokenURLReportOverlayWebWindow; +var BROKEN_URL_REPORT_YES_BUTTON = 0x4000; +var BROKEN_URL_REPORT_NO_BUTTON = 0x10000; +var MAX_URL_BEFORE_WARNING_FOR_LONG_PROCESS = 20; + +function brokenURLReportRequestUrlValidityCheck(no) { + brokenURLReportHttpRequest = new XMLHttpRequest(); + brokenURLReportHttpRequest.requestComplete.connect(brokenURLReportGetResponseStatus); + brokenURLReportHttpRequest.open("GET", brokenURLReportUrlList[no].url); + brokenURLReportHttpRequest.send(); +} + +function brokenURLReportGetResponseStatus() { + if (brokenURLReportHttpRequest.status === 0 || brokenURLReportHttpRequest.status > 299) { + if (brokenURLReportHttpRequest.status === 0) { + brokenURLReportUrlList[brokenURLReportProcessedUrlNo].validity = "0 - URL not well-formed"; + } else { + brokenURLReportUrlList[brokenURLReportProcessedUrlNo].validity = brokenURLReportHttpRequest.status + " - " + brokenURLReportHttpRequest.statusText; + } + brokenURLReportInvalideUrlList.push(brokenURLReportUrlList[brokenURLReportProcessedUrlNo]); + } + brokenURLReportHttpRequest.requestComplete.disconnect(brokenURLReportGetResponseStatus); + brokenURLReportHttpRequest = null; + brokenURLReportProcessedUrlNo = brokenURLReportProcessedUrlNo + 1; + if (brokenURLReportProcessedUrlNo === brokenURLReportUrlList.length) { + brokenURLReportGenerateFormatedReport(brokenURLReportInvalideUrlList); + brokenURLReportUrlList = []; + brokenURLReportInvalideUrlList = []; + brokenURLReportProcessedUrlNo = 0; + } else { + brokenURLReportRequestUrlValidityCheck(brokenURLReportProcessedUrlNo); + } +} + +function brokenURLReportGenerateFormatedReport(brokenURLReportInvalideUrlList) { + var brokenURLReportContent = ""; + if (brokenURLReportInvalideUrlList.length === 0) { + brokenURLReportContent = "

Broken URL Report

" + brokenURLReportUrlList.length + " URL tested.
NO ISSUES HAVE BEEN FOUND.




"; + brokenURLReportContent += "

This report ignores Asset Server URLs (atp://), local drive paths, and any string not starting with 'http'.
"; + Script.setTimeout(function () { + brokenURLReportOverlayWebWindow.emitScriptEvent(brokenURLReportContent); + }, 3000); + return; + } + brokenURLReportContent = "

Broken URL Report

\n"; + brokenURLReportContent += "
Measure current setTimeout accuracy."zip" a list of keys and corresponding values to form key-value mapemulate Object.values(keyValues)generate an integer sequence (inclusive of [from, to])return compressed/decompressed versions of the input data
\n"; + brokenURLReportContent += " \n"; + brokenURLReportContent += " \n"; + brokenURLReportContent += " \n"; + brokenURLReportContent += " \n"; + brokenURLReportContent += " \n"; + brokenURLReportContent += " \n"; + brokenURLReportContent += " \n"; + brokenURLReportContent += " \n"; + brokenURLReportContent += " \n"; + brokenURLReportContent += " \n"; + brokenURLReportContent += " \n"; + brokenURLReportContent += " \n"; + brokenURLReportContent += " \n"; + brokenURLReportContent += " \n"; + for (var i = 0; i < brokenURLReportInvalideUrlList.length; i++ ){ + brokenURLReportContent += " \n"; + brokenURLReportContent += " \n"; + brokenURLReportContent += " \n"; + brokenURLReportContent += " \n"; + brokenURLReportContent += " \n"; + brokenURLReportContent += " \n"; + brokenURLReportContent += " \n"; + brokenURLReportContent += " \n"; + brokenURLReportContent += " \n"; + } + brokenURLReportContent += "
 EntityBroken Url
NoTypeName & ID PropertyStatusCurrent URL
" + (i + 1) + "" + brokenURLReportInvalideUrlList[i].type + "" + brokenURLReportInvalideUrlList[i].name + "
" + brokenURLReportInvalideUrlList[i].id + "
" + brokenURLReportInvalideUrlList[i].urlType + "" + brokenURLReportInvalideUrlList[i].validity + "" + brokenURLReportInvalideUrlList[i].url + "
\n"; + brokenURLReportContent += "

" + brokenURLReportUrlList.length + " URL tested.

"; + brokenURLReportContent += "
This report ignores Asset Server URLs (atp://), local drive paths, and any string not starting with 'http'.
"; + + Script.setTimeout(function () { + brokenURLReportOverlayWebWindow.emitScriptEvent(brokenURLReportContent); + }, 3000); +} + +function brokenURLReportGetUrlTypeColor(urlType) { + var color = "#FFFFFF"; + switch (urlType) { + case "script": + color = "#00FF00"; + break; + case "serverScripts": + color = "#FF00FF"; + break; + case "imageURL": + color = "#00FFFF"; + break; + case "materialURL": + color = "#FF6600"; + break; + case "modelURL": + color = "#FFFF00"; + break; + case "compoundShapeURL": + color = "#6666FF"; + break; + case "animation.url": + color = "#6699FF"; + break; + case "textures": + color = "#FF0066"; + break; + case "xTextureURL": + color = "#0000FF"; + break; + case "yTextureURL": + color = "#009966"; + break; + case "zTextureURL": + color = "#993366"; + break; + case "font": + color = "#FFFFFF"; + break; + case "sourceUrl": + color = "#BBFF00"; + break; + case "scriptURL": + color = "#FFBBBB"; + break; + case "filterURL": + color = "#BBBBFF"; + break; + case "skybox.url": + color = "#BBFFFF"; + break; + case "ambientLight.ambientURL": + color = "#FF3300"; + } + return color; +} + +function brokenURLReport(entityIDs) { + if (entityIDs.length === 0) { + audioFeedback.rejection(); + Window.alert("You have nothing selected."); + return; + } else { + var properties; + for (var i = 0; i < entityIDs.length; i++ ){ + properties = Entities.getEntityProperties(entityIDs[i]); + if (properties.script.toLowerCase().startsWith("http")) { + brokenURLReportUrlEntry = { + id: entityIDs[i], + name: properties.name, + type: properties.type, + urlType: "script", + url: properties.script, + validity: "NOT_TESTED" + }; + brokenURLReportUrlList.push(brokenURLReportUrlEntry); + } + if (properties.serverScripts.toLowerCase().startsWith("http")) { + brokenURLReportUrlEntry = { + id: entityIDs[i], + name: properties.name, + type: properties.type, + urlType: "serverScripts", + url: properties.serverScripts, + validity: "NOT_TESTED" + }; + brokenURLReportUrlList.push(brokenURLReportUrlEntry); + } + if (properties.type === "Image" && properties.imageURL.toLowerCase().startsWith("http")) { + brokenURLReportUrlEntry = { + id: entityIDs[i], + name: properties.name, + type: properties.type, + urlType: "imageURL", + url: properties.imageURL, + validity: "NOT_TESTED" + }; + brokenURLReportUrlList.push(brokenURLReportUrlEntry); + } + if (properties.type === "Material" && properties.materialURL.toLowerCase().startsWith("http")) { + brokenURLReportUrlEntry = { + id: entityIDs[i], + name: properties.name, + type: properties.type, + urlType: "materialURL", + url: properties.materialURL, + validity: "NOT_TESTED" + }; + brokenURLReportUrlList.push(brokenURLReportUrlEntry); + } + if (properties.type === "Model" && properties.modelURL.toLowerCase().startsWith("http")) { + brokenURLReportUrlEntry = { + id: entityIDs[i], + name: properties.name, + type: properties.type, + urlType: "modelURL", + url: properties.modelURL, + validity: "NOT_TESTED" + }; + brokenURLReportUrlList.push(brokenURLReportUrlEntry); + } + if ( + (properties.type === "Zone" || properties.type === "Model" || properties.type === "ParticleEffect") + && properties.compoundShapeURL.toLowerCase().startsWith("http") + ) { + brokenURLReportUrlEntry = { + id: entityIDs[i], + name: properties.name, + type: properties.type, + urlType: "compoundShapeURL", + url: properties.compoundShapeURL, + validity: "NOT_TESTED" + }; + brokenURLReportUrlList.push(brokenURLReportUrlEntry); + } + if (properties.type === "Model" && properties.animation.url.toLowerCase().startsWith("http")) { + brokenURLReportUrlEntry = { + id: entityIDs[i], + name: properties.name, + type: properties.type, + urlType: "animation.url", + url: properties.animation.url, + validity: "NOT_TESTED" + }; + brokenURLReportUrlList.push(brokenURLReportUrlEntry); + } + if (properties.type === "ParticleEffect" && properties.textures.toLowerCase().startsWith("http")) { + brokenURLReportUrlEntry = { + id: entityIDs[i], + name: properties.name, + type: properties.type, + urlType: "textures", + url: properties.textures, + validity: "NOT_TESTED" + }; + brokenURLReportUrlList.push(brokenURLReportUrlEntry); + } + if (properties.type === "PolyVox" && properties.xTextureURL.toLowerCase().startsWith("http")) { + brokenURLReportUrlEntry = { + id: entityIDs[i], + name: properties.name, + type: properties.type, + urlType: "xTextureURL", + url: properties.xTextureURL, + validity: "NOT_TESTED" + }; + brokenURLReportUrlList.push(brokenURLReportUrlEntry); + } + if (properties.type === "PolyVox" && properties.yTextureURL.toLowerCase().startsWith("http")) { + brokenURLReportUrlEntry = { + id: entityIDs[i], + name: properties.name, + type: properties.type, + urlType: "yTextureURL", + url: properties.yTextureURL, + validity: "NOT_TESTED" + }; + brokenURLReportUrlList.push(brokenURLReportUrlEntry); + } + if (properties.type === "PolyVox" && properties.zTextureURL.toLowerCase().startsWith("http")) { + brokenURLReportUrlEntry = { + id: entityIDs[i], + name: properties.name, + type: properties.type, + urlType: "zTextureURL", + url: properties.zTextureURL, + validity: "NOT_TESTED" + }; + brokenURLReportUrlList.push(brokenURLReportUrlEntry); + } + if (properties.type === "Text" && properties.font.toLowerCase().startsWith("http")) { + brokenURLReportUrlEntry = { + id: entityIDs[i], + name: properties.name, + type: properties.type, + urlType: "font", + url: properties.font, + validity: "NOT_TESTED" + }; + brokenURLReportUrlList.push(brokenURLReportUrlEntry); + } + if (properties.type === "Web" && properties.sourceUrl.toLowerCase().startsWith("http")) { + brokenURLReportUrlEntry = { + id: entityIDs[i], + name: properties.name, + type: properties.type, + urlType: "sourceUrl", + url: properties.sourceUrl, + validity: "NOT_TESTED" + }; + brokenURLReportUrlList.push(brokenURLReportUrlEntry); + } + if (properties.type === "Web" && properties.scriptURL.toLowerCase().startsWith("http")) { + brokenURLReportUrlEntry = { + id: entityIDs[i], + name: properties.name, + type: properties.type, + urlType: "scriptURL", + url: properties.scriptURL, + validity: "NOT_TESTED" + }; + brokenURLReportUrlList.push(brokenURLReportUrlEntry); + } + if (properties.type === "Zone" && properties.filterURL.toLowerCase().startsWith("http")) { + brokenURLReportUrlEntry = { + id: entityIDs[i], + name: properties.name, + type: properties.type, + urlType: "filterURL", + url: properties.filterURL, + validity: "NOT_TESTED" + }; + brokenURLReportUrlList.push(brokenURLReportUrlEntry); + } + if (properties.type === "Zone" && properties.skybox.url.toLowerCase().startsWith("http")) { + brokenURLReportUrlEntry = { + id: entityIDs[i], + name: properties.name, + type: properties.type, + urlType: "skybox.url", + url: properties.skybox.url, + validity: "NOT_TESTED" + }; + brokenURLReportUrlList.push(brokenURLReportUrlEntry); + } + if (properties.type === "Zone" && properties.ambientLight.ambientURL.toLowerCase().startsWith("http")) { + brokenURLReportUrlEntry = { + id: entityIDs[i], + name: properties.name, + type: properties.type, + urlType: "ambientLight.ambientURL", + url: properties.ambientLight.ambientURL, + validity: "NOT_TESTED" + }; + brokenURLReportUrlList.push(brokenURLReportUrlEntry); + } + } + if (brokenURLReportUrlList.length === 0) { + audioFeedback.confirmation(); + Window.alert("No 'http' URL has been found within the current selection."); + return; + } else { + if (brokenURLReportUrlList.length > MAX_URL_BEFORE_WARNING_FOR_LONG_PROCESS) { + var message = "Number of http URLs found: " + brokenURLReportUrlList.length + "\n The analysis may take time. Do you want to proceed?"; + var answer = Window.confirm(message); + if (!answer) { + return; + } + } + if (brokenURLReportOverlayWebWindow !== undefined) { + brokenURLReportOverlayWebWindow.close(); + } + brokenURLReportOverlayWebWindow = new OverlayWebWindow({ + title: "Broken URL Report", + source: Script.resolvePath("brokenURLReport.html"), + width: 1000, + height: 600 + }); + brokenURLReportContent = ""; + brokenURLReportRequestUrlValidityCheck(brokenURLReportProcessedUrlNo); + } + } + + brokenURLReportOverlayWebWindow.webEventReceived.connect(function (message) { + try { + var data = JSON.parse(message); + } catch(e) { + print("brokenURLReport.js: Error parsing JSON"); + return; + } + if (data.action === "select") { + selectionManager.setSelections([data.entityID], this); + } + }); +} diff --git a/scripts/system/create/modules/entityShapeVisualizer.js b/scripts/system/create/modules/entityShapeVisualizer.js index 7a1cd74d25..8f218f3555 100644 --- a/scripts/system/create/modules/entityShapeVisualizer.js +++ b/scripts/system/create/modules/entityShapeVisualizer.js @@ -13,6 +13,7 @@ var SHAPETYPE_TO_SHAPE = { "box": "Cube", "ellipsoid": "Sphere", + "sphere": "Sphere", "cylinder-y": "Cylinder", }; @@ -35,14 +36,6 @@ function getEntityShapePropertiesForType(properties) { modelURL: properties.compoundShapeURL, localDimensions: properties.localDimensions }; - } else if (properties.shapeType === "sphere") { - var sphereDiameter = Math.max(properties.localDimensions.x, properties.localDimensions.y, - properties.localDimensions.z); - return { - type: "Sphere", - modelURL: properties.compoundShapeURL, - localDimensions: {x: sphereDiameter, y: sphereDiameter, z: sphereDiameter} - }; } break; } diff --git a/scripts/system/html/css/edit-style.css b/scripts/system/html/css/edit-style.css index efbb531124..5aea382d63 100644 --- a/scripts/system/html/css/edit-style.css +++ b/scripts/system/html/css/edit-style.css @@ -463,6 +463,22 @@ input[type=button].white, button.hifi-edit-button.white { background-color: #afafaf; background: linear-gradient(#fff 20%, #afafaf 100%); } +input[type=button].secondary, button.hifi-edit-button.secondary { + font-family: Raleway-Bold; + font-size: 10px; + text-transform: uppercase; + vertical-align: top; + height: 18px; + min-width: 60px; + padding: 0 14px; + margin-right: 6px; + border-radius: 4px; + border: none; + color: #fff; + background-color: #000; + background: linear-gradient(#343434 20%, #000 100%); + cursor: pointer; +} input[type=button]:enabled:hover, button.hifi-edit-button:enabled:hover { background: linear-gradient(#000, #000); @@ -1939,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; @@ -1969,7 +2044,7 @@ div.entity-list-menu { } div.menu-separator{ - width: 90%; + width: 100%; height: 2px; background-color: #505050; } @@ -1987,12 +2062,12 @@ button.menu-button { } button.menu-button:hover { - background-color: #00B4EF; + background-color: #919191; border: none; } button.menu-button:active { - background-color: #00B4EF; + background-color: #919191; border: none; } diff --git a/scripts/system/miniTablet.js b/scripts/system/miniTablet.js index 1650cb60f4..c9942afd48 100644 --- a/scripts/system/miniTablet.js +++ b/scripts/system/miniTablet.js @@ -563,7 +563,7 @@ // Tablet targets. isGoto = false, - TABLET_ADDRESS_DIALOG = "hifi/tablet/TabletAddressDialog.qml", + TABLET_EXPLORE_APP_UI = Script.resolvePath("../communityScripts/explore/explore.html"), // Trigger values. leftTriggerOn = 0, @@ -907,7 +907,7 @@ var miniTabletProperties; if (isGoto) { - tablet.loadQMLSource(TABLET_ADDRESS_DIALOG); + tablet.gotoWebScreen(TABLET_EXPLORE_APP_UI); } else { tablet.gotoHomeScreen(); } diff --git a/server-console/CMakeLists.txt b/server-console/CMakeLists.txt index 49742cacf0..03432ab08d 100644 --- a/server-console/CMakeLists.txt +++ b/server-console/CMakeLists.txt @@ -1,5 +1,10 @@ set(TARGET_NAME packaged-server-console) +if (CLIENT_ONLY AND APPLE) + # Don't include Console.app in client-only OSX DMGs. + return() +endif() + if (PRODUCTION_BUILD) set(PRODUCTION_OPTION "--production") endif() @@ -24,7 +29,11 @@ set_target_properties(${TARGET_NAME}-npm-install PROPERTIES FOLDER "hidden/Serve # add a dependency from the package target to the server components if (BUILD_CLIENT) - add_dependencies(${TARGET_NAME} interface) + if (APPLE) + add_dependencies(${TARGET_NAME} Vircadia) + else() + add_dependencies(${TARGET_NAME} interface) + endif() endif() if (BUILD_SERVER) 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/main.js b/server-console/src/main.js index e83b37ac4c..80be5c3fc2 100644 --- a/server-console/src/main.js +++ b/server-console/src/main.js @@ -460,7 +460,7 @@ var labels = { } }, goHome: { - label: 'Visit Sandbox', + label: 'Visit Local Server', click: visitSandboxClicked, enabled: false }, 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-manual/controllers/CMakeLists.txt b/tests-manual/controllers/CMakeLists.txt index 03043c79f2..932826c8de 100644 --- a/tests-manual/controllers/CMakeLists.txt +++ b/tests-manual/controllers/CMakeLists.txt @@ -7,6 +7,7 @@ setup_hifi_project(Script Qml) set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "Tests/manual-tests/") setup_memory_debugger() +setup_thread_debugger() # link in the shared libraries link_hifi_libraries(shared gl script-engine plugins render-utils ui-plugins input-plugins display-plugins controllers) diff --git a/tests-manual/entities/CMakeLists.txt b/tests-manual/entities/CMakeLists.txt index 6d0bf9f149..a6eed4f234 100644 --- a/tests-manual/entities/CMakeLists.txt +++ b/tests-manual/entities/CMakeLists.txt @@ -4,6 +4,7 @@ set(TARGET_NAME "entities-test") # This is not a testcase -- just set it up as a regular hifi project setup_hifi_project(Network Script) setup_memory_debugger() +setup_thread_debugger() set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "Tests/manual-tests/") # link in the shared libraries diff --git a/tests-manual/gl/CMakeLists.txt b/tests-manual/gl/CMakeLists.txt index 40bb64be1c..5b738a6e39 100644 --- a/tests-manual/gl/CMakeLists.txt +++ b/tests-manual/gl/CMakeLists.txt @@ -2,6 +2,7 @@ set(TARGET_NAME gl-test) # This is not a testcase -- just set it up as a regular hifi project setup_hifi_project(Quick Gui OpenGL) setup_memory_debugger() +setup_thread_debugger() set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "Tests/manual-tests/") link_hifi_libraries(shared gl) package_libraries_for_deployment() diff --git a/tests-manual/gpu-textures/CMakeLists.txt b/tests-manual/gpu-textures/CMakeLists.txt index 907690748a..d148b0cd21 100644 --- a/tests-manual/gpu-textures/CMakeLists.txt +++ b/tests-manual/gpu-textures/CMakeLists.txt @@ -2,6 +2,7 @@ set(TARGET_NAME gpu-textures-tests) # This is not a testcase -- just set it up as a regular hifi project setup_hifi_project(Quick Gui Script) setup_memory_debugger() +setup_thread_debugger() set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "Tests/manual-tests/") link_hifi_libraries( shared shaders task networking gl diff --git a/tests-manual/gpu/CMakeLists.txt b/tests-manual/gpu/CMakeLists.txt index 6e3781acff..dc7bfbe75e 100644 --- a/tests-manual/gpu/CMakeLists.txt +++ b/tests-manual/gpu/CMakeLists.txt @@ -2,6 +2,7 @@ set(TARGET_NAME gpu-test) # This is not a testcase -- just set it up as a regular hifi project setup_hifi_project(Quick Gui Script) setup_memory_debugger() +setup_thread_debugger() set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "Tests/manual-tests/") link_hifi_libraries( shared task networking gl diff --git a/tests-manual/qml/CMakeLists.txt b/tests-manual/qml/CMakeLists.txt index f56b8c4533..1b56927713 100644 --- a/tests-manual/qml/CMakeLists.txt +++ b/tests-manual/qml/CMakeLists.txt @@ -1,6 +1,7 @@ set(TARGET_NAME qml-test) setup_hifi_project(Quick Qml Gui OpenGL) setup_memory_debugger() +setup_thread_debugger() set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "Tests/manual-tests/") link_hifi_libraries(shared networking gl qml) diff --git a/tests-manual/render-perf/CMakeLists.txt b/tests-manual/render-perf/CMakeLists.txt index 9e7d826d03..67d3ac2d86 100644 --- a/tests-manual/render-perf/CMakeLists.txt +++ b/tests-manual/render-perf/CMakeLists.txt @@ -6,6 +6,7 @@ if (WIN32) endif() setup_memory_debugger() +setup_thread_debugger() # This is not a testcase -- just set it up as a regular hifi project setup_hifi_project(Quick Gui) diff --git a/tests-manual/render-texture-load/CMakeLists.txt b/tests-manual/render-texture-load/CMakeLists.txt index 2e939e931a..77afdfa5d0 100644 --- a/tests-manual/render-texture-load/CMakeLists.txt +++ b/tests-manual/render-texture-load/CMakeLists.txt @@ -6,6 +6,7 @@ if (WIN32) endif() setup_memory_debugger() +setup_thread_debugger() # This is not a testcase -- just set it up as a regular hifi project setup_hifi_project(Quick Gui) diff --git a/tests-manual/render-utils/CMakeLists.txt b/tests-manual/render-utils/CMakeLists.txt index 9f575ee8ca..e5548de2b2 100644 --- a/tests-manual/render-utils/CMakeLists.txt +++ b/tests-manual/render-utils/CMakeLists.txt @@ -6,6 +6,7 @@ setup_hifi_project(Quick Gui) set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "Tests/manual-tests/") setup_memory_debugger() +setup_thread_debugger() # link in the shared libraries link_hifi_libraries(render-utils shaders gl gpu shared ${PLATFORM_GL_BACKEND}) diff --git a/tests/recording/CMakeLists.txt b/tests/recording/CMakeLists.txt index dbb942a27a..a0925aaf6d 100644 --- a/tests/recording/CMakeLists.txt +++ b/tests/recording/CMakeLists.txt @@ -3,6 +3,7 @@ set(TARGET_NAME recording-test) setup_hifi_project(Test) set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "Tests/manual-tests/") setup_memory_debugger() +setup_thread_debugger() link_hifi_libraries(shared recording) if (WIN32) target_link_libraries(${TARGET_NAME} Winmm.lib) diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index 4942ecbd63..5de2f6fdf8 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -21,20 +21,27 @@ endfunction() if (BUILD_TOOLS) set(ALL_TOOLS udt-test - vhacd-util gpu-frame-player ice-client ktx-tool ac-client skeleton-dump atp-client - oven ) + # Don't include oven or vhacd-til in OSX client-only DMGs. + if (NOT CLIENT_ONLY OR NOT APPLE) + list(APPEND ALL_TOOLS oven) + list(APPEND ALL_TOOLS vhacd-util) + endif() + # Allow different tools for stable builds if (STABLE_BUILD) else() - list(APPEND ALL_TOOLS nitpick) + # Don't include nitpick in OSX client-only DMGs. + if (NOT APPLE OR NOT CLIENT_ONLY) + list(APPEND ALL_TOOLS nitpick) + endif() endif() foreach(TOOL ${ALL_TOOLS}) diff --git a/tools/ac-client/CMakeLists.txt b/tools/ac-client/CMakeLists.txt index ad16187dcb..fe878b3cb4 100644 --- a/tools/ac-client/CMakeLists.txt +++ b/tools/ac-client/CMakeLists.txt @@ -1,4 +1,5 @@ set(TARGET_NAME ac-client) setup_hifi_project(Core) setup_memory_debugger() +setup_thread_debugger() link_hifi_libraries(shared networking) diff --git a/tools/atp-client/CMakeLists.txt b/tools/atp-client/CMakeLists.txt index 19c70597f7..0ed5969cb6 100644 --- a/tools/atp-client/CMakeLists.txt +++ b/tools/atp-client/CMakeLists.txt @@ -1,4 +1,5 @@ set(TARGET_NAME atp-client) setup_hifi_project(Core) setup_memory_debugger() +setup_thread_debugger() link_hifi_libraries(shared networking) diff --git a/tools/dissectors/1-hfudt.lua b/tools/dissectors/1-hfudt.lua index 9a51cc8d7c..5a03331fc6 100644 --- a/tools/dissectors/1-hfudt.lua +++ b/tools/dissectors/1-hfudt.lua @@ -53,7 +53,7 @@ local message_positions = { local packet_types = { [0] = "Unknown", - [1] = "StunResponse", + [1] = "DomainConnectRequestPending", [2] = "DomainList", [3] = "Ping", [4] = "PingReply", diff --git a/tools/doxygen/Doxyfile b/tools/doxygen/Doxyfile new file mode 100644 index 0000000000..de001ea220 --- /dev/null +++ b/tools/doxygen/Doxyfile @@ -0,0 +1,2665 @@ +# Doxyfile 1.9.1 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project. +# +# All text after a double hash (##) is considered a comment and is placed in +# front of the TAG it is preceding. +# +# All text after a single hash (#) is considered a comment and will be ignored. +# The format is: +# TAG = value [value, ...] +# For lists, items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (\" \"). + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the configuration +# file that follow. The default is UTF-8 which is also the encoding used for all +# text before the first occurrence of this tag. Doxygen uses libiconv (or the +# iconv built into libc) for the transcoding. See +# https://www.gnu.org/software/libiconv/ for the list of possible encodings. +# The default value is: UTF-8. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by +# double-quotes, unless you are using Doxywizard) that should identify the +# project for which the documentation is generated. This name is used in the +# title of most generated pages and in a few other places. +# The default value is: My Project. + +PROJECT_NAME = "Vircadia C++ Documentation" + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. This +# could be handy for archiving the generated documentation or if some version +# control system is used. + +PROJECT_NUMBER = + +# Using the PROJECT_BRIEF tag one can provide an optional one line description +# for a project that appears at the top of each page and should give viewer a +# quick idea about the purpose of the project. Keep the description short. + +PROJECT_BRIEF = + +# With the PROJECT_LOGO tag one can specify a logo or an icon that is included +# in the documentation. The maximum height of the logo should not exceed 55 +# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy +# the logo to the output directory. + +PROJECT_LOGO = vircadia.png + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path +# into which the generated documentation will be written. If a relative path is +# entered, it will be relative to the location where doxygen was started. If +# left blank the current directory will be used. + +OUTPUT_DIRECTORY = ../../build/docs + +# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub- +# directories (in 2 levels) under the output directory of each output format and +# will distribute the generated files over these directories. Enabling this +# option can be useful when feeding doxygen a huge amount of source files, where +# putting all generated files in the same directory would otherwise causes +# performance problems for the file system. +# The default value is: NO. + +CREATE_SUBDIRS = NO + +# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII +# characters to appear in the names of generated files. If set to NO, non-ASCII +# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode +# U+3044. +# The default value is: NO. + +ALLOW_UNICODE_NAMES = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese, +# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States), +# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian, +# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages), +# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian, +# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian, +# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish, +# Ukrainian and Vietnamese. +# The default value is: English. + +OUTPUT_LANGUAGE = English + +# The OUTPUT_TEXT_DIRECTION tag is used to specify the direction in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all generated output in the proper direction. +# Possible values are: None, LTR, RTL and Context. +# The default value is: None. + +OUTPUT_TEXT_DIRECTION = None + +# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member +# descriptions after the members that are listed in the file and class +# documentation (similar to Javadoc). Set to NO to disable this. +# The default value is: YES. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief +# description of a member or function before the detailed description +# +# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. +# The default value is: YES. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator that is +# used to form the text in various listings. Each string in this list, if found +# as the leading text of the brief description, will be stripped from the text +# and the result, after processing the whole list, is used as the annotated +# text. Otherwise, the brief description is used as-is. If left blank, the +# following values are used ($name is automatically replaced with the name of +# the entity):The $name class, The $name widget, The $name file, is, provides, +# specifies, contains, represents, a, an and the. + +ABBREVIATE_BRIEF = "The $name class" \ + "The $name widget" \ + "The $name file" \ + is \ + provides \ + specifies \ + contains \ + represents \ + a \ + an \ + the + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# doxygen will generate a detailed section even if there is only a brief +# description. +# The default value is: NO. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. +# The default value is: NO. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path +# before files name in the file list and in the header files. If set to NO the +# shortest path that makes the file name unique will be used +# The default value is: YES. + +FULL_PATH_NAMES = NO + +# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. +# Stripping is only done if one of the specified strings matches the left-hand +# part of the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the path to +# strip. +# +# Note that you can specify absolute paths here, but also relative paths, which +# will be relative from the directory where doxygen is started. +# This tag requires that the tag FULL_PATH_NAMES is set to YES. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the +# path mentioned in the documentation of a class, which tells the reader which +# header file to include in order to use a class. If left blank only the name of +# the header file containing the class definition is used. Otherwise one should +# specify the list of include paths that are normally passed to the compiler +# using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but +# less readable) file names. This can be useful is your file systems doesn't +# support long names like on DOS, Mac, or CD-ROM. +# The default value is: NO. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the +# first line (until the first dot) of a Javadoc-style comment as the brief +# description. If set to NO, the Javadoc-style will behave just like regular Qt- +# style comments (thus requiring an explicit @brief command for a brief +# description.) +# The default value is: NO. + +JAVADOC_AUTOBRIEF = NO + +# If the JAVADOC_BANNER tag is set to YES then doxygen will interpret a line +# such as +# /*************** +# as being the beginning of a Javadoc-style comment "banner". If set to NO, the +# Javadoc-style will behave just like regular comments and it will not be +# interpreted by doxygen. +# The default value is: NO. + +JAVADOC_BANNER = NO + +# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first +# line (until the first dot) of a Qt-style comment as the brief description. If +# set to NO, the Qt-style will behave just like regular Qt-style comments (thus +# requiring an explicit \brief command for a brief description.) +# The default value is: NO. + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a +# multi-line C++ special comment block (i.e. a block of //! or /// comments) as +# a brief description. This used to be the default behavior. The new default is +# to treat a multi-line C++ comment block as a detailed description. Set this +# tag to YES if you prefer the old behavior instead. +# +# Note that setting this tag to YES also means that rational rose comments are +# not recognized any more. +# The default value is: NO. + +MULTILINE_CPP_IS_BRIEF = NO + +# By default Python docstrings are displayed as preformatted text and doxygen's +# special commands cannot be used. By setting PYTHON_DOCSTRING to NO the +# doxygen's special commands can be used and the contents of the docstring +# documentation blocks is shown as doxygen documentation. +# The default value is: YES. + +PYTHON_DOCSTRING = YES + +# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the +# documentation from any documented member that it re-implements. +# The default value is: YES. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new +# page for each member. If set to NO, the documentation of a member will be part +# of the file/class/namespace that contains it. +# The default value is: NO. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen +# uses this value to replace tabs by spaces in code fragments. +# Minimum value: 1, maximum value: 16, default value: 4. + +TAB_SIZE = 4 + +# This tag can be used to specify a number of aliases that act as commands in +# the documentation. An alias has the form: +# name=value +# For example adding +# "sideeffect=@par Side Effects:\n" +# will allow you to put the command \sideeffect (or @sideeffect) in the +# documentation, which will result in a user-defined paragraph with heading +# "Side Effects:". You can put \n's in the value part of an alias to insert +# newlines (in the resulting output). You can put ^^ in the value part of an +# alias to insert a newline as if a physical newline was in the original file. +# When you need a literal { or } or , in the value part of an alias you have to +# escape them by means of a backslash (\), this can lead to conflicts with the +# commands \{ and \} for these it is advised to use the version @{ and @} or use +# a double escape (\\{ and \\}) + +ALIASES = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources +# only. Doxygen will then generate output that is more tailored for C. For +# instance, some of the names that are used will be different. The list of all +# members will be omitted, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_FOR_C = NO + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or +# Python sources only. Doxygen will then generate output that is more tailored +# for that language. For instance, namespaces will be presented as packages, +# qualified scopes will look different, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources. Doxygen will then generate output that is tailored for Fortran. +# The default value is: NO. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for VHDL. +# The default value is: NO. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Set the OPTIMIZE_OUTPUT_SLICE tag to YES if your project consists of Slice +# sources only. Doxygen will then generate output that is more tailored for that +# language. For instance, namespaces will be presented as modules, types will be +# separated into more groups, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_SLICE = NO + +# Doxygen selects the parser to use depending on the extension of the files it +# parses. With this tag you can assign which parser to use for a given +# extension. Doxygen has a built-in mapping, but you can override or extend it +# using this tag. The format is ext=language, where ext is a file extension, and +# language is one of the parsers supported by doxygen: IDL, Java, JavaScript, +# Csharp (C#), C, C++, D, PHP, md (Markdown), Objective-C, Python, Slice, VHDL, +# Fortran (fixed format Fortran: FortranFixed, free formatted Fortran: +# FortranFree, unknown formatted Fortran: Fortran. In the later case the parser +# tries to guess whether the code is fixed or free formatted code, this is the +# default for Fortran type files). For instance to make doxygen treat .inc files +# as Fortran files (default is PHP), and .f files as C (default is Fortran), +# use: inc=Fortran f=C. +# +# Note: For files without extension you can use no_extension as a placeholder. +# +# Note that for custom extensions you also need to set FILE_PATTERNS otherwise +# the files are not read by doxygen. When specifying no_extension you should add +# * to the FILE_PATTERNS. +# +# Note see also the list of default file extension mappings. + +EXTENSION_MAPPING = + +# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments +# according to the Markdown format, which allows for more readable +# documentation. See https://daringfireball.net/projects/markdown/ for details. +# The output of markdown processing is further processed by doxygen, so you can +# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in +# case of backward compatibilities issues. +# The default value is: YES. + +MARKDOWN_SUPPORT = YES + +# When the TOC_INCLUDE_HEADINGS tag is set to a non-zero value, all headings up +# to that level are automatically included in the table of contents, even if +# they do not have an id attribute. +# Note: This feature currently applies only to Markdown headings. +# Minimum value: 0, maximum value: 99, default value: 5. +# This tag requires that the tag MARKDOWN_SUPPORT is set to YES. + +TOC_INCLUDE_HEADINGS = 5 + +# When enabled doxygen tries to link words that correspond to documented +# classes, or namespaces to their corresponding documentation. Such a link can +# be prevented in individual cases by putting a % sign in front of the word or +# globally by setting AUTOLINK_SUPPORT to NO. +# The default value is: YES. + +AUTOLINK_SUPPORT = YES + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should set this +# tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); +# versus func(std::string) {}). This also make the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. +# The default value is: NO. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. +# The default value is: NO. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip (see: +# https://www.riverbankcomputing.com/software/sip/intro) sources only. Doxygen +# will parse them like normal C++ but will assume all classes use public instead +# of private inheritance when no explicit protection keyword is present. +# The default value is: NO. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate +# getter and setter methods for a property. Setting this option to YES will make +# doxygen to replace the get and set methods by a property in the documentation. +# This will only work if the methods are indeed getting or setting a simple +# type. If this is not the case, or you want to show the methods anyway, you +# should set this option to NO. +# The default value is: YES. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. +# The default value is: NO. + +DISTRIBUTE_GROUP_DOC = NO + +# If one adds a struct or class to a group and this option is enabled, then also +# any nested class or struct is added to the same group. By default this option +# is disabled and one has to add nested compounds explicitly via \ingroup. +# The default value is: NO. + +GROUP_NESTED_COMPOUNDS = NO + +# Set the SUBGROUPING tag to YES to allow class member groups of the same type +# (for instance a group of public functions) to be put as a subgroup of that +# type (e.g. under the Public Functions section). Set it to NO to prevent +# subgrouping. Alternatively, this can be done per class using the +# \nosubgrouping command. +# The default value is: YES. + +SUBGROUPING = YES + +# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions +# are shown inside the group in which they are included (e.g. using \ingroup) +# instead of on a separate page (for HTML and Man pages) or section (for LaTeX +# and RTF). +# +# Note that this feature does not work in combination with +# SEPARATE_MEMBER_PAGES. +# The default value is: NO. + +INLINE_GROUPED_CLASSES = NO + +# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions +# with only public data fields or simple typedef fields will be shown inline in +# the documentation of the scope in which they are defined (i.e. file, +# namespace, or group documentation), provided this scope is documented. If set +# to NO, structs, classes, and unions are shown on a separate page (for HTML and +# Man pages) or section (for LaTeX and RTF). +# The default value is: NO. + +INLINE_SIMPLE_STRUCTS = NO + +# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or +# enum is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically be +# useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. +# The default value is: NO. + +TYPEDEF_HIDES_STRUCT = NO + +# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This +# cache is used to resolve symbols given their name and scope. Since this can be +# an expensive process and often the same symbol appears multiple times in the +# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small +# doxygen will become slower. If the cache is too large, memory is wasted. The +# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range +# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 +# symbols. At the end of a run doxygen will report the cache usage and suggest +# the optimal cache size from a speed point of view. +# Minimum value: 0, maximum value: 9, default value: 0. + +LOOKUP_CACHE_SIZE = 0 + +# The NUM_PROC_THREADS specifies the number threads doxygen is allowed to use +# during processing. When set to 0 doxygen will based this on the number of +# cores available in the system. You can set it explicitly to a value larger +# than 0 to get more control over the balance between CPU load and processing +# speed. At this moment only the input processing can be done using multiple +# threads. Since this is still an experimental feature the default is set to 1, +# which efficively disables parallel processing. Please report any issues you +# encounter. Generating dot graphs in parallel is controlled by the +# DOT_NUM_THREADS setting. +# Minimum value: 0, maximum value: 32, default value: 1. + +NUM_PROC_THREADS = 1 + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in +# documentation are documented, even if no documentation was available. Private +# class members and static file members will be hidden unless the +# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. +# Note: This will also disable the warnings about undocumented members that are +# normally produced when WARNINGS is set to YES. +# The default value is: NO. + +EXTRACT_ALL = NO + +# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will +# be included in the documentation. +# The default value is: NO. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_PRIV_VIRTUAL tag is set to YES, documented private virtual +# methods of a class will be included in the documentation. +# The default value is: NO. + +EXTRACT_PRIV_VIRTUAL = NO + +# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal +# scope will be included in the documentation. +# The default value is: NO. + +EXTRACT_PACKAGE = NO + +# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be +# included in the documentation. +# The default value is: NO. + +EXTRACT_STATIC = NO + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined +# locally in source files will be included in the documentation. If set to NO, +# only classes defined in header files are included. Does not have any effect +# for Java sources. +# The default value is: YES. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. If set to YES, local methods, +# which are defined in the implementation section but not in the interface are +# included in the documentation. If set to NO, only methods in the interface are +# included. +# The default value is: NO. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base name of +# the file that contains the anonymous namespace. By default anonymous namespace +# are hidden. +# The default value is: NO. + +EXTRACT_ANON_NSPACES = NO + +# If this flag is set to YES, the name of an unnamed parameter in a declaration +# will be determined by the corresponding definition. By default unnamed +# parameters remain unnamed in the output. +# The default value is: YES. + +RESOLVE_UNNAMED_PARAMS = YES + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all +# undocumented members inside documented classes or files. If set to NO these +# members will be included in the various overviews, but no documentation +# section is generated. This option has no effect if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_MEMBERS = YES + +# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. If set +# to NO, these classes will be included in the various overviews. This option +# has no effect if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_CLASSES = YES + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend +# declarations. If set to NO, these declarations will be included in the +# documentation. +# The default value is: NO. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any +# documentation blocks found inside the body of a function. If set to NO, these +# blocks will be appended to the function's detailed documentation block. +# The default value is: NO. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation that is typed after a +# \internal command is included. If the tag is set to NO then the documentation +# will be excluded. Set it to YES to include the internal documentation. +# The default value is: NO. + +INTERNAL_DOCS = NO + +# With the correct setting of option CASE_SENSE_NAMES doxygen will better be +# able to match the capabilities of the underlying filesystem. In case the +# filesystem is case sensitive (i.e. it supports files in the same directory +# whose names only differ in casing), the option must be set to YES to properly +# deal with such files in case they appear in the input. For filesystems that +# are not case sensitive the option should be be set to NO to properly deal with +# output files written for symbols that only differ in casing, such as for two +# classes, one named CLASS and the other named Class, and to also support +# references to files without having to specify the exact matching casing. On +# Windows (including Cygwin) and MacOS, users should typically set this option +# to NO, whereas on Linux or other Unix flavors it should typically be set to +# YES. +# The default value is: system dependent. + +CASE_SENSE_NAMES = NO + +# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with +# their full class and namespace scopes in the documentation. If set to YES, the +# scope will be hidden. +# The default value is: NO. + +HIDE_SCOPE_NAMES = NO + +# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will +# append additional text to a page's title, such as Class Reference. If set to +# YES the compound reference will be hidden. +# The default value is: NO. + +HIDE_COMPOUND_REFERENCE= NO + +# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of +# the files that are included by a file in the documentation of that file. +# The default value is: YES. + +SHOW_INCLUDE_FILES = YES + +# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each +# grouped member an include statement to the documentation, telling the reader +# which file to include in order to use the member. +# The default value is: NO. + +SHOW_GROUPED_MEMB_INC = NO + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include +# files with double quotes in the documentation rather than with sharp brackets. +# The default value is: NO. + +FORCE_LOCAL_INCLUDES = NO + +# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the +# documentation for inline members. +# The default value is: YES. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the +# (detailed) documentation of file and class members alphabetically by member +# name. If set to NO, the members will appear in declaration order. +# The default value is: YES. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief +# descriptions of file, namespace and class members alphabetically by member +# name. If set to NO, the members will appear in declaration order. Note that +# this will also influence the order of the classes in the class list. +# The default value is: NO. + +SORT_BRIEF_DOCS = NO + +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the +# (brief and detailed) documentation of class members so that constructors and +# destructors are listed first. If set to NO the constructors will appear in the +# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. +# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief +# member documentation. +# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting +# detailed member documentation. +# The default value is: NO. + +SORT_MEMBERS_CTORS_1ST = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy +# of group names into alphabetical order. If set to NO the group names will +# appear in their defined order. +# The default value is: NO. + +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by +# fully-qualified names, including namespaces. If set to NO, the class list will +# be sorted only by class name, not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the alphabetical +# list. +# The default value is: NO. + +SORT_BY_SCOPE_NAME = NO + +# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper +# type resolution of all parameters of a function it will reject a match between +# the prototype and the implementation of a member function even if there is +# only one candidate or it is obvious which candidate to choose by doing a +# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still +# accept a match between prototype and implementation in such cases. +# The default value is: NO. + +STRICT_PROTO_MATCHING = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo +# list. This list is created by putting \todo commands in the documentation. +# The default value is: YES. + +GENERATE_TODOLIST = NO + +# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test +# list. This list is created by putting \test commands in the documentation. +# The default value is: YES. + +GENERATE_TESTLIST = NO + +# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug +# list. This list is created by putting \bug commands in the documentation. +# The default value is: YES. + +GENERATE_BUGLIST = NO + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO) +# the deprecated list. This list is created by putting \deprecated commands in +# the documentation. +# The default value is: YES. + +GENERATE_DEPRECATEDLIST= NO + +# The ENABLED_SECTIONS tag can be used to enable conditional documentation +# sections, marked by \if ... \endif and \cond +# ... \endcond blocks. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the +# initial value of a variable or macro / define can have for it to appear in the +# documentation. If the initializer consists of more lines than specified here +# it will be hidden. Use a value of 0 to hide initializers completely. The +# appearance of the value of individual variables and macros / defines can be +# controlled using \showinitializer or \hideinitializer command in the +# documentation regardless of this setting. +# Minimum value: 0, maximum value: 10000, default value: 30. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at +# the bottom of the documentation of classes and structs. If set to YES, the +# list will mention the files that were used to generate the documentation. +# The default value is: YES. + +SHOW_USED_FILES = YES + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This +# will remove the Files entry from the Quick Index and from the Folder Tree View +# (if specified). +# The default value is: YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces +# page. This will remove the Namespaces entry from the Quick Index and from the +# Folder Tree View (if specified). +# The default value is: YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command command input-file, where command is the value of the +# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided +# by doxygen. Whatever the program writes to standard output is used as the file +# version. For an example see the documentation. + +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed +# by doxygen. The layout file controls the global structure of the generated +# output files in an output format independent way. To create the layout file +# that represents doxygen's defaults, run doxygen with the -l option. You can +# optionally specify a file name after the option, if omitted DoxygenLayout.xml +# will be used as the name of the layout file. +# +# Note that if you run doxygen from a directory containing a file called +# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE +# tag is left empty. + +LAYOUT_FILE = + +# The CITE_BIB_FILES tag can be used to specify one or more bib files containing +# the reference definitions. This must be a list of .bib files. The .bib +# extension is automatically appended if omitted. This requires the bibtex tool +# to be installed. See also https://en.wikipedia.org/wiki/BibTeX for more info. +# For LaTeX the style of the bibliography can be controlled using +# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the +# search path. See also \cite for info how to create references. + +CITE_BIB_FILES = + +#--------------------------------------------------------------------------- +# Configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated to +# standard output by doxygen. If QUIET is set to YES this implies that the +# messages are off. +# The default value is: 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 +# this implies that the warnings are on. +# +# Tip: Turn warnings on while writing the documentation. +# The default value is: YES. + +WARNINGS = YES + +# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate +# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag +# will automatically be disabled. +# The default value is: YES. + +WARN_IF_UNDOCUMENTED = YES + +# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some parameters +# in a documented function, or documenting parameters that don't exist or using +# markup commands wrongly. +# The default value is: YES. + +WARN_IF_DOC_ERROR = YES + +# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that +# are documented, but have no documentation for their parameters or return +# value. If set to NO, doxygen will only warn about wrong or incomplete +# parameter documentation, but not about the absence of documentation. If +# EXTRACT_ALL is set to YES then this flag will automatically be disabled. +# The default value is: NO. + +WARN_NO_PARAMDOC = NO + +# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when +# a warning is encountered. If the WARN_AS_ERROR tag is set to FAIL_ON_WARNINGS +# then doxygen will continue running as if WARN_AS_ERROR tag is set to NO, but +# at the end of the doxygen process doxygen will return with a non-zero status. +# Possible values are: NO, YES and FAIL_ON_WARNINGS. +# The default value is: NO. + +WARN_AS_ERROR = NO + +# The WARN_FORMAT tag determines the format of the warning messages that doxygen +# can produce. The string should contain the $file, $line, and $text tags, which +# will be replaced by the file and line number from which the warning originated +# and the warning text. Optionally the format may contain $version, which will +# be replaced by the version of the file (if it could be obtained via +# FILE_VERSION_FILTER) +# The default value is: $file:$line: $text. + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning and error +# messages should be written. If left blank the output is written to standard +# error (stderr). + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# Configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag is used to specify the files and/or directories that contain +# documented source files. You may enter file names like myfile.cpp or +# directories like /usr/src/myproject. Separate the files or directories with +# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING +# Note: If this tag is empty the current directory is searched. + +INPUT = ../../assignment-client \ + ../../domain-server \ + ../../ice-server \ + ../../interface \ + ../../libraries \ + ../../plugins + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses +# libiconv (or the iconv built into libc) for the transcoding. See the libiconv +# documentation (see: +# https://www.gnu.org/software/libiconv/) for the list of possible encodings. +# The default value is: UTF-8. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and +# *.h) to filter out the source-files in the directories. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# read by doxygen. +# +# Note the list of default checked file patterns might differ from the list of +# default file extension mappings. +# +# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp, +# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, +# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, +# *.m, *.markdown, *.md, *.mm, *.dox (to be provided as doxygen C comment), +# *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, *.f18, *.f, *.for, *.vhd, *.vhdl, +# *.ucf, *.qsf and *.ice. + +FILE_PATTERNS = *.c \ + *.cc \ + *.cxx \ + *.cpp \ + *.c++ \ + *.java \ + *.ii \ + *.ixx \ + *.ipp \ + *.i++ \ + *.inl \ + *.idl \ + *.ddl \ + *.odl \ + *.h \ + *.hh \ + *.hxx \ + *.hpp \ + *.h++ \ + *.cs \ + *.d \ + *.php \ + *.php4 \ + *.php5 \ + *.phtml \ + *.inc \ + *.m \ + *.markdown \ + *.md \ + *.mm \ + *.dox \ + *.py \ + *.pyw \ + *.f90 \ + *.f95 \ + *.f03 \ + *.f08 \ + *.f18 \ + *.f \ + *.for \ + *.vhd \ + *.vhdl \ + *.ucf \ + *.qsf \ + *.ice + +# The RECURSIVE tag can be used to specify whether or not subdirectories should +# be searched for input files as well. +# The default value is: NO. + +RECURSIVE = YES + +# The EXCLUDE tag can be used to specify files and/or directories that should be +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. +# +# Note that relative paths are relative to the directory from which doxygen is +# run. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or +# directories that are symbolic links (a Unix file system feature) are excluded +# from the input. +# The default value is: NO. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories for example use the pattern */test/* + +EXCLUDE_PATTERNS = + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories use the pattern */test/* + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or directories +# that contain example code fragments that are included (see the \include +# command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and +# *.h) to filter out the source-files in the directories. If left blank all +# files are included. + +EXAMPLE_PATTERNS = * + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude commands +# irrespective of the value of the RECURSIVE tag. +# The default value is: NO. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or directories +# that contain images that are to be included in the documentation (see the +# \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command: +# +# +# +# where is the value of the INPUT_FILTER tag, and is the +# name of an input file. Doxygen will then use the output that the filter +# program writes to standard output. If FILTER_PATTERNS is specified, this tag +# will be ignored. +# +# Note that the filter must not add or remove lines; it is applied before the +# code is scanned, but not when the output code is generated. If lines are added +# or removed, the anchors will not be placed correctly. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# properly processed by doxygen. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: pattern=filter +# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how +# filters are used. If the FILTER_PATTERNS tag is empty or if none of the +# patterns match the file name, INPUT_FILTER is applied. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# properly processed by doxygen. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will also be used to filter the input files that are used for +# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). +# The default value is: NO. + +FILTER_SOURCE_FILES = NO + +# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file +# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and +# it is also possible to disable source filtering for a specific pattern using +# *.ext= (so without naming a filter). +# This tag requires that the tag FILTER_SOURCE_FILES is set to YES. + +FILTER_SOURCE_PATTERNS = + +# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that +# is part of the input, its contents will be placed on the main page +# (index.html). This can be useful if you have a project on for instance GitHub +# and want to reuse the introduction page also for the doxygen output. + +USE_MDFILE_AS_MAINPAGE = + +#--------------------------------------------------------------------------- +# Configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will be +# generated. Documented entities will be cross-referenced with these sources. +# +# Note: To get rid of all source code in the generated output, make sure that +# also VERBATIM_HEADERS is set to NO. +# The default value is: NO. + +SOURCE_BROWSER = NO + +# Setting the INLINE_SOURCES tag to YES will include the body of functions, +# classes and enums directly into the documentation. +# The default value is: NO. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any +# special comment blocks from generated source code fragments. Normal C, C++ and +# Fortran comments will always remain visible. +# The default value is: YES. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES then for each documented +# entity all documented functions referencing it will be listed. +# The default value is: NO. + +REFERENCED_BY_RELATION = NO + +# If the REFERENCES_RELATION tag is set to YES then for each documented function +# all documented entities called/used by that function will be listed. +# The default value is: NO. + +REFERENCES_RELATION = NO + +# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set +# to YES then the hyperlinks from functions in REFERENCES_RELATION and +# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will +# link to the documentation. +# The default value is: YES. + +REFERENCES_LINK_SOURCE = YES + +# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the +# source code will show a tooltip with additional information such as prototype, +# brief description and links to the definition and documentation. Since this +# will make the HTML file larger and loading of large files a bit slower, you +# can opt to disable this feature. +# The default value is: YES. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +SOURCE_TOOLTIPS = YES + +# If the USE_HTAGS tag is set to YES then the references to source code will +# point to the HTML generated by the htags(1) tool instead of doxygen built-in +# source browser. The htags tool is part of GNU's global source tagging system +# (see https://www.gnu.org/software/global/global.html). You will need version +# 4.8.6 or higher. +# +# To use it do the following: +# - Install the latest version of global +# - Enable SOURCE_BROWSER and USE_HTAGS in the configuration file +# - Make sure the INPUT points to the root of the source tree +# - Run doxygen as normal +# +# Doxygen will invoke htags (and that will in turn invoke gtags), so these +# tools must be available from the command line (i.e. in the search path). +# +# The result: instead of the source browser generated by doxygen, the links to +# source code will now point to the output of htags. +# The default value is: NO. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a +# verbatim copy of the header file for each class for which an include is +# specified. Set to NO to disable this. +# See also: Section \class. +# The default value is: YES. + +VERBATIM_HEADERS = YES + +# If the CLANG_ASSISTED_PARSING tag is set to YES then doxygen will use the +# clang parser (see: +# http://clang.llvm.org/) for more accurate parsing at the cost of reduced +# performance. This can be particularly helpful with template rich C++ code for +# which doxygen's built-in parser lacks the necessary type information. +# Note: The availability of this option depends on whether or not doxygen was +# generated with the -Duse_libclang=ON option for CMake. +# The default value is: NO. + +CLANG_ASSISTED_PARSING = NO + +# If clang assisted parsing is enabled and the CLANG_ADD_INC_PATHS tag is set to +# YES then doxygen will add the directory of each input to the include path. +# The default value is: YES. + +CLANG_ADD_INC_PATHS = YES + +# If clang assisted parsing is enabled you can provide the compiler with command +# line options that you would normally use when invoking the compiler. Note that +# the include paths will already be set by doxygen for the files and directories +# specified with INPUT and INCLUDE_PATH. +# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES. + +CLANG_OPTIONS = + +# If clang assisted parsing is enabled you can provide the clang parser with the +# path to the directory containing a file called compile_commands.json. This +# file is the compilation database (see: +# http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html) containing the +# options used when the source files were built. This is equivalent to +# specifying the -p option to a clang tool, such as clang-check. These options +# will then be passed to the parser. Any options specified with CLANG_OPTIONS +# will be added as well. +# Note: The availability of this option depends on whether or not doxygen was +# generated with the -Duse_libclang=ON option for CMake. + +CLANG_DATABASE_PATH = + +#--------------------------------------------------------------------------- +# Configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all +# compounds will be generated. Enable this if the project contains a lot of +# classes, structs, unions or interfaces. +# The default value is: YES. + +ALPHABETICAL_INDEX = NO + +# In case all classes in a project start with a common prefix, all classes will +# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag +# can be used to specify a prefix (or a list of prefixes) that should be ignored +# while generating the index headers. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output +# The default value is: YES. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a +# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of +# it. +# The default directory is: html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each +# generated HTML page (for example: .htm, .php, .asp). +# The default value is: .html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a user-defined HTML header file for +# each generated HTML page. If the tag is left blank doxygen will generate a +# standard header. +# +# To get valid HTML the header file that includes any scripts and style sheets +# that doxygen needs, which is dependent on the configuration options used (e.g. +# the setting GENERATE_TREEVIEW). It is highly recommended to start with a +# default header using +# doxygen -w html new_header.html new_footer.html new_stylesheet.css +# YourConfigFile +# and then modify the file new_header.html. See also section "Doxygen usage" +# for information on how to generate the default header that doxygen normally +# uses. +# Note: The header is subject to change so you typically have to regenerate the +# default header when upgrading to a newer version of doxygen. For a description +# of the possible markers and block names see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each +# generated HTML page. If the tag is left blank doxygen will generate a standard +# footer. See HTML_HEADER for more information on how to generate a default +# footer and what special commands can be used inside the footer. See also +# section "Doxygen usage" for information on how to generate the default footer +# that doxygen normally uses. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style +# sheet that is used by each HTML page. It can be used to fine-tune the look of +# the HTML output. If left blank doxygen will generate a default style sheet. +# See also section "Doxygen usage" for information on how to generate the style +# sheet that doxygen normally uses. +# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as +# it is more robust and this tag (HTML_STYLESHEET) will in the future become +# obsolete. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_STYLESHEET = + +# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined +# cascading style sheets that are included after the standard style sheets +# created by doxygen. Using this option one can overrule certain style aspects. +# This is preferred over using HTML_STYLESHEET since it does not replace the +# standard style sheet and is therefore more robust against future updates. +# Doxygen will copy the style sheet files to the output directory. +# Note: The order of the extra style sheet files is of importance (e.g. the last +# style sheet in the list overrules the setting of the previous ones in the +# list). For an example see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_STYLESHEET = + +# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or +# other source files which should be copied to the HTML output directory. Note +# that these files will be copied to the base HTML output directory. Use the +# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these +# files. In the HTML_STYLESHEET file, use the file name only. Also note that the +# files will be copied as-is; there are no commands or markers available. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_FILES = + +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen +# will adjust the colors in the style sheet and background images according to +# this color. Hue is specified as an angle on a colorwheel, see +# https://en.wikipedia.org/wiki/Hue for more information. For instance the value +# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 +# purple, and 360 is red again. +# Minimum value: 0, maximum value: 359, default value: 220. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_HUE = 220 + +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors +# in the HTML output. For a value of 0 the output will use grayscales only. A +# value of 255 will produce the most vivid colors. +# Minimum value: 0, maximum value: 255, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_SAT = 100 + +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the +# luminance component of the colors in the HTML output. Values below 100 +# gradually make the output lighter, whereas values above 100 make the output +# darker. The value divided by 100 is the actual gamma applied, so 80 represents +# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not +# change the gamma. +# Minimum value: 40, maximum value: 240, default value: 80. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_GAMMA = 80 + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting this +# to YES can help to show when doxygen was last run and thus if the +# documentation is up to date. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_TIMESTAMP = NO + +# If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML +# documentation will contain a main index with vertical navigation menus that +# are dynamically created via JavaScript. If disabled, the navigation index will +# consists of multiple levels of tabs that are statically embedded in every HTML +# page. Disable this option to support browsers that do not have JavaScript, +# like the Qt help browser. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_DYNAMIC_MENUS = YES + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_DYNAMIC_SECTIONS = NO + +# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries +# shown in the various tree structured indices initially; the user can expand +# and collapse entries dynamically later on. Doxygen will expand the tree to +# such a level that at most the specified number of entries are visible (unless +# a fully collapsed tree already exceeds this amount). So setting the number of +# entries 1 will produce a full collapsed tree by default. 0 is a special value +# representing an infinite number of entries and will result in a full expanded +# tree by default. +# Minimum value: 0, maximum value: 9999, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_INDEX_NUM_ENTRIES = 100 + +# If the GENERATE_DOCSET tag is set to YES, additional index files will be +# generated that can be used as input for Apple's Xcode 3 integrated development +# environment (see: +# https://developer.apple.com/xcode/), introduced with OSX 10.5 (Leopard). To +# create a documentation set, doxygen will generate a Makefile in the HTML +# output directory. Running make will produce the docset in that directory and +# running make install will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at +# startup. See https://developer.apple.com/library/archive/featuredarticles/Doxy +# genXcode/_index.html for more information. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_DOCSET = NO + +# This tag determines the name of the docset feed. A documentation feed provides +# an umbrella under which multiple documentation sets from a single provider +# (such as a company or product suite) can be grouped. +# The default value is: Doxygen generated docs. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# This tag specifies a string that should uniquely identify the documentation +# set bundle. This should be a reverse domain-name style string, e.g. +# com.mycompany.MyDocSet. Doxygen will append .docset to the name. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify +# the documentation publisher. This should be a reverse domain-name style +# string, e.g. com.mycompany.MyDocSet.documentation. +# The default value is: org.doxygen.Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_ID = org.doxygen.Publisher + +# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. +# The default value is: Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_NAME = Publisher + +# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three +# additional HTML index files: index.hhp, index.hhc, and index.hhk. The +# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop +# (see: +# https://www.microsoft.com/en-us/download/details.aspx?id=21138) on Windows. +# +# The HTML Help Workshop contains a compiler that can convert all HTML output +# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML +# files are now used as the Windows 98 help format, and will replace the old +# Windows help format (.hlp) on all Windows platforms in the future. Compressed +# HTML files also contain an index, a table of contents, and you can search for +# words in the documentation. The HTML workshop also contains a viewer for +# compressed HTML files. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_HTMLHELP = NO + +# The CHM_FILE tag can be used to specify the file name of the resulting .chm +# file. You can add a path in front of the file if the result should not be +# written to the html output directory. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_FILE = + +# The HHC_LOCATION tag can be used to specify the location (absolute path +# including file name) of the HTML help compiler (hhc.exe). If non-empty, +# doxygen will try to run the HTML help compiler on the generated index.hhp. +# The file has to be specified with full path. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +HHC_LOCATION = + +# The GENERATE_CHI flag controls if a separate .chi index file is generated +# (YES) or that it should be included in the main .chm file (NO). +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +GENERATE_CHI = NO + +# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc) +# and project file content. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_INDEX_ENCODING = + +# The BINARY_TOC flag controls whether a binary table of contents is generated +# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it +# enables the Previous and Next buttons. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members to +# the table of contents of the HTML help documentation and to the tree view. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +TOC_EXPAND = NO + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that +# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help +# (.qch) of the generated HTML documentation. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify +# the file name of the resulting .qch file. The path specified is relative to +# the HTML output folder. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help +# Project output. For more information please see Qt Help Project / Namespace +# (see: +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace). +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt +# Help Project output. For more information please see Qt Help Project / Virtual +# Folders (see: +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual-folders). +# The default value is: doc. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_VIRTUAL_FOLDER = doc + +# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom +# filter to add. For more information please see Qt Help Project / Custom +# Filters (see: +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see Qt Help Project / Custom +# Filters (see: +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's filter section matches. Qt Help Project / Filter Attributes (see: +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#filter-attributes). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_SECT_FILTER_ATTRS = + +# The QHG_LOCATION tag can be used to specify the location (absolute path +# including file name) of Qt's qhelpgenerator. If non-empty doxygen will try to +# run qhelpgenerator on the generated .qhp file. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be +# generated, together with the HTML files, they form an Eclipse help plugin. To +# install this plugin and make it available under the help contents menu in +# Eclipse, the contents of the directory containing the HTML and XML files needs +# to be copied into the plugins directory of eclipse. The name of the directory +# within the plugins directory should be the same as the ECLIPSE_DOC_ID value. +# After copying Eclipse needs to be restarted before the help appears. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the Eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have this +# name. Each documentation set should have its own identifier. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# If you want full control over the layout of the generated HTML pages it might +# be necessary to disable the index and replace it with your own. The +# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top +# of each HTML page. A value of NO enables the index and the value YES disables +# it. Since the tabs in the index contain the same information as the navigation +# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +DISABLE_INDEX = YES + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. If the tag +# value is set to YES, a side panel will be generated containing a tree-like +# index structure (just like the one that is generated for HTML Help). For this +# to work a browser that supports JavaScript, DHTML, CSS and frames is required +# (i.e. any modern browser). Windows users are probably better off using the +# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can +# further fine-tune the look of the index. As an example, the default style +# sheet generated by doxygen has an example that shows how to put an image at +# the root of the tree instead of the PROJECT_NAME. Since the tree basically has +# the same information as the tab index, you could consider setting +# DISABLE_INDEX to YES when enabling this option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_TREEVIEW = YES + +# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that +# doxygen will group on one line in the generated HTML documentation. +# +# Note that a value of 0 will completely suppress the enum values from appearing +# in the overview section. +# Minimum value: 0, maximum value: 20, default value: 4. +# This tag requires that the tag GENERATE_HTML is set to YES. + +ENUM_VALUES_PER_LINE = 4 + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used +# to set the initial width (in pixels) of the frame in which the tree is shown. +# Minimum value: 0, maximum value: 1500, default value: 250. +# This tag requires that the tag GENERATE_HTML is set to YES. + +TREEVIEW_WIDTH = 250 + +# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to +# external symbols imported via tag files in a separate window. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +EXT_LINKS_IN_WINDOW = NO + +# If the HTML_FORMULA_FORMAT option is set to svg, doxygen will use the pdf2svg +# tool (see https://github.com/dawbarton/pdf2svg) or inkscape (see +# https://inkscape.org) to generate formulas as SVG images instead of PNGs for +# the HTML output. These images will generally look nicer at scaled resolutions. +# Possible values are: png (the default) and svg (looks nicer but requires the +# pdf2svg or inkscape tool). +# The default value is: png. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FORMULA_FORMAT = png + +# Use this tag to change the font size of LaTeX formulas included as images in +# the HTML documentation. When you change the font size after a successful +# doxygen run you need to manually remove any form_*.png images from the HTML +# output directory to force them to be regenerated. +# Minimum value: 8, maximum value: 50, default value: 10. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_FONTSIZE = 10 + +# Use the FORMULA_TRANSPARENT tag to determine whether or not the images +# generated for formulas are transparent PNGs. Transparent PNGs are not +# supported properly for IE 6.0, but are supported on all modern browsers. +# +# Note that when changing this option you need to delete any form_*.png files in +# the HTML output directory before the changes have effect. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_TRANSPARENT = YES + +# The FORMULA_MACROFILE can contain LaTeX \newcommand and \renewcommand commands +# to create new LaTeX commands to be used in formulas as building blocks. See +# the section "Including formulas" for details. + +FORMULA_MACROFILE = + +# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see +# https://www.mathjax.org) which uses client side JavaScript for the rendering +# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX +# installed or if you want to formulas look prettier in the HTML output. When +# enabled you may also need to install MathJax separately and configure the path +# to it using the MATHJAX_RELPATH option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +USE_MATHJAX = NO + +# When MathJax is enabled you can set the default output format to be used for +# the MathJax output. See the MathJax site (see: +# http://docs.mathjax.org/en/v2.7-latest/output.html) for more details. +# Possible values are: HTML-CSS (which is slower, but has the best +# compatibility), NativeMML (i.e. MathML) and SVG. +# The default value is: HTML-CSS. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_FORMAT = HTML-CSS + +# When MathJax is enabled you need to specify the location relative to the HTML +# output directory using the MATHJAX_RELPATH option. The destination directory +# should contain the MathJax.js script. For instance, if the mathjax directory +# is located at the same level as the HTML output directory, then +# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax +# Content Delivery Network so you can quickly see the result without installing +# MathJax. However, it is strongly recommended to install a local copy of +# MathJax from https://www.mathjax.org before deployment. +# The default value is: https://cdn.jsdelivr.net/npm/mathjax@2. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_RELPATH = https://cdn.jsdelivr.net/npm/mathjax@2 + +# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax +# extension names that should be enabled during MathJax rendering. For example +# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_EXTENSIONS = + +# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces +# of code that will be used on startup of the MathJax code. See the MathJax site +# (see: +# http://docs.mathjax.org/en/v2.7-latest/output.html) for more details. For an +# example see the documentation. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_CODEFILE = + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box for +# the HTML output. The underlying search engine uses javascript and DHTML and +# should work on any modern browser. Note that when using HTML help +# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) +# there is already a search function so this one should typically be disabled. +# For large projects the javascript based search engine can be slow, then +# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to +# search using the keyboard; to jump to the search box use + S +# (what the is depends on the OS and browser, but it is typically +# , /