mirror of
https://github.com/overte-org/overte.git
synced 2025-04-23 05:14:37 +02:00
Merge branch 'master' into domainlist-recv-logging
This commit is contained in:
commit
8a280e71e1
225 changed files with 15020 additions and 1576 deletions
BUILD.mdBUILD_ANDROID.mdBUILD_LINUX.mdBUILD_OSX.mdBUILD_QUEST.mdBUILD_WIN.mdCMakeLists.txt
assignment-client/src/avatars
cmake
macros
ports/bullet3
debian
domain-server/src
DomainGatekeeper.cppDomainGatekeeper.hDomainServer.cppDomainServer.hDomainServerNodeData.hNodeConnectionData.cppNodeConnectionData.h
hifi_vcpkg.pyinterface
CMakeLists.txt
resources
images/Default-Sky-9-cubemap
Default-Sky-9-cubemap-ambient.jpgDefault-Sky-9-cubemap-ambient.ktxDefault-Sky-9-cubemap-ambient.texmeta.jsonDefault-Sky-9-cubemap-ambient_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT.ktxDefault-Sky-9-cubemap-ambient_COMPRESSED_SRGB8_ETC2.ktxDefault-Sky-9-cubemap.ktxDefault-Sky-9-cubemap.texmeta.jsonDefault-Sky-9-cubemap_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT.ktxDefault-Sky-9-cubemap_COMPRESSED_SRGB8_ETC2.ktx
qml/hifi/simplifiedUI
avatarApp
settingsApp
simplifiedConstants
simplifiedControls
topBar
src
Application.cppApplication.hMenu.cppMenu.h
avatar
commerce
main.cppoctree
scripting
Audio.cppAudio.hPlatformInfoScriptingInterface.cppPlatformInfoScriptingInterface.hRenderScriptingInterface.cppRenderScriptingInterface.hSelectionScriptingInterface.cppSelectionScriptingInterface.hSettingsScriptingInterface.hWindowScriptingInterface.h
ui
libraries
audio-client/src
audio/src
avatars-renderer/src/avatars-renderer
avatars/src
display-plugins/src/display-plugins
entities-renderer/src
entities/src
gpu-gl/src/gpu/gl45
gpu/src/gpu
graphics/src/graphics
image/src/image
ktx/src
model-baker/src/model-baker
47
BUILD.md
47
BUILD.md
|
@ -6,26 +6,25 @@
|
|||
* [BUILD_ANDROID.md](BUILD_ANDROID.md) - additional instructions for Android
|
||||
|
||||
### Dependencies
|
||||
|
||||
- [git](https://git-scm.com/downloads): >= 1.6
|
||||
- [cmake](https://cmake.org/download/): 3.9
|
||||
- [Qt](https://www.qt.io/download-open-source): 5.10.1
|
||||
- [Python](https://www.python.org/downloads/): 3.6 or higher
|
||||
|
||||
### 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 (Win32) / 0.5 (Mac)
|
||||
- [OpenVR](https://github.com/ValveSoftware/openvr): 1.0.6 (Win32 only)
|
||||
- [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/highfidelity/vcpkg):
|
||||
- [VHACD](https://github.com/virneo/v-hacd)
|
||||
- [zlib](http://www.zlib.net/): 1.28 (Win32 only)
|
||||
- [nvtt](https://github.com/highfidelity/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 (Win32) / 0.5 (Mac)
|
||||
- [OpenVR](https://github.com/ValveSoftware/openvr): 1.0.6 (Win32 only)
|
||||
- [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/highfidelity/vcpkg):
|
||||
- [VHACD](https://github.com/virneo/v-hacd)
|
||||
- [zlib](http://www.zlib.net/): 1.28 (Win32 only)
|
||||
- [nvtt](https://github.com/highfidelity/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.
|
||||
|
||||
|
@ -36,16 +35,14 @@ These are not placed in your normal build tree when doing an out of source build
|
|||
Hifi uses CMake to generate build files and project files for your platform.
|
||||
|
||||
#### Qt
|
||||
CMake will download Qt 5.12.3 using vcpkg.
|
||||
|
||||
In order for CMake to find the Qt5 find modules, you will need to set a QT_CMAKE_PREFIX_PATH environment variable pointing to your Qt installation.
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
export QT_CMAKE_PREFIX_PATH=/usr/local/Qt5.10.1/5.10.1/gcc_64/lib/cmake
|
||||
export QT_CMAKE_PREFIX_PATH=/usr/local/qt/5.10.1/clang_64/lib/cmake/
|
||||
export QT_CMAKE_PREFIX_PATH=/usr/local/Cellar/qt5/5.10.1/lib/cmake
|
||||
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
|
||||
|
||||
#### Vcpkg
|
||||
|
@ -68,15 +65,15 @@ Create a build directory in the root of your checkout and then run the CMake bui
|
|||
cd build
|
||||
cmake ..
|
||||
|
||||
If cmake gives you the same error message repeatedly after the build fails (e.g. you had a typo in the QT_CMAKE_PREFIX_PATH that you fixed but the `.cmake` files still cannot be found), try removing `CMakeCache.txt`.
|
||||
If cmake gives you the same error message repeatedly after the build fails, try removing `CMakeCache.txt`.
|
||||
|
||||
#### 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 during build file generation:
|
||||
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.10.1/lib/cmake
|
||||
cmake .. -DQT_CMAKE_PREFIX_PATH=/usr/local/qt/5.12.3/lib/cmake
|
||||
|
||||
#### Finding Dependencies
|
||||
|
||||
|
|
108
BUILD_ANDROID.md
108
BUILD_ANDROID.md
|
@ -1,64 +1,118 @@
|
|||
Please read the [general build guide](BUILD.md) for information on building other platform. Only Android specific instructions are found in this file.
|
||||
Please read the [general build guide](BUILD.md) for information on building other platforms. Only Android specific instructions are found in this file. **Note that these instructions apply to building for Oculus Quest.**
|
||||
|
||||
# Dependencies
|
||||
|
||||
Building is currently supported on OSX, Windows and Linux platforms, but developers intending to do work on the library dependencies are strongly urged to use 64 bit Linux as a build platform
|
||||
Building is currently supported on Windows, OSX and Linux, but developers intending to do work on the library dependencies are strongly urged to use 64 bit Linux as a build platform.
|
||||
|
||||
You will need the following tools to build Android targets.
|
||||
### OS specific dependencies
|
||||
|
||||
* [Android Studio](https://developer.android.com/studio/index.html)
|
||||
Please install the dependencies for your OS using the [Windows](BUILD_WIN.md), [OSX](BUILD_OSX.md) or [Linux](BUILD_LINUX.md) build instructions before attempting to build for Android.
|
||||
|
||||
### Android Studio
|
||||
|
||||
Download the Android Studio installer and run it. Once installed, at the welcome screen, click configure in the lower right corner and select SDK manager
|
||||
Download the [Android Studio](https://developer.android.com/studio/index.html) installer and run it. Once installed, at the welcome screen, click _Configure_ in the lower right corner and select _SDK Manager_.
|
||||
|
||||
From the SDK Platforms tab, select API levels 24 and 26.
|
||||
From the _SDK Platforms_ tab, select API levels 26 and 28.
|
||||
|
||||
From the SDK Tools tab select the following
|
||||
From the _SDK Tools_ tab, select the following
|
||||
|
||||
* Android SDK Build-Tools
|
||||
* GPU Debugging Tools
|
||||
* CMake (even if you have a separate CMake installation)
|
||||
* LLDB
|
||||
* Android SDK Platform-Tools
|
||||
* Android SDK Tools
|
||||
* NDK (even if you have the NDK installed separately)
|
||||
|
||||
Make sure the NDK installed version is 18 (or higher)
|
||||
Still in the _SDK Tools_ tab, click _Show Package Details_. Select CMake 3.6.4. Do this even if you have a separate CMake installation.
|
||||
|
||||
# Environment
|
||||
Also, make sure the NDK installed version is 18 (or higher).
|
||||
|
||||
Setting up the environment for android builds requires some additional steps
|
||||
# Environment
|
||||
|
||||
#### Set up machine specific Gradle properties
|
||||
### Create a keystore in Android Studio
|
||||
Follow the directions [here](https://developer.android.com/studio/publish/app-signing#generate-key) to create a keystore file. You can save it anywhere (preferably not in the `hifi` folder).
|
||||
|
||||
Create a `gradle.properties` file in $HOME/.gradle. Edit the file to contain the following
|
||||
### Set up machine specific Gradle properties
|
||||
|
||||
Create a `gradle.properties` file in the `.gradle` folder (`$HOME/.gradle` on Unix, `Users/<yourname>/.gradle` on Windows). Edit the file to contain the following
|
||||
|
||||
HIFI_ANDROID_PRECOMPILED=<your_home_directory>/Android/hifi_externals
|
||||
HIFI_ANDROID_KEYSTORE=<key_store_directory>/<keystore_name>.jks
|
||||
HIFI_ANDROID_KEYSTORE_PASSWORD=<password>
|
||||
HIFI_ANDROID_KEY_ALIAS=<key_alias>
|
||||
HIFI_ANDROID_KEY_PASSWORD=<key_passwords>
|
||||
|
||||
Note, do not use `$HOME` for the path. It must be a fully qualified path name.
|
||||
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.
|
||||
|
||||
### Setup the repository
|
||||
#### If you are building for an Android phone
|
||||
|
||||
Clone the repository
|
||||
Add these lines to `gradle.properties`
|
||||
|
||||
`git clone https://github.com/highfidelity/hifi.git`
|
||||
SUPPRESS_QUEST_INTERFACE
|
||||
SUPPRESS_QUEST_FRAME_PLAYER
|
||||
|
||||
Enter the repository `android` directory
|
||||
#### If you are building for an Oculus Quest
|
||||
|
||||
`cd hifi/android`
|
||||
Add these lines to `gradle.properties`
|
||||
|
||||
Execute two gradle pre-build steps. This steps should only need to be done once, unless you're working on the Android dependencies
|
||||
SUPPRESS_INTERFACE
|
||||
SUPPRESS_FRAME_PLAYER
|
||||
|
||||
`./gradlew extractDependencies`
|
||||
The above code to suppress modules is not necessary, but will speed up the build process.
|
||||
|
||||
`./gradlew setupDependencies`
|
||||
### Clone the repository
|
||||
|
||||
`git clone https://github.com/highfidelity/hifi.git `
|
||||
|
||||
# Building & Running
|
||||
|
||||
* Open Android Studio
|
||||
* Choose _Open Existing Android Studio Project_
|
||||
* Navigate to the `hifi` repository and choose the `android` folder and select _OK_
|
||||
* From the _Build_ menu select _Make Project_
|
||||
* Once the build completes, from the _Run_ menu select _Run App_
|
||||
### Building Modules
|
||||
|
||||
* Open Android Studio
|
||||
* Choose _Open an existing Android Studio project_
|
||||
* Navigate to the `hifi` repository and choose the `android` folder and select _OK_
|
||||
* Wait for Gradle to sync (this should take around 20 minutes the first time)
|
||||
* From the _Build_ menu select _Make Project_
|
||||
|
||||
### Running a Module
|
||||
|
||||
* In the toolbar at the top of Android Studio, next to the green hammer icon, you should see a dropdown menu.
|
||||
* You may already see a configuration for the module you are trying to build. If so, select it.
|
||||
* Otherwise, select _Edit Configurations_.
|
||||
|
||||
Your configuration should be as follows
|
||||
|
||||
* Type: Android App
|
||||
* Module: <your module> (you probably want `interface` or `questInterface`)
|
||||
|
||||
For the interface modules, you also need to select the activity to launch.
|
||||
|
||||
#### For the Android phone interface
|
||||
|
||||
* From the _Launch_ drop down menu, select _Specified Activity_
|
||||
* In the _Activity_ field directly below, put `io.highfidelity.hifiinterface.PermissionChecker`
|
||||
|
||||
#### For the Oculus Quest interface
|
||||
|
||||
* From the _Launch_ drop down menu, select _Specified Activity_
|
||||
* In the _Activity_ field directly below, put `io.highfidelity.questInterface.PermissionsChecker`
|
||||
|
||||
Note the 's' in Permission**s**Checker for the Quest.
|
||||
|
||||
Now you are able to run your module! Click the green play button in the top toolbar of Android Studio
|
||||
r
|
||||
# Troubleshooting
|
||||
|
||||
To view a more complete debug log,
|
||||
|
||||
* Click the icon with the two overlapping squares in the upper left corner of the tab where the sync is running (hover text says _Toggle view_)
|
||||
* To change verbosity, click _File > Settings_. Under _Build, Execution, Deployment > Compiler_ you can add command-line flags, as per Gradle documentation
|
||||
|
||||
Some things you can try if you want to do a clean build
|
||||
|
||||
* Delete the `build` and `.externalNativeBuild` folders from the folder for each module you're building (for example, `hifi/android/apps/interface`)
|
||||
* If you have set your `HIFI_VCPKG_ROOT` environment variable, delete the contents of that directory; otherwise, delete `AppData/Local/Temp/hifi`
|
||||
* In Android Studio, click _File > Invalidate Caches / Restart_ and select _Invalidate and Restart_
|
||||
|
||||
If you see lots of "couldn't acquire lock" errors,
|
||||
* Open Task Manager and close any running Clang / Gradle processes
|
138
BUILD_LINUX.md
138
BUILD_LINUX.md
|
@ -2,56 +2,72 @@
|
|||
|
||||
Please read the [general build guide](BUILD.md) for information on dependencies required for all platforms. Only Linux specific instructions are found in this file.
|
||||
|
||||
## Qt5 Dependencies
|
||||
|
||||
Should you choose not to install Qt5 via a package manager that handles dependencies for you, you may be missing some Qt5 dependencies. On Ubuntu, for example, the following additional packages are required:
|
||||
|
||||
libasound2 libxmu-dev libxi-dev freeglut3-dev libasound2-dev libjack0 libjack-dev libxrandr-dev libudev-dev libssl-dev zlib1g-dev
|
||||
|
||||
## Ubuntu 16.04/18.04 specific build guide
|
||||
|
||||
### Ubuntu 18.04 only
|
||||
### Ubuntu 16.04 only
|
||||
Add the following line to *.bash_profile*
|
||||
`export QT_QPA_FONTDIR=/usr/share/fonts/truetype/dejavu/`
|
||||
### Ubuntu 18.04 server only
|
||||
Add the universe repository:
|
||||
_(This is not enabled by default on the server edition)_
|
||||
```bash
|
||||
sudo add-apt-repository universe
|
||||
sudo apt-get update
|
||||
```
|
||||
|
||||
### Prepare environment
|
||||
Install Qt 5.10.1:
|
||||
#### Install build tools:
|
||||
1. First update the repositiories:
|
||||
```bash
|
||||
wget http://debian.highfidelity.com/pool/h/hi/hifiqt5.10.1_5.10.1_amd64.deb
|
||||
sudo dpkg -i hifiqt5.10.1_5.10.1_amd64.deb
|
||||
sudo apt-get update -y
|
||||
sudo apt-get upgrade -y
|
||||
```
|
||||
|
||||
Install build dependencies:
|
||||
1. git
|
||||
```bash
|
||||
sudo apt-get install libasound2 libxmu-dev libxi-dev freeglut3-dev libasound2-dev libjack0 libjack-dev libxrandr-dev libudev-dev libssl-dev zlib1g-dev
|
||||
sudo apt-get install git -y
|
||||
```
|
||||
|
||||
To compile interface in a server you must install:
|
||||
Verify by git --version
|
||||
1. g++
|
||||
```bash
|
||||
sudo apt-get install g++ -y
|
||||
```
|
||||
Verify by g++ --version
|
||||
1. *Ubuntu 18.04* cmake
|
||||
```bash
|
||||
sudo apt-get install cmake -y
|
||||
```
|
||||
Verify by git --version
|
||||
1. *Ubuntu 16.04* cmake
|
||||
```bash
|
||||
wget https://cmake.org/files/v3.14/cmake-3.14.2-Linux-x86_64.sh
|
||||
sudo sh cmake-3.14.2-Linux-x86_64.sh --prefix=/usr/local --exclude-subdir
|
||||
```
|
||||
#### Install build dependencies:
|
||||
1. OpenSSL
|
||||
```bash
|
||||
sudo apt-get install libssl-dev
|
||||
```
|
||||
Verify with `openssl version`
|
||||
1. OpenGL
|
||||
Verify (first install mesa-utils - `sudo apt install mesa-utils -y`) by `glxinfo | grep "OpenGL version"`
|
||||
```bash
|
||||
sudo apt-get install libgl1-mesa-dev -y
|
||||
sudo ln -s /usr/lib/x86_64-linux-gnu/libGL.so.346.35 /usr/lib/x86_64-linux-gnu/libGL.so.1.2.0
|
||||
```
|
||||
#### To compile interface in a server you must install:
|
||||
```bash
|
||||
sudo apt-get -y install libpulse0 libnss3 libnspr4 libfontconfig1 libxcursor1 libxcomposite1 libxtst6 libxslt1.1
|
||||
```
|
||||
|
||||
Install build tools:
|
||||
1. Misc dependencies
|
||||
```bash
|
||||
# For Ubuntu 18.04
|
||||
sudo apt-get install cmake
|
||||
sudo apt-get install libasound2 libxmu-dev libxi-dev freeglut3-dev libasound2-dev libjack0 libjack-dev libxrandr-dev libudev-dev libssl-dev zlib1g-dev
|
||||
```
|
||||
1. To compile interface in a server you must install:
|
||||
```bash
|
||||
# For Ubuntu 16.04
|
||||
wget https://cmake.org/files/v3.9/cmake-3.9.5-Linux-x86_64.sh
|
||||
sudo sh cmake-3.9.5-Linux-x86_64.sh --prefix=/usr/local --exclude-subdir
|
||||
sudo apt-get -y install libpulse0 libnss3 libnspr4 libfontconfig1 libxcursor1 libxcomposite1 libxtst6 libxslt1.1
|
||||
```
|
||||
|
||||
Install Python 3:
|
||||
1. Install Python 3:
|
||||
```bash
|
||||
sudo apt-get install python3.6
|
||||
```
|
||||
|
||||
Install node, required to build the jsdoc documentation
|
||||
1. Install node, required to build the jsdoc documentation
|
||||
```bash
|
||||
sudo apt-get install nodejs
|
||||
```
|
||||
|
@ -84,9 +100,11 @@ cd hifi/build
|
|||
|
||||
Prepare makefiles:
|
||||
```bash
|
||||
cmake -DQT_CMAKE_PREFIX_PATH=/usr/local/Qt5.10.1/5.10.1/gcc_64/lib/cmake ..
|
||||
cmake ..
|
||||
```
|
||||
|
||||
* If cmake fails with a vcpkg error - delete /tmp/hifi/vcpkg.
|
||||
|
||||
Start compilation of the server and get a cup of coffee:
|
||||
```bash
|
||||
make domain-server assignment-client
|
||||
|
@ -128,46 +146,34 @@ Go to localhost in the running interface.
|
|||
|
||||
In Ubuntu 18.04 there is a problem related with NVidia driver library version.
|
||||
|
||||
It can be workarounded following these steps:
|
||||
It can be worked around following these steps:
|
||||
|
||||
Uninstall incompatible nvtt libraries:
|
||||
```bash
|
||||
sudo apt-get remove libnvtt2 libnvtt-dev
|
||||
```
|
||||
1. Uninstall incompatible nvtt libraries:
|
||||
`sudo apt-get remove libnvtt2 libnvtt-dev`
|
||||
|
||||
Install libssl1.0-dev:
|
||||
```bash
|
||||
sudo apt-get -y install libssl1.0-dev
|
||||
```
|
||||
1. Install libssl1.0-dev:
|
||||
`sudo apt-get -y install libssl1.0-dev`
|
||||
|
||||
Clone castano nvidia-texture-tools:
|
||||
```
|
||||
git clone https://github.com/castano/nvidia-texture-tools
|
||||
cd nvidia-texture-tools/
|
||||
```
|
||||
1. Clone castano nvidia-texture-tools:
|
||||
`git clone https://github.com/castano/nvidia-texture-tools`
|
||||
`cd nvidia-texture-tools/`
|
||||
|
||||
Make these changes in repo:
|
||||
* In file **VERSION** set `2.2.1`
|
||||
* In file **configure**:
|
||||
* set `build="release"`
|
||||
* set `-DNVTT_SHARED=1`
|
||||
1. Make these changes in repo:
|
||||
* In file **VERSION** set `2.2.1`
|
||||
* In file **configure**:
|
||||
* set `build="release"`
|
||||
* set `-DNVTT_SHARED=1`
|
||||
|
||||
Configure, build and install:
|
||||
```
|
||||
./configure
|
||||
make
|
||||
sudo make install
|
||||
```
|
||||
1. Configure, build and install:
|
||||
`./configure`
|
||||
`make`
|
||||
`sudo make install`
|
||||
|
||||
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.. 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`
|
||||
|
||||
After running this steps you can run interface:
|
||||
```
|
||||
interface/interface
|
||||
```
|
||||
1. After running this steps you can run interface:
|
||||
`interface/interface`
|
||||
|
|
17
BUILD_OSX.md
17
BUILD_OSX.md
|
@ -4,30 +4,21 @@ Please read the [general build guide](BUILD.md) for information on dependencies
|
|||
|
||||
[Homebrew](https://brew.sh/) is an excellent package manager for macOS. It makes install of some High Fidelity dependencies very simple.
|
||||
|
||||
brew install cmake openssl qt
|
||||
brew install cmake openssl
|
||||
|
||||
### 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.
|
||||
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.
|
||||
|
||||
### 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:
|
||||
|
||||
export OPENSSL_ROOT_DIR=/usr/local/Cellar/openssl/1.0.2l
|
||||
|
||||
Note that this uses the version from the homebrew formula at the time of this writing, and the version in the path will likely change.
|
||||
|
||||
### Qt
|
||||
|
||||
Assuming you've installed Qt using the homebrew instructions above, you'll need to set QT_CMAKE_PREFIX_PATH so CMake can find your installations.
|
||||
For Qt installed via homebrew, set QT_CMAKE_PREFIX_PATH:
|
||||
|
||||
export QT_CMAKE_PREFIX_PATH=/usr/local/Cellar/qt/5.10.1/lib/cmake
|
||||
|
||||
Note that this uses the version from the homebrew formula at the time of this writing, and the version in the path will likely change.
|
||||
|
||||
### Xcode
|
||||
|
||||
If Xcode is your editor of choice, you can ask CMake to generate Xcode project files instead of Unix Makefiles.
|
||||
|
|
|
@ -1,65 +0,0 @@
|
|||
Please read the [general build guide](BUILD.md) for information on building other platform. Only Quest specific instructions are found in this file.
|
||||
|
||||
# Dependencies
|
||||
|
||||
Building is currently supported on OSX, Windows and Linux platforms, but developers intending to do work on the library dependencies are strongly urged to use 64 bit Linux as a build platform
|
||||
|
||||
You will need the following tools to build Android targets.
|
||||
|
||||
* [Android Studio](https://developer.android.com/studio/index.html)
|
||||
|
||||
### Android Studio
|
||||
|
||||
Download the Android Studio installer and run it. Once installed, at the welcome screen, click configure in the lower right corner and select SDK manager
|
||||
|
||||
From the SDK Platforms tab, select API levels 24 and 26.
|
||||
|
||||
From the SDK Tools tab select the following
|
||||
|
||||
* Android SDK Build-Tools
|
||||
* GPU Debugging Tools
|
||||
* CMake (even if you have a separate CMake installation)
|
||||
* LLDB
|
||||
* Android SDK Platform-Tools
|
||||
* Android SDK Tools
|
||||
* NDK (even if you have the NDK installed separately)
|
||||
|
||||
Make sure the NDK installed version is 18 (or higher)
|
||||
|
||||
# Environment
|
||||
|
||||
Setting up the environment for android builds requires some additional steps
|
||||
|
||||
#### Set up machine specific Gradle properties
|
||||
|
||||
Create a `gradle.properties` file in $HOME/.gradle. Edit the file to contain the following
|
||||
|
||||
HIFI_ANDROID_PRECOMPILED=<your_home_directory>/Android/hifi_externals
|
||||
HIFI_ANDROID_KEYSTORE=<key_store_directory>/<keystore_name>.jks
|
||||
HIFI_ANDROID_KEYSTORE_PASSWORD=<password>
|
||||
HIFI_ANDROID_KEY_ALIAS=<key_alias>
|
||||
HIFI_ANDROID_KEY_PASSWORD=<key_password>
|
||||
|
||||
Note, do not use `$HOME` for the path. It must be a fully qualified path name.
|
||||
|
||||
### Setup the repository
|
||||
|
||||
Clone the repository
|
||||
|
||||
`git clone https://github.com/highfidelity/hifi.git`
|
||||
|
||||
Enter the repository `android` directory
|
||||
|
||||
`cd hifi/android`
|
||||
|
||||
# Building & Running
|
||||
|
||||
* Open Android Studio
|
||||
* Choose _Open Existing Android Studio Project_
|
||||
* Navigate to the `hifi` repository and choose the `android` folder and select _OK_
|
||||
* Open Gradle.settings and comment out any projects not necessary
|
||||
* From _File_ menu select _Sync with File System_ to resync Gradle settings
|
||||
* From the _Build_ menu select _Make Project_
|
||||
* From
|
||||
* Once the build completes, from the _Run_ menu select _Run App_
|
||||
|
72
BUILD_WIN.md
72
BUILD_WIN.md
|
@ -1,17 +1,29 @@
|
|||
This is a stand-alone guide for creating your first High Fidelity build for Windows 64-bit.
|
||||
|
||||
This is a stand-alone guide for creating your first High Fidelity build for Windows 64-bit.
|
||||
## Building High Fidelity
|
||||
Note: We are now using Visual Studio 2017 and Qt 5.10.1. If you are upgrading from Visual Studio 2013 and Qt 5.6.2, do a clean uninstall of those versions before going through this guide.
|
||||
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: 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 2017 & Python
|
||||
### Step 1. Visual Studio & Python
|
||||
|
||||
If you don’t have Community or Professional edition of Visual Studio 2017, download [Visual Studio Community 2017](https://www.visualstudio.com/downloads/).
|
||||
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.
|
||||
|
||||
When selecting components, check "Desktop development with C++". Also on the right on the Summary toolbar, check "Windows 8.1 SDK and UCRT SDK" and "VC++ 2015.3 v140 toolset (x86,x64)". If you do not already have a python development environment installed, also check "Python Development" in this screen.
|
||||
When selecting components, check "Desktop development with C++". On the right on the Summary toolbar, select the following components.
|
||||
|
||||
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.
|
||||
#### 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,
|
||||
|
||||
* MSVC v141 - VS 2017 C++ x64/x86 build tools
|
||||
* MSVC v140 - VS 2015 C++ build tools (v14.00)
|
||||
|
||||
If you do not already have a Python development environment installed, also check "Python Development" in this screen.
|
||||
|
||||
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.
|
||||
|
||||
### Step 1a. Alternate Python
|
||||
|
||||
|
@ -22,28 +34,18 @@ If you do not wish to use the Python installation bundled with Visual Studio, yo
|
|||
Download and install the latest version of CMake 3.9.
|
||||
|
||||
Download the file named win64-x64 Installer from the [CMake Website](https://cmake.org/download/). You can access the installer on this [3.9 Version page](https://cmake.org/files/v3.9/). During installation, make sure to check "Add CMake to system PATH for all users" when prompted.
|
||||
|
||||
### Step 3. Installing Qt
|
||||
|
||||
Download and install the [Qt Open Source Online Installer](https://www.qt.io/download-open-source/?hsCtaTracking=f977210e-de67-475f-a32b-65cec207fd03%7Cd62710cd-e1db-46aa-8d4d-2f1c1ffdacea). While installing, you only need to have the following components checked under Qt 5.10.1: "msvc2017 64-bit", "Qt WebEngine", and "Qt Script (Deprecated)".
|
||||
|
||||
Note: Installing the Sources is optional but recommended if you have room for them (~2GB).
|
||||
|
||||
### Step 4. Setting Qt Environment Variable
|
||||
|
||||
Go to `Control Panel > System > Advanced System Settings > Environment Variables > New...` (or search “Environment Variables” in Start Search).
|
||||
* Set "Variable name": `QT_CMAKE_PREFIX_PATH`
|
||||
* Set "Variable value": `C:\Qt\5.10.1\msvc2017_64\lib\cmake`
|
||||
|
||||
### Step 5. Running CMake to Generate Build Files
|
||||
|
||||
Run Command Prompt from Start and run the following commands:
|
||||
```
|
||||
cd "%HIFI_DIR%"
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -G "Visual Studio 15 Win64"
|
||||
```
|
||||
Run Command Prompt from Start and run the following commands:
|
||||
`cd "%HIFI_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,
|
||||
Run `cmake .. -G "Visual Studio 16 2019" -A x64`.
|
||||
|
||||
Where `%HIFI_DIR%` is the directory for the highfidelity repository.
|
||||
|
||||
|
@ -73,11 +75,11 @@ Note: You can also run Interface by launching it from command line or File Explo
|
|||
|
||||
## Troubleshooting
|
||||
|
||||
For any problems after Step #7, first try this:
|
||||
* Delete your locally cloned copy of the highfidelity repository
|
||||
* Restart your computer
|
||||
* Redownload the [repository](https://github.com/highfidelity/hifi)
|
||||
* Restart directions from Step #7
|
||||
For any problems after Step #7, first try this:
|
||||
* Delete your locally cloned copy of the highfidelity repository
|
||||
* Restart your computer
|
||||
* Redownload the [repository](https://github.com/highfidelity/hifi)
|
||||
* Restart directions from Step #7
|
||||
|
||||
#### CMake gives you the same error message repeatedly after the build fails
|
||||
|
||||
|
@ -85,8 +87,4 @@ Remove `CMakeCache.txt` found in the `%HIFI_DIR%\build` directory.
|
|||
|
||||
#### CMake can't find OpenSSL
|
||||
|
||||
Remove `CMakeCache.txt` found in the `%HIFI_DIR%\build` directory. Verify that your VCPKG_ROOT environment variable is set and pointing to the correct location. Verify that the file `${VCPKG_ROOT}/installed/x64-windows/include/openssl/ssl.h` exists.
|
||||
|
||||
#### Qt is throwing an error
|
||||
|
||||
Make sure you have the correct version (5.10.1) installed and `QT_CMAKE_PREFIX_PATH` environment variable is set correctly.
|
||||
Remove `CMakeCache.txt` found in the `%HIFI_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.
|
||||
|
|
|
@ -17,14 +17,19 @@ if (APPLE)
|
|||
set(ENV{MACOSX_DEPLOYMENT_TARGET} 10.9)
|
||||
endif()
|
||||
|
||||
set(RELEASE_TYPE "$ENV{RELEASE_TYPE}")
|
||||
if ((NOT "${RELEASE_TYPE}" STREQUAL "PRODUCTION") AND (NOT "${RELEASE_TYPE}" STREQUAL "PR"))
|
||||
set(RELEASE_TYPE "DEV")
|
||||
endif()
|
||||
|
||||
if (HIFI_ANDROID)
|
||||
execute_process(
|
||||
COMMAND ${HIFI_PYTHON_EXEC} ${CMAKE_CURRENT_SOURCE_DIR}/prebuild.py --android ${HIFI_ANDROID_APP} --build-root ${CMAKE_BINARY_DIR}
|
||||
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}
|
||||
)
|
||||
else()
|
||||
execute_process(
|
||||
COMMAND ${HIFI_PYTHON_EXEC} ${CMAKE_CURRENT_SOURCE_DIR}/prebuild.py --build-root ${CMAKE_BINARY_DIR}
|
||||
COMMAND ${HIFI_PYTHON_EXEC} ${CMAKE_CURRENT_SOURCE_DIR}/prebuild.py --release-type ${RELEASE_TYPE} --build-root ${CMAKE_BINARY_DIR}
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
)
|
||||
# squelch the Policy CMP0074 warning without requiring an update to cmake 3.12.
|
||||
|
@ -36,8 +41,8 @@ endif()
|
|||
if(NOT EXISTS "${CMAKE_BINARY_DIR}/vcpkg.cmake")
|
||||
message(FATAL_ERROR "vcpkg configuration missing.")
|
||||
endif()
|
||||
|
||||
include("${CMAKE_BINARY_DIR}/vcpkg.cmake")
|
||||
|
||||
project(hifi)
|
||||
include("cmake/init.cmake")
|
||||
include("cmake/compiler.cmake")
|
||||
|
@ -93,9 +98,9 @@ if (ANDROID)
|
|||
set(PLATFORM_QT_COMPONENTS AndroidExtras WebView)
|
||||
add_definitions(-DHIFI_ANDROID_APP=\"${HIFI_ANDROID_APP}\")
|
||||
if (
|
||||
(${HIFI_ANDROID_APP} STREQUAL "questInterface") OR
|
||||
(${HIFI_ANDROID_APP} STREQUAL "questInterface") OR
|
||||
(${HIFI_ANDROID_APP} STREQUAL "questFramePlayer") OR
|
||||
(${HIFI_ANDROID_APP} STREQUAL "framePlayer")
|
||||
(${HIFI_ANDROID_APP} STREQUAL "framePlayer")
|
||||
)
|
||||
# We know the quest hardware has this extension, so we can force the use of instanced stereo
|
||||
add_definitions(-DHAVE_EXT_clip_cull_distance)
|
||||
|
@ -105,18 +110,18 @@ if (ANDROID)
|
|||
# We can also use our own foveated textures
|
||||
add_definitions(-DHAVE_QCOM_texture_foveated)
|
||||
|
||||
# if set, the application itself or some library it depends on MUST implement
|
||||
# if set, the application itself or some library it depends on MUST implement
|
||||
# `DisplayPluginList getDisplayPlugins()` and `InputPluginList getInputPlugins()`
|
||||
add_definitions(-DCUSTOM_INPUT_PLUGINS)
|
||||
add_definitions(-DCUSTOM_DISPLAY_PLUGINS)
|
||||
add_definitions(-DCUSTOM_INPUT_PLUGINS)
|
||||
add_definitions(-DCUSTOM_DISPLAY_PLUGINS)
|
||||
set(PLATFORM_PLUGIN_LIBRARIES oculusMobile oculusMobilePlugin)
|
||||
endif()
|
||||
|
||||
# Allow client code to use preprocessor macros to distinguish between quest and non-quest builds
|
||||
if (${HIFI_ANDROID_APP} STREQUAL "questInterface")
|
||||
add_definitions(-DANDROID_APP_QUEST_INTERFACE)
|
||||
add_definitions(-DANDROID_APP_QUEST_INTERFACE)
|
||||
elseif(${HIFI_ANDROID_APP} STREQUAL "interface")
|
||||
add_definitions(-DANDROID_APP_INTERFACE)
|
||||
add_definitions(-DANDROID_APP_INTERFACE)
|
||||
endif()
|
||||
else ()
|
||||
set(PLATFORM_QT_COMPONENTS WebEngine Xml)
|
||||
|
@ -194,6 +199,8 @@ GroupSources("scripts")
|
|||
GroupSources("unpublishedScripts")
|
||||
unset(JS_SRC)
|
||||
|
||||
set_packaging_parameters()
|
||||
|
||||
# Locate the required Qt build on the filesystem
|
||||
setup_qt()
|
||||
list(APPEND CMAKE_PREFIX_PATH "${QT_CMAKE_PREFIX_PATH}")
|
||||
|
@ -203,6 +210,12 @@ find_package( Threads )
|
|||
add_definitions(-DGLM_FORCE_RADIANS)
|
||||
add_definitions(-DGLM_ENABLE_EXPERIMENTAL)
|
||||
add_definitions(-DGLM_FORCE_CTOR_INIT)
|
||||
|
||||
if (WIN32)
|
||||
# Deal with fakakta Visual Studo 2017 bug
|
||||
add_definitions(-DQT_NO_FLOAT16_OPERATORS)
|
||||
endif()
|
||||
|
||||
if (HIFI_USE_OPTIMIZED_IK)
|
||||
MESSAGE(STATUS "SET THE USE IK DEFINITION ")
|
||||
add_definitions(-DHIFI_USE_OPTIMIZED_IK)
|
||||
|
@ -215,8 +228,6 @@ setup_externals_binary_dir()
|
|||
|
||||
option(USE_NSIGHT "Attempt to find the nSight libraries" 1)
|
||||
|
||||
set_packaging_parameters()
|
||||
|
||||
# FIXME hack to work on the proper Android toolchain
|
||||
if (ANDROID)
|
||||
add_subdirectory(android/apps/${HIFI_ANDROID_APP})
|
||||
|
@ -250,11 +261,11 @@ add_subdirectory(tools)
|
|||
|
||||
if (BUILD_TESTS)
|
||||
# Turn on testing so that add_test works
|
||||
# MUST be in the root cmake file for ctest to work
|
||||
# MUST be in the root cmake file for ctest to work
|
||||
include(CTest)
|
||||
enable_testing()
|
||||
add_subdirectory(tests)
|
||||
if (BUILD_MANUAL_TESTS)
|
||||
if (BUILD_MANUAL_TESTS)
|
||||
add_subdirectory(tests-manual)
|
||||
endif()
|
||||
endif()
|
||||
|
|
|
@ -204,7 +204,10 @@ void AvatarMixerClientData::processSetTraitsMessage(ReceivedMessage& message,
|
|||
if (traitType == AvatarTraits::SkeletonModelURL) {
|
||||
// special handling for skeleton model URL, since we need to make sure it is in the whitelist
|
||||
checkSkeletonURLAgainstWhitelist(slaveSharedData, sendingNode, packetTraitVersion);
|
||||
#ifdef AVATAR_POP_CHECK
|
||||
// Deferred for UX work. With no PoP check, no need to get the .fst.
|
||||
_avatar->fetchAvatarFST();
|
||||
#endif
|
||||
}
|
||||
|
||||
anyTraitsChanged = true;
|
||||
|
|
|
@ -138,7 +138,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 override;
|
||||
|
||||
virtual void setSkeletonModelURL(const QUrl& skeletonModelURL) override;
|
||||
Q_INVOKABLE virtual void setSkeletonModelURL(const QUrl& skeletonModelURL) override;
|
||||
|
||||
/**jsdoc
|
||||
* @comment Uses the base class's JSDoc.
|
||||
|
|
|
@ -10,28 +10,32 @@
|
|||
#
|
||||
|
||||
macro(fixup_interface)
|
||||
if (APPLE)
|
||||
if (APPLE)
|
||||
string(REPLACE " " "\\ " ESCAPED_BUNDLE_NAME ${INTERFACE_BUNDLE_NAME})
|
||||
string(REPLACE " " "\\ " ESCAPED_INSTALL_PATH ${INTERFACE_INSTALL_DIR})
|
||||
set(_INTERFACE_INSTALL_PATH "${ESCAPED_INSTALL_PATH}/${ESCAPED_BUNDLE_NAME}.app")
|
||||
|
||||
string(REPLACE " " "\\ " ESCAPED_BUNDLE_NAME ${INTERFACE_BUNDLE_NAME})
|
||||
string(REPLACE " " "\\ " ESCAPED_INSTALL_PATH ${INTERFACE_INSTALL_DIR})
|
||||
set(_INTERFACE_INSTALL_PATH "${ESCAPED_INSTALL_PATH}/${ESCAPED_BUNDLE_NAME}.app")
|
||||
find_program(MACDEPLOYQT_COMMAND macdeployqt PATHS "${QT_DIR}/bin" NO_DEFAULT_PATH)
|
||||
|
||||
find_program(MACDEPLOYQT_COMMAND macdeployqt PATHS "${QT_DIR}/bin" NO_DEFAULT_PATH)
|
||||
if (NOT MACDEPLOYQT_COMMAND AND (PRODUCTION_BUILD OR PR_BUILD))
|
||||
message(FATAL_ERROR "Could not find macdeployqt at ${QT_DIR}/bin.\
|
||||
It is required to produce an relocatable interface application.\
|
||||
Check that the variable QT_DIR points to your Qt installation.\
|
||||
")
|
||||
endif ()
|
||||
|
||||
if (NOT MACDEPLOYQT_COMMAND AND (PRODUCTION_BUILD OR PR_BUILD))
|
||||
message(FATAL_ERROR "Could not find macdeployqt at ${QT_DIR}/bin.\
|
||||
It is required to produce an relocatable interface application.\
|
||||
Check that the environment variable QT_DIR points to your Qt installation.\
|
||||
")
|
||||
if (RELEASE_TYPE STREQUAL "DEV")
|
||||
install(CODE "
|
||||
execute_process(COMMAND ${MACDEPLOYQT_COMMAND}\
|
||||
\${CMAKE_INSTALL_PREFIX}/${_INTERFACE_INSTALL_PATH}/\
|
||||
-verbose=2 -qmldir=${CMAKE_SOURCE_DIR}/interface/resources/qml/\
|
||||
)"
|
||||
COMPONENT ${CLIENT_COMPONENT}
|
||||
)
|
||||
else ()
|
||||
add_custom_command(TARGET ${TARGET_NAME} POST_BUILD
|
||||
COMMAND ${MACDEPLOYQT_COMMAND} "$<TARGET_FILE_DIR:${TARGET_NAME}>/../.." -verbose=2 -qmldir=${CMAKE_SOURCE_DIR}/interface/resources/qml/
|
||||
)
|
||||
endif()
|
||||
endif ()
|
||||
|
||||
install(CODE "
|
||||
execute_process(COMMAND ${MACDEPLOYQT_COMMAND}\
|
||||
\${CMAKE_INSTALL_PREFIX}/${_INTERFACE_INSTALL_PATH}/\
|
||||
-verbose=2 -qmldir=${CMAKE_SOURCE_DIR}/interface/resources/qml/\
|
||||
)"
|
||||
COMPONENT ${CLIENT_COMPONENT}
|
||||
)
|
||||
|
||||
endif ()
|
||||
endmacro()
|
||||
|
|
|
@ -10,27 +10,32 @@
|
|||
#
|
||||
|
||||
macro(fixup_nitpick)
|
||||
if (APPLE)
|
||||
string(REPLACE " " "\\ " ESCAPED_BUNDLE_NAME ${NITPICK_BUNDLE_NAME})
|
||||
string(REPLACE " " "\\ " ESCAPED_INSTALL_PATH ${NITPICK_INSTALL_DIR})
|
||||
set(_NITPICK_INSTALL_PATH "${ESCAPED_INSTALL_PATH}/${ESCAPED_BUNDLE_NAME}.app")
|
||||
if (APPLE)
|
||||
string(REPLACE " " "\\ " ESCAPED_BUNDLE_NAME ${NITPICK_BUNDLE_NAME})
|
||||
string(REPLACE " " "\\ " ESCAPED_INSTALL_PATH ${NITPICK_INSTALL_DIR})
|
||||
set(_NITPICK_INSTALL_PATH "${ESCAPED_INSTALL_PATH}/${ESCAPED_BUNDLE_NAME}.app")
|
||||
|
||||
find_program(MACDEPLOYQT_COMMAND macdeployqt PATHS "${QT_DIR}/bin" NO_DEFAULT_PATH)
|
||||
find_program(MACDEPLOYQT_COMMAND macdeployqt PATHS "${QT_DIR}/bin" NO_DEFAULT_PATH)
|
||||
|
||||
if (NOT MACDEPLOYQT_COMMAND AND (PRODUCTION_BUILD OR PR_BUILD))
|
||||
message(FATAL_ERROR "Could not find macdeployqt at ${QT_DIR}/bin.\
|
||||
It is required to produce a relocatable nitpick application.\
|
||||
Check that the environment variable QT_DIR points to your Qt installation.\
|
||||
")
|
||||
if (NOT MACDEPLOYQT_COMMAND AND (PRODUCTION_BUILD OR PR_BUILD))
|
||||
message(FATAL_ERROR "Could not find macdeployqt at ${QT_DIR}/bin.\
|
||||
It is required to produce a relocatable nitpick application.\
|
||||
Check that the variable QT_DIR points to your Qt installation.\
|
||||
")
|
||||
endif ()
|
||||
|
||||
if (RELEASE_TYPE STREQUAL "DEV")
|
||||
install(CODE "
|
||||
execute_process(COMMAND ${MACDEPLOYQT_COMMAND}\
|
||||
\${CMAKE_INSTALL_PREFIX}/${_NITPICK_INSTALL_PATH}/\
|
||||
-verbose=2 -qmldir=${CMAKE_SOURCE_DIR}/interface/resources/qml/\
|
||||
)"
|
||||
COMPONENT ${CLIENT_COMPONENT}
|
||||
)
|
||||
else ()
|
||||
add_custom_command(TARGET ${TARGET_NAME} POST_BUILD
|
||||
COMMAND ${MACDEPLOYQT_COMMAND} "$<TARGET_FILE_DIR:${TARGET_NAME}>/../.." -verbose=2 -qmldir=${CMAKE_SOURCE_DIR}/interface/resources/qml/
|
||||
)
|
||||
endif()
|
||||
endif ()
|
||||
|
||||
install(CODE "
|
||||
execute_process(COMMAND ${MACDEPLOYQT_COMMAND}\
|
||||
\${CMAKE_INSTALL_PREFIX}/${_NITPICK_INSTALL_PATH}/\
|
||||
-verbose=2 -qmldir=${CMAKE_SOURCE_DIR}/interface/resources/qml/\
|
||||
)"
|
||||
COMPONENT ${CLIENT_COMPONENT}
|
||||
)
|
||||
|
||||
endif ()
|
||||
endmacro()
|
||||
|
|
|
@ -39,7 +39,7 @@ macro(PACKAGE_LIBRARIES_FOR_DEPLOYMENT)
|
|||
add_custom_command(
|
||||
TARGET ${TARGET_NAME}
|
||||
POST_BUILD
|
||||
COMMAND CMD /C "SET PATH=%PATH%;${QT_DIR}/bin && ${WINDEPLOYQT_COMMAND}\
|
||||
COMMAND CMD /C "SET PATH=${QT_DIR}/bin;%PATH% && ${WINDEPLOYQT_COMMAND}\
|
||||
${EXTRA_DEPLOY_OPTIONS} $<$<OR:$<CONFIG:Release>,$<CONFIG:MinSizeRel>,$<CONFIG:RelWithDebInfo>>:--release>\
|
||||
--no-compiler-runtime --no-opengl-sw --no-angle -no-system-d3d-compiler \"$<TARGET_FILE:${TARGET_NAME}>\""
|
||||
)
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
#
|
||||
# Created by Bradley Austin Davis on 2017/09/02
|
||||
# Copyright 2013-2017 High Fidelity, Inc.
|
||||
#
|
||||
|
@ -6,67 +5,91 @@
|
|||
# See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
#
|
||||
|
||||
# Construct a default QT location from a root path, a version and an architecture
|
||||
|
||||
function(calculate_default_qt_dir _QT_VERSION _RESULT_NAME)
|
||||
if (ANDROID)
|
||||
set(QT_DEFAULT_ARCH "android_armv7")
|
||||
elseif(UWP)
|
||||
set(QT_DEFAULT_ARCH "winrt_x64_msvc2017")
|
||||
elseif(APPLE)
|
||||
set(QT_DEFAULT_ARCH "clang_64")
|
||||
elseif(WIN32)
|
||||
set(QT_DEFAULT_ARCH "msvc2017_64")
|
||||
else()
|
||||
set(QT_DEFAULT_ARCH "gcc_64")
|
||||
function(get_sub_directories result curdir)
|
||||
file(GLOB children RELATIVE ${curdir} ${curdir}/*)
|
||||
set(dirlist "")
|
||||
foreach(child ${children})
|
||||
if(IS_DIRECTORY ${curdir}/${child})
|
||||
LIST(APPEND dirlist ${child})
|
||||
endif()
|
||||
endforeach()
|
||||
set(${result} ${dirlist} PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
if (WIN32 OR (ANDROID AND ("${CMAKE_HOST_SYSTEM_NAME}" STREQUAL "Windows")))
|
||||
set(QT_DEFAULT_ROOT "c:/Qt")
|
||||
else()
|
||||
set(QT_DEFAULT_ROOT "$ENV{HOME}/Qt")
|
||||
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
|
||||
# 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")
|
||||
endif()
|
||||
if(NOT EXISTS "${_QT_CORE_DIR}")
|
||||
message(FATAL_ERROR "Could not find 'include/QtCore' in '${_QT_DIR}'")
|
||||
endif()
|
||||
set(subdirs "")
|
||||
get_sub_directories(subdirs ${_QT_CORE_DIR})
|
||||
|
||||
foreach(subdir ${subdirs})
|
||||
string(REGEX MATCH "5.[0-9]+.[0-9]+$" _QT_VERSION ${subdir})
|
||||
if (NOT "${_QT_VERSION}" STREQUAL "")
|
||||
# found it!
|
||||
set(${result} "${_QT_VERSION}" PARENT_SCOPE)
|
||||
break()
|
||||
endif()
|
||||
|
||||
set_from_env(QT_ROOT QT_ROOT ${QT_DEFAULT_ROOT})
|
||||
set_from_env(QT_ARCH QT_ARCH ${QT_DEFAULT_ARCH})
|
||||
|
||||
set(${_RESULT_NAME} "${QT_ROOT}/${_QT_VERSION}/${QT_ARCH}" PARENT_SCOPE)
|
||||
endforeach()
|
||||
endfunction()
|
||||
|
||||
# Sets the QT_CMAKE_PREFIX_PATH and QT_DIR variables
|
||||
# Also enables CMAKE_AUTOMOC and CMAKE_AUTORCC
|
||||
macro(setup_qt)
|
||||
set_from_env(QT_VERSION QT_VERSION "5.10.1")
|
||||
# if QT_CMAKE_PREFIX_PATH was not specified before hand,
|
||||
# try to use the environment variable
|
||||
if (NOT QT_CMAKE_PREFIX_PATH)
|
||||
set(QT_CMAKE_PREFIX_PATH "$ENV{QT_CMAKE_PREFIX_PATH}")
|
||||
# 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 VCPKG_QT_CMAKE_PREFIX_PATH)
|
||||
message(FATAL_ERROR "VCPKG_QT_CMAKE_PREFIX_PATH should have been set by hifi_vcpkg.py")
|
||||
endif()
|
||||
if (("QT_CMAKE_PREFIX_PATH" STREQUAL "") OR (NOT EXISTS "${QT_CMAKE_PREFIX_PATH}"))
|
||||
calculate_default_qt_dir(${QT_VERSION} QT_DIR)
|
||||
set(QT_CMAKE_PREFIX_PATH "${QT_DIR}/lib/cmake")
|
||||
if (NOT DEV_BUILD)
|
||||
if (APPLE)
|
||||
# HACK: manually set the QT_CMAKE_PREFIX_PATH so that hard-coded paths find new QT libs where we'll put them
|
||||
set(QT_CMAKE_PREFIX_PATH "/var/tmp/qt5-install/lib/cmake")
|
||||
elseif (UNIX AND DEFINED ENV{QT_CMAKE_PREFIX_PATH})
|
||||
# HACK: obey QT_CMAKE_PREFIX_PATH to allow UNIX to use older QT libs
|
||||
set(QT_CMAKE_PREFIX_PATH $ENV{QT_CMAKE_PREFIX_PATH})
|
||||
else()
|
||||
set(QT_CMAKE_PREFIX_PATH ${VCPKG_QT_CMAKE_PREFIX_PATH})
|
||||
endif()
|
||||
else()
|
||||
# figure out where the qt dir is
|
||||
get_filename_component(QT_DIR "${QT_CMAKE_PREFIX_PATH}/../../" ABSOLUTE)
|
||||
# DEV_BUILD
|
||||
if (DEFINED ENV{QT_CMAKE_PREFIX_PATH})
|
||||
set(QT_CMAKE_PREFIX_PATH $ENV{QT_CMAKE_PREFIX_PATH})
|
||||
else()
|
||||
set(QT_CMAKE_PREFIX_PATH ${VCPKG_QT_CMAKE_PREFIX_PATH})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (WIN32)
|
||||
# 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()
|
||||
|
||||
# This check doesn't work on Mac
|
||||
#if (NOT EXISTS "${QT_DIR}/include/QtCore/QtGlobal")
|
||||
# message(FATAL_ERROR "Unable to locate Qt includes in ${QT_DIR}")
|
||||
#endif()
|
||||
|
||||
if (NOT EXISTS "${QT_CMAKE_PREFIX_PATH}/Qt5Core/Qt5CoreConfig.cmake")
|
||||
message(FATAL_ERROR "Unable to locate Qt cmake config in ${QT_CMAKE_PREFIX_PATH}")
|
||||
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 "The Qt build in use is: \"${QT_DIR}\"")
|
||||
message(STATUS "Using Qt build in : '${QT_DIR}' with version ${QT_VERSION}")
|
||||
|
||||
# Instruct CMake to run moc automatically when needed.
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
|
|
|
@ -25,14 +25,13 @@ vcpkg_from_github(
|
|||
HEAD_REF master
|
||||
)
|
||||
|
||||
|
||||
vcpkg_configure_cmake(
|
||||
SOURCE_PATH ${SOURCE_PATH}
|
||||
OPTIONS
|
||||
-DCMAKE_WINDOWS_EXPORT_ALL_SYMBOLS=ON
|
||||
-DUSE_MSVC_RUNTIME_LIBRARY_DLL=ON
|
||||
-DUSE_GLUT=0
|
||||
-DUSE_DX11=0
|
||||
-DUSE_GLUT=0
|
||||
-DUSE_DX11=0
|
||||
-DBUILD_DEMOS=OFF
|
||||
-DBUILD_OPENGL3_DEMOS=OFF
|
||||
-DBUILD_BULLET3=OFF
|
||||
|
|
5
debian/changelog
vendored
Normal file
5
debian/changelog
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
hifi-interface (84-1) unstable; urgency=medium
|
||||
|
||||
* Initial release
|
||||
|
||||
-- Seth Alves <seth.alves@gmail.com> Tue, 14 May 2019 19:45:31 -0700
|
1
debian/compat
vendored
Normal file
1
debian/compat
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
11
|
15
debian/control
vendored
Normal file
15
debian/control
vendored
Normal file
|
@ -0,0 +1,15 @@
|
|||
Source: hifi-interface
|
||||
Section: comm
|
||||
Priority: optional
|
||||
Maintainer: Seth Alves <seth.alves@gmail.com>
|
||||
Build-Depends: debhelper (>= 11), cmake
|
||||
Standards-Version: 4.1.3
|
||||
Homepage: https://www.highfidelity.com/
|
||||
Vcs-Browser: https://github.com/highfidelity/hifi
|
||||
Vcs-Git: https://github.com/highfidelity/hifi.git
|
||||
|
||||
Package: hifi-interface
|
||||
Architecture: any
|
||||
Depends: ${shlibs:Depends}, ${misc:Depends}, libqt5quick5, libqt5quickcontrols2-5, libqt5quickwidgets5, qml-module-qtquick-controls, qml-module-qtquick-controls2, qml-module-qtquick-dialogs, libqt5webchannel5, qml-module-qtwebchannel, qml-module-qtwebengine, qml-module-qt-labs-folderlistmodel, qml-module-qt-labs-settings
|
||||
Description: High Fidelity allows creation and sharing of VR experiences.
|
||||
The High Fidelity metaverse provides built-in social features, including avatar interactions, spatialized audio and interactive physics. Additionally, you have the ability to import any 3D object into your virtual environment.
|
23
debian/copyright
vendored
Normal file
23
debian/copyright
vendored
Normal file
|
@ -0,0 +1,23 @@
|
|||
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
|
||||
Upstream-Name: hifi-interface
|
||||
Source: https://github.com/highfidelity/hifi
|
||||
|
||||
Files: *
|
||||
Copyright: 2013-2019, High Fidelity, Inc.
|
||||
License: Apache-2.0
|
||||
|
||||
License: Apache-2.0
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
.
|
||||
https://www.apache.org/licenses/LICENSE-2.0
|
||||
.
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
.
|
||||
On Debian systems, the complete text of the Apache version 2.0 license
|
||||
can be found in "/usr/share/common-licenses/Apache-2.0".
|
2
debian/hifi-interface-docs.docs
vendored
Normal file
2
debian/hifi-interface-docs.docs
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
README.Debian
|
||||
README.source
|
1
debian/hifi-interface.dirs
vendored
Normal file
1
debian/hifi-interface.dirs
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
opt/hifi/interface/
|
76
debian/patches/hifi_use_system_qt.diff
vendored
Normal file
76
debian/patches/hifi_use_system_qt.diff
vendored
Normal file
|
@ -0,0 +1,76 @@
|
|||
Index: hifi-interface-84/cmake/macros/SetupQt.cmake
|
||||
===================================================================
|
||||
--- hifi-interface-84.orig/cmake/macros/SetupQt.cmake
|
||||
+++ hifi-interface-84/cmake/macros/SetupQt.cmake
|
||||
@@ -18,19 +18,19 @@ function(calculate_default_qt_dir _QT_VE
|
||||
elseif(WIN32)
|
||||
set(QT_DEFAULT_ARCH "msvc2017_64")
|
||||
else()
|
||||
- set(QT_DEFAULT_ARCH "gcc_64")
|
||||
+ set(QT_DEFAULT_ARCH "x86_64-linux-gnu")
|
||||
endif()
|
||||
|
||||
if (WIN32 OR (ANDROID AND ("${CMAKE_HOST_SYSTEM_NAME}" STREQUAL "Windows")))
|
||||
set(QT_DEFAULT_ROOT "c:/Qt")
|
||||
else()
|
||||
- set(QT_DEFAULT_ROOT "$ENV{HOME}/Qt")
|
||||
+ set(QT_DEFAULT_ROOT "/usr/lib")
|
||||
endif()
|
||||
|
||||
set_from_env(QT_ROOT QT_ROOT ${QT_DEFAULT_ROOT})
|
||||
set_from_env(QT_ARCH QT_ARCH ${QT_DEFAULT_ARCH})
|
||||
|
||||
- set(${_RESULT_NAME} "${QT_ROOT}/${_QT_VERSION}/${QT_ARCH}" PARENT_SCOPE)
|
||||
+ set(${_RESULT_NAME} "${QT_ROOT}/${QT_ARCH}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
# Sets the QT_CMAKE_PREFIX_PATH and QT_DIR variables
|
||||
@@ -44,7 +44,7 @@ macro(setup_qt)
|
||||
endif()
|
||||
if (("QT_CMAKE_PREFIX_PATH" STREQUAL "") OR (NOT EXISTS "${QT_CMAKE_PREFIX_PATH}"))
|
||||
calculate_default_qt_dir(${QT_VERSION} QT_DIR)
|
||||
- set(QT_CMAKE_PREFIX_PATH "${QT_DIR}/lib/cmake")
|
||||
+ set(QT_CMAKE_PREFIX_PATH "${QT_DIR}/cmake")
|
||||
else()
|
||||
# figure out where the qt dir is
|
||||
get_filename_component(QT_DIR "${QT_CMAKE_PREFIX_PATH}/../../" ABSOLUTE)
|
||||
Index: hifi-interface-84/interface/CMakeLists.txt
|
||||
===================================================================
|
||||
--- hifi-interface-84.orig/interface/CMakeLists.txt
|
||||
+++ hifi-interface-84/interface/CMakeLists.txt
|
||||
@@ -35,7 +35,7 @@ else ()
|
||||
add_custom_command(
|
||||
OUTPUT ${RESOURCES_RCC}
|
||||
DEPENDS ${RESOURCES_QRC} ${GENERATE_QRC_DEPENDS}
|
||||
- COMMAND "${QT_DIR}/bin/rcc"
|
||||
+ COMMAND "rcc"
|
||||
ARGS ${RESOURCES_QRC} -binary -o ${RESOURCES_RCC}
|
||||
)
|
||||
endif()
|
||||
@@ -399,6 +399,13 @@ else()
|
||||
|
||||
optional_win_executable_signing()
|
||||
endif()
|
||||
+
|
||||
+ install(
|
||||
+ DIRECTORY "$<TARGET_FILE_DIR:${TARGET_NAME}>/"
|
||||
+ DESTINATION ${INTERFACE_INSTALL_DIR}
|
||||
+ COMPONENT ${CLIENT_COMPONENT}
|
||||
+ )
|
||||
+
|
||||
endif()
|
||||
|
||||
if (SCRIPTS_INSTALL_DIR)
|
||||
Index: hifi-interface-84/tools/nitpick/CMakeLists.txt
|
||||
===================================================================
|
||||
--- hifi-interface-84.orig/tools/nitpick/CMakeLists.txt
|
||||
+++ hifi-interface-84/tools/nitpick/CMakeLists.txt
|
||||
@@ -12,7 +12,7 @@ generate_qrc(OUTPUT ${RESOURCES_QRC} PAT
|
||||
add_custom_command(
|
||||
OUTPUT ${RESOURCES_RCC}
|
||||
DEPENDS ${RESOURCES_QRC} ${GENERATE_QRC_DEPENDS}
|
||||
- COMMAND "${QT_DIR}/bin/rcc"
|
||||
+ COMMAND "rcc"
|
||||
ARGS ${RESOURCES_QRC} -binary -o ${RESOURCES_RCC}
|
||||
)
|
||||
|
1
debian/patches/series
vendored
Normal file
1
debian/patches/series
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
hifi_use_system_qt.diff
|
24
debian/rules
vendored
Executable file
24
debian/rules
vendored
Executable file
|
@ -0,0 +1,24 @@
|
|||
#!/usr/bin/make -f
|
||||
|
||||
%:
|
||||
dh $@
|
||||
|
||||
|
||||
override_dh_auto_configure:
|
||||
mkdir obj-$(DEB_TARGET_MULTIARCH)
|
||||
(cd obj-$(DEB_TARGET_MULTIARCH) && cmake .. -DCMAKE_INSTALL_PREFIX=/opt/hifi -DCMAKE_VERBOSE_MAKEFILE=ON -DCMAKE_EXPORT_NO_PACKAGE_REGISTRY=ON "-GUnix Makefiles" -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCLIENT_ONLY=ON -DDOWNLOAD_SERVERLESS_CONTENT=ON -DCMAKE_CXX_COMPILER=/usr/lib/llvm-7/bin/clang\+\+ -DOpenGL_GL_PREFERENCE=GLVND)
|
||||
|
||||
override_dh_auto_build:
|
||||
(cd obj-$(DEB_TARGET_MULTIARCH) && make -j4)
|
||||
|
||||
S=obj-$(DEB_TARGET_MULTIARCH)
|
||||
I=debian/hifi-interface/opt/hifi/interface
|
||||
|
||||
override_dh_auto_install:
|
||||
cp $(S)/interface/interface $(I)
|
||||
cp $(S)/ext/makefiles/steamworks/project/src/steamworks/redistributable_bin/linux64/libsteam_api.so $(I)
|
||||
cp $(S)/ext/makefiles/quazip/project/build/libquazip5.so.1 $(I)
|
||||
cp $(S)/ext/makefiles/polyvox/project/build/library/PolyVoxCore/libPolyVoxCore.so.0 $(I)
|
||||
cp $(S)/interface/resources.rcc $(I)
|
||||
cp -r $(S)/interface/scripts $(I)/scripts
|
||||
cp -r $(S)/interface/plugins $(I)/plugins
|
1
debian/source/format
vendored
Normal file
1
debian/source/format
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
3.0 (quilt)
|
6
debian/source/include-binaries
vendored
Normal file
6
debian/source/include-binaries
vendored
Normal file
|
@ -0,0 +1,6 @@
|
|||
interface/compiledResources/resources.rcc
|
||||
tools/nitpick/compiledResources/resources.rcc
|
||||
__pycache__/hifi_android.cpython-37.pyc
|
||||
__pycache__/hifi_singleton.cpython-37.pyc
|
||||
__pycache__/hifi_utils.cpython-37.pyc
|
||||
__pycache__/hifi_vcpkg.cpython-37.pyc
|
|
@ -128,7 +128,7 @@ void DomainGatekeeper::processConnectRequestPacket(QSharedPointer<ReceivedMessag
|
|||
|
||||
// signal that we just connected a node so the DomainServer can get it a list
|
||||
// and broadcast its presence right away
|
||||
emit connectedNode(node);
|
||||
emit connectedNode(node, message->getFirstPacketReceiveTime());
|
||||
} else {
|
||||
qDebug() << "Refusing connection from node at" << message->getSenderSockAddr()
|
||||
<< "with hardware address" << nodeConnection.hardwareAddress
|
||||
|
@ -358,7 +358,8 @@ SharedNodePointer DomainGatekeeper::processAssignmentConnectRequest(const NodeCo
|
|||
nodeData->setNodeVersion(it->second.getNodeVersion());
|
||||
nodeData->setHardwareAddress(nodeConnection.hardwareAddress);
|
||||
nodeData->setMachineFingerprint(nodeConnection.machineFingerprint);
|
||||
|
||||
// client-side send time of last connect/domain list request
|
||||
nodeData->setLastDomainCheckinTimestamp(nodeConnection.lastPingTimestamp);
|
||||
nodeData->setWasAssigned(true);
|
||||
|
||||
// cleanup the PendingAssignedNodeData for this assignment now that it's connecting
|
||||
|
@ -499,6 +500,9 @@ SharedNodePointer DomainGatekeeper::processAgentConnectRequest(const NodeConnect
|
|||
// set the machine fingerprint passed in the connect request
|
||||
nodeData->setMachineFingerprint(nodeConnection.machineFingerprint);
|
||||
|
||||
// set client-side send time of last connect/domain list request
|
||||
nodeData->setLastDomainCheckinTimestamp(nodeConnection.lastPingTimestamp);
|
||||
|
||||
// also add an interpolation to DomainServerNodeData so that servers can get username in stats
|
||||
nodeData->addOverrideForKey(USERNAME_UUID_REPLACEMENT_STATS_KEY,
|
||||
uuidStringWithoutCurlyBraces(newNode->getUUID()), username);
|
||||
|
|
|
@ -64,7 +64,7 @@ public slots:
|
|||
|
||||
signals:
|
||||
void killNode(SharedNodePointer node);
|
||||
void connectedNode(SharedNodePointer node);
|
||||
void connectedNode(SharedNodePointer node, quint64 requestReceiveTime);
|
||||
|
||||
public slots:
|
||||
void updateNodePermissions();
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include <memory>
|
||||
#include <random>
|
||||
#include <iostream>
|
||||
#include <chrono>
|
||||
|
||||
#include <QDir>
|
||||
#include <QJsonDocument>
|
||||
|
@ -57,6 +58,8 @@
|
|||
|
||||
#include <OctreeDataUtils.h>
|
||||
|
||||
using namespace std::chrono;
|
||||
|
||||
Q_LOGGING_CATEGORY(domain_server, "hifi.domain_server")
|
||||
Q_LOGGING_CATEGORY(domain_server_ice, "hifi.domain_server.ice")
|
||||
|
||||
|
@ -1068,7 +1071,10 @@ void DomainServer::processListRequestPacket(QSharedPointer<ReceivedMessage> mess
|
|||
// update the connecting hostname in case it has changed
|
||||
nodeData->setPlaceName(nodeRequestData.placeName);
|
||||
|
||||
sendDomainListToNode(sendingNode, message->getSenderSockAddr());
|
||||
// client-side send time of last connect/domain list request
|
||||
nodeData->setLastDomainCheckinTimestamp(nodeRequestData.lastPingTimestamp);
|
||||
|
||||
sendDomainListToNode(sendingNode, message->getFirstPacketReceiveTime(), message->getSenderSockAddr());
|
||||
}
|
||||
|
||||
bool DomainServer::isInInterestSet(const SharedNodePointer& nodeA, const SharedNodePointer& nodeB) {
|
||||
|
@ -1130,11 +1136,11 @@ QUrl DomainServer::oauthAuthorizationURL(const QUuid& stateUUID) {
|
|||
return authorizationURL;
|
||||
}
|
||||
|
||||
void DomainServer::handleConnectedNode(SharedNodePointer newNode) {
|
||||
void DomainServer::handleConnectedNode(SharedNodePointer newNode, quint64 requestReceiveTime) {
|
||||
DomainServerNodeData* nodeData = static_cast<DomainServerNodeData*>(newNode->getLinkedData());
|
||||
|
||||
// reply back to the user with a PacketType::DomainList
|
||||
sendDomainListToNode(newNode, nodeData->getSendingSockAddr());
|
||||
sendDomainListToNode(newNode, requestReceiveTime, nodeData->getSendingSockAddr());
|
||||
|
||||
// if this node is a user (unassigned Agent), signal
|
||||
if (newNode->getType() == NodeType::Agent && !nodeData->wasAssigned()) {
|
||||
|
@ -1150,7 +1156,7 @@ void DomainServer::handleConnectedNode(SharedNodePointer newNode) {
|
|||
broadcastNewNode(newNode);
|
||||
}
|
||||
|
||||
void DomainServer::sendDomainListToNode(const SharedNodePointer& node, const HifiSockAddr &senderSockAddr) {
|
||||
void DomainServer::sendDomainListToNode(const SharedNodePointer& node, quint64 requestPacketReceiveTime, const HifiSockAddr &senderSockAddr) {
|
||||
const int NUM_DOMAIN_LIST_EXTENDED_HEADER_BYTES = NUM_BYTES_RFC4122_UUID + NLPacket::NUM_BYTES_LOCALID +
|
||||
NUM_BYTES_RFC4122_UUID + NLPacket::NUM_BYTES_LOCALID + 4;
|
||||
|
||||
|
@ -1158,7 +1164,7 @@ void DomainServer::sendDomainListToNode(const SharedNodePointer& node, const Hif
|
|||
// this data is at the beginning of each of the domain list packets
|
||||
QByteArray extendedHeader(NUM_DOMAIN_LIST_EXTENDED_HEADER_BYTES, 0);
|
||||
QDataStream extendedHeaderStream(&extendedHeader, QIODevice::WriteOnly);
|
||||
|
||||
DomainServerNodeData* nodeData = static_cast<DomainServerNodeData*>(node->getLinkedData());
|
||||
auto limitedNodeList = DependencyManager::get<LimitedNodeList>();
|
||||
|
||||
extendedHeaderStream << limitedNodeList->getSessionUUID();
|
||||
|
@ -1167,13 +1173,14 @@ void DomainServer::sendDomainListToNode(const SharedNodePointer& node, const Hif
|
|||
extendedHeaderStream << node->getLocalID();
|
||||
extendedHeaderStream << node->getPermissions();
|
||||
extendedHeaderStream << limitedNodeList->getAuthenticatePackets();
|
||||
extendedHeaderStream << nodeData->getLastDomainCheckinTimestamp();
|
||||
extendedHeaderStream << requestPacketReceiveTime;
|
||||
extendedHeaderStream << quint64(duration_cast<microseconds>(p_high_resolution_clock::now().time_since_epoch()).count());
|
||||
auto domainListPackets = NLPacketList::create(PacketType::DomainList, extendedHeader);
|
||||
|
||||
// always send the node their own UUID back
|
||||
QDataStream domainListStream(domainListPackets.get());
|
||||
|
||||
DomainServerNodeData* nodeData = static_cast<DomainServerNodeData*>(node->getLinkedData());
|
||||
|
||||
// store the nodeInterestSet on this DomainServerNodeData, in case it has changed
|
||||
auto& nodeInterestSet = nodeData->getNodeInterestSet();
|
||||
|
||||
|
|
|
@ -111,7 +111,7 @@ private slots:
|
|||
void sendHeartbeatToMetaverse() { sendHeartbeatToMetaverse(QString()); }
|
||||
void sendHeartbeatToIceServer();
|
||||
|
||||
void handleConnectedNode(SharedNodePointer newNode);
|
||||
void handleConnectedNode(SharedNodePointer newNode, quint64 requestReceiveTime);
|
||||
void handleTempDomainSuccess(QNetworkReply* requestReply);
|
||||
void handleTempDomainError(QNetworkReply* requestReply);
|
||||
|
||||
|
@ -172,7 +172,7 @@ private:
|
|||
void handleKillNode(SharedNodePointer nodeToKill);
|
||||
void broadcastNodeDisconnect(const SharedNodePointer& disconnnectedNode);
|
||||
|
||||
void sendDomainListToNode(const SharedNodePointer& node, const HifiSockAddr& senderSockAddr);
|
||||
void sendDomainListToNode(const SharedNodePointer& node, quint64 requestPacketReceiveTime, const HifiSockAddr& senderSockAddr);
|
||||
|
||||
bool isInInterestSet(const SharedNodePointer& nodeA, const SharedNodePointer& nodeB);
|
||||
|
||||
|
|
|
@ -61,6 +61,9 @@ public:
|
|||
void setMachineFingerprint(const QUuid& machineFingerprint) { _machineFingerprint = machineFingerprint; }
|
||||
const QUuid& getMachineFingerprint() { return _machineFingerprint; }
|
||||
|
||||
void setLastDomainCheckinTimestamp(quint64 lastDomainCheckinTimestamp) { _lastDomainCheckinTimestamp = lastDomainCheckinTimestamp; }
|
||||
quint64 getLastDomainCheckinTimestamp() { return _lastDomainCheckinTimestamp; }
|
||||
|
||||
void addOverrideForKey(const QString& key, const QString& value, const QString& overrideValue);
|
||||
void removeOverrideForKey(const QString& key, const QString& value);
|
||||
|
||||
|
@ -93,7 +96,7 @@ private:
|
|||
QString _nodeVersion;
|
||||
QString _hardwareAddress;
|
||||
QUuid _machineFingerprint;
|
||||
|
||||
quint64 _lastDomainCheckinTimestamp;
|
||||
QString _placeName;
|
||||
|
||||
bool _wasAssigned { false };
|
||||
|
|
|
@ -36,6 +36,8 @@ NodeConnectionData NodeConnectionData::fromDataStream(QDataStream& dataStream, c
|
|||
// now the machine fingerprint
|
||||
dataStream >> newHeader.machineFingerprint;
|
||||
}
|
||||
|
||||
dataStream >> newHeader.lastPingTimestamp;
|
||||
|
||||
dataStream >> newHeader.nodeType
|
||||
>> newHeader.publicSockAddr >> newHeader.localSockAddr
|
||||
|
|
|
@ -22,6 +22,7 @@ public:
|
|||
bool isConnectRequest = true);
|
||||
|
||||
QUuid connectUUID;
|
||||
quint64 lastPingTimestamp{ 0 }; // client-side send time of last connect/domain list request
|
||||
NodeType_t nodeType;
|
||||
HifiSockAddr publicSockAddr;
|
||||
HifiSockAddr localSockAddr;
|
||||
|
|
|
@ -15,10 +15,12 @@ print = functools.partial(print, flush=True)
|
|||
# Encapsulates the vcpkg system
|
||||
class VcpkgRepo:
|
||||
CMAKE_TEMPLATE = """
|
||||
# this file auto-generated by hifi_vcpkg.py
|
||||
get_filename_component(CMAKE_TOOLCHAIN_FILE "{}" ABSOLUTE CACHE)
|
||||
get_filename_component(CMAKE_TOOLCHAIN_FILE_UNCACHED "{}" ABSOLUTE)
|
||||
set(VCPKG_INSTALL_ROOT "{}")
|
||||
set(VCPKG_TOOLS_DIR "{}")
|
||||
set(VCPKG_QT_CMAKE_PREFIX_PATH "{}")
|
||||
"""
|
||||
|
||||
CMAKE_TEMPLATE_NON_ANDROID = """
|
||||
|
@ -171,6 +173,11 @@ endif()
|
|||
if not self.args.android:
|
||||
print("Installing build dependencies")
|
||||
self.run(['install', '--triplet', self.triplet, 'hifi-client-deps'])
|
||||
|
||||
# If not android, install our Qt build
|
||||
if not self.args.android:
|
||||
print("Installing Qt")
|
||||
self.installQt()
|
||||
|
||||
def cleanBuilds(self):
|
||||
# Remove temporary build artifacts
|
||||
|
@ -206,22 +213,33 @@ endif()
|
|||
with open(self.tagFile, 'w') as f:
|
||||
f.write(self.tagContents)
|
||||
|
||||
def getQt5InstallPath(self):
|
||||
qt5InstallPath = os.path.join(self.path, 'installed', 'qt5-install')
|
||||
if platform.system() == "Darwin" and self.args.release_type != "DEV":
|
||||
# HACK for MacOS Jenkins PRODUCTION and PR builds during Qt-5.12.3 transition
|
||||
# we always supply /var/tmp/qt5-install for QT_CMAKE_PREFIX_PATH
|
||||
qt5InstallPath = "/var/tmp/qt5-install"
|
||||
elif self.args.android:
|
||||
precompiled = os.path.realpath(self.androidPackagePath)
|
||||
qt5InstallPath = os.path.realpath(os.path.join(precompiled, 'qt'))
|
||||
return qt5InstallPath
|
||||
|
||||
def writeConfig(self):
|
||||
print("Writing cmake config to {}".format(self.configFilePath))
|
||||
# Write out the configuration for use by CMake
|
||||
cmakeScript = os.path.join(self.path, 'scripts/buildsystems/vcpkg.cmake')
|
||||
installPath = os.path.join(self.path, 'installed', self.triplet)
|
||||
toolsPath = os.path.join(self.path, 'installed', self.hostTriplet, 'tools')
|
||||
cmakeTemplate = VcpkgRepo.CMAKE_TEMPLATE
|
||||
if not self.args.android:
|
||||
cmakeTemplate += VcpkgRepo.CMAKE_TEMPLATE_NON_ANDROID
|
||||
else:
|
||||
precompiled = os.path.realpath(self.androidPackagePath)
|
||||
qtCmakePrefix = os.path.realpath(os.path.join(precompiled, 'qt/lib/cmake'))
|
||||
cmakeTemplate += 'set(HIFI_ANDROID_PRECOMPILED "{}")\n'.format(precompiled)
|
||||
cmakeTemplate += 'set(QT_CMAKE_PREFIX_PATH "{}")\n'.format(qtCmakePrefix)
|
||||
|
||||
cmakeConfig = cmakeTemplate.format(cmakeScript, cmakeScript, installPath, toolsPath).replace('\\', '/')
|
||||
cmakeTemplate = VcpkgRepo.CMAKE_TEMPLATE
|
||||
if self.args.android:
|
||||
precompiled = os.path.realpath(self.androidPackagePath)
|
||||
cmakeTemplate += 'set(HIFI_ANDROID_PRECOMPILED "{}")\n'.format(precompiled)
|
||||
else:
|
||||
cmakeTemplate += VcpkgRepo.CMAKE_TEMPLATE_NON_ANDROID
|
||||
|
||||
qtCmakePrefixPath = os.path.join(self.getQt5InstallPath(), "lib/cmake")
|
||||
cmakeConfig = cmakeTemplate.format(cmakeScript, cmakeScript, installPath, toolsPath, qtCmakePrefixPath).replace('\\', '/')
|
||||
with open(self.configFilePath, 'w') as f:
|
||||
f.write(cmakeConfig)
|
||||
|
||||
|
@ -232,3 +250,28 @@ endif()
|
|||
print("Not implemented")
|
||||
|
||||
|
||||
def installQt(self):
|
||||
qt5InstallPath = self.getQt5InstallPath()
|
||||
if not os.path.isdir(qt5InstallPath):
|
||||
print ('Downloading Qt from AWS')
|
||||
dest, tail = os.path.split(qt5InstallPath)
|
||||
|
||||
url = 'NOT DEFINED'
|
||||
if platform.system() == 'Windows':
|
||||
url = 'https://hifi-public.s3.amazonaws.com/dependencies/vcpkg/qt5-install-5.12.3-windows2.tar.gz'
|
||||
elif platform.system() == 'Darwin':
|
||||
url = 'https://hifi-public.s3.amazonaws.com/dependencies/vcpkg/qt5-install-5.12.3-macos.tar.gz'
|
||||
elif platform.system() == 'Linux':
|
||||
if platform.linux_distribution()[1][:3] == '16.':
|
||||
url = 'https://hifi-public.s3.amazonaws.com/dependencies/vcpkg/qt5-install-5.12.3-ubuntu-16.04.tar.gz'
|
||||
elif platform.linux_distribution()[1][:3] == '18.':
|
||||
url = 'https://hifi-public.s3.amazonaws.com/dependencies/vcpkg/qt5-install-5.12.3-ubuntu-18.04.tar.gz'
|
||||
else:
|
||||
print('UNKNOWN LINUX VERSION!!!')
|
||||
else:
|
||||
print('UNKNOWN OPERATING SYSTEM!!!')
|
||||
|
||||
print('Extracting ' + url + ' to ' + dest)
|
||||
hifi_utils.downloadAndExtract(url, dest)
|
||||
else:
|
||||
print ('Qt has already been downloaded')
|
||||
|
|
|
@ -334,11 +334,11 @@ if (APPLE)
|
|||
COMMAND "${CMAKE_COMMAND}" -E copy_directory
|
||||
"${PROJECT_SOURCE_DIR}/resources/fonts"
|
||||
"${RESOURCES_DEV_DIR}/fonts"
|
||||
#copy serverless for android
|
||||
COMMAND "${CMAKE_COMMAND}" -E copy_directory
|
||||
"${PROJECT_SOURCE_DIR}/resources/serverless"
|
||||
"${RESOURCES_DEV_DIR}/serverless"
|
||||
# add redirect json to macOS builds.
|
||||
#copy serverless for android
|
||||
COMMAND "${CMAKE_COMMAND}" -E copy_directory
|
||||
"${PROJECT_SOURCE_DIR}/resources/serverless"
|
||||
"${RESOURCES_DEV_DIR}/serverless"
|
||||
# add redirect json to macOS builds.
|
||||
COMMAND "${CMAKE_COMMAND}" -E copy_if_different
|
||||
"${PROJECT_SOURCE_DIR}/resources/serverless/redirect.json"
|
||||
"${RESOURCES_DEV_DIR}/serverless/redirect.json"
|
||||
|
@ -401,6 +401,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"
|
||||
)
|
||||
endif()
|
||||
|
||||
if (SCRIPTS_INSTALL_DIR)
|
||||
# setup install of scripts beside interface executable
|
||||
install(
|
||||
|
|
Binary file not shown.
After ![]() (image error) Size: 548 KiB |
Binary file not shown.
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"compressed": {
|
||||
"COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT": "Default-Sky-9-cubemap-ambient_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT.ktx",
|
||||
"COMPRESSED_SRGB8_ETC2": "Default-Sky-9-cubemap-ambient_COMPRESSED_SRGB8_ETC2.ktx"
|
||||
},
|
||||
"original": "Default-Sky-9-cubemap-ambient.jpg",
|
||||
"uncompressed": "Default-Sky-9-cubemap-ambient.ktx",
|
||||
"version": 1
|
||||
}
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -4,5 +4,6 @@
|
|||
"COMPRESSED_SRGB8_ETC2": "Default-Sky-9-cubemap_COMPRESSED_SRGB8_ETC2.ktx"
|
||||
},
|
||||
"original": "Default-Sky-9-cubemap.jpg",
|
||||
"uncompressed": "Default-Sky-9-cubemap.ktx"
|
||||
"uncompressed": "Default-Sky-9-cubemap.ktx",
|
||||
"version": 1
|
||||
}
|
||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -58,7 +58,8 @@ Rectangle {
|
|||
if (isLoggedIn) {
|
||||
Commerce.getWalletStatus();
|
||||
} else {
|
||||
// Show some error to the user
|
||||
errorText.text = "There was a problem while retrieving your inventory. " +
|
||||
"Please try closing and re-opening the Avatar app.\n\nLogin status result: " + isLoggedIn;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -66,11 +67,19 @@ Rectangle {
|
|||
if (walletStatus === 5) {
|
||||
getInventory();
|
||||
} else {
|
||||
// Show some error to the user
|
||||
errorText.text = "There was a problem while retrieving your inventory. " +
|
||||
"Please try closing and re-opening the Avatar app.\n\nWallet status result: " + walletStatus;
|
||||
}
|
||||
}
|
||||
|
||||
onInventoryResult: {
|
||||
if (result.status !== "success") {
|
||||
errorText.text = "There was a problem while retrieving your inventory. " +
|
||||
"Please try closing and re-opening the Avatar app.\n\nInventory status: " + result.status + "\nMessage: " + result.message;
|
||||
} else if (result.data && result.data.assets && result.data.assets.length === 0 && avatarAppInventoryModel.count === 0) {
|
||||
errorText.text = "You have not created any avatars yet! Create an avatar with the Avatar Creator, then close and re-open the Avatar App."
|
||||
}
|
||||
|
||||
avatarAppInventoryModel.handlePage(result.status !== "success" && result.message, result);
|
||||
root.updatePreviewUrl();
|
||||
}
|
||||
|
@ -172,7 +181,7 @@ Rectangle {
|
|||
anchors.bottom: parent.bottom
|
||||
|
||||
AnimatedImage {
|
||||
visible: !inventoryContentsList.visible
|
||||
visible: !inventoryContentsList.visible && !errorText.visible
|
||||
anchors.centerIn: parent
|
||||
width: 72
|
||||
height: width
|
||||
|
@ -181,7 +190,7 @@ Rectangle {
|
|||
|
||||
ListView {
|
||||
id: inventoryContentsList
|
||||
visible: avatarAppInventoryModel.count !== 0
|
||||
visible: avatarAppInventoryModel.count !== 0 && !errorText.visible
|
||||
interactive: contentItem.height > height
|
||||
clip: true
|
||||
model: avatarAppInventoryModel
|
||||
|
@ -196,6 +205,18 @@ Rectangle {
|
|||
standaloneIncompatible: model.standalone_incompatible
|
||||
}
|
||||
}
|
||||
|
||||
HifiStylesUit.GraphikRegular {
|
||||
id: errorText
|
||||
text: ""
|
||||
visible: text !== ""
|
||||
anchors.fill: parent
|
||||
size: 22
|
||||
color: simplifiedUI.colors.text.white
|
||||
wrapMode: Text.Wrap
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -19,8 +19,8 @@ Flickable {
|
|||
id: root
|
||||
contentWidth: parent.width
|
||||
contentHeight: audioColumnLayout.height
|
||||
topMargin: 16
|
||||
bottomMargin: 16
|
||||
topMargin: 24
|
||||
bottomMargin: 24
|
||||
clip: true
|
||||
|
||||
function changePeakValuesEnabled(enabled) {
|
||||
|
@ -60,7 +60,7 @@ Flickable {
|
|||
HifiStylesUit.GraphikRegular {
|
||||
id: volumeControlsTitle
|
||||
text: "Volume Controls"
|
||||
Layout.maximumWidth: parent.width
|
||||
Layout.preferredWidth: parent.width
|
||||
height: paintedHeight
|
||||
size: 22
|
||||
color: simplifiedUI.colors.text.white
|
||||
|
@ -68,57 +68,82 @@ Flickable {
|
|||
|
||||
SimplifiedControls.Slider {
|
||||
id: peopleVolume
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
Layout.preferredWidth: parent.width
|
||||
Layout.preferredHeight: 30
|
||||
Layout.topMargin: simplifiedUI.margins.settings.settingsGroupTopMargin
|
||||
height: 30
|
||||
labelText: "People Volume"
|
||||
from: -60
|
||||
to: 10
|
||||
from: simplifiedUI.numericConstants.mutedValue
|
||||
to: 20.0
|
||||
defaultValue: 0.0
|
||||
value: AudioScriptingInterface.getAvatarGain()
|
||||
stepSize: 5.0
|
||||
value: AudioScriptingInterface.avatarGain
|
||||
live: true
|
||||
function updatePeopleGain(sliderValue) {
|
||||
if (AudioScriptingInterface.avatarGain !== sliderValue) {
|
||||
AudioScriptingInterface.avatarGain = sliderValue;
|
||||
}
|
||||
}
|
||||
onValueChanged: {
|
||||
if (AudioScriptingInterface.getAvatarGain() != peopleVolume.value) {
|
||||
AudioScriptingInterface.setAvatarGain(peopleVolume.value);
|
||||
updatePeopleGain(value);
|
||||
}
|
||||
onPressedChanged: {
|
||||
if (!pressed) {
|
||||
updatePeopleGain(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SimplifiedControls.Slider {
|
||||
id: environmentVolume
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
Layout.preferredWidth: parent.width
|
||||
Layout.preferredHeight: 30
|
||||
Layout.topMargin: 2
|
||||
height: 30
|
||||
labelText: "Environment Volume"
|
||||
from: -60
|
||||
to: 10
|
||||
from: simplifiedUI.numericConstants.mutedValue
|
||||
to: 20.0
|
||||
defaultValue: 0.0
|
||||
value: AudioScriptingInterface.getInjectorGain()
|
||||
stepSize: 5.0
|
||||
value: AudioScriptingInterface.serverInjectorGain
|
||||
live: true
|
||||
function updateEnvironmentGain(sliderValue) {
|
||||
if (AudioScriptingInterface.serverInjectorGain !== sliderValue) {
|
||||
AudioScriptingInterface.serverInjectorGain = sliderValue;
|
||||
AudioScriptingInterface.localInjectorGain = sliderValue;
|
||||
}
|
||||
}
|
||||
onValueChanged: {
|
||||
if (AudioScriptingInterface.getInjectorGain() != environmentVolume.value) {
|
||||
AudioScriptingInterface.setInjectorGain(environmentVolume.value);
|
||||
updateEnvironmentGain(value);
|
||||
}
|
||||
onPressedChanged: {
|
||||
if (!pressed) {
|
||||
updateEnvironmentGain(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SimplifiedControls.Slider {
|
||||
id: systemSoundVolume
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
Layout.preferredWidth: parent.width
|
||||
Layout.preferredHeight: 30
|
||||
Layout.topMargin: 2
|
||||
height: 30
|
||||
labelText: "System Sound Volume"
|
||||
from: -60
|
||||
to: 10
|
||||
from: simplifiedUI.numericConstants.mutedValue
|
||||
to: 20.0
|
||||
defaultValue: 0.0
|
||||
value: AudioScriptingInterface.getSystemInjectorGain()
|
||||
stepSize: 5.0
|
||||
value: AudioScriptingInterface.systemInjectorGain
|
||||
live: true
|
||||
function updateSystemGain(sliderValue) {
|
||||
if (AudioScriptingInterface.systemInjectorGain !== sliderValue) {
|
||||
AudioScriptingInterface.systemInjectorGain = sliderValue;
|
||||
}
|
||||
}
|
||||
onValueChanged: {
|
||||
if (AudioScriptingInterface.getSystemInjectorGain() != systemSoundVolume.value) {
|
||||
AudioScriptingInterface.setSystemInjectorGain(systemSoundVolume.value);
|
||||
updateSystemGain(value);
|
||||
}
|
||||
onPressedChanged: {
|
||||
if (!pressed) {
|
||||
updateSystemGain(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -144,8 +169,8 @@ Flickable {
|
|||
|
||||
SimplifiedControls.Switch {
|
||||
id: muteMicrophoneSwitch
|
||||
width: parent.width
|
||||
height: 18
|
||||
Layout.preferredHeight: 18
|
||||
Layout.preferredWidth: parent.width
|
||||
labelTextOn: "Mute Microphone"
|
||||
checked: AudioScriptingInterface.mutedDesktop
|
||||
onClicked: {
|
||||
|
@ -155,8 +180,8 @@ Flickable {
|
|||
|
||||
SimplifiedControls.Switch {
|
||||
id: pushToTalkSwitch
|
||||
width: parent.width
|
||||
height: 18
|
||||
Layout.preferredHeight: 18
|
||||
Layout.preferredWidth: parent.width
|
||||
labelTextOn: "Push to Talk - Press and Hold \"T\" to Talk"
|
||||
checked: AudioScriptingInterface.pushToTalkDesktop
|
||||
onClicked: {
|
||||
|
@ -184,12 +209,11 @@ Flickable {
|
|||
|
||||
ListView {
|
||||
id: inputDeviceListView
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
Layout.preferredWidth: parent.width
|
||||
Layout.preferredHeight: contentItem.height
|
||||
Layout.topMargin: simplifiedUI.margins.settings.settingsGroupTopMargin
|
||||
interactive: false
|
||||
height: contentItem.height
|
||||
spacing: 4
|
||||
spacing: simplifiedUI.margins.settings.spacingBetweenRadiobuttons
|
||||
clip: true
|
||||
model: AudioScriptingInterface.devices.input
|
||||
delegate: Item {
|
||||
|
@ -200,6 +224,8 @@ Flickable {
|
|||
id: inputDeviceCheckbox
|
||||
anchors.left: parent.left
|
||||
width: parent.width - inputLevel.width
|
||||
height: 16
|
||||
wrapLabel: false
|
||||
checked: selectedDesktop
|
||||
text: model.devicename
|
||||
ButtonGroup.group: inputDeviceButtonGroup
|
||||
|
@ -221,6 +247,7 @@ Flickable {
|
|||
}
|
||||
|
||||
SimplifiedControls.Button {
|
||||
id: audioLoopbackButton
|
||||
property bool audioLoopedBack: AudioScriptingInterface.getLocalEcho()
|
||||
|
||||
function startAudioLoopback() {
|
||||
|
@ -236,29 +263,23 @@ Flickable {
|
|||
}
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: loopbackTimer
|
||||
interval: 8000
|
||||
running: false
|
||||
repeat: false
|
||||
onTriggered: {
|
||||
Component.onDestruction: stopAudioLoopback();
|
||||
|
||||
onVisibleChanged: {
|
||||
if (!visible) {
|
||||
stopAudioLoopback();
|
||||
}
|
||||
}
|
||||
|
||||
id: testYourMicButton
|
||||
enabled: !HMD.active
|
||||
anchors.left: parent.left
|
||||
Layout.topMargin: simplifiedUI.margins.settings.settingsGroupTopMargin
|
||||
width: 160
|
||||
height: 32
|
||||
text: audioLoopedBack ? "STOP TESTING" : "TEST YOUR MIC"
|
||||
onClicked: {
|
||||
if (audioLoopedBack) {
|
||||
loopbackTimer.stop();
|
||||
stopAudioLoopback();
|
||||
} else {
|
||||
loopbackTimer.restart();
|
||||
startAudioLoopback();
|
||||
}
|
||||
}
|
||||
|
@ -283,12 +304,11 @@ Flickable {
|
|||
|
||||
ListView {
|
||||
id: outputDeviceListView
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
Layout.preferredWidth: parent.width
|
||||
Layout.preferredHeight: contentItem.height
|
||||
Layout.topMargin: simplifiedUI.margins.settings.settingsGroupTopMargin
|
||||
interactive: false
|
||||
height: contentItem.height
|
||||
spacing: 4
|
||||
spacing: simplifiedUI.margins.settings.spacingBetweenRadiobuttons
|
||||
clip: true
|
||||
model: AudioScriptingInterface.devices.output
|
||||
delegate: Item {
|
||||
|
@ -299,8 +319,10 @@ Flickable {
|
|||
id: outputDeviceCheckbox
|
||||
anchors.left: parent.left
|
||||
width: parent.width
|
||||
height: 16
|
||||
checked: selectedDesktop
|
||||
text: model.devicename
|
||||
wrapLabel: false
|
||||
ButtonGroup.group: outputDeviceButtonGroup
|
||||
onClicked: {
|
||||
AudioScriptingInterface.setOutputDevice(model.info, false); // `false` argument for Desktop mode setting
|
||||
|
@ -349,7 +371,6 @@ Flickable {
|
|||
|
||||
id: testYourSoundButton
|
||||
enabled: !HMD.active
|
||||
anchors.left: parent.left
|
||||
Layout.topMargin: simplifiedUI.margins.settings.settingsGroupTopMargin
|
||||
width: 160
|
||||
height: 32
|
||||
|
|
|
@ -20,8 +20,8 @@ Flickable {
|
|||
id: root
|
||||
contentWidth: parent.width
|
||||
contentHeight: generalColumnLayout.height
|
||||
topMargin: 16
|
||||
bottomMargin: 16
|
||||
topMargin: 24
|
||||
bottomMargin: 24
|
||||
clip: true
|
||||
|
||||
onAvatarNametagModeChanged: {
|
||||
|
@ -63,6 +63,7 @@ Flickable {
|
|||
ColumnLayout {
|
||||
id: avatarNameTagsRadioButtonGroup
|
||||
Layout.topMargin: simplifiedUI.margins.settings.settingsGroupTopMargin
|
||||
spacing: simplifiedUI.margins.settings.spacingBetweenRadiobuttons
|
||||
|
||||
SimplifiedControls.RadioButton {
|
||||
id: avatarNameTagsOff
|
||||
|
@ -110,6 +111,7 @@ Flickable {
|
|||
ColumnLayout {
|
||||
id: performanceRadioButtonGroup
|
||||
Layout.topMargin: simplifiedUI.margins.settings.settingsGroupTopMargin
|
||||
spacing: simplifiedUI.margins.settings.spacingBetweenRadiobuttons
|
||||
|
||||
SimplifiedControls.RadioButton {
|
||||
id: performanceLow
|
||||
|
@ -157,6 +159,7 @@ Flickable {
|
|||
ColumnLayout {
|
||||
id: cameraRadioButtonGroup
|
||||
Layout.topMargin: simplifiedUI.margins.settings.settingsGroupTopMargin
|
||||
spacing: simplifiedUI.margins.settings.spacingBetweenRadiobuttons
|
||||
|
||||
SimplifiedControls.RadioButton {
|
||||
id: firstPerson
|
||||
|
|
|
@ -19,8 +19,8 @@ Flickable {
|
|||
id: root
|
||||
contentWidth: parent.width
|
||||
contentHeight: vrColumnLayout.height
|
||||
topMargin: 16
|
||||
bottomMargin: 16
|
||||
topMargin: 24
|
||||
bottomMargin: 24
|
||||
clip: true
|
||||
|
||||
function changePeakValuesEnabled(enabled) {
|
||||
|
@ -70,6 +70,7 @@ Flickable {
|
|||
id: controlsRadioButtonGroup
|
||||
width: parent.width
|
||||
Layout.topMargin: simplifiedUI.margins.settings.settingsGroupTopMargin
|
||||
spacing: simplifiedUI.margins.settings.spacingBetweenRadiobuttons
|
||||
|
||||
ButtonGroup { id: controlsButtonGroup }
|
||||
|
||||
|
@ -197,12 +198,11 @@ Flickable {
|
|||
|
||||
ListView {
|
||||
id: inputDeviceListView
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
Layout.preferredWidth: parent.width
|
||||
Layout.preferredHeight: contentItem.height
|
||||
Layout.topMargin: simplifiedUI.margins.settings.settingsGroupTopMargin
|
||||
interactive: false
|
||||
height: contentItem.height
|
||||
spacing: 4
|
||||
spacing: simplifiedUI.margins.settings.spacingBetweenRadiobuttons
|
||||
clip: true
|
||||
model: AudioScriptingInterface.devices.input
|
||||
delegate: Item {
|
||||
|
@ -213,8 +213,10 @@ Flickable {
|
|||
id: inputDeviceCheckbox
|
||||
anchors.left: parent.left
|
||||
width: parent.width - inputLevel.width
|
||||
height: 16
|
||||
checked: selectedHMD
|
||||
text: model.devicename
|
||||
wrapLabel: false
|
||||
ButtonGroup.group: inputDeviceButtonGroup
|
||||
onClicked: {
|
||||
AudioScriptingInterface.setStereoInput(false); // the next selected audio device might not support stereo
|
||||
|
@ -234,6 +236,7 @@ Flickable {
|
|||
}
|
||||
|
||||
SimplifiedControls.Button {
|
||||
id: audioLoopbackButton
|
||||
property bool audioLoopedBack: AudioScriptingInterface.getLocalEcho()
|
||||
|
||||
function startAudioLoopback() {
|
||||
|
@ -249,29 +252,23 @@ Flickable {
|
|||
}
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: loopbackTimer
|
||||
interval: 8000
|
||||
running: false
|
||||
repeat: false
|
||||
onTriggered: {
|
||||
Component.onDestruction: stopAudioLoopback();
|
||||
|
||||
onVisibleChanged: {
|
||||
if (!visible) {
|
||||
stopAudioLoopback();
|
||||
}
|
||||
}
|
||||
|
||||
id: testYourMicButton
|
||||
enabled: HMD.active
|
||||
anchors.left: parent.left
|
||||
Layout.topMargin: simplifiedUI.margins.settings.settingsGroupTopMargin
|
||||
width: 160
|
||||
height: 32
|
||||
text: audioLoopedBack ? "STOP TESTING" : "TEST YOUR MIC"
|
||||
onClicked: {
|
||||
if (audioLoopedBack) {
|
||||
loopbackTimer.stop();
|
||||
stopAudioLoopback();
|
||||
} else {
|
||||
loopbackTimer.restart();
|
||||
startAudioLoopback();
|
||||
}
|
||||
}
|
||||
|
@ -296,12 +293,11 @@ Flickable {
|
|||
|
||||
ListView {
|
||||
id: outputDeviceListView
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
Layout.preferredWidth: parent.width
|
||||
Layout.preferredHeight: contentItem.height
|
||||
Layout.topMargin: simplifiedUI.margins.settings.settingsGroupTopMargin
|
||||
interactive: false
|
||||
height: contentItem.height
|
||||
spacing: 4
|
||||
spacing: simplifiedUI.margins.settings.spacingBetweenRadiobuttons
|
||||
clip: true
|
||||
model: AudioScriptingInterface.devices.output
|
||||
delegate: Item {
|
||||
|
@ -312,11 +308,13 @@ Flickable {
|
|||
id: outputDeviceCheckbox
|
||||
anchors.left: parent.left
|
||||
width: parent.width
|
||||
checked: selectedDesktop
|
||||
height: 16
|
||||
checked: selectedHMD
|
||||
text: model.devicename
|
||||
wrapLabel: false
|
||||
ButtonGroup.group: outputDeviceButtonGroup
|
||||
onClicked: {
|
||||
AudioScriptingInterface.setOutputDevice(model.info, true); // `false` argument for Desktop mode setting
|
||||
AudioScriptingInterface.setOutputDevice(model.info, true); // `true` argument for VR mode setting
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -362,7 +360,6 @@ Flickable {
|
|||
|
||||
id: testYourSoundButton
|
||||
enabled: HMD.active
|
||||
anchors.left: parent.left
|
||||
Layout.topMargin: simplifiedUI.margins.settings.settingsGroupTopMargin
|
||||
width: 160
|
||||
height: 32
|
||||
|
|
|
@ -147,7 +147,7 @@ QtObject {
|
|||
}
|
||||
|
||||
readonly property color darkSeparator: "#595959"
|
||||
readonly property color darkBackground: "#1A1A1A"
|
||||
readonly property color darkBackground: "#000000"
|
||||
readonly property color darkBackgroundHighlight: "#575757"
|
||||
readonly property color highlightOnDark: Qt.rgba(1, 1, 1, 0.2)
|
||||
readonly property color white: "#FFFFFF"
|
||||
|
@ -182,9 +182,10 @@ QtObject {
|
|||
}
|
||||
|
||||
readonly property QtObject settings: QtObject {
|
||||
property real subtitleTopMargin: 2
|
||||
property real settingsGroupTopMargin: 10
|
||||
property real spacingBetweenSettings: 48
|
||||
property int subtitleTopMargin: 2
|
||||
property int settingsGroupTopMargin: 24
|
||||
property int spacingBetweenSettings: 48
|
||||
property int spacingBetweenRadiobuttons: 14
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -220,4 +221,8 @@ QtObject {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
readonly property QtObject numericConstants: QtObject {
|
||||
readonly property real mutedValue: -60.0
|
||||
}
|
||||
}
|
||||
|
|
|
@ -87,7 +87,6 @@ RadioButton {
|
|||
|
||||
contentItem: Text {
|
||||
id: radioButtonLabel
|
||||
height: root.radioButtonRadius
|
||||
font.pixelSize: 14
|
||||
font.family: "Graphik"
|
||||
font.weight: Font.Normal
|
||||
|
@ -99,5 +98,6 @@ RadioButton {
|
|||
enabled: root.enabled
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
leftPadding: radioButtonIndicator.width + root.labelLeftMargin
|
||||
topPadding: -3 // For perfect alignment when using Graphik
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@ Item {
|
|||
property alias live: sliderControl.live
|
||||
property alias stepSize: sliderControl.stepSize
|
||||
property alias snapMode: sliderControl.snapMode
|
||||
property alias pressed: sliderControl.pressed
|
||||
property real defaultValue: 0.0
|
||||
|
||||
HifiStylesUit.GraphikRegular {
|
||||
|
|
|
@ -70,8 +70,6 @@ Item {
|
|||
}
|
||||
|
||||
onCheckedChanged: {
|
||||
root.checkedChanged();
|
||||
Tablet.playSound(TabletEnums.ButtonClick);
|
||||
originalSwitch.changeColor();
|
||||
}
|
||||
|
||||
|
|
|
@ -203,7 +203,10 @@ Rectangle {
|
|||
|
||||
Image {
|
||||
id: outputDeviceButton
|
||||
property bool outputMuted: false
|
||||
property bool outputMuted: AudioScriptingInterface.avatarGain === simplifiedUI.numericConstants.mutedValue &&
|
||||
AudioScriptingInterface.serverInjectorGain === simplifiedUI.numericConstants.mutedValue &&
|
||||
AudioScriptingInterface.localInjectorGain === simplifiedUI.numericConstants.mutedValue &&
|
||||
AudioScriptingInterface.systemInjectorGain === simplifiedUI.numericConstants.mutedValue
|
||||
source: outputDeviceButton.outputMuted ? "./images/outputDeviceMuted.svg" : "./images/outputDeviceLoud.svg"
|
||||
anchors.centerIn: parent
|
||||
width: 20
|
||||
|
@ -228,13 +231,16 @@ Rectangle {
|
|||
}
|
||||
onClicked: {
|
||||
Tablet.playSound(TabletEnums.ButtonClick);
|
||||
outputDeviceButton.outputMuted = !outputDeviceButton.outputMuted;
|
||||
|
||||
if (!outputDeviceButton.outputMuted && !AudioScriptingInterface.muted) {
|
||||
AudioScriptingInterface.muted = true;
|
||||
}
|
||||
|
||||
sendToScript({
|
||||
"source": "SimplifiedTopBar.qml",
|
||||
"method": "setOutputMuted",
|
||||
"data": {
|
||||
"outputMuted": outputDeviceButton.outputMuted
|
||||
"outputMuted": !outputDeviceButton.outputMuted
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -242,6 +248,69 @@ Rectangle {
|
|||
}
|
||||
|
||||
|
||||
Item {
|
||||
id: statusButtonContainer
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.left: outputDeviceButtonContainer.right
|
||||
anchors.leftMargin: 8
|
||||
width: 36
|
||||
height: width
|
||||
|
||||
Rectangle {
|
||||
id: statusButton
|
||||
property string currentStatus
|
||||
anchors.centerIn: parent
|
||||
anchors.horizontalCenterOffset: 1
|
||||
anchors.verticalCenterOffset: 2
|
||||
width: 13
|
||||
height: width
|
||||
radius: width/2
|
||||
visible: false
|
||||
}
|
||||
|
||||
ColorOverlay {
|
||||
anchors.fill: statusButton
|
||||
opacity: statusButton.currentStatus ? 1 : 0
|
||||
source: statusButton
|
||||
color: if (statusButton.currentStatus === "busy") {
|
||||
"#ff001a"
|
||||
} else if (statusButton.currentStatus === "available") {
|
||||
"#009036"
|
||||
} else if (statusButton.currentStatus) {
|
||||
"#ffed00"
|
||||
}
|
||||
}
|
||||
|
||||
Image {
|
||||
id: focusIcon
|
||||
source: "./images/focus.svg"
|
||||
opacity: statusButtonMouseArea.containsMouse ? 1.0 : (statusButton.currentStatus === "busy" ? 0.7 : 0.3)
|
||||
anchors.centerIn: parent
|
||||
width: 36
|
||||
height: 20
|
||||
fillMode: Image.PreserveAspectFit
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: statusButtonMouseArea
|
||||
anchors.fill: parent
|
||||
enabled: statusButton.currentStatus
|
||||
hoverEnabled: true
|
||||
onEntered: {
|
||||
Tablet.playSound(TabletEnums.ButtonHover);
|
||||
}
|
||||
onClicked: {
|
||||
Tablet.playSound(TabletEnums.ButtonClick);
|
||||
|
||||
sendToScript({
|
||||
"source": "SimplifiedTopBar.qml",
|
||||
"method": "toggleStatus"
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
Item {
|
||||
id: hmdButtonContainer
|
||||
|
@ -250,6 +319,7 @@ Rectangle {
|
|||
anchors.rightMargin: 14
|
||||
width: 32
|
||||
height: width
|
||||
visible: false
|
||||
|
||||
Image {
|
||||
id: displayModeImage
|
||||
|
@ -279,11 +349,6 @@ Rectangle {
|
|||
Tablet.playSound(TabletEnums.ButtonClick);
|
||||
var displayPluginCount = Window.getDisplayPluginCount();
|
||||
if (HMD.active) {
|
||||
// This next line seems backwards and shouldn't be necessary - the NOTIFY handler should
|
||||
// result in `displayModeImage.source` changing automatically - but that's not working.
|
||||
// This is working. So, I'm keeping it.
|
||||
displayModeImage.source = "./images/vrMode.svg";
|
||||
|
||||
// Switch to desktop mode - selects first VR display plugin
|
||||
for (var i = 0; i < displayPluginCount; i++) {
|
||||
if (!Window.isDisplayPluginHmd(i)) {
|
||||
|
@ -292,11 +357,6 @@ Rectangle {
|
|||
}
|
||||
}
|
||||
} else {
|
||||
// This next line seems backwards and shouldn't be necessary - the NOTIFY handler should
|
||||
// result in `displayModeImage.source` changing automatically - but that's not working.
|
||||
// This is working. So, I'm keeping it.
|
||||
displayModeImage.source = "./images/desktopMode.svg";
|
||||
|
||||
// Switch to VR mode - selects first HMD display plugin
|
||||
for (var i = 0; i < displayPluginCount; i++) {
|
||||
if (Window.isDisplayPluginHmd(i)) {
|
||||
|
@ -306,6 +366,17 @@ Rectangle {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
// Don't show VR button unless they have a VR headset.
|
||||
var displayPluginCount = Window.getDisplayPluginCount();
|
||||
for (var i = 0; i < displayPluginCount; i++) {
|
||||
if (Window.isDisplayPluginHmd(i)) {
|
||||
hmdButtonContainer.visible = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -385,8 +456,8 @@ Rectangle {
|
|||
}
|
||||
break;
|
||||
|
||||
case "updateOutputMuted":
|
||||
outputDeviceButton.outputMuted = message.data.outputMuted;
|
||||
case "updateStatusButton":
|
||||
statusButton.currentStatus = message.data.currentStatus;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="32" height="19.001" fill="none" version="1.1" viewBox="0 0 32 19.001" xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
|
||||
<metadata>
|
||||
<rdf:RDF>
|
||||
<cc:Work rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
|
||||
<dc:title/>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<path d="m7 19h-3.542c-0.46115 0.0089-0.91905-0.0192-1.3443-0.2001-0.42525-0.1808-0.80846-0.4496-1.125-0.7892-0.3234-0.3355-0.57737-0.7329-0.74698-1.1691-0.16962-0.4362-0.25146-0.9023-0.24076-1.3709v-5.47c-0.0066251-0.46326 0.078429-0.92318 0.25019-1.3526 0.17176-0.42944 0.42674-0.81971 0.74988-1.1478 0.32313-0.32808 0.70786-0.58732 1.1316-0.76244 0.42368-0.17511 0.87772-0.26255 1.3353-0.25716h1.4718c0.03732-0.87492 0.24704-1.7335 0.61682-2.5251s0.89216-1.5005 1.5364-2.0849c1.2696-1.2214 3.1558-1.8924 4.9071-1.87l8 2.2471e-5c1.7402-0.025877 3.6023 0.64637 4.8546 1.87 1.2793 1.2015 2.0626 2.8482 2.1927 4.61h1.3178c0.946-0.01712 1.8609 0.3419 2.5484 1 0.3479 0.31321 0.625 0.69864 0.8125 1.13 0.1875 0.43142 0.2809 0.89867 0.274 1.37v5.47c0.0037 0.4767-0.091 0.9488-0.2781 1.3863-0.1871 0.4374-0.376 0.8397-0.7219 1.163-0.3346 0.3376-0.5167 0.5951-0.9542 0.7753-0.4376 0.1803-1.2083 0.2298-1.6807 0.2247h-3.3624v-12.049c0.0051-0.65734-0.1179-1.3092-0.362-1.9184-0.2441-0.60915-0.6044-1.1636-1.0603-1.6316-0.4213-0.48067-0.9384-0.86553-1.5173-1.1292-0.5788-0.26371-1.4283-0.27101-2.0631-0.27147h-8c-0.6475-0.00706-1.4451-0.00352-2.0378 0.26031-0.59274 0.26384-1.1231 0.65262-1.5556 1.1404-0.45594 0.46802-0.81626 1.0225-1.0603 1.6316-0.24406 0.60916-0.35129 1.261-0.34623 1.9184zm-3.4717-2h1.4717v-8.4793h-1.4717c-0.92847 0-1.5283 0.49-1.5283 1.48v5.47c0.01975 0.99 0.59981 1.5293 1.5283 1.5293zm26.472-6.9993c8e-3 -0.84434-0.6554-1.4883-1.5049-1.48h-1.4478v8.4793h1.4478c0.8319 0.0109 1.5175-0.722 1.5049-1.5293z" fill="#fff"/>
|
||||
</svg>
|
After (image error) Size: 2 KiB |
File diff suppressed because one or more lines are too long
After (image error) Size: 5.2 KiB |
|
@ -1190,13 +1190,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
|||
|
||||
// setup a timer for domain-server check ins
|
||||
QTimer* domainCheckInTimer = new QTimer(this);
|
||||
QWeakPointer<NodeList> nodeListWeak = nodeList;
|
||||
connect(domainCheckInTimer, &QTimer::timeout, [this, nodeListWeak] {
|
||||
auto nodeList = nodeListWeak.lock();
|
||||
if (!isServerlessMode() && nodeList) {
|
||||
nodeList->sendDomainServerCheckIn();
|
||||
}
|
||||
});
|
||||
connect(domainCheckInTimer, &QTimer::timeout, nodeList.data(), &NodeList::sendDomainServerCheckIn);
|
||||
domainCheckInTimer->start(DOMAIN_SERVER_CHECK_IN_MSECS);
|
||||
connect(this, &QCoreApplication::aboutToQuit, [domainCheckInTimer] {
|
||||
domainCheckInTimer->stop();
|
||||
|
@ -3328,6 +3322,7 @@ void Application::onDesktopRootContextCreated(QQmlContext* surfaceContext) {
|
|||
surfaceContext->setContextProperty("HMD", DependencyManager::get<HMDScriptingInterface>().data());
|
||||
surfaceContext->setContextProperty("Scene", DependencyManager::get<SceneScriptingInterface>().data());
|
||||
surfaceContext->setContextProperty("Render", RenderScriptingInterface::getInstance());
|
||||
surfaceContext->setContextProperty("PlatformInfo", PlatformInfoScriptingInterface::getInstance());
|
||||
surfaceContext->setContextProperty("Workload", _gameWorkload._engine->getConfiguration().get());
|
||||
surfaceContext->setContextProperty("Reticle", getApplicationCompositor().getReticleInterface());
|
||||
surfaceContext->setContextProperty("Snapshot", DependencyManager::get<Snapshot>().data());
|
||||
|
@ -3451,6 +3446,7 @@ void Application::setupQmlSurface(QQmlContext* surfaceContext, bool setAdditiona
|
|||
surfaceContext->setContextProperty("HiFiAbout", AboutUtil::getInstance());
|
||||
surfaceContext->setContextProperty("WalletScriptingInterface", DependencyManager::get<WalletScriptingInterface>().data());
|
||||
surfaceContext->setContextProperty("ResourceRequestObserver", DependencyManager::get<ResourceRequestObserver>().data());
|
||||
surfaceContext->setContextProperty("PlatformInfo", PlatformInfoScriptingInterface::getInstance());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3806,10 +3802,14 @@ void Application::handleSandboxStatus(QNetworkReply* reply) {
|
|||
|
||||
// If this is a first run we short-circuit the address passed in
|
||||
if (_firstRun.get()) {
|
||||
DependencyManager::get<AddressManager>()->goToEntry();
|
||||
sentTo = SENT_TO_ENTRY;
|
||||
_firstRun.set(false);
|
||||
|
||||
if (!_overrideEntry) {
|
||||
DependencyManager::get<AddressManager>()->goToEntry();
|
||||
sentTo = SENT_TO_ENTRY;
|
||||
} else {
|
||||
DependencyManager::get<AddressManager>()->loadSettings(addressLookupString);
|
||||
sentTo = SENT_TO_PREVIOUS_LOCATION;
|
||||
}
|
||||
_firstRun.set(false);
|
||||
} else {
|
||||
QString goingTo = "";
|
||||
if (addressLookupString.isEmpty()) {
|
||||
|
@ -3825,7 +3825,7 @@ void Application::handleSandboxStatus(QNetworkReply* reply) {
|
|||
DependencyManager::get<AddressManager>()->loadSettings(addressLookupString);
|
||||
sentTo = SENT_TO_PREVIOUS_LOCATION;
|
||||
}
|
||||
|
||||
|
||||
UserActivityLogger::getInstance().logAction("startup_sent_to", {
|
||||
{ "sent_to", sentTo },
|
||||
{ "sandbox_is_running", sandboxIsRunning },
|
||||
|
@ -3886,6 +3886,7 @@ void Application::setIsInterstitialMode(bool interstitialMode) {
|
|||
}
|
||||
|
||||
void Application::setIsServerlessMode(bool serverlessDomain) {
|
||||
DependencyManager::get<NodeList>()->setSendDomainServerCheckInEnabled(!serverlessDomain);
|
||||
auto tree = getEntities()->getTree();
|
||||
if (tree) {
|
||||
tree->setIsServerlessMode(serverlessDomain);
|
||||
|
@ -5439,9 +5440,7 @@ void Application::init() {
|
|||
qCDebug(interfaceapp) << "Loaded settings";
|
||||
|
||||
// fire off an immediate domain-server check in now that settings are loaded
|
||||
if (!isServerlessMode()) {
|
||||
DependencyManager::get<NodeList>()->sendDomainServerCheckIn();
|
||||
}
|
||||
QMetaObject::invokeMethod(DependencyManager::get<NodeList>().data(), "sendDomainServerCheckIn");
|
||||
|
||||
// This allows collision to be set up properly for shape entities supported by GeometryCache.
|
||||
// This is before entity setup to ensure that it's ready for whenever instance collision is initialized.
|
||||
|
@ -6404,6 +6403,7 @@ void Application::update(float deltaTime) {
|
|||
PerformanceTimer perfTimer("simulation");
|
||||
|
||||
getEntities()->preUpdate();
|
||||
_entitySimulation->removeDeadEntities();
|
||||
|
||||
auto t0 = std::chrono::high_resolution_clock::now();
|
||||
auto t1 = t0;
|
||||
|
@ -9361,6 +9361,19 @@ void Application::showUrlHandler(const QUrl& url) {
|
|||
}
|
||||
});
|
||||
}
|
||||
void Application::overrideEntry(){
|
||||
_overrideEntry = true;
|
||||
}
|
||||
void Application::forceDisplayName(const QString& displayName) {
|
||||
getMyAvatar()->setDisplayName(displayName);
|
||||
}
|
||||
void Application::forceLoginWithTokens(const QString& tokens) {
|
||||
DependencyManager::get<AccountManager>()->setAccessTokens(tokens);
|
||||
Setting::Handle<bool>(KEEP_ME_LOGGED_IN_SETTING_NAME, true).set(true);
|
||||
}
|
||||
void Application::setConfigFileURL(const QString& fileUrl) {
|
||||
DependencyManager::get<AccountManager>()->setConfigFileURL(fileUrl);
|
||||
}
|
||||
|
||||
#if defined(Q_OS_ANDROID)
|
||||
void Application::beforeEnterBackground() {
|
||||
|
|
|
@ -356,6 +356,11 @@ public:
|
|||
|
||||
void openDirectory(const QString& path);
|
||||
|
||||
void overrideEntry();
|
||||
void forceDisplayName(const QString& displayName);
|
||||
void forceLoginWithTokens(const QString& tokens);
|
||||
void setConfigFileURL(const QString& fileUrl);
|
||||
|
||||
signals:
|
||||
void svoImportRequested(const QString& url);
|
||||
|
||||
|
@ -828,5 +833,6 @@ private:
|
|||
bool _resumeAfterLoginDialogActionTaken_WasPostponed { false };
|
||||
bool _resumeAfterLoginDialogActionTaken_SafeToRun { false };
|
||||
bool _startUpFinished { false };
|
||||
bool _overrideEntry { false };
|
||||
};
|
||||
#endif // hifi_Application_h
|
||||
|
|
|
@ -49,16 +49,13 @@
|
|||
#include "DeferredLightingEffect.h"
|
||||
#include "PickManager.h"
|
||||
|
||||
#include "LightingModel.h"
|
||||
#include "AmbientOcclusionEffect.h"
|
||||
#include "RenderShadowTask.h"
|
||||
#include "AntialiasingEffect.h"
|
||||
|
||||
#include "scripting/SettingsScriptingInterface.h"
|
||||
#if defined(Q_OS_MAC) || defined(Q_OS_WIN)
|
||||
#include "SpeechRecognizer.h"
|
||||
#endif
|
||||
|
||||
#include "scripting/RenderScriptingInterface.h"
|
||||
|
||||
extern bool DEV_DECIMATE_TEXTURES;
|
||||
|
||||
Menu* Menu::getInstance() {
|
||||
|
@ -367,45 +364,14 @@ Menu::Menu() {
|
|||
// Developer > Render >>>
|
||||
MenuWrapper* renderOptionsMenu = developerMenu->addMenu("Render");
|
||||
|
||||
action = addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::AntiAliasing, 0, true);
|
||||
connect(action, &QAction::triggered, [action] {
|
||||
auto renderConfig = qApp->getRenderEngine()->getConfiguration();
|
||||
if (renderConfig) {
|
||||
auto mainViewJitterCamConfig = renderConfig->getConfig<JitterSample>("RenderMainView.JitterCam");
|
||||
auto mainViewAntialiasingConfig = renderConfig->getConfig<Antialiasing>("RenderMainView.Antialiasing");
|
||||
if (mainViewJitterCamConfig && mainViewAntialiasingConfig) {
|
||||
if (action->isChecked()) {
|
||||
mainViewJitterCamConfig->play();
|
||||
mainViewAntialiasingConfig->setDebugFXAA(false);
|
||||
} else {
|
||||
mainViewJitterCamConfig->none();
|
||||
mainViewAntialiasingConfig->setDebugFXAA(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::AntiAliasing, 0, RenderScriptingInterface::getInstance()->getAntialiasingEnabled(),
|
||||
RenderScriptingInterface::getInstance(), SLOT(setAntialiasingEnabled(bool)));
|
||||
|
||||
action = addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::Shadows, 0, true);
|
||||
connect(action, &QAction::triggered, [action] {
|
||||
auto renderConfig = qApp->getRenderEngine()->getConfiguration();
|
||||
if (renderConfig) {
|
||||
auto lightingModelConfig = renderConfig->getConfig<MakeLightingModel>("RenderMainView.LightingModel");
|
||||
if (lightingModelConfig) {
|
||||
lightingModelConfig->setShadow(action->isChecked());
|
||||
}
|
||||
}
|
||||
});
|
||||
addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::Shadows, 0, RenderScriptingInterface::getInstance()->getShadowsEnabled(),
|
||||
RenderScriptingInterface::getInstance(), SLOT(setShadowsEnabled(bool)));
|
||||
|
||||
action = addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::AmbientOcclusion, 0, false);
|
||||
connect(action, &QAction::triggered, [action] {
|
||||
auto renderConfig = qApp->getRenderEngine()->getConfiguration();
|
||||
if (renderConfig) {
|
||||
auto lightingModelConfig = renderConfig->getConfig<MakeLightingModel>("RenderMainView.LightingModel");
|
||||
if (lightingModelConfig) {
|
||||
lightingModelConfig->setAmbientOcclusion(action->isChecked());
|
||||
}
|
||||
}
|
||||
});
|
||||
addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::AmbientOcclusion, 0, RenderScriptingInterface::getInstance()->getAmbientOcclusionEnabled(),
|
||||
RenderScriptingInterface::getInstance(), SLOT(setAmbientOcclusionEnabled(bool)));
|
||||
|
||||
addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::WorldAxes);
|
||||
addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::DefaultSkybox, 0, true);
|
||||
|
@ -522,6 +488,12 @@ Menu::Menu() {
|
|||
addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::ComputeBlendshapes, 0, true,
|
||||
DependencyManager::get<ModelBlender>().data(), SLOT(setComputeBlendshapes(bool)));
|
||||
|
||||
{
|
||||
auto drawStatusConfig = qApp->getRenderEngine()->getConfiguration()->getConfig<render::DrawStatus>("RenderMainView.DrawStatus");
|
||||
addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::HighlightTransitions, 0, false,
|
||||
drawStatusConfig, SLOT(setShowFade(bool)));
|
||||
}
|
||||
|
||||
// Developer > Assets >>>
|
||||
// Menu item is not currently needed but code should be kept in case it proves useful again at some stage.
|
||||
//#define WANT_ASSET_MIGRATION
|
||||
|
|
|
@ -228,6 +228,7 @@ namespace MenuOption {
|
|||
const QString NotificationSoundsTablet = "play_notification_sounds_tablet";
|
||||
const QString ForceCoarsePicking = "Force Coarse Picking";
|
||||
const QString ComputeBlendshapes = "Compute Blendshapes";
|
||||
const QString HighlightTransitions = "Highlight Transitions";
|
||||
}
|
||||
|
||||
#endif // hifi_Menu_h
|
||||
|
|
|
@ -412,7 +412,7 @@ AvatarSharedPointer AvatarManager::newSharedAvatar(const QUuid& sessionUUID) {
|
|||
auto otherAvatar = new OtherAvatar(qApp->thread());
|
||||
otherAvatar->setSessionUUID(sessionUUID);
|
||||
auto nodeList = DependencyManager::get<NodeList>();
|
||||
if (!nodeList || !nodeList->isIgnoringNode(sessionUUID)) {
|
||||
if (nodeList && !nodeList->isIgnoringNode(sessionUUID)) {
|
||||
otherAvatar->createOrb();
|
||||
}
|
||||
return AvatarSharedPointer(otherAvatar, [](OtherAvatar* ptr) { ptr->deleteLater(); });
|
||||
|
@ -521,6 +521,7 @@ void AvatarManager::buildPhysicsTransaction(PhysicsEngine::Transaction& transact
|
|||
}
|
||||
}
|
||||
}
|
||||
_otherAvatarsToChangeInPhysics.clear();
|
||||
}
|
||||
|
||||
void AvatarManager::handleProcessedPhysicsTransaction(PhysicsEngine::Transaction& transaction) {
|
||||
|
@ -645,7 +646,7 @@ void AvatarManager::clearOtherAvatars() {
|
|||
}
|
||||
|
||||
void AvatarManager::deleteAllAvatars() {
|
||||
assert(_otherAvatarsToChangeInPhysics.empty());
|
||||
_otherAvatarsToChangeInPhysics.clear();
|
||||
QReadLocker locker(&_hashLock);
|
||||
AvatarHash::iterator avatarIterator = _avatarHash.begin();
|
||||
while (avatarIterator != _avatarHash.end()) {
|
||||
|
|
|
@ -2367,6 +2367,11 @@ void MyAvatar::clearJointsData() {
|
|||
}
|
||||
|
||||
void MyAvatar::setSkeletonModelURL(const QUrl& skeletonModelURL) {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QMetaObject::invokeMethod(this, "setSkeletonModelURL", Q_ARG(const QUrl&, skeletonModelURL));
|
||||
return;
|
||||
}
|
||||
|
||||
_skeletonModelChangeCount++;
|
||||
int skeletonModelChangeCount = _skeletonModelChangeCount;
|
||||
|
||||
|
|
|
@ -2409,7 +2409,7 @@ private:
|
|||
void updateEyeContactTarget(float deltaTime);
|
||||
|
||||
// These are made private for MyAvatar so that you will use the "use" methods instead
|
||||
virtual void setSkeletonModelURL(const QUrl& skeletonModelURL) override;
|
||||
Q_INVOKABLE virtual void setSkeletonModelURL(const QUrl& skeletonModelURL) override;
|
||||
|
||||
virtual void updatePalms() override {}
|
||||
void lateUpdatePalms();
|
||||
|
|
|
@ -62,7 +62,7 @@ void OtherAvatar::removeOrb() {
|
|||
}
|
||||
|
||||
void OtherAvatar::updateOrbPosition() {
|
||||
if (_otherAvatarOrbMeshPlaceholderID.isNull()) {
|
||||
if (!_otherAvatarOrbMeshPlaceholderID.isNull()) {
|
||||
EntityItemProperties properties;
|
||||
properties.setPosition(getHead()->getPosition());
|
||||
DependencyManager::get<EntityScriptingInterface>()->editEntity(_otherAvatarOrbMeshPlaceholderID, properties);
|
||||
|
|
|
@ -654,7 +654,7 @@ QString Wallet::signWithKey(const QByteArray& text, const QString& key) {
|
|||
EC_KEY* ecPrivateKey = NULL;
|
||||
|
||||
if ((ecPrivateKey = readPrivateKey(keyFilePath()))) {
|
||||
unsigned char* sig = new unsigned char[ECDSA_size(ecPrivateKey)];
|
||||
const auto sig = std::make_unique<unsigned char[]>(ECDSA_size(ecPrivateKey));
|
||||
|
||||
unsigned int signatureBytes = 0;
|
||||
|
||||
|
@ -663,10 +663,10 @@ QString Wallet::signWithKey(const QByteArray& text, const QString& key) {
|
|||
QByteArray hashedPlaintext = QCryptographicHash::hash(text, QCryptographicHash::Sha256);
|
||||
|
||||
int retrn = ECDSA_sign(0, reinterpret_cast<const unsigned char*>(hashedPlaintext.constData()), hashedPlaintext.size(),
|
||||
sig, &signatureBytes, ecPrivateKey);
|
||||
sig.get(), &signatureBytes, ecPrivateKey);
|
||||
|
||||
EC_KEY_free(ecPrivateKey);
|
||||
QByteArray signature(reinterpret_cast<const char*>(sig), signatureBytes);
|
||||
QByteArray signature(reinterpret_cast<const char*>(sig.get()), signatureBytes);
|
||||
if (retrn != -1) {
|
||||
return signature.toBase64();
|
||||
}
|
||||
|
|
|
@ -75,6 +75,7 @@ int main(int argc, const char* argv[]) {
|
|||
QCommandLineOption helpOption = parser.addHelpOption();
|
||||
|
||||
QCommandLineOption urlOption("url", "", "value");
|
||||
QCommandLineOption noLauncherOption("no-launcher", "Do not execute the launcher");
|
||||
QCommandLineOption noUpdaterOption("no-updater", "Do not show auto-updater");
|
||||
QCommandLineOption checkMinSpecOption("checkMinSpec", "Check if machine meets minimum specifications");
|
||||
QCommandLineOption runServerOption("runServer", "Whether to run the server");
|
||||
|
@ -82,8 +83,11 @@ int main(int argc, const char* argv[]) {
|
|||
QCommandLineOption allowMultipleInstancesOption("allowMultipleInstances", "Allow multiple instances to run");
|
||||
QCommandLineOption overrideAppLocalDataPathOption("cache", "set test cache <dir>", "dir");
|
||||
QCommandLineOption overrideScriptsPathOption(SCRIPTS_SWITCH, "set scripts <path>", "path");
|
||||
QCommandLineOption responseTokensOption("tokens", "set response tokens <json>", "json");
|
||||
QCommandLineOption displayNameOption("displayName", "set user display name <string>", "string");
|
||||
|
||||
parser.addOption(urlOption);
|
||||
parser.addOption(noLauncherOption);
|
||||
parser.addOption(noUpdaterOption);
|
||||
parser.addOption(checkMinSpecOption);
|
||||
parser.addOption(runServerOption);
|
||||
|
@ -91,6 +95,8 @@ int main(int argc, const char* argv[]) {
|
|||
parser.addOption(overrideAppLocalDataPathOption);
|
||||
parser.addOption(overrideScriptsPathOption);
|
||||
parser.addOption(allowMultipleInstancesOption);
|
||||
parser.addOption(responseTokensOption);
|
||||
parser.addOption(displayNameOption);
|
||||
|
||||
if (!parser.parse(arguments)) {
|
||||
std::cout << parser.errorText().toStdString() << std::endl; // Avoid Qt log spam
|
||||
|
@ -106,6 +112,52 @@ int main(int argc, const char* argv[]) {
|
|||
Q_UNREACHABLE();
|
||||
}
|
||||
|
||||
QString applicationPath;
|
||||
{
|
||||
// A temporary application instance is needed to get the location of the running executable
|
||||
// Tests using high_resolution_clock show that this takes about 30-50 microseconds (on my machine, YMMV)
|
||||
// If we wanted to avoid the QCoreApplication, we would need to write our own
|
||||
// cross-platform implementation.
|
||||
QCoreApplication tempApp(argc, const_cast<char**>(argv));
|
||||
applicationPath = QCoreApplication::applicationDirPath();
|
||||
}
|
||||
|
||||
static const QString APPLICATION_CONFIG_FILENAME = "config.json";
|
||||
QDir applicationDir(applicationPath);
|
||||
QString configFileName = applicationDir.filePath(APPLICATION_CONFIG_FILENAME);
|
||||
QFile configFile(configFileName);
|
||||
QString launcherPath;
|
||||
|
||||
if (configFile.exists()) {
|
||||
if (!configFile.open(QIODevice::ReadOnly)) {
|
||||
qWarning() << "Found application config, but could not open it";
|
||||
} else {
|
||||
auto contents = configFile.readAll();
|
||||
QJsonParseError error;
|
||||
|
||||
auto doc = QJsonDocument::fromJson(contents, &error);
|
||||
if (error.error) {
|
||||
qWarning() << "Found application config, but could not parse it: " << error.errorString();
|
||||
} else {
|
||||
static const QString LAUNCHER_PATH_KEY = "launcherPath";
|
||||
launcherPath = doc.object()[LAUNCHER_PATH_KEY].toString();
|
||||
if (!launcherPath.isEmpty()) {
|
||||
if (!parser.isSet(noLauncherOption)) {
|
||||
qDebug() << "Found a launcherPath in application config. Starting launcher.";
|
||||
QProcess launcher;
|
||||
launcher.setProgram(launcherPath);
|
||||
launcher.startDetached();
|
||||
return 0;
|
||||
} else {
|
||||
qDebug() << "Found a launcherPath in application config, but the launcher"
|
||||
" has been suppressed. Continuing normal execution.";
|
||||
}
|
||||
configFile.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Early check for --traceFile argument
|
||||
auto tracer = DependencyManager::set<tracing::Tracer>();
|
||||
const char * traceFile = nullptr;
|
||||
|
@ -353,6 +405,24 @@ int main(int argc, const char* argv[]) {
|
|||
|
||||
printSystemInformation();
|
||||
|
||||
auto appPointer = dynamic_cast<Application*>(&app);
|
||||
if (appPointer) {
|
||||
if (parser.isSet(urlOption)) {
|
||||
appPointer->overrideEntry();
|
||||
}
|
||||
if (parser.isSet(displayNameOption)) {
|
||||
QString displayName = QString(parser.value(displayNameOption));
|
||||
appPointer->forceDisplayName(displayName);
|
||||
}
|
||||
if (!launcherPath.isEmpty()) {
|
||||
appPointer->setConfigFileURL(configFileName);
|
||||
}
|
||||
if (parser.isSet(responseTokensOption)) {
|
||||
QString tokens = QString(parser.value(responseTokensOption));
|
||||
appPointer->forceLoginWithTokens(tokens);
|
||||
}
|
||||
}
|
||||
|
||||
QTranslator translator;
|
||||
translator.load("i18n/interface_en");
|
||||
app.installTranslator(&translator);
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
//
|
||||
|
||||
#include "SafeLanding.h"
|
||||
|
||||
#include <SharedUtil.h>
|
||||
|
||||
#include "EntityTreeRenderer.h"
|
||||
|
@ -35,24 +34,26 @@ bool SafeLanding::SequenceLessThan::operator()(const int& a, const int& b) const
|
|||
}
|
||||
|
||||
void SafeLanding::startEntitySequence(QSharedPointer<EntityTreeRenderer> entityTreeRenderer) {
|
||||
auto entityTree = entityTreeRenderer->getTree();
|
||||
|
||||
if (entityTree) {
|
||||
Locker lock(_lock);
|
||||
_entityTree = entityTree;
|
||||
_trackedEntities.clear();
|
||||
_trackingEntities = true;
|
||||
_maxTrackedEntityCount = 0;
|
||||
connect(std::const_pointer_cast<EntityTree>(_entityTree).get(),
|
||||
&EntityTree::addingEntity, this, &SafeLanding::addTrackedEntity);
|
||||
connect(std::const_pointer_cast<EntityTree>(_entityTree).get(),
|
||||
&EntityTree::deletingEntity, this, &SafeLanding::deleteTrackedEntity);
|
||||
if (!entityTreeRenderer.isNull()) {
|
||||
auto entityTree = entityTreeRenderer->getTree();
|
||||
if (entityTree) {
|
||||
Locker lock(_lock);
|
||||
_entityTreeRenderer = entityTreeRenderer;
|
||||
_trackedEntities.clear();
|
||||
_trackingEntities = true;
|
||||
_maxTrackedEntityCount = 0;
|
||||
connect(std::const_pointer_cast<EntityTree>(entityTree).get(),
|
||||
&EntityTree::addingEntity, this, &SafeLanding::addTrackedEntity, Qt::DirectConnection);
|
||||
connect(std::const_pointer_cast<EntityTree>(entityTree).get(),
|
||||
&EntityTree::deletingEntity, this, &SafeLanding::deleteTrackedEntity);
|
||||
|
||||
_sequenceNumbers.clear();
|
||||
_initialStart = INVALID_SEQUENCE;
|
||||
_initialEnd = INVALID_SEQUENCE;
|
||||
_startTime = usecTimestampNow();
|
||||
EntityTreeRenderer::setEntityLoadingPriorityFunction(&ElevatedPriority);
|
||||
_sequenceNumbers.clear();
|
||||
_initialStart = INVALID_SEQUENCE;
|
||||
_initialEnd = INVALID_SEQUENCE;
|
||||
_startTime = usecTimestampNow();
|
||||
EntityTreeRenderer::setEntityLoadingPriorityFunction(&ElevatedPriority);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -70,7 +71,12 @@ void SafeLanding::stopEntitySequence() {
|
|||
void SafeLanding::addTrackedEntity(const EntityItemID& entityID) {
|
||||
if (_trackingEntities) {
|
||||
Locker lock(_lock);
|
||||
EntityItemPointer entity = _entityTree->findEntityByID(entityID);
|
||||
|
||||
if (_entityTreeRenderer.isNull() || _entityTreeRenderer->getTree() == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
EntityItemPointer entity = _entityTreeRenderer->getTree()->findEntityByID(entityID);
|
||||
|
||||
if (entity && !entity->isLocalEntity() && entity->getCreated() < _startTime) {
|
||||
|
||||
|
@ -111,7 +117,7 @@ bool SafeLanding::isLoadSequenceComplete() {
|
|||
Locker lock(_lock);
|
||||
_initialStart = INVALID_SEQUENCE;
|
||||
_initialEnd = INVALID_SEQUENCE;
|
||||
_entityTree = nullptr;
|
||||
_entityTreeRenderer.clear();
|
||||
_trackingEntities = false; // Don't track anything else that comes in.
|
||||
EntityTreeRenderer::setEntityLoadingPriorityFunction(StandardPriority);
|
||||
}
|
||||
|
@ -158,7 +164,7 @@ bool SafeLanding::isSequenceNumbersComplete() {
|
|||
return false;
|
||||
}
|
||||
|
||||
bool isEntityPhysicsReady(const EntityItemPointer& entity) {
|
||||
bool SafeLanding::isEntityPhysicsReady(const EntityItemPointer& entity) {
|
||||
if (entity && !entity->getCollisionless()) {
|
||||
const auto& entityType = entity->getType();
|
||||
if (entityType == EntityTypes::Model) {
|
||||
|
@ -168,7 +174,10 @@ bool isEntityPhysicsReady(const EntityItemPointer& entity) {
|
|||
bool hasAABox;
|
||||
entity->getAABox(hasAABox);
|
||||
if (hasAABox && downloadedCollisionTypes.count(modelEntity->getShapeType()) != 0) {
|
||||
return (!entity->shouldBePhysical() || entity->isInPhysicsSimulation() || modelEntity->computeShapeFailedToLoad());
|
||||
auto space = _entityTreeRenderer->getWorkloadSpace();
|
||||
uint8_t region = space ? space->getRegion(entity->getSpaceIndex()) : (uint8_t)workload::Region::INVALID;
|
||||
bool shouldBePhysical = region < workload::Region::R3 && entity->shouldBePhysical();
|
||||
return (!shouldBePhysical || entity->isInPhysicsSimulation() || modelEntity->computeShapeFailedToLoad());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,13 +38,14 @@ private slots:
|
|||
|
||||
private:
|
||||
bool isSequenceNumbersComplete();
|
||||
bool isEntityPhysicsReady(const EntityItemPointer& entity);
|
||||
void debugDumpSequenceIDs() const;
|
||||
bool isEntityLoadingComplete();
|
||||
|
||||
std::mutex _lock;
|
||||
using Locker = std::lock_guard<std::mutex>;
|
||||
bool _trackingEntities { false };
|
||||
EntityTreePointer _entityTree;
|
||||
QSharedPointer<EntityTreeRenderer> _entityTreeRenderer;
|
||||
using EntityMap = std::map<EntityItemID, EntityItemPointer>;
|
||||
EntityMap _trackedEntities;
|
||||
|
||||
|
|
|
@ -400,10 +400,19 @@ void Audio::setReverbOptions(const AudioEffectOptions* options) {
|
|||
}
|
||||
|
||||
void Audio::setAvatarGain(float gain) {
|
||||
bool changed = false;
|
||||
if (getAvatarGain() != gain) {
|
||||
changed = true;
|
||||
}
|
||||
|
||||
withWriteLock([&] {
|
||||
// ask the NodeList to set the master avatar gain
|
||||
DependencyManager::get<NodeList>()->setAvatarGain(QUuid(), gain);
|
||||
});
|
||||
|
||||
if (changed) {
|
||||
emit avatarGainChanged(gain);
|
||||
}
|
||||
}
|
||||
|
||||
float Audio::getAvatarGain() {
|
||||
|
@ -413,10 +422,19 @@ float Audio::getAvatarGain() {
|
|||
}
|
||||
|
||||
void Audio::setInjectorGain(float gain) {
|
||||
bool changed = false;
|
||||
if (getInjectorGain() != gain) {
|
||||
changed = true;
|
||||
}
|
||||
|
||||
withWriteLock([&] {
|
||||
// ask the NodeList to set the audio injector gain
|
||||
DependencyManager::get<NodeList>()->setInjectorGain(gain);
|
||||
});
|
||||
|
||||
if (changed) {
|
||||
emit serverInjectorGainChanged(gain);
|
||||
}
|
||||
}
|
||||
|
||||
float Audio::getInjectorGain() {
|
||||
|
@ -426,6 +444,11 @@ float Audio::getInjectorGain() {
|
|||
}
|
||||
|
||||
void Audio::setLocalInjectorGain(float gain) {
|
||||
bool changed = false;
|
||||
if (getLocalInjectorGain() != gain) {
|
||||
changed = true;
|
||||
}
|
||||
|
||||
withWriteLock([&] {
|
||||
if (_localInjectorGain != gain) {
|
||||
_localInjectorGain = gain;
|
||||
|
@ -436,6 +459,11 @@ void Audio::setLocalInjectorGain(float gain) {
|
|||
DependencyManager::get<AudioClient>()->setLocalInjectorGain(gain);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
if (changed) {
|
||||
emit localInjectorGainChanged(gain);
|
||||
}
|
||||
}
|
||||
|
||||
float Audio::getLocalInjectorGain() {
|
||||
|
@ -445,6 +473,11 @@ float Audio::getLocalInjectorGain() {
|
|||
}
|
||||
|
||||
void Audio::setSystemInjectorGain(float gain) {
|
||||
bool changed = false;
|
||||
if (getSystemInjectorGain() != gain) {
|
||||
changed = true;
|
||||
}
|
||||
|
||||
withWriteLock([&] {
|
||||
if (_systemInjectorGain != gain) {
|
||||
_systemInjectorGain = gain;
|
||||
|
@ -455,6 +488,10 @@ void Audio::setSystemInjectorGain(float gain) {
|
|||
DependencyManager::get<AudioClient>()->setSystemInjectorGain(gain);
|
||||
}
|
||||
});
|
||||
|
||||
if (changed) {
|
||||
emit systemInjectorGainChanged(gain);
|
||||
}
|
||||
}
|
||||
|
||||
float Audio::getSystemInjectorGain() {
|
||||
|
|
|
@ -66,6 +66,10 @@ class Audio : public AudioScriptingInterface, protected ReadWriteLockable {
|
|||
* @property {boolean} pushToTalkHMD - <code>true</code> if HMD push-to-talk is enabled, otherwise <code>false</code>.
|
||||
* @property {boolean} pushingToTalk - <code>true</code> if the user is currently pushing-to-talk, otherwise
|
||||
* <code>false</code>.
|
||||
* @property {float} avatarGain - The gain (relative volume) that avatars' voices are played at. This gain is used at the server.
|
||||
* @property {float} localInjectorGain - The gain (relative volume) that local injectors (local environment sounds) are played at.
|
||||
* @property {float} serverInjectorGain - The gain (relative volume) that server injectors (server environment sounds) are played at. This gain is used at the server.
|
||||
* @property {float} systemInjectorGain - The gain (relative volume) that system sounds are played at.
|
||||
*
|
||||
* @comment The following properties are from AudioScriptingInterface.h.
|
||||
* @property {boolean} isStereoInput - <code>true</code> if the input audio is being used in stereo, otherwise
|
||||
|
@ -90,6 +94,10 @@ class Audio : public AudioScriptingInterface, protected ReadWriteLockable {
|
|||
Q_PROPERTY(bool pushToTalkDesktop READ getPTTDesktop WRITE setPTTDesktop NOTIFY pushToTalkDesktopChanged)
|
||||
Q_PROPERTY(bool pushToTalkHMD READ getPTTHMD WRITE setPTTHMD NOTIFY pushToTalkHMDChanged)
|
||||
Q_PROPERTY(bool pushingToTalk READ getPushingToTalk WRITE setPushingToTalk NOTIFY pushingToTalkChanged)
|
||||
Q_PROPERTY(float avatarGain READ getAvatarGain WRITE setAvatarGain NOTIFY avatarGainChanged)
|
||||
Q_PROPERTY(float localInjectorGain READ getLocalInjectorGain WRITE setLocalInjectorGain NOTIFY localInjectorGainChanged)
|
||||
Q_PROPERTY(float serverInjectorGain READ getInjectorGain WRITE setInjectorGain NOTIFY serverInjectorGainChanged)
|
||||
Q_PROPERTY(float systemInjectorGain READ getSystemInjectorGain WRITE setSystemInjectorGain NOTIFY systemInjectorGainChanged)
|
||||
|
||||
public:
|
||||
static QString AUDIO;
|
||||
|
@ -412,6 +420,38 @@ signals:
|
|||
*/
|
||||
void pushingToTalkChanged(bool talking);
|
||||
|
||||
/**jsdoc
|
||||
* Triggered when the avatar gain changes.
|
||||
* @function Audio.avatarGainChanged
|
||||
* @param {float} gain - The new avatar gain value.
|
||||
* @returns {Signal}
|
||||
*/
|
||||
void avatarGainChanged(float gain);
|
||||
|
||||
/**jsdoc
|
||||
* Triggered when the local injector gain changes.
|
||||
* @function Audio.localInjectorGainChanged
|
||||
* @param {float} gain - The new local injector gain value.
|
||||
* @returns {Signal}
|
||||
*/
|
||||
void localInjectorGainChanged(float gain);
|
||||
|
||||
/**jsdoc
|
||||
* Triggered when the server injector gain changes.
|
||||
* @function Audio.serverInjectorGainChanged
|
||||
* @param {float} gain - The new server injector gain value.
|
||||
* @returns {Signal}
|
||||
*/
|
||||
void serverInjectorGainChanged(float gain);
|
||||
|
||||
/**jsdoc
|
||||
* Triggered when the system injector gain changes.
|
||||
* @function Audio.systemInjectorGainChanged
|
||||
* @param {float} gain - The new system injector gain value.
|
||||
* @returns {Signal}
|
||||
*/
|
||||
void systemInjectorGainChanged(float gain);
|
||||
|
||||
public slots:
|
||||
|
||||
/**jsdoc
|
||||
|
|
|
@ -10,6 +10,9 @@
|
|||
#include <shared/GlobalAppProperties.h>
|
||||
#include <thread>
|
||||
|
||||
#include <platform/Platform.h>
|
||||
#include <platform/Profiler.h>
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
#include <Windows.h>
|
||||
#elif defined Q_OS_MAC
|
||||
|
@ -21,6 +24,17 @@ PlatformInfoScriptingInterface* PlatformInfoScriptingInterface::getInstance() {
|
|||
return &sharedInstance;
|
||||
}
|
||||
|
||||
|
||||
PlatformInfoScriptingInterface::PlatformInfoScriptingInterface() {
|
||||
platform::create();
|
||||
if (!platform::enumeratePlatform()) {
|
||||
}
|
||||
}
|
||||
|
||||
PlatformInfoScriptingInterface::~PlatformInfoScriptingInterface() {
|
||||
platform::destroy();
|
||||
}
|
||||
|
||||
QString PlatformInfoScriptingInterface::getOperatingSystemType() {
|
||||
#ifdef Q_OS_WIN
|
||||
return "WINDOWS";
|
||||
|
@ -149,3 +163,52 @@ bool PlatformInfoScriptingInterface::isStandalone() {
|
|||
return qApp->property(hifi::properties::STANDALONE).toBool();
|
||||
#endif
|
||||
}
|
||||
|
||||
int PlatformInfoScriptingInterface::getNumCPUs() {
|
||||
return platform::getNumCPUs();
|
||||
}
|
||||
|
||||
QString PlatformInfoScriptingInterface::getCPU(int index) {
|
||||
auto desc = platform::getCPU(index);
|
||||
return QString(desc.dump().c_str());
|
||||
}
|
||||
|
||||
int PlatformInfoScriptingInterface::getNumGPUs() {
|
||||
return platform::getNumGPUs();
|
||||
}
|
||||
|
||||
QString PlatformInfoScriptingInterface::getGPU(int index) {
|
||||
auto desc = platform::getGPU(index);
|
||||
return QString(desc.dump().c_str());
|
||||
}
|
||||
|
||||
int PlatformInfoScriptingInterface::getNumDisplays() {
|
||||
return platform::getNumDisplays();
|
||||
}
|
||||
|
||||
QString PlatformInfoScriptingInterface::getDisplay(int index) {
|
||||
auto desc = platform::getDisplay(index);
|
||||
return QString(desc.dump().c_str());
|
||||
}
|
||||
|
||||
QString PlatformInfoScriptingInterface::getMemory() {
|
||||
auto desc = platform::getMemory(0);
|
||||
return QString(desc.dump().c_str());
|
||||
}
|
||||
|
||||
QString PlatformInfoScriptingInterface::getComputer() {
|
||||
auto desc = platform::getComputer();
|
||||
return QString(desc.dump().c_str());
|
||||
}
|
||||
|
||||
|
||||
PlatformInfoScriptingInterface::PlatformTier PlatformInfoScriptingInterface::getTierProfiled() {
|
||||
return (PlatformInfoScriptingInterface::PlatformTier) platform::Profiler::profilePlatform();
|
||||
}
|
||||
|
||||
QStringList PlatformInfoScriptingInterface::getPlatformTierNames() {
|
||||
static const QStringList platformTierNames = { "UNKNWON", "LOW", "MID", "HIGH" };
|
||||
return platformTierNames;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#ifndef hifi_PlatformInfoScriptingInterface_h
|
||||
#define hifi_PlatformInfoScriptingInterface_h
|
||||
|
||||
#include <platform/Profiler.h>
|
||||
#include <QtCore/QObject>
|
||||
|
||||
class QScriptValue;
|
||||
|
@ -25,6 +26,20 @@ class QScriptValue;
|
|||
class PlatformInfoScriptingInterface : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
|
||||
public:
|
||||
PlatformInfoScriptingInterface();
|
||||
virtual ~PlatformInfoScriptingInterface();
|
||||
|
||||
// Platform tier enum type
|
||||
enum PlatformTier {
|
||||
UNKNOWN = platform::Profiler::Tier::UNKNOWN,
|
||||
LOW = platform::Profiler::Tier::LOW,
|
||||
MID = platform::Profiler::Tier::MID,
|
||||
HIGH = platform::Profiler::Tier::HIGH,
|
||||
};
|
||||
Q_ENUM(PlatformTier);
|
||||
|
||||
public slots:
|
||||
/**jsdoc
|
||||
* @function PlatformInfo.getInstance
|
||||
|
@ -98,6 +113,96 @@ public slots:
|
|||
* @returns {boolean} <code>true</code> if Interface is running on a stand-alone device, <code>false</code> if it isn't.
|
||||
*/
|
||||
bool isStandalone();
|
||||
|
||||
/**jsdoc
|
||||
* Get the number of CPUs.
|
||||
* @function PlatformInfo.getNumCPUs
|
||||
* @returns {number} The number of CPUs detected on the hardware platform.
|
||||
*/
|
||||
int getNumCPUs();
|
||||
|
||||
/**jsdoc
|
||||
* Get the description of the CPU at the index parameter
|
||||
* expected fields are:
|
||||
* - cpuVendor...
|
||||
* @param index The index of the CPU of the platform
|
||||
* @function PlatformInfo.getCPU
|
||||
* @returns {string} The CPU description json field
|
||||
*/
|
||||
QString getCPU(int index);
|
||||
|
||||
/**jsdoc
|
||||
* Get the number of GPUs.
|
||||
* @function PlatformInfo.getNumGPUs
|
||||
* @returns {number} The number of GPUs detected on the hardware platform.
|
||||
*/
|
||||
int getNumGPUs();
|
||||
|
||||
/**jsdoc
|
||||
* Get the description of the GPU at the index parameter
|
||||
* expected fields are:
|
||||
* - gpuVendor...
|
||||
* @param index The index of the GPU of the platform
|
||||
* @function PlatformInfo.getGPU
|
||||
* @returns {string} The GPU description json field
|
||||
*/
|
||||
QString getGPU(int index);
|
||||
|
||||
/**jsdoc
|
||||
* Get the number of Displays.
|
||||
* @function PlatformInfo.getNumDisplays
|
||||
* @returns {number} The number of Displays detected on the hardware platform.
|
||||
*/
|
||||
int getNumDisplays();
|
||||
|
||||
/**jsdoc
|
||||
* Get the description of the Display at the index parameter
|
||||
* expected fields are:
|
||||
* - DisplayVendor...
|
||||
* @param index The index of the Display of the platform
|
||||
* @function PlatformInfo.getDisplay
|
||||
* @returns {string} The Display description json field
|
||||
*/
|
||||
QString getDisplay(int index);
|
||||
|
||||
/**jsdoc
|
||||
* Get the description of the Memory
|
||||
* expected fields are:
|
||||
* - MemoryVendor...
|
||||
* @function PlatformInfo.getMemory
|
||||
* @returns {string} The Memory description json field
|
||||
*/
|
||||
QString getMemory();
|
||||
|
||||
/**jsdoc
|
||||
* Get the description of the Computer
|
||||
* expected fields are:
|
||||
* - ComputerVendor...
|
||||
* @function PlatformInfo.getComputer
|
||||
* @returns {string} The Computer description json field
|
||||
*/
|
||||
QString getComputer();
|
||||
|
||||
|
||||
/**jsdoc
|
||||
* Get the Platform TIer profiled on startup of the Computer
|
||||
* Platform Tier is an ineger/enum value:
|
||||
* LOW = 0, MID = 1, HIGH = 2
|
||||
* @function PlatformInfo.getTierProfiled
|
||||
* @returns {number} The Platform Tier profiled on startup.
|
||||
*/
|
||||
PlatformTier getTierProfiled();
|
||||
|
||||
/**jsdoc
|
||||
* Get the Platform Tier possible Names as an array of strings
|
||||
* Platform Tier is an ineger/enum value:
|
||||
* LOW = 0, MID = 1, HIGH = 2
|
||||
* @function PlatformInfo.getPlatformTierNames
|
||||
* @returns {string} The array of names matching the number returned from PlatformInfo.getTierProfiled
|
||||
*/
|
||||
QStringList getPlatformTierNames();
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif // hifi_PlatformInfoScriptingInterface_h
|
||||
|
|
|
@ -7,6 +7,9 @@
|
|||
//
|
||||
#include "RenderScriptingInterface.h"
|
||||
|
||||
#include "LightingModel.h"
|
||||
#include "AntialiasingEffect.h"
|
||||
|
||||
const QString DEFERRED = "deferred";
|
||||
const QString FORWARD = "forward";
|
||||
|
||||
|
@ -17,6 +20,9 @@ RenderScriptingInterface* RenderScriptingInterface::getInstance() {
|
|||
|
||||
RenderScriptingInterface::RenderScriptingInterface() {
|
||||
setRenderMethod((render::Args::RenderMethod)_renderMethodSetting.get() == render::Args::RenderMethod::DEFERRED ? DEFERRED : FORWARD);
|
||||
setShadowsEnabled(_shadowsEnabledSetting.get());
|
||||
setAmbientOcclusionEnabled(_ambientOcclusionEnabledSetting.get());
|
||||
setAntialiasingEnabled(_antialiasingEnabledSetting.get());
|
||||
}
|
||||
|
||||
QString RenderScriptingInterface::getRenderMethod() {
|
||||
|
@ -24,6 +30,11 @@ QString RenderScriptingInterface::getRenderMethod() {
|
|||
}
|
||||
|
||||
void RenderScriptingInterface::setRenderMethod(const QString& renderMethod) {
|
||||
render::Args::RenderMethod newMethod = renderMethod == FORWARD ? render::Args::RenderMethod::FORWARD : render::Args::RenderMethod::DEFERRED;
|
||||
if (_renderMethodSetting.get() == newMethod) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QMetaObject::invokeMethod(this, "setRenderMethod", Q_ARG(const QString&, renderMethod));
|
||||
return;
|
||||
|
@ -31,14 +42,81 @@ void RenderScriptingInterface::setRenderMethod(const QString& renderMethod) {
|
|||
|
||||
auto config = dynamic_cast<task::SwitchConfig*>(qApp->getRenderEngine()->getConfiguration()->getConfig("RenderMainView.DeferredForwardSwitch"));
|
||||
if (config) {
|
||||
if (renderMethod == DEFERRED) {
|
||||
_renderMethodSetting.set(render::Args::RenderMethod::DEFERRED);
|
||||
config->setBranch(render::Args::RenderMethod::DEFERRED);
|
||||
emit config->dirtyEnabled();
|
||||
} else if (renderMethod == FORWARD) {
|
||||
_renderMethodSetting.set(render::Args::RenderMethod::FORWARD);
|
||||
config->setBranch(render::Args::RenderMethod::FORWARD);
|
||||
emit config->dirtyEnabled();
|
||||
_renderMethodSetting.set(newMethod);
|
||||
config->setBranch(newMethod);
|
||||
emit config->dirtyEnabled();
|
||||
}
|
||||
}
|
||||
|
||||
bool RenderScriptingInterface::getShadowsEnabled() {
|
||||
return _shadowsEnabledSetting.get();
|
||||
}
|
||||
|
||||
void RenderScriptingInterface::setShadowsEnabled(bool enabled) {
|
||||
if (_shadowsEnabledSetting.get() == enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QMetaObject::invokeMethod(this, "setShadowsEnabled", Q_ARG(bool, enabled));
|
||||
return;
|
||||
}
|
||||
|
||||
auto lightingModelConfig = qApp->getRenderEngine()->getConfiguration()->getConfig<MakeLightingModel>("RenderMainView.LightingModel");
|
||||
if (lightingModelConfig) {
|
||||
Menu::getInstance()->setIsOptionChecked(MenuOption::Shadows, enabled);
|
||||
_shadowsEnabledSetting.set(enabled);
|
||||
lightingModelConfig->setShadow(enabled);
|
||||
}
|
||||
}
|
||||
|
||||
bool RenderScriptingInterface::getAmbientOcclusionEnabled() {
|
||||
return _ambientOcclusionEnabledSetting.get();
|
||||
}
|
||||
|
||||
void RenderScriptingInterface::setAmbientOcclusionEnabled(bool enabled) {
|
||||
if (_ambientOcclusionEnabledSetting.get() == enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QMetaObject::invokeMethod(this, "setAmbientOcclusionEnabled", Q_ARG(bool, enabled));
|
||||
return;
|
||||
}
|
||||
|
||||
auto lightingModelConfig = qApp->getRenderEngine()->getConfiguration()->getConfig<MakeLightingModel>("RenderMainView.LightingModel");
|
||||
if (lightingModelConfig) {
|
||||
Menu::getInstance()->setIsOptionChecked(MenuOption::AmbientOcclusion, enabled);
|
||||
_ambientOcclusionEnabledSetting.set(enabled);
|
||||
lightingModelConfig->setAmbientOcclusion(enabled);
|
||||
}
|
||||
}
|
||||
|
||||
bool RenderScriptingInterface::getAntialiasingEnabled() {
|
||||
return _antialiasingEnabledSetting.get();
|
||||
}
|
||||
|
||||
void RenderScriptingInterface::setAntialiasingEnabled(bool enabled) {
|
||||
if (_antialiasingEnabledSetting.get() == enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QMetaObject::invokeMethod(this, "setAntialiasingEnabled", Q_ARG(bool, enabled));
|
||||
return;
|
||||
}
|
||||
|
||||
auto mainViewJitterCamConfig = qApp->getRenderEngine()->getConfiguration()->getConfig<JitterSample>("RenderMainView.JitterCam");
|
||||
auto mainViewAntialiasingConfig = qApp->getRenderEngine()->getConfiguration()->getConfig<Antialiasing>("RenderMainView.Antialiasing");
|
||||
if (mainViewJitterCamConfig && mainViewAntialiasingConfig) {
|
||||
Menu::getInstance()->setIsOptionChecked(MenuOption::AntiAliasing, enabled);
|
||||
_antialiasingEnabledSetting.set(enabled);
|
||||
if (enabled) {
|
||||
mainViewJitterCamConfig->play();
|
||||
mainViewAntialiasingConfig->setDebugFXAA(false);
|
||||
} else {
|
||||
mainViewJitterCamConfig->none();
|
||||
mainViewAntialiasingConfig->setDebugFXAA(true);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -26,6 +26,9 @@
|
|||
class RenderScriptingInterface : public QObject {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QString renderMethod READ getRenderMethod WRITE setRenderMethod)
|
||||
Q_PROPERTY(bool shadowsEnabled READ getShadowsEnabled WRITE setShadowsEnabled)
|
||||
Q_PROPERTY(bool ambientOcclusionEnabled READ getAmbientOcclusionEnabled WRITE setAmbientOcclusionEnabled)
|
||||
Q_PROPERTY(bool antialiasingEnabled READ getAntialiasingEnabled WRITE setAntialiasingEnabled)
|
||||
|
||||
public:
|
||||
RenderScriptingInterface();
|
||||
|
@ -37,8 +40,8 @@ public slots:
|
|||
* Get a config for a job by name
|
||||
* @function Render.getConfig
|
||||
* @param {string} name - Can be:
|
||||
* - <job_name>. Search for the first job named job_name traversing the the sub graph of task and jobs (from this task as root)
|
||||
* - <parent_name>.[<sub_parent_names>.]<job_name>. Allows you to first look for the parent_name job (from this task as root) and then search from there for the
|
||||
* - <job_name>: Search for the first job named job_name traversing the the sub graph of task and jobs (from this task as root)
|
||||
* - <parent_name>.[<sub_parent_names>.]<job_name>: Allows you to first look for the parent_name job (from this task as root) and then search from there for the
|
||||
* optional sub_parent_names and finally from there looking for the job_name (assuming every job in the path is found)
|
||||
* @returns {object} The sub job config.
|
||||
*/
|
||||
|
@ -58,8 +61,53 @@ public slots:
|
|||
*/
|
||||
void setRenderMethod(const QString& renderMethod);
|
||||
|
||||
/**jsdoc
|
||||
* Whether or not shadows are enabled
|
||||
* @function Render.getShadowsEnabled
|
||||
* @returns {bool} <code>true</code> if shadows are enabled, otherwise <code>false</code>
|
||||
*/
|
||||
bool getShadowsEnabled();
|
||||
|
||||
/**jsdoc
|
||||
* Enables or disables shadows
|
||||
* @function Render.setShadowsEnabled
|
||||
* @param {bool} enabled - <code>true</code> to enable shadows, <code>false</code> to disable them
|
||||
*/
|
||||
void setShadowsEnabled(bool enabled);
|
||||
|
||||
/**jsdoc
|
||||
* Whether or not ambient occlusion is enabled
|
||||
* @function Render.getAmbientOcclusionEnabled
|
||||
* @returns {bool} <code>true</code> if ambient occlusion is enabled, otherwise <code>false</code>
|
||||
*/
|
||||
bool getAmbientOcclusionEnabled();
|
||||
|
||||
/**jsdoc
|
||||
* Enables or disables ambient occlusion
|
||||
* @function Render.setAmbientOcclusionEnabled
|
||||
* @param {bool} enabled - <code>true</code> to enable ambient occlusion, <code>false</code> to disable it
|
||||
*/
|
||||
void setAmbientOcclusionEnabled(bool enabled);
|
||||
|
||||
/**jsdoc
|
||||
* Whether or not anti-aliasing is enabled
|
||||
* @function Render.getAntialiasingEnabled
|
||||
* @returns {bool} <code>true</code> if anti-aliasing is enabled, otherwise <code>false</code>
|
||||
*/
|
||||
bool getAntialiasingEnabled();
|
||||
|
||||
/**jsdoc
|
||||
* Enables or disables anti-aliasing
|
||||
* @function Render.setAntialiasingEnabled
|
||||
* @param {bool} enabled - <code>true</code> to enable anti-aliasing, <code>false</code> to disable it
|
||||
*/
|
||||
void setAntialiasingEnabled(bool enabled);
|
||||
|
||||
private:
|
||||
Setting::Handle<int> _renderMethodSetting { "renderMethod", RENDER_FORWARD ? render::Args::RenderMethod::FORWARD : render::Args::RenderMethod::DEFERRED };
|
||||
Setting::Handle<bool> _shadowsEnabledSetting { "shadowsEnabled", true };
|
||||
Setting::Handle<bool> _ambientOcclusionEnabledSetting { "ambientOcclusionEnabled", false };
|
||||
Setting::Handle<bool> _antialiasingEnabledSetting { "antialiasingEnabled", true };
|
||||
};
|
||||
|
||||
#endif // hifi_RenderScriptingInterface_h
|
||||
|
|
|
@ -44,13 +44,14 @@ SelectionScriptingInterface::SelectionScriptingInterface() {
|
|||
}
|
||||
|
||||
/**jsdoc
|
||||
* The type of a specific item in a selection list.
|
||||
* <table>
|
||||
* <thead>
|
||||
* <tr><th>Value</th><th>Description</th></tr>
|
||||
* </thead>
|
||||
* <tbody>
|
||||
* <tr><td><code>"avatar"</code></td><td></td></tr>
|
||||
* <tr><td><code>"entity"</code></td><td></td></tr>
|
||||
* <tr><td><code>"avatar"</code></td><td>The item is an avatar.</td></tr>
|
||||
* <tr><td><code>"entity"</code></td><td>The item is an entity.</td></tr>
|
||||
* </tbody>
|
||||
* </table>
|
||||
* @typedef {string} Selection.ItemType
|
||||
|
@ -245,9 +246,10 @@ void SelectionScriptingInterface::printList(const QString& listName) {
|
|||
}
|
||||
|
||||
/**jsdoc
|
||||
* A selection list.
|
||||
* @typedef {object} Selection.SelectedItemsList
|
||||
* @property {Uuid[]} avatars - The IDs of the avatars in the selection.
|
||||
* @property {Uuid[]} entities - The IDs of the entities in the selection.
|
||||
* @property {Uuid[]} avatars - The IDs of the avatars in the selection list.
|
||||
* @property {Uuid[]} entities - The IDs of the entities in the selection list.
|
||||
*/
|
||||
QVariantMap SelectionScriptingInterface::getSelectedItemsList(const QString& listName) const {
|
||||
QReadLocker lock(&_selectionListsLock);
|
||||
|
@ -438,18 +440,19 @@ bool SelectionHighlightStyle::fromVariantMap(const QVariantMap& properties) {
|
|||
}
|
||||
|
||||
/**jsdoc
|
||||
* The highlighting style of a selection list.
|
||||
* @typedef {object} Selection.HighlightStyle
|
||||
* @property {Color} outlineUnoccludedColor - Color of the specified highlight region.
|
||||
* @property {Color} outlineOccludedColor - ""
|
||||
* @property {Color} fillUnoccludedColor- ""
|
||||
* @property {Color} fillOccludedColor- ""
|
||||
* @property {number} outlineUnoccludedAlpha - Alpha value ranging from <code>0.0</code> (not visible) to <code>1.0</code>
|
||||
* (fully opaque) for the specified highlight region.
|
||||
* @property {number} outlineOccludedAlpha - ""
|
||||
* @property {number} fillUnoccludedAlpha - ""
|
||||
* @property {number} fillOccludedAlpha - ""
|
||||
* @property {number} outlineWidth - Width of the outline, in pixels.
|
||||
* @property {boolean} isOutlineSmooth - <code>true</code> to enable outline smooth fall-off.
|
||||
* @property {Color} outlineUnoccludedColor=255,178,51 - Unoccluded outline color.
|
||||
* @property {Color} outlineOccludedColor=255,178,51 - Occluded outline color.
|
||||
* @property {Color} fillUnoccludedColor=51,178,255 - Unoccluded fill color.
|
||||
* @property {Color} fillOccludedColor=51,178,255 - Occluded fill color.
|
||||
* @property {number} outlineUnoccludedAlpha=0.9 - Unoccluded outline alpha, range <code>0.0</code> – <code>1.0</code>.
|
||||
* @property {number} outlineOccludedAlpha=0.9 - Occluded outline alpha, range <code>0.0</code> – <code>1.0</code>.
|
||||
* @property {number} fillUnoccludedAlpha=0.0 - Unoccluded fill alpha, range <code>0.0</code> – <code>1.0</code>.
|
||||
* @property {number} fillOccludedAlpha=0.0 - Occluded fill alpha, range <code>0.0</code> – <code>1.0</code>.
|
||||
* @property {number} outlineWidth=2 - Width of the outline, in pixels.
|
||||
* @property {boolean} isOutlineSmooth=false - <code>true</code> to fade the outside edge of the outline, <code>false</code>
|
||||
* to have a sharp edge.
|
||||
*/
|
||||
QVariantMap SelectionHighlightStyle::toVariantMap() const {
|
||||
QVariantMap properties;
|
||||
|
|
|
@ -77,47 +77,45 @@ protected:
|
|||
};
|
||||
|
||||
/**jsdoc
|
||||
* The <code>Selection</code> API provides a means of grouping together avatars and entities in named lists.
|
||||
* The <code>Selection</code> API provides a means of grouping together and highlighting avatars and entities in named lists.
|
||||
*
|
||||
* @namespace Selection
|
||||
*
|
||||
* @hifi-interface
|
||||
* @hifi-client-entity
|
||||
* @hifi-avatar
|
||||
*
|
||||
* @example <caption>Outline an entity when it is grabbed by a controller.</caption>
|
||||
* // Create a box and copy the following text into the entity's "Script URL" field.
|
||||
* @example <caption>Outline an entity when it is grabbed by the mouse or a controller.</caption>
|
||||
* // Create an entity and copy the following script into the entity's "Script URL" field.
|
||||
* // Move the entity behind another entity to see the occluded outline.
|
||||
* (function () {
|
||||
* print("Starting highlight script...............");
|
||||
* var _this = this;
|
||||
* var prevID = 0;
|
||||
* var listName = "contextOverlayHighlightList";
|
||||
* var listType = "entity";
|
||||
*
|
||||
* _this.startNearGrab = function(entityID){
|
||||
* if (prevID !== entityID) {
|
||||
* Selection.addToSelectedItemsList(listName, listType, entityID);
|
||||
* prevID = entityID;
|
||||
* }
|
||||
* var LIST_NAME = "SelectionExample",
|
||||
* ITEM_TYPE = "entity",
|
||||
* HIGHLIGHT_STYLE = {
|
||||
* outlineUnoccludedColor: { red: 0, green: 180, blue: 239 },
|
||||
* outlineUnoccludedAlpha: 0.5,
|
||||
* outlineOccludedColor: { red: 239, green: 180, blue: 0 },
|
||||
* outlineOccludedAlpha: 0.5,
|
||||
* outlineWidth: 4
|
||||
* };
|
||||
*
|
||||
* Selection.enableListHighlight(LIST_NAME, HIGHLIGHT_STYLE);
|
||||
*
|
||||
* this.startNearGrab = function (entityID) {
|
||||
* Selection.addToSelectedItemsList(LIST_NAME, ITEM_TYPE, entityID);
|
||||
* };
|
||||
*
|
||||
* _this.releaseGrab = function(entityID){
|
||||
* if (prevID !== 0) {
|
||||
* Selection.removeFromSelectedItemsList("contextOverlayHighlightList", listType, prevID);
|
||||
* prevID = 0;
|
||||
* }
|
||||
*
|
||||
* this.startDistanceGrab = function (entityID) {
|
||||
* Selection.addToSelectedItemsList(LIST_NAME, ITEM_TYPE, entityID);
|
||||
* };
|
||||
*
|
||||
* var cleanup = function(){
|
||||
* Entities.findEntities(MyAvatar.position, 1000).forEach(function(entity) {
|
||||
* try {
|
||||
* Selection.removeListFromMap(listName);
|
||||
* } catch (e) {
|
||||
* print("Error cleaning up.");
|
||||
* }
|
||||
* });
|
||||
*
|
||||
* this.releaseGrab = function (entityID) {
|
||||
* Selection.removeFromSelectedItemsList(LIST_NAME, ITEM_TYPE, entityID);
|
||||
* };
|
||||
*
|
||||
* Script.scriptEnding.connect(cleanup);
|
||||
*
|
||||
* Script.scriptEnding.connect(function () {
|
||||
* Selection.removeListFromMap(LIST_NAME);
|
||||
* });
|
||||
* });
|
||||
*/
|
||||
class SelectionScriptingInterface : public QObject, public Dependency {
|
||||
|
@ -127,121 +125,119 @@ public:
|
|||
SelectionScriptingInterface();
|
||||
|
||||
/**jsdoc
|
||||
* Get the names of all the selection lists.
|
||||
* @function Selection.getListNames
|
||||
* @returns {list[]} An array of names of all the selection lists.
|
||||
*/
|
||||
* Gets the names of all current selection lists.
|
||||
* @function Selection.getListNames
|
||||
* @returns {string[]} The names of all current selection lists.
|
||||
* @example <caption>List all the current selection lists.</caption>
|
||||
* print("Selection lists: " + Selection.getListNames());
|
||||
*/
|
||||
Q_INVOKABLE QStringList getListNames() const;
|
||||
|
||||
/**jsdoc
|
||||
* Delete a named selection list.
|
||||
* @function Selection.removeListFromMap
|
||||
* @param {string} listName - The name of the selection list.
|
||||
* @returns {boolean} <code>true</code> if the selection existed and was successfully removed, otherwise <code>false</code>.
|
||||
*/
|
||||
* Deletes a selection list.
|
||||
* @function Selection.removeListFromMap
|
||||
* @param {string} listName - The name of the selection list to delete.
|
||||
* @returns {boolean} <code>true</code> if the selection existed and was successfully removed, otherwise <code>false</code>.
|
||||
*/
|
||||
Q_INVOKABLE bool removeListFromMap(const QString& listName);
|
||||
|
||||
/**jsdoc
|
||||
* Add an item to a selection list.
|
||||
* @function Selection.addToSelectedItemsList
|
||||
* @param {string} listName - The name of the selection list to add the item to.
|
||||
* @param {Selection.ItemType} itemType - The type of the item being added.
|
||||
* @param {Uuid} id - The ID of the item to add to the selection.
|
||||
* @returns {boolean} <code>true</code> if the item was successfully added, otherwise <code>false</code>.
|
||||
*/
|
||||
* 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.
|
||||
* @param {Selection.ItemType} itemType - The type of item being added.
|
||||
* @param {Uuid} itemID - The ID of the item to add.
|
||||
* @returns {boolean} <code>true</code> if the item was successfully added or already existed in the list, otherwise
|
||||
* <code>false</code>.
|
||||
*/
|
||||
Q_INVOKABLE bool addToSelectedItemsList(const QString& listName, const QString& itemType, const QUuid& id);
|
||||
|
||||
/**jsdoc
|
||||
* Remove an item from a selection list.
|
||||
* @function Selection.removeFromSelectedItemsList
|
||||
* @param {string} listName - The name of the selection list to remove the item from.
|
||||
* @param {Selection.ItemType} itemType - The type of the item being removed.
|
||||
* @param {Uuid} id - The ID of the item to remove.
|
||||
* @returns {boolean} <code>true</code> if the item was successfully removed, otherwise <code>false</code>.
|
||||
* <codefalse</code> is returned if the list doesn't contain any data.
|
||||
*/
|
||||
* Removes an item from a selection list.
|
||||
* @function Selection.removeFromSelectedItemsList
|
||||
* @param {string} listName - The name of the selection list to remove the item from.
|
||||
* @param {Selection.ItemType} itemType - The type of item being removed.
|
||||
* @param {Uuid} itemID - The ID of the item to remove.
|
||||
* @returns {boolean} <code>true</code> if the item was successfully removed or was not in the list, otherwise
|
||||
* <code>false</code>.
|
||||
*/
|
||||
Q_INVOKABLE bool removeFromSelectedItemsList(const QString& listName, const QString& itemType, const QUuid& id);
|
||||
|
||||
/**jsdoc
|
||||
* Remove all items from a selection.
|
||||
* @function Selection.clearSelectedItemsList
|
||||
* @param {string} listName - The name of the selection list.
|
||||
* @returns {boolean} <code>true</code> if the item was successfully cleared, otherwise <code>false</code>.
|
||||
*/
|
||||
* Removes all items from a selection list.
|
||||
* @function Selection.clearSelectedItemsList
|
||||
* @param {string} listName - The name of the selection list.
|
||||
* @returns {boolean} <code>true</code> always.
|
||||
*/
|
||||
Q_INVOKABLE bool clearSelectedItemsList(const QString& listName);
|
||||
|
||||
/**jsdoc
|
||||
* Print out the list of avatars and entities in a selection to the <em>debug log</em> (not the script log).
|
||||
* @function Selection.printList
|
||||
* @param {string} listName - The name of the selection list.
|
||||
*/
|
||||
* 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
|
||||
* Get the list of avatars and entities stored in a selection list.
|
||||
* @function Selection.getSelectedItemsList
|
||||
* @param {string} listName - The name of the selection list.
|
||||
* @returns {Selection.SelectedItemsList} The content of a selection list. If the list name doesn't exist, the function
|
||||
* returns an empty object with no properties.
|
||||
*/
|
||||
* Gets the list of avatars and entities in a selection list.
|
||||
* @function Selection.getSelectedItemsList
|
||||
* @param {string} listName - The name of the selection list.
|
||||
* @returns {Selection.SelectedItemsList} The content of the selection list if the list exists, otherwise an empty object.
|
||||
*/
|
||||
Q_INVOKABLE QVariantMap getSelectedItemsList(const QString& listName) const;
|
||||
|
||||
/**jsdoc
|
||||
* Get the names of the highlighted selection lists.
|
||||
* @function Selection.getHighlightedListNames
|
||||
* @returns {string[]} An array of names of the selection list currently highlight enabled.
|
||||
*/
|
||||
* 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
|
||||
* Enable highlighting for a selection list.
|
||||
* If the selection list doesn't exist, it will be created.
|
||||
* All objects in the list will be displayed with the highlight effect specified.
|
||||
* The function can be called several times with different values in the style to modify it.<br />
|
||||
* Note: This function implicitly calls {@link Selection.enableListToScene}.
|
||||
* @function Selection.enableListHighlight
|
||||
* @param {string} listName - The name of the selection list.
|
||||
* @param {Selection.HighlightStyle} highlightStyle - The highlight style.
|
||||
* @returns {boolean} true if the selection was successfully enabled for highlight.
|
||||
*/
|
||||
* 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.
|
||||
* <p>Note: This function implicitly calls {@link Selection.enableListToScene|enableListToScene}.</p>
|
||||
* @function Selection.enableListHighlight
|
||||
* @param {string} listName - The name of the selection list.
|
||||
* @param {Selection.HighlightStyle} highlightStyle - The highlight style.
|
||||
* @returns {boolean} <code>true</code> always.
|
||||
*/
|
||||
Q_INVOKABLE bool enableListHighlight(const QString& listName, const QVariantMap& highlightStyle);
|
||||
|
||||
/**jsdoc
|
||||
* Disable highlighting for the selection list.
|
||||
* If the selection list doesn't exist or wasn't enabled for highlighting then nothing happens and <code>false</code> is
|
||||
* returned.<br />
|
||||
* Note: This function implicitly calls {@link Selection.disableListToScene}.
|
||||
* @function Selection.disableListHighlight
|
||||
* @param {string} listName - The name of the selection list.
|
||||
* @returns {boolean} <code>true</code> if the selection was successfully disabled for highlight, otherwise
|
||||
* <code>false</code>.
|
||||
*/
|
||||
* Disables highlighting for a selection list.
|
||||
* <p>Note: This function implicitly calls {@link Selection.disableListToScene|disableListToScene}.</p>
|
||||
* @function Selection.disableListHighlight
|
||||
* @param {string} listName - The name of the selection list.
|
||||
* @returns {boolean} <code>true</code> always.
|
||||
*/
|
||||
Q_INVOKABLE bool disableListHighlight(const QString& listName);
|
||||
|
||||
/**jsdoc
|
||||
* Enable scene selection for the selection list.
|
||||
* If the Selection doesn't exist, it will be created.
|
||||
* All objects in the list will be sent to a scene selection.
|
||||
* @function Selection.enableListToScene
|
||||
* @param {string} listName - The name of the selection list.
|
||||
* @returns {boolean} <code>true</code> if the selection was successfully enabled on the scene, otherwise <code>false</code>.
|
||||
*/
|
||||
* 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
|
||||
* @param {string} listName - The name of the selection list.
|
||||
* @returns {boolean} <code>true</code> always.
|
||||
*/
|
||||
Q_INVOKABLE bool enableListToScene(const QString& listName);
|
||||
|
||||
/**jsdoc
|
||||
* Disable scene selection for the named selection.
|
||||
* If the selection list doesn't exist or wasn't enabled on the scene then nothing happens and <code>false</code> is
|
||||
* returned.
|
||||
* @function Selection.disableListToScene
|
||||
* @param {string} listName - The name of the selection list.
|
||||
* @returns {boolean} true if the selection was successfully disabled on the scene, false otherwise.
|
||||
*/
|
||||
* Disables scene selection for a selection list.
|
||||
* @function Selection.disableListToScene
|
||||
* @param {string} listName - The name of the selection list.
|
||||
* @returns {boolean} <code>true</code> always.
|
||||
*/
|
||||
Q_INVOKABLE bool disableListToScene(const QString& listName);
|
||||
|
||||
/**jsdoc
|
||||
* Get the highlight style values for the a selection list.
|
||||
* If the selection doesn't exist or hasn't been highlight enabled yet, an empty object is returned.
|
||||
* @function Selection.getListHighlightStyle
|
||||
* @param {string} listName - The name of the selection list.
|
||||
* @returns {Selection.HighlightStyle} highlight style
|
||||
*/
|
||||
* Gets the current highlighting style for a selection list.
|
||||
* @function Selection.getListHighlightStyle
|
||||
* @param {string} listName - The name of the selection list.
|
||||
* @returns {Selection.HighlightStyle} The highlight style of the selection list if the list exists and highlighting is
|
||||
* enabled, otherwise an empty object.
|
||||
*/
|
||||
Q_INVOKABLE QVariantMap getListHighlightStyle(const QString& listName) const;
|
||||
|
||||
|
||||
|
@ -253,7 +249,7 @@ public:
|
|||
|
||||
signals:
|
||||
/**jsdoc
|
||||
* Triggered when a list's content changes.
|
||||
* 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.
|
||||
* @returns {Signal}
|
||||
|
@ -276,7 +272,6 @@ private:
|
|||
void setupHandler(const QString& selectionName);
|
||||
void removeHandler(const QString& selectionName);
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif // hifi_SelectionScriptingInterface_h
|
||||
|
|
|
@ -16,7 +16,8 @@
|
|||
#include <QString>
|
||||
|
||||
/**jsdoc
|
||||
* The Settings API provides a facility to store and retrieve values that persist between Interface runs.
|
||||
* The <code>Settings</code> API provides a facility to store and retrieve values that persist between Interface runs.
|
||||
*
|
||||
* @namespace Settings
|
||||
*
|
||||
* @hifi-interface
|
||||
|
@ -33,7 +34,7 @@ public:
|
|||
public slots:
|
||||
|
||||
/**jsdoc
|
||||
* Retrieve the value from a named setting.
|
||||
* Retrieves the value from a named setting.
|
||||
* @function Settings.getValue
|
||||
* @param {string} key - The name of the setting.
|
||||
* @param {string|number|boolean|object} [defaultValue=""] - The value to return if the setting doesn't exist.
|
||||
|
@ -50,8 +51,8 @@ public slots:
|
|||
QVariant getValue(const QString& setting, const QVariant& defaultValue);
|
||||
|
||||
/**jsdoc
|
||||
* Store a value in a named setting. If the setting already exists its value is overwritten, otherwise a new setting is
|
||||
* created. If the value is set to <code>null</code> or <code>undefined</code>, the setting is deleted.
|
||||
* Stores a value in a named setting. If the setting already exists, its value is overwritten. If the value is
|
||||
* <code>null</code> or <code>undefined</code>, the setting is deleted.
|
||||
* @function Settings.setValue
|
||||
* @param {string} key - The name of the setting. Be sure to use a unique name if creating a new setting.
|
||||
* @param {string|number|boolean|object|undefined} value - The value to store in the setting. If <code>null</code> or
|
||||
|
|
|
@ -313,8 +313,9 @@ public slots:
|
|||
* 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}
|
||||
* are emitted. The path to store the snapshots and the length of the animated GIF to capture are specified in Settings >
|
||||
* General > Snapshots.
|
||||
* are emitted.
|
||||
* <p>Snapshots are saved to the path specified in Settings > General > Snapshots, which can be accessed via the
|
||||
* {@link Snapshot} API.</p>
|
||||
*
|
||||
* @function Window.takeSnapshot
|
||||
* @param {boolean} [notify=true] - This value is passed on through the {@link Window.stillSnapshotTaken|stillSnapshotTaken}
|
||||
|
@ -351,13 +352,15 @@ public slots:
|
|||
* var notify = true;
|
||||
* var animated = true;
|
||||
* var aspect = 1920 / 1080;
|
||||
* var filename = "";
|
||||
* var filename = "example-snapshot";
|
||||
* Window.takeSnapshot(notify, animated, aspect, filename);
|
||||
*/
|
||||
void takeSnapshot(bool notify = true, bool includeAnimated = false, float aspectRatio = 0.0f, const QString& filename = QString());
|
||||
|
||||
/**jsdoc
|
||||
* Takes a still snapshot of the current view from the secondary camera that can be set up through the {@link Render} API.
|
||||
* <p>Snapshots are saved to the path specified in Settings > General > Snapshots, which can be accessed via the
|
||||
* {@link Snapshot} API.</p>
|
||||
* @function Window.takeSecondaryCameraSnapshot
|
||||
* @param {boolean} [notify=true] - This value is passed on through the {@link Window.stillSnapshotTaken|stillSnapshotTaken}
|
||||
* signal.
|
||||
|
@ -372,6 +375,8 @@ public slots:
|
|||
/**jsdoc
|
||||
* Takes a 360° snapshot at a given position for the secondary camera. The secondary camera does not need to have been
|
||||
* set up.
|
||||
* <p>Snapshots are saved to the path specified in Settings > General > Snapshots, which can be accessed via the
|
||||
* {@link Snapshot} API.</p>
|
||||
* @function Window.takeSecondaryCamera360Snapshot
|
||||
* @param {Vec3} cameraPosition - The position of the camera for the snapshot.
|
||||
* @param {boolean} [cubemapOutputFormat=false] - If <code>true</code> then the snapshot is saved as a cube map image,
|
||||
|
|
|
@ -109,7 +109,11 @@ InteractiveWindow::InteractiveWindow(const QString& sourceUrl, const QVariantMap
|
|||
auto mainWindow = qApp->getWindow();
|
||||
_dockWidget = std::shared_ptr<DockWidget>(new DockWidget(title, mainWindow), dockWidgetDeleter);
|
||||
auto quickView = _dockWidget->getQuickView();
|
||||
Application::setupQmlSurface(quickView->rootContext(), true);
|
||||
|
||||
Application::setupQmlSurface(quickView->rootContext() , true);
|
||||
|
||||
//add any whitelisted callbacks
|
||||
OffscreenUi::applyWhiteList(sourceUrl, quickView->rootContext());
|
||||
|
||||
/**jsdoc
|
||||
* Configures how a <code>NATIVE</code> window is displayed.
|
||||
|
@ -150,6 +154,8 @@ InteractiveWindow::InteractiveWindow(const QString& sourceUrl, const QVariantMap
|
|||
}
|
||||
});
|
||||
_dockWidget->setSource(QUrl(sourceUrl));
|
||||
|
||||
|
||||
mainWindow->addDockWidget(dockArea, _dockWidget.get());
|
||||
} else {
|
||||
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
||||
|
|
|
@ -180,11 +180,7 @@ private:
|
|||
mutable ReadWriteLockable _preferMalletsOverLasersSettingLock;
|
||||
mutable ReadWriteLockable _ignoreItemsLock;
|
||||
|
||||
#ifdef Q_OS_ANDROID
|
||||
Setting::Handle<bool> _use3DKeyboard { "use3DKeyboard", false };
|
||||
#else
|
||||
Setting::Handle<bool> _use3DKeyboard { "use3DKeyboard", true };
|
||||
#endif
|
||||
|
||||
QString _typedCharacters;
|
||||
TextDisplay _textDisplay;
|
||||
|
|
|
@ -38,6 +38,10 @@ private:
|
|||
|
||||
|
||||
/**jsdoc
|
||||
* The <code>Snapshot</code> 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 <code>Window</code> API functions such as
|
||||
* {@link Window.takeSnapshot}.
|
||||
*
|
||||
* @namespace Snapshot
|
||||
*
|
||||
* @hifi-interface
|
||||
|
@ -64,23 +68,31 @@ public:
|
|||
signals:
|
||||
|
||||
/**jsdoc
|
||||
* Triggered when the path that snapshots are saved to is changed.
|
||||
* @function Snapshot.snapshotLocationSet
|
||||
* @param {string} location
|
||||
* @param {string} location - The new snapshots location.
|
||||
* @returns {Signal}
|
||||
* @example <caption>Report when the snapshots location is changed.</caption>
|
||||
* // Run this script then change the snapshots location in Settings > General > Snapshots.
|
||||
* Snapshot.snapshotLocationSet.connect(function (path) {
|
||||
* print("New snapshot location: " + path);
|
||||
* });
|
||||
*/
|
||||
void snapshotLocationSet(const QString& value);
|
||||
|
||||
public slots:
|
||||
|
||||
/**jsdoc
|
||||
* Gets the path that snapshots are saved to.
|
||||
* @function Snapshot.getSnapshotsLocation
|
||||
* @returns {string}
|
||||
* @returns {string} The path to save snapshots to.
|
||||
*/
|
||||
Q_INVOKABLE QString getSnapshotsLocation();
|
||||
|
||||
/**jsdoc
|
||||
* Sets the path that snapshots are saved to.
|
||||
* @function Snapshot.setSnapshotsLocation
|
||||
* @param {String} location
|
||||
* @param {String} location - The path to save snapshots to.
|
||||
*/
|
||||
Q_INVOKABLE void setSnapshotsLocation(const QString& location);
|
||||
|
||||
|
|
|
@ -314,10 +314,11 @@ class Stats : public QQuickItem {
|
|||
STATS_PROPERTY(QVector3D, parabolaPicksUpdated, QVector3D(0, 0, 0))
|
||||
STATS_PROPERTY(QVector3D, collisionPicksUpdated, QVector3D(0, 0, 0))
|
||||
|
||||
#ifdef DEBUG_EVENT_QUEUE
|
||||
STATS_PROPERTY(bool, eventQueueDebuggingOn, true)
|
||||
STATS_PROPERTY(int, mainThreadQueueDepth, -1);
|
||||
STATS_PROPERTY(int, nodeListThreadQueueDepth, -1);
|
||||
|
||||
#ifdef DEBUG_EVENT_QUEUE
|
||||
STATS_PROPERTY(bool, eventQueueDebuggingOn, true)
|
||||
#else
|
||||
STATS_PROPERTY(bool, eventQueueDebuggingOn, false)
|
||||
#endif // DEBUG_EVENT_QUEUE
|
||||
|
|
|
@ -1869,6 +1869,7 @@ bool AudioClient::switchOutputToAudioDevice(const QAudioDeviceInfo outputDeviceI
|
|||
if (_audioOutput) {
|
||||
_audioOutputIODevice.close();
|
||||
_audioOutput->stop();
|
||||
_audioOutputInitialized = false;
|
||||
|
||||
//must be deleted in next eventloop cycle when its called from notify()
|
||||
_audioOutput->deleteLater();
|
||||
|
@ -1939,52 +1940,50 @@ bool AudioClient::switchOutputToAudioDevice(const QAudioDeviceInfo outputDeviceI
|
|||
int requestedSize = _sessionOutputBufferSizeFrames * frameSize * AudioConstants::SAMPLE_SIZE;
|
||||
_audioOutput->setBufferSize(requestedSize);
|
||||
|
||||
// initialize mix buffers on the _audioOutput thread to avoid races
|
||||
connect(_audioOutput, &QAudioOutput::stateChanged, [&, frameSize, requestedSize](QAudio::State state) {
|
||||
if (state == QAudio::ActiveState) {
|
||||
// restrict device callback to _outputPeriod samples
|
||||
_outputPeriod = _audioOutput->periodSize() / AudioConstants::SAMPLE_SIZE;
|
||||
// device callback may exceed reported period, so double it to avoid stutter
|
||||
_outputPeriod *= 2;
|
||||
|
||||
_outputMixBuffer = new float[_outputPeriod];
|
||||
_outputScratchBuffer = new int16_t[_outputPeriod];
|
||||
|
||||
// size local output mix buffer based on resampled network frame size
|
||||
int networkPeriod = _localToOutputResampler ? _localToOutputResampler->getMaxOutput(AudioConstants::NETWORK_FRAME_SAMPLES_STEREO) : AudioConstants::NETWORK_FRAME_SAMPLES_STEREO;
|
||||
_localOutputMixBuffer = new float[networkPeriod];
|
||||
|
||||
// local period should be at least twice the output period,
|
||||
// in case two device reads happen before more data can be read (worst case)
|
||||
int localPeriod = _outputPeriod * 2;
|
||||
// round up to an exact multiple of networkPeriod
|
||||
localPeriod = ((localPeriod + networkPeriod - 1) / networkPeriod) * networkPeriod;
|
||||
// this ensures lowest latency without stutter from underrun
|
||||
_localInjectorsStream.resizeForFrameSize(localPeriod);
|
||||
|
||||
int bufferSize = _audioOutput->bufferSize();
|
||||
int bufferSamples = bufferSize / AudioConstants::SAMPLE_SIZE;
|
||||
int bufferFrames = bufferSamples / (float)frameSize;
|
||||
qCDebug(audioclient) << "frame (samples):" << frameSize;
|
||||
qCDebug(audioclient) << "buffer (frames):" << bufferFrames;
|
||||
qCDebug(audioclient) << "buffer (samples):" << bufferSamples;
|
||||
qCDebug(audioclient) << "buffer (bytes):" << bufferSize;
|
||||
qCDebug(audioclient) << "requested (bytes):" << requestedSize;
|
||||
qCDebug(audioclient) << "period (samples):" << _outputPeriod;
|
||||
qCDebug(audioclient) << "local buffer (samples):" << localPeriod;
|
||||
|
||||
disconnect(_audioOutput, &QAudioOutput::stateChanged, 0, 0);
|
||||
|
||||
// unlock to avoid a deadlock with the device callback (which always succeeds this initialization)
|
||||
localAudioLock.unlock();
|
||||
}
|
||||
});
|
||||
connect(_audioOutput, &QAudioOutput::notify, this, &AudioClient::outputNotify);
|
||||
|
||||
// start the output device
|
||||
_audioOutputIODevice.start();
|
||||
|
||||
_audioOutput->start(&_audioOutputIODevice);
|
||||
|
||||
// initialize mix buffers
|
||||
|
||||
// restrict device callback to _outputPeriod samples
|
||||
_outputPeriod = _audioOutput->periodSize() / AudioConstants::SAMPLE_SIZE;
|
||||
// device callback may exceed reported period, so double it to avoid stutter
|
||||
_outputPeriod *= 2;
|
||||
|
||||
_outputMixBuffer = new float[_outputPeriod];
|
||||
_outputScratchBuffer = new int16_t[_outputPeriod];
|
||||
|
||||
// size local output mix buffer based on resampled network frame size
|
||||
int networkPeriod = _localToOutputResampler ? _localToOutputResampler->getMaxOutput(AudioConstants::NETWORK_FRAME_SAMPLES_STEREO) : AudioConstants::NETWORK_FRAME_SAMPLES_STEREO;
|
||||
_localOutputMixBuffer = new float[networkPeriod];
|
||||
|
||||
// local period should be at least twice the output period,
|
||||
// in case two device reads happen before more data can be read (worst case)
|
||||
int localPeriod = _outputPeriod * 2;
|
||||
// round up to an exact multiple of networkPeriod
|
||||
localPeriod = ((localPeriod + networkPeriod - 1) / networkPeriod) * networkPeriod;
|
||||
// this ensures lowest latency without stutter from underrun
|
||||
_localInjectorsStream.resizeForFrameSize(localPeriod);
|
||||
|
||||
_audioOutputInitialized = true;
|
||||
|
||||
int bufferSize = _audioOutput->bufferSize();
|
||||
int bufferSamples = bufferSize / AudioConstants::SAMPLE_SIZE;
|
||||
int bufferFrames = bufferSamples / (float)frameSize;
|
||||
qCDebug(audioclient) << "frame (samples):" << frameSize;
|
||||
qCDebug(audioclient) << "buffer (frames):" << bufferFrames;
|
||||
qCDebug(audioclient) << "buffer (samples):" << bufferSamples;
|
||||
qCDebug(audioclient) << "buffer (bytes):" << bufferSize;
|
||||
qCDebug(audioclient) << "requested (bytes):" << requestedSize;
|
||||
qCDebug(audioclient) << "period (samples):" << _outputPeriod;
|
||||
qCDebug(audioclient) << "local buffer (samples):" << localPeriod;
|
||||
|
||||
// unlock to avoid a deadlock with the device callback (which always succeeds this initialization)
|
||||
localAudioLock.unlock();
|
||||
|
||||
// setup a loopback audio output device
|
||||
_loopbackAudioOutput = new QAudioOutput(outputDeviceInfo, _outputFormat, this);
|
||||
|
||||
|
@ -2082,6 +2081,12 @@ float AudioClient::gainForSource(float distance, float volume) {
|
|||
|
||||
qint64 AudioClient::AudioOutputIODevice::readData(char * data, qint64 maxSize) {
|
||||
|
||||
// lock-free wait for initialization to avoid races
|
||||
if (!_audio->_audioOutputInitialized.load(std::memory_order_acquire)) {
|
||||
memset(data, 0, maxSize);
|
||||
return maxSize;
|
||||
}
|
||||
|
||||
// samples requested from OUTPUT_CHANNEL_COUNT
|
||||
int deviceChannelCount = _audio->_outputFormat.channelCount();
|
||||
int samplesRequested = (int)(maxSize / AudioConstants::SAMPLE_SIZE) * OUTPUT_CHANNEL_COUNT / deviceChannelCount;
|
||||
|
@ -2162,6 +2167,8 @@ qint64 AudioClient::AudioOutputIODevice::readData(char * data, qint64 maxSize) {
|
|||
}
|
||||
|
||||
bytesWritten = framesPopped * AudioConstants::SAMPLE_SIZE * deviceChannelCount;
|
||||
assert(bytesWritten <= maxSize);
|
||||
|
||||
} else {
|
||||
// nothing on network, don't grab anything from injectors, and just return 0s
|
||||
memset(data, 0, maxSize);
|
||||
|
@ -2174,7 +2181,6 @@ qint64 AudioClient::AudioOutputIODevice::readData(char * data, qint64 maxSize) {
|
|||
_audio->_audioFileWav.addRawAudioChunk(reinterpret_cast<char*>(scratchBuffer), bytesWritten);
|
||||
}
|
||||
|
||||
|
||||
int bytesAudioOutputUnplayed = _audio->_audioOutput->bufferSize() - _audio->_audioOutput->bytesFree();
|
||||
float msecsAudioOutputUnplayed = bytesAudioOutputUnplayed / (float)_audio->_outputFormat.bytesForDuration(USECS_PER_MSEC);
|
||||
_audio->_stats.updateOutputMsUnplayed(msecsAudioOutputUnplayed);
|
||||
|
|
|
@ -340,6 +340,7 @@ private:
|
|||
QIODevice* _inputDevice;
|
||||
int _numInputCallbackBytes;
|
||||
QAudioOutput* _audioOutput;
|
||||
std::atomic<bool> _audioOutputInitialized { false };
|
||||
QAudioFormat _desiredOutputFormat;
|
||||
QAudioFormat _outputFormat;
|
||||
int _outputFrameSize;
|
||||
|
|
|
@ -364,10 +364,19 @@ int InboundAudioStream::popSamples(int maxSamples, bool allOrNothing) {
|
|||
// buffer calculations.
|
||||
setToStarved();
|
||||
_consecutiveNotMixedCount++;
|
||||
//Kick PLC to generate a filler frame, reducing 'click'
|
||||
lostAudioData(allOrNothing ? (maxSamples - samplesAvailable) / _ringBuffer.getNumFrameSamples() : 1);
|
||||
samplesPopped = _ringBuffer.samplesAvailable();
|
||||
if (samplesPopped) {
|
||||
|
||||
// use PLC to generate extrapolated audio data, to reduce clicking
|
||||
if (allOrNothing) {
|
||||
int samplesNeeded = maxSamples - samplesAvailable;
|
||||
int packetsNeeded = (samplesNeeded + _ringBuffer.getNumFrameSamples() - 1) / _ringBuffer.getNumFrameSamples();
|
||||
lostAudioData(packetsNeeded);
|
||||
} else {
|
||||
lostAudioData(1);
|
||||
}
|
||||
samplesAvailable = _ringBuffer.samplesAvailable();
|
||||
|
||||
if (samplesAvailable > 0) {
|
||||
samplesPopped = std::min(samplesAvailable, maxSamples);
|
||||
popSamplesNoCheck(samplesPopped);
|
||||
} else {
|
||||
// No samples available means a packet is currently being
|
||||
|
|
|
@ -1519,18 +1519,19 @@ void Avatar::scaleVectorRelativeToPosition(glm::vec3 &positionToScale) const {
|
|||
}
|
||||
|
||||
void Avatar::setSkeletonModelURL(const QUrl& skeletonModelURL) {
|
||||
AvatarData::setSkeletonModelURL(skeletonModelURL);
|
||||
if (QThread::currentThread() == thread()) {
|
||||
|
||||
if (!isMyAvatar() && !DependencyManager::get<NodeList>()->isIgnoringNode(getSessionUUID())) {
|
||||
createOrb();
|
||||
}
|
||||
|
||||
_skeletonModel->setURL(_skeletonModelURL);
|
||||
indicateLoadingStatus(LoadingStatus::LoadModel);
|
||||
} else {
|
||||
QMetaObject::invokeMethod(_skeletonModel.get(), "setURL", Qt::QueuedConnection, Q_ARG(QUrl, _skeletonModelURL));
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QMetaObject::invokeMethod(this, "setSkeletonModelURL", Q_ARG(const QUrl&, skeletonModelURL));
|
||||
return;
|
||||
}
|
||||
|
||||
AvatarData::setSkeletonModelURL(skeletonModelURL);
|
||||
|
||||
if (!isMyAvatar() && !DependencyManager::get<NodeList>()->isIgnoringNode(getSessionUUID())) {
|
||||
createOrb();
|
||||
}
|
||||
indicateLoadingStatus(LoadingStatus::LoadModel);
|
||||
|
||||
_skeletonModel->setURL(_skeletonModelURL);
|
||||
}
|
||||
|
||||
void Avatar::setModelURLFinished(bool success) {
|
||||
|
|
|
@ -339,7 +339,7 @@ public:
|
|||
*/
|
||||
Q_INVOKABLE glm::quat jointToWorldRotation(const glm::quat& rotation, const int jointIndex = -1) const;
|
||||
|
||||
virtual void setSkeletonModelURL(const QUrl& skeletonModelURL) override;
|
||||
Q_INVOKABLE virtual void setSkeletonModelURL(const QUrl& skeletonModelURL) override;
|
||||
virtual void setAttachmentData(const QVector<AttachmentData>& attachmentData) override;
|
||||
|
||||
void updateDisplayNameAlpha(bool showDisplayName);
|
||||
|
|
|
@ -1211,7 +1211,7 @@ public:
|
|||
const QString& getDisplayName() const { return _displayName; }
|
||||
const QString& getSessionDisplayName() const { return _sessionDisplayName; }
|
||||
bool getLookAtSnappingEnabled() const { return _lookAtSnappingEnabled; }
|
||||
virtual void setSkeletonModelURL(const QUrl& skeletonModelURL);
|
||||
Q_INVOKABLE virtual void setSkeletonModelURL(const QUrl& skeletonModelURL);
|
||||
|
||||
virtual void setDisplayName(const QString& displayName);
|
||||
virtual void setSessionDisplayName(const QString& sessionDisplayName) {
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
// These properties have JSDoc documentation in HMDScriptingInterface.h.
|
||||
class AbstractHMDScriptingInterface : public QObject {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(bool active READ isHMDMode NOTIFY mountedChanged)
|
||||
Q_PROPERTY(bool active READ isHMDMode NOTIFY displayModeChanged)
|
||||
Q_PROPERTY(float ipd READ getIPD)
|
||||
Q_PROPERTY(float eyeHeight READ getEyeHeight)
|
||||
Q_PROPERTY(float playerHeight READ getPlayerHeight)
|
||||
|
|
|
@ -32,19 +32,6 @@
|
|||
using namespace render;
|
||||
using namespace render::entities;
|
||||
|
||||
// These or the icon "name" used by the render item status value, they correspond to the atlas texture used by the DrawItemStatus
|
||||
// job in the current rendering pipeline defined as of now (11/2015) in render-utils/RenderDeferredTask.cpp.
|
||||
enum class RenderItemStatusIcon {
|
||||
ACTIVE_IN_BULLET = 0,
|
||||
PACKET_SENT = 1,
|
||||
PACKET_RECEIVED = 2,
|
||||
SIMULATION_OWNER = 3,
|
||||
HAS_ACTIONS = 4,
|
||||
OTHER_SIMULATION_OWNER = 5,
|
||||
ENTITY_HOST_TYPE = 6,
|
||||
NONE = 255
|
||||
};
|
||||
|
||||
void EntityRenderer::initEntityRenderers() {
|
||||
REGISTER_ENTITY_TYPE_WITH_FACTORY(Model, RenderableModelEntityItem::factory)
|
||||
REGISTER_ENTITY_TYPE_WITH_FACTORY(PolyVox, RenderablePolyVoxEntityItem::factory)
|
||||
|
@ -67,7 +54,7 @@ void EntityRenderer::makeStatusGetters(const EntityItemPointer& entity, Item::St
|
|||
return render::Item::Status::Value(1.0f - normalizedDelta, (normalizedDelta > 1.0f ?
|
||||
render::Item::Status::Value::GREEN :
|
||||
render::Item::Status::Value::RED),
|
||||
(unsigned char)RenderItemStatusIcon::PACKET_RECEIVED);
|
||||
(unsigned char)render::Item::Status::Icon::PACKET_RECEIVED);
|
||||
});
|
||||
|
||||
statusGetters.push_back([entity] () -> render::Item::Status::Value {
|
||||
|
@ -79,17 +66,17 @@ void EntityRenderer::makeStatusGetters(const EntityItemPointer& entity, Item::St
|
|||
return render::Item::Status::Value(1.0f - normalizedDelta, (normalizedDelta > 1.0f ?
|
||||
render::Item::Status::Value::MAGENTA :
|
||||
render::Item::Status::Value::CYAN),
|
||||
(unsigned char)RenderItemStatusIcon::PACKET_SENT);
|
||||
(unsigned char)render::Item::Status::Icon::PACKET_SENT);
|
||||
});
|
||||
|
||||
statusGetters.push_back([entity] () -> render::Item::Status::Value {
|
||||
ObjectMotionState* motionState = static_cast<ObjectMotionState*>(entity->getPhysicsInfo());
|
||||
if (motionState && motionState->isActive()) {
|
||||
return render::Item::Status::Value(1.0f, render::Item::Status::Value::BLUE,
|
||||
(unsigned char)RenderItemStatusIcon::ACTIVE_IN_BULLET);
|
||||
(unsigned char)render::Item::Status::Icon::ACTIVE_IN_BULLET);
|
||||
}
|
||||
return render::Item::Status::Value(0.0f, render::Item::Status::Value::BLUE,
|
||||
(unsigned char)RenderItemStatusIcon::ACTIVE_IN_BULLET);
|
||||
(unsigned char)render::Item::Status::Icon::ACTIVE_IN_BULLET);
|
||||
});
|
||||
|
||||
statusGetters.push_back([entity, myNodeID] () -> render::Item::Status::Value {
|
||||
|
@ -98,39 +85,39 @@ void EntityRenderer::makeStatusGetters(const EntityItemPointer& entity, Item::St
|
|||
|
||||
if (weOwnSimulation) {
|
||||
return render::Item::Status::Value(1.0f, render::Item::Status::Value::BLUE,
|
||||
(unsigned char)RenderItemStatusIcon::SIMULATION_OWNER);
|
||||
(unsigned char)render::Item::Status::Icon::SIMULATION_OWNER);
|
||||
} else if (otherOwnSimulation) {
|
||||
return render::Item::Status::Value(1.0f, render::Item::Status::Value::RED,
|
||||
(unsigned char)RenderItemStatusIcon::OTHER_SIMULATION_OWNER);
|
||||
(unsigned char)render::Item::Status::Icon::OTHER_SIMULATION_OWNER);
|
||||
}
|
||||
return render::Item::Status::Value(0.0f, render::Item::Status::Value::BLUE,
|
||||
(unsigned char)RenderItemStatusIcon::SIMULATION_OWNER);
|
||||
(unsigned char)render::Item::Status::Icon::SIMULATION_OWNER);
|
||||
});
|
||||
|
||||
statusGetters.push_back([entity] () -> render::Item::Status::Value {
|
||||
if (entity->hasActions()) {
|
||||
return render::Item::Status::Value(1.0f, render::Item::Status::Value::GREEN,
|
||||
(unsigned char)RenderItemStatusIcon::HAS_ACTIONS);
|
||||
(unsigned char)render::Item::Status::Icon::HAS_ACTIONS);
|
||||
}
|
||||
return render::Item::Status::Value(0.0f, render::Item::Status::Value::GREEN,
|
||||
(unsigned char)RenderItemStatusIcon::HAS_ACTIONS);
|
||||
(unsigned char)render::Item::Status::Icon::HAS_ACTIONS);
|
||||
});
|
||||
|
||||
statusGetters.push_back([entity, myNodeID] () -> render::Item::Status::Value {
|
||||
if (entity->isAvatarEntity()) {
|
||||
if (entity->getOwningAvatarID() == myNodeID) {
|
||||
return render::Item::Status::Value(1.0f, render::Item::Status::Value::GREEN,
|
||||
(unsigned char)RenderItemStatusIcon::ENTITY_HOST_TYPE);
|
||||
(unsigned char)render::Item::Status::Icon::ENTITY_HOST_TYPE);
|
||||
} else {
|
||||
return render::Item::Status::Value(1.0f, render::Item::Status::Value::RED,
|
||||
(unsigned char)RenderItemStatusIcon::ENTITY_HOST_TYPE);
|
||||
(unsigned char)render::Item::Status::Icon::ENTITY_HOST_TYPE);
|
||||
}
|
||||
} else if (entity->isLocalEntity()) {
|
||||
return render::Item::Status::Value(1.0f, render::Item::Status::Value::BLUE,
|
||||
(unsigned char)RenderItemStatusIcon::ENTITY_HOST_TYPE);
|
||||
(unsigned char)render::Item::Status::Icon::ENTITY_HOST_TYPE);
|
||||
}
|
||||
return render::Item::Status::Value(0.0f, render::Item::Status::Value::GREEN,
|
||||
(unsigned char)RenderItemStatusIcon::ENTITY_HOST_TYPE);
|
||||
(unsigned char)render::Item::Status::Icon::ENTITY_HOST_TYPE);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -363,7 +363,7 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& shapeInfo) {
|
|||
ShapeType type = getShapeType();
|
||||
|
||||
auto model = getModel();
|
||||
if (!model) {
|
||||
if (!model || !model->isLoaded()) {
|
||||
type = SHAPE_TYPE_NONE;
|
||||
}
|
||||
|
||||
|
|
|
@ -1770,6 +1770,7 @@ signals:
|
|||
/**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.
|
||||
* <p>See also, {@link Script.addEventHandler}.</p>
|
||||
* @function Entities.collisionWithEntity
|
||||
* @param {Uuid} idA - The ID of one entity in the collision. For an entity script, this is the ID of the entity containing
|
||||
* the script.
|
||||
|
@ -1882,6 +1883,7 @@ signals:
|
|||
/**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.
|
||||
* <p>See also, {@link Script.addEventHandler}.</p>
|
||||
* @function Entities.mousePressOnEntity
|
||||
* @param {Uuid} entityID - The ID of the entity that was pressed.
|
||||
* @param {PointerEvent} event - Details of the event.
|
||||
|
@ -1906,6 +1908,7 @@ signals:
|
|||
|
||||
/**jsdoc
|
||||
* Repeatedly triggered while the mouse cursor or controller laser moves on an entity.
|
||||
* <p>See also, {@link Script.addEventHandler}.</p>
|
||||
* @function Entities.mouseMoveOnEntity
|
||||
* @param {Uuid} entityID - The ID of the entity that was moved on.
|
||||
* @param {PointerEvent} event - Details of the event.
|
||||
|
@ -1916,6 +1919,7 @@ signals:
|
|||
/**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.
|
||||
* <p>See also, {@link Script.addEventHandler}.</p>
|
||||
* @function Entities.mouseReleaseOnEntity
|
||||
* @param {Uuid} entityID - The ID of the entity that was originally pressed.
|
||||
* @param {PointerEvent} event - Details of the event.
|
||||
|
@ -1942,6 +1946,7 @@ signals:
|
|||
|
||||
/**jsdoc
|
||||
* Triggered when a mouse button is clicked while the mouse cursor is on an entity. Note: Not triggered by controller.
|
||||
* <p>See also, {@link Script.addEventHandler}.</p>
|
||||
* @function Entities.clickDownOnEntity
|
||||
* @param {Uuid} entityID - The ID of the entity that was clicked.
|
||||
* @param {PointerEvent} event - Details of the event.
|
||||
|
@ -1952,6 +1957,7 @@ signals:
|
|||
/**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 controller.
|
||||
* <p>See also, {@link Script.addEventHandler}.</p>
|
||||
* @function Entities.holdingClickOnEntity
|
||||
* @param {Uuid} entityID - The ID of the entity that was originally clicked.
|
||||
* @param {PointerEvent} event - Details of the event.
|
||||
|
@ -1962,6 +1968,7 @@ signals:
|
|||
/**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 controller.
|
||||
* <p>See also, {@link Script.addEventHandler}.</p>
|
||||
* @function Entities.clickReleaseOnEntity
|
||||
* @param {Uuid} entityID - The ID of the entity that was originally clicked.
|
||||
* @param {PointerEvent} event - Details of the event.
|
||||
|
@ -1971,6 +1978,7 @@ signals:
|
|||
|
||||
/**jsdoc
|
||||
* Triggered when the mouse cursor or controller laser starts hovering on an entity.
|
||||
* <p>See also, {@link Script.addEventHandler}.</p>
|
||||
* @function Entities.hoverEnterEntity
|
||||
* @param {Uuid} entityID - The ID of the entity that is being hovered.
|
||||
* @param {PointerEvent} event - Details of the event.
|
||||
|
@ -1980,6 +1988,7 @@ signals:
|
|||
|
||||
/**jsdoc
|
||||
* Repeatedly triggered when the mouse cursor or controller laser moves while hovering over an entity.
|
||||
* <p>See also, {@link Script.addEventHandler}.</p>
|
||||
* @function Entities.hoverOverEntity
|
||||
* @param {Uuid} entityID - The ID of the entity that is being hovered.
|
||||
* @param {PointerEvent} event - Details of the event.
|
||||
|
@ -1989,6 +1998,7 @@ signals:
|
|||
|
||||
/**jsdoc
|
||||
* Triggered when the mouse cursor or controller laser stops hovering over an entity.
|
||||
* <p>See also, {@link Script.addEventHandler}.</p>
|
||||
* @function Entities.hoverLeaveEntity
|
||||
* @param {Uuid} entityID - The ID of the entity that was being hovered.
|
||||
* @param {PointerEvent} event - Details of the event.
|
||||
|
@ -1999,6 +2009,7 @@ signals:
|
|||
|
||||
/**jsdoc
|
||||
* Triggered when an avatar enters an entity.
|
||||
* <p>See also, {@link Script.addEventHandler}.</p>
|
||||
* @function Entities.enterEntity
|
||||
* @param {Uuid} entityID - The ID of the entity that the avatar entered.
|
||||
* @returns {Signal}
|
||||
|
@ -2032,6 +2043,7 @@ signals:
|
|||
|
||||
/**jsdoc
|
||||
* Triggered when an avatar leaves an entity.
|
||||
* <p>See also, {@link Script.addEventHandler}.</p>
|
||||
* @function Entities.leaveEntity
|
||||
* @param {Uuid} entityID - The ID of the entity that the avatar left.
|
||||
* @returns {Signal}
|
||||
|
|
|
@ -220,6 +220,10 @@ void GL45Texture::generateMips() const {
|
|||
(void)CHECK_GL_ERROR();
|
||||
}
|
||||
|
||||
// (NOTE: it seems to work now, but for posterity:) DSA ARB does not work on AMD, so use EXT
|
||||
// unless EXT is not available on the driver
|
||||
#define AMD_CUBE_MAP_EXT_WORKAROUND 0
|
||||
|
||||
Size GL45Texture::copyMipFaceLinesFromTexture(uint16_t mip, uint8_t face, const uvec3& size, uint32_t yOffset, GLenum internalFormat, GLenum format, GLenum type, Size sourceSize, const void* sourcePointer) const {
|
||||
Size amountCopied = sourceSize;
|
||||
if (GL_TEXTURE_2D == _target) {
|
||||
|
@ -267,22 +271,26 @@ Size GL45Texture::copyMipFaceLinesFromTexture(uint16_t mip, uint8_t face, const
|
|||
case GL_COMPRESSED_SIGNED_R11_EAC:
|
||||
case GL_COMPRESSED_RG11_EAC:
|
||||
case GL_COMPRESSED_SIGNED_RG11_EAC:
|
||||
#if AMD_CUBE_MAP_EXT_WORKAROUND
|
||||
if (glCompressedTextureSubImage2DEXT) {
|
||||
auto target = GLTexture::CUBE_FACE_LAYOUT[face];
|
||||
glCompressedTextureSubImage2DEXT(_id, target, mip, 0, yOffset, size.x, size.y, internalFormat,
|
||||
static_cast<GLsizei>(sourceSize), sourcePointer);
|
||||
} else {
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
glCompressedTextureSubImage3D(_id, mip, 0, yOffset, face, size.x, size.y, 1, internalFormat,
|
||||
static_cast<GLsizei>(sourceSize), sourcePointer);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// DSA ARB does not work on AMD, so use EXT
|
||||
// unless EXT is not available on the driver
|
||||
#if AMD_CUBE_MAP_EXT_WORKAROUND
|
||||
if (glTextureSubImage2DEXT) {
|
||||
auto target = GLTexture::CUBE_FACE_LAYOUT[face];
|
||||
glTextureSubImage2DEXT(_id, target, mip, 0, yOffset, size.x, size.y, format, type, sourcePointer);
|
||||
} else {
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
glTextureSubImage3D(_id, mip, 0, yOffset, face, size.x, size.y, 1, format, type, sourcePointer);
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -26,8 +26,8 @@ const Element Element::COLOR_COMPRESSED_BCX_SRGB { TILE4x4, COMPRESSED, COMPRESS
|
|||
const Element Element::COLOR_COMPRESSED_BCX_SRGBA_MASK { TILE4x4, COMPRESSED, COMPRESSED_BC1_SRGBA };
|
||||
const Element Element::COLOR_COMPRESSED_BCX_SRGBA { TILE4x4, COMPRESSED, COMPRESSED_BC3_SRGBA };
|
||||
const Element Element::COLOR_COMPRESSED_BCX_XY { TILE4x4, COMPRESSED, COMPRESSED_BC5_XY };
|
||||
const Element Element::COLOR_COMPRESSED_BCX_SRGBA_HIGH { TILE4x4, COMPRESSED, COMPRESSED_BC7_SRGBA };
|
||||
const Element Element::COLOR_COMPRESSED_BCX_HDR_RGB { TILE4x4, COMPRESSED, COMPRESSED_BC6_RGB };
|
||||
const Element Element::COLOR_COMPRESSED_BCX_SRGBA_HIGH { TILE4x4, COMPRESSED, COMPRESSED_BC7_SRGBA };
|
||||
|
||||
const Element Element::COLOR_COMPRESSED_ETC2_RGB { TILE4x4, COMPRESSED, COMPRESSED_ETC2_RGB };
|
||||
const Element Element::COLOR_COMPRESSED_ETC2_SRGB { TILE4x4, COMPRESSED, COMPRESSED_ETC2_SRGB };
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
#include "Batch.h"
|
||||
#include "TextureTable.h"
|
||||
|
||||
|
||||
#include "FrameIOKeys.h"
|
||||
|
||||
namespace gpu {
|
||||
|
@ -324,6 +323,13 @@ TexturePointer Deserializer::readTexture(const json& node, uint32_t external) {
|
|||
readOptional(ktxFile, node, keys::ktxFile);
|
||||
Element ktxTexelFormat, ktxMipFormat;
|
||||
if (!ktxFile.empty()) {
|
||||
// If we get a texture that starts with ":" we need to re-route it to the resources directory
|
||||
if (ktxFile.at(0) == ':') {
|
||||
QString frameReaderPath = __FILE__;
|
||||
frameReaderPath.replace("\\", "/");
|
||||
frameReaderPath.replace("libraries/gpu/src/gpu/framereader.cpp", "interface/resources", Qt::CaseInsensitive);
|
||||
ktxFile.replace(0, 1, frameReaderPath.toStdString());
|
||||
}
|
||||
if (QFileInfo(ktxFile.c_str()).isRelative()) {
|
||||
ktxFile = basedir + ktxFile;
|
||||
}
|
||||
|
|
|
@ -26,13 +26,14 @@ layout(location=0) in vec3 _normal;
|
|||
layout(location=0) out vec4 _fragColor;
|
||||
|
||||
void main(void) {
|
||||
vec3 coord = normalize(_normal);
|
||||
vec3 color = skybox.color.rgb;
|
||||
// FIXME: For legacy reasons, when skybox.color.a is 0.5, this is equivalent to:
|
||||
// skyboxColor * skyboxTexel
|
||||
// It should actually be:
|
||||
// mix(skyboxColor, skyboxTexel, skybox.color.a)
|
||||
// and the blend factor should be user controlled
|
||||
|
||||
// blend is only set if there is a cubemap
|
||||
float check = float(skybox.color.a > 0.0);
|
||||
color = mix(color, texture(cubeMap, coord).rgb, check);
|
||||
color *= mix(vec3(1.0), skybox.color.rgb, check * float(skybox.color.a < 1.0));
|
||||
|
||||
_fragColor = vec4(color, 0.0);
|
||||
vec3 skyboxTexel = texture(cubeMap, normalize(_normal)).rgb;
|
||||
vec3 skyboxColor = skybox.color.rgb;
|
||||
_fragColor = vec4(mix(vec3(1.0), skyboxTexel, float(skybox.color.a > 0.0)) *
|
||||
mix(vec3(1.0), skyboxColor, float(skybox.color.a < 1.0)), 1.0);
|
||||
}
|
||||
|
|
|
@ -690,6 +690,8 @@ void convertImageToLDRTexture(gpu::Texture* texture, Image&& image, BackendTarge
|
|||
compressionOptions.setFormat(nvtt::Format_BC4);
|
||||
} else if (mipFormat == gpu::Element::COLOR_COMPRESSED_BCX_XY) {
|
||||
compressionOptions.setFormat(nvtt::Format_BC5);
|
||||
} else if (mipFormat == gpu::Element::COLOR_COMPRESSED_BCX_HDR_RGB) {
|
||||
compressionOptions.setFormat(nvtt::Format_BC6);
|
||||
} else if (mipFormat == gpu::Element::COLOR_COMPRESSED_BCX_SRGBA_HIGH) {
|
||||
alphaMode = nvtt::AlphaMode_Transparency;
|
||||
compressionOptions.setFormat(nvtt::Format_BC7);
|
||||
|
|
|
@ -57,6 +57,7 @@ namespace TextureUsage {
|
|||
* @typedef {number} TextureCache.TextureType
|
||||
*/
|
||||
enum Type {
|
||||
// NOTE: add new texture types at the bottom here
|
||||
DEFAULT_TEXTURE,
|
||||
STRICT_TEXTURE,
|
||||
ALBEDO_TEXTURE,
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include <QJsonObject>
|
||||
|
||||
const QString TEXTURE_META_EXTENSION = ".texmeta.json";
|
||||
const uint16_t KTX_VERSION = 1;
|
||||
|
||||
bool TextureMeta::deserialize(const QByteArray& data, TextureMeta* meta) {
|
||||
QJsonParseError error;
|
||||
|
@ -46,6 +47,9 @@ bool TextureMeta::deserialize(const QByteArray& data, TextureMeta* meta) {
|
|||
}
|
||||
}
|
||||
}
|
||||
if (root.contains("version")) {
|
||||
meta->version = root["version"].toInt();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -62,6 +66,7 @@ QByteArray TextureMeta::serialize() {
|
|||
root["original"] = original.toString();
|
||||
root["uncompressed"] = uncompressed.toString();
|
||||
root["compressed"] = compressed;
|
||||
root["version"] = KTX_VERSION;
|
||||
doc.setObject(root);
|
||||
|
||||
return doc.toJson();
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "khronos/KHR.h"
|
||||
|
||||
extern const QString TEXTURE_META_EXTENSION;
|
||||
extern const uint16_t KTX_VERSION;
|
||||
|
||||
namespace std {
|
||||
template<> struct hash<khronos::gl::texture::InternalFormat> {
|
||||
|
@ -37,6 +38,7 @@ struct TextureMeta {
|
|||
QUrl original;
|
||||
QUrl uncompressed;
|
||||
std::unordered_map<khronos::gl::texture::InternalFormat, QUrl> availableTextureTypes;
|
||||
uint16_t version { 0 };
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ namespace baker {
|
|||
class GetModelPartsTask {
|
||||
public:
|
||||
using Input = hfm::Model::Pointer;
|
||||
using Output = VaryingSet6<std::vector<hfm::Mesh>, hifi::URL, baker::MeshIndicesToModelNames, baker::BlendshapesPerMesh, QHash<QString, hfm::Material>, std::vector<hfm::Joint>>;
|
||||
using Output = VaryingSet5<std::vector<hfm::Mesh>, hifi::URL, baker::MeshIndicesToModelNames, baker::BlendshapesPerMesh, std::vector<hfm::Joint>>;
|
||||
using JobModel = Job::ModelIO<GetModelPartsTask, Input, Output>;
|
||||
|
||||
void run(const BakeContextPointer& context, const Input& input, Output& output) {
|
||||
|
@ -40,8 +40,7 @@ namespace baker {
|
|||
for (int i = 0; i < hfmModelIn->meshes.size(); i++) {
|
||||
blendshapesPerMesh.push_back(hfmModelIn->meshes[i].blendshapes.toStdVector());
|
||||
}
|
||||
output.edit4() = hfmModelIn->materials;
|
||||
output.edit5() = hfmModelIn->joints.toStdVector();
|
||||
output.edit4() = hfmModelIn->joints.toStdVector();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -134,17 +133,16 @@ namespace baker {
|
|||
const auto url = modelPartsIn.getN<GetModelPartsTask::Output>(1);
|
||||
const auto meshIndicesToModelNames = modelPartsIn.getN<GetModelPartsTask::Output>(2);
|
||||
const auto blendshapesPerMeshIn = modelPartsIn.getN<GetModelPartsTask::Output>(3);
|
||||
const auto materials = modelPartsIn.getN<GetModelPartsTask::Output>(4);
|
||||
const auto jointsIn = modelPartsIn.getN<GetModelPartsTask::Output>(5);
|
||||
const auto jointsIn = modelPartsIn.getN<GetModelPartsTask::Output>(4);
|
||||
|
||||
// Calculate normals and tangents for meshes and blendshapes if they do not exist
|
||||
// Note: Normals are never calculated here for OBJ models. OBJ files optionally define normals on a per-face basis, so for consistency normals are calculated beforehand in OBJSerializer.
|
||||
const auto normalsPerMesh = model.addJob<CalculateMeshNormalsTask>("CalculateMeshNormals", meshesIn);
|
||||
const auto calculateMeshTangentsInputs = CalculateMeshTangentsTask::Input(normalsPerMesh, meshesIn, materials).asVarying();
|
||||
const auto calculateMeshTangentsInputs = CalculateMeshTangentsTask::Input(normalsPerMesh, meshesIn).asVarying();
|
||||
const auto tangentsPerMesh = model.addJob<CalculateMeshTangentsTask>("CalculateMeshTangents", calculateMeshTangentsInputs);
|
||||
const auto calculateBlendshapeNormalsInputs = CalculateBlendshapeNormalsTask::Input(blendshapesPerMeshIn, meshesIn).asVarying();
|
||||
const auto normalsPerBlendshapePerMesh = model.addJob<CalculateBlendshapeNormalsTask>("CalculateBlendshapeNormals", calculateBlendshapeNormalsInputs);
|
||||
const auto calculateBlendshapeTangentsInputs = CalculateBlendshapeTangentsTask::Input(normalsPerBlendshapePerMesh, blendshapesPerMeshIn, meshesIn, materials).asVarying();
|
||||
const auto calculateBlendshapeTangentsInputs = CalculateBlendshapeTangentsTask::Input(normalsPerBlendshapePerMesh, blendshapesPerMeshIn, meshesIn).asVarying();
|
||||
const auto tangentsPerBlendshapePerMesh = model.addJob<CalculateBlendshapeTangentsTask>("CalculateBlendshapeTangents", calculateBlendshapeTangentsInputs);
|
||||
|
||||
// Build the graphics::MeshPointer for each hfm::Mesh
|
||||
|
|
|
@ -19,7 +19,6 @@ void CalculateBlendshapeTangentsTask::run(const baker::BakeContextPointer& conte
|
|||
const auto& normalsPerBlendshapePerMesh = input.get0();
|
||||
const auto& blendshapesPerMesh = input.get1();
|
||||
const auto& meshes = input.get2();
|
||||
const auto& materials = input.get3();
|
||||
auto& tangentsPerBlendshapePerMeshOut = output;
|
||||
|
||||
tangentsPerBlendshapePerMeshOut.reserve(normalsPerBlendshapePerMesh.size());
|
||||
|
@ -30,16 +29,6 @@ void CalculateBlendshapeTangentsTask::run(const baker::BakeContextPointer& conte
|
|||
tangentsPerBlendshapePerMeshOut.emplace_back();
|
||||
auto& tangentsPerBlendshapeOut = tangentsPerBlendshapePerMeshOut[tangentsPerBlendshapePerMeshOut.size()-1];
|
||||
|
||||
// Check if we actually need to calculate the tangents, or just append empty arrays
|
||||
bool needTangents = false;
|
||||
for (const auto& meshPart : mesh.parts) {
|
||||
auto materialIt = materials.find(meshPart.materialID);
|
||||
if (materialIt != materials.end() && (*materialIt).needTangentSpace()) {
|
||||
needTangents = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t j = 0; j < blendshapes.size(); j++) {
|
||||
const auto& blendshape = blendshapes[j];
|
||||
const auto& tangentsIn = blendshape.tangents;
|
||||
|
@ -53,8 +42,8 @@ void CalculateBlendshapeTangentsTask::run(const baker::BakeContextPointer& conte
|
|||
continue;
|
||||
}
|
||||
|
||||
// Check if we can and should calculate tangents (we need normals to calculate the tangents)
|
||||
if (normals.empty() || !needTangents) {
|
||||
// Check if we can calculate tangents (we need normals and texcoords to calculate the tangents)
|
||||
if (normals.empty() || normals.size() != (size_t)mesh.texCoords.size()) {
|
||||
continue;
|
||||
}
|
||||
tangentsOut.resize(normals.size());
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue