diff --git a/.clang-format b/.clang-format
new file mode 100644
index 0000000000..f000a27017
--- /dev/null
+++ b/.clang-format
@@ -0,0 +1,39 @@
+Language: Cpp
+Standard: Cpp11
+BasedOnStyle: "Chromium"
+ColumnLimit: 128
+IndentWidth: 4
+UseTab: Never
+
+BreakBeforeBraces: Custom
+BraceWrapping:
+ AfterEnum: true
+ AfterClass: false
+ AfterControlStatement: false
+ AfterFunction: false
+ AfterNamespace: false
+ AfterStruct: false
+ AfterUnion: false
+ BeforeCatch: false
+ BeforeElse: false
+ SplitEmptyFunction: false
+ SplitEmptyNamespace: true
+
+
+AccessModifierOffset: -4
+AllowShortFunctionsOnASingleLine: InlineOnly
+BreakConstructorInitializers: BeforeColon
+BreakConstructorInitializersBeforeComma: true
+IndentCaseLabels: true
+ReflowComments: false
+Cpp11BracedListStyle: false
+ContinuationIndentWidth: 4
+ConstructorInitializerAllOnOneLineOrOnePerLine: false
+CompactNamespaces: true
+SortIncludes: false
+SpaceBeforeAssignmentOperators: true
+SpaceBeforeParens: ControlStatements
+
+PenaltyReturnTypeOnItsOwnLine: 1000
+PenaltyBreakBeforeFirstCallParameter: 1000
+
diff --git a/.eslintrc.js b/.eslintrc.js
index 54ff0a1268..5667a04984 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -68,7 +68,7 @@ module.exports = {
"eqeqeq": ["error", "always"],
"indent": ["error", 4, { "SwitchCase": 1 }],
"keyword-spacing": ["error", { "before": true, "after": true }],
- "max-len": ["error", 192, 4],
+ "max-len": ["error", 128, 4],
"new-cap": ["error"],
"no-floating-decimal": ["error"],
//"no-magic-numbers": ["error", { "ignore": [0, 1], "ignoreArrayIndexes": true }],
diff --git a/.gitignore b/.gitignore
index da71a5e1c3..700abee4cd 100644
--- a/.gitignore
+++ b/.gitignore
@@ -15,7 +15,9 @@ Makefile
# Android Studio
*.iml
local.properties
-android/libraries
+android/gradle*
+android/.gradle
+android/app/src/main/jniLibs
# VSCode
# List taken from Github Global Ignores master@435c4d92
@@ -64,6 +66,10 @@ gvr-interface/libs/*
# ignore files for various dev environments
TAGS
*.sw[po]
+*.qmlc
+
+# ignore QML compilation output
+*.qmlc
# ignore node files for the console
node_modules
diff --git a/BUILD.md b/BUILD.md
index 4d321146c3..feed677828 100644
--- a/BUILD.md
+++ b/BUILD.md
@@ -25,7 +25,7 @@ The above dependencies will be downloaded, built, linked and included automatica
These are not placed in your normal build tree when doing an out of source build so that they do not need to be re-downloaded and re-compiled every time the CMake build folder is cleared. Should you want to force a re-download and re-compile of a specific external, you can simply remove that directory from the appropriate subfolder in `build/ext`. Should you want to force a re-download and re-compile of all externals, just remove the `build/ext` folder.
-If you would like to use a specific install of a dependency instead of the version that would be grabbed as a CMake ExternalProject, you can pass -DUSE_LOCAL_$NAME=0 (where $NAME is the name of the subfolder in [cmake/externals](cmake/externals)) when you run CMake to tell it not to get that dependency as an external project.
+If you would like to use a specific install of a dependency instead of the version that would be grabbed as a CMake ExternalProject, you can pass -DUSE\_LOCAL\_$NAME=0 (where $NAME is the name of the subfolder in [cmake/externals](cmake/externals)) when you run CMake to tell it not to get that dependency as an external project.
### OS Specific Build Guides
diff --git a/BUILD_ANDROID.md b/BUILD_ANDROID.md
index cc51e58b1d..5d2e6b9293 100644
--- a/BUILD_ANDROID.md
+++ b/BUILD_ANDROID.md
@@ -1,25 +1,23 @@
-Please read the [general build guide](BUILD.md) for information on dependencies required for all platforms. Only Android specific instructions are found in this file.
+Please read the [general build guide](BUILD.md) for information on building other platform. Only Android specific instructions are found in this file.
-# Android Dependencies
+# Dependencies
+
+*Currently Android building is only supported on 64 bit Linux host environments*
You will need the following tools to build our Android targets.
-* [Qt](http://www.qt.io/download-open-source/#) ~> 5.9.1
+* [Gradle](https://gradle.org/install/)
* [Android Studio](https://developer.android.com/studio/index.html)
-* [Google VR SDK](https://github.com/googlevr/gvr-android-sdk/releases)
-* [Gradle](https://gradle.org/releases/)
-### Qt
+### Gradle
-Download the Qt online installer. Run the installer and select the android_armv7 binaries. Installing to the default path is recommended
+Install gradle version 4.1 or higher. Following the instructions to install via [SDKMAN!](http://sdkman.io/install.html) is recommended.
### 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 level 26.
-
-* Install the ARM EABI v7a System Image if you want to run an emulator.
+From the SDK Platforms tab, select API levels 24 and 26.
From the SDK Tools tab select the following
@@ -29,123 +27,41 @@ From the SDK Tools tab select the following
* LLDB
* Android SDK Platform-Tools
* Android SDK Tools
-* Android SDK Tools
* NDK (even if you have the NDK installed separately)
-### Google VR SDK
+# Environment
-Download the 1.8 Google VR SDK [release](https://github.com/googlevr/gvr-android-sdk/archive/v1.80.0.zip). Unzip the archive to a location on your drive.
-
-### Gradle
-
-Download [Gradle 4.1](https://services.gradle.org/distributions/gradle-4.1-all.zip) and unzip it on your local drive. You may wish to add the location of the bin directory within the archive to your path
+Setting up the environment for android builds requires some additional steps
#### Set up machine specific Gradle properties
-Create a `gradle.properties` file in ~/.gradle. Edit the file to contain the following
+Create a `gradle.properties` file in $HOME/.gradle. Edit the file to contain the following
- QT5_ROOT=C\:\\Qt\\5.9.1\\android_armv7
- GVR_ROOT=C\:\\Android\\gvr-android-sdk
+ HIFI_ANDROID_PRECOMPILED=/Android/hifi_externals
-Replace the paths with your local installations of Qt5 and the Google VR SDK
+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`
+
+Execute a gradle pre-build setup. This step should only need to be done once
+
+`gradle setupDepedencies`
-# TODO fix the rest
+# Building & Running
-You will also need to cross-compile the dependencies required for all platforms for Android, and help CMake find these compiled libraries on your machine.
+* Open Android Studio
+* Choose _Open Existing Android Studio Project_
+* Navigate to the `hifi` repository and choose the `android` folder and select _OK_
+* If Android Studio asks you if you want to use the Gradle wrapper, select cancel and tell it where your local gradle installation is. If you used SDKMAN to install gradle it will be located in `$HOME/.sdkman/candidates/gradle/current/`
+* From the _Build_ menu select _Make Project_
+* Once the build completes, from the _Run_ menu select _Run App_
-#### Scribe
-
-High Fidelity has a shader pre-processing tool called `scribe` that various libraries will call on during the build process. You must compile scribe using your native toolchain (following the build instructions for your platform) and then pass a CMake variable or set an ENV variable `SCRIBE_PATH` that is a path to the scribe executable.
-
-CMake will fatally error if it does not find the scribe executable while using the android toolchain.
-
-#### Optional Components
-
-* [Oculus Mobile SDK](https://developer.oculus.com/downloads/#sdk=mobile) ~> 0.4.2
-
-#### ANDROID_LIB_DIR
-
-Since you won't be installing Android dependencies to system paths on your development machine, CMake will need a little help tracking down your Android dependencies.
-
-This is most easily accomplished by installing all Android dependencies in the same folder. You can place this folder wherever you like on your machine. In this build guide and across our CMakeLists files this folder is referred to as `ANDROID_LIB_DIR`. You can set `ANDROID_LIB_DIR` in your environment or by passing when you run CMake.
-
-#### Qt
-
-Install Qt 5.5.1 for Android for your host environment from the [Qt downloads page](http://www.qt.io/download/). Install Qt to ``$ANDROID_LIB_DIR/Qt``. This is required so that our root CMakeLists file can help CMake find your Android Qt installation.
-
-The component required for the Android build is the `Android armv7` component.
-
-If you would like to install Qt to a different location, or attempt to build with a different Qt version, you can pass `ANDROID_QT_CMAKE_PREFIX_PATH` to CMake. Point to the `cmake` folder inside `$VERSION_NUMBER/android_armv7/lib`. Otherwise, our root CMakeLists will set it to `$ANDROID_LIB_DIR/Qt/5.5/android_armv7/lib/cmake`.
-
-#### OpenSSL
-
-Cross-compilation of OpenSSL has been tested from an OS X machine running 10.10 compiling OpenSSL 1.0.2. It is likely that the steps below will work for other OpenSSL versions than 1.0.2.
-
-The original instructions to compile OpenSSL for Android from your host environment can be found [here](http://wiki.openssl.org/index.php/Android). We required some tweaks to get OpenSSL to successfully compile, those tweaks are explained below.
-
-Download the [OpenSSL source](https://www.openssl.org/source/) and extract the tarball inside your `ANDROID_LIB_DIR`. Rename the extracted folder to `openssl`.
-
-You will need the [setenv-android.sh script](http://wiki.openssl.org/index.php/File:Setenv-android.sh) from the OpenSSL wiki.
-
-You must change three values at the top of the `setenv-android.sh` script - `_ANDROID_NDK`, `_ANDROID_EABI` and `_ANDROID_API`.
-`_ANDROID_NDK` should be `android-ndk-r10`, `_ANDROID_EABI` should be `arm-linux-androidebi-4.9` and `_ANDROID_API` should be `19`.
-
-First, make sure `ANDROID_NDK_ROOT` is set in your env. This should be the path to the root of your Android NDK install. `setenv-android.sh` needs `ANDROID_NDK_ROOT` to set the environment variables required for building OpenSSL.
-
-Source the `setenv-android.sh` script so it can set environment variables that OpenSSL will use while compiling. If you use zsh as your shell you may need to modify the `setenv-android.sh` for it to set the correct variables in your env.
-
-```
-export ANDROID_NDK_ROOT=YOUR_NDK_ROOT
-source setenv-android.sh
-```
-
-Then, from the OpenSSL directory, run the following commands.
-
-```
-perl -pi -e 's/install: all install_docs install_sw/install: install_docs install_sw/g' Makefile.org
-./config shared -no-ssl2 -no-ssl3 -no-comp -no-hw -no-engine --openssldir=/usr/local/ssl/$ANDROID_API
-make depend
-make all
-```
-
-This should generate libcrypto and libssl in the root of the OpenSSL directory. YOU MUST remove the `libssl.so` and `libcrypto.so` files that are generated. They are symlinks to `libssl.so.VER` and `libcrypto.so.VER` which Android does not know how to handle. By removing `libssl.so` and `libcrypto.so` the FindOpenSSL module will find the static libs and use those instead.
-
-If you have been building other components it is possible that the OpenSSL compile will fail based on the values other cross-compilations (tbb, bullet) have set. Ensure that you are in a new terminal window to avoid compilation errors from previously set environment variables.
-
-#### Oculus Mobile SDK
-
-The Oculus Mobile SDK is optional, for Gear VR support. It is not required to compile gvr-interface.
-
-Download the [Oculus Mobile SDK](https://developer.oculus.com/downloads/#sdk=mobile) and extract the archive inside your `ANDROID_LIB_DIR` folder. Rename the extracted folder to `libovr`.
-
-From the VRLib directory, use ndk-build to build VrLib.
-
-```
-cd VRLib
-ndk-build
-```
-
-This will create the liboculus.a archive that our FindLibOVR module will look for when cmake is run.
-
-##### Hybrid testing
-
-Currently the 'vr_dual' mode that would allow us to run a hybrid app has limited support in the Oculus Mobile SDK. The best way to have an application we can launch without having to connect to the GearVR is to put the Gear VR Service into developer mode. This stops Oculus Home from taking over the device when it is plugged into the Gear VR headset, and allows the application to be launched from the Applications page.
-
-To put the Gear VR Service into developer mode you need an application with an Oculus Signature File on your device. Generate an Oculus Signature File for your device on the [Oculus osig tool page](https://developer.oculus.com/tools/osig/). Place this file in the gvr-interface/assets directory. Cmake will automatically copy it into your apk in the right place when you execute `make gvr-interface-apk`.
-
-Once the application is on your device, go to `Settings->Application Manager->Gear VR Service->Manage Storage`. Tap on `VR Service Version` six times. It will scan your device to verify that you have an osig file in an application on your device, and then it will let you enable Developer mode.
-
-### CMake
-
-We use CMake to generate the makefiles that compile and deploy the Android APKs to your device. In order to create Makefiles for the Android targets, CMake requires that some environment variables are set, and that other variables are passed to it when it is run.
-
-The following must be set in your environment:
-
-* ANDROID_NDK - the root of your Android NDK install
-* ANDROID_HOME - the root of your Android SDK install
-* ANDROID_LIB_DIR - the directory containing cross-compiled versions of dependencies
-
-The following must be passed to CMake when it is run:
-
-* USE_ANDROID_TOOLCHAIN - set to true to build for Android
diff --git a/README.md b/README.md
index 6294981e9a..e0bbed3105 100644
--- a/README.md
+++ b/README.md
@@ -19,6 +19,10 @@ Documentation is available at [docs.highfidelity.com](https://docs.highfidelity.
There is also detailed [documentation on our coding standards](https://wiki.highfidelity.com/wiki/Coding_Standards).
+Contributor License Agreement (CLA)
+=========
+Technology companies frequently receive and use code from contributors outside the company's development team. Outside code can be a tremendous resource, but it also carries responsibility. Best practice for accepting outside contributions consists of an Apache-type Contributor License Agreement (CLA). We have modeled the High Fidelity CLA after the CLA that Google presents to developers for contributions to their projects. This CLA does not transfer ownership of code, instead simply granting a non-exclusive right for High Fidelity to use the code you’ve contributed. In that regard, you should be sure you have permission if the work relates to or uses the resources of a company that you work for. You will be asked to sign our CLA when you create your first PR or when the CLA is updated. You can also [review it here](https://gist.githubusercontent.com/hifi-gustavo/fef8f06a8233d42a0040d45c3efb97a9/raw/9981827eb94f0b18666083670b6f6a02929fb402/High%2520Fidelity%2520CLA). We sincerely appreciate your contribution and efforts toward the success of the platform.
+
Build Instructions
=========
All information required to build is found in the [build guide](BUILD.md).
diff --git a/android/app/CMakeLists.txt b/android/app/CMakeLists.txt
index 2d6df925e9..3d4516d0bf 100644
--- a/android/app/CMakeLists.txt
+++ b/android/app/CMakeLists.txt
@@ -1,8 +1,10 @@
set(TARGET_NAME native-lib)
setup_hifi_library()
-link_hifi_libraries(shared networking gl gpu gpu-gles render-utils)
-autoscribe_shader_lib(gpu model render render-utils)
-target_opengl()
+link_hifi_libraries(shared networking gl gpu gpu-gles image fbx render-utils physics)
+
target_link_libraries(native-lib android log m)
-target_include_directories(native-lib PRIVATE "${GVR_ROOT}/libraries/headers")
-target_link_libraries(native-lib "C:/Users/bdavis/Git/hifi/android/libraries/jni/armeabi-v7a/libgvr.so")
+
+target_opengl()
+target_googlevr()
+
+
diff --git a/android/app/build.gradle b/android/app/build.gradle
index bd1c596bf3..29b7e4a6cc 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -1,27 +1,32 @@
apply plugin: 'com.android.application'
+ext.RELEASE_NUMBER = project.hasProperty('RELEASE_NUMBER') ? project.getProperty('RELEASE_NUMBER') : '0'
+ext.RELEASE_TYPE = project.hasProperty('RELEASE_TYPE') ? project.getProperty('RELEASE_TYPE') : 'DEV'
+ext.BUILD_BRANCH = project.hasProperty('BUILD_BRANCH') ? project.getProperty('BUILD_BRANCH') : ''
+
android {
compileSdkVersion 26
- buildToolsVersion "26.0.1"
defaultConfig {
applicationId "org.saintandreas.testapp"
minSdkVersion 24
targetSdkVersion 26
versionCode 1
versionName "1.0"
- ndk { abiFilters 'armeabi-v7a' }
+ ndk { abiFilters 'arm64-v8a' }
externalNativeBuild {
cmake {
arguments '-DHIFI_ANDROID=1',
'-DANDROID_PLATFORM=android-24',
'-DANDROID_TOOLCHAIN=clang',
- '-DANDROID_STL=gnustl_shared',
- '-DGVR_ROOT=' + GVR_ROOT,
- '-DNATIVE_SCRIBE=c:/bin/scribe.exe',
- "-DHIFI_ANDROID_PRECOMPILED=${project.rootDir}/libraries/jni/armeabi-v7a"
+ '-DANDROID_STL=c++_shared',
+ '-DQT_CMAKE_PREFIX_PATH=' + HIFI_ANDROID_PRECOMPILED + '/qt/lib/cmake',
+ '-DNATIVE_SCRIBE=' + HIFI_ANDROID_PRECOMPILED + '/scribe',
+ '-DHIFI_ANDROID_PRECOMPILED=' + HIFI_ANDROID_PRECOMPILED,
+ '-DRELEASE_NUMBER=' + RELEASE_NUMBER,
+ '-DRELEASE_TYPE=' + RELEASE_TYPE,
+ '-DBUILD_BRANCH=' + BUILD_BRANCH
}
}
- jackOptions { enabled true }
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
@@ -29,17 +34,20 @@ android {
}
buildTypes {
+ applicationVariants.all { variant ->
+ variant.outputs.all {
+ if (RELEASE_NUMBER != '0') {
+ outputFileName = "app_" + RELEASE_NUMBER + "_" + RELEASE_TYPE + ".apk"
+ }
+ }
+ }
+
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
- sourceSets {
- main {
- jniLibs.srcDirs += '../libraries/jni';
- }
- }
externalNativeBuild {
cmake {
path '../../CMakeLists.txt'
@@ -53,5 +61,3 @@ dependencies {
compile 'com.google.vr:sdk-audio:1.80.0'
compile 'com.google.vr:sdk-base:1.80.0'
}
-
-build.dependsOn(':extractQt5')
diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
index 05547bd5ae..c96ac0ef90 100644
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -7,12 +7,10 @@
-
-
-
-
-
-
-
-
diff --git a/android/app/src/main/cpp/native-lib.cpp b/android/app/src/main/cpp/native-lib.cpp
index 156d43d849..fe21a250de 100644
--- a/android/app/src/main/cpp/native-lib.cpp
+++ b/android/app/src/main/cpp/native-lib.cpp
@@ -37,12 +37,7 @@ extern "C" {
JNI_METHOD(jlong, nativeCreateRenderer)
(JNIEnv *env, jclass clazz, jobject class_loader, jobject android_context, jlong native_gvr_api) {
qInstallMessageHandler(messageHandler);
-#if defined(GVR)
- auto gvrContext = reinterpret_cast(native_gvr_api);
- return toJni(new NativeRenderer(gvrContext));
-#else
- return toJni(new NativeRenderer(nullptr));
-#endif
+ return toJni(new NativeRenderer());
}
JNI_METHOD(void, nativeDestroyRenderer)
diff --git a/android/app/src/main/cpp/renderer.cpp b/android/app/src/main/cpp/renderer.cpp
index a877ebd777..3b23b7e187 100644
--- a/android/app/src/main/cpp/renderer.cpp
+++ b/android/app/src/main/cpp/renderer.cpp
@@ -1,138 +1,14 @@
#include "renderer.h"
#include
+#include
#include
+
#include
-
-#include "GoogleVRHelpers.h"
-
#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include
-#include
-#include
-#include
-
-#include
-#include
-#include
-
-#include
-#include
-
-#include
-#include
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include
-#include
-
-#if 0
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#endif
-
-
-template
-void withFrameBuffer(gvr::Frame& frame, int32_t index, F f) {
- frame.BindBuffer(index);
- f();
- frame.Unbind();
-}
-
-
-static const uint64_t kPredictionTimeWithoutVsyncNanos = 50000000;
-
-// Each shader has two variants: a single-eye ES 2.0 variant, and a multiview
-// ES 3.0 variant. The multiview vertex shaders use transforms defined by
-// arrays of mat4 uniforms, using gl_ViewID_OVR to determine the array index.
-
-#define UNIFORM_LIGHT_POS 20
-#define UNIFORM_M 16
-#define UNIFORM_MV 8
-#define UNIFORM_MVP 0
-
-#if 0
-uniform Transform { // API uses “Transform[2]” to refer to instance 2
- mat4 u_MVP[2];
- mat4 u_MVMatrix[2];
- mat4 u_Model;
- vec3 u_LightPos[2];
-};
-static const char *kDiffuseLightingVertexShader = R"glsl(
-#version 300 es
-#extension GL_OVR_multiview2 : enable
-
-layout(num_views=2) in;
-
-layout(location = 0) uniform mat4 u_MVP[2];
-layout(location = 8) uniform mat4 u_MVMatrix[2];
-layout(location = 16) uniform mat4 u_Model;
-layout(location = 20) uniform vec3 u_LightPos[2];
-
-layout(location = 0) in vec4 a_Position;
-layout(location = 1) in vec4 a_Color;
-layout(location = 2) in vec3 a_Normal;
-
-out vec4 v_Color;
-out vec3 v_Grid;
-
-void main() {
- mat4 mvp = u_MVP[gl_ViewID_OVR];
- mat4 modelview = u_MVMatrix[gl_ViewID_OVR];
- vec3 lightpos = u_LightPos[gl_ViewID_OVR];
- v_Grid = vec3(u_Model * a_Position);
- vec3 modelViewVertex = vec3(modelview * a_Position);
- vec3 modelViewNormal = vec3(modelview * vec4(a_Normal, 0.0));
- float distance = length(lightpos - modelViewVertex);
- vec3 lightVector = normalize(lightpos - modelViewVertex);
- float diffuse = max(dot(modelViewNormal, lightVector), 0.5);
- diffuse = diffuse * (1.0 / (1.0 + (0.00001 * distance * distance)));
- v_Color = vec4(a_Color.rgb * diffuse, a_Color.a);
- gl_Position = mvp * a_Position;
-}
-)glsl";
-#endif
-
-
-static const char *kSimepleVertexShader = R"glsl(
-#version 300 es
+static const char *kSimepleVertexShader = R"glsl(#version 300 es
#extension GL_OVR_multiview2 : enable
layout(num_views=2) in;
@@ -147,9 +23,7 @@ void main() {
}
)glsl";
-
-static const char *kPassthroughFragmentShader = R"glsl(
-#version 300 es
+static const char *kPassthroughFragmentShader = R"glsl(#version 300 es
precision mediump float;
in vec4 v_Color;
out vec4 FragColor;
@@ -157,6 +31,17 @@ out vec4 FragColor;
void main() { FragColor = v_Color; }
)glsl";
+
+int LoadGLShader(int type, const char *shadercode) {
+ GLuint result = 0;
+ std::string shaderError;
+ static const std::string SHADER_DEFINES;
+ if (!gl::compileShader(type, shadercode, SHADER_DEFINES, result, shaderError)) {
+ qWarning() << "QQQ" << __FUNCTION__ << "Shader compile failure" << shaderError.c_str();
+ }
+ return result;
+}
+
static void CheckGLError(const char* label) {
int gl_error = glGetError();
if (gl_error != GL_NO_ERROR) {
@@ -167,158 +52,6 @@ static void CheckGLError(const char* label) {
}
// Contains vertex, normal and other data.
-namespace cube {
- const std::array CUBE_COORDS{{
- // Front face
- -1.0f, 1.0f, 1.0f,
- -1.0f, -1.0f, 1.0f,
- 1.0f, 1.0f, 1.0f,
- -1.0f, -1.0f, 1.0f,
- 1.0f, -1.0f, 1.0f,
- 1.0f, 1.0f, 1.0f,
-
- // Right face
- 1.0f, 1.0f, 1.0f,
- 1.0f, -1.0f, 1.0f,
- 1.0f, 1.0f, -1.0f,
- 1.0f, -1.0f, 1.0f,
- 1.0f, -1.0f, -1.0f,
- 1.0f, 1.0f, -1.0f,
-
- // Back face
- 1.0f, 1.0f, -1.0f,
- 1.0f, -1.0f, -1.0f,
- -1.0f, 1.0f, -1.0f,
- 1.0f, -1.0f, -1.0f,
- -1.0f, -1.0f, -1.0f,
- -1.0f, 1.0f, -1.0f,
-
- // Left face
- -1.0f, 1.0f, -1.0f,
- -1.0f, -1.0f, -1.0f,
- -1.0f, 1.0f, 1.0f,
- -1.0f, -1.0f, -1.0f,
- -1.0f, -1.0f, 1.0f,
- -1.0f, 1.0f, 1.0f,
-
- // Top face
- -1.0f, 1.0f, -1.0f,
- -1.0f, 1.0f, 1.0f,
- 1.0f, 1.0f, -1.0f,
- -1.0f, 1.0f, 1.0f,
- 1.0f, 1.0f, 1.0f,
- 1.0f, 1.0f, -1.0f,
-
- // Bottom face
- 1.0f, -1.0f, -1.0f,
- 1.0f, -1.0f, 1.0f,
- -1.0f, -1.0f, -1.0f,
- 1.0f, -1.0f, 1.0f,
- -1.0f, -1.0f, 1.0f,
- -1.0f, -1.0f, -1.0f
- }};
-
- const std::array CUBE_COLORS{{
- // front, green
- 0.0f, 0.5273f, 0.2656f,
- 0.0f, 0.5273f, 0.2656f,
- 0.0f, 0.5273f, 0.2656f,
- 0.0f, 0.5273f, 0.2656f,
- 0.0f, 0.5273f, 0.2656f,
- 0.0f, 0.5273f, 0.2656f,
-
- // right, blue
- 0.0f, 0.3398f, 0.9023f,
- 0.0f, 0.3398f, 0.9023f,
- 0.0f, 0.3398f, 0.9023f,
- 0.0f, 0.3398f, 0.9023f,
- 0.0f, 0.3398f, 0.9023f,
- 0.0f, 0.3398f, 0.9023f,
-
- // back, also green
- 0.0f, 0.5273f, 0.2656f,
- 0.0f, 0.5273f, 0.2656f,
- 0.0f, 0.5273f, 0.2656f,
- 0.0f, 0.5273f, 0.2656f,
- 0.0f, 0.5273f, 0.2656f,
- 0.0f, 0.5273f, 0.2656f,
-
- // left, also blue
- 0.0f, 0.3398f, 0.9023f,
- 0.0f, 0.3398f, 0.9023f,
- 0.0f, 0.3398f, 0.9023f,
- 0.0f, 0.3398f, 0.9023f,
- 0.0f, 0.3398f, 0.9023f,
- 0.0f, 0.3398f, 0.9023f,
-
- // top, red
- 0.8359375f, 0.17578125f, 0.125f,
- 0.8359375f, 0.17578125f, 0.125f,
- 0.8359375f, 0.17578125f, 0.125f,
- 0.8359375f, 0.17578125f, 0.125f,
- 0.8359375f, 0.17578125f, 0.125f,
- 0.8359375f, 0.17578125f, 0.125f,
-
- // bottom, also red
- 0.8359375f, 0.17578125f, 0.125f,
- 0.8359375f, 0.17578125f, 0.125f,
- 0.8359375f, 0.17578125f, 0.125f,
- 0.8359375f, 0.17578125f, 0.125f,
- 0.8359375f, 0.17578125f, 0.125f,
- 0.8359375f, 0.17578125f, 0.125f
- }};
-
- const std::array CUBE_NORMALS{{
- // Front face
- 0.0f, 0.0f, 1.0f,
- 0.0f, 0.0f, 1.0f,
- 0.0f, 0.0f, 1.0f,
- 0.0f, 0.0f, 1.0f,
- 0.0f, 0.0f, 1.0f,
- 0.0f, 0.0f, 1.0f,
-
- // Right face
- 1.0f, 0.0f, 0.0f,
- 1.0f, 0.0f, 0.0f,
- 1.0f, 0.0f, 0.0f,
- 1.0f, 0.0f, 0.0f,
- 1.0f, 0.0f, 0.0f,
- 1.0f, 0.0f, 0.0f,
-
- // Back face
- 0.0f, 0.0f, -1.0f,
- 0.0f, 0.0f, -1.0f,
- 0.0f, 0.0f, -1.0f,
- 0.0f, 0.0f, -1.0f,
- 0.0f, 0.0f, -1.0f,
- 0.0f, 0.0f, -1.0f,
-
- // Left face
- -1.0f, 0.0f, 0.0f,
- -1.0f, 0.0f, 0.0f,
- -1.0f, 0.0f, 0.0f,
- -1.0f, 0.0f, 0.0f,
- -1.0f, 0.0f, 0.0f,
- -1.0f, 0.0f, 0.0f,
-
- // Top face
- 0.0f, 1.0f, 0.0f,
- 0.0f, 1.0f, 0.0f,
- 0.0f, 1.0f, 0.0f,
- 0.0f, 1.0f, 0.0f,
- 0.0f, 1.0f, 0.0f,
- 0.0f, 1.0f, 0.0f,
-
- // Bottom face
- 0.0f, -1.0f, 0.0f,
- 0.0f, -1.0f, 0.0f,
- 0.0f, -1.0f, 0.0f,
- 0.0f, -1.0f, 0.0f,
- 0.0f, -1.0f, 0.0f,
- 0.0f, -1.0f, 0.0f
- }};
-}
-
namespace triangle {
static std::array TRIANGLE_VERTS {{
-0.5f, -0.5f, 0.0f,
@@ -327,229 +60,36 @@ namespace triangle {
}};
}
-std::array buildViewports(const std::unique_ptr &gvrapi) {
- return { {gvrapi->CreateBufferViewport(), gvrapi->CreateBufferViewport()} };
-};
-
-const std::string VERTEX_SHADER_DEFINES{ R"GLSL(
-#version 300 es
-#extension GL_EXT_clip_cull_distance : enable
-#define GPU_VERTEX_SHADER
-#define GPU_SSBO_TRANSFORM_OBJECT 1
-#define GPU_TRANSFORM_IS_STEREO
-#define GPU_TRANSFORM_STEREO_CAMERA
-#define GPU_TRANSFORM_STEREO_CAMERA_INSTANCED
-#define GPU_TRANSFORM_STEREO_SPLIT_SCREEN
-)GLSL" };
-
-const std::string PIXEL_SHADER_DEFINES{ R"GLSL(
-#version 300 es
-precision mediump float;
-#define GPU_PIXEL_SHADER
-#define GPU_TRANSFORM_IS_STEREO
-#define GPU_TRANSFORM_STEREO_CAMERA
-#define GPU_TRANSFORM_STEREO_CAMERA_INSTANCED
-#define GPU_TRANSFORM_STEREO_SPLIT_SCREEN
-)GLSL" };
-
-
-#if defined(GVR)
-NativeRenderer::NativeRenderer(gvr_context *vrContext) :
- _gvrapi(new gvr::GvrApi(vrContext, false)),
- _viewports(buildViewports(_gvrapi)),
- _gvr_viewer_type(_gvrapi->GetViewerType())
-#else
-NativeRenderer::NativeRenderer(void *vrContext)
-#endif
-{
- start = std::chrono::system_clock::now();
- qDebug() << "QQQ" << __FUNCTION__;
-}
-
-
-/**
- * Converts a raw text file, saved as a resource, into an OpenGL ES shader.
- *
- * @param type The type of shader we will be creating.
- * @param resId The resource ID of the raw text file.
- * @return The shader object handler.
- */
-int LoadGLShader(int type, const char *shadercode) {
- GLuint result = 0;
- std::string shaderError;
- static const std::string SHADER_DEFINES;
- if (!gl::compileShader(type, shadercode, SHADER_DEFINES, result, shaderError)) {
- qWarning() << "QQQ" << __FUNCTION__ << "Shader compile failure" << shaderError.c_str();
- }
- return result;
-}
-
-// Computes a texture size that has approximately half as many pixels. This is
-// equivalent to scaling each dimension by approximately sqrt(2)/2.
-static gvr::Sizei HalfPixelCount(const gvr::Sizei &in) {
- // Scale each dimension by sqrt(2)/2 ~= 7/10ths.
- gvr::Sizei out;
- out.width = (7 * in.width) / 10;
- out.height = (7 * in.height) / 10;
- return out;
-}
-
-
-#if defined(GVR)
-void NativeRenderer::InitializeVR() {
- _gvrapi->InitializeGl();
- bool multiviewEnabled = _gvrapi->IsFeatureSupported(GVR_FEATURE_MULTIVIEW);
- qWarning() << "QQQ" << __FUNCTION__ << "Multiview enabled " << multiviewEnabled;
- // Because we are using 2X MSAA, we can render to half as many pixels and
- // achieve similar quality.
- _renderSize = HalfPixelCount(_gvrapi->GetMaximumEffectiveRenderTargetSize());
-
- std::vector specs;
- specs.push_back(_gvrapi->CreateBufferSpec());
- specs[0].SetColorFormat(GVR_COLOR_FORMAT_RGBA_8888);
- specs[0].SetDepthStencilFormat(GVR_DEPTH_STENCIL_FORMAT_DEPTH_16);
- specs[0].SetSamples(2);
- gvr::Sizei half_size = {_renderSize.width / 2, _renderSize.height};
- specs[0].SetMultiviewLayers(2);
- specs[0].SetSize(half_size);
-
- _swapchain.reset(new gvr::SwapChain(_gvrapi->CreateSwapChain(specs)));
- _viewportlist.reset(new gvr::BufferViewportList(_gvrapi->CreateEmptyBufferViewportList()));
-}
-void NativeRenderer::PrepareFramebuffer() {
- const gvr::Sizei recommended_size = HalfPixelCount(
- _gvrapi->GetMaximumEffectiveRenderTargetSize());
- if (_renderSize.width != recommended_size.width ||
- _renderSize.height != recommended_size.height) {
- // We need to resize the framebuffer. Note that multiview uses two texture
- // layers, each with half the render width.
- gvr::Sizei framebuffer_size = recommended_size;
- framebuffer_size.width /= 2;
- _swapchain->ResizeBuffer(0, framebuffer_size);
- _renderSize = recommended_size;
- }
-}
-#endif
-
-void testShaderBuild(const char* vs_src, const char * fs_src) {
- std::string error;
- GLuint vs, fs;
- if (!gl::compileShader(GL_VERTEX_SHADER, vs_src, VERTEX_SHADER_DEFINES, vs, error) ||
- !gl::compileShader(GL_FRAGMENT_SHADER, fs_src, PIXEL_SHADER_DEFINES, fs, error)) {
- throw std::runtime_error("Failed to compile shader");
- }
- auto pr = gl::compileProgram({ vs, fs }, error);
- if (!pr) {
- throw std::runtime_error("Failed to link shader");
- }
-}
void NativeRenderer::InitializeGl() {
- qDebug() << "QQQ" << __FUNCTION__;
- //gl::initModuleGl();
-#if defined(GVR)
- InitializeVR();
-#endif
-
glDisable(GL_DEPTH_TEST);
glDisable(GL_CULL_FACE);
glDisable(GL_SCISSOR_TEST);
glDisable(GL_BLEND);
-
-
const uint32_t vertShader = LoadGLShader(GL_VERTEX_SHADER, kSimepleVertexShader);
- //const uint32_t vertShader = LoadGLShader(GL_VERTEX_SHADER, kDiffuseLightingVertexShader);
const uint32_t fragShader = LoadGLShader(GL_FRAGMENT_SHADER, kPassthroughFragmentShader);
std::string error;
- _cubeProgram = gl::compileProgram({ vertShader, fragShader }, error);
+ _program = gl::compileProgram({ vertShader, fragShader }, error);
CheckGLError("build program");
- glGenBuffers(1, &_cubeBuffer);
- glBindBuffer(GL_ARRAY_BUFFER, _cubeBuffer);
+ glGenBuffers(1, &_geometryBuffer);
+ glBindBuffer(GL_ARRAY_BUFFER, _geometryBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 9, triangle::TRIANGLE_VERTS.data(), GL_STATIC_DRAW);
- /*
- glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 108 * 3, NULL, GL_STATIC_DRAW);
- glBufferSubData(GL_ARRAY_BUFFER, sizeof(float) * 108 * 0, sizeof(float) * 108, cube::CUBE_COORDS.data());
- glBufferSubData(GL_ARRAY_BUFFER, sizeof(float) * 108 * 1, sizeof(float) * 108, cube::CUBE_COLORS.data());
- glBufferSubData(GL_ARRAY_BUFFER, sizeof(float) * 108 * 2, sizeof(float) * 108, cube::CUBE_NORMALS.data());
- */
glBindBuffer(GL_ARRAY_BUFFER, 0);
CheckGLError("upload vertices");
- glGenVertexArrays(1, &_cubeVao);
- glBindBuffer(GL_ARRAY_BUFFER, _cubeBuffer);
- glBindVertexArray(_cubeVao);
+ glGenVertexArrays(1, &_vao);
+ glBindBuffer(GL_ARRAY_BUFFER, _geometryBuffer);
+ glBindVertexArray(_vao);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
- /*
- glVertexAttribPointer(0, 3, GL_FLOAT, false, 0, 0);
- glEnableVertexAttribArray(0);
- glVertexAttribPointer(1, 3, GL_FLOAT, false, 0, (const void*)(sizeof(float) * 108 * 1) );
- glEnableVertexAttribArray(1);
- glVertexAttribPointer(2, 3, GL_FLOAT, false, 0, (const void*)(sizeof(float) * 108 * 2));
- glEnableVertexAttribArray(2);
- */
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
CheckGLError("build vao ");
-
- static std::once_flag once;
- std::call_once(once, [&]{
- testShaderBuild(sdf_text3D_vert, sdf_text3D_frag);
-
- testShaderBuild(DrawTransformUnitQuad_vert, DrawTexture_frag);
- testShaderBuild(DrawTexcoordRectTransformUnitQuad_vert, DrawTexture_frag);
- testShaderBuild(DrawViewportQuadTransformTexcoord_vert, DrawTexture_frag);
- testShaderBuild(DrawTransformUnitQuad_vert, DrawTextureOpaque_frag);
- testShaderBuild(DrawTransformUnitQuad_vert, DrawColoredTexture_frag);
-
- testShaderBuild(simple_vert, simple_frag);
- testShaderBuild(simple_vert, simple_textured_frag);
- testShaderBuild(simple_vert, simple_textured_unlit_frag);
- testShaderBuild(deferred_light_vert, directional_ambient_light_frag);
- testShaderBuild(deferred_light_vert, directional_skybox_light_frag);
- testShaderBuild(standardTransformPNTC_vert, standardDrawTexture_frag);
- testShaderBuild(standardTransformPNTC_vert, DrawTextureOpaque_frag);
-
- testShaderBuild(model_vert, model_frag);
- testShaderBuild(model_normal_map_vert, model_normal_map_frag);
- testShaderBuild(model_vert, model_specular_map_frag);
- testShaderBuild(model_normal_map_vert, model_normal_specular_map_frag);
- testShaderBuild(model_vert, model_translucent_frag);
- testShaderBuild(model_normal_map_vert, model_translucent_frag);
- testShaderBuild(model_lightmap_vert, model_lightmap_frag);
- testShaderBuild(model_lightmap_normal_map_vert, model_lightmap_normal_map_frag);
- testShaderBuild(model_lightmap_vert, model_lightmap_specular_map_frag);
- testShaderBuild(model_lightmap_normal_map_vert, model_lightmap_normal_specular_map_frag);
-
- testShaderBuild(skin_model_vert, model_frag);
- testShaderBuild(skin_model_normal_map_vert, model_normal_map_frag);
- testShaderBuild(skin_model_vert, model_specular_map_frag);
- testShaderBuild(skin_model_normal_map_vert, model_normal_specular_map_frag);
- testShaderBuild(skin_model_vert, model_translucent_frag);
- testShaderBuild(skin_model_normal_map_vert, model_translucent_frag);
-
- testShaderBuild(model_shadow_vert, model_shadow_frag);
-
- testShaderBuild(overlay3D_vert, overlay3D_frag);
-
-#if 0
- testShaderBuild(textured_particle_vert, textured_particle_frag);
- testShaderBuild(skybox_vert, skybox_frag);
- testShaderBuild(paintStroke_vert,paintStroke_frag);
- testShaderBuild(polyvox_vert, polyvox_frag);
-#endif
-
- });
-
- qDebug() << "done";
}
-static const float kZNear = 1.0f;
-static const float kZFar = 100.0f;
-static const gvr_rectf fullscreen = {0, 1, 0, 1};
void NativeRenderer::DrawFrame() {
auto now = std::chrono::duration_cast(
@@ -559,65 +99,12 @@ void NativeRenderer::DrawFrame() {
v.g = 1.0f - v.r;
v.b = 1.0f;
- PrepareFramebuffer();
-
- // A client app does its rendering here.
- gvr::ClockTimePoint target_time = gvr::GvrApi::GetTimePointNow();
- target_time.monotonic_system_time_nanos += kPredictionTimeWithoutVsyncNanos;
-
- using namespace googlevr;
- using namespace bilateral;
- const auto gvrHeadPose = _gvrapi->GetHeadSpaceFromStartSpaceRotation(target_time);
- _head_view = toGlm(gvrHeadPose);
- _viewportlist->SetToRecommendedBufferViewports();
-
- glm::mat4 eye_views[2];
- for_each_side([&](bilateral::Side side) {
- int eye = index(side);
- const gvr::Eye gvr_eye = eye == 0 ? GVR_LEFT_EYE : GVR_RIGHT_EYE;
- const auto& eyeView = eye_views[eye] = toGlm(_gvrapi->GetEyeFromHeadMatrix(gvr_eye)) * _head_view;
- auto& viewport = _viewports[eye];
-
- _viewportlist->GetBufferViewport(eye, &viewport);
- viewport.SetSourceUv(fullscreen);
- viewport.SetSourceLayer(eye);
- _viewportlist->SetBufferViewport(eye, viewport);
- const auto &mvc = _modelview_cube[eye] = eyeView * _model_cube;
- const auto &mvf = _modelview_floor[eye] = eyeView * _model_floor;
- const gvr_rectf fov = viewport.GetSourceFov();
- const glm::mat4 perspective = perspectiveMatrixFromView(fov, kZNear, kZFar);
- _modelview_projection_cube[eye] = perspective * mvc;
- _modelview_projection_floor[eye] = perspective * mvf;
- _light_pos_eye_space[eye] = glm::vec3(eyeView * _light_pos_world_space);
- });
-
-
- gvr::Frame frame = _swapchain->AcquireFrame();
- withFrameBuffer(frame, 0, [&]{
- glClearColor(v.r, v.g, v.b, 1);
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- glViewport(0, 0, _renderSize.width / 2, _renderSize.height);
- glUseProgram(_cubeProgram);
- glBindVertexArray(_cubeVao);
- glDrawArrays(GL_TRIANGLES, 0, 3);
- /*
- float* fp;
- fp = (float*)&_light_pos_eye_space[0];
- glUniform3fv(UNIFORM_LIGHT_POS, 2, fp);
- fp = (float*)&_modelview_cube[0];
- glUniformMatrix4fv(UNIFORM_MV, 2, GL_FALSE, fp);
- fp = (float*)&_modelview_projection_cube[0];
- glUniformMatrix4fv(UNIFORM_MVP, 2, GL_FALSE, fp);
- fp = (float*)&_model_cube;
- glUniformMatrix4fv(UNIFORM_M, 1, GL_FALSE, fp);
- glDrawArrays(GL_TRIANGLES, 0, 36);
- */
- glBindVertexArray(0);
- });
-
- frame.Submit(*_viewportlist, gvrHeadPose);
- CheckGLError("onDrawFrame");
-
+ glClearColor(v.r, v.g, v.b, 1.0f);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ glUseProgram(_program);
+ glBindVertexArray(_vao);
+ glDrawArrays(GL_TRIANGLES, 0, 3);
+ glBindVertexArray(0);
}
void NativeRenderer::OnTriggerEvent() {
@@ -626,11 +113,8 @@ void NativeRenderer::OnTriggerEvent() {
void NativeRenderer::OnPause() {
qDebug() << "QQQ" << __FUNCTION__;
- _gvrapi->PauseTracking();
}
void NativeRenderer::OnResume() {
qDebug() << "QQQ" << __FUNCTION__;
- _gvrapi->ResumeTracking();
- _gvrapi->RefreshViewerProfile();
}
diff --git a/android/app/src/main/cpp/renderer.h b/android/app/src/main/cpp/renderer.h
index df7c51cab4..522f672e3b 100644
--- a/android/app/src/main/cpp/renderer.h
+++ b/android/app/src/main/cpp/renderer.h
@@ -4,21 +4,8 @@
#include
#include
-#define GVR
-
-#if defined(GVR)
-#include
-#endif
-
class NativeRenderer {
public:
-
-#if defined(GVR)
- NativeRenderer(gvr_context* vrContext);
-#else
- NativeRenderer(void* vrContext);
-#endif
-
void InitializeGl();
void DrawFrame();
void OnTriggerEvent();
@@ -26,35 +13,9 @@ public:
void OnResume();
private:
+ std::chrono::time_point start { std::chrono::system_clock::now() };
-
- std::chrono::time_point start;
-#if defined(GVR)
- void InitializeVR();
- void PrepareFramebuffer();
-
- std::unique_ptr _gvrapi;
- gvr::ViewerType _gvr_viewer_type;
- std::unique_ptr _viewportlist;
- std::unique_ptr _swapchain;
- std::array _viewports;
- gvr::Sizei _renderSize;
-#endif
-
- uint32_t _cubeBuffer { 0 };
- uint32_t _cubeVao { 0 };
- uint32_t _cubeProgram { 0 };
-
- glm::mat4 _head_view;
- glm::mat4 _model_cube;
- glm::mat4 _camera;
- glm::mat4 _view;
- glm::mat4 _model_floor;
-
- std::array _modelview_cube;
- std::array _modelview_floor;
- std::array _modelview_projection_cube;
- std::array _modelview_projection_floor;
- std::array _light_pos_eye_space;
- const glm::vec4 _light_pos_world_space{ 0, 2, 0, 1};
+ uint32_t _geometryBuffer { 0 };
+ uint32_t _vao { 0 };
+ uint32_t _program { 0 };
};
diff --git a/android/app/src/main/java/org/saintandreas/testapp/MainActivity.java b/android/app/src/main/java/org/saintandreas/testapp/MainActivity.java
index 7eea14dce9..65e6c394e7 100644
--- a/android/app/src/main/java/org/saintandreas/testapp/MainActivity.java
+++ b/android/app/src/main/java/org/saintandreas/testapp/MainActivity.java
@@ -26,10 +26,9 @@ public class MainActivity extends Activity {
}
private long nativeRenderer;
- private GvrLayout gvrLayout;
private GLSurfaceView surfaceView;
- private native long nativeCreateRenderer(ClassLoader appClassLoader, Context context, long nativeGvrContext);
+ private native long nativeCreateRenderer(ClassLoader appClassLoader, Context context);
private native void nativeDestroyRenderer(long renderer);
private native void nativeInitializeGl(long renderer);
private native void nativeDrawFrame(long renderer);
@@ -55,30 +54,21 @@ public class MainActivity extends Activity {
if ((visibility & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0) { setImmersiveSticky(); }
});
- gvrLayout = new GvrLayout(this);
nativeRenderer = nativeCreateRenderer(
getClass().getClassLoader(),
- getApplicationContext(),
- gvrLayout.getGvrApi().getNativeGvrContext());
+ getApplicationContext());
surfaceView = new GLSurfaceView(this);
surfaceView.setEGLContextClientVersion(3);
surfaceView.setEGLConfigChooser(8, 8, 8, 0, 0, 0);
surfaceView.setPreserveEGLContextOnPause(true);
surfaceView.setRenderer(new NativeRenderer());
-
- gvrLayout.setPresentationView(surfaceView);
- setContentView(gvrLayout);
- if (gvrLayout.setAsyncReprojectionEnabled(true)) {
- AndroidCompat.setSustainedPerformanceMode(this, true);
- }
- AndroidCompat.setVrModeEnabled(this, true);
+ setContentView(surfaceView);
}
@Override
protected void onDestroy() {
super.onDestroy();
- gvrLayout.shutdown();
nativeDestroyRenderer(nativeRenderer);
nativeRenderer = 0;
}
@@ -87,14 +77,12 @@ public class MainActivity extends Activity {
protected void onPause() {
surfaceView.queueEvent(()->nativeOnPause(nativeRenderer));
surfaceView.onPause();
- gvrLayout.onPause();
super.onPause();
}
@Override
protected void onResume() {
super.onResume();
- gvrLayout.onResume();
surfaceView.onResume();
surfaceView.queueEvent(()->nativeOnResume(nativeRenderer));
}
diff --git a/android/build.gradle b/android/build.gradle
index 77c3dd498c..75b1b7ad4e 100644
--- a/android/build.gradle
+++ b/android/build.gradle
@@ -1,91 +1,216 @@
-// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
jcenter()
+ google()
}
dependencies {
- classpath 'com.android.tools.build:gradle:2.3.3'
-
- // NOTE: Do not place your application dependencies here; they belong
- // in the individual module build.gradle files
+ classpath 'com.android.tools.build:gradle:3.0.1'
}
}
+plugins {
+ id 'de.undercouch.download' version '3.3.0'
+}
+
allprojects {
repositories {
jcenter()
+ google()
}
}
+
+def baseFolder = new File(HIFI_ANDROID_PRECOMPILED)
+def jniFolder = new File('app/src/main/jniLibs/arm64-v8a')
+
+import org.apache.tools.ant.taskdefs.condition.Os
+
+def baseUrl = 'https://hifi-public.s3.amazonaws.com/austin/android/'
+def qtFile='qt-5.9.3_linux_armv8-libcpp.tgz'
+def qtChecksum='547da3547d5690144e23d6504c6d6e91'
+if (Os.isFamily(Os.FAMILY_MAC)) {
+ qtFile = 'qt-5.9.3_osx_armv8-libcpp.tgz'
+ qtChecksum='6fa3e068cfdee863fc909b294a3a0cc6'
+} else if (Os.isFamily(Os.FAMILY_WINDOWS)) {
+ qtFile = 'qt-5.9.3_win_armv8-libcpp.tgz'
+ qtChecksum='3a757378a7e9dbbfc662177e0eb46408'
+}
+
+def packages = [
+ qt: [
+ file: qtFile,
+ checksum: qtChecksum,
+ sharedLibFolder: '',
+ includeLibs: ['lib/*.so', 'plugins/*/*.so']
+ ],
+ bullet: [
+ file: 'bullet-2.83_armv8-libcpp.tgz',
+ checksum: '2c558d604fce337f5eba3eb7ec1252fd'
+ ],
+ draco: [
+ file: 'draco_armv8-libcpp.tgz',
+ checksum: '617a80d213a5ec69fbfa21a1f2f738cd'
+ ],
+ gvr: [
+ file: 'gvrsdk_v1.101.0.tgz',
+ checksum: '57fd02baa069176ba18597a29b6b4fc7'
+ ],
+ openssl: [
+ file: 'openssl-1.1.0g_armv8.tgz',
+ checksum: 'cabb681fbccd79594f65fcc266e02f32'
+ ],
+ polyvox: [
+ file: 'polyvox_armv8-libcpp.tgz',
+ checksum: '5c918288741ee754c16aeb12bb46b9e1',
+ sharedLibFolder: 'lib',
+ includeLibs: ['Release/libPolyVoxCore.so', 'libPolyVoxUtil.so']
+ ],
+ tbb: [
+ file: 'tbb-2018_U1_armv8_libcpp.tgz',
+ checksum: '20768f298f53b195e71b414b0ae240c4',
+ sharedLibFolder: 'lib/release',
+ includeLibs: ['libtbb.so', 'libtbbmalloc.so']
+ ]
+]
+
+task downloadDependencies {
+ doLast {
+ packages.each { entry ->
+ def filename = entry.value['file'];
+ def url = baseUrl + filename;
+ download {
+ src url
+ dest new File(baseFolder, filename)
+ onlyIfNewer true
+ }
+ }
+ }
+}
+
+import de.undercouch.gradle.tasks.download.Verify
+
+task verifyQt(type: Verify) { def p = packages['qt']; src new File(baseFolder, p['file']); checksum p['checksum']; }
+task verifyBullet(type: Verify) { def p = packages['bullet']; src new File(baseFolder, p['file']); checksum p['checksum'] }
+task verifyDraco(type: Verify) { def p = packages['draco']; src new File(baseFolder, p['file']); checksum p['checksum'] }
+task verifyGvr(type: Verify) { def p = packages['gvr']; src new File(baseFolder, p['file']); checksum p['checksum'] }
+task verifyOpenSSL(type: Verify) { def p = packages['openssl']; src new File(baseFolder, p['file']); checksum p['checksum'] }
+task verifyPolyvox(type: Verify) { def p = packages['polyvox']; src new File(baseFolder, p['file']); checksum p['checksum'] }
+task verifyTBB(type: Verify) { def p = packages['tbb']; src new File(baseFolder, p['file']); checksum p['checksum'] }
+
+task verifyDependencyDownloads(dependsOn: downloadDependencies) { }
+verifyDependencyDownloads.dependsOn verifyQt
+verifyDependencyDownloads.dependsOn verifyBullet
+verifyDependencyDownloads.dependsOn verifyDraco
+verifyDependencyDownloads.dependsOn verifyGvr
+verifyDependencyDownloads.dependsOn verifyOpenSSL
+verifyDependencyDownloads.dependsOn verifyPolyvox
+verifyDependencyDownloads.dependsOn verifyTBB
+
+task extractDependencies(dependsOn: verifyDependencyDownloads) {
+ doLast {
+ packages.each { entry ->
+ def folder = entry.key;
+ def filename = entry.value['file'];
+ def localFile = new File(HIFI_ANDROID_PRECOMPILED, filename)
+ def localFolder = new File(HIFI_ANDROID_PRECOMPILED, folder)
+ copy {
+ from tarTree(resources.gzip(localFile))
+ into localFolder
+ }
+ }
+ }
+}
+
+task copyDependencies(dependsOn: extractDependencies) {
+ doLast {
+ packages.each { entry ->
+ def packageName = entry.key
+ def currentPackage = entry.value;
+ if (currentPackage.containsKey('sharedLibFolder')) {
+ def localFolder = new File(baseFolder, packageName + '/' + currentPackage['sharedLibFolder'])
+ def tree = fileTree(localFolder);
+ if (currentPackage.containsKey('includeLibs')) {
+ currentPackage['includeLibs'].each { includeSpec -> tree.include includeSpec }
+ }
+ tree.visit { element ->
+ if (!element.file.isDirectory()) {
+ copy { from element.file; into jniFolder }
+ }
+ }
+ }
+ }
+ }
+}
+
+def scribeFile='scribe_linux_x86_64'
+def scribeLocalFile='scribe'
+def scribeChecksum='c98678d9726bd8bbf1bab792acf3ff6c'
+if (Os.isFamily(Os.FAMILY_MAC)) {
+ scribeFile = 'scribe_osx_x86_64'
+ scribeChecksum='a137ad62c1bf7cca739da219544a9a16'
+} else if (Os.isFamily(Os.FAMILY_WINDOWS)) {
+ scribeFile = 'scribe_win32_x86_64.exe'
+ scribeLocalFile = 'scribe.exe'
+ scribeChecksum='75c2ce9ed45d17de375e3988bfaba816'
+
+}
+
+import de.undercouch.gradle.tasks.download.Download
+
+task downloadScribe(type: Download) {
+ src baseUrl + scribeFile
+ dest new File(baseFolder, scribeLocalFile)
+ onlyIfNewer true
+}
+
+task verifyScribe (type: Verify, dependsOn: downloadScribe) {
+ src new File(baseFolder, scribeLocalFile);
+ checksum scribeChecksum
+}
+
+task fixScribePermissions(type: Exec, dependsOn: verifyScribe) {
+ commandLine 'chmod', 'a+x', HIFI_ANDROID_PRECOMPILED + '/' + scribeLocalFile
+}
+
+task setupScribe(dependsOn: verifyScribe) { }
+
+// On Windows, we don't need to set the executable bit, but on OSX and Unix we do
+if (!Os.isFamily(Os.FAMILY_WINDOWS)) {
+ setupScribe.dependsOn fixScribePermissions
+}
+
+task extractGvrBinaries(dependsOn: extractDependencies) {
+ doLast {
+ def gvrLibFolder = new File(HIFI_ANDROID_PRECOMPILED, 'gvr/gvr-android-sdk-1.101.0/libraries');
+ zipTree(new File(HIFI_ANDROID_PRECOMPILED, 'gvr/gvr-android-sdk-1.101.0/libraries/sdk-audio-1.101.0.aar')).visit { element ->
+ def fileName = element.file.toString();
+ if (fileName.endsWith('libgvr_audio.so') && fileName.contains('arm64-v8a')) {
+ copy { from element.file; into gvrLibFolder }
+ }
+ }
+ zipTree(new File(HIFI_ANDROID_PRECOMPILED, 'gvr/gvr-android-sdk-1.101.0/libraries/sdk-base-1.101.0.aar')).visit { element ->
+ def fileName = element.file.toString();
+ if (fileName.endsWith('libgvr.so') && fileName.contains('arm64-v8a')) {
+ copy { from element.file; into gvrLibFolder }
+ }
+ }
+ fileTree(gvrLibFolder).visit { element ->
+ if (element.file.toString().endsWith('.so')) {
+ copy { from element.file; into jniFolder }
+ }
+ }
+ }
+
+}
+
+task setupDependencies(dependsOn: [setupScribe, copyDependencies, extractGvrBinaries]) {
+}
+
+task cleanDependencies(type: Delete) {
+ delete HIFI_ANDROID_PRECOMPILED
+ delete 'app/src/main/jniLibs/arm64-v8a'
+}
+
task clean(type: Delete) {
delete rootProject.buildDir
}
-
-task extractQt5jars(type: Copy) {
- from fileTree(QT5_ROOT + "/jar")
- into("${project.rootDir}/libraries/jar")
- include("*.jar")
-}
-
-task extractQt5so(type: Copy) {
- from fileTree(QT5_ROOT + "/lib")
- into("${project.rootDir}/libraries/jni/armeabi-v7a/")
- include("libQt5AndroidExtras.so")
- include("libQt5Concurrent.so")
- include("libQt5Core.so")
- include("libQt5Gamepad.so")
- include("libQt5Gui.so")
- include("libQt5Location.so")
- include("libQt5Multimedia.so")
- include("libQt5MultimediaQuick_p.so")
- include("libQt5Network.so")
- include("libQt5NetworkAuth.so")
- include("libQt5OpenGL.so")
- include("libQt5Positioning.so")
- include("libQt5Qml.so")
- include("libQt5Quick.so")
- include("libQt5QuickControls2.so")
- include("libQt5QuickParticles.so")
- include("libQt5QuickTemplates2.so")
- include("libQt5QuickWidgets.so")
- include("libQt5Script.so")
- include("libQt5ScriptTools.so")
- include("libQt5Sensors.so")
- include("libQt5Svg.so")
- include("libQt5WebChannel.so")
- include("libQt5WebSockets.so")
- include("libQt5WebView.so")
- include("libQt5Widgets.so")
- include("libQt5Xml.so")
- include("libQt5XmlPatterns.so")
-}
-
-task extractAudioSo(type: Copy) {
- from zipTree(GVR_ROOT + "/libraries/sdk-audio-1.80.0.aar")
- into "${project.rootDir}/libraries/"
- include "jni/armeabi-v7a/libgvr_audio.so"
-}
-
-task extractGvrSo(type: Copy) {
- from zipTree(GVR_ROOT + "/libraries/sdk-base-1.80.0.aar")
- into "${project.rootDir}/libraries/"
- include "jni/armeabi-v7a/libgvr.so"
-}
-
-task extractNdk { }
-extractNdk.dependsOn extractAudioSo
-extractNdk.dependsOn extractGvrSo
-
-task extractQt5 { }
-extractQt5.dependsOn extractQt5so
-extractQt5.dependsOn extractQt5jars
-
-task extractBinaries { }
-extractBinaries.dependsOn extractQt5
-extractBinaries.dependsOn extractNdk
-
-task deleteBinaries(type: Delete) {
- delete "${project.rootDir}/libraries/jni"
-}
-
-//clean.dependsOn(deleteBinaries)
diff --git a/android/setupGVR.gradle b/android/setupGVR.gradle
new file mode 100644
index 0000000000..c91674068f
--- /dev/null
+++ b/android/setupGVR.gradle
@@ -0,0 +1,41 @@
+buildscript {
+ repositories {
+ jcenter()
+ google()
+ }
+ dependencies {
+ classpath 'com.android.tools.build:gradle:3.0.1'
+ classpath 'de.undercouch:gradle-download-task:3.3.0'
+ }
+}
+
+
+def file='gvrsdk_v1.101.0.tgz'
+def url='https://hifi-public.s3.amazonaws.com/austin/android/' + file
+def destFile = new File(HIFI_ANDROID_PRECOMPILED, file)
+
+// FIXME find a way to only download if the file doesn't exist
+task downloadGVR(type: de.undercouch.gradle.tasks.download.Download) {
+ src url
+ dest destFile
+}
+
+task extractGVR(dependsOn: downloadGVR, type: Copy) {
+ from tarTree(resources.gzip(destFile))
+ into new File(HIFI_ANDROID_PRECOMPILED, 'gvr')
+}
+
+task copyGVRAudioLibs(dependsOn: extractGVR, type: Copy) {
+ from zipTree(new File(HIFI_ANDROID_PRECOMPILED, 'gvr/gvr-android-sdk-1.101.0/libraries/sdk-audio-1.101.0.aar'))
+ include 'jni/arm64-v8a/libgvr_audio.so'
+ into HIFI_ANDROID_PRECOMPILED
+}
+
+task copyGVRLibs(dependsOn: extractGVR, type: Copy) {
+ from zipTree(new File(HIFI_ANDROID_PRECOMPILED, 'gvr/gvr-android-sdk-1.101.0/libraries/sdk-base-1.101.0.aar'))
+ include 'jni/arm64-v8a/libgvr.so'
+ into HIFI_ANDROID_PRECOMPILED
+}
+
+task setupGVR(dependsOn: [copyGVRLibs, copyGVRAudioLibs]) {
+}
diff --git a/assignment-client/src/Agent.cpp b/assignment-client/src/Agent.cpp
index 4efc3343d1..f166a780ff 100644
--- a/assignment-client/src/Agent.cpp
+++ b/assignment-client/src/Agent.cpp
@@ -441,7 +441,7 @@ void Agent::executeScript() {
Transform audioTransform;
auto headOrientation = scriptedAvatar->getHeadOrientation();
- audioTransform.setTranslation(scriptedAvatar->getPosition());
+ audioTransform.setTranslation(scriptedAvatar->getWorldPosition());
audioTransform.setRotation(headOrientation);
QByteArray encodedBuffer;
@@ -452,7 +452,7 @@ void Agent::executeScript() {
}
AbstractAudioInterface::emitAudioPacket(encodedBuffer.data(), encodedBuffer.size(), audioSequenceNumber,
- audioTransform, scriptedAvatar->getPosition(), glm::vec3(0),
+ audioTransform, scriptedAvatar->getWorldPosition(), glm::vec3(0),
packetType, _selectedCodecName);
});
@@ -742,10 +742,10 @@ void Agent::processAgentAvatarAudio() {
audioPacket->writePrimitive(numAvailableSamples);
// use the orientation and position of this avatar for the source of this audio
- audioPacket->writePrimitive(scriptedAvatar->getPosition());
+ audioPacket->writePrimitive(scriptedAvatar->getWorldPosition());
glm::quat headOrientation = scriptedAvatar->getHeadOrientation();
audioPacket->writePrimitive(headOrientation);
- audioPacket->writePrimitive(scriptedAvatar->getPosition());
+ audioPacket->writePrimitive(scriptedAvatar->getWorldPosition());
audioPacket->writePrimitive(glm::vec3(0));
// no matter what, the loudness should be set to 0
@@ -759,10 +759,10 @@ void Agent::processAgentAvatarAudio() {
audioPacket->writePrimitive((quint8)0);
// use the orientation and position of this avatar for the source of this audio
- audioPacket->writePrimitive(scriptedAvatar->getPosition());
+ audioPacket->writePrimitive(scriptedAvatar->getWorldPosition());
glm::quat headOrientation = scriptedAvatar->getHeadOrientation();
audioPacket->writePrimitive(headOrientation);
- audioPacket->writePrimitive(scriptedAvatar->getPosition());
+ audioPacket->writePrimitive(scriptedAvatar->getWorldPosition()); // HUH? why do we write this twice??
audioPacket->writePrimitive(glm::vec3(0));
QByteArray encodedBuffer;
diff --git a/assignment-client/src/AssignmentClientMonitor.cpp b/assignment-client/src/AssignmentClientMonitor.cpp
index 5539d6a0bb..1868ccfafe 100644
--- a/assignment-client/src/AssignmentClientMonitor.cpp
+++ b/assignment-client/src/AssignmentClientMonitor.cpp
@@ -28,6 +28,10 @@
const QString ASSIGNMENT_CLIENT_MONITOR_TARGET_NAME = "assignment-client-monitor";
const int WAIT_FOR_CHILD_MSECS = 1000;
+#ifdef Q_OS_WIN
+HANDLE PROCESS_GROUP = createProcessGroup();
+#endif
+
AssignmentClientMonitor::AssignmentClientMonitor(const unsigned int numAssignmentClientForks,
const unsigned int minAssignmentClientForks,
const unsigned int maxAssignmentClientForks,
@@ -202,6 +206,10 @@ void AssignmentClientMonitor::spawnChildClient() {
assignmentClient->setProcessChannelMode(QProcess::ForwardedChannels);
assignmentClient->start(QCoreApplication::applicationFilePath(), _childArguments);
+#ifdef Q_OS_WIN
+ addProcessToGroup(PROCESS_GROUP, assignmentClient->processId());
+#endif
+
QString stdoutPath, stderrPath;
if (_wantsChildFileLogging) {
diff --git a/assignment-client/src/assets/AssetServer.cpp b/assignment-client/src/assets/AssetServer.cpp
index c03721d097..ca0f222e0c 100644
--- a/assignment-client/src/assets/AssetServer.cpp
+++ b/assignment-client/src/assets/AssetServer.cpp
@@ -30,6 +30,7 @@
#include
#include
+#include
#include
#include
#include
@@ -51,8 +52,10 @@ const QString ASSET_SERVER_LOGGING_TARGET_NAME = "asset-server";
static const QStringList BAKEABLE_MODEL_EXTENSIONS = { "fbx" };
static QStringList BAKEABLE_TEXTURE_EXTENSIONS;
+static const QStringList BAKEABLE_SCRIPT_EXTENSIONS = {};
static const QString BAKED_MODEL_SIMPLE_NAME = "asset.fbx";
static const QString BAKED_TEXTURE_SIMPLE_NAME = "texture.ktx";
+static const QString BAKED_SCRIPT_SIMPLE_NAME = "asset.js";
void AssetServer::bakeAsset(const AssetHash& assetHash, const AssetPath& assetPath, const QString& filePath) {
qDebug() << "Starting bake for: " << assetPath << assetHash;
@@ -99,6 +102,8 @@ std::pair AssetServer::getAssetStatus(const AssetPath& pa
bakedFilename = BAKED_MODEL_SIMPLE_NAME;
} else if (BAKEABLE_TEXTURE_EXTENSIONS.contains(extension.toLocal8Bit()) && hasMetaFile(hash)) {
bakedFilename = BAKED_TEXTURE_SIMPLE_NAME;
+ } else if (BAKEABLE_SCRIPT_EXTENSIONS.contains(extension)) {
+ bakedFilename = BAKED_SCRIPT_SIMPLE_NAME;
} else {
return { Irrelevant, "" };
}
@@ -186,6 +191,8 @@ bool AssetServer::needsToBeBaked(const AssetPath& path, const AssetHash& assetHa
bakedFilename = BAKED_MODEL_SIMPLE_NAME;
} else if (loaded && BAKEABLE_TEXTURE_EXTENSIONS.contains(extension.toLocal8Bit())) {
bakedFilename = BAKED_TEXTURE_SIMPLE_NAME;
+ } else if (BAKEABLE_SCRIPT_EXTENSIONS.contains(extension)) {
+ bakedFilename = BAKED_SCRIPT_SIMPLE_NAME;
} else {
return false;
}
@@ -228,7 +235,8 @@ void updateConsumedCores() {
AssetServer::AssetServer(ReceivedMessage& message) :
ThreadedAssignment(message),
_transferTaskPool(this),
- _bakingTaskPool(this)
+ _bakingTaskPool(this),
+ _filesizeLimit(MAX_UPLOAD_SIZE)
{
// store the current state of image compression so we can reset it when this assignment is complete
_wasColorTextureCompressionEnabled = image::isColorTexturesCompressionEnabled();
@@ -336,8 +344,8 @@ void AssetServer::completeSetup() {
auto maxBandwidthValue = assetServerObject[MAX_BANDWIDTH_OPTION];
auto maxBandwidthFloat = maxBandwidthValue.toDouble(-1);
+ const int BITS_PER_MEGABITS = 1000 * 1000;
if (maxBandwidthFloat > 0.0) {
- const int BITS_PER_MEGABITS = 1000 * 1000;
int maxBandwidth = maxBandwidthFloat * BITS_PER_MEGABITS;
nodeList->setConnectionMaxBandwidth(maxBandwidth);
qCInfo(asset_server) << "Set maximum bandwith per connection to" << maxBandwidthFloat << "Mb/s."
@@ -399,6 +407,15 @@ void AssetServer::completeSetup() {
qCCritical(asset_server) << "Asset Server assignment will not continue because mapping file could not be loaded.";
setFinished(true);
}
+
+ // get file size limit for an asset
+ static const QString ASSETS_FILESIZE_LIMIT_OPTION = "assets_filesize_limit";
+ auto assetsFilesizeLimitJSONValue = assetServerObject[ASSETS_FILESIZE_LIMIT_OPTION];
+ auto assetsFilesizeLimit = (uint64_t)assetsFilesizeLimitJSONValue.toInt(MAX_UPLOAD_SIZE);
+
+ if (assetsFilesizeLimit != 0 && assetsFilesizeLimit < MAX_UPLOAD_SIZE) {
+ _filesizeLimit = assetsFilesizeLimit * BITS_PER_MEGABITS;
+ }
}
void AssetServer::cleanupUnmappedFiles() {
@@ -488,6 +505,8 @@ void AssetServer::handleGetMappingOperation(ReceivedMessage& message, SharedNode
bakedRootFile = BAKED_MODEL_SIMPLE_NAME;
} else if (BAKEABLE_TEXTURE_EXTENSIONS.contains(assetPathExtension.toLocal8Bit())) {
bakedRootFile = BAKED_TEXTURE_SIMPLE_NAME;
+ } else if (BAKEABLE_SCRIPT_EXTENSIONS.contains(assetPathExtension)) {
+ bakedRootFile = BAKED_SCRIPT_SIMPLE_NAME;
}
auto originalAssetHash = it->second;
@@ -721,7 +740,7 @@ void AssetServer::handleAssetUpload(QSharedPointer message, Sha
if (senderNode->getCanWriteToAssetServer()) {
qCDebug(asset_server) << "Starting an UploadAssetTask for upload from" << uuidStringWithoutCurlyBraces(senderNode->getUUID());
- auto task = new UploadAssetTask(message, senderNode, _filesDirectory);
+ auto task = new UploadAssetTask(message, senderNode, _filesDirectory, _filesizeLimit);
_transferTaskPool.start(task);
} else {
// this is a node the domain told us is not allowed to rez entities
@@ -1141,6 +1160,7 @@ bool AssetServer::renameMapping(AssetPath oldPath, AssetPath newPath) {
static const QString BAKED_ASSET_SIMPLE_FBX_NAME = "asset.fbx";
static const QString BAKED_ASSET_SIMPLE_TEXTURE_NAME = "texture.ktx";
+static const QString BAKED_ASSET_SIMPLE_JS_NAME = "asset.js";
QString getBakeMapping(const AssetHash& hash, const QString& relativeFilePath) {
return HIDDEN_BAKED_CONTENT_FOLDER + hash + "/" + relativeFilePath;
@@ -1204,14 +1224,14 @@ void AssetServer::handleCompletedBake(QString originalAssetHash, QString origina
// setup the mapping for this bake file
auto relativeFilePath = QUrl(filePath).fileName();
qDebug() << "Relative file path is: " << relativeFilePath;
-
if (relativeFilePath.endsWith(".fbx", Qt::CaseInsensitive)) {
// for an FBX file, we replace the filename with the simple name
// (to handle the case where two mapped assets have the same hash but different names)
relativeFilePath = BAKED_ASSET_SIMPLE_FBX_NAME;
+ } else if (relativeFilePath.endsWith(".js", Qt::CaseInsensitive)) {
+ relativeFilePath = BAKED_ASSET_SIMPLE_JS_NAME;
} else if (!originalAssetPath.endsWith(".fbx", Qt::CaseInsensitive)) {
relativeFilePath = BAKED_ASSET_SIMPLE_TEXTURE_NAME;
-
}
QString bakeMapping = getBakeMapping(originalAssetHash, relativeFilePath);
@@ -1364,6 +1384,8 @@ bool AssetServer::setBakingEnabled(const AssetPathList& paths, bool enabled) {
bakedFilename = BAKED_MODEL_SIMPLE_NAME;
} else if (BAKEABLE_TEXTURE_EXTENSIONS.contains(extension.toLocal8Bit()) && hasMetaFile(hash)) {
bakedFilename = BAKED_TEXTURE_SIMPLE_NAME;
+ } else if (BAKEABLE_SCRIPT_EXTENSIONS.contains(extension)) {
+ bakedFilename = BAKED_SCRIPT_SIMPLE_NAME;
} else {
continue;
}
diff --git a/assignment-client/src/assets/AssetServer.h b/assignment-client/src/assets/AssetServer.h
index aeb40a416f..e6393e6a98 100644
--- a/assignment-client/src/assets/AssetServer.h
+++ b/assignment-client/src/assets/AssetServer.h
@@ -127,6 +127,8 @@ private:
bool _wasGrayscaleTextureCompressionEnabled { false };
bool _wasNormalTextureCompressionEnabled { false };
bool _wasCubeTextureCompressionEnabled { false };
+
+ uint64_t _filesizeLimit;
};
#endif
diff --git a/assignment-client/src/assets/BakeAssetTask.cpp b/assignment-client/src/assets/BakeAssetTask.cpp
index 94a0739612..6c78d2baf3 100644
--- a/assignment-client/src/assets/BakeAssetTask.cpp
+++ b/assignment-client/src/assets/BakeAssetTask.cpp
@@ -15,6 +15,7 @@
#include
#include
+#include
BakeAssetTask::BakeAssetTask(const AssetHash& assetHash, const AssetPath& assetPath, const QString& filePath) :
_assetHash(assetHash),
@@ -52,6 +53,10 @@ void BakeAssetTask::run() {
_baker = std::unique_ptr {
new FBXBaker(QUrl("file:///" + _filePath), fn, tempOutputDir)
};
+ } else if (_assetPath.endsWith(".js", Qt::CaseInsensitive)) {
+ _baker = std::unique_ptr{
+ new JSBaker(QUrl("file:///" + _filePath), PathUtils::generateTemporaryDir())
+ };
} else {
tempOutputDir = PathUtils::generateTemporaryDir();
_baker = std::unique_ptr {
diff --git a/assignment-client/src/assets/UploadAssetTask.cpp b/assignment-client/src/assets/UploadAssetTask.cpp
index 7e8e94c34d..5e6d59d032 100644
--- a/assignment-client/src/assets/UploadAssetTask.cpp
+++ b/assignment-client/src/assets/UploadAssetTask.cpp
@@ -22,10 +22,11 @@
UploadAssetTask::UploadAssetTask(QSharedPointer receivedMessage, SharedNodePointer senderNode,
- const QDir& resourcesDir) :
+ const QDir& resourcesDir, uint64_t filesizeLimit) :
_receivedMessage(receivedMessage),
_senderNode(senderNode),
- _resourcesDir(resourcesDir)
+ _resourcesDir(resourcesDir),
+ _filesizeLimit(filesizeLimit)
{
}
@@ -48,7 +49,7 @@ void UploadAssetTask::run() {
auto replyPacket = NLPacket::create(PacketType::AssetUploadReply, -1, true);
replyPacket->writePrimitive(messageID);
- if (fileSize > MAX_UPLOAD_SIZE) {
+ if (fileSize > _filesizeLimit) {
replyPacket->writePrimitive(AssetServerError::AssetTooLarge);
} else {
QByteArray fileData = buffer.read(fileSize);
diff --git a/assignment-client/src/assets/UploadAssetTask.h b/assignment-client/src/assets/UploadAssetTask.h
index 700eecbf9a..8c9e0d234a 100644
--- a/assignment-client/src/assets/UploadAssetTask.h
+++ b/assignment-client/src/assets/UploadAssetTask.h
@@ -26,7 +26,8 @@ class Node;
class UploadAssetTask : public QRunnable {
public:
- UploadAssetTask(QSharedPointer message, QSharedPointer senderNode, const QDir& resourcesDir);
+ UploadAssetTask(QSharedPointer message, QSharedPointer senderNode,
+ const QDir& resourcesDir, uint64_t filesizeLimit);
void run() override;
@@ -34,6 +35,7 @@ private:
QSharedPointer _receivedMessage;
QSharedPointer _senderNode;
QDir _resourcesDir;
+ uint64_t _filesizeLimit;
};
#endif // hifi_UploadAssetTask_h
diff --git a/assignment-client/src/audio/AudioMixer.cpp b/assignment-client/src/audio/AudioMixer.cpp
index 9ed6c7fdbc..7f088d8183 100644
--- a/assignment-client/src/audio/AudioMixer.cpp
+++ b/assignment-client/src/audio/AudioMixer.cpp
@@ -29,6 +29,7 @@
#include
#include
+#include "AudioLogging.h"
#include "AudioHelpers.h"
#include "AudioRingBuffer.h"
#include "AudioMixerClientData.h"
@@ -130,7 +131,7 @@ void AudioMixer::queueReplicatedAudioPacket(QSharedPointer mess
PacketType rewrittenType = PacketTypeEnum::getReplicatedPacketMapping().key(message->getType());
if (rewrittenType == PacketType::Unknown) {
- qDebug() << "Cannot unwrap replicated packet type not present in REPLICATED_PACKET_WRAPPING";
+ qCDebug(audio) << "Cannot unwrap replicated packet type not present in REPLICATED_PACKET_WRAPPING";
}
auto replicatedMessage = QSharedPointer::create(audioData, rewrittenType,
@@ -345,7 +346,7 @@ void AudioMixer::sendStatsPacket() {
void AudioMixer::run() {
- qDebug() << "Waiting for connection to domain to request settings from domain-server.";
+ qCDebug(audio) << "Waiting for connection to domain to request settings from domain-server.";
// wait until we have the domain-server settings, otherwise we bail
DomainHandler& domainHandler = DependencyManager::get()->getDomainHandler();
@@ -502,14 +503,14 @@ void AudioMixer::throttle(std::chrono::microseconds duration, int frame) {
int proportionalTerm = 1 + (_trailingMixRatio - TARGET) / 0.1f;
_throttlingRatio += THROTTLE_RATE * proportionalTerm;
_throttlingRatio = std::min(_throttlingRatio, 1.0f);
- qDebug("audio-mixer is struggling (%f mix/sleep) - throttling %f of streams",
- (double)_trailingMixRatio, (double)_throttlingRatio);
+ qCDebug(audio) << "audio-mixer is struggling (" << _trailingMixRatio << "mix/sleep) - throttling"
+ << _throttlingRatio << "of streams";
} else if (_throttlingRatio > 0.0f && _trailingMixRatio <= BACKOFF_TARGET) {
int proportionalTerm = 1 + (TARGET - _trailingMixRatio) / 0.2f;
_throttlingRatio -= BACKOFF_RATE * proportionalTerm;
_throttlingRatio = std::max(_throttlingRatio, 0.0f);
- qDebug("audio-mixer is recovering (%f mix/sleep) - throttling %f of streams",
- (double)_trailingMixRatio, (double)_throttlingRatio);
+ qCDebug(audio) << "audio-mixer is recovering (" << _trailingMixRatio << "mix/sleep) - throttling"
+ << _throttlingRatio << "of streams";
}
}
}
@@ -534,7 +535,7 @@ void AudioMixer::clearDomainSettings() {
}
void AudioMixer::parseSettingsObject(const QJsonObject& settingsObject) {
- qDebug() << "AVX2 Support:" << (cpuSupportsAVX2() ? "enabled" : "disabled");
+ qCDebug(audio) << "AVX2 Support:" << (cpuSupportsAVX2() ? "enabled" : "disabled");
if (settingsObject.contains(AUDIO_THREADING_GROUP_KEY)) {
QJsonObject audioThreadingGroupObject = settingsObject[AUDIO_THREADING_GROUP_KEY].toObject();
@@ -557,7 +558,7 @@ void AudioMixer::parseSettingsObject(const QJsonObject& settingsObject) {
const QString DYNAMIC_JITTER_BUFFER_JSON_KEY = "dynamic_jitter_buffer";
bool enableDynamicJitterBuffer = audioBufferGroupObject[DYNAMIC_JITTER_BUFFER_JSON_KEY].toBool();
if (enableDynamicJitterBuffer) {
- qDebug() << "Enabling dynamic jitter buffers.";
+ qCDebug(audio) << "Enabling dynamic jitter buffers.";
bool ok;
const QString DESIRED_JITTER_BUFFER_FRAMES_KEY = "static_desired_jitter_buffer_frames";
@@ -565,9 +566,9 @@ void AudioMixer::parseSettingsObject(const QJsonObject& settingsObject) {
if (!ok) {
_numStaticJitterFrames = InboundAudioStream::DEFAULT_STATIC_JITTER_FRAMES;
}
- qDebug() << "Static desired jitter buffer frames:" << _numStaticJitterFrames;
+ qCDebug(audio) << "Static desired jitter buffer frames:" << _numStaticJitterFrames;
} else {
- qDebug() << "Disabling dynamic jitter buffers.";
+ qCDebug(audio) << "Disabling dynamic jitter buffers.";
_numStaticJitterFrames = DISABLE_STATIC_JITTER_FRAMES;
}
@@ -621,7 +622,7 @@ void AudioMixer::parseSettingsObject(const QJsonObject& settingsObject) {
if (audioEnvGroupObject[CODEC_PREFERENCE_ORDER].isString()) {
QString codecPreferenceOrder = audioEnvGroupObject[CODEC_PREFERENCE_ORDER].toString();
_codecPreferenceOrder = codecPreferenceOrder.split(",");
- qDebug() << "Codec preference order changed to" << _codecPreferenceOrder;
+ qCDebug(audio) << "Codec preference order changed to" << _codecPreferenceOrder;
}
const QString ATTENATION_PER_DOULING_IN_DISTANCE = "attenuation_per_doubling_in_distance";
@@ -630,7 +631,7 @@ void AudioMixer::parseSettingsObject(const QJsonObject& settingsObject) {
float attenuation = audioEnvGroupObject[ATTENATION_PER_DOULING_IN_DISTANCE].toString().toFloat(&ok);
if (ok) {
_attenuationPerDoublingInDistance = attenuation;
- qDebug() << "Attenuation per doubling in distance changed to" << _attenuationPerDoublingInDistance;
+ qCDebug(audio) << "Attenuation per doubling in distance changed to" << _attenuationPerDoublingInDistance;
}
}
@@ -640,7 +641,7 @@ void AudioMixer::parseSettingsObject(const QJsonObject& settingsObject) {
float noiseMutingThreshold = audioEnvGroupObject[NOISE_MUTING_THRESHOLD].toString().toFloat(&ok);
if (ok) {
_noiseMutingThreshold = noiseMutingThreshold;
- qDebug() << "Noise muting threshold changed to" << _noiseMutingThreshold;
+ qCDebug(audio) << "Noise muting threshold changed to" << _noiseMutingThreshold;
}
}
@@ -680,8 +681,7 @@ void AudioMixer::parseSettingsObject(const QJsonObject& settingsObject) {
glm::vec3 dimensions(xMax - xMin, yMax - yMin, zMax - zMin);
AABox zoneAABox(corner, dimensions);
_audioZones.insert(zone, zoneAABox);
- qDebug() << "Added zone:" << zone << "(corner:" << corner
- << ", dimensions:" << dimensions << ")";
+ qCDebug(audio) << "Added zone:" << zone << "(corner:" << corner << ", dimensions:" << dimensions << ")";
}
}
}
@@ -712,7 +712,7 @@ void AudioMixer::parseSettingsObject(const QJsonObject& settingsObject) {
_audioZones.contains(settings.source) && _audioZones.contains(settings.listener)) {
_zoneSettings.push_back(settings);
- qDebug() << "Added Coefficient:" << settings.source << settings.listener << settings.coefficient;
+ qCDebug(audio) << "Added Coefficient:" << settings.source << settings.listener << settings.coefficient;
}
}
}
@@ -745,7 +745,7 @@ void AudioMixer::parseSettingsObject(const QJsonObject& settingsObject) {
_zoneReverbSettings.push_back(settings);
- qDebug() << "Added Reverb:" << zone << reverbTime << wetLevel;
+ qCDebug(audio) << "Added Reverb:" << zone << reverbTime << wetLevel;
}
}
}
diff --git a/assignment-client/src/audio/AudioMixerClientData.cpp b/assignment-client/src/audio/AudioMixerClientData.cpp
index 9bba9c7f30..49453c6fc6 100644
--- a/assignment-client/src/audio/AudioMixerClientData.cpp
+++ b/assignment-client/src/audio/AudioMixerClientData.cpp
@@ -19,6 +19,7 @@
#include "InjectedAudioStream.h"
+#include "AudioLogging.h"
#include "AudioHelpers.h"
#include "AudioMixer.h"
#include "AudioMixerClientData.h"
@@ -132,7 +133,7 @@ void AudioMixerClientData::optionallyReplicatePacket(ReceivedMessage& message, c
if (PacketTypeEnum::getReplicatedPacketMapping().key(message.getType()) != PacketType::Unknown) {
mirroredType = message.getType();
} else {
- qDebug() << "Packet passed to optionallyReplicatePacket was not a replicatable type - returning";
+ qCDebug(audio) << "Packet passed to optionallyReplicatePacket was not a replicatable type - returning";
return;
}
}
@@ -189,8 +190,16 @@ void AudioMixerClientData::parsePerAvatarGainSet(ReceivedMessage& message, const
uint8_t packedGain;
message.readPrimitive(&packedGain);
float gain = unpackFloatGainFromByte(packedGain);
- hrtfForStream(avatarUuid, QUuid()).setGainAdjustment(gain);
- qDebug() << "Setting gain adjustment for hrtf[" << uuid << "][" << avatarUuid << "] to " << gain;
+
+ if (avatarUuid.isNull()) {
+ // set the MASTER avatar gain
+ setMasterAvatarGain(gain);
+ qCDebug(audio) << "Setting MASTER avatar gain for " << uuid << " to " << gain;
+ } else {
+ // set the per-source avatar gain
+ hrtfForStream(avatarUuid, QUuid()).setGainAdjustment(gain);
+ qCDebug(audio) << "Setting avatar gain adjustment for hrtf[" << uuid << "][" << avatarUuid << "] to " << gain;
+ }
}
void AudioMixerClientData::parseNodeIgnoreRequest(QSharedPointer message, const SharedNodePointer& node) {
@@ -276,7 +285,7 @@ int AudioMixerClientData::parseData(ReceivedMessage& message) {
auto avatarAudioStream = new AvatarAudioStream(isStereo, AudioMixer::getStaticJitterFrames());
avatarAudioStream->setupCodec(_codec, _selectedCodecName, AudioConstants::MONO);
- qDebug() << "creating new AvatarAudioStream... codec:" << _selectedCodecName;
+ qCDebug(audio) << "creating new AvatarAudioStream... codec:" << _selectedCodecName;
connect(avatarAudioStream, &InboundAudioStream::mismatchedAudioCodec,
this, &AudioMixerClientData::handleMismatchAudioFormat);
@@ -315,7 +324,7 @@ int AudioMixerClientData::parseData(ReceivedMessage& message) {
#if INJECTORS_SUPPORT_CODECS
injectorStream->setupCodec(_codec, _selectedCodecName, isStereo ? AudioConstants::STEREO : AudioConstants::MONO);
- qDebug() << "creating new injectorStream... codec:" << _selectedCodecName;
+ qCDebug(audio) << "creating new injectorStream... codec:" << _selectedCodecName;
#endif
auto emplaced = _audioStreams.emplace(
@@ -339,8 +348,8 @@ int AudioMixerClientData::parseData(ReceivedMessage& message) {
auto parseResult = matchingStream->parseData(message);
if (matchingStream->getOverflowCount() > overflowBefore) {
- qDebug() << "Just overflowed on stream from" << message.getSourceID() << "at" << message.getSenderSockAddr();
- qDebug() << "This stream is for" << (isMicStream ? "microphone audio" : "injected audio");
+ qCDebug(audio) << "Just overflowed on stream from" << message.getSourceID() << "at" << message.getSenderSockAddr();
+ qCDebug(audio) << "This stream is for" << (isMicStream ? "microphone audio" : "injected audio");
}
return parseResult;
@@ -689,7 +698,7 @@ void AudioMixerClientData::setupCodecForReplicatedAgent(QSharedPointerreadString();
if (codecString != _selectedCodecName) {
- qDebug() << "Manually setting codec for replicated agent" << uuidStringWithoutCurlyBraces(getNodeID())
+ qCDebug(audio) << "Manually setting codec for replicated agent" << uuidStringWithoutCurlyBraces(getNodeID())
<< "-" << codecString;
const std::pair codec = AudioMixer::negotiateCodec({ codecString });
diff --git a/assignment-client/src/audio/AudioMixerClientData.h b/assignment-client/src/audio/AudioMixerClientData.h
index 7a8690d8cc..c3a31715ea 100644
--- a/assignment-client/src/audio/AudioMixerClientData.h
+++ b/assignment-client/src/audio/AudioMixerClientData.h
@@ -83,6 +83,9 @@ public:
// uses randomization to have the AudioMixer send a stats packet to this node around every second
bool shouldSendStats(int frameNumber);
+ float getMasterAvatarGain() const { return _masterAvatarGain; }
+ void setMasterAvatarGain(float gain) { _masterAvatarGain = gain; }
+
AudioLimiter audioLimiter;
void setupCodec(CodecPluginPointer codec, const QString& codecName);
@@ -175,6 +178,8 @@ private:
int _frameToSendStats { 0 };
+ float _masterAvatarGain { 1.0f }; // per-listener mixing gain, applied only to avatars
+
CodecPluginPointer _codec;
QString _selectedCodecName;
Encoder* _encoder{ nullptr }; // for outbound mixed stream
diff --git a/assignment-client/src/audio/AudioMixerSlave.cpp b/assignment-client/src/audio/AudioMixerSlave.cpp
index a131e266d2..6d150a0dc3 100644
--- a/assignment-client/src/audio/AudioMixerSlave.cpp
+++ b/assignment-client/src/audio/AudioMixerSlave.cpp
@@ -48,8 +48,8 @@ void sendEnvironmentPacket(const SharedNodePointer& node, AudioMixerClientData&
// mix helpers
inline float approximateGain(const AvatarAudioStream& listeningNodeStream, const PositionalAudioStream& streamToAdd,
const glm::vec3& relativePosition);
-inline float computeGain(const AvatarAudioStream& listeningNodeStream, const PositionalAudioStream& streamToAdd,
- const glm::vec3& relativePosition, bool isEcho);
+inline float computeGain(const AudioMixerClientData& listenerNodeData, const AvatarAudioStream& listeningNodeStream,
+ const PositionalAudioStream& streamToAdd, const glm::vec3& relativePosition, bool isEcho);
inline float computeAzimuth(const AvatarAudioStream& listeningNodeStream, const PositionalAudioStream& streamToAdd,
const glm::vec3& relativePosition);
@@ -266,7 +266,7 @@ void AudioMixerSlave::addStream(AudioMixerClientData& listenerNodeData, const QU
glm::vec3 relativePosition = streamToAdd.getPosition() - listeningNodeStream.getPosition();
float distance = glm::max(glm::length(relativePosition), EPSILON);
- float gain = computeGain(listeningNodeStream, streamToAdd, relativePosition, isEcho);
+ float gain = computeGain(listenerNodeData, listeningNodeStream, streamToAdd, relativePosition, isEcho);
float azimuth = isEcho ? 0.0f : computeAzimuth(listeningNodeStream, listeningNodeStream, relativePosition);
const int HRTF_DATASET_INDEX = 1;
@@ -484,10 +484,12 @@ float approximateGain(const AvatarAudioStream& listeningNodeStream, const Positi
// when throttling, as close streams are expected to be heard by a user
float distance = glm::length(relativePosition);
return gain / distance;
+
+ // avatar: skip master gain - it is constant for all streams
}
-float computeGain(const AvatarAudioStream& listeningNodeStream, const PositionalAudioStream& streamToAdd,
- const glm::vec3& relativePosition, bool isEcho) {
+float computeGain(const AudioMixerClientData& listenerNodeData, const AvatarAudioStream& listeningNodeStream,
+ const PositionalAudioStream& streamToAdd, const glm::vec3& relativePosition, bool isEcho) {
float gain = 1.0f;
// injector: apply attenuation
@@ -507,6 +509,9 @@ float computeGain(const AvatarAudioStream& listeningNodeStream, const Positional
float offAxisCoefficient = MAX_OFF_AXIS_ATTENUATION + (angleOfDelivery * (OFF_AXIS_ATTENUATION_STEP / PI_OVER_TWO));
gain *= offAxisCoefficient;
+
+ // apply master gain, only to avatars
+ gain *= listenerNodeData.getMasterAvatarGain();
}
auto& audioZones = AudioMixer::getAudioZones();
diff --git a/assignment-client/src/avatars/AvatarMixerClientData.h b/assignment-client/src/avatars/AvatarMixerClientData.h
index 12b0286088..d5c7784da7 100644
--- a/assignment-client/src/avatars/AvatarMixerClientData.h
+++ b/assignment-client/src/avatars/AvatarMixerClientData.h
@@ -91,7 +91,7 @@ public:
void loadJSONStats(QJsonObject& jsonObject) const;
- glm::vec3 getPosition() const { return _avatar ? _avatar->getPosition() : glm::vec3(0); }
+ glm::vec3 getPosition() const { return _avatar ? _avatar->getWorldPosition() : glm::vec3(0); }
glm::vec3 getGlobalBoundingBoxCorner() const { return _avatar ? _avatar->getGlobalBoundingBoxCorner() : glm::vec3(0); }
bool isRadiusIgnoring(const QUuid& other) const { return _radiusIgnoredOthers.find(other) != _radiusIgnoredOthers.end(); }
void addToRadiusIgnoringSet(const QUuid& other) { _radiusIgnoredOthers.insert(other); }
diff --git a/assignment-client/src/avatars/AvatarMixerSlave.cpp b/assignment-client/src/avatars/AvatarMixerSlave.cpp
index 5d36a6d261..dd045c24ea 100644
--- a/assignment-client/src/avatars/AvatarMixerSlave.cpp
+++ b/assignment-client/src/avatars/AvatarMixerSlave.cpp
@@ -209,7 +209,7 @@ void AvatarMixerSlave::broadcastAvatarDataToAgent(const SharedNodePointer& node)
assert(avatarNode); // we can't have gotten here without the avatarData being a valid key in the map
return nodeData->getLastBroadcastTime(avatarNode->getUUID());
}, [&](AvatarSharedPointer avatar)->float{
- glm::vec3 nodeBoxHalfScale = (avatar->getPosition() - avatar->getGlobalBoundingBoxCorner() * avatar->getSensorToWorldScale());
+ glm::vec3 nodeBoxHalfScale = (avatar->getWorldPosition() - avatar->getGlobalBoundingBoxCorner() * avatar->getSensorToWorldScale());
return glm::max(nodeBoxHalfScale.x, glm::max(nodeBoxHalfScale.y, nodeBoxHalfScale.z));
}, [&](AvatarSharedPointer avatar)->bool {
if (avatar == thisAvatar) {
diff --git a/assignment-client/src/avatars/ScriptableAvatar.cpp b/assignment-client/src/avatars/ScriptableAvatar.cpp
index 5060891284..c9ded2d6fb 100644
--- a/assignment-client/src/avatars/ScriptableAvatar.cpp
+++ b/assignment-client/src/avatars/ScriptableAvatar.cpp
@@ -20,7 +20,7 @@
QByteArray ScriptableAvatar::toByteArrayStateful(AvatarDataDetail dataDetail, bool dropFaceTracking) {
- _globalPosition = getPosition();
+ _globalPosition = getWorldPosition();
return AvatarData::toByteArrayStateful(dataDetail);
}
diff --git a/assignment-client/src/entities/EntityServer.cpp b/assignment-client/src/entities/EntityServer.cpp
index 2c8f8a9e37..995a5bad27 100644
--- a/assignment-client/src/entities/EntityServer.cpp
+++ b/assignment-client/src/entities/EntityServer.cpp
@@ -16,6 +16,10 @@
#include
#include
#include
+#include
+#include
+#include
+#include
#include "AssignmentParentFinder.h"
#include "EntityNodeData.h"
@@ -29,15 +33,26 @@ const char* LOCAL_MODELS_PERSIST_FILE = "resources/models.svo";
EntityServer::EntityServer(ReceivedMessage& message) :
OctreeServer(message),
- _entitySimulation(NULL)
+ _entitySimulation(NULL),
+ _dynamicDomainVerificationTimer(this)
{
DependencyManager::set();
DependencyManager::set();
DependencyManager::set();
auto& packetReceiver = DependencyManager::get()->getPacketReceiver();
- packetReceiver.registerListenerForTypes({ PacketType::EntityAdd, PacketType::EntityEdit, PacketType::EntityErase, PacketType::EntityPhysics },
- this, "handleEntityPacket");
+ packetReceiver.registerListenerForTypes({ PacketType::EntityAdd,
+ PacketType::EntityEdit,
+ PacketType::EntityErase,
+ PacketType::EntityPhysics,
+ PacketType::ChallengeOwnership,
+ PacketType::ChallengeOwnershipRequest,
+ PacketType::ChallengeOwnershipReply },
+ this,
+ "handleEntityPacket");
+
+ connect(&_dynamicDomainVerificationTimer, &QTimer::timeout, this, &EntityServer::startDynamicDomainVerification);
+ _dynamicDomainVerificationTimer.setSingleShot(true);
}
EntityServer::~EntityServer() {
@@ -93,6 +108,9 @@ void EntityServer::beforeRun() {
connect(_pruneDeletedEntitiesTimer, SIGNAL(timeout()), this, SLOT(pruneDeletedEntities()));
const int PRUNE_DELETED_MODELS_INTERVAL_MSECS = 1 * 1000; // once every second
_pruneDeletedEntitiesTimer->start(PRUNE_DELETED_MODELS_INTERVAL_MSECS);
+
+ DomainHandler& domainHandler = DependencyManager::get()->getDomainHandler();
+ connect(&domainHandler, &DomainHandler::settingsReceiveFail, this, &EntityServer::domainSettingsRequestFailed);
}
void EntityServer::entityCreated(const EntityItem& newEntity, const SharedNodePointer& senderNode) {
@@ -296,6 +314,18 @@ void EntityServer::readAdditionalConfiguration(const QJsonObject& settingsSectio
tree->setEntityMaxTmpLifetime(EntityTree::DEFAULT_MAX_TMP_ENTITY_LIFETIME);
}
+ int minTime;
+ if (readOptionInt("dynamicDomainVerificationTimeMin", settingsSectionObject, minTime)) {
+ _MINIMUM_DYNAMIC_DOMAIN_VERIFICATION_TIMER_MS = minTime * 1000;
+ }
+
+ int maxTime;
+ if (readOptionInt("dynamicDomainVerificationTimeMax", settingsSectionObject, maxTime)) {
+ _MAXIMUM_DYNAMIC_DOMAIN_VERIFICATION_TIMER_MS = maxTime * 1000;
+ }
+
+ startDynamicDomainVerification();
+
tree->setWantEditLogging(wantEditLogging);
tree->setWantTerseEditLogging(wantTerseEditLogging);
@@ -410,3 +440,79 @@ QString EntityServer::serverSubclassStats() {
return statsString;
}
+
+void EntityServer::domainSettingsRequestFailed() {
+ auto nodeList = DependencyManager::get();
+ qCDebug(entities) << "The EntityServer couldn't get the Domain Settings. Starting dynamic domain verification with default values...";
+
+ _MINIMUM_DYNAMIC_DOMAIN_VERIFICATION_TIMER_MS = DEFAULT_MINIMUM_DYNAMIC_DOMAIN_VERIFICATION_TIMER_MS;
+ _MAXIMUM_DYNAMIC_DOMAIN_VERIFICATION_TIMER_MS = DEFAULT_MAXIMUM_DYNAMIC_DOMAIN_VERIFICATION_TIMER_MS;
+ startDynamicDomainVerification();
+}
+
+void EntityServer::startDynamicDomainVerification() {
+ qCDebug(entities) << "Starting Dynamic Domain Verification...";
+
+ QString thisDomainID = DependencyManager::get()->getDomainId().remove(QRegExp("\\{|\\}"));
+
+ EntityTreePointer tree = std::static_pointer_cast(_tree);
+ QHash localMap(tree->getEntityCertificateIDMap());
+
+ QHashIterator i(localMap);
+ qCDebug(entities) << localMap.size() << "entities in _entityCertificateIDMap";
+ while (i.hasNext()) {
+ i.next();
+
+ EntityItemPointer entity = tree->findEntityByEntityItemID(i.value());
+
+ if (entity) {
+ if (!entity->getProperties().verifyStaticCertificateProperties()) {
+ qCDebug(entities) << "During Dynamic Domain Verification, a certified entity with ID" << i.value() << "failed"
+ << "static certificate verification.";
+ // Delete the entity if it doesn't pass static certificate verification
+ tree->deleteEntity(i.value(), true);
+ } else {
+
+ QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();
+ QNetworkRequest networkRequest;
+ networkRequest.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
+ networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
+ QUrl requestURL = NetworkingConstants::METAVERSE_SERVER_URL;
+ requestURL.setPath("/api/v1/commerce/proof_of_purchase_status/location");
+ QJsonObject request;
+ request["certificate_id"] = i.key();
+ networkRequest.setUrl(requestURL);
+
+ QNetworkReply* networkReply = NULL;
+ networkReply = networkAccessManager.put(networkRequest, QJsonDocument(request).toJson());
+
+ connect(networkReply, &QNetworkReply::finished, [=]() {
+ QJsonObject jsonObject = QJsonDocument::fromJson(networkReply->readAll()).object();
+ jsonObject = jsonObject["data"].toObject();
+
+ if (networkReply->error() == QNetworkReply::NoError) {
+ if (jsonObject["domain_id"].toString() != thisDomainID) {
+ qCDebug(entities) << "Entity's cert's domain ID" << jsonObject["domain_id"].toString()
+ << "doesn't match the current Domain ID" << thisDomainID << "; deleting entity" << i.value();
+ tree->deleteEntity(i.value(), true);
+ } else {
+ qCDebug(entities) << "Entity passed dynamic domain verification:" << i.value();
+ }
+ } else {
+ qCDebug(entities) << "Call to" << networkReply->url() << "failed with error" << networkReply->error() << "; deleting entity" << i.value()
+ << "More info:" << jsonObject;
+ tree->deleteEntity(i.value(), true);
+ }
+
+ networkReply->deleteLater();
+ });
+ }
+ } else {
+ qCWarning(entities) << "During DDV, an entity with ID" << i.value() << "was NOT found in the Entity Tree!";
+ }
+ }
+
+ int nextInterval = qrand() % ((_MAXIMUM_DYNAMIC_DOMAIN_VERIFICATION_TIMER_MS + 1) - _MINIMUM_DYNAMIC_DOMAIN_VERIFICATION_TIMER_MS) + _MINIMUM_DYNAMIC_DOMAIN_VERIFICATION_TIMER_MS;
+ qCDebug(entities) << "Restarting Dynamic Domain Verification timer for" << nextInterval / 1000 << "seconds";
+ _dynamicDomainVerificationTimer.start(nextInterval);
+}
diff --git a/assignment-client/src/entities/EntityServer.h b/assignment-client/src/entities/EntityServer.h
index 26c2f149aa..05404b28c8 100644
--- a/assignment-client/src/entities/EntityServer.h
+++ b/assignment-client/src/entities/EntityServer.h
@@ -73,6 +73,7 @@ protected:
private slots:
void handleEntityPacket(QSharedPointer message, SharedNodePointer senderNode);
+ void domainSettingsRequestFailed();
private:
SimpleEntitySimulationPointer _entitySimulation;
@@ -80,6 +81,13 @@ private:
QReadWriteLock _viewerSendingStatsLock;
QMap> _viewerSendingStats;
+
+ static const int DEFAULT_MINIMUM_DYNAMIC_DOMAIN_VERIFICATION_TIMER_MS = 45 * 60 * 1000; // 45m
+ static const int DEFAULT_MAXIMUM_DYNAMIC_DOMAIN_VERIFICATION_TIMER_MS = 60 * 60 * 1000; // 1h
+ int _MINIMUM_DYNAMIC_DOMAIN_VERIFICATION_TIMER_MS = DEFAULT_MINIMUM_DYNAMIC_DOMAIN_VERIFICATION_TIMER_MS; // 45m
+ int _MAXIMUM_DYNAMIC_DOMAIN_VERIFICATION_TIMER_MS = DEFAULT_MAXIMUM_DYNAMIC_DOMAIN_VERIFICATION_TIMER_MS; // 1h
+ QTimer _dynamicDomainVerificationTimer;
+ void startDynamicDomainVerification();
};
#endif // hifi_EntityServer_h
diff --git a/assignment-client/src/entities/EntityTreeSendThread.cpp b/assignment-client/src/entities/EntityTreeSendThread.cpp
index 03014bae6a..e5cee84f1b 100644
--- a/assignment-client/src/entities/EntityTreeSendThread.cpp
+++ b/assignment-client/src/entities/EntityTreeSendThread.cpp
@@ -23,6 +23,17 @@ EntityTreeSendThread::EntityTreeSendThread(OctreeServer* myServer, const SharedN
{
connect(std::static_pointer_cast(myServer->getOctree()).get(), &EntityTree::editingEntityPointer, this, &EntityTreeSendThread::editingEntityPointer, Qt::QueuedConnection);
connect(std::static_pointer_cast(myServer->getOctree()).get(), &EntityTree::deletingEntityPointer, this, &EntityTreeSendThread::deletingEntityPointer, Qt::QueuedConnection);
+
+ // connect to connection ID change on EntityNodeData so we can clear state for this receiver
+ auto nodeData = static_cast(node->getLinkedData());
+ connect(nodeData, &EntityNodeData::incomingConnectionIDChanged, this, &EntityTreeSendThread::resetState);
+}
+
+void EntityTreeSendThread::resetState() {
+ qCDebug(entities) << "Clearing known EntityTreeSendThread state for" << _nodeUuid;
+
+ _knownState.clear();
+ _traversal.reset();
}
void EntityTreeSendThread::preDistributionProcessing() {
@@ -175,7 +186,7 @@ bool EntityTreeSendThread::addAncestorsToExtraFlaggedEntities(const QUuid& filte
return parentWasNew || ancestorsWereNew;
}
- // since we didn't have a parent niether of our parents or ancestors could be new additions
+ // since we didn't have a parent, neither of our parents or ancestors could be new additions
return false;
}
@@ -204,7 +215,9 @@ bool EntityTreeSendThread::addDescendantsToExtraFlaggedEntities(const QUuid& fil
return hasNewChild || hasNewDescendants;
}
-void EntityTreeSendThread::startNewTraversal(const ViewFrustum& view, EntityTreeElementPointer root, int32_t lodLevelOffset, bool usesViewFrustum) {
+void EntityTreeSendThread::startNewTraversal(const ViewFrustum& view, EntityTreeElementPointer root, int32_t lodLevelOffset,
+ bool usesViewFrustum) {
+
DiffTraversal::Type type = _traversal.prepareNewTraversal(view, root, lodLevelOffset, usesViewFrustum);
// there are three types of traversal:
//
@@ -423,12 +436,19 @@ bool EntityTreeSendThread::traverseTreeAndBuildNextPacketPayload(EncodeBitstream
uint64_t sendTime = usecTimestampNow();
auto nodeData = static_cast(params.nodeData);
nodeData->stats.encodeStarted();
+ auto entityNode = _node.toStrongRef();
+ auto entityNodeData = static_cast(entityNode->getLinkedData());
while(!_sendQueue.empty()) {
PrioritizedEntity queuedItem = _sendQueue.top();
EntityItemPointer entity = queuedItem.getEntity();
if (entity) {
// Only send entities that match the jsonFilters, but keep track of everything we've tried to send so we don't try to send it again
- if (entity->matchesJSONFilters(jsonFilters)) {
+ bool entityMatchesFilters = entity->matchesJSONFilters(jsonFilters);
+ if (entityMatchesFilters || entityNodeData->isEntityFlaggedAsExtra(entity->getID())) {
+ if (!jsonFilters.isEmpty() && entityMatchesFilters) {
+ // Record explicitly filtered-in entity so that extra entities can be flagged.
+ entityNodeData->insertSentFilteredEntity(entity->getID());
+ }
OctreeElement::AppendState appendEntityState = entity->appendEntityData(&_packetData, params, _extraEncodeData);
if (appendEntityState != OctreeElement::COMPLETED) {
diff --git a/assignment-client/src/entities/EntityTreeSendThread.h b/assignment-client/src/entities/EntityTreeSendThread.h
index 49901491ff..594f423838 100644
--- a/assignment-client/src/entities/EntityTreeSendThread.h
+++ b/assignment-client/src/entities/EntityTreeSendThread.h
@@ -33,12 +33,16 @@ protected:
void traverseTreeAndSendContents(SharedNodePointer node, OctreeQueryNode* nodeData,
bool viewFrustumChanged, bool isFullScene) override;
+private slots:
+ void resetState(); // clears our known state forcing entities to appear unsent
+
private:
// the following two methods return booleans to indicate if any extra flagged entities were new additions to set
bool addAncestorsToExtraFlaggedEntities(const QUuid& filteredEntityID, EntityItem& entityItem, EntityNodeData& nodeData);
bool addDescendantsToExtraFlaggedEntities(const QUuid& filteredEntityID, EntityItem& entityItem, EntityNodeData& nodeData);
- void startNewTraversal(const ViewFrustum& viewFrustum, EntityTreeElementPointer root, int32_t lodLevelOffset, bool usesViewFrustum);
+ void startNewTraversal(const ViewFrustum& viewFrustum, EntityTreeElementPointer root, int32_t lodLevelOffset,
+ bool usesViewFrustum);
bool traverseTreeAndBuildNextPacketPayload(EncodeBitstreamParams& params, const QJsonObject& jsonFilters) override;
void preDistributionProcessing() override;
diff --git a/assignment-client/src/octree/OctreeInboundPacketProcessor.cpp b/assignment-client/src/octree/OctreeInboundPacketProcessor.cpp
index 04409b3b21..bce6e7fe44 100644
--- a/assignment-client/src/octree/OctreeInboundPacketProcessor.cpp
+++ b/assignment-client/src/octree/OctreeInboundPacketProcessor.cpp
@@ -92,7 +92,19 @@ void OctreeInboundPacketProcessor::processPacket(QSharedPointer
// Ask our tree subclass if it can handle the incoming packet...
PacketType packetType = message->getType();
- if (_myServer->getOctree()->handlesEditPacketType(packetType)) {
+ if (packetType == PacketType::ChallengeOwnership) {
+ _myServer->getOctree()->withWriteLock([&] {
+ _myServer->getOctree()->processChallengeOwnershipPacket(*message, sendingNode);
+ });
+ } else if (packetType == PacketType::ChallengeOwnershipRequest) {
+ _myServer->getOctree()->withWriteLock([&] {
+ _myServer->getOctree()->processChallengeOwnershipRequestPacket(*message, sendingNode);
+ });
+ } else if (packetType == PacketType::ChallengeOwnershipReply) {
+ _myServer->getOctree()->withWriteLock([&] {
+ _myServer->getOctree()->processChallengeOwnershipReplyPacket(*message, sendingNode);
+ });
+ } else if (_myServer->getOctree()->handlesEditPacketType(packetType)) {
PerformanceWarning warn(debugProcessPacket, "processPacket KNOWN TYPE", debugProcessPacket);
_receivedPacketCount++;
diff --git a/assignment-client/src/octree/OctreeSendThread.cpp b/assignment-client/src/octree/OctreeSendThread.cpp
index 89e3d403fc..3ae653307f 100644
--- a/assignment-client/src/octree/OctreeSendThread.cpp
+++ b/assignment-client/src/octree/OctreeSendThread.cpp
@@ -82,8 +82,12 @@ bool OctreeSendThread::process() {
if (auto node = _node.lock()) {
OctreeQueryNode* nodeData = static_cast(node->getLinkedData());
- // Sometimes the node data has not yet been linked, in which case we can't really do anything
- if (nodeData && !nodeData->isShuttingDown()) {
+ // If we don't have the OctreeQueryNode at all
+ // or it's uninitialized because we haven't received a query yet from the client
+ // or we don't know where we should send packets for this node
+ // or we're shutting down
+ // then we can't send an entity data packet
+ if (nodeData && nodeData->hasReceivedFirstQuery() && node->getActiveSocket() && !nodeData->isShuttingDown()) {
bool viewFrustumChanged = nodeData->updateCurrentViewFrustum();
packetDistributor(node, nodeData, viewFrustumChanged);
}
diff --git a/assignment-client/src/octree/OctreeSendThread.h b/assignment-client/src/octree/OctreeSendThread.h
index bc7d2c2588..220952e209 100644
--- a/assignment-client/src/octree/OctreeSendThread.h
+++ b/assignment-client/src/octree/OctreeSendThread.h
@@ -59,7 +59,8 @@ protected:
OctreePacketData _packetData;
QWeakPointer _node;
OctreeServer* _myServer { nullptr };
-
+ QUuid _nodeUuid;
+
private:
/// Called before a packetDistributor pass to allow for pre-distribution processing
virtual void preDistributionProcessing() {};
@@ -71,8 +72,6 @@ private:
virtual void preStartNewScene(OctreeQueryNode* nodeData, bool isFullScene);
virtual bool shouldTraverseAndSend(OctreeQueryNode* nodeData) { return hasSomethingToSend(nodeData); }
- QUuid _nodeUuid;
-
int _truePacketsSent { 0 }; // available for debug stats
int _trueBytesSent { 0 }; // available for debug stats
int _packetsSentThisInterval { 0 }; // used for bandwidth throttle condition
diff --git a/assignment-client/src/octree/OctreeServer.cpp b/assignment-client/src/octree/OctreeServer.cpp
index 4a1aade59d..c535c48dda 100644
--- a/assignment-client/src/octree/OctreeServer.cpp
+++ b/assignment-client/src/octree/OctreeServer.cpp
@@ -22,7 +22,6 @@
#include
#include
#include
-#include
#include
#include
diff --git a/assignment-client/src/scripts/EntityScriptServer.cpp b/assignment-client/src/scripts/EntityScriptServer.cpp
index 2bfcdcdf8c..c8067ce81f 100644
--- a/assignment-client/src/scripts/EntityScriptServer.cpp
+++ b/assignment-client/src/scripts/EntityScriptServer.cpp
@@ -30,6 +30,8 @@
#include
#include
+#include // for EntityScriptServerServices
+
#include "EntityScriptServerLogging.h"
#include "../entities/AssignmentParentFinder.h"
@@ -68,6 +70,9 @@ EntityScriptServer::EntityScriptServer(ReceivedMessage& message) : ThreadedAssig
DependencyManager::set();
DependencyManager::set(ScriptEngine::ENTITY_SERVER_SCRIPT);
+ DependencyManager::set();
+
+
// Needed to ensure the creation of the DebugDraw instance on the main thread
DebugDraw::getInstance();
@@ -85,6 +90,7 @@ EntityScriptServer::EntityScriptServer(ReceivedMessage& message) : ThreadedAssig
packetReceiver.registerListener(PacketType::ReloadEntityServerScript, this, "handleReloadEntityServerScriptPacket");
packetReceiver.registerListener(PacketType::EntityScriptGetStatus, this, "handleEntityScriptGetStatusPacket");
packetReceiver.registerListener(PacketType::EntityServerScriptLog, this, "handleEntityServerScriptLogPacket");
+ packetReceiver.registerListener(PacketType::EntityScriptCallMethod, this, "handleEntityScriptCallMethodPacket");
static const int LOG_INTERVAL = MSECS_PER_SECOND / 10;
auto timer = new QTimer(this);
@@ -231,6 +237,27 @@ void EntityScriptServer::pushLogs() {
}
}
+void EntityScriptServer::handleEntityScriptCallMethodPacket(QSharedPointer receivedMessage, SharedNodePointer senderNode) {
+
+ if (_entitiesScriptEngine && _entityViewer.getTree() && !_shuttingDown) {
+ auto entityID = QUuid::fromRfc4122(receivedMessage->read(NUM_BYTES_RFC4122_UUID));
+
+ auto method = receivedMessage->readString();
+
+ quint16 paramCount;
+ receivedMessage->readPrimitive(¶mCount);
+
+ QStringList params;
+ for (int param = 0; param < paramCount; param++) {
+ auto paramString = receivedMessage->readString();
+ params << paramString;
+ }
+
+ _entitiesScriptEngine->callEntityScriptMethod(entityID, method, params, senderNode->getUUID());
+ }
+}
+
+
void EntityScriptServer::run() {
// make sure we request our script once the agent connects to the domain
auto nodeList = DependencyManager::get();
@@ -561,6 +588,7 @@ void EntityScriptServer::aboutToFinish() {
// cleanup the AudioInjectorManager (and any still running injectors)
DependencyManager::destroy();
DependencyManager::destroy();
+ DependencyManager::destroy();
// cleanup codec & encoder
if (_codec && _encoder) {
diff --git a/assignment-client/src/scripts/EntityScriptServer.h b/assignment-client/src/scripts/EntityScriptServer.h
index e6bd12460b..f9c5e921f0 100644
--- a/assignment-client/src/scripts/EntityScriptServer.h
+++ b/assignment-client/src/scripts/EntityScriptServer.h
@@ -54,6 +54,9 @@ private slots:
void pushLogs();
+ void handleEntityScriptCallMethodPacket(QSharedPointer message, SharedNodePointer senderNode);
+
+
private:
void negotiateAudioFormat();
void selectAudioFormat(const QString& selectedCodecName);
diff --git a/cmake/externals/draco/CMakeLists.txt b/cmake/externals/draco/CMakeLists.txt
index 44ddd6d3de..6a894e76b6 100644
--- a/cmake/externals/draco/CMakeLists.txt
+++ b/cmake/externals/draco/CMakeLists.txt
@@ -13,7 +13,7 @@ ExternalProject_Add(
${EXTERNAL_NAME}
URL http://hifi-public.s3.amazonaws.com/dependencies/draco-1.1.0.zip
URL_MD5 208f8b04c91d5f1c73d731a3ea37c5bb
- CONFIGURE_COMMAND CMAKE_ARGS ${ANDROID_CMAKE_ARGS} -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -DCMAKE_INSTALL_PREFIX:PATH= ${EXTRA_CMAKE_FLAGS}
+ CONFIGURE_COMMAND CMAKE_ARGS ${ANDROID_CMAKE_ARGS} -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -DCMAKE_INSTALL_PREFIX:PATH=-$ ${EXTRA_CMAKE_FLAGS}
LOG_DOWNLOAD 1
LOG_CONFIGURE 1
LOG_BUILD 1
@@ -23,10 +23,11 @@ ExternalProject_Add(
set_target_properties(${EXTERNAL_NAME} PROPERTIES FOLDER "hidden/externals")
ExternalProject_Get_Property(${EXTERNAL_NAME} INSTALL_DIR)
+set(SUFFIXED_INSTALL_DIR "${INSTALL_DIR}-$")
string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER)
-set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${INSTALL_DIR}/include CACHE PATH "List of Draco include directories")
+set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${SUFFIXED_INSTALL_DIR}/include CACHE PATH "List of Draco include directories")
if (UNIX)
set(LIB_PREFIX "lib")
@@ -35,6 +36,6 @@ elseif (WIN32)
set(LIB_EXT "lib")
endif ()
-set(${EXTERNAL_NAME_UPPER}_LIBRARY ${INSTALL_DIR}/lib/${LIB_PREFIX}draco.${LIB_EXT} CACHE FILEPATH "Path to Draco release library")
-set(${EXTERNAL_NAME_UPPER}_ENCODER_LIBRARY ${INSTALL_DIR}/lib/${LIB_PREFIX}dracoenc.${LIB_EXT} CACHE FILEPATH "Path to Draco encoder release library")
-set(${EXTERNAL_NAME_UPPER}_DECODER_LIBRARY ${INSTALL_DIR}/lib/${LIB_PREFIX}dracodec.${LIB_EXT} CACHE FILEPATH "Path to Draco decoder release library")
+set(${EXTERNAL_NAME_UPPER}_LIBRARY ${SUFFIXED_INSTALL_DIR}/lib/${LIB_PREFIX}draco.${LIB_EXT} CACHE FILEPATH "Path to Draco release library")
+set(${EXTERNAL_NAME_UPPER}_ENCODER_LIBRARY ${SUFFIXED_INSTALL_DIR}/lib/${LIB_PREFIX}dracoenc.${LIB_EXT} CACHE FILEPATH "Path to Draco encoder release library")
+set(${EXTERNAL_NAME_UPPER}_DECODER_LIBRARY ${SUFFIXED_INSTALL_DIR}/lib/${LIB_PREFIX}dracodec.${LIB_EXT} CACHE FILEPATH "Path to Draco decoder release library")
diff --git a/cmake/externals/hifiAudioCodec/CMakeLists.txt b/cmake/externals/hifiAudioCodec/CMakeLists.txt
index a30396c6fd..e3ba36a440 100644
--- a/cmake/externals/hifiAudioCodec/CMakeLists.txt
+++ b/cmake/externals/hifiAudioCodec/CMakeLists.txt
@@ -5,43 +5,41 @@ set(EXTERNAL_NAME hifiAudioCodec)
string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER)
-if (NOT ANDROID)
-
- if (WIN32 OR APPLE)
- ExternalProject_Add(
- ${EXTERNAL_NAME}
- URL http://s3.amazonaws.com/hifi-public/dependencies/codecSDK-1.zip
- URL_MD5 23ec3fe51eaa155ea159a4971856fc13
- CONFIGURE_COMMAND ""
- BUILD_COMMAND ""
- INSTALL_COMMAND ""
- LOG_DOWNLOAD 1
- )
- else ()
- ExternalProject_Add(
- ${EXTERNAL_NAME}
- URL http://s3.amazonaws.com/hifi-public/dependencies/codecSDK-linux.zip
- URL_MD5 7d37914a18aa4de971d2f45dd3043bde
- CONFIGURE_COMMAND ""
- BUILD_COMMAND ""
- INSTALL_COMMAND ""
- LOG_DOWNLOAD 1
- )
- endif()
-
- # Hide this external target (for ide users)
- set_target_properties(${EXTERNAL_NAME} PROPERTIES FOLDER "hidden/externals")
-
- ExternalProject_Get_Property(${EXTERNAL_NAME} SOURCE_DIR)
-
- set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${SOURCE_DIR}/include CACHE TYPE INTERNAL)
-
- if (WIN32)
- set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${SOURCE_DIR}/Release/audio.lib CACHE TYPE INTERNAL)
- elseif(APPLE)
- set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${SOURCE_DIR}/Release/libaudio.a CACHE TYPE INTERNAL)
- elseif(NOT ANDROID)
- set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${SOURCE_DIR}/Release/libaudio.a CACHE TYPE INTERNAL)
- endif()
-
+if (WIN32)
+ set(DOWNLOAD_URL http://s3.amazonaws.com/hifi-public/dependencies/codecSDK-win-2.0.zip)
+ set(DOWNLOAD_MD5 9199d4dbd6b16bed736b235efe980e67)
+elseif (APPLE)
+ set(DOWNLOAD_URL http://s3.amazonaws.com/hifi-public/dependencies/codecSDK-mac-2.0.zip)
+ set(DOWNLOAD_MD5 21649881e7d5dc94f922179be96f76ba)
+elseif (ANDROID)
+ set(DOWNLOAD_URL http://s3.amazonaws.com/hifi-public/dependencies/codecSDK-android-2.0.zip)
+ set(DOWNLOAD_MD5 aef2a852600d498d58aa586668191683)
+elseif (UNIX)
+ set(DOWNLOAD_URL http://s3.amazonaws.com/hifi-public/dependencies/codecSDK-linux-2.0.zip)
+ set(DOWNLOAD_MD5 67fb7755f9bcafb98a9fceea53bc7481)
+else()
+ return()
+endif()
+
+ExternalProject_Add(
+ ${EXTERNAL_NAME}
+ URL ${DOWNLOAD_URL}
+ URL_MD5 ${DOWNLOAD_MD5}
+ CONFIGURE_COMMAND ""
+ BUILD_COMMAND ""
+ INSTALL_COMMAND ""
+ LOG_DOWNLOAD 1
+)
+
+# Hide this external target (for ide users)
+set_target_properties(${EXTERNAL_NAME} PROPERTIES FOLDER "hidden/externals")
+
+ExternalProject_Get_Property(${EXTERNAL_NAME} SOURCE_DIR)
+
+set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${SOURCE_DIR}/include CACHE TYPE INTERNAL)
+
+if (WIN32)
+ set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${SOURCE_DIR}/Release/audio.lib CACHE TYPE INTERNAL)
+else()
+ set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${SOURCE_DIR}/Release/libaudio.a CACHE TYPE INTERNAL)
endif()
diff --git a/cmake/externals/wasapi/CMakeLists.txt b/cmake/externals/wasapi/CMakeLists.txt
index 4437024962..4c0ffaf88f 100644
--- a/cmake/externals/wasapi/CMakeLists.txt
+++ b/cmake/externals/wasapi/CMakeLists.txt
@@ -6,8 +6,8 @@ if (WIN32)
include(ExternalProject)
ExternalProject_Add(
${EXTERNAL_NAME}
- URL http://hifi-public.s3.amazonaws.com/dependencies/qtaudio_wasapi9.zip
- URL_MD5 94f4765bdbcd53cd099f349ae031e769
+ URL http://hifi-public.s3.amazonaws.com/dependencies/qtaudio_wasapi10.zip
+ URL_MD5 4f40e49715a420fb67b45b9cee19052c
CONFIGURE_COMMAND ""
BUILD_COMMAND ""
INSTALL_COMMAND ""
diff --git a/cmake/macros/AutoScribeShader.cmake b/cmake/macros/AutoScribeShader.cmake
index c5b35b7e90..1919ecf00a 100755
--- a/cmake/macros/AutoScribeShader.cmake
+++ b/cmake/macros/AutoScribeShader.cmake
@@ -118,6 +118,7 @@ macro(AUTOSCRIBE_SHADER_LIB)
foreach(SHADER_FILE ${SHADER_SOURCE_FILES})
AUTOSCRIBE_SHADER(${SHADER_FILE} ${SHADER_INCLUDE_FILES})
file(TO_CMAKE_PATH "${AUTOSCRIBE_SHADER_RETURN}" AUTOSCRIBE_GENERATED_FILE)
+ set_property(SOURCE ${AUTOSCRIBE_GENERATED_FILE} PROPERTY SKIP_AUTOMOC ON)
list(APPEND AUTOSCRIBE_SHADER_SRC ${AUTOSCRIBE_GENERATED_FILE})
endforeach()
#message(${TARGET_NAME} ${AUTOSCRIBE_SHADER_SRC})
diff --git a/cmake/macros/GenerateQrc.cmake b/cmake/macros/GenerateQrc.cmake
new file mode 100644
index 0000000000..0283b3ea9b
--- /dev/null
+++ b/cmake/macros/GenerateQrc.cmake
@@ -0,0 +1,20 @@
+
+function(GENERATE_QRC)
+ set(oneValueArgs OUTPUT PREFIX PATH)
+ set(multiValueArgs GLOBS)
+ cmake_parse_arguments(GENERATE_QRC "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN} )
+ if ("${GENERATE_QRC_PREFIX}" STREQUAL "")
+ set(QRC_PREFIX_PATH /)
+ else()
+ set(QRC_PREFIX_PATH ${GENERATE_QRC_PREFIX})
+ endif()
+
+ foreach(GLOB ${GENERATE_QRC_GLOBS})
+ file(GLOB_RECURSE FOUND_FILES RELATIVE ${GENERATE_QRC_PATH} ${GLOB})
+ foreach(FILENAME ${FOUND_FILES})
+ set(QRC_CONTENTS "${QRC_CONTENTS}${GENERATE_QRC_PATH}/${FILENAME}\n")
+ endforeach()
+ endforeach()
+
+ configure_file("${HF_CMAKE_DIR}/templates/resources.qrc.in" ${GENERATE_QRC_OUTPUT})
+endfunction()
diff --git a/cmake/macros/SetFromEnv.cmake b/cmake/macros/SetFromEnv.cmake
new file mode 100644
index 0000000000..0832c5a536
--- /dev/null
+++ b/cmake/macros/SetFromEnv.cmake
@@ -0,0 +1,17 @@
+#
+# Created by Bradley Austin Davis on 2017/11/27
+# Copyright 2013-2017 High Fidelity, Inc.
+#
+# Distributed under the Apache License, Version 2.0.
+# See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
+#
+
+function(set_from_env _RESULT_NAME _ENV_VAR_NAME _DEFAULT_VALUE)
+ if (NOT DEFINED ${_RESULT_NAME})
+ if ("$ENV{${_ENV_VAR_NAME}}" STREQUAL "")
+ set (${_RESULT_NAME} ${_DEFAULT_VALUE} PARENT_SCOPE)
+ else()
+ set (${_RESULT_NAME} $ENV{${_ENV_VAR_NAME}} PARENT_SCOPE)
+ endif()
+ endif()
+endfunction()
diff --git a/cmake/macros/SetPackagingParameters.cmake b/cmake/macros/SetPackagingParameters.cmake
index 8faa4e6d96..e26f81edd9 100644
--- a/cmake/macros/SetPackagingParameters.cmake
+++ b/cmake/macros/SetPackagingParameters.cmake
@@ -15,13 +15,14 @@ macro(SET_PACKAGING_PARAMETERS)
set(PR_BUILD 0)
set(PRODUCTION_BUILD 0)
set(DEV_BUILD 0)
-
- set(RELEASE_TYPE $ENV{RELEASE_TYPE})
- set(RELEASE_NUMBER $ENV{RELEASE_NUMBER})
- string(TOLOWER "$ENV{BRANCH}" BUILD_BRANCH)
set(BUILD_GLOBAL_SERVICES "DEVELOPMENT")
set(USE_STABLE_GLOBAL_SERVICES 0)
+ set_from_env(RELEASE_TYPE RELEASE_TYPE "DEV")
+ set_from_env(RELEASE_NUMBER RELEASE_NUMBER "")
+ set_from_env(BUILD_BRANCH BRANCH "")
+ string(TOLOWER "${BUILD_BRANCH}" BUILD_BRANCH)
+
message(STATUS "The BUILD_BRANCH variable is: ${BUILD_BRANCH}")
message(STATUS "The BRANCH environment variable is: $ENV{BRANCH}")
message(STATUS "The RELEASE_TYPE variable is: ${RELEASE_TYPE}")
diff --git a/cmake/macros/SetupQt.cmake b/cmake/macros/SetupQt.cmake
index bbdce06f37..00a398761b 100644
--- a/cmake/macros/SetupQt.cmake
+++ b/cmake/macros/SetupQt.cmake
@@ -1,19 +1,11 @@
#
-# Copyright 2015 High Fidelity, Inc.
-# Created by Bradley Austin Davis on 2015/10/10
+# Created by Bradley Austin Davis on 2017/09/02
+# Copyright 2013-2017 High Fidelity, Inc.
#
# Distributed under the Apache License, Version 2.0.
# See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
#
-function(set_from_env _RESULT_NAME _ENV_VAR_NAME _DEFAULT_VALUE)
- if ("$ENV{${_ENV_VAR_NAME}}" STREQUAL "")
- set (${_RESULT_NAME} ${_DEFAULT_VALUE} PARENT_SCOPE)
- else()
- set (${_RESULT_NAME} $ENV{${_ENV_VAR_NAME}} PARENT_SCOPE)
- endif()
-endfunction()
-
# Construct a default QT location from a root path, a version and an architecture
function(calculate_default_qt_dir _RESULT_NAME)
if (ANDROID)
diff --git a/cmake/macros/TargetBullet.cmake b/cmake/macros/TargetBullet.cmake
index 207595d23f..48fe0e0c05 100644
--- a/cmake/macros/TargetBullet.cmake
+++ b/cmake/macros/TargetBullet.cmake
@@ -6,8 +6,19 @@
# See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
#
macro(TARGET_BULLET)
- add_dependency_external_projects(bullet)
- find_package(Bullet REQUIRED)
+ if (ANDROID)
+ set(INSTALL_DIR ${HIFI_ANDROID_PRECOMPILED}/bullet)
+ set(BULLET_INCLUDE_DIRS "${INSTALL_DIR}/include/bullet" CACHE TYPE INTERNAL)
+
+ set(LIB_DIR ${INSTALL_DIR}/lib)
+ list(APPEND BULLET_LIBRARIES ${LIB_DIR}/libBulletDynamics.a)
+ list(APPEND BULLET_LIBRARIES ${LIB_DIR}/libBulletCollision.a)
+ list(APPEND BULLET_LIBRARIES ${LIB_DIR}/libLinearMath.a)
+ list(APPEND BULLET_LIBRARIES ${LIB_DIR}/libBulletSoftBody.a)
+ else()
+ add_dependency_external_projects(bullet)
+ find_package(Bullet REQUIRED)
+ endif()
# perform the system include hack for OS X to ignore warnings
if (APPLE)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -isystem ${BULLET_INCLUDE_DIRS}")
@@ -16,3 +27,5 @@ macro(TARGET_BULLET)
endif()
target_link_libraries(${TARGET_NAME} ${BULLET_LIBRARIES})
endmacro()
+
+
diff --git a/cmake/macros/TargetDraco.cmake b/cmake/macros/TargetDraco.cmake
new file mode 100755
index 0000000000..c198ac35b0
--- /dev/null
+++ b/cmake/macros/TargetDraco.cmake
@@ -0,0 +1,18 @@
+macro(TARGET_DRACO)
+ if (ANDROID)
+ set(INSTALL_DIR ${HIFI_ANDROID_PRECOMPILED}/draco)
+ set(DRACO_INCLUDE_DIRS "${INSTALL_DIR}/include" CACHE TYPE INTERNAL)
+
+ set(LIB_DIR ${INSTALL_DIR}/lib)
+ list(APPEND DRACO_LIBRARIES ${LIB_DIR}/libdraco.a)
+ list(APPEND DRACO_LIBRARIES ${LIB_DIR}/libdracodec.a)
+ list(APPEND DRACO_LIBRARIES ${LIB_DIR}/libdracoenc.a)
+ else()
+ add_dependency_external_projects(draco)
+ find_package(Draco REQUIRED)
+ list(APPEND DRACO_LIBRARIES ${DRACO_LIBRARY})
+ list(APPEND DRACO_LIBRARIES ${DRACO_ENCODER_LIBRARY})
+ endif()
+ target_include_directories(${TARGET_NAME} SYSTEM PRIVATE ${DRACO_INCLUDE_DIRS})
+ target_link_libraries(${TARGET_NAME} ${DRACO_LIBRARIES})
+endmacro()
diff --git a/cmake/macros/TargetGoogleVR.cmake b/cmake/macros/TargetGoogleVR.cmake
new file mode 100644
index 0000000000..852037770d
--- /dev/null
+++ b/cmake/macros/TargetGoogleVR.cmake
@@ -0,0 +1,14 @@
+#
+# Created by Bradley Austin Davis on 2017/11/28
+# Copyright 2013-2017 High Fidelity, Inc.
+#
+# Distributed under the Apache License, Version 2.0.
+# See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
+#
+macro(TARGET_GOOGLEVR)
+ if (ANDROID)
+ set(GVR_ROOT "${HIFI_ANDROID_PRECOMPILED}/gvr/gvr-android-sdk-1.101.0/")
+ target_include_directories(native-lib PRIVATE "${GVR_ROOT}/libraries/headers")
+ target_link_libraries(native-lib "${GVR_ROOT}/libraries/libgvr.so")
+ endif()
+endmacro()
diff --git a/cmake/macros/TargetOpenSSL.cmake b/cmake/macros/TargetOpenSSL.cmake
index 7ee0283a48..82601bf6aa 100644
--- a/cmake/macros/TargetOpenSSL.cmake
+++ b/cmake/macros/TargetOpenSSL.cmake
@@ -6,14 +6,10 @@
# See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
#
macro(TARGET_OPENSSL)
-
if (ANDROID)
-
- # FIXME use a distributable binary
- set(OPENSSL_INSTALL_DIR C:/Android/openssl)
+ set(OPENSSL_INSTALL_DIR ${HIFI_ANDROID_PRECOMPILED}/openssl)
set(OPENSSL_INCLUDE_DIR "${OPENSSL_INSTALL_DIR}/include" CACHE TYPE INTERNAL)
set(OPENSSL_LIBRARIES "${OPENSSL_INSTALL_DIR}/lib/libcrypto.a;${OPENSSL_INSTALL_DIR}/lib/libssl.a" CACHE TYPE INTERNAL)
-
else()
find_package(OpenSSL REQUIRED)
@@ -28,5 +24,4 @@ macro(TARGET_OPENSSL)
include_directories(SYSTEM "${OPENSSL_INCLUDE_DIR}")
target_link_libraries(${TARGET_NAME} ${OPENSSL_LIBRARIES})
-
endmacro()
diff --git a/cmake/macros/TargetPolyvox.cmake b/cmake/macros/TargetPolyvox.cmake
new file mode 100644
index 0000000000..9db6b522c7
--- /dev/null
+++ b/cmake/macros/TargetPolyvox.cmake
@@ -0,0 +1,24 @@
+#
+# Created by Bradley Austin Davis on 2017/11/28
+# Copyright 2013-2017 High Fidelity, Inc.
+#
+# Distributed under the Apache License, Version 2.0.
+# See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
+#
+macro(TARGET_POLYVOX)
+ if (ANDROID)
+ set(INSTALL_DIR ${HIFI_ANDROID_PRECOMPILED}/polyvox)
+ set(POLYVOX_INCLUDE_DIRS "${INSTALL_DIR}/include" CACHE TYPE INTERNAL)
+ set(LIB_DIR ${INSTALL_DIR}/lib)
+ list(APPEND POLYVOX_LIBRARIES ${LIB_DIR}/libPolyVoxUtil.so)
+ list(APPEND POLYVOX_LIBRARIES ${LIB_DIR}/Release/libPolyVoxCore.so)
+ else()
+ add_dependency_external_projects(polyvox)
+ find_package(PolyVox REQUIRED)
+ endif()
+ target_include_directories(${TARGET_NAME} SYSTEM PUBLIC ${POLYVOX_INCLUDE_DIRS})
+ target_link_libraries(${TARGET_NAME} ${POLYVOX_LIBRARIES})
+endmacro()
+
+
+
diff --git a/cmake/macros/TargetTBB.cmake b/cmake/macros/TargetTBB.cmake
index e9c4639c3d..1e2e69eeaa 100644
--- a/cmake/macros/TargetTBB.cmake
+++ b/cmake/macros/TargetTBB.cmake
@@ -8,10 +8,10 @@
macro(TARGET_TBB)
if (ANDROID)
- set(TBB_INSTALL_DIR C:/tbb-2018/built)
- set(TBB_LIBRARY ${HIFI_ANDROID_PRECOMPILED}/libtbb.so CACHE FILEPATH "TBB library location")
- set(TBB_MALLOC_LIBRARY ${HIFI_ANDROID_PRECOMPILED}/libtbbmalloc.so CACHE FILEPATH "TBB malloc library location")
- set(TBB_INCLUDE_DIRS ${TBB_INSTALL_DIR}/include CACHE TYPE "List of tbb include directories" CACHE FILEPATH "TBB includes location")
+ set(TBB_INSTALL_DIR ${HIFI_ANDROID_PRECOMPILED}/tbb)
+ set(TBB_INCLUDE_DIRS ${TBB_INSTALL_DIR}/include CACHE FILEPATH "TBB includes location")
+ set(TBB_LIBRARY ${TBB_INSTALL_DIR}/lib/release/libtbb.so CACHE FILEPATH "TBB library location")
+ set(TBB_MALLOC_LIBRARY ${TBB_INSTALL_DIR}/lib/release/libtbbmalloc.so CACHE FILEPATH "TBB malloc library location")
set(TBB_LIBRARIES ${TBB_LIBRARY} ${TBB_MALLOC_LIBRARY})
else()
add_dependency_external_projects(tbb)
diff --git a/cmake/modules/FindOpenSSL.cmake b/cmake/modules/FindOpenSSL.cmake
index 338dee7bc8..0619c4d587 100644
--- a/cmake/modules/FindOpenSSL.cmake
+++ b/cmake/modules/FindOpenSSL.cmake
@@ -60,7 +60,7 @@ if (WIN32 AND NOT CYGWIN)
select_library_configurations(LIB_EAY)
select_library_configurations(SSL_EAY)
set(OPENSSL_LIBRARIES ${SSL_EAY_LIBRARY} ${LIB_EAY_LIBRARY})
- find_path(OPENSSL_DLL_PATH NAMES ssleay32.dll PATH_SUFFIXES "bin" ${_OPENSSL_ROOT_HINTS_AND_PATHS})
+ find_path(OPENSSL_DLL_PATH NAMES ssleay32.dll PATH_SUFFIXES "bin" HINTS ${_OPENSSL_ROOT_HINTS_AND_PATHS} NO_DEFAULT_PATH)
endif()
else()
diff --git a/cmake/templates/resources.qrc.in b/cmake/templates/resources.qrc.in
new file mode 100644
index 0000000000..6466b9ec51
--- /dev/null
+++ b/cmake/templates/resources.qrc.in
@@ -0,0 +1,5 @@
+
+
+@QRC_CONTENTS@
+
+
diff --git a/domain-server/resources/describe-settings.json b/domain-server/resources/describe-settings.json
index 8d0e949ff3..31f224667c 100644
--- a/domain-server/resources/describe-settings.json
+++ b/domain-server/resources/describe-settings.json
@@ -1,6 +1,12 @@
{
- "version": 1.8,
+ "version": 2.0,
"settings": [
+ {
+ "name": "label",
+ "label": "Label",
+ "settings": [
+ ]
+ },
{
"name": "metaverse",
"label": "Metaverse / Networking",
@@ -14,7 +20,8 @@
{
"name": "id",
"label": "Domain ID",
- "help": "This is your High Fidelity domain ID. If you do not want your domain to be registered in the High Fidelity metaverse you can leave this blank."
+ "help": "This is your High Fidelity domain ID. If you do not want your domain to be registered in the High Fidelity metaverse you can leave this blank.",
+ "advanced": true
},
{
"name": "automatic_networking",
@@ -82,11 +89,13 @@
{
"name": "description",
"label": "Description",
+ "advanced": true,
"help": "A description of your domain (256 character limit)."
},
{
"name": "maturity",
"label": "Maturity",
+ "advanced": true,
"help": "A maturity rating, available as a guideline for content on your domain.",
"default": "unrated",
"type": "select",
@@ -116,6 +125,7 @@
{
"name": "hosts",
"label": "Hosts",
+ "advanced": true,
"type": "table",
"can_add_new_rows": true,
"help": "Usernames of hosts who can reliably show your domain to new visitors.",
@@ -131,6 +141,7 @@
{
"name": "tags",
"label": "Tags",
+ "advanced": true,
"type": "table",
"can_add_new_rows": true,
"help": "Common categories under which your domain falls.",
@@ -207,7 +218,7 @@
"name": "standard_permissions",
"type": "table",
"label": "Domain-Wide User Permissions",
- "help": "Indicate which types of users can have which domain-wide permissions.",
+ "help": "Indicate which types of users can have which domain-wide permissions.",
"caption": "Standard Permissions",
"can_add_new_rows": false,
"groups": [
@@ -216,8 +227,8 @@
"span": 1
},
{
- "label": "Permissions ?",
- "span": 8
+ "label": "Permissions ?",
+ "span": 10
}
],
"columns": [
@@ -253,6 +264,20 @@
"editable": true,
"default": false
},
+ {
+ "name": "id_can_rez_certified",
+ "label": "Rez Certified",
+ "type": "checkbox",
+ "editable": true,
+ "default": false
+ },
+ {
+ "name": "id_can_rez_tmp_certified",
+ "label": "Rez Temporary Certified",
+ "type": "checkbox",
+ "editable": true,
+ "default": false
+ },
{
"name": "id_can_write_to_asset_server",
"label": "Write Assets",
@@ -283,7 +308,7 @@
}
],
"non-deletable-row-key": "permissions_id",
- "non-deletable-row-values": ["localhost", "anonymous", "logged-in"]
+ "non-deletable-row-values": [ "localhost", "anonymous", "logged-in" ]
},
{
"name": "group_permissions",
@@ -300,8 +325,8 @@
"span": 1
},
{
- "label": "Permissions ?",
- "span": 8
+ "label": "Permissions ?",
+ "span": 10
}
],
"columns": [
@@ -362,6 +387,20 @@
"editable": true,
"default": false
},
+ {
+ "name": "id_can_rez_certified",
+ "label": "Rez Certified",
+ "type": "checkbox",
+ "editable": true,
+ "default": false
+ },
+ {
+ "name": "id_can_rez_tmp_certified",
+ "label": "Rez Temporary Certified",
+ "type": "checkbox",
+ "editable": true,
+ "default": false
+ },
{
"name": "id_can_write_to_asset_server",
"label": "Write Assets",
@@ -383,7 +422,7 @@
"editable": true,
"default": false
},
- {
+ {
"name": "id_can_replace_content",
"label": "Replace Content",
"type": "checkbox",
@@ -407,8 +446,8 @@
"span": 1
},
{
- "label": "Permissions ?",
- "span": 8
+ "label": "Permissions ?",
+ "span": 10
}
],
"columns": [
@@ -466,6 +505,20 @@
"editable": true,
"default": false
},
+ {
+ "name": "id_can_rez_certified",
+ "label": "Rez Certified",
+ "type": "checkbox",
+ "editable": true,
+ "default": false
+ },
+ {
+ "name": "id_can_rez_tmp_certified",
+ "label": "Rez Temporary Certified",
+ "type": "checkbox",
+ "editable": true,
+ "default": false
+ },
{
"name": "id_can_write_to_asset_server",
"label": "Write Assets",
@@ -487,7 +540,7 @@
"editable": true,
"default": false
},
- {
+ {
"name": "id_can_replace_content",
"label": "Replace Content",
"type": "checkbox",
@@ -507,8 +560,8 @@
"span": 1
},
{
- "label": "Permissions ?",
- "span": 8
+ "label": "Permissions ?",
+ "span": 10
}
],
"columns": [
@@ -544,6 +597,20 @@
"editable": true,
"default": false
},
+ {
+ "name": "id_can_rez_certified",
+ "label": "Rez Certified",
+ "type": "checkbox",
+ "editable": true,
+ "default": false
+ },
+ {
+ "name": "id_can_rez_tmp_certified",
+ "label": "Rez Temporary Certified",
+ "type": "checkbox",
+ "editable": true,
+ "default": false
+ },
{
"name": "id_can_write_to_asset_server",
"label": "Write Assets",
@@ -565,7 +632,7 @@
"editable": true,
"default": false
},
- {
+ {
"name": "id_can_replace_content",
"label": "Replace Content",
"type": "checkbox",
@@ -585,8 +652,8 @@
"span": 1
},
{
- "label": "Permissions ?",
- "span": 8
+ "label": "Permissions ?",
+ "span": 10
}
],
"columns": [
@@ -622,6 +689,20 @@
"editable": true,
"default": false
},
+ {
+ "name": "id_can_rez_certified",
+ "label": "Rez Certified",
+ "type": "checkbox",
+ "editable": true,
+ "default": false
+ },
+ {
+ "name": "id_can_rez_tmp_certified",
+ "label": "Rez Temporary Certified",
+ "type": "checkbox",
+ "editable": true,
+ "default": false
+ },
{
"name": "id_can_write_to_asset_server",
"label": "Write Assets",
@@ -643,7 +724,7 @@
"editable": true,
"default": false
},
- {
+ {
"name": "id_can_replace_content",
"label": "Replace Content",
"type": "checkbox",
@@ -663,8 +744,8 @@
"span": 1
},
{
- "label": "Permissions ?",
- "span": 8
+ "label": "Permissions ?",
+ "span": 10
}
],
"columns": [
@@ -700,6 +781,20 @@
"editable": true,
"default": false
},
+ {
+ "name": "id_can_rez_certified",
+ "label": "Rez Certified",
+ "type": "checkbox",
+ "editable": true,
+ "default": false
+ },
+ {
+ "name": "id_can_rez_tmp_certified",
+ "label": "Rez Temporary Certified",
+ "type": "checkbox",
+ "editable": true,
+ "default": false
+ },
{
"name": "id_can_write_to_asset_server",
"label": "Write Assets",
@@ -721,7 +816,7 @@
"editable": true,
"default": false
},
- {
+ {
"name": "id_can_replace_content",
"label": "Replace Content",
"type": "checkbox",
@@ -741,8 +836,8 @@
"span": 1
},
{
- "label": "Permissions ?",
- "span": 8
+ "label": "Permissions ?",
+ "span": 10
}
],
"columns": [
@@ -778,6 +873,20 @@
"editable": true,
"default": false
},
+ {
+ "name": "id_can_rez_certified",
+ "label": "Rez Certified",
+ "type": "checkbox",
+ "editable": true,
+ "default": false
+ },
+ {
+ "name": "id_can_rez_tmp_certified",
+ "label": "Rez Temporary Certified",
+ "type": "checkbox",
+ "editable": true,
+ "default": false
+ },
{
"name": "id_can_write_to_asset_server",
"label": "Write Assets",
@@ -799,7 +908,7 @@
"editable": true,
"default": false
},
- {
+ {
"name": "id_can_replace_content",
"label": "Replace Content",
"type": "checkbox",
@@ -807,6 +916,14 @@
"default": false
}
]
+ },
+ {
+ "name": "multi_kick_logged_in",
+ "type": "checkbox",
+ "label": "Multi-Kick for Logged In Users",
+ "help": "Kick logged in users by machine fingerprint (in addition to the default kick by username)",
+ "default": false,
+ "advanced": true
}
]
},
@@ -841,7 +958,7 @@
{
"name": "asset_server",
"label": "Asset Server (ATP)",
- "assignment-types": [3],
+ "assignment-types": [ 3 ],
"settings": [
{
"name": "enabled",
@@ -858,13 +975,21 @@
"help": "The path to the directory assets are stored in. If this path is relative, it will be relative to the application data directory. If you change this path you will need to manually copy any existing assets from the previous directory.",
"default": "",
"advanced": true
+ },
+ {
+ "name": "assets_filesize_limit",
+ "type": "int",
+ "label": "File Size Limit",
+ "help": "The file size limit of an asset that can be imported into the asset server in MBytes. 0 (default) means no limit on file size.",
+ "default": 0,
+ "advanced": true
}
]
},
{
"name": "entity_script_server",
"label": "Entity Script Server (ESS)",
- "assignment-types": [5],
+ "assignment-types": [ 5 ],
"settings": [
{
"name": "entity_pps_per_script",
@@ -887,7 +1012,7 @@
{
"name": "avatars",
"label": "Avatars",
- "assignment-types": [1, 2],
+ "assignment-types": [ 1, 2 ],
"settings": [
{
"name": "min_avatar_scale",
@@ -926,7 +1051,7 @@
{
"name": "audio_threading",
"label": "Audio Threading",
- "assignment-types": [0],
+ "assignment-types": [ 0 ],
"settings": [
{
"name": "auto_threads",
@@ -949,7 +1074,7 @@
{
"name": "audio_env",
"label": "Audio Environment",
- "assignment-types": [0],
+ "assignment-types": [ 0 ],
"settings": [
{
"name": "attenuation_per_doubling_in_distance",
@@ -1156,6 +1281,22 @@
"default": "3600",
"advanced": true
},
+ {
+ "name": "dynamicDomainVerificationTimeMin",
+ "label": "Dynamic Domain Verification Time (seconds) - Minimum",
+ "help": "The lower limit on the amount of time that passes before Dynamic Domain Verification on entities occurs. Units are seconds.",
+ "placeholder": "2700",
+ "default": "2700",
+ "advanced": true
+ },
+ {
+ "name": "dynamicDomainVerificationTimeMax",
+ "label": "Dynamic Domain Verification Time (seconds) - Maximum",
+ "help": "The upper limit on the amount of time that passes before Dynamic Domain Verification on entities occurs. Units are seconds.",
+ "placeholder": "3600",
+ "default": "3600",
+ "advanced": true
+ },
{
"name": "entityScriptSourceWhitelist",
"label": "Entity Scripts Allowed from:",
@@ -1503,6 +1644,29 @@
]
}
]
+ },
+ {
+ "name": "wizard",
+ "label": "Setup Wizard",
+ "restart": false,
+ "hidden": true,
+ "settings": [
+ {
+ "name": "cloud_domain",
+ "type": "checkbox",
+ "default": false
+ },
+ {
+ "name": "steps_completed",
+ "type": "int",
+ "default": 0
+ },
+ {
+ "name": "completed_once",
+ "type": "checkbox",
+ "default": false
+ }
+ ]
}
]
-}
\ No newline at end of file
+}
diff --git a/domain-server/resources/web/content/index.shtml b/domain-server/resources/web/content/index.shtml
index e1ba5499b6..0e48c1eff8 100644
--- a/domain-server/resources/web/content/index.shtml
+++ b/domain-server/resources/web/content/index.shtml
@@ -19,12 +19,13 @@
Upload an entities file (e.g.: models.json.gz) to replace the content of this domain.
Note: Your domain's content will be replaced by the content you upload, but the backup files of your domain's content will not immediately be changed.
-
- If your domain has any content that you would like to re-use at a later date, save a manual backup of your models.json.gz file, which is usually stored at the following paths:
-
If your domain has any content that you would like to re-use at a later date, save a manual backup of your models.json.gz file, which is usually stored at the following paths: