diff --git a/.gitattributes b/.gitattributes
index 406780d20a..4a06c4288a 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -10,6 +10,7 @@
*.json text
*.js text
*.qml text
+*.qrc text
*.slf text
*.slh text
*.slv text
diff --git a/.gitignore b/.gitignore
index d6227f1f30..8aa82865a4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -12,6 +12,11 @@ ext/
Makefile
*.user
+# Android Studio
+*.iml
+local.properties
+android/libraries
+
# Xcode
*.xcodeproj
*.xcworkspace
diff --git a/BUILD_ANDROID.md b/BUILD_ANDROID.md
index d69d20ee8a..cc51e58b1d 100644
--- a/BUILD_ANDROID.md
+++ b/BUILD_ANDROID.md
@@ -1,19 +1,56 @@
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.
-### Android Dependencies
+# Android Dependencies
You will need the following tools to build our Android targets.
-* [cmake](http://www.cmake.org/download/) ~> 3.5.1
-* [Qt](http://www.qt.io/download-open-source/#) ~> 5.6.2
-* [ant](http://ant.apache.org/bindownload.cgi) ~> 1.9.4
-* [Android NDK](https://developer.android.com/tools/sdk/ndk/index.html) ~> r10d
-* [Android SDK](http://developer.android.com/sdk/installing/index.html) ~> 24.4.1.1
- * Install the latest Platform-tools
- * Install the latest Build-tools
- * Install the SDK Platform for API Level 19
- * Install Sources for Android SDK for API Level 19
- * Install the ARM EABI v7a System Image if you want to run an emulator.
+* [Qt](http://www.qt.io/download-open-source/#) ~> 5.9.1
+* [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
+
+Download the Qt online installer. Run the installer and select the android_armv7 binaries. Installing to the default path 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 Tools tab select the following
+
+* Android SDK Build-Tools
+* GPU Debugging Tools
+* CMake (even if you have a separate CMake installation)
+* LLDB
+* Android SDK Platform-Tools
+* Android SDK Tools
+* Android SDK Tools
+* NDK (even if you have the NDK installed separately)
+
+### Google VR SDK
+
+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
+
+#### Set up machine specific Gradle properties
+
+Create a `gradle.properties` file in ~/.gradle. Edit the file to contain the following
+
+ QT5_ROOT=C\:\\Qt\\5.9.1\\android_armv7
+ GVR_ROOT=C\:\\Android\\gvr-android-sdk
+
+Replace the paths with your local installations of Qt5 and the Google VR SDK
+
+
+# TODO fix the rest
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.
diff --git a/CMakeLists.txt b/CMakeLists.txt
index be513abddb..9d3296a168 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,13 +1,16 @@
-if (WIN32)
+# If we're running under the gradle build, HIFI_ANDROID will be set here, but
+# ANDROID will not be set until after the `project` statement. This is the *ONLY*
+# place you need to use `HIFI_ANDROID` instead of `ANDROID`
+if (WIN32 AND NOT HIFI_ANDROID)
cmake_minimum_required(VERSION 3.7)
else()
cmake_minimum_required(VERSION 3.2)
endif()
-include("cmake/init.cmake")
-
project(hifi)
+include("cmake/init.cmake")
+
include("cmake/compiler.cmake")
if (NOT DEFINED SERVER_ONLY)
@@ -54,11 +57,13 @@ endif()
file(GLOB_RECURSE CMAKE_SRC cmake/*.cmake cmake/CMakeLists.txt)
add_custom_target(cmake SOURCES ${CMAKE_SRC})
GroupSources("cmake")
+unset(CMAKE_SRC)
file(GLOB_RECURSE JS_SRC scripts/*.js unpublishedScripts/*.js)
add_custom_target(js SOURCES ${JS_SRC})
GroupSources("scripts")
GroupSources("unpublishedScripts")
+unset(JS_SRC)
# Locate the required Qt build on the filesystem
setup_qt()
@@ -77,6 +82,12 @@ option(USE_NSIGHT "Attempt to find the nSight libraries" 1)
set_packaging_parameters()
+# FIXME hack to work on the proper Android toolchain
+if (ANDROID)
+ add_subdirectory(android/app)
+ return()
+endif()
+
# add subdirectories for all targets
if (BUILD_SERVER)
add_subdirectory(assignment-client)
diff --git a/android/app/CMakeLists.txt b/android/app/CMakeLists.txt
new file mode 100644
index 0000000000..2d6df925e9
--- /dev/null
+++ b/android/app/CMakeLists.txt
@@ -0,0 +1,8 @@
+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()
+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")
diff --git a/android/app/build.gradle b/android/app/build.gradle
new file mode 100644
index 0000000000..bd1c596bf3
--- /dev/null
+++ b/android/app/build.gradle
@@ -0,0 +1,57 @@
+apply plugin: 'com.android.application'
+
+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' }
+ 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"
+ }
+ }
+ jackOptions { enabled true }
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+ }
+
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+ }
+ }
+
+ sourceSets {
+ main {
+ jniLibs.srcDirs += '../libraries/jni';
+ }
+ }
+ externalNativeBuild {
+ cmake {
+ path '../../CMakeLists.txt'
+ }
+ }
+}
+
+dependencies {
+ compile fileTree(dir: "${project.rootDir}/libraries/jar", include: 'QtAndroid-bundled.jar')
+ compile fileTree(dir: 'libs', include: ['*.jar'])
+ 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/proguard-rules.pro b/android/app/proguard-rules.pro
new file mode 100644
index 0000000000..b3c0078513
--- /dev/null
+++ b/android/app/proguard-rules.pro
@@ -0,0 +1,25 @@
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in C:\Android\SDK/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the proguardFiles
+# directive in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
new file mode 100644
index 0000000000..05547bd5ae
--- /dev/null
+++ b/android/app/src/main/AndroidManifest.xml
@@ -0,0 +1,37 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android/app/src/main/cpp/GoogleVRHelpers.h b/android/app/src/main/cpp/GoogleVRHelpers.h
new file mode 100644
index 0000000000..10c46b036f
--- /dev/null
+++ b/android/app/src/main/cpp/GoogleVRHelpers.h
@@ -0,0 +1,50 @@
+#include
+#include
+#include
+
+namespace googlevr {
+
+ // Convert a GVR matrix to GLM matrix
+ glm::mat4 toGlm(const gvr::Mat4f &matrix) {
+ glm::mat4 result;
+ for (int i = 0; i < 4; ++i) {
+ for (int j = 0; j < 4; ++j) {
+ result[j][i] = matrix.m[i][j];
+ }
+ }
+ return result;
+ }
+
+ // Given a field of view in degrees, compute the corresponding projection
+// matrix.
+ glm::mat4 perspectiveMatrixFromView(const gvr::Rectf& fov, float z_near, float z_far) {
+ const float x_left = -std::tan(fov.left * M_PI / 180.0f) * z_near;
+ const float x_right = std::tan(fov.right * M_PI / 180.0f) * z_near;
+ const float y_bottom = -std::tan(fov.bottom * M_PI / 180.0f) * z_near;
+ const float y_top = std::tan(fov.top * M_PI / 180.0f) * z_near;
+ const float Y = (2 * z_near) / (y_top - y_bottom);
+ const float A = (x_right + x_left) / (x_right - x_left);
+ const float B = (y_top + y_bottom) / (y_top - y_bottom);
+ const float C = (z_near + z_far) / (z_near - z_far);
+ const float D = (2 * z_near * z_far) / (z_near - z_far);
+
+ glm::mat4 result { 0 };
+ result[2][0] = A;
+ result[1][1] = Y;
+ result[2][1] = B;
+ result[2][2] = C;
+ result[3][2] = D;
+ result[2][3] = -1;
+ return result;
+ }
+
+ glm::quat toGlm(const gvr::ControllerQuat& q) {
+ glm::quat result;
+ result.w = q.qw;
+ result.x = q.qx;
+ result.y = q.qy;
+ result.z = q.qz;
+ return result;
+ }
+
+}
diff --git a/android/app/src/main/cpp/native-lib.cpp b/android/app/src/main/cpp/native-lib.cpp
new file mode 100644
index 0000000000..156d43d849
--- /dev/null
+++ b/android/app/src/main/cpp/native-lib.cpp
@@ -0,0 +1,78 @@
+#include
+
+#include
+#include
+
+#include "renderer.h"
+
+int QtMsgTypeToAndroidPriority(QtMsgType type) {
+ int priority = ANDROID_LOG_UNKNOWN;
+ switch (type) {
+ case QtDebugMsg: priority = ANDROID_LOG_DEBUG; break;
+ case QtWarningMsg: priority = ANDROID_LOG_WARN; break;
+ case QtCriticalMsg: priority = ANDROID_LOG_ERROR; break;
+ case QtFatalMsg: priority = ANDROID_LOG_FATAL; break;
+ case QtInfoMsg: priority = ANDROID_LOG_INFO; break;
+ default: break;
+ }
+ return priority;
+}
+
+void messageHandler(QtMsgType type, const QMessageLogContext& context, const QString& message) {
+ __android_log_write(QtMsgTypeToAndroidPriority(type), "Interface", message.toStdString().c_str());
+}
+
+static jlong toJni(NativeRenderer *renderer) {
+ return reinterpret_cast(renderer);
+}
+
+static NativeRenderer *fromJni(jlong renderer) {
+ return reinterpret_cast(renderer);
+}
+
+#define JNI_METHOD(r, name) JNIEXPORT r JNICALL Java_org_saintandreas_testapp_MainActivity_##name
+
+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
+}
+
+JNI_METHOD(void, nativeDestroyRenderer)
+(JNIEnv *env, jclass clazz, jlong renderer) {
+ delete fromJni(renderer);
+}
+
+JNI_METHOD(void, nativeInitializeGl)
+(JNIEnv *env, jobject obj, jlong renderer) {
+ fromJni(renderer)->InitializeGl();
+}
+
+JNI_METHOD(void, nativeDrawFrame)
+(JNIEnv *env, jobject obj, jlong renderer) {
+ fromJni(renderer)->DrawFrame();
+}
+
+JNI_METHOD(void, nativeOnTriggerEvent)
+(JNIEnv *env, jobject obj, jlong renderer) {
+ fromJni(renderer)->OnTriggerEvent();
+}
+
+JNI_METHOD(void, nativeOnPause)
+(JNIEnv *env, jobject obj, jlong renderer) {
+ fromJni(renderer)->OnPause();
+}
+
+JNI_METHOD(void, nativeOnResume)
+(JNIEnv *env, jobject obj, jlong renderer) {
+ fromJni(renderer)->OnResume();
+}
+
+} // extern "C"
diff --git a/android/app/src/main/cpp/renderer.cpp b/android/app/src/main/cpp/renderer.cpp
new file mode 100644
index 0000000000..a877ebd777
--- /dev/null
+++ b/android/app/src/main/cpp/renderer.cpp
@@ -0,0 +1,636 @@
+#include "renderer.h"
+
+#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
+#extension GL_OVR_multiview2 : enable
+
+layout(num_views=2) in;
+
+layout(location = 0) in vec4 a_Position;
+
+out vec4 v_Color;
+
+void main() {
+ v_Color = vec4(a_Position.xyz, 1.0);
+ gl_Position = vec4(a_Position.xyz, 1.0);
+}
+)glsl";
+
+
+static const char *kPassthroughFragmentShader = R"glsl(
+#version 300 es
+precision mediump float;
+in vec4 v_Color;
+out vec4 FragColor;
+
+void main() { FragColor = v_Color; }
+)glsl";
+
+static void CheckGLError(const char* label) {
+ int gl_error = glGetError();
+ if (gl_error != GL_NO_ERROR) {
+ qWarning("GL error @ %s: %d", label, gl_error);
+ // Crash immediately to make OpenGL errors obvious.
+ abort();
+ }
+}
+
+// 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,
+ 0.5f, -0.5f, 0.0f,
+ 0.0f, 0.5f, 0.0f
+ }};
+}
+
+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);
+ CheckGLError("build program");
+
+ glGenBuffers(1, &_cubeBuffer);
+ glBindBuffer(GL_ARRAY_BUFFER, _cubeBuffer);
+ 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);
+
+ 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(
+ std::chrono::system_clock::now() - start);
+ glm::vec3 v;
+ v.r = (float) (now.count() % 1000) / 1000.0f;
+ 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");
+
+}
+
+void NativeRenderer::OnTriggerEvent() {
+ qDebug() << "QQQ" << __FUNCTION__;
+}
+
+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
new file mode 100644
index 0000000000..df7c51cab4
--- /dev/null
+++ b/android/app/src/main/cpp/renderer.h
@@ -0,0 +1,60 @@
+#pragma once
+
+#include
+#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();
+ void OnPause();
+ void OnResume();
+
+private:
+
+
+ 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};
+};
diff --git a/android/app/src/main/java/org/saintandreas/testapp/MainActivity.java b/android/app/src/main/java/org/saintandreas/testapp/MainActivity.java
new file mode 100644
index 0000000000..7eea14dce9
--- /dev/null
+++ b/android/app/src/main/java/org/saintandreas/testapp/MainActivity.java
@@ -0,0 +1,105 @@
+package org.saintandreas.testapp;
+
+import android.app.Activity;
+import android.content.Context;
+import android.opengl.GLSurfaceView;
+import android.os.Bundle;
+import android.view.View;
+
+import com.google.vr.ndk.base.AndroidCompat;
+import com.google.vr.ndk.base.GvrLayout;
+
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.opengles.GL10;
+
+public class MainActivity extends Activity {
+ private final static int IMMERSIVE_STICKY_VIEW_FLAGS = View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
+ View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |
+ View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |
+ View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
+ View.SYSTEM_UI_FLAG_FULLSCREEN |
+ View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
+
+ static {
+ System.loadLibrary("gvr");
+ System.loadLibrary("native-lib");
+ }
+
+ private long nativeRenderer;
+ private GvrLayout gvrLayout;
+ private GLSurfaceView surfaceView;
+
+ private native long nativeCreateRenderer(ClassLoader appClassLoader, Context context, long nativeGvrContext);
+ private native void nativeDestroyRenderer(long renderer);
+ private native void nativeInitializeGl(long renderer);
+ private native void nativeDrawFrame(long renderer);
+ private native void nativeOnTriggerEvent(long renderer);
+ private native void nativeOnPause(long renderer);
+ private native void nativeOnResume(long renderer);
+
+ class NativeRenderer implements GLSurfaceView.Renderer {
+ @Override public void onSurfaceCreated(GL10 gl, EGLConfig config) { nativeInitializeGl(nativeRenderer); }
+ @Override public void onSurfaceChanged(GL10 gl, int width, int height) { }
+ @Override public void onDrawFrame(GL10 gl) {
+ nativeDrawFrame(nativeRenderer);
+ }
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setImmersiveSticky();
+ getWindow()
+ .getDecorView()
+ .setOnSystemUiVisibilityChangeListener((int visibility)->{
+ if ((visibility & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0) { setImmersiveSticky(); }
+ });
+
+ gvrLayout = new GvrLayout(this);
+ nativeRenderer = nativeCreateRenderer(
+ getClass().getClassLoader(),
+ getApplicationContext(),
+ gvrLayout.getGvrApi().getNativeGvrContext());
+
+ 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);
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ gvrLayout.shutdown();
+ nativeDestroyRenderer(nativeRenderer);
+ nativeRenderer = 0;
+ }
+
+ @Override
+ 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));
+ }
+
+ private void setImmersiveSticky() {
+ getWindow().getDecorView().setSystemUiVisibility(IMMERSIVE_STICKY_VIEW_FLAGS);
+ }
+}
diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 0000000000..cde69bccce
Binary files /dev/null and b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ
diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
new file mode 100644
index 0000000000..9a078e3e1a
Binary files /dev/null and b/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png differ
diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 0000000000..c133a0cbd3
Binary files /dev/null and b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
new file mode 100644
index 0000000000..efc028a636
Binary files /dev/null and b/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png differ
diff --git a/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 0000000000..bfa42f0e7b
Binary files /dev/null and b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ
diff --git a/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
new file mode 100644
index 0000000000..3af2608a44
Binary files /dev/null and b/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ
diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000000..324e72cdd7
Binary files /dev/null and b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
new file mode 100644
index 0000000000..9bec2e6231
Binary files /dev/null and b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ
diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 0000000000..aee44e1384
Binary files /dev/null and b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ
diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
new file mode 100644
index 0000000000..34947cd6bb
Binary files /dev/null and b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ
diff --git a/android/app/src/main/res/values/colors.xml b/android/app/src/main/res/values/colors.xml
new file mode 100644
index 0000000000..344907f039
--- /dev/null
+++ b/android/app/src/main/res/values/colors.xml
@@ -0,0 +1,4 @@
+
+
+ #ffffff
+
diff --git a/android/app/src/main/res/values/strings.xml b/android/app/src/main/res/values/strings.xml
new file mode 100644
index 0000000000..5d6a4c1b99
--- /dev/null
+++ b/android/app/src/main/res/values/strings.xml
@@ -0,0 +1,3 @@
+
+ TestApp
+
diff --git a/android/app/src/main/res/values/styles.xml b/android/app/src/main/res/values/styles.xml
new file mode 100644
index 0000000000..033324ac58
--- /dev/null
+++ b/android/app/src/main/res/values/styles.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
diff --git a/android/build.gradle b/android/build.gradle
new file mode 100644
index 0000000000..77c3dd498c
--- /dev/null
+++ b/android/build.gradle
@@ -0,0 +1,91 @@
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+buildscript {
+ repositories {
+ jcenter()
+ }
+ 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
+ }
+}
+
+allprojects {
+ repositories {
+ jcenter()
+ }
+}
+
+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/gradle.properties b/android/gradle.properties
new file mode 100644
index 0000000000..aac7c9b461
--- /dev/null
+++ b/android/gradle.properties
@@ -0,0 +1,17 @@
+# Project-wide Gradle settings.
+
+# IDE (e.g. Android Studio) users:
+# Gradle settings configured through the IDE *will override*
+# any settings specified in this file.
+
+# For more details on how to configure your build environment visit
+# http://www.gradle.org/docs/current/userguide/build_environment.html
+
+# Specifies the JVM arguments used for the daemon process.
+# The setting is particularly useful for tweaking memory settings.
+org.gradle.jvmargs=-Xmx1536m
+
+# When configured, Gradle will run in incubating parallel mode.
+# This option should only be used with decoupled projects. More details, visit
+# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
+# org.gradle.parallel=true
diff --git a/android/settings.gradle b/android/settings.gradle
new file mode 100644
index 0000000000..e7b4def49c
--- /dev/null
+++ b/android/settings.gradle
@@ -0,0 +1 @@
+include ':app'
diff --git a/cmake/android/AndroidManifest.xml.in b/cmake/android/AndroidManifest.xml.in
deleted file mode 100755
index aa834f3384..0000000000
--- a/cmake/android/AndroidManifest.xml.in
+++ /dev/null
@@ -1,82 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- ${ANDROID_EXTRA_ACTIVITY_XML}
-
-
-
-
-
- ${ANDROID_EXTRA_APPLICATION_XML}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/cmake/android/QtCreateAPK.cmake b/cmake/android/QtCreateAPK.cmake
deleted file mode 100644
index 30ee2f57bd..0000000000
--- a/cmake/android/QtCreateAPK.cmake
+++ /dev/null
@@ -1,159 +0,0 @@
-#
-# QtCreateAPK.cmake
-#
-# Created by Stephen Birarda on 11/18/14.
-# Copyright 2013 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
-#
-
-#
-# OPTIONS
-# These options will modify how QtCreateAPK behaves. May be useful if somebody wants to fork.
-# For High Fidelity purposes these should not need to be changed.
-#
-set(ANDROID_THIS_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}) # Directory this CMake file is in
-
-if (POLICY CMP0026)
- cmake_policy(SET CMP0026 OLD)
-endif ()
-
-macro(qt_create_apk)
- if(ANDROID_APK_FULLSCREEN)
- set(ANDROID_APK_THEME "android:theme=\"@android:style/Theme.NoTitleBar.Fullscreen\"")
- else()
- set(ANDROID_APK_THEME "")
- endif()
-
- if (UPPER_CMAKE_BUILD_TYPE MATCHES RELEASE)
- set(ANDROID_APK_DEBUGGABLE "false")
- set(ANDROID_APK_RELEASE_LOCAL ${ANDROID_APK_RELEASE})
- else ()
- set(ANDROID_APK_DEBUGGABLE "true")
- set(ANDROID_APK_RELEASE_LOCAL "0")
- endif ()
-
- # Create "AndroidManifest.xml"
- configure_file("${ANDROID_THIS_DIRECTORY}/AndroidManifest.xml.in" "${ANDROID_APK_BUILD_DIR}/AndroidManifest.xml")
-
- # create "strings.xml"
- configure_file("${ANDROID_THIS_DIRECTORY}/strings.xml.in" "${ANDROID_APK_BUILD_DIR}/res/values/strings.xml")
-
- # find androiddeployqt
- find_program(ANDROID_DEPLOY_QT androiddeployqt HINTS "${QT_DIR}/bin")
-
- # set the path to our app shared library
- set(EXECUTABLE_DESTINATION_PATH "${ANDROID_APK_OUTPUT_DIR}/libs/${ANDROID_ABI}/lib${TARGET_NAME}.so")
-
- # add our dependencies to the deployment file
- get_property(_DEPENDENCIES TARGET ${TARGET_NAME} PROPERTY INTERFACE_LINK_LIBRARIES)
-
- foreach(_IGNORE_COPY IN LISTS IGNORE_COPY_LIBS)
- list(REMOVE_ITEM _DEPENDENCIES ${_IGNORE_COPY})
- endforeach()
-
- foreach(_DEP IN LISTS _DEPENDENCIES)
- if (NOT TARGET ${_DEP})
- list(APPEND _DEPS_LIST ${_DEP})
- else ()
- if(NOT _DEP MATCHES "Qt5::.*")
- get_property(_DEP_LOCATION TARGET ${_DEP} PROPERTY "LOCATION_${CMAKE_BUILD_TYPE}")
-
- # recurisvely add libraries which are dependencies of this target
- get_property(_DEP_DEPENDENCIES TARGET ${_DEP} PROPERTY INTERFACE_LINK_LIBRARIES)
-
- foreach(_SUB_DEP IN LISTS _DEP_DEPENDENCIES)
- if (NOT TARGET ${_SUB_DEP} AND NOT _SUB_DEP MATCHES "Qt5::.*")
- list(APPEND _DEPS_LIST ${_SUB_DEP})
- endif()
- endforeach()
-
- list(APPEND _DEPS_LIST ${_DEP_LOCATION})
- endif()
- endif ()
- endforeach()
-
- list(REMOVE_DUPLICATES _DEPS_LIST)
-
- # just copy static libs to apk libs folder - don't add to deps list
- foreach(_LOCATED_DEP IN LISTS _DEPS_LIST)
- if (_LOCATED_DEP MATCHES "\\.a$")
- add_custom_command(
- TARGET ${TARGET_NAME}
- POST_BUILD
- COMMAND ${CMAKE_COMMAND} -E copy ${_LOCATED_DEP} "${ANDROID_APK_OUTPUT_DIR}/libs/${ANDROID_ABI}"
- )
- list(REMOVE_ITEM _DEPS_LIST ${_LOCATED_DEP})
- endif ()
- endforeach()
-
- string(REPLACE ";" "," _DEPS "${_DEPS_LIST}")
-
- configure_file("${ANDROID_THIS_DIRECTORY}/deployment-file.json.in" "${TARGET_NAME}-deployment.json")
-
- # copy the res folder from the target to the apk build dir
- add_custom_target(
- ${TARGET_NAME}-copy-res
- COMMAND ${CMAKE_COMMAND} -E copy_directory "${CMAKE_CURRENT_SOURCE_DIR}/res" "${ANDROID_APK_BUILD_DIR}/res"
- )
-
- # copy the assets folder from the target to the apk build dir
- add_custom_target(
- ${TARGET_NAME}-copy-assets
- COMMAND ${CMAKE_COMMAND} -E copy_directory "${CMAKE_CURRENT_SOURCE_DIR}/assets" "${ANDROID_APK_BUILD_DIR}/assets"
- )
-
- # copy the java folder from src to the apk build dir
- add_custom_target(
- ${TARGET_NAME}-copy-java
- COMMAND ${CMAKE_COMMAND} -E copy_directory "${CMAKE_CURRENT_SOURCE_DIR}/src/java" "${ANDROID_APK_BUILD_DIR}/src"
- )
-
- # copy the libs folder from src to the apk build dir
- add_custom_target(
- ${TARGET_NAME}-copy-libs
- COMMAND ${CMAKE_COMMAND} -E copy_directory "${CMAKE_CURRENT_SOURCE_DIR}/libs" "${ANDROID_APK_BUILD_DIR}/libs"
- )
-
- # handle setup for ndk-gdb
- add_custom_target(${TARGET_NAME}-gdb DEPENDS ${TARGET_NAME})
-
- if (ANDROID_APK_DEBUGGABLE)
- get_property(TARGET_LOCATION TARGET ${TARGET_NAME} PROPERTY LOCATION)
-
- set(GDB_SOLIB_PATH ${ANDROID_APK_BUILD_DIR}/obj/local/${ANDROID_NDK_ABI_NAME}/)
-
- # generate essential Android Makefiles
- file(WRITE ${ANDROID_APK_BUILD_DIR}/jni/Android.mk "APP_ABI := ${ANDROID_NDK_ABI_NAME}\n")
- file(WRITE ${ANDROID_APK_BUILD_DIR}/jni/Application.mk "APP_ABI := ${ANDROID_NDK_ABI_NAME}\n")
-
- # create gdb.setup
- get_directory_property(PROJECT_INCLUDES DIRECTORY ${PROJECT_SOURCE_DIR} INCLUDE_DIRECTORIES)
- string(REGEX REPLACE ";" " " PROJECT_INCLUDES "${PROJECT_INCLUDES}")
- file(WRITE ${ANDROID_APK_BUILD_DIR}/libs/${ANDROID_NDK_ABI_NAME}/gdb.setup "set solib-search-path ${GDB_SOLIB_PATH}\n")
- file(APPEND ${ANDROID_APK_BUILD_DIR}/libs/${ANDROID_NDK_ABI_NAME}/gdb.setup "directory ${PROJECT_INCLUDES}\n")
-
- # copy lib to obj
- add_custom_command(TARGET ${TARGET_NAME}-gdb PRE_BUILD COMMAND ${CMAKE_COMMAND} -E make_directory ${GDB_SOLIB_PATH})
- add_custom_command(TARGET ${TARGET_NAME}-gdb PRE_BUILD COMMAND cp ${TARGET_LOCATION} ${GDB_SOLIB_PATH})
-
- # strip symbols
- add_custom_command(TARGET ${TARGET_NAME}-gdb PRE_BUILD COMMAND ${CMAKE_STRIP} ${TARGET_LOCATION})
- endif ()
-
- # use androiddeployqt to create the apk
- add_custom_target(${TARGET_NAME}-apk
- COMMAND ${ANDROID_DEPLOY_QT} --input "${TARGET_NAME}-deployment.json" --output "${ANDROID_APK_OUTPUT_DIR}" --android-platform android-${ANDROID_API_LEVEL} ${ANDROID_DEPLOY_QT_INSTALL} --verbose --deployment bundled "\\$(ARGS)"
- DEPENDS ${TARGET_NAME} ${TARGET_NAME}-copy-res ${TARGET_NAME}-copy-assets ${TARGET_NAME}-copy-java ${TARGET_NAME}-copy-libs ${TARGET_NAME}-gdb
- )
-
- # rename the APK if the caller asked us to
- if (ANDROID_APK_CUSTOM_NAME)
- add_custom_command(
- TARGET ${TARGET_NAME}-apk
- POST_BUILD
- COMMAND ${CMAKE_COMMAND} -E rename "${ANDROID_APK_OUTPUT_DIR}/bin/QtApp-debug.apk" "${ANDROID_APK_OUTPUT_DIR}/bin/${ANDROID_APK_CUSTOM_NAME}"
- )
- endif ()
-endmacro()
\ No newline at end of file
diff --git a/cmake/android/android.toolchain.cmake b/cmake/android/android.toolchain.cmake
deleted file mode 100755
index 806cef6b18..0000000000
--- a/cmake/android/android.toolchain.cmake
+++ /dev/null
@@ -1,1725 +0,0 @@
-# Copyright (c) 2010-2011, Ethan Rublee
-# Copyright (c) 2011-2014, Andrey Kamaev
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are met:
-#
-# 1. Redistributions of source code must retain the above copyright notice,
-# this list of conditions and the following disclaimer.
-#
-# 2. Redistributions in binary form must reproduce the above copyright notice,
-# this list of conditions and the following disclaimer in the documentation
-# and/or other materials provided with the distribution.
-#
-# 3. Neither the name of the copyright holder nor the names of its
-# contributors may be used to endorse or promote products derived from this
-# software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
-# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-# POSSIBILITY OF SUCH DAMAGE.
-
-# ------------------------------------------------------------------------------
-# Android CMake toolchain file, for use with the Android NDK r5-r10d
-# Requires cmake 2.6.3 or newer (2.8.9 or newer is recommended).
-# See home page: https://github.com/taka-no-me/android-cmake
-#
-# Usage Linux:
-# $ export ANDROID_NDK=/absolute/path/to/the/android-ndk
-# $ mkdir build && cd build
-# $ cmake -DCMAKE_TOOLCHAIN_FILE=path/to/the/android.toolchain.cmake ..
-# $ make -j8
-#
-# Usage Windows:
-# You need native port of make to build your project.
-# Android NDK r7 (and newer) already has make.exe on board.
-# For older NDK you have to install it separately.
-# For example, this one: http://gnuwin32.sourceforge.net/packages/make.htm
-#
-# $ SET ANDROID_NDK=C:\absolute\path\to\the\android-ndk
-# $ mkdir build && cd build
-# $ cmake.exe -G"MinGW Makefiles"
-# -DCMAKE_TOOLCHAIN_FILE=path\to\the\android.toolchain.cmake
-# -DCMAKE_MAKE_PROGRAM="%ANDROID_NDK%\prebuilt\windows\bin\make.exe" ..
-# $ cmake.exe --build .
-#
-#
-# Options (can be set as cmake parameters: -D=):
-# ANDROID_NDK=/opt/android-ndk - path to the NDK root.
-# Can be set as environment variable. Can be set only at first cmake run.
-#
-# ANDROID_ABI=armeabi-v7a - specifies the target Application Binary
-# Interface (ABI). This option nearly matches to the APP_ABI variable
-# used by ndk-build tool from Android NDK.
-#
-# Possible targets are:
-# "armeabi" - ARMv5TE based CPU with software floating point operations
-# "armeabi-v7a" - ARMv7 based devices with hardware FPU instructions
-# this ABI target is used by default
-# "armeabi-v7a with NEON" - same as armeabi-v7a, but
-# sets NEON as floating-point unit
-# "armeabi-v7a with VFPV3" - same as armeabi-v7a, but
-# sets VFPV3 as floating-point unit (has 32 registers instead of 16)
-# "armeabi-v6 with VFP" - tuned for ARMv6 processors having VFP
-# "x86" - IA-32 instruction set
-# "mips" - MIPS32 instruction set
-#
-# 64-bit ABIs for NDK r10 and newer:
-# "arm64-v8a" - ARMv8 AArch64 instruction set
-# "x86_64" - Intel64 instruction set (r1)
-# "mips64" - MIPS64 instruction set (r6)
-#
-# ANDROID_NATIVE_API_LEVEL=android-8 - level of Android API compile for.
-# Option is read-only when standalone toolchain is used.
-# Note: building for "android-L" requires explicit configuration.
-#
-# ANDROID_TOOLCHAIN_NAME=arm-linux-androideabi-4.9 - the name of compiler
-# toolchain to be used. The list of possible values depends on the NDK
-# version. For NDK r10c the possible values are:
-#
-# * aarch64-linux-android-4.9
-# * aarch64-linux-android-clang3.4
-# * aarch64-linux-android-clang3.5
-# * arm-linux-androideabi-4.6
-# * arm-linux-androideabi-4.8
-# * arm-linux-androideabi-4.9 (default)
-# * arm-linux-androideabi-clang3.4
-# * arm-linux-androideabi-clang3.5
-# * mips64el-linux-android-4.9
-# * mips64el-linux-android-clang3.4
-# * mips64el-linux-android-clang3.5
-# * mipsel-linux-android-4.6
-# * mipsel-linux-android-4.8
-# * mipsel-linux-android-4.9
-# * mipsel-linux-android-clang3.4
-# * mipsel-linux-android-clang3.5
-# * x86-4.6
-# * x86-4.8
-# * x86-4.9
-# * x86-clang3.4
-# * x86-clang3.5
-# * x86_64-4.9
-# * x86_64-clang3.4
-# * x86_64-clang3.5
-#
-# ANDROID_FORCE_ARM_BUILD=OFF - set ON to generate 32-bit ARM instructions
-# instead of Thumb. Is not available for "armeabi-v6 with VFP"
-# (is forced to be ON) ABI.
-#
-# ANDROID_NO_UNDEFINED=ON - set ON to show all undefined symbols as linker
-# errors even if they are not used.
-#
-# ANDROID_SO_UNDEFINED=OFF - set ON to allow undefined symbols in shared
-# libraries. Automatically turned for NDK r5x and r6x due to GLESv2
-# problems.
-#
-# ANDROID_STL=gnustl_static - specify the runtime to use.
-#
-# Possible values are:
-# none -> Do not configure the runtime.
-# system -> Use the default minimal system C++ runtime library.
-# Implies -fno-rtti -fno-exceptions.
-# Is not available for standalone toolchain.
-# system_re -> Use the default minimal system C++ runtime library.
-# Implies -frtti -fexceptions.
-# Is not available for standalone toolchain.
-# gabi++_static -> Use the GAbi++ runtime as a static library.
-# Implies -frtti -fno-exceptions.
-# Available for NDK r7 and newer.
-# Is not available for standalone toolchain.
-# gabi++_shared -> Use the GAbi++ runtime as a shared library.
-# Implies -frtti -fno-exceptions.
-# Available for NDK r7 and newer.
-# Is not available for standalone toolchain.
-# stlport_static -> Use the STLport runtime as a static library.
-# Implies -fno-rtti -fno-exceptions for NDK before r7.
-# Implies -frtti -fno-exceptions for NDK r7 and newer.
-# Is not available for standalone toolchain.
-# stlport_shared -> Use the STLport runtime as a shared library.
-# Implies -fno-rtti -fno-exceptions for NDK before r7.
-# Implies -frtti -fno-exceptions for NDK r7 and newer.
-# Is not available for standalone toolchain.
-# gnustl_static -> Use the GNU STL as a static library.
-# Implies -frtti -fexceptions.
-# gnustl_shared -> Use the GNU STL as a shared library.
-# Implies -frtti -fno-exceptions.
-# Available for NDK r7b and newer.
-# Silently degrades to gnustl_static if not available.
-# c++_static -> Use the LLVM libc++ runtime as a static library.
-# c++_shared -> Use the LLVM libc++ runtime as a shared library.
-#
-# ANDROID_STL_FORCE_FEATURES=ON - turn rtti and exceptions support based on
-# chosen runtime. If disabled, then the user is responsible for settings
-# these options.
-#
-# What?:
-# android-cmake toolchain searches for NDK/toolchain in the following order:
-# ANDROID_NDK - cmake parameter
-# ANDROID_NDK - environment variable
-# ANDROID_STANDALONE_TOOLCHAIN - cmake parameter
-# ANDROID_STANDALONE_TOOLCHAIN - environment variable
-# ANDROID_NDK - default locations
-# ANDROID_STANDALONE_TOOLCHAIN - default locations
-#
-# Make sure to do the following in your scripts:
-# SET( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${my_cxx_flags}" )
-# SET( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${my_cxx_flags}" )
-# The flags will be prepopulated with critical flags, so don't loose them.
-# Also be aware that toolchain also sets configuration-specific compiler
-# flags and linker flags.
-#
-# ANDROID and BUILD_ANDROID will be set to true, you may test any of these
-# variables to make necessary Android-specific configuration changes.
-#
-# Also ARMEABI or ARMEABI_V7A or X86 or MIPS or ARM64_V8A or X86_64 or MIPS64
-# will be set true, mutually exclusive. NEON option will be set true
-# if VFP is set to NEON.
-#
-# ------------------------------------------------------------------------------
-
-cmake_minimum_required( VERSION 2.6.3 )
-
-if( DEFINED CMAKE_CROSSCOMPILING )
- # subsequent toolchain loading is not really needed
- return()
-endif()
-
-if( CMAKE_TOOLCHAIN_FILE )
- # touch toolchain variable to suppress "unused variable" warning
-endif()
-
-# inherit settings in recursive loads
-get_property( _CMAKE_IN_TRY_COMPILE GLOBAL PROPERTY IN_TRY_COMPILE )
-if( _CMAKE_IN_TRY_COMPILE )
- include( "${CMAKE_CURRENT_SOURCE_DIR}/../android.toolchain.config.cmake" OPTIONAL )
-endif()
-
-# this one is important
-if( CMAKE_VERSION VERSION_GREATER "3.0.99" )
- set( CMAKE_SYSTEM_NAME Android )
-else()
- set( CMAKE_SYSTEM_NAME Linux )
-endif()
-
-# this one not so much
-set( CMAKE_SYSTEM_VERSION 1 )
-
-# rpath makes low sense for Android
-set( CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG "" )
-set( CMAKE_SKIP_RPATH TRUE CACHE BOOL "If set, runtime paths are not added when using shared libraries." )
-
-# NDK search paths
-set( ANDROID_SUPPORTED_NDK_VERSIONS ${ANDROID_EXTRA_NDK_VERSIONS} -r10d -r10c -r10b -r10 -r9d -r9c -r9b -r9 -r8e -r8d -r8c -r8b -r8 -r7c -r7b -r7 -r6b -r6 -r5c -r5b -r5 "" )
-if( NOT DEFINED ANDROID_NDK_SEARCH_PATHS )
- if( CMAKE_HOST_WIN32 )
- file( TO_CMAKE_PATH "$ENV{PROGRAMFILES}" ANDROID_NDK_SEARCH_PATHS )
- set( ANDROID_NDK_SEARCH_PATHS "${ANDROID_NDK_SEARCH_PATHS}" "$ENV{SystemDrive}/NVPACK" )
- else()
- file( TO_CMAKE_PATH "$ENV{HOME}" ANDROID_NDK_SEARCH_PATHS )
- set( ANDROID_NDK_SEARCH_PATHS /opt "${ANDROID_NDK_SEARCH_PATHS}/NVPACK" )
- endif()
-endif()
-if( NOT DEFINED ANDROID_STANDALONE_TOOLCHAIN_SEARCH_PATH )
- set( ANDROID_STANDALONE_TOOLCHAIN_SEARCH_PATH /opt/android-toolchain )
-endif()
-
-# known ABIs
-set( ANDROID_SUPPORTED_ABIS_arm "armeabi-v7a;armeabi;armeabi-v7a with NEON;armeabi-v7a with VFPV3;armeabi-v6 with VFP" )
-set( ANDROID_SUPPORTED_ABIS_arm64 "arm64-v8a" )
-set( ANDROID_SUPPORTED_ABIS_x86 "x86" )
-set( ANDROID_SUPPORTED_ABIS_x86_64 "x86_64" )
-set( ANDROID_SUPPORTED_ABIS_mips "mips" )
-set( ANDROID_SUPPORTED_ABIS_mips64 "mips64" )
-
-# API level defaults
-set( ANDROID_DEFAULT_NDK_API_LEVEL 8 )
-set( ANDROID_DEFAULT_NDK_API_LEVEL_arm64 21 )
-set( ANDROID_DEFAULT_NDK_API_LEVEL_x86 9 )
-set( ANDROID_DEFAULT_NDK_API_LEVEL_x86_64 21 )
-set( ANDROID_DEFAULT_NDK_API_LEVEL_mips 9 )
-set( ANDROID_DEFAULT_NDK_API_LEVEL_mips64 21 )
-
-
-macro( __LIST_FILTER listvar regex )
- if( ${listvar} )
- foreach( __val ${${listvar}} )
- if( __val MATCHES "${regex}" )
- list( REMOVE_ITEM ${listvar} "${__val}" )
- endif()
- endforeach()
- endif()
-endmacro()
-
-macro( __INIT_VARIABLE var_name )
- set( __test_path 0 )
- foreach( __var ${ARGN} )
- if( __var STREQUAL "PATH" )
- set( __test_path 1 )
- break()
- endif()
- endforeach()
-
- if( __test_path AND NOT EXISTS "${${var_name}}" )
- unset( ${var_name} CACHE )
- endif()
-
- if( " ${${var_name}}" STREQUAL " " )
- set( __values 0 )
- foreach( __var ${ARGN} )
- if( __var STREQUAL "VALUES" )
- set( __values 1 )
- elseif( NOT __var STREQUAL "PATH" )
- if( __var MATCHES "^ENV_.*$" )
- string( REPLACE "ENV_" "" __var "${__var}" )
- set( __value "$ENV{${__var}}" )
- elseif( DEFINED ${__var} )
- set( __value "${${__var}}" )
- elseif( __values )
- set( __value "${__var}" )
- else()
- set( __value "" )
- endif()
-
- if( NOT " ${__value}" STREQUAL " " AND (NOT __test_path OR EXISTS "${__value}") )
- set( ${var_name} "${__value}" )
- break()
- endif()
- endif()
- endforeach()
- unset( __value )
- unset( __values )
- endif()
-
- if( __test_path )
- file( TO_CMAKE_PATH "${${var_name}}" ${var_name} )
- endif()
- unset( __test_path )
-endmacro()
-
-macro( __DETECT_NATIVE_API_LEVEL _var _path )
- set( __ndkApiLevelRegex "^[\t ]*#define[\t ]+__ANDROID_API__[\t ]+([0-9]+)[\t ]*.*$" )
- file( STRINGS ${_path} __apiFileContent REGEX "${__ndkApiLevelRegex}" )
- if( NOT __apiFileContent )
- message( SEND_ERROR "Could not get Android native API level. Probably you have specified invalid level value, or your copy of NDK/toolchain is broken." )
- endif()
- string( REGEX REPLACE "${__ndkApiLevelRegex}" "\\1" ${_var} "${__apiFileContent}" )
- unset( __apiFileContent )
- unset( __ndkApiLevelRegex )
-endmacro()
-
-macro( __DETECT_TOOLCHAIN_MACHINE_NAME _var _root )
- if( EXISTS "${_root}" )
- file( GLOB __gccExePath RELATIVE "${_root}/bin/" "${_root}/bin/*-gcc${TOOL_OS_SUFFIX}" )
- __LIST_FILTER( __gccExePath "^[.].*" )
- list( LENGTH __gccExePath __gccExePathsCount )
- if( NOT __gccExePathsCount EQUAL 1 AND NOT _CMAKE_IN_TRY_COMPILE )
- message( WARNING "Could not determine machine name for compiler from ${_root}" )
- set( ${_var} "" )
- else()
- get_filename_component( __gccExeName "${__gccExePath}" NAME_WE )
- string( REPLACE "-gcc" "" ${_var} "${__gccExeName}" )
- endif()
- unset( __gccExePath )
- unset( __gccExePathsCount )
- unset( __gccExeName )
- else()
- set( ${_var} "" )
- endif()
-endmacro()
-
-
-# fight against cygwin
-set( ANDROID_FORBID_SYGWIN TRUE CACHE BOOL "Prevent cmake from working under cygwin and using cygwin tools")
-mark_as_advanced( ANDROID_FORBID_SYGWIN )
-if( ANDROID_FORBID_SYGWIN )
- if( CYGWIN )
- message( FATAL_ERROR "Android NDK and android-cmake toolchain are not welcome Cygwin. It is unlikely that this cmake toolchain will work under cygwin. But if you want to try then you can set cmake variable ANDROID_FORBID_SYGWIN to FALSE and rerun cmake." )
- endif()
-
- if( CMAKE_HOST_WIN32 )
- # remove cygwin from PATH
- set( __new_path "$ENV{PATH}")
- __LIST_FILTER( __new_path "cygwin" )
- set(ENV{PATH} "${__new_path}")
- unset(__new_path)
- endif()
-endif()
-
-
-# detect current host platform
-if( NOT DEFINED ANDROID_NDK_HOST_X64 AND (CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "amd64|x86_64|AMD64" OR CMAKE_HOST_APPLE) )
- set( ANDROID_NDK_HOST_X64 1 CACHE BOOL "Try to use 64-bit compiler toolchain" )
- mark_as_advanced( ANDROID_NDK_HOST_X64 )
-endif()
-
-set( TOOL_OS_SUFFIX "" )
-if( CMAKE_HOST_APPLE )
- set( ANDROID_NDK_HOST_SYSTEM_NAME "darwin-x86_64" )
- set( ANDROID_NDK_HOST_SYSTEM_NAME2 "darwin-x86" )
-elseif( CMAKE_HOST_WIN32 )
- set( ANDROID_NDK_HOST_SYSTEM_NAME "windows-x86_64" )
- set( ANDROID_NDK_HOST_SYSTEM_NAME2 "windows" )
- set( TOOL_OS_SUFFIX ".exe" )
-elseif( CMAKE_HOST_UNIX )
- set( ANDROID_NDK_HOST_SYSTEM_NAME "linux-x86_64" )
- set( ANDROID_NDK_HOST_SYSTEM_NAME2 "linux-x86" )
-else()
- message( FATAL_ERROR "Cross-compilation on your platform is not supported by this cmake toolchain" )
-endif()
-
-if( NOT ANDROID_NDK_HOST_X64 )
- set( ANDROID_NDK_HOST_SYSTEM_NAME ${ANDROID_NDK_HOST_SYSTEM_NAME2} )
-endif()
-
-# see if we have path to Android NDK
-if( NOT ANDROID_NDK AND NOT ANDROID_STANDALONE_TOOLCHAIN )
- __INIT_VARIABLE( ANDROID_NDK PATH ENV_ANDROID_NDK )
-endif()
-if( NOT ANDROID_NDK )
- # see if we have path to Android standalone toolchain
- __INIT_VARIABLE( ANDROID_STANDALONE_TOOLCHAIN PATH ENV_ANDROID_STANDALONE_TOOLCHAIN )
-
- if( NOT ANDROID_STANDALONE_TOOLCHAIN )
- #try to find Android NDK in one of the the default locations
- set( __ndkSearchPaths )
- foreach( __ndkSearchPath ${ANDROID_NDK_SEARCH_PATHS} )
- foreach( suffix ${ANDROID_SUPPORTED_NDK_VERSIONS} )
- list( APPEND __ndkSearchPaths "${__ndkSearchPath}/android-ndk${suffix}" )
- endforeach()
- endforeach()
- __INIT_VARIABLE( ANDROID_NDK PATH VALUES ${__ndkSearchPaths} )
- unset( __ndkSearchPaths )
-
- if( ANDROID_NDK )
- message( STATUS "Using default path for Android NDK: ${ANDROID_NDK}" )
- message( STATUS " If you prefer to use a different location, please define a cmake or environment variable: ANDROID_NDK" )
- else()
- #try to find Android standalone toolchain in one of the the default locations
- __INIT_VARIABLE( ANDROID_STANDALONE_TOOLCHAIN PATH ANDROID_STANDALONE_TOOLCHAIN_SEARCH_PATH )
-
- if( ANDROID_STANDALONE_TOOLCHAIN )
- message( STATUS "Using default path for standalone toolchain ${ANDROID_STANDALONE_TOOLCHAIN}" )
- message( STATUS " If you prefer to use a different location, please define the variable: ANDROID_STANDALONE_TOOLCHAIN" )
- endif( ANDROID_STANDALONE_TOOLCHAIN )
- endif( ANDROID_NDK )
- endif( NOT ANDROID_STANDALONE_TOOLCHAIN )
-endif( NOT ANDROID_NDK )
-
-# remember found paths
-if( ANDROID_NDK )
- get_filename_component( ANDROID_NDK "${ANDROID_NDK}" ABSOLUTE )
- set( ANDROID_NDK "${ANDROID_NDK}" CACHE INTERNAL "Path of the Android NDK" FORCE )
- set( BUILD_WITH_ANDROID_NDK True )
- if( EXISTS "${ANDROID_NDK}/RELEASE.TXT" )
- file( STRINGS "${ANDROID_NDK}/RELEASE.TXT" ANDROID_NDK_RELEASE_FULL LIMIT_COUNT 1 REGEX "r[0-9]+[a-z]?" )
- string( REGEX MATCH "r([0-9]+)([a-z]?)" ANDROID_NDK_RELEASE "${ANDROID_NDK_RELEASE_FULL}" )
- else()
- set( ANDROID_NDK_RELEASE "r1x" )
- set( ANDROID_NDK_RELEASE_FULL "unreleased" )
- endif()
- string( REGEX REPLACE "r([0-9]+)([a-z]?)" "\\1*1000" ANDROID_NDK_RELEASE_NUM "${ANDROID_NDK_RELEASE}" )
- string( FIND " abcdefghijklmnopqastuvwxyz" "${CMAKE_MATCH_2}" __ndkReleaseLetterNum )
- math( EXPR ANDROID_NDK_RELEASE_NUM "${ANDROID_NDK_RELEASE_NUM}+${__ndkReleaseLetterNum}" )
-elseif( ANDROID_STANDALONE_TOOLCHAIN )
- get_filename_component( ANDROID_STANDALONE_TOOLCHAIN "${ANDROID_STANDALONE_TOOLCHAIN}" ABSOLUTE )
- # try to detect change
- if( CMAKE_AR )
- string( LENGTH "${ANDROID_STANDALONE_TOOLCHAIN}" __length )
- string( SUBSTRING "${CMAKE_AR}" 0 ${__length} __androidStandaloneToolchainPreviousPath )
- if( NOT __androidStandaloneToolchainPreviousPath STREQUAL ANDROID_STANDALONE_TOOLCHAIN )
- message( FATAL_ERROR "It is not possible to change path to the Android standalone toolchain on subsequent run." )
- endif()
- unset( __androidStandaloneToolchainPreviousPath )
- unset( __length )
- endif()
- set( ANDROID_STANDALONE_TOOLCHAIN "${ANDROID_STANDALONE_TOOLCHAIN}" CACHE INTERNAL "Path of the Android standalone toolchain" FORCE )
- set( BUILD_WITH_STANDALONE_TOOLCHAIN True )
-else()
- list(GET ANDROID_NDK_SEARCH_PATHS 0 ANDROID_NDK_SEARCH_PATH)
- message( FATAL_ERROR "Could not find neither Android NDK nor Android standalone toolchain.
- You should either set an environment variable:
- export ANDROID_NDK=~/my-android-ndk
- or
- export ANDROID_STANDALONE_TOOLCHAIN=~/my-android-toolchain
- or put the toolchain or NDK in the default path:
- sudo ln -s ~/my-android-ndk ${ANDROID_NDK_SEARCH_PATH}/android-ndk
- sudo ln -s ~/my-android-toolchain ${ANDROID_STANDALONE_TOOLCHAIN_SEARCH_PATH}" )
-endif()
-
-# android NDK layout
-if( BUILD_WITH_ANDROID_NDK )
- if( NOT DEFINED ANDROID_NDK_LAYOUT )
- # try to automatically detect the layout
- if( EXISTS "${ANDROID_NDK}/RELEASE.TXT")
- set( ANDROID_NDK_LAYOUT "RELEASE" )
- elseif( EXISTS "${ANDROID_NDK}/../../linux-x86/toolchain/" )
- set( ANDROID_NDK_LAYOUT "LINARO" )
- elseif( EXISTS "${ANDROID_NDK}/../../gcc/" )
- set( ANDROID_NDK_LAYOUT "ANDROID" )
- endif()
- endif()
- set( ANDROID_NDK_LAYOUT "${ANDROID_NDK_LAYOUT}" CACHE STRING "The inner layout of NDK" )
- mark_as_advanced( ANDROID_NDK_LAYOUT )
- if( ANDROID_NDK_LAYOUT STREQUAL "LINARO" )
- set( ANDROID_NDK_HOST_SYSTEM_NAME ${ANDROID_NDK_HOST_SYSTEM_NAME2} ) # only 32-bit at the moment
- set( ANDROID_NDK_TOOLCHAINS_PATH "${ANDROID_NDK}/../../${ANDROID_NDK_HOST_SYSTEM_NAME}/toolchain" )
- set( ANDROID_NDK_TOOLCHAINS_SUBPATH "" )
- set( ANDROID_NDK_TOOLCHAINS_SUBPATH2 "" )
- elseif( ANDROID_NDK_LAYOUT STREQUAL "ANDROID" )
- set( ANDROID_NDK_HOST_SYSTEM_NAME ${ANDROID_NDK_HOST_SYSTEM_NAME2} ) # only 32-bit at the moment
- set( ANDROID_NDK_TOOLCHAINS_PATH "${ANDROID_NDK}/../../gcc/${ANDROID_NDK_HOST_SYSTEM_NAME}/arm" )
- set( ANDROID_NDK_TOOLCHAINS_SUBPATH "" )
- set( ANDROID_NDK_TOOLCHAINS_SUBPATH2 "" )
- else() # ANDROID_NDK_LAYOUT STREQUAL "RELEASE"
- set( ANDROID_NDK_TOOLCHAINS_PATH "${ANDROID_NDK}/toolchains" )
- set( ANDROID_NDK_TOOLCHAINS_SUBPATH "/prebuilt/${ANDROID_NDK_HOST_SYSTEM_NAME}" )
- set( ANDROID_NDK_TOOLCHAINS_SUBPATH2 "/prebuilt/${ANDROID_NDK_HOST_SYSTEM_NAME2}" )
- endif()
- get_filename_component( ANDROID_NDK_TOOLCHAINS_PATH "${ANDROID_NDK_TOOLCHAINS_PATH}" ABSOLUTE )
-
- # try to detect change of NDK
- if( CMAKE_AR )
- string( LENGTH "${ANDROID_NDK_TOOLCHAINS_PATH}" __length )
- string( SUBSTRING "${CMAKE_AR}" 0 ${__length} __androidNdkPreviousPath )
- if( NOT __androidNdkPreviousPath STREQUAL ANDROID_NDK_TOOLCHAINS_PATH )
- message( FATAL_ERROR "It is not possible to change the path to the NDK on subsequent CMake run. You must remove all generated files from your build folder first.
- " )
- endif()
- unset( __androidNdkPreviousPath )
- unset( __length )
- endif()
-endif()
-
-
-# get all the details about standalone toolchain
-if( BUILD_WITH_STANDALONE_TOOLCHAIN )
- __DETECT_NATIVE_API_LEVEL( ANDROID_SUPPORTED_NATIVE_API_LEVELS "${ANDROID_STANDALONE_TOOLCHAIN}/sysroot/usr/include/android/api-level.h" )
- set( ANDROID_STANDALONE_TOOLCHAIN_API_LEVEL ${ANDROID_SUPPORTED_NATIVE_API_LEVELS} )
- set( __availableToolchains "standalone" )
- __DETECT_TOOLCHAIN_MACHINE_NAME( __availableToolchainMachines "${ANDROID_STANDALONE_TOOLCHAIN}" )
- if( NOT __availableToolchainMachines )
- message( FATAL_ERROR "Could not determine machine name of your toolchain. Probably your Android standalone toolchain is broken." )
- endif()
- if( __availableToolchainMachines MATCHES x86_64 )
- set( __availableToolchainArchs "x86_64" )
- elseif( __availableToolchainMachines MATCHES i686 )
- set( __availableToolchainArchs "x86" )
- elseif( __availableToolchainMachines MATCHES aarch64 )
- set( __availableToolchainArchs "arm64" )
- elseif( __availableToolchainMachines MATCHES arm )
- set( __availableToolchainArchs "arm" )
- elseif( __availableToolchainMachines MATCHES mips64el )
- set( __availableToolchainArchs "mips64" )
- elseif( __availableToolchainMachines MATCHES mipsel )
- set( __availableToolchainArchs "mips" )
- endif()
- execute_process( COMMAND "${ANDROID_STANDALONE_TOOLCHAIN}/bin/${__availableToolchainMachines}-gcc${TOOL_OS_SUFFIX}" -dumpversion
- OUTPUT_VARIABLE __availableToolchainCompilerVersions OUTPUT_STRIP_TRAILING_WHITESPACE )
- string( REGEX MATCH "[0-9]+[.][0-9]+([.][0-9]+)?" __availableToolchainCompilerVersions "${__availableToolchainCompilerVersions}" )
- if( EXISTS "${ANDROID_STANDALONE_TOOLCHAIN}/bin/clang${TOOL_OS_SUFFIX}" )
- list( APPEND __availableToolchains "standalone-clang" )
- list( APPEND __availableToolchainMachines ${__availableToolchainMachines} )
- list( APPEND __availableToolchainArchs ${__availableToolchainArchs} )
- list( APPEND __availableToolchainCompilerVersions ${__availableToolchainCompilerVersions} )
- endif()
-endif()
-
-macro( __GLOB_NDK_TOOLCHAINS __availableToolchainsVar __availableToolchainsLst __toolchain_subpath )
- foreach( __toolchain ${${__availableToolchainsLst}} )
- if( "${__toolchain}" MATCHES "-clang3[.][0-9]$" AND NOT EXISTS "${ANDROID_NDK_TOOLCHAINS_PATH}/${__toolchain}${__toolchain_subpath}" )
- SET( __toolchainVersionRegex "^TOOLCHAIN_VERSION[\t ]+:=[\t ]+(.*)$" )
- FILE( STRINGS "${ANDROID_NDK_TOOLCHAINS_PATH}/${__toolchain}/setup.mk" __toolchainVersionStr REGEX "${__toolchainVersionRegex}" )
- if( __toolchainVersionStr )
- string( REGEX REPLACE "${__toolchainVersionRegex}" "\\1" __toolchainVersionStr "${__toolchainVersionStr}" )
- string( REGEX REPLACE "-clang3[.][0-9]$" "-${__toolchainVersionStr}" __gcc_toolchain "${__toolchain}" )
- else()
- string( REGEX REPLACE "-clang3[.][0-9]$" "-4.6" __gcc_toolchain "${__toolchain}" )
- endif()
- unset( __toolchainVersionStr )
- unset( __toolchainVersionRegex )
- else()
- set( __gcc_toolchain "${__toolchain}" )
- endif()
- __DETECT_TOOLCHAIN_MACHINE_NAME( __machine "${ANDROID_NDK_TOOLCHAINS_PATH}/${__gcc_toolchain}${__toolchain_subpath}" )
- if( __machine )
- string( REGEX MATCH "[0-9]+[.][0-9]+([.][0-9x]+)?$" __version "${__gcc_toolchain}" )
- if( __machine MATCHES x86_64 )
- set( __arch "x86_64" )
- elseif( __machine MATCHES i686 )
- set( __arch "x86" )
- elseif( __machine MATCHES aarch64 )
- set( __arch "arm64" )
- elseif( __machine MATCHES arm )
- set( __arch "arm" )
- elseif( __machine MATCHES mips64el )
- set( __arch "mips64" )
- elseif( __machine MATCHES mipsel )
- set( __arch "mips" )
- else()
- set( __arch "" )
- endif()
- #message("machine: !${__machine}!\narch: !${__arch}!\nversion: !${__version}!\ntoolchain: !${__toolchain}!\n")
- if (__arch)
- list( APPEND __availableToolchainMachines "${__machine}" )
- list( APPEND __availableToolchainArchs "${__arch}" )
- list( APPEND __availableToolchainCompilerVersions "${__version}" )
- list( APPEND ${__availableToolchainsVar} "${__toolchain}" )
- endif()
- endif()
- unset( __gcc_toolchain )
- endforeach()
-endmacro()
-
-# get all the details about NDK
-if( BUILD_WITH_ANDROID_NDK )
- file( GLOB ANDROID_SUPPORTED_NATIVE_API_LEVELS RELATIVE "${ANDROID_NDK}/platforms" "${ANDROID_NDK}/platforms/android-*" )
- string( REPLACE "android-" "" ANDROID_SUPPORTED_NATIVE_API_LEVELS "${ANDROID_SUPPORTED_NATIVE_API_LEVELS}" )
- set( __availableToolchains "" )
- set( __availableToolchainMachines "" )
- set( __availableToolchainArchs "" )
- set( __availableToolchainCompilerVersions "" )
- if( ANDROID_TOOLCHAIN_NAME AND EXISTS "${ANDROID_NDK_TOOLCHAINS_PATH}/${ANDROID_TOOLCHAIN_NAME}/" )
- # do not go through all toolchains if we know the name
- set( __availableToolchainsLst "${ANDROID_TOOLCHAIN_NAME}" )
- __GLOB_NDK_TOOLCHAINS( __availableToolchains __availableToolchainsLst "${ANDROID_NDK_TOOLCHAINS_SUBPATH}" )
- if( NOT __availableToolchains AND NOT ANDROID_NDK_TOOLCHAINS_SUBPATH STREQUAL ANDROID_NDK_TOOLCHAINS_SUBPATH2 )
- __GLOB_NDK_TOOLCHAINS( __availableToolchains __availableToolchainsLst "${ANDROID_NDK_TOOLCHAINS_SUBPATH2}" )
- if( __availableToolchains )
- set( ANDROID_NDK_TOOLCHAINS_SUBPATH ${ANDROID_NDK_TOOLCHAINS_SUBPATH2} )
- endif()
- endif()
- endif()
- if( NOT __availableToolchains )
- file( GLOB __availableToolchainsLst RELATIVE "${ANDROID_NDK_TOOLCHAINS_PATH}" "${ANDROID_NDK_TOOLCHAINS_PATH}/*" )
- if( __availableToolchainsLst )
- list(SORT __availableToolchainsLst) # we need clang to go after gcc
- endif()
- __LIST_FILTER( __availableToolchainsLst "^[.]" )
- __LIST_FILTER( __availableToolchainsLst "llvm" )
- __LIST_FILTER( __availableToolchainsLst "renderscript" )
- __GLOB_NDK_TOOLCHAINS( __availableToolchains __availableToolchainsLst "${ANDROID_NDK_TOOLCHAINS_SUBPATH}" )
- if( NOT __availableToolchains AND NOT ANDROID_NDK_TOOLCHAINS_SUBPATH STREQUAL ANDROID_NDK_TOOLCHAINS_SUBPATH2 )
- __GLOB_NDK_TOOLCHAINS( __availableToolchains __availableToolchainsLst "${ANDROID_NDK_TOOLCHAINS_SUBPATH2}" )
- if( __availableToolchains )
- set( ANDROID_NDK_TOOLCHAINS_SUBPATH ${ANDROID_NDK_TOOLCHAINS_SUBPATH2} )
- endif()
- endif()
- endif()
- if( NOT __availableToolchains )
- message( FATAL_ERROR "Could not find any working toolchain in the NDK. Probably your Android NDK is broken." )
- endif()
-endif()
-
-# build list of available ABIs
-set( ANDROID_SUPPORTED_ABIS "" )
-set( __uniqToolchainArchNames ${__availableToolchainArchs} )
-list( REMOVE_DUPLICATES __uniqToolchainArchNames )
-list( SORT __uniqToolchainArchNames )
-foreach( __arch ${__uniqToolchainArchNames} )
- list( APPEND ANDROID_SUPPORTED_ABIS ${ANDROID_SUPPORTED_ABIS_${__arch}} )
-endforeach()
-unset( __uniqToolchainArchNames )
-if( NOT ANDROID_SUPPORTED_ABIS )
- message( FATAL_ERROR "No one of known Android ABIs is supported by this cmake toolchain." )
-endif()
-
-# choose target ABI
-__INIT_VARIABLE( ANDROID_ABI VALUES ${ANDROID_SUPPORTED_ABIS} )
-# verify that target ABI is supported
-list( FIND ANDROID_SUPPORTED_ABIS "${ANDROID_ABI}" __androidAbiIdx )
-if( __androidAbiIdx EQUAL -1 )
- string( REPLACE ";" "\", \"" PRINTABLE_ANDROID_SUPPORTED_ABIS "${ANDROID_SUPPORTED_ABIS}" )
- message( FATAL_ERROR "Specified ANDROID_ABI = \"${ANDROID_ABI}\" is not supported by this cmake toolchain or your NDK/toolchain.
- Supported values are: \"${PRINTABLE_ANDROID_SUPPORTED_ABIS}\"
- " )
-endif()
-unset( __androidAbiIdx )
-
-# set target ABI options
-if( ANDROID_ABI STREQUAL "x86" )
- set( X86 true )
- set( ANDROID_NDK_ABI_NAME "x86" )
- set( ANDROID_ARCH_NAME "x86" )
- set( ANDROID_LLVM_TRIPLE "i686-none-linux-android" )
- set( CMAKE_SYSTEM_PROCESSOR "i686" )
-elseif( ANDROID_ABI STREQUAL "x86_64" )
- set( X86 true )
- set( X86_64 true )
- set( ANDROID_NDK_ABI_NAME "x86_64" )
- set( ANDROID_ARCH_NAME "x86_64" )
- set( CMAKE_SYSTEM_PROCESSOR "x86_64" )
- set( ANDROID_LLVM_TRIPLE "x86_64-none-linux-android" )
-elseif( ANDROID_ABI STREQUAL "mips64" )
- set( MIPS64 true )
- set( ANDROID_NDK_ABI_NAME "mips64" )
- set( ANDROID_ARCH_NAME "mips64" )
- set( ANDROID_LLVM_TRIPLE "mips64el-none-linux-android" )
- set( CMAKE_SYSTEM_PROCESSOR "mips64" )
-elseif( ANDROID_ABI STREQUAL "mips" )
- set( MIPS true )
- set( ANDROID_NDK_ABI_NAME "mips" )
- set( ANDROID_ARCH_NAME "mips" )
- set( ANDROID_LLVM_TRIPLE "mipsel-none-linux-android" )
- set( CMAKE_SYSTEM_PROCESSOR "mips" )
-elseif( ANDROID_ABI STREQUAL "arm64-v8a" )
- set( ARM64_V8A true )
- set( ANDROID_NDK_ABI_NAME "arm64-v8a" )
- set( ANDROID_ARCH_NAME "arm64" )
- set( ANDROID_LLVM_TRIPLE "aarch64-none-linux-android" )
- set( CMAKE_SYSTEM_PROCESSOR "aarch64" )
- set( VFPV3 true )
- set( NEON true )
-elseif( ANDROID_ABI STREQUAL "armeabi" )
- set( ARMEABI true )
- set( ANDROID_NDK_ABI_NAME "armeabi" )
- set( ANDROID_ARCH_NAME "arm" )
- set( ANDROID_LLVM_TRIPLE "armv5te-none-linux-androideabi" )
- set( CMAKE_SYSTEM_PROCESSOR "armv5te" )
-elseif( ANDROID_ABI STREQUAL "armeabi-v6 with VFP" )
- set( ARMEABI_V6 true )
- set( ANDROID_NDK_ABI_NAME "armeabi" )
- set( ANDROID_ARCH_NAME "arm" )
- set( ANDROID_LLVM_TRIPLE "armv5te-none-linux-androideabi" )
- set( CMAKE_SYSTEM_PROCESSOR "armv6" )
- # need always fallback to older platform
- set( ARMEABI true )
-elseif( ANDROID_ABI STREQUAL "armeabi-v7a")
- set( ARMEABI_V7A true )
- set( ANDROID_NDK_ABI_NAME "armeabi-v7a" )
- set( ANDROID_ARCH_NAME "arm" )
- set( ANDROID_LLVM_TRIPLE "armv7-none-linux-androideabi" )
- set( CMAKE_SYSTEM_PROCESSOR "armv7-a" )
-elseif( ANDROID_ABI STREQUAL "armeabi-v7a with VFPV3" )
- set( ARMEABI_V7A true )
- set( ANDROID_NDK_ABI_NAME "armeabi-v7a" )
- set( ANDROID_ARCH_NAME "arm" )
- set( ANDROID_LLVM_TRIPLE "armv7-none-linux-androideabi" )
- set( CMAKE_SYSTEM_PROCESSOR "armv7-a" )
- set( VFPV3 true )
-elseif( ANDROID_ABI STREQUAL "armeabi-v7a with NEON" )
- set( ARMEABI_V7A true )
- set( ANDROID_NDK_ABI_NAME "armeabi-v7a" )
- set( ANDROID_ARCH_NAME "arm" )
- set( ANDROID_LLVM_TRIPLE "armv7-none-linux-androideabi" )
- set( CMAKE_SYSTEM_PROCESSOR "armv7-a" )
- set( VFPV3 true )
- set( NEON true )
-else()
- message( SEND_ERROR "Unknown ANDROID_ABI=\"${ANDROID_ABI}\" is specified." )
-endif()
-
-if( CMAKE_BINARY_DIR AND EXISTS "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeSystem.cmake" )
- # really dirty hack
- # it is not possible to change CMAKE_SYSTEM_PROCESSOR after the first run...
- file( APPEND "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeSystem.cmake" "SET(CMAKE_SYSTEM_PROCESSOR \"${CMAKE_SYSTEM_PROCESSOR}\")\n" )
-endif()
-
-if( ANDROID_ARCH_NAME STREQUAL "arm" AND NOT ARMEABI_V6 )
- __INIT_VARIABLE( ANDROID_FORCE_ARM_BUILD VALUES OFF )
- set( ANDROID_FORCE_ARM_BUILD ${ANDROID_FORCE_ARM_BUILD} CACHE BOOL "Use 32-bit ARM instructions instead of Thumb-1" FORCE )
- mark_as_advanced( ANDROID_FORCE_ARM_BUILD )
-else()
- unset( ANDROID_FORCE_ARM_BUILD CACHE )
-endif()
-
-# choose toolchain
-if( ANDROID_TOOLCHAIN_NAME )
- list( FIND __availableToolchains "${ANDROID_TOOLCHAIN_NAME}" __toolchainIdx )
- if( __toolchainIdx EQUAL -1 )
- list( SORT __availableToolchains )
- string( REPLACE ";" "\n * " toolchains_list "${__availableToolchains}" )
- set( toolchains_list " * ${toolchains_list}")
- message( FATAL_ERROR "Specified toolchain \"${ANDROID_TOOLCHAIN_NAME}\" is missing in your NDK or broken. Please verify that your NDK is working or select another compiler toolchain.
-To configure the toolchain set CMake variable ANDROID_TOOLCHAIN_NAME to one of the following values:\n${toolchains_list}\n" )
- endif()
- list( GET __availableToolchainArchs ${__toolchainIdx} __toolchainArch )
- if( NOT __toolchainArch STREQUAL ANDROID_ARCH_NAME )
- message( SEND_ERROR "Selected toolchain \"${ANDROID_TOOLCHAIN_NAME}\" is not able to compile binaries for the \"${ANDROID_ARCH_NAME}\" platform." )
- endif()
-else()
- set( __toolchainIdx -1 )
- set( __applicableToolchains "" )
- set( __toolchainMaxVersion "0.0.0" )
- list( LENGTH __availableToolchains __availableToolchainsCount )
- math( EXPR __availableToolchainsCount "${__availableToolchainsCount}-1" )
- foreach( __idx RANGE ${__availableToolchainsCount} )
- list( GET __availableToolchainArchs ${__idx} __toolchainArch )
- if( __toolchainArch STREQUAL ANDROID_ARCH_NAME )
- list( GET __availableToolchainCompilerVersions ${__idx} __toolchainVersion )
- string( REPLACE "x" "99" __toolchainVersion "${__toolchainVersion}")
- if( __toolchainVersion VERSION_GREATER __toolchainMaxVersion )
- set( __toolchainMaxVersion "${__toolchainVersion}" )
- set( __toolchainIdx ${__idx} )
- endif()
- endif()
- endforeach()
- unset( __availableToolchainsCount )
- unset( __toolchainMaxVersion )
- unset( __toolchainVersion )
-endif()
-unset( __toolchainArch )
-if( __toolchainIdx EQUAL -1 )
- message( FATAL_ERROR "No one of available compiler toolchains is able to compile for ${ANDROID_ARCH_NAME} platform." )
-endif()
-list( GET __availableToolchains ${__toolchainIdx} ANDROID_TOOLCHAIN_NAME )
-list( GET __availableToolchainMachines ${__toolchainIdx} ANDROID_TOOLCHAIN_MACHINE_NAME )
-list( GET __availableToolchainCompilerVersions ${__toolchainIdx} ANDROID_COMPILER_VERSION )
-
-unset( __toolchainIdx )
-unset( __availableToolchains )
-unset( __availableToolchainMachines )
-unset( __availableToolchainArchs )
-unset( __availableToolchainCompilerVersions )
-
-# choose native API level
-__INIT_VARIABLE( ANDROID_NATIVE_API_LEVEL ENV_ANDROID_NATIVE_API_LEVEL ANDROID_API_LEVEL ENV_ANDROID_API_LEVEL ANDROID_STANDALONE_TOOLCHAIN_API_LEVEL ANDROID_DEFAULT_NDK_API_LEVEL_${ANDROID_ARCH_NAME} ANDROID_DEFAULT_NDK_API_LEVEL )
-string( REPLACE "android-" "" ANDROID_NATIVE_API_LEVEL "${ANDROID_NATIVE_API_LEVEL}" )
-string( STRIP "${ANDROID_NATIVE_API_LEVEL}" ANDROID_NATIVE_API_LEVEL )
-# adjust API level
-set( __real_api_level ${ANDROID_DEFAULT_NDK_API_LEVEL_${ANDROID_ARCH_NAME}} )
-foreach( __level ${ANDROID_SUPPORTED_NATIVE_API_LEVELS} )
- if( (__level LESS ANDROID_NATIVE_API_LEVEL OR __level STREQUAL ANDROID_NATIVE_API_LEVEL) AND NOT __level LESS __real_api_level )
- set( __real_api_level ${__level} )
- endif()
-endforeach()
-if( __real_api_level AND NOT ANDROID_NATIVE_API_LEVEL STREQUAL __real_api_level )
- message( STATUS "Adjusting Android API level 'android-${ANDROID_NATIVE_API_LEVEL}' to 'android-${__real_api_level}'")
- set( ANDROID_NATIVE_API_LEVEL ${__real_api_level} )
-endif()
-unset(__real_api_level)
-# validate
-list( FIND ANDROID_SUPPORTED_NATIVE_API_LEVELS "${ANDROID_NATIVE_API_LEVEL}" __levelIdx )
-if( __levelIdx EQUAL -1 )
- message( SEND_ERROR "Specified Android native API level 'android-${ANDROID_NATIVE_API_LEVEL}' is not supported by your NDK/toolchain." )
-else()
- if( BUILD_WITH_ANDROID_NDK )
- __DETECT_NATIVE_API_LEVEL( __realApiLevel "${ANDROID_NDK}/platforms/android-${ANDROID_NATIVE_API_LEVEL}/arch-${ANDROID_ARCH_NAME}/usr/include/android/api-level.h" )
- if( NOT __realApiLevel EQUAL ANDROID_NATIVE_API_LEVEL AND NOT __realApiLevel GREATER 9000 )
- message( SEND_ERROR "Specified Android API level (${ANDROID_NATIVE_API_LEVEL}) does not match to the level found (${__realApiLevel}). Probably your copy of NDK is broken." )
- endif()
- unset( __realApiLevel )
- endif()
- set( ANDROID_NATIVE_API_LEVEL "${ANDROID_NATIVE_API_LEVEL}" CACHE STRING "Android API level for native code" FORCE )
- set( CMAKE_ANDROID_API ${ANDROID_NATIVE_API_LEVEL} )
- if( CMAKE_VERSION VERSION_GREATER "2.8" )
- list( SORT ANDROID_SUPPORTED_NATIVE_API_LEVELS )
- set_property( CACHE ANDROID_NATIVE_API_LEVEL PROPERTY STRINGS ${ANDROID_SUPPORTED_NATIVE_API_LEVELS} )
- endif()
-endif()
-unset( __levelIdx )
-
-
-# remember target ABI
-set( ANDROID_ABI "${ANDROID_ABI}" CACHE STRING "The target ABI for Android. If arm, then armeabi-v7a is recommended for hardware floating point." FORCE )
-if( CMAKE_VERSION VERSION_GREATER "2.8" )
- list( SORT ANDROID_SUPPORTED_ABIS_${ANDROID_ARCH_NAME} )
- set_property( CACHE ANDROID_ABI PROPERTY STRINGS ${ANDROID_SUPPORTED_ABIS_${ANDROID_ARCH_NAME}} )
-endif()
-
-
-# runtime choice (STL, rtti, exceptions)
-if( NOT ANDROID_STL )
- set( ANDROID_STL gnustl_static )
-endif()
-set( ANDROID_STL "${ANDROID_STL}" CACHE STRING "C++ runtime" )
-set( ANDROID_STL_FORCE_FEATURES ON CACHE BOOL "automatically configure rtti and exceptions support based on C++ runtime" )
-mark_as_advanced( ANDROID_STL ANDROID_STL_FORCE_FEATURES )
-
-if( BUILD_WITH_ANDROID_NDK )
- if( NOT "${ANDROID_STL}" MATCHES "^(none|system|system_re|gabi\\+\\+_static|gabi\\+\\+_shared|stlport_static|stlport_shared|gnustl_static|gnustl_shared|c\\+\\+_static|c\\+\\+_shared)$")
- message( FATAL_ERROR "ANDROID_STL is set to invalid value \"${ANDROID_STL}\".
-The possible values are:
- none -> Do not configure the runtime.
- system -> Use the default minimal system C++ runtime library.
- system_re -> Same as system but with rtti and exceptions.
- gabi++_static -> Use the GAbi++ runtime as a static library.
- gabi++_shared -> Use the GAbi++ runtime as a shared library.
- stlport_static -> Use the STLport runtime as a static library.
- stlport_shared -> Use the STLport runtime as a shared library.
- gnustl_static -> (default) Use the GNU STL as a static library.
- gnustl_shared -> Use the GNU STL as a shared library.
- c++_static -> Use the LLVM libc++ runtime as a static library.
- c++_shared -> Use the LLVM libc++ runtime as a shared library.
-" )
- endif()
-elseif( BUILD_WITH_STANDALONE_TOOLCHAIN )
- if( NOT "${ANDROID_STL}" MATCHES "^(none|gnustl_static|gnustl_shared)$")
- message( FATAL_ERROR "ANDROID_STL is set to invalid value \"${ANDROID_STL}\".
-The possible values are:
- none -> Do not configure the runtime.
- gnustl_static -> (default) Use the GNU STL as a static library.
- gnustl_shared -> Use the GNU STL as a shared library.
-" )
- endif()
-endif()
-
-unset( ANDROID_RTTI )
-unset( ANDROID_EXCEPTIONS )
-unset( ANDROID_STL_INCLUDE_DIRS )
-unset( __libstl )
-unset( __libsupcxx )
-
-if( NOT _CMAKE_IN_TRY_COMPILE AND ANDROID_NDK_RELEASE STREQUAL "r7b" AND ARMEABI_V7A AND NOT VFPV3 AND ANDROID_STL MATCHES "gnustl" )
- message( WARNING "The GNU STL armeabi-v7a binaries from NDK r7b can crash non-NEON devices. The files provided with NDK r7b were not configured properly, resulting in crashes on Tegra2-based devices and others when trying to use certain floating-point functions (e.g., cosf, sinf, expf).
-You are strongly recommended to switch to another NDK release.
-" )
-endif()
-
-if( NOT _CMAKE_IN_TRY_COMPILE AND X86 AND ANDROID_STL MATCHES "gnustl" AND ANDROID_NDK_RELEASE STREQUAL "r6" )
- message( WARNING "The x86 system header file from NDK r6 has incorrect definition for ptrdiff_t. You are recommended to upgrade to a newer NDK release or manually patch the header:
-See https://android.googlesource.com/platform/development.git f907f4f9d4e56ccc8093df6fee54454b8bcab6c2
- diff --git a/ndk/platforms/android-9/arch-x86/include/machine/_types.h b/ndk/platforms/android-9/arch-x86/include/machine/_types.h
- index 5e28c64..65892a1 100644
- --- a/ndk/platforms/android-9/arch-x86/include/machine/_types.h
- +++ b/ndk/platforms/android-9/arch-x86/include/machine/_types.h
- @@ -51,7 +51,11 @@ typedef long int ssize_t;
- #endif
- #ifndef _PTRDIFF_T
- #define _PTRDIFF_T
- -typedef long ptrdiff_t;
- +# ifdef __ANDROID__
- + typedef int ptrdiff_t;
- +# else
- + typedef long ptrdiff_t;
- +# endif
- #endif
-" )
-endif()
-
-
-# setup paths and STL for standalone toolchain
-if( BUILD_WITH_STANDALONE_TOOLCHAIN )
- set( ANDROID_TOOLCHAIN_ROOT "${ANDROID_STANDALONE_TOOLCHAIN}" )
- set( ANDROID_CLANG_TOOLCHAIN_ROOT "${ANDROID_STANDALONE_TOOLCHAIN}" )
- set( ANDROID_SYSROOT "${ANDROID_STANDALONE_TOOLCHAIN}/sysroot" )
-
- if( NOT ANDROID_STL STREQUAL "none" )
- set( ANDROID_STL_INCLUDE_DIRS "${ANDROID_STANDALONE_TOOLCHAIN}/include/c++/${ANDROID_COMPILER_VERSION}" )
- if( NOT EXISTS "${ANDROID_STL_INCLUDE_DIRS}" )
- # old location ( pre r8c )
- set( ANDROID_STL_INCLUDE_DIRS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/include/c++/${ANDROID_COMPILER_VERSION}" )
- endif()
- if( ARMEABI_V7A AND EXISTS "${ANDROID_STL_INCLUDE_DIRS}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/${CMAKE_SYSTEM_PROCESSOR}/bits" )
- list( APPEND ANDROID_STL_INCLUDE_DIRS "${ANDROID_STL_INCLUDE_DIRS}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/${CMAKE_SYSTEM_PROCESSOR}" )
- elseif( ARMEABI AND NOT ANDROID_FORCE_ARM_BUILD AND EXISTS "${ANDROID_STL_INCLUDE_DIRS}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/thumb/bits" )
- list( APPEND ANDROID_STL_INCLUDE_DIRS "${ANDROID_STL_INCLUDE_DIRS}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/thumb" )
- else()
- list( APPEND ANDROID_STL_INCLUDE_DIRS "${ANDROID_STL_INCLUDE_DIRS}/${ANDROID_TOOLCHAIN_MACHINE_NAME}" )
- endif()
- # always search static GNU STL to get the location of libsupc++.a
- if( ARMEABI_V7A AND NOT ANDROID_FORCE_ARM_BUILD AND EXISTS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/thumb/libstdc++.a" )
- set( __libstl "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/thumb" )
- elseif( ARMEABI_V7A AND EXISTS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/libstdc++.a" )
- set( __libstl "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}" )
- elseif( ARMEABI AND NOT ANDROID_FORCE_ARM_BUILD AND EXISTS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/thumb/libstdc++.a" )
- set( __libstl "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/thumb" )
- elseif( EXISTS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/libstdc++.a" )
- set( __libstl "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib" )
- endif()
- if( __libstl )
- set( __libsupcxx "${__libstl}/libsupc++.a" )
- set( __libstl "${__libstl}/libstdc++.a" )
- endif()
- if( NOT EXISTS "${__libsupcxx}" )
- message( FATAL_ERROR "The required libstdsupc++.a is missing in your standalone toolchain.
- Usually it happens because of bug in make-standalone-toolchain.sh script from NDK r7, r7b and r7c.
- You need to either upgrade to newer NDK or manually copy
- $ANDROID_NDK/sources/cxx-stl/gnu-libstdc++/libs/${ANDROID_NDK_ABI_NAME}/libsupc++.a
- to
- ${__libsupcxx}
- " )
- endif()
- if( ANDROID_STL STREQUAL "gnustl_shared" )
- if( ARMEABI_V7A AND EXISTS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/libgnustl_shared.so" )
- set( __libstl "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/libgnustl_shared.so" )
- elseif( ARMEABI AND NOT ANDROID_FORCE_ARM_BUILD AND EXISTS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/thumb/libgnustl_shared.so" )
- set( __libstl "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/thumb/libgnustl_shared.so" )
- elseif( EXISTS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/libgnustl_shared.so" )
- set( __libstl "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/libgnustl_shared.so" )
- endif()
- endif()
- endif()
-endif()
-
-# clang
-if( "${ANDROID_TOOLCHAIN_NAME}" STREQUAL "standalone-clang" )
- set( ANDROID_COMPILER_IS_CLANG 1 )
- execute_process( COMMAND "${ANDROID_CLANG_TOOLCHAIN_ROOT}/bin/clang${TOOL_OS_SUFFIX}" --version OUTPUT_VARIABLE ANDROID_CLANG_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE )
- string( REGEX MATCH "[0-9]+[.][0-9]+" ANDROID_CLANG_VERSION "${ANDROID_CLANG_VERSION}")
-elseif( "${ANDROID_TOOLCHAIN_NAME}" MATCHES "-clang3[.][0-9]?$" )
- string( REGEX MATCH "3[.][0-9]$" ANDROID_CLANG_VERSION "${ANDROID_TOOLCHAIN_NAME}")
- string( REGEX REPLACE "-clang${ANDROID_CLANG_VERSION}$" "-${ANDROID_COMPILER_VERSION}" ANDROID_GCC_TOOLCHAIN_NAME "${ANDROID_TOOLCHAIN_NAME}" )
- if( NOT EXISTS "${ANDROID_NDK_TOOLCHAINS_PATH}/llvm-${ANDROID_CLANG_VERSION}${ANDROID_NDK_TOOLCHAINS_SUBPATH}/bin/clang${TOOL_OS_SUFFIX}" )
- message( FATAL_ERROR "Could not find the Clang compiler driver" )
- endif()
- set( ANDROID_COMPILER_IS_CLANG 1 )
- set( ANDROID_CLANG_TOOLCHAIN_ROOT "${ANDROID_NDK_TOOLCHAINS_PATH}/llvm-${ANDROID_CLANG_VERSION}${ANDROID_NDK_TOOLCHAINS_SUBPATH}" )
-else()
- set( ANDROID_GCC_TOOLCHAIN_NAME "${ANDROID_TOOLCHAIN_NAME}" )
- unset( ANDROID_COMPILER_IS_CLANG CACHE )
-endif()
-
-string( REPLACE "." "" _clang_name "clang${ANDROID_CLANG_VERSION}" )
-if( NOT EXISTS "${ANDROID_CLANG_TOOLCHAIN_ROOT}/bin/${_clang_name}${TOOL_OS_SUFFIX}" )
- set( _clang_name "clang" )
-endif()
-
-
-# setup paths and STL for NDK
-if( BUILD_WITH_ANDROID_NDK )
- set( ANDROID_TOOLCHAIN_ROOT "${ANDROID_NDK_TOOLCHAINS_PATH}/${ANDROID_GCC_TOOLCHAIN_NAME}${ANDROID_NDK_TOOLCHAINS_SUBPATH}" )
- set( ANDROID_SYSROOT "${ANDROID_NDK}/platforms/android-${ANDROID_NATIVE_API_LEVEL}/arch-${ANDROID_ARCH_NAME}" )
-
- if( ANDROID_STL STREQUAL "none" )
- # do nothing
- elseif( ANDROID_STL STREQUAL "system" )
- set( ANDROID_RTTI OFF )
- set( ANDROID_EXCEPTIONS OFF )
- set( ANDROID_STL_INCLUDE_DIRS "${ANDROID_NDK}/sources/cxx-stl/system/include" )
- elseif( ANDROID_STL STREQUAL "system_re" )
- set( ANDROID_RTTI ON )
- set( ANDROID_EXCEPTIONS ON )
- set( ANDROID_STL_INCLUDE_DIRS "${ANDROID_NDK}/sources/cxx-stl/system/include" )
- elseif( ANDROID_STL MATCHES "gabi" )
- if( ANDROID_NDK_RELEASE_NUM LESS 7000 ) # before r7
- message( FATAL_ERROR "gabi++ is not available in your NDK. You have to upgrade to NDK r7 or newer to use gabi++.")
- endif()
- set( ANDROID_RTTI ON )
- set( ANDROID_EXCEPTIONS OFF )
- set( ANDROID_STL_INCLUDE_DIRS "${ANDROID_NDK}/sources/cxx-stl/gabi++/include" )
- set( __libstl "${ANDROID_NDK}/sources/cxx-stl/gabi++/libs/${ANDROID_NDK_ABI_NAME}/libgabi++_static.a" )
- elseif( ANDROID_STL MATCHES "stlport" )
- if( NOT ANDROID_NDK_RELEASE_NUM LESS 8004 ) # before r8d
- set( ANDROID_EXCEPTIONS ON )
- else()
- set( ANDROID_EXCEPTIONS OFF )
- endif()
- if( ANDROID_NDK_RELEASE_NUM LESS 7000 ) # before r7
- set( ANDROID_RTTI OFF )
- else()
- set( ANDROID_RTTI ON )
- endif()
- set( ANDROID_STL_INCLUDE_DIRS "${ANDROID_NDK}/sources/cxx-stl/stlport/stlport" )
- set( __libstl "${ANDROID_NDK}/sources/cxx-stl/stlport/libs/${ANDROID_NDK_ABI_NAME}/libstlport_static.a" )
- elseif( ANDROID_STL MATCHES "gnustl" )
- set( ANDROID_EXCEPTIONS ON )
- set( ANDROID_RTTI ON )
- if( EXISTS "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/${ANDROID_COMPILER_VERSION}" )
- if( ARMEABI_V7A AND ANDROID_COMPILER_VERSION VERSION_EQUAL "4.7" AND ANDROID_NDK_RELEASE STREQUAL "r8d" )
- # gnustl binary for 4.7 compiler is buggy :(
- # TODO: look for right fix
- set( __libstl "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/4.6" )
- else()
- set( __libstl "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/${ANDROID_COMPILER_VERSION}" )
- endif()
- else()
- set( __libstl "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++" )
- endif()
- set( ANDROID_STL_INCLUDE_DIRS "${__libstl}/include" "${__libstl}/libs/${ANDROID_NDK_ABI_NAME}/include" "${__libstl}/include/backward" )
- if( EXISTS "${__libstl}/libs/${ANDROID_NDK_ABI_NAME}/libgnustl_static.a" )
- set( __libstl "${__libstl}/libs/${ANDROID_NDK_ABI_NAME}/libgnustl_static.a" )
- else()
- set( __libstl "${__libstl}/libs/${ANDROID_NDK_ABI_NAME}/libstdc++.a" )
- endif()
- elseif( ANDROID_STL MATCHES "c\\+\\+_shared" OR ANDROID_STL MATCHES "c\\+\\+_static" )
- set( ANDROID_EXCEPTIONS ON )
- set( ANDROID_RTTI ON )
- set( ANDROID_CXX_ROOT "${ANDROID_NDK}/sources/cxx-stl/" )
- set( ANDROID_LLVM_ROOT "${ANDROID_CXX_ROOT}/llvm-libc++" )
-
- if( X86 )
- set( ANDROID_ABI_INCLUDE_DIRS "${ANDROID_CXX_ROOT}/gabi++/include" )
- else()
- set( ANDROID_ABI_INCLUDE_DIRS "${ANDROID_CXX_ROOT}/llvm-libc++abi/include" )
- endif()
-
- set( ANDROID_STL_INCLUDE_DIRS "${ANDROID_LLVM_ROOT}/libcxx/include" "${ANDROID_ABI_INCLUDE_DIRS}" )
-
- # android support sfiles
- include_directories ( SYSTEM ${ANDROID_NDK}/sources/android/support/include )
-
- if(ANDROID_STL MATCHES "c\\+\\+_shared")
- set ( LLVM_LIBRARY_NAME "libc++_shared.so")
- else()
- set ( LLVM_LIBRARY_NAME "libc++_static.a" )
- endif ()
-
- if( EXISTS "${ANDROID_LLVM_ROOT}/libs/${ANDROID_NDK_ABI_NAME}/${LLVM_LIBRARY_NAME}" )
- set( __libstl "${ANDROID_LLVM_ROOT}/libs/${ANDROID_NDK_ABI_NAME}/${LLVM_LIBRARY_NAME}" )
- else()
- message( FATAL_ERROR "Could not find libc++ library" )
- endif()
- else()
- message( FATAL_ERROR "Unknown runtime: ${ANDROID_STL}" )
- endif()
- # find libsupc++.a - rtti & exceptions
- if( ANDROID_STL STREQUAL "system_re" OR ANDROID_STL MATCHES "gnustl" )
- set( __libsupcxx "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/${ANDROID_COMPILER_VERSION}/libs/${ANDROID_NDK_ABI_NAME}/libsupc++.a" ) # r8b or newer
- if( NOT EXISTS "${__libsupcxx}" )
- set( __libsupcxx "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/libs/${ANDROID_NDK_ABI_NAME}/libsupc++.a" ) # r7-r8
- endif()
- if( NOT EXISTS "${__libsupcxx}" ) # before r7
- if( ARMEABI_V7A )
- if( ANDROID_FORCE_ARM_BUILD )
- set( __libsupcxx "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/libsupc++.a" )
- else()
- set( __libsupcxx "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/thumb/libsupc++.a" )
- endif()
- elseif( ARMEABI AND NOT ANDROID_FORCE_ARM_BUILD )
- set( __libsupcxx "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/thumb/libsupc++.a" )
- else()
- set( __libsupcxx "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/libsupc++.a" )
- endif()
- endif()
- if( NOT EXISTS "${__libsupcxx}")
- message( ERROR "Could not find libsupc++.a for a chosen platform. Either your NDK is not supported or is broken.")
- endif()
- endif()
-endif()
-
-
-# case of shared STL linkage
-if( ANDROID_STL MATCHES "shared" AND DEFINED __libstl )
- string( REPLACE "_static.a" "_shared.so" __libstl "${__libstl}" )
- # TODO: check if .so file exists before the renaming
-endif()
-
-
-# ccache support
-__INIT_VARIABLE( _ndk_ccache NDK_CCACHE ENV_NDK_CCACHE )
-if( _ndk_ccache )
- if( DEFINED NDK_CCACHE AND NOT EXISTS NDK_CCACHE )
- unset( NDK_CCACHE CACHE )
- endif()
- find_program( NDK_CCACHE "${_ndk_ccache}" DOC "The path to ccache binary")
-else()
- unset( NDK_CCACHE CACHE )
-endif()
-unset( _ndk_ccache )
-
-
-# setup the cross-compiler
-if( NOT CMAKE_C_COMPILER )
- if( NDK_CCACHE AND NOT ANDROID_SYSROOT MATCHES "[ ;\"]" )
- set( CMAKE_C_COMPILER "${NDK_CCACHE}" CACHE PATH "ccache as C compiler" )
- set( CMAKE_CXX_COMPILER "${NDK_CCACHE}" CACHE PATH "ccache as C++ compiler" )
- if( ANDROID_COMPILER_IS_CLANG )
- set( CMAKE_C_COMPILER_ARG1 "${ANDROID_CLANG_TOOLCHAIN_ROOT}/bin/${_clang_name}${TOOL_OS_SUFFIX}" CACHE PATH "C compiler")
- set( CMAKE_CXX_COMPILER_ARG1 "${ANDROID_CLANG_TOOLCHAIN_ROOT}/bin/${_clang_name}++${TOOL_OS_SUFFIX}" CACHE PATH "C++ compiler")
- else()
- set( CMAKE_C_COMPILER_ARG1 "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-gcc${TOOL_OS_SUFFIX}" CACHE PATH "C compiler")
- set( CMAKE_CXX_COMPILER_ARG1 "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-g++${TOOL_OS_SUFFIX}" CACHE PATH "C++ compiler")
- endif()
- else()
- if( ANDROID_COMPILER_IS_CLANG )
- set( CMAKE_C_COMPILER "${ANDROID_CLANG_TOOLCHAIN_ROOT}/bin/${_clang_name}${TOOL_OS_SUFFIX}" CACHE PATH "C compiler")
- set( CMAKE_CXX_COMPILER "${ANDROID_CLANG_TOOLCHAIN_ROOT}/bin/${_clang_name}++${TOOL_OS_SUFFIX}" CACHE PATH "C++ compiler")
- else()
- set( CMAKE_C_COMPILER "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-gcc${TOOL_OS_SUFFIX}" CACHE PATH "C compiler" )
- set( CMAKE_CXX_COMPILER "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-g++${TOOL_OS_SUFFIX}" CACHE PATH "C++ compiler" )
- endif()
- endif()
- set( CMAKE_ASM_COMPILER "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-gcc${TOOL_OS_SUFFIX}" CACHE PATH "assembler" )
- set( CMAKE_STRIP "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-strip${TOOL_OS_SUFFIX}" CACHE PATH "strip" )
- if( EXISTS "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-gcc-ar${TOOL_OS_SUFFIX}" )
- # Use gcc-ar if we have it for better LTO support.
- set( CMAKE_AR "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-gcc-ar${TOOL_OS_SUFFIX}" CACHE PATH "archive" )
- else()
- set( CMAKE_AR "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-ar${TOOL_OS_SUFFIX}" CACHE PATH "archive" )
- endif()
- set( CMAKE_LINKER "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-ld${TOOL_OS_SUFFIX}" CACHE PATH "linker" )
- set( CMAKE_NM "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-nm${TOOL_OS_SUFFIX}" CACHE PATH "nm" )
- set( CMAKE_OBJCOPY "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-objcopy${TOOL_OS_SUFFIX}" CACHE PATH "objcopy" )
- set( CMAKE_OBJDUMP "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-objdump${TOOL_OS_SUFFIX}" CACHE PATH "objdump" )
- set( CMAKE_RANLIB "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-ranlib${TOOL_OS_SUFFIX}" CACHE PATH "ranlib" )
-endif()
-
-set( _CMAKE_TOOLCHAIN_PREFIX "${ANDROID_TOOLCHAIN_MACHINE_NAME}-" )
-if( CMAKE_VERSION VERSION_LESS 2.8.5 )
- set( CMAKE_ASM_COMPILER_ARG1 "-c" )
-endif()
-if( APPLE )
- find_program( CMAKE_INSTALL_NAME_TOOL NAMES install_name_tool )
- if( NOT CMAKE_INSTALL_NAME_TOOL )
- message( FATAL_ERROR "Could not find install_name_tool, please check your installation." )
- endif()
- mark_as_advanced( CMAKE_INSTALL_NAME_TOOL )
-endif()
-
-# Force set compilers because standard identification works badly for us
-include( CMakeForceCompiler )
-CMAKE_FORCE_C_COMPILER( "${CMAKE_C_COMPILER}" GNU )
-if( ANDROID_COMPILER_IS_CLANG )
- set( CMAKE_C_COMPILER_ID Clang )
-endif()
-set( CMAKE_C_PLATFORM_ID Linux )
-if( X86_64 OR MIPS64 OR ARM64_V8A )
- set( CMAKE_C_SIZEOF_DATA_PTR 8 )
-else()
- set( CMAKE_C_SIZEOF_DATA_PTR 4 )
-endif()
-set( CMAKE_C_HAS_ISYSROOT 1 )
-set( CMAKE_C_COMPILER_ABI ELF )
-CMAKE_FORCE_CXX_COMPILER( "${CMAKE_CXX_COMPILER}" GNU )
-if( ANDROID_COMPILER_IS_CLANG )
- set( CMAKE_CXX_COMPILER_ID Clang)
-endif()
-set( CMAKE_CXX_PLATFORM_ID Linux )
-set( CMAKE_CXX_SIZEOF_DATA_PTR ${CMAKE_C_SIZEOF_DATA_PTR} )
-set( CMAKE_CXX_HAS_ISYSROOT 1 )
-set( CMAKE_CXX_COMPILER_ABI ELF )
-set( CMAKE_CXX_SOURCE_FILE_EXTENSIONS cc cp cxx cpp CPP c++ C )
-# force ASM compiler (required for CMake < 2.8.5)
-set( CMAKE_ASM_COMPILER_ID_RUN TRUE )
-set( CMAKE_ASM_COMPILER_ID GNU )
-set( CMAKE_ASM_COMPILER_WORKS TRUE )
-set( CMAKE_ASM_COMPILER_FORCED TRUE )
-set( CMAKE_COMPILER_IS_GNUASM 1)
-set( CMAKE_ASM_SOURCE_FILE_EXTENSIONS s S asm )
-
-foreach( lang C CXX ASM )
- if( ANDROID_COMPILER_IS_CLANG )
- set( CMAKE_${lang}_COMPILER_VERSION ${ANDROID_CLANG_VERSION} )
- else()
- set( CMAKE_${lang}_COMPILER_VERSION ${ANDROID_COMPILER_VERSION} )
- endif()
-endforeach()
-
-# flags and definitions
-remove_definitions( -DANDROID )
-add_definitions( -DANDROID )
-
-if( ANDROID_SYSROOT MATCHES "[ ;\"]" )
- if( CMAKE_HOST_WIN32 )
- # try to convert path to 8.3 form
- file( WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/cvt83.cmd" "@echo %~s1" )
- execute_process( COMMAND "$ENV{ComSpec}" /c "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/cvt83.cmd" "${ANDROID_SYSROOT}"
- OUTPUT_VARIABLE __path OUTPUT_STRIP_TRAILING_WHITESPACE
- RESULT_VARIABLE __result ERROR_QUIET )
- if( __result EQUAL 0 )
- file( TO_CMAKE_PATH "${__path}" ANDROID_SYSROOT )
- set( ANDROID_CXX_FLAGS "--sysroot=${ANDROID_SYSROOT}" )
- else()
- set( ANDROID_CXX_FLAGS "--sysroot=\"${ANDROID_SYSROOT}\"" )
- endif()
- else()
- set( ANDROID_CXX_FLAGS "'--sysroot=${ANDROID_SYSROOT}'" )
- endif()
- if( NOT _CMAKE_IN_TRY_COMPILE )
- # quotes can break try_compile and compiler identification
- message(WARNING "Path to your Android NDK (or toolchain) has non-alphanumeric symbols.\nThe build might be broken.\n")
- endif()
-else()
- set( ANDROID_CXX_FLAGS "--sysroot=${ANDROID_SYSROOT}" )
-endif()
-
-# NDK flags
-if (ARM64_V8A )
- set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -funwind-tables" )
- set( ANDROID_CXX_FLAGS_RELEASE "-fomit-frame-pointer -fstrict-aliasing" )
- set( ANDROID_CXX_FLAGS_DEBUG "-fno-omit-frame-pointer -fno-strict-aliasing" )
- if( NOT ANDROID_COMPILER_IS_CLANG )
- set( ANDROID_CXX_FLAGS_RELEASE "${ANDROID_CXX_FLAGS_RELEASE} -funswitch-loops -finline-limit=300" )
- endif()
-elseif( ARMEABI OR ARMEABI_V7A)
- set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -funwind-tables" )
- if( NOT ANDROID_FORCE_ARM_BUILD AND NOT ARMEABI_V6 )
- set( ANDROID_CXX_FLAGS_RELEASE "-mthumb -fomit-frame-pointer -fno-strict-aliasing" )
- set( ANDROID_CXX_FLAGS_DEBUG "-marm -fno-omit-frame-pointer -fno-strict-aliasing" )
- if( NOT ANDROID_COMPILER_IS_CLANG )
- set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -finline-limit=64" )
- endif()
- else()
- # always compile ARMEABI_V6 in arm mode; otherwise there is no difference from ARMEABI
- set( ANDROID_CXX_FLAGS_RELEASE "-marm -fomit-frame-pointer -fstrict-aliasing" )
- set( ANDROID_CXX_FLAGS_DEBUG "-marm -fno-omit-frame-pointer -fno-strict-aliasing" )
- if( NOT ANDROID_COMPILER_IS_CLANG )
- set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -funswitch-loops -finline-limit=300" )
- endif()
- endif()
-elseif( X86 OR X86_64 )
- set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -funwind-tables" )
- if( NOT ANDROID_COMPILER_IS_CLANG )
- set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -funswitch-loops -finline-limit=300" )
- endif()
- set( ANDROID_CXX_FLAGS_RELEASE "-fomit-frame-pointer -fstrict-aliasing" )
- set( ANDROID_CXX_FLAGS_DEBUG "-fno-omit-frame-pointer -fno-strict-aliasing" )
-elseif( MIPS OR MIPS64 )
- set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -fno-strict-aliasing -finline-functions -funwind-tables -fmessage-length=0" )
- set( ANDROID_CXX_FLAGS_RELEASE "-fomit-frame-pointer" )
- set( ANDROID_CXX_FLAGS_DEBUG "-fno-omit-frame-pointer" )
- if( NOT ANDROID_COMPILER_IS_CLANG )
- set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -fno-inline-functions-called-once -fgcse-after-reload -frerun-cse-after-loop -frename-registers" )
- set( ANDROID_CXX_FLAGS_RELEASE "${ANDROID_CXX_FLAGS_RELEASE} -funswitch-loops -finline-limit=300" )
- endif()
-elseif()
- set( ANDROID_CXX_FLAGS_RELEASE "" )
- set( ANDROID_CXX_FLAGS_DEBUG "" )
-endif()
-
-set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -fsigned-char" ) # good/necessary when porting desktop libraries
-
-if( NOT X86 AND NOT ANDROID_COMPILER_IS_CLANG )
- set( ANDROID_CXX_FLAGS "-Wno-psabi ${ANDROID_CXX_FLAGS}" )
-endif()
-
-if( NOT ANDROID_COMPILER_VERSION VERSION_LESS "4.6" )
- set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -no-canonical-prefixes" ) # see https://android-review.googlesource.com/#/c/47564/
-endif()
-
-# ABI-specific flags
-if( ARMEABI_V7A )
- set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -march=armv7-a -mfloat-abi=softfp" )
- if( NEON )
- set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -mfpu=neon" )
- elseif( VFPV3 )
- set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -mfpu=vfpv3" )
- else()
- set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -mfpu=vfpv3-d16" )
- endif()
-elseif( ARMEABI_V6 )
- set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -march=armv6 -mfloat-abi=softfp -mfpu=vfp" ) # vfp == vfpv2
-elseif( ARMEABI )
- set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -march=armv5te -mtune=xscale -msoft-float" )
-endif()
-
-if( ANDROID_STL MATCHES "gnustl" AND (EXISTS "${__libstl}" OR EXISTS "${__libsupcxx}") )
- set( CMAKE_CXX_CREATE_SHARED_LIBRARY " -o " )
- set( CMAKE_CXX_CREATE_SHARED_MODULE " -o " )
- set( CMAKE_CXX_LINK_EXECUTABLE " -o " )
-else()
- set( CMAKE_CXX_CREATE_SHARED_LIBRARY " -o " )
- set( CMAKE_CXX_CREATE_SHARED_MODULE " -o " )
- set( CMAKE_CXX_LINK_EXECUTABLE " -o " )
-endif()
-
-# STL
-if( EXISTS "${__libstl}" OR EXISTS "${__libsupcxx}" )
- if( EXISTS "${__libstl}" )
- set( CMAKE_CXX_CREATE_SHARED_LIBRARY "${CMAKE_CXX_CREATE_SHARED_LIBRARY} \"${__libstl}\"" )
- set( CMAKE_CXX_CREATE_SHARED_MODULE "${CMAKE_CXX_CREATE_SHARED_MODULE} \"${__libstl}\"" )
- set( CMAKE_CXX_LINK_EXECUTABLE "${CMAKE_CXX_LINK_EXECUTABLE} \"${__libstl}\"" )
- endif()
- if( EXISTS "${__libsupcxx}" )
- set( CMAKE_CXX_CREATE_SHARED_LIBRARY "${CMAKE_CXX_CREATE_SHARED_LIBRARY} \"${__libsupcxx}\"" )
- set( CMAKE_CXX_CREATE_SHARED_MODULE "${CMAKE_CXX_CREATE_SHARED_MODULE} \"${__libsupcxx}\"" )
- set( CMAKE_CXX_LINK_EXECUTABLE "${CMAKE_CXX_LINK_EXECUTABLE} \"${__libsupcxx}\"" )
- # C objects:
- set( CMAKE_C_CREATE_SHARED_LIBRARY " -o " )
- set( CMAKE_C_CREATE_SHARED_MODULE " -o " )
- set( CMAKE_C_LINK_EXECUTABLE " -o " )
- set( CMAKE_C_CREATE_SHARED_LIBRARY "${CMAKE_C_CREATE_SHARED_LIBRARY} \"${__libsupcxx}\"" )
- set( CMAKE_C_CREATE_SHARED_MODULE "${CMAKE_C_CREATE_SHARED_MODULE} \"${__libsupcxx}\"" )
- set( CMAKE_C_LINK_EXECUTABLE "${CMAKE_C_LINK_EXECUTABLE} \"${__libsupcxx}\"" )
- endif()
- if( ANDROID_STL MATCHES "gnustl" )
- if( NOT EXISTS "${ANDROID_LIBM_PATH}" )
- set( ANDROID_LIBM_PATH -lm )
- endif()
- set( CMAKE_CXX_CREATE_SHARED_LIBRARY "${CMAKE_CXX_CREATE_SHARED_LIBRARY} ${ANDROID_LIBM_PATH}" )
- set( CMAKE_CXX_CREATE_SHARED_MODULE "${CMAKE_CXX_CREATE_SHARED_MODULE} ${ANDROID_LIBM_PATH}" )
- set( CMAKE_CXX_LINK_EXECUTABLE "${CMAKE_CXX_LINK_EXECUTABLE} ${ANDROID_LIBM_PATH}" )
- endif()
-endif()
-
-# variables controlling optional build flags
-if( ANDROID_NDK_RELEASE_NUM LESS 7000 ) # before r7
- # libGLESv2.so in NDK's prior to r7 refers to missing external symbols.
- # So this flag option is required for all projects using OpenGL from native.
- __INIT_VARIABLE( ANDROID_SO_UNDEFINED VALUES ON )
-else()
- __INIT_VARIABLE( ANDROID_SO_UNDEFINED VALUES OFF )
-endif()
-__INIT_VARIABLE( ANDROID_NO_UNDEFINED VALUES ON )
-__INIT_VARIABLE( ANDROID_FUNCTION_LEVEL_LINKING VALUES ON )
-__INIT_VARIABLE( ANDROID_GOLD_LINKER VALUES ON )
-__INIT_VARIABLE( ANDROID_NOEXECSTACK VALUES ON )
-__INIT_VARIABLE( ANDROID_RELRO VALUES ON )
-
-set( ANDROID_NO_UNDEFINED ${ANDROID_NO_UNDEFINED} CACHE BOOL "Show all undefined symbols as linker errors" )
-set( ANDROID_SO_UNDEFINED ${ANDROID_SO_UNDEFINED} CACHE BOOL "Allows or disallows undefined symbols in shared libraries" )
-set( ANDROID_FUNCTION_LEVEL_LINKING ${ANDROID_FUNCTION_LEVEL_LINKING} CACHE BOOL "Put each function in separate section and enable garbage collection of unused input sections at link time" )
-set( ANDROID_GOLD_LINKER ${ANDROID_GOLD_LINKER} CACHE BOOL "Enables gold linker" )
-set( ANDROID_NOEXECSTACK ${ANDROID_NOEXECSTACK} CACHE BOOL "Allows or disallows undefined symbols in shared libraries" )
-set( ANDROID_RELRO ${ANDROID_RELRO} CACHE BOOL "Enables RELRO - a memory corruption mitigation technique" )
-mark_as_advanced( ANDROID_NO_UNDEFINED ANDROID_SO_UNDEFINED ANDROID_FUNCTION_LEVEL_LINKING ANDROID_GOLD_LINKER ANDROID_NOEXECSTACK ANDROID_RELRO )
-
-# linker flags
-set( ANDROID_LINKER_FLAGS "" )
-
-if( ARMEABI_V7A )
- # this is *required* to use the following linker flags that routes around
- # a CPU bug in some Cortex-A8 implementations:
- set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -Wl,--fix-cortex-a8" )
-endif()
-
-if( ANDROID_NO_UNDEFINED )
- if( MIPS )
- # there is some sysroot-related problem in mips linker...
- if( NOT ANDROID_SYSROOT MATCHES "[ ;\"]" )
- set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -Wl,--no-undefined -Wl,-rpath-link,${ANDROID_SYSROOT}/usr/lib" )
- endif()
- else()
- set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -Wl,--no-undefined" )
- endif()
-endif()
-
-if( ANDROID_SO_UNDEFINED )
- set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -Wl,-allow-shlib-undefined" )
-endif()
-
-if( ANDROID_FUNCTION_LEVEL_LINKING )
- set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -fdata-sections -ffunction-sections" )
- set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -Wl,--gc-sections" )
-endif()
-
-if( ANDROID_COMPILER_VERSION VERSION_EQUAL "4.6" )
- if( ANDROID_GOLD_LINKER AND (CMAKE_HOST_UNIX OR ANDROID_NDK_RELEASE_NUM GREATER 8002) AND (ARMEABI OR ARMEABI_V7A OR X86) )
- set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -fuse-ld=gold" )
- elseif( ANDROID_NDK_RELEASE_NUM GREATER 8002 ) # after r8b
- set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -fuse-ld=bfd" )
- elseif( ANDROID_NDK_RELEASE STREQUAL "r8b" AND ARMEABI AND NOT _CMAKE_IN_TRY_COMPILE )
- message( WARNING "The default bfd linker from arm GCC 4.6 toolchain can fail with 'unresolvable R_ARM_THM_CALL relocation' error message. See https://code.google.com/p/android/issues/detail?id=35342
- On Linux and OS X host platform you can workaround this problem using gold linker (default).
- Rerun cmake with -DANDROID_GOLD_LINKER=ON option in case of problems.
-" )
- endif()
-endif() # version 4.6
-
-if( ANDROID_NOEXECSTACK )
- if( ANDROID_COMPILER_IS_CLANG )
- set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -Xclang -mnoexecstack" )
- else()
- set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -Wa,--noexecstack" )
- endif()
- set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -Wl,-z,noexecstack" )
-endif()
-
-if( ANDROID_RELRO )
- set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -Wl,-z,relro -Wl,-z,now" )
-endif()
-
-if( ANDROID_COMPILER_IS_CLANG )
- set( ANDROID_CXX_FLAGS "-target ${ANDROID_LLVM_TRIPLE} -Qunused-arguments ${ANDROID_CXX_FLAGS}" )
- if( BUILD_WITH_ANDROID_NDK )
- set( ANDROID_CXX_FLAGS "-gcc-toolchain ${ANDROID_TOOLCHAIN_ROOT} ${ANDROID_CXX_FLAGS}" )
- endif()
-endif()
-
-# cache flags
-set( CMAKE_CXX_FLAGS "" CACHE STRING "c++ flags" )
-set( CMAKE_C_FLAGS "" CACHE STRING "c flags" )
-set( CMAKE_CXX_FLAGS_RELEASE "-O3 -DNDEBUG" CACHE STRING "c++ Release flags" )
-set( CMAKE_C_FLAGS_RELEASE "-O3 -DNDEBUG" CACHE STRING "c Release flags" )
-set( CMAKE_CXX_FLAGS_DEBUG "-O0 -g -DDEBUG -D_DEBUG" CACHE STRING "c++ Debug flags" )
-set( CMAKE_C_FLAGS_DEBUG "-O0 -g -DDEBUG -D_DEBUG" CACHE STRING "c Debug flags" )
-set( CMAKE_SHARED_LINKER_FLAGS "" CACHE STRING "shared linker flags" )
-set( CMAKE_MODULE_LINKER_FLAGS "" CACHE STRING "module linker flags" )
-set( CMAKE_EXE_LINKER_FLAGS "-Wl,-z,nocopyreloc" CACHE STRING "executable linker flags" )
-
-# put flags to cache (for debug purpose only)
-set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS}" CACHE INTERNAL "Android specific c/c++ flags" )
-set( ANDROID_CXX_FLAGS_RELEASE "${ANDROID_CXX_FLAGS_RELEASE}" CACHE INTERNAL "Android specific c/c++ Release flags" )
-set( ANDROID_CXX_FLAGS_DEBUG "${ANDROID_CXX_FLAGS_DEBUG}" CACHE INTERNAL "Android specific c/c++ Debug flags" )
-set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS}" CACHE INTERNAL "Android specific c/c++ linker flags" )
-
-# finish flags
-set( CMAKE_CXX_FLAGS "${ANDROID_CXX_FLAGS} ${CMAKE_CXX_FLAGS}" )
-set( CMAKE_C_FLAGS "${ANDROID_CXX_FLAGS} ${CMAKE_C_FLAGS}" )
-set( CMAKE_CXX_FLAGS_RELEASE "${ANDROID_CXX_FLAGS_RELEASE} ${CMAKE_CXX_FLAGS_RELEASE}" )
-set( CMAKE_C_FLAGS_RELEASE "${ANDROID_CXX_FLAGS_RELEASE} ${CMAKE_C_FLAGS_RELEASE}" )
-set( CMAKE_CXX_FLAGS_DEBUG "${ANDROID_CXX_FLAGS_DEBUG} ${CMAKE_CXX_FLAGS_DEBUG}" )
-set( CMAKE_C_FLAGS_DEBUG "${ANDROID_CXX_FLAGS_DEBUG} ${CMAKE_C_FLAGS_DEBUG}" )
-set( CMAKE_SHARED_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} ${CMAKE_SHARED_LINKER_FLAGS}" )
-set( CMAKE_MODULE_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} ${CMAKE_MODULE_LINKER_FLAGS}" )
-set( CMAKE_EXE_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} ${CMAKE_EXE_LINKER_FLAGS}" )
-
-if( MIPS AND BUILD_WITH_ANDROID_NDK AND ANDROID_NDK_RELEASE STREQUAL "r8" )
- set( CMAKE_SHARED_LINKER_FLAGS "-Wl,-T,${ANDROID_NDK_TOOLCHAINS_PATH}/${ANDROID_GCC_TOOLCHAIN_NAME}/mipself.xsc ${CMAKE_SHARED_LINKER_FLAGS}" )
- set( CMAKE_MODULE_LINKER_FLAGS "-Wl,-T,${ANDROID_NDK_TOOLCHAINS_PATH}/${ANDROID_GCC_TOOLCHAIN_NAME}/mipself.xsc ${CMAKE_MODULE_LINKER_FLAGS}" )
- set( CMAKE_EXE_LINKER_FLAGS "-Wl,-T,${ANDROID_NDK_TOOLCHAINS_PATH}/${ANDROID_GCC_TOOLCHAIN_NAME}/mipself.x ${CMAKE_EXE_LINKER_FLAGS}" )
-endif()
-
-# pie/pic
-if( NOT (ANDROID_NATIVE_API_LEVEL LESS 16) AND (NOT DEFINED ANDROID_APP_PIE OR ANDROID_APP_PIE) AND (CMAKE_VERSION VERSION_GREATER 2.8.8) )
- set( CMAKE_POSITION_INDEPENDENT_CODE TRUE )
- set( CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fPIE -pie")
-else()
- set( CMAKE_POSITION_INDEPENDENT_CODE FALSE )
- set( CMAKE_CXX_FLAGS "-fpic ${CMAKE_CXX_FLAGS}" )
- set( CMAKE_C_FLAGS "-fpic ${CMAKE_C_FLAGS}" )
-endif()
-
-# configure rtti
-if( DEFINED ANDROID_RTTI AND ANDROID_STL_FORCE_FEATURES )
- if( ANDROID_RTTI )
- set( CMAKE_CXX_FLAGS "-frtti ${CMAKE_CXX_FLAGS}" )
- else()
- set( CMAKE_CXX_FLAGS "-fno-rtti ${CMAKE_CXX_FLAGS}" )
- endif()
-endif()
-
-# configure exceptios
-if( DEFINED ANDROID_EXCEPTIONS AND ANDROID_STL_FORCE_FEATURES )
- if( ANDROID_EXCEPTIONS )
- set( CMAKE_CXX_FLAGS "-fexceptions ${CMAKE_CXX_FLAGS}" )
- set( CMAKE_C_FLAGS "-fexceptions ${CMAKE_C_FLAGS}" )
- else()
- set( CMAKE_CXX_FLAGS "-fno-exceptions ${CMAKE_CXX_FLAGS}" )
- set( CMAKE_C_FLAGS "-fno-exceptions ${CMAKE_C_FLAGS}" )
- endif()
-endif()
-
-# global includes and link directories
-include_directories( SYSTEM "${ANDROID_SYSROOT}/usr/include" ${ANDROID_STL_INCLUDE_DIRS} )
-get_filename_component(__android_install_path "${CMAKE_INSTALL_PREFIX}/libs/${ANDROID_NDK_ABI_NAME}" ABSOLUTE) # avoid CMP0015 policy warning
-link_directories( "${__android_install_path}" )
-
-# detect if need link crtbegin_so.o explicitly
-if( NOT DEFINED ANDROID_EXPLICIT_CRT_LINK )
- set( __cmd "${CMAKE_CXX_CREATE_SHARED_LIBRARY}" )
- string( REPLACE "" "${CMAKE_CXX_COMPILER} ${CMAKE_CXX_COMPILER_ARG1}" __cmd "${__cmd}" )
- string( REPLACE "" "${CMAKE_C_COMPILER} ${CMAKE_C_COMPILER_ARG1}" __cmd "${__cmd}" )
- string( REPLACE "" "${CMAKE_CXX_FLAGS}" __cmd "${__cmd}" )
- string( REPLACE "" "" __cmd "${__cmd}" )
- string( REPLACE "" "${CMAKE_SHARED_LINKER_FLAGS}" __cmd "${__cmd}" )
- string( REPLACE "" "-shared" __cmd "${__cmd}" )
- string( REPLACE "" "" __cmd "${__cmd}" )
- string( REPLACE "" "" __cmd "${__cmd}" )
- string( REPLACE "" "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/toolchain_crtlink_test.so" __cmd "${__cmd}" )
- string( REPLACE "" "\"${ANDROID_SYSROOT}/usr/lib/crtbegin_so.o\"" __cmd "${__cmd}" )
- string( REPLACE "" "" __cmd "${__cmd}" )
- separate_arguments( __cmd )
- foreach( __var ANDROID_NDK ANDROID_NDK_TOOLCHAINS_PATH ANDROID_STANDALONE_TOOLCHAIN )
- if( ${__var} )
- set( __tmp "${${__var}}" )
- separate_arguments( __tmp )
- string( REPLACE "${__tmp}" "${${__var}}" __cmd "${__cmd}")
- endif()
- endforeach()
- string( REPLACE "'" "" __cmd "${__cmd}" )
- string( REPLACE "\"" "" __cmd "${__cmd}" )
- execute_process( COMMAND ${__cmd} RESULT_VARIABLE __cmd_result OUTPUT_QUIET ERROR_QUIET )
- if( __cmd_result EQUAL 0 )
- set( ANDROID_EXPLICIT_CRT_LINK ON )
- else()
- set( ANDROID_EXPLICIT_CRT_LINK OFF )
- endif()
-endif()
-
-if( ANDROID_EXPLICIT_CRT_LINK )
- set( CMAKE_CXX_CREATE_SHARED_LIBRARY "${CMAKE_CXX_CREATE_SHARED_LIBRARY} \"${ANDROID_SYSROOT}/usr/lib/crtbegin_so.o\"" )
- set( CMAKE_CXX_CREATE_SHARED_MODULE "${CMAKE_CXX_CREATE_SHARED_MODULE} \"${ANDROID_SYSROOT}/usr/lib/crtbegin_so.o\"" )
-endif()
-
-# setup output directories
-set( CMAKE_INSTALL_PREFIX "${ANDROID_TOOLCHAIN_ROOT}/user" CACHE STRING "path for installing" )
-
-if( DEFINED LIBRARY_OUTPUT_PATH_ROOT
- OR EXISTS "${CMAKE_SOURCE_DIR}/AndroidManifest.xml"
- OR (EXISTS "${CMAKE_SOURCE_DIR}/../AndroidManifest.xml" AND EXISTS "${CMAKE_SOURCE_DIR}/../jni/") )
- set( LIBRARY_OUTPUT_PATH_ROOT ${CMAKE_SOURCE_DIR} CACHE PATH "Root for binaries output, set this to change where Android libs are installed to" )
- if( NOT _CMAKE_IN_TRY_COMPILE )
- if( EXISTS "${CMAKE_SOURCE_DIR}/jni/CMakeLists.txt" )
- set( EXECUTABLE_OUTPUT_PATH "${LIBRARY_OUTPUT_PATH_ROOT}/bin/${ANDROID_NDK_ABI_NAME}" CACHE PATH "Output directory for applications" )
- else()
- set( EXECUTABLE_OUTPUT_PATH "${LIBRARY_OUTPUT_PATH_ROOT}/bin" CACHE PATH "Output directory for applications" )
- endif()
- set( LIBRARY_OUTPUT_PATH "${LIBRARY_OUTPUT_PATH_ROOT}/libs/${ANDROID_NDK_ABI_NAME}" CACHE PATH "Output directory for Android libs" )
- endif()
-endif()
-
-# copy shaed stl library to build directory
-if( NOT _CMAKE_IN_TRY_COMPILE AND __libstl MATCHES "[.]so$" AND DEFINED LIBRARY_OUTPUT_PATH )
- get_filename_component( __libstlname "${__libstl}" NAME )
- execute_process( COMMAND "${CMAKE_COMMAND}" -E copy_if_different "${__libstl}" "${LIBRARY_OUTPUT_PATH}/${__libstlname}" RESULT_VARIABLE __fileCopyProcess )
- if( NOT __fileCopyProcess EQUAL 0 OR NOT EXISTS "${LIBRARY_OUTPUT_PATH}/${__libstlname}")
- message( SEND_ERROR "Failed copying of ${__libstl} to the ${LIBRARY_OUTPUT_PATH}/${__libstlname}" )
- endif()
- unset( __fileCopyProcess )
- unset( __libstlname )
-endif()
-
-
-# set these global flags for cmake client scripts to change behavior
-set( ANDROID True )
-set( BUILD_ANDROID True )
-
-# where is the target environment
-set( CMAKE_FIND_ROOT_PATH "${ANDROID_TOOLCHAIN_ROOT}/bin" "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}" "${ANDROID_SYSROOT}" "${CMAKE_INSTALL_PREFIX}" "${CMAKE_INSTALL_PREFIX}/share" )
-
-# only search for libraries and includes in the ndk toolchain
-set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY )
-set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY )
-set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY )
-
-
-# macro to find packages on the host OS
-macro( find_host_package )
- set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER )
- set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY NEVER )
- set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE NEVER )
- if( CMAKE_HOST_WIN32 )
- SET( WIN32 1 )
- SET( UNIX )
- elseif( CMAKE_HOST_APPLE )
- SET( APPLE 1 )
- SET( UNIX )
- endif()
- find_package( ${ARGN} )
- SET( WIN32 )
- SET( APPLE )
- SET( UNIX 1 )
- set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY )
- set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY )
- set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY )
-endmacro()
-
-
-# macro to find programs on the host OS
-macro( find_host_program )
- set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER )
- set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY NEVER )
- set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE NEVER )
- if( CMAKE_HOST_WIN32 )
- SET( WIN32 1 )
- SET( UNIX )
- elseif( CMAKE_HOST_APPLE )
- SET( APPLE 1 )
- SET( UNIX )
- endif()
- find_program( ${ARGN} )
- SET( WIN32 )
- SET( APPLE )
- SET( UNIX 1 )
- set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY )
- set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY )
- set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY )
-endmacro()
-
-
-# export toolchain settings for the try_compile() command
-if( NOT _CMAKE_IN_TRY_COMPILE )
- set( __toolchain_config "")
- foreach( __var NDK_CCACHE LIBRARY_OUTPUT_PATH_ROOT ANDROID_FORBID_SYGWIN
- ANDROID_NDK_HOST_X64
- ANDROID_NDK
- ANDROID_NDK_LAYOUT
- ANDROID_STANDALONE_TOOLCHAIN
- ANDROID_TOOLCHAIN_NAME
- ANDROID_ABI
- ANDROID_NATIVE_API_LEVEL
- ANDROID_STL
- ANDROID_STL_FORCE_FEATURES
- ANDROID_FORCE_ARM_BUILD
- ANDROID_NO_UNDEFINED
- ANDROID_SO_UNDEFINED
- ANDROID_FUNCTION_LEVEL_LINKING
- ANDROID_GOLD_LINKER
- ANDROID_NOEXECSTACK
- ANDROID_RELRO
- ANDROID_LIBM_PATH
- ANDROID_EXPLICIT_CRT_LINK
- ANDROID_APP_PIE
- )
- if( DEFINED ${__var} )
- if( ${__var} MATCHES " ")
- set( __toolchain_config "${__toolchain_config}set( ${__var} \"${${__var}}\" CACHE INTERNAL \"\" )\n" )
- else()
- set( __toolchain_config "${__toolchain_config}set( ${__var} ${${__var}} CACHE INTERNAL \"\" )\n" )
- endif()
- endif()
- endforeach()
- file( WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/android.toolchain.config.cmake" "${__toolchain_config}" )
- unset( __toolchain_config )
-endif()
-
-
-# force cmake to produce / instead of \ in build commands for Ninja generator
-if( CMAKE_GENERATOR MATCHES "Ninja" AND CMAKE_HOST_WIN32 )
- # it is a bad hack after all
- # CMake generates Ninja makefiles with UNIX paths only if it thinks that we are going to build with MinGW
- set( CMAKE_COMPILER_IS_MINGW TRUE ) # tell CMake that we are MinGW
- set( CMAKE_CROSSCOMPILING TRUE ) # stop recursion
- enable_language( C )
- enable_language( CXX )
- # unset( CMAKE_COMPILER_IS_MINGW ) # can't unset because CMake does not convert back-slashes in response files without it
- unset( MINGW )
-endif()
-
-
-# Variables controlling behavior or set by cmake toolchain:
-# ANDROID_ABI : "armeabi-v7a" (default), "armeabi", "armeabi-v7a with NEON", "armeabi-v7a with VFPV3", "armeabi-v6 with VFP", "x86", "mips", "arm64-v8a", "x86_64", "mips64"
-# ANDROID_NATIVE_API_LEVEL : 3,4,5,8,9,14,15,16,17,18,19,21 (depends on NDK version)
-# ANDROID_STL : gnustl_static/gnustl_shared/stlport_static/stlport_shared/gabi++_static/gabi++_shared/system_re/system/none
-# ANDROID_FORBID_SYGWIN : ON/OFF
-# ANDROID_NO_UNDEFINED : ON/OFF
-# ANDROID_SO_UNDEFINED : OFF/ON (default depends on NDK version)
-# ANDROID_FUNCTION_LEVEL_LINKING : ON/OFF
-# ANDROID_GOLD_LINKER : ON/OFF
-# ANDROID_NOEXECSTACK : ON/OFF
-# ANDROID_RELRO : ON/OFF
-# ANDROID_FORCE_ARM_BUILD : ON/OFF
-# ANDROID_STL_FORCE_FEATURES : ON/OFF
-# ANDROID_LIBM_PATH : path to libm.so (set to something like $(TOP)/out/target/product//obj/lib/libm.so) to workaround unresolved `sincos`
-# Can be set only at the first run:
-# ANDROID_NDK : path to your NDK install
-# NDK_CCACHE : path to your ccache executable
-# ANDROID_TOOLCHAIN_NAME : the NDK name of compiler toolchain
-# ANDROID_NDK_HOST_X64 : try to use x86_64 toolchain (default for x64 host systems)
-# ANDROID_NDK_LAYOUT : the inner NDK structure (RELEASE, LINARO, ANDROID)
-# LIBRARY_OUTPUT_PATH_ROOT :
-# ANDROID_STANDALONE_TOOLCHAIN
-#
-# Primary read-only variables:
-# ANDROID : always TRUE
-# ARMEABI : TRUE for arm v6 and older devices
-# ARMEABI_V6 : TRUE for arm v6
-# ARMEABI_V7A : TRUE for arm v7a
-# ARM64_V8A : TRUE for arm64-v8a
-# NEON : TRUE if NEON unit is enabled
-# VFPV3 : TRUE if VFP version 3 is enabled
-# X86 : TRUE if configured for x86
-# X86_64 : TRUE if configured for x86_64
-# MIPS : TRUE if configured for mips
-# MIPS64 : TRUE if configured for mips64
-# BUILD_WITH_ANDROID_NDK : TRUE if NDK is used
-# BUILD_WITH_STANDALONE_TOOLCHAIN : TRUE if standalone toolchain is used
-# ANDROID_NDK_HOST_SYSTEM_NAME : "windows", "linux-x86" or "darwin-x86" depending on host platform
-# ANDROID_NDK_ABI_NAME : "armeabi", "armeabi-v7a", "x86", "mips", "arm64-v8a", "x86_64", "mips64" depending on ANDROID_ABI
-# ANDROID_NDK_RELEASE : from r5 to r10d; set only for NDK
-# ANDROID_NDK_RELEASE_NUM : numeric ANDROID_NDK_RELEASE version (1000*major+minor)
-# ANDROID_ARCH_NAME : "arm", "x86", "mips", "arm64", "x86_64", "mips64" depending on ANDROID_ABI
-# ANDROID_SYSROOT : path to the compiler sysroot
-# TOOL_OS_SUFFIX : "" or ".exe" depending on host platform
-# ANDROID_COMPILER_IS_CLANG : TRUE if clang compiler is used
-#
-# Secondary (less stable) read-only variables:
-# ANDROID_COMPILER_VERSION : GCC version used (not Clang version)
-# ANDROID_CLANG_VERSION : version of clang compiler if clang is used
-# ANDROID_CXX_FLAGS : C/C++ compiler flags required by Android platform
-# ANDROID_SUPPORTED_ABIS : list of currently allowed values for ANDROID_ABI
-# ANDROID_TOOLCHAIN_MACHINE_NAME : "arm-linux-androideabi", "arm-eabi" or "i686-android-linux"
-# ANDROID_TOOLCHAIN_ROOT : path to the top level of toolchain (standalone or placed inside NDK)
-# ANDROID_CLANG_TOOLCHAIN_ROOT : path to clang tools
-# ANDROID_SUPPORTED_NATIVE_API_LEVELS : list of native API levels found inside NDK
-# ANDROID_STL_INCLUDE_DIRS : stl include paths
-# ANDROID_RTTI : if rtti is enabled by the runtime
-# ANDROID_EXCEPTIONS : if exceptions are enabled by the runtime
-# ANDROID_GCC_TOOLCHAIN_NAME : read-only, differs from ANDROID_TOOLCHAIN_NAME only if clang is used
-#
-# Defaults:
-# ANDROID_DEFAULT_NDK_API_LEVEL
-# ANDROID_DEFAULT_NDK_API_LEVEL_${ARCH}
-# ANDROID_NDK_SEARCH_PATHS
-# ANDROID_SUPPORTED_ABIS_${ARCH}
-# ANDROID_SUPPORTED_NDK_VERSIONS
diff --git a/cmake/android/deployment-file.json.in b/cmake/android/deployment-file.json.in
deleted file mode 100644
index 81ed8a6ecc..0000000000
--- a/cmake/android/deployment-file.json.in
+++ /dev/null
@@ -1,13 +0,0 @@
-{
- "qt": "@QT_DIR@",
- "sdk": "@ANDROID_SDK_ROOT@",
- "ndk": "@ANDROID_NDK@",
- "toolchain-prefix": "@ANDROID_TOOLCHAIN_MACHINE_NAME@",
- "tool-prefix": "@ANDROID_TOOLCHAIN_MACHINE_NAME@",
- "toolchain-version": "@ANDROID_COMPILER_VERSION@",
- "ndk-host": "@ANDROID_NDK_HOST_SYSTEM_NAME@",
- "target-architecture": "@ANDROID_ABI@",
- "application-binary": "@EXECUTABLE_DESTINATION_PATH@",
- "android-extra-libs": "@_DEPS@",
- "android-package-source-directory": "@ANDROID_APK_BUILD_DIR@"
-}
diff --git a/cmake/android/strings.xml.in b/cmake/android/strings.xml.in
deleted file mode 100644
index 6e6ce7b12e..0000000000
--- a/cmake/android/strings.xml.in
+++ /dev/null
@@ -1,11 +0,0 @@
-
-
-
-
-
- ${ANDROID_APP_DISPLAY_NAME}
-
- Can\'t find Ministro service.\nThe application can\'t start.
- This application requires Ministro service. Would you like to install it?
- Your application encountered a fatal error and cannot continue.
-
diff --git a/cmake/externals/glm/CMakeLists.txt b/cmake/externals/glm/CMakeLists.txt
index 79a44fa48e..bc8089074f 100644
--- a/cmake/externals/glm/CMakeLists.txt
+++ b/cmake/externals/glm/CMakeLists.txt
@@ -6,7 +6,7 @@ ExternalProject_Add(
URL https://hifi-public.s3.amazonaws.com/dependencies/glm-0.9.8.zip
URL_MD5 579ac77a3110befa3244d68c0ceb7281
BINARY_DIR ${EXTERNAL_PROJECT_PREFIX}/build
- CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH=
+ CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH= ${EXTERNAL_ARGS}
LOG_DOWNLOAD 1
LOG_CONFIGURE 1
LOG_BUILD 1
diff --git a/cmake/externals/tbb/CMakeLists.txt b/cmake/externals/tbb/CMakeLists.txt
index 71d7b94597..9664fe7250 100644
--- a/cmake/externals/tbb/CMakeLists.txt
+++ b/cmake/externals/tbb/CMakeLists.txt
@@ -8,9 +8,6 @@ if (WIN32)
elseif (APPLE)
set(DOWNLOAD_URL http://s3.amazonaws.com/hifi-public/dependencies/tbb2017_20170604oss_mac_slim.tar.gz)
set(DOWNLOAD_MD5 62bde626b396f8e1a85c6a8ded1d8105)
-elseif (ANDROID)
- set(DOWNLOAD_URL http://hifi-public.s3.amazonaws.com/dependencies/tbb2017_20170604oss_and_slim.tar.gz)
- set(DOWNLOAD_MD5 04d50b64e1d81245a1be5f75f34d64c7)
else ()
set(DOWNLOAD_URL http://hifi-public.s3.amazonaws.com/dependencies/tbb2017_20170604oss_lin_slim.tar.gz)
set(DOWNLOAD_MD5 2a5c721f40fa3503ffc12c18dd00011c)
@@ -107,3 +104,4 @@ endif ()
if (DEFINED ${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE)
set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${SOURCE_DIR}/include CACHE TYPE "List of tbb include directories")
endif ()
+
diff --git a/cmake/init.cmake b/cmake/init.cmake
index 75fb3a4b52..9d7b0fd94c 100644
--- a/cmake/init.cmake
+++ b/cmake/init.cmake
@@ -34,10 +34,23 @@ file(GLOB HIFI_CUSTOM_MACROS "cmake/macros/*.cmake")
foreach(CUSTOM_MACRO ${HIFI_CUSTOM_MACROS})
include(${CUSTOM_MACRO})
endforeach()
+unset(HIFI_CUSTOM_MACROS)
if (ANDROID)
- file(GLOB ANDROID_CUSTOM_MACROS "cmake/android/*.cmake")
- foreach(CUSTOM_MACRO ${ANDROID_CUSTOM_MACROS})
- include(${CUSTOM_MACRO})
- endforeach()
+ set(BUILD_SHARED_LIBS ON)
+ set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE BOTH)
+
+ string(REGEX REPLACE "\\\\" "/" ANDROID_NDK ${ANDROID_NDK})
+ string(REGEX REPLACE "\\\\" "/" CMAKE_TOOLCHAIN_FILE ${CMAKE_TOOLCHAIN_FILE})
+ string(REGEX REPLACE "\\\\" "/" ANDROID_TOOLCHAIN ${ANDROID_TOOLCHAIN})
+ string(REGEX REPLACE "\\\\" "/" CMAKE_MAKE_PROGRAM ${CMAKE_MAKE_PROGRAM})
+ list(APPEND EXTERNAL_ARGS -DANDROID_ABI=${ANDROID_ABI})
+ list(APPEND EXTERNAL_ARGS -DANDROID_NDK=${ANDROID_NDK})
+ list(APPEND EXTERNAL_ARGS -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE})
+ list(APPEND EXTERNAL_ARGS -DCMAKE_MAKE_PROGRAM=${CMAKE_MAKE_PROGRAM})
+ list(APPEND EXTERNAL_ARGS -DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE})
+ list(APPEND EXTERNAL_ARGS -DHIFI_ANDROID=${HIFI_ANDROID})
+ list(APPEND EXTERNAL_ARGS -DANDROID_PLATFORM=${ANDROID_PLATFORM})
+ list(APPEND EXTERNAL_ARGS -DANDROID_TOOLCHAIN=${ANDROID_TOOLCHAIN})
+ list(APPEND EXTERNAL_ARGS -DANDROID_STL=${ANDROID_STL})
endif ()
diff --git a/cmake/macros/AutoScribeShader.cmake b/cmake/macros/AutoScribeShader.cmake
index c43ade45d2..c5b35b7e90 100755
--- a/cmake/macros/AutoScribeShader.cmake
+++ b/cmake/macros/AutoScribeShader.cmake
@@ -62,7 +62,9 @@ function(AUTOSCRIBE_SHADER SHADER_FILE)
# since it's unrunnable by the cross-compiling build machine
# so, we require the compiling user to point us at a compiled executable version for their native toolchain
- find_program(NATIVE_SCRIBE scribe PATHS ${SCRIBE_PATH} ENV SCRIBE_PATH)
+ if (NOT NATIVE_SCRIBE)
+ find_program(NATIVE_SCRIBE scribe PATHS ${SCRIBE_PATH} ENV SCRIBE_PATH)
+ endif()
if (NOT NATIVE_SCRIBE)
message(FATAL_ERROR "The High Fidelity scribe tool is required for shader pre-processing. \
diff --git a/cmake/macros/SetPackagingParameters.cmake b/cmake/macros/SetPackagingParameters.cmake
index 8458d53f68..8faa4e6d96 100644
--- a/cmake/macros/SetPackagingParameters.cmake
+++ b/cmake/macros/SetPackagingParameters.cmake
@@ -162,5 +162,6 @@ macro(SET_PACKAGING_PARAMETERS)
# create a header file our targets can use to find out the application version
file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/includes")
configure_file("${HF_CMAKE_DIR}/templates/BuildInfo.h.in" "${CMAKE_BINARY_DIR}/includes/BuildInfo.h")
+ include_directories("${CMAKE_BINARY_DIR}/includes")
endmacro(SET_PACKAGING_PARAMETERS)
diff --git a/cmake/macros/SetupHifiLibrary.cmake b/cmake/macros/SetupHifiLibrary.cmake
index d0fc58af0c..04687e2c84 100644
--- a/cmake/macros/SetupHifiLibrary.cmake
+++ b/cmake/macros/SetupHifiLibrary.cmake
@@ -12,7 +12,7 @@ macro(SETUP_HIFI_LIBRARY)
project(${TARGET_NAME})
# grab the implementation and header files
- file(GLOB_RECURSE LIB_SRCS "src/*.h" "src/*.cpp" "src/*.c")
+ file(GLOB_RECURSE LIB_SRCS "src/*.h" "src/*.cpp" "src/*.c" "src/*.qrc")
list(APPEND ${TARGET_NAME}_SRCS ${LIB_SRCS})
# add compiler flags to AVX source files
@@ -65,7 +65,7 @@ macro(SETUP_HIFI_LIBRARY)
list(APPEND ${TARGET_NAME}_DEPENDENCY_QT_MODULES Core)
# find these Qt modules and link them to our own target
- find_package(Qt5 COMPONENTS ${${TARGET_NAME}_DEPENDENCY_QT_MODULES} REQUIRED)
+ find_package(Qt5 COMPONENTS ${${TARGET_NAME}_DEPENDENCY_QT_MODULES} REQUIRED CMAKE_FIND_ROOT_PATH_BOTH)
foreach(QT_MODULE ${${TARGET_NAME}_DEPENDENCY_QT_MODULES})
target_link_libraries(${TARGET_NAME} Qt5::${QT_MODULE})
diff --git a/cmake/macros/SetupQt.cmake b/cmake/macros/SetupQt.cmake
index b2a89f81e5..ece8607b9b 100644
--- a/cmake/macros/SetupQt.cmake
+++ b/cmake/macros/SetupQt.cmake
@@ -28,7 +28,7 @@ function(calculate_default_qt_dir _RESULT_NAME)
set(QT_DEFAULT_ARCH "gcc_64")
endif()
- if (WIN32)
+ if (WIN32 OR (ANDROID AND ("${CMAKE_HOST_SYSTEM_NAME}" STREQUAL "Windows")))
set(QT_DEFAULT_ROOT "c:/Qt")
else()
set(QT_DEFAULT_ROOT "$ENV{HOME}/Qt")
diff --git a/cmake/macros/TargetGlew.cmake b/cmake/macros/TargetGlew.cmake
index 5f71f021ec..bc4d5cb033 100644
--- a/cmake/macros/TargetGlew.cmake
+++ b/cmake/macros/TargetGlew.cmake
@@ -6,9 +6,11 @@
# See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
#
macro(TARGET_GLEW)
- add_dependency_external_projects(glew)
- find_package(GLEW REQUIRED)
- add_definitions(-DGLEW_STATIC)
- target_include_directories(${TARGET_NAME} PUBLIC ${GLEW_INCLUDE_DIRS})
- target_link_libraries(${TARGET_NAME} ${GLEW_LIBRARY})
+ if (NOT ANDROID)
+ add_definitions(-DGLEW_STATIC)
+ add_dependency_external_projects(glew)
+ find_package(GLEW REQUIRED)
+ target_include_directories(${TARGET_NAME} PUBLIC ${GLEW_INCLUDE_DIRS})
+ target_link_libraries(${TARGET_NAME} ${GLEW_LIBRARY})
+ endif()
endmacro()
\ No newline at end of file
diff --git a/cmake/macros/TargetOpenGL.cmake b/cmake/macros/TargetOpenGL.cmake
index 73c92e651a..6ad92259bb 100644
--- a/cmake/macros/TargetOpenGL.cmake
+++ b/cmake/macros/TargetOpenGL.cmake
@@ -6,15 +6,13 @@
# See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
#
macro(TARGET_OPENGL)
- add_definitions(-DGLEW_STATIC)
if (APPLE)
# link in required OS X frameworks and include the right GL headers
find_library(OpenGL OpenGL)
target_link_libraries(${TARGET_NAME} ${OpenGL})
elseif(ANDROID)
- target_link_libraries(${TARGET_NAME} "-lGLESv3" "-lEGL")
+ target_link_libraries(${TARGET_NAME} GLESv3 EGL)
else()
- target_nsight()
find_package(OpenGL REQUIRED)
if (${OPENGL_INCLUDE_DIR})
include_directories(SYSTEM "${OPENGL_INCLUDE_DIR}")
@@ -22,4 +20,6 @@ macro(TARGET_OPENGL)
target_link_libraries(${TARGET_NAME} "${OPENGL_LIBRARY}")
target_include_directories(${TARGET_NAME} PUBLIC ${OPENGL_INCLUDE_DIR})
endif()
+ target_nsight()
+ target_glew()
endmacro()
diff --git a/cmake/macros/TargetOpenSSL.cmake b/cmake/macros/TargetOpenSSL.cmake
new file mode 100644
index 0000000000..7ee0283a48
--- /dev/null
+++ b/cmake/macros/TargetOpenSSL.cmake
@@ -0,0 +1,32 @@
+#
+# Copyright 2015 High Fidelity, Inc.
+# Created by Bradley Austin Davis on 2015/10/10
+#
+# 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_OPENSSL)
+
+ if (ANDROID)
+
+ # FIXME use a distributable binary
+ set(OPENSSL_INSTALL_DIR C:/Android/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)
+
+ if (APPLE AND ${OPENSSL_INCLUDE_DIR} STREQUAL "/usr/include")
+ # this is a user on OS X using system OpenSSL, which is going to throw warnings since they're deprecating for their common crypto
+ message(WARNING "The found version of OpenSSL is the OS X system version. This will produce deprecation warnings."
+ "\nWe recommend you install a newer version (at least 1.0.1h) in a different directory and set OPENSSL_ROOT_DIR in your env so Cmake can find it.")
+ endif()
+
+ endif()
+
+ include_directories(SYSTEM "${OPENSSL_INCLUDE_DIR}")
+ target_link_libraries(${TARGET_NAME} ${OPENSSL_LIBRARIES})
+
+endmacro()
diff --git a/cmake/macros/TargetTBB.cmake b/cmake/macros/TargetTBB.cmake
new file mode 100644
index 0000000000..e9c4639c3d
--- /dev/null
+++ b/cmake/macros/TargetTBB.cmake
@@ -0,0 +1,24 @@
+#
+# Copyright 2015 High Fidelity, Inc.
+# Created by Bradley Austin Davis on 2015/10/10
+#
+# 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_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_LIBRARIES ${TBB_LIBRARY} ${TBB_MALLOC_LIBRARY})
+else()
+ add_dependency_external_projects(tbb)
+ find_package(TBB REQUIRED)
+endif()
+
+target_link_libraries(${TARGET_NAME} ${TBB_LIBRARIES})
+target_include_directories(${TARGET_NAME} SYSTEM PUBLIC ${TBB_INCLUDE_DIRS})
+
+endmacro()
diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt
index 43e50c6d33..305a6475f6 100644
--- a/interface/CMakeLists.txt
+++ b/interface/CMakeLists.txt
@@ -171,8 +171,6 @@ else ()
add_executable(${TARGET_NAME} ${INTERFACE_SRCS} ${QM})
endif ()
-target_include_directories(${TARGET_NAME} PRIVATE "${CMAKE_BINARY_DIR}/includes")
-
if (WIN32)
# These are external plugins, but we need to do the 'add dependency' here so that their
# binary directories get added to the fixup path
@@ -214,10 +212,6 @@ target_include_directories(${TARGET_NAME} PRIVATE "${CMAKE_BINARY_DIR}/libraries
target_bullet()
target_opengl()
-if (NOT ANDROID)
- target_glew()
-endif ()
-
# perform standard include and linking for found externals
foreach(EXTERNAL ${OPTIONAL_EXTERNALS})
diff --git a/interface/resources/qml/controls-uit/Keyboard.qml b/interface/resources/qml/controls-uit/Keyboard.qml
index 4739534fcd..ab361491bd 100644
--- a/interface/resources/qml/controls-uit/Keyboard.qml
+++ b/interface/resources/qml/controls-uit/Keyboard.qml
@@ -116,6 +116,13 @@ Item {
wrapMode: Text.WordWrap
readOnly: false // we need to leave this property read-only to allow control to accept QKeyEvent
selectByMouse: false
+
+ Keys.onPressed: {
+ if (event.key == Qt.Key_Return) {
+ mirrorText.text = "";
+ event.accepted = true;
+ }
+ }
}
MouseArea { // ... and we need this mouse area to prevent mirrorText from getting mouse events to ensure it will never get focus
diff --git a/interface/resources/qml/hifi/tablet/TabletMenuItem.qml b/interface/resources/qml/hifi/tablet/TabletMenuItem.qml
index 71e59e0d01..11d3cab35e 100644
--- a/interface/resources/qml/hifi/tablet/TabletMenuItem.qml
+++ b/interface/resources/qml/hifi/tablet/TabletMenuItem.qml
@@ -21,9 +21,9 @@ Item {
property alias text: label.text
property var source
- implicitHeight: source.visible ? 2 * label.implicitHeight : 0
+ implicitHeight: source !== null ? source.visible ? 2 * label.implicitHeight : 0 : 0
implicitWidth: 2 * hifi.dimensions.menuPadding.x + check.width + label.width + tail.width
- visible: source.visible
+ visible: source !== null ? source.visible : false
width: parent.width
Item {
@@ -42,7 +42,9 @@ Item {
id: checkbox
// FIXME: Should use radio buttons if source.exclusiveGroup.
width: 20
- visible: source.visible && source.type === 1 && source.checkable && !source.exclusiveGroup
+ visible: source !== null ?
+ source.visible && source.type === 1 && source.checkable && !source.exclusiveGroup :
+ false
checked: setChecked()
function setChecked() {
if (!source || source.type !== 1 || !source.checkable) {
@@ -58,7 +60,9 @@ Item {
id: radiobutton
// FIXME: Should use radio buttons if source.exclusiveGroup.
width: 20
- visible: source.visible && source.type === 1 && source.checkable && source.exclusiveGroup
+ visible: source !== null ?
+ source.visible && source.type === 1 && source.checkable && source.exclusiveGroup :
+ false
checked: setChecked()
function setChecked() {
if (!source || source.type !== 1 || !source.checkable) {
@@ -80,9 +84,13 @@ Item {
anchors.left: check.right
anchors.verticalCenter: parent.verticalCenter
verticalAlignment: Text.AlignVCenter
- color: source.enabled ? hifi.colors.baseGrayShadow : hifi.colors.baseGrayShadow50
- enabled: source.visible && (source.type !== 0 ? source.enabled : false)
- visible: source.visible
+ color: source !== null ?
+ source.enabled ? hifi.colors.baseGrayShadow :
+ hifi.colors.baseGrayShadow50 :
+ "transparent"
+
+ enabled: source !== null ? source.visible && (source.type !== 0 ? source.enabled : false) : false
+ visible: source !== null ? source.visible : false
wrapMode: Text.WordWrap
}
@@ -93,7 +101,7 @@ Item {
leftMargin: hifi.dimensions.menuPadding.x + check.width
rightMargin: hifi.dimensions.menuPadding.x + tail.width
}
- visible: source.type === MenuItemType.Separator
+ visible: source !== null ? source.type === MenuItemType.Separator : false
Rectangle {
anchors {
@@ -117,23 +125,23 @@ Item {
RalewayLight {
id: shortcut
- text: source.shortcut ? source.shortcut : ""
+ text: source !== null ? source.shortcut ? source.shortcut : "" : ""
size: hifi.fontSizes.shortcutText
color: hifi.colors.baseGrayShadow
anchors.verticalCenter: parent.verticalCenter
anchors.right: parent.right
anchors.rightMargin: 15
- visible: source.visible && text != ""
+ visible: source !== null ? source.visible && text != "" : false
}
HiFiGlyphs {
text: hifi.glyphs.disclosureExpand
- color: source.enabled ? hifi.colors.baseGrayShadow : hifi.colors.baseGrayShadow25
+ color: source !== null ? source.enabled ? hifi.colors.baseGrayShadow : hifi.colors.baseGrayShadow25 : "transparent"
size: 70
anchors.verticalCenter: parent.verticalCenter
anchors.right: parent.right
horizontalAlignment: Text.AlignRight
- visible: source.visible && (source.type === 2)
+ visible: source !== null ? source.visible && (source.type === 2) : false
}
}
}
diff --git a/interface/resources/qml/hifi/tablet/TabletMenuStack.qml b/interface/resources/qml/hifi/tablet/TabletMenuStack.qml
index e7eefbc5e7..ce4fac3bd5 100644
--- a/interface/resources/qml/hifi/tablet/TabletMenuStack.qml
+++ b/interface/resources/qml/hifi/tablet/TabletMenuStack.qml
@@ -70,7 +70,6 @@ Item {
for (var i = 0; i < items.length; ++i) {
var item = items[i];
- if (!item.visible) continue;
switch (item.type) {
case MenuItemType.Menu:
result.append({"name": item.title, "item": item})
@@ -216,5 +215,4 @@ Item {
function nextItem() { d.topMenu.nextItem(); }
function selectCurrentItem() { d.topMenu.selectCurrentItem(); }
function previousPage() { d.topMenu.previousPage(); }
-
}
diff --git a/interface/resources/qml/hifi/tablet/TabletMenuView.qml b/interface/resources/qml/hifi/tablet/TabletMenuView.qml
index 92e7f59524..ecfb653923 100644
--- a/interface/resources/qml/hifi/tablet/TabletMenuView.qml
+++ b/interface/resources/qml/hifi/tablet/TabletMenuView.qml
@@ -9,8 +9,6 @@
//
import QtQuick 2.5
-import QtQuick.Controls 1.4
-import QtQuick.Controls.Styles 1.4
import "../../styles-uit"
import "."
@@ -36,7 +34,6 @@ FocusScope {
//color: isSubMenu ? hifi.colors.faintGray : hifi.colors.faintGray80
}
-
ListView {
id: listView
x: 0
@@ -68,8 +65,8 @@ FocusScope {
delegate: TabletMenuItem {
text: name
source: item
- onImplicitHeightChanged: listView.recalcSize()
- onImplicitWidthChanged: listView.recalcSize()
+ onImplicitHeightChanged: listView !== null ? listView.recalcSize() : 0
+ onImplicitWidthChanged: listView !== null ? listView.recalcSize() : 0
MouseArea {
anchors.fill: parent
@@ -124,8 +121,6 @@ FocusScope {
function nextItem() { listView.currentIndex = (listView.currentIndex + listView.count + 1) % listView.count; }
function selectCurrentItem() { if (listView.currentIndex != -1) root.selected(currentItem.source); }
function previousPage() { root.parent.pop(); }
-
-
}
diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp
index e1c3af1939..480928ccd2 100644
--- a/interface/src/Application.cpp
+++ b/interface/src/Application.cpp
@@ -980,7 +980,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
connect(scriptEngines, &ScriptEngines::scriptLoadError,
scriptEngines, [](const QString& filename, const QString& error){
- OffscreenUi::warning(nullptr, "Error Loading Script", filename + " failed to load.");
+ OffscreenUi::asyncWarning(nullptr, "Error Loading Script", filename + " failed to load.");
}, Qt::QueuedConnection);
#ifdef _WIN32
@@ -1845,7 +1845,7 @@ void Application::domainConnectionRefused(const QString& reasonMessage, int reas
case DomainHandler::ConnectionRefusedReason::Unknown: {
QString message = "Unable to connect to the location you are visiting.\n";
message += reasonMessage;
- OffscreenUi::warning("", message);
+ OffscreenUi::asyncWarning("", message);
break;
}
default:
@@ -2369,6 +2369,7 @@ void Application::initializeUi() {
// Pre-create a couple of Web3D overlays to speed up tablet UI
auto offscreenSurfaceCache = DependencyManager::get();
+ offscreenSurfaceCache->reserve(TabletScriptingInterface::QML, 1);
offscreenSurfaceCache->reserve(Web3DOverlay::QML, 2);
}
@@ -2581,7 +2582,6 @@ void Application::paintGL() {
// scale IPD by sensorToWorldScale, to make the world seem larger or smaller accordingly.
ipdScale *= sensorToWorldScale;
- mat4 eyeProjections[2];
{
PROFILE_RANGE(render, "/mainRender");
PerformanceTimer perfTimer("mainRender");
@@ -2638,17 +2638,8 @@ void Application::paintGL() {
PerformanceTimer perfTimer("postComposite");
renderArgs._batch = &postCompositeBatch;
renderArgs._batch->setViewportTransform(ivec4(0, 0, finalFramebufferSize.width(), finalFramebufferSize.height()));
- for_each_eye([&](Eye eye) {
-
- // apply eye offset and IPD scale to the view matrix
- mat4 eyeToHead = displayPlugin->getEyeToHeadTransform(eye);
- vec3 eyeOffset = glm::vec3(eyeToHead[3]);
- mat4 eyeOffsetTransform = glm::translate(mat4(), eyeOffset * -1.0f * ipdScale);
- renderArgs._batch->setViewTransform(renderArgs.getViewFrustum().getView() * eyeOffsetTransform);
-
- renderArgs._batch->setProjectionTransform(eyeProjections[eye]);
- _overlays.render3DHUDOverlays(&renderArgs);
- });
+ renderArgs._batch->setViewTransform(renderArgs.getViewFrustum().getView());
+ _overlays.render3DHUDOverlays(&renderArgs);
}
auto frame = _gpuContext->endFrame();
@@ -3751,7 +3742,7 @@ bool Application::acceptSnapshot(const QString& urlString) {
DependencyManager::get()->handleLookupString(snapshotData->getURL().toString());
}
} else {
- OffscreenUi::warning("", "No location details were found in the file\n" +
+ OffscreenUi::asyncWarning("", "No location details were found in the file\n" +
snapshotPath + "\nTry dragging in an authentic Hifi snapshot.");
}
return true;
@@ -6151,7 +6142,7 @@ void Application::setSessionUUID(const QUuid& sessionUUID) const {
bool Application::askToSetAvatarUrl(const QString& url) {
QUrl realUrl(url);
if (realUrl.isLocalFile()) {
- OffscreenUi::warning("", "You can not use local files for avatar components.");
+ OffscreenUi::asyncWarning("", "You can not use local files for avatar components.");
return false;
}
@@ -6163,41 +6154,55 @@ bool Application::askToSetAvatarUrl(const QString& url) {
QString modelName = fstMapping["name"].toString();
QString modelLicense = fstMapping["license"].toString();
- bool agreeToLicence = true; // assume true
+ bool agreeToLicense = true; // assume true
+ //create set avatar callback
+ auto setAvatar = [=] (QString url, QString modelName) {
+ ModalDialogListener* dlg = OffscreenUi::asyncQuestion("Set Avatar",
+ "Would you like to use '" + modelName + "' for your avatar?",
+ QMessageBox::Ok | QMessageBox::Cancel, QMessageBox::Ok);
+ QObject::connect(dlg, &ModalDialogListener::response, this, [=] (QVariant answer) {
+ QObject::disconnect(dlg, &ModalDialogListener::response, this, nullptr);
+
+ bool ok = (QMessageBox::Ok == static_cast(answer.toInt()));
+ if (ok) {
+ getMyAvatar()->useFullAvatarURL(url, modelName);
+ emit fullAvatarURLChanged(url, modelName);
+ } else {
+ qCDebug(interfaceapp) << "Declined to use the avatar: " << url;
+ }
+ });
+ };
+
if (!modelLicense.isEmpty()) {
- // word wrap the licence text to fit in a reasonable shaped message box.
+ // word wrap the license text to fit in a reasonable shaped message box.
const int MAX_CHARACTERS_PER_LINE = 90;
modelLicense = simpleWordWrap(modelLicense, MAX_CHARACTERS_PER_LINE);
- agreeToLicence = QMessageBox::Yes == OffscreenUi::question("Avatar Usage License",
- modelLicense + "\nDo you agree to these terms?",
- QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
- }
+ ModalDialogListener* dlg = OffscreenUi::asyncQuestion("Avatar Usage License",
+ modelLicense + "\nDo you agree to these terms?",
+ QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
+ QObject::connect(dlg, &ModalDialogListener::response, this, [=, &agreeToLicense] (QVariant answer) {
+ QObject::disconnect(dlg, &ModalDialogListener::response, this, nullptr);
- bool ok = false;
+ agreeToLicense = (static_cast(answer.toInt()) == QMessageBox::Yes);
+ if (agreeToLicense) {
+ switch (modelType) {
+ case FSTReader::HEAD_AND_BODY_MODEL: {
+ setAvatar(url, modelName);
+ break;
+ }
+ default:
+ OffscreenUi::asyncWarning("", modelName + "Does not support a head and body as required.");
+ break;
+ }
+ } else {
+ qCDebug(interfaceapp) << "Declined to agree to avatar license: " << url;
+ }
- if (!agreeToLicence) {
- qCDebug(interfaceapp) << "Declined to agree to avatar license: " << url;
+ //auto offscreenUi = DependencyManager::get();
+ });
} else {
- switch (modelType) {
-
- case FSTReader::HEAD_AND_BODY_MODEL:
- ok = QMessageBox::Ok == OffscreenUi::question("Set Avatar",
- "Would you like to use '" + modelName + "' for your avatar?",
- QMessageBox::Ok | QMessageBox::Cancel, QMessageBox::Ok);
- break;
-
- default:
- OffscreenUi::warning("", modelName + "Does not support a head and body as required.");
- break;
- }
- }
-
- if (ok) {
- getMyAvatar()->useFullAvatarURL(url, modelName);
- emit fullAvatarURLChanged(url, modelName);
- } else {
- qCDebug(interfaceapp) << "Declined to use the avatar: " << url;
+ setAvatar(url, modelName);
}
return true;
@@ -6205,8 +6210,6 @@ bool Application::askToSetAvatarUrl(const QString& url) {
bool Application::askToLoadScript(const QString& scriptFilenameOrURL) {
- QMessageBox::StandardButton reply;
-
QString shortName = scriptFilenameOrURL;
QUrl scriptURL { scriptFilenameOrURL };
@@ -6218,15 +6221,20 @@ bool Application::askToLoadScript(const QString& scriptFilenameOrURL) {
}
QString message = "Would you like to run this script:\n" + shortName;
+ ModalDialogListener* dlg = OffscreenUi::asyncQuestion(getWindow(), "Run Script", message,
+ QMessageBox::Yes | QMessageBox::No);
- reply = OffscreenUi::question(getWindow(), "Run Script", message, QMessageBox::Yes | QMessageBox::No);
+ QObject::connect(dlg, &ModalDialogListener::response, this, [=] (QVariant answer) {
+ const QString& fileName = scriptFilenameOrURL;
+ if (static_cast(answer.toInt()) == QMessageBox::Yes) {
+ qCDebug(interfaceapp) << "Chose to run the script: " << fileName;
+ DependencyManager::get()->loadScript(fileName);
+ } else {
+ qCDebug(interfaceapp) << "Declined to run the script: " << scriptFilenameOrURL;
+ }
+ QObject::disconnect(dlg, &ModalDialogListener::response, this, nullptr);
+ });
- if (reply == QMessageBox::Yes) {
- qCDebug(interfaceapp) << "Chose to run the script: " << scriptFilenameOrURL;
- DependencyManager::get()->loadScript(scriptFilenameOrURL);
- } else {
- qCDebug(interfaceapp) << "Declined to run the script: " << scriptFilenameOrURL;
- }
return true;
}
@@ -6263,22 +6271,26 @@ bool Application::askToWearAvatarAttachmentUrl(const QString& url) {
name = nameValue.toString();
}
- // display confirmation dialog
- if (displayAvatarAttachmentConfirmationDialog(name)) {
-
- // add attachment to avatar
- auto myAvatar = getMyAvatar();
- assert(myAvatar);
- auto attachmentDataVec = myAvatar->getAttachmentData();
- AttachmentData attachmentData;
- attachmentData.fromJson(jsonObject);
- attachmentDataVec.push_back(attachmentData);
- myAvatar->setAttachmentData(attachmentDataVec);
-
- } else {
- qCDebug(interfaceapp) << "User declined to wear the avatar attachment: " << url;
- }
-
+ auto avatarAttachmentConfirmationTitle = tr("Avatar Attachment Confirmation");
+ auto avatarAttachmentConfirmationMessage = tr("Would you like to wear '%1' on your avatar?").arg(name);
+ ModalDialogListener* dlg = OffscreenUi::asyncQuestion(avatarAttachmentConfirmationTitle,
+ avatarAttachmentConfirmationMessage,
+ QMessageBox::Ok | QMessageBox::Cancel);
+ QObject::connect(dlg, &ModalDialogListener::response, this, [=] (QVariant answer) {
+ QObject::disconnect(dlg, &ModalDialogListener::response, this, nullptr);
+ if (static_cast(answer.toInt()) == QMessageBox::Yes) {
+ // add attachment to avatar
+ auto myAvatar = getMyAvatar();
+ assert(myAvatar);
+ auto attachmentDataVec = myAvatar->getAttachmentData();
+ AttachmentData attachmentData;
+ attachmentData.fromJson(jsonObject);
+ attachmentDataVec.push_back(attachmentData);
+ myAvatar->setAttachmentData(attachmentDataVec);
+ } else {
+ qCDebug(interfaceapp) << "User declined to wear the avatar attachment: " << url;
+ }
+ });
} else {
// json parse error
auto avatarAttachmentParseErrorString = tr("Error parsing attachment JSON from url: \"%1\"");
@@ -6351,20 +6363,7 @@ bool Application::askToReplaceDomainContent(const QString& url) {
void Application::displayAvatarAttachmentWarning(const QString& message) const {
auto avatarAttachmentWarningTitle = tr("Avatar Attachment Failure");
- OffscreenUi::warning(avatarAttachmentWarningTitle, message);
-}
-
-bool Application::displayAvatarAttachmentConfirmationDialog(const QString& name) const {
- auto avatarAttachmentConfirmationTitle = tr("Avatar Attachment Confirmation");
- auto avatarAttachmentConfirmationMessage = tr("Would you like to wear '%1' on your avatar?").arg(name);
- auto reply = OffscreenUi::question(avatarAttachmentConfirmationTitle,
- avatarAttachmentConfirmationMessage,
- QMessageBox::Ok | QMessageBox::Cancel);
- if (QMessageBox::Ok == reply) {
- return true;
- } else {
- return false;
- }
+ OffscreenUi::asyncWarning(avatarAttachmentWarningTitle, message);
}
void Application::showDialog(const QUrl& widgetUrl, const QUrl& tabletUrl, const QString& name) const {
@@ -6686,7 +6685,7 @@ void Application::addAssetToWorldCheckModelSize() {
if (dimensions != DEFAULT_DIMENSIONS) {
// Scale model so that its maximum is exactly specific size.
- const float MAXIMUM_DIMENSION = 1.0f * getMyAvatar()->getSensorToWorldScale();
+ const float MAXIMUM_DIMENSION = getMyAvatar()->getSensorToWorldScale();
auto previousDimensions = dimensions;
auto scale = std::min(MAXIMUM_DIMENSION / dimensions.x, std::min(MAXIMUM_DIMENSION / dimensions.y,
MAXIMUM_DIMENSION / dimensions.z));
@@ -6945,12 +6944,17 @@ void Application::openUrl(const QUrl& url) const {
void Application::loadDialog() {
auto scriptEngines = DependencyManager::get();
- QString fileNameString = OffscreenUi::getOpenFileName(
- _glWidget, tr("Open Script"), getPreviousScriptLocation(), tr("JavaScript Files (*.js)"));
- if (!fileNameString.isEmpty() && QFile(fileNameString).exists()) {
- setPreviousScriptLocation(QFileInfo(fileNameString).absolutePath());
- DependencyManager::get()->loadScript(fileNameString, true, false, false, true); // Don't load from cache
- }
+ ModalDialogListener* dlg = OffscreenUi::getOpenFileNameAsync(_glWidget, tr("Open Script"),
+ getPreviousScriptLocation(),
+ tr("JavaScript Files (*.js)"));
+ connect(dlg, &ModalDialogListener::response, this, [=] (QVariant answer) {
+ disconnect(dlg, &ModalDialogListener::response, this, nullptr);
+ const QString& response = answer.toString();
+ if (!response.isEmpty() && QFile(response).exists()) {
+ setPreviousScriptLocation(QFileInfo(response).absolutePath());
+ DependencyManager::get()->loadScript(response, true, false, false, true); // Don't load from cache
+ }
+ });
}
QString Application::getPreviousScriptLocation() {
@@ -6963,12 +6967,16 @@ void Application::setPreviousScriptLocation(const QString& location) {
}
void Application::loadScriptURLDialog() const {
- QString newScript = OffscreenUi::getText(OffscreenUi::ICON_NONE, "Open and Run Script", "Script URL");
- if (QUrl(newScript).scheme() == "atp") {
- OffscreenUi::warning("Error Loading Script", "Cannot load client script over ATP");
- } else if (!newScript.isEmpty()) {
- DependencyManager::get()->loadScript(newScript.trimmed());
- }
+ ModalDialogListener* dlg = OffscreenUi::getTextAsync(OffscreenUi::ICON_NONE, "Open and Run Script", "Script URL");
+ connect(dlg, &ModalDialogListener::response, this, [=] (QVariant response) {
+ disconnect(dlg, &ModalDialogListener::response, this, nullptr);
+ const QString& newScript = response.toString();
+ if (QUrl(newScript).scheme() == "atp") {
+ OffscreenUi::asyncWarning("Error Loading Script", "Cannot load client script over ATP");
+ } else if (!newScript.isEmpty()) {
+ DependencyManager::get()->loadScript(newScript.trimmed());
+ }
+ });
}
void Application::loadLODToolsDialog() {
@@ -7085,7 +7093,7 @@ void Application::notifyPacketVersionMismatch() {
QString message = "The location you are visiting is running an incompatible server version.\n";
message += "Content may not display properly.";
- OffscreenUi::warning("", message);
+ OffscreenUi::asyncWarning("", message);
}
}
@@ -7094,7 +7102,7 @@ void Application::checkSkeleton() const {
qCDebug(interfaceapp) << "MyAvatar model has no skeleton";
QString message = "Your selected avatar body has no skeleton.\n\nThe default body will be loaded...";
- OffscreenUi::warning("", message);
+ OffscreenUi::asyncWarning("", message);
getMyAvatar()->useFullAvatarURL(AvatarData::defaultFullAvatarModelUrl(), DEFAULT_FULL_AVATAR_MODEL_NAME);
} else {
diff --git a/interface/src/Application.h b/interface/src/Application.h
index 86e4f94917..04441276eb 100644
--- a/interface/src/Application.h
+++ b/interface/src/Application.h
@@ -429,7 +429,6 @@ private slots:
bool askToWearAvatarAttachmentUrl(const QString& url);
void displayAvatarAttachmentWarning(const QString& message) const;
- bool displayAvatarAttachmentConfirmationDialog(const QString& name) const;
bool askToReplaceDomainContent(const QString& url);
diff --git a/interface/src/AvatarBookmarks.cpp b/interface/src/AvatarBookmarks.cpp
index 73192b0bef..5b9c45eef5 100644
--- a/interface/src/AvatarBookmarks.cpp
+++ b/interface/src/AvatarBookmarks.cpp
@@ -106,30 +106,30 @@ void AvatarBookmarks::changeToBookmarkedAvatar() {
}
void AvatarBookmarks::addBookmark() {
- bool ok = false;
- auto bookmarkName = OffscreenUi::getText(OffscreenUi::ICON_PLACEMARK, "Bookmark Avatar", "Name", QString(), &ok);
- if (!ok) {
- return;
- }
+ ModalDialogListener* dlg = OffscreenUi::getTextAsync(OffscreenUi::ICON_PLACEMARK, "Bookmark Avatar", "Name", QString());
+ connect(dlg, &ModalDialogListener::response, this, [=] (QVariant response) {
+ disconnect(dlg, &ModalDialogListener::response, this, nullptr);
+ auto bookmarkName = response.toString();
+ bookmarkName = bookmarkName.trimmed().replace(QRegExp("(\r\n|[\r\n\t\v ])+"), " ");
+ if (bookmarkName.length() == 0) {
+ return;
+ }
- bookmarkName = bookmarkName.trimmed().replace(QRegExp("(\r\n|[\r\n\t\v ])+"), " ");
- if (bookmarkName.length() == 0) {
- return;
- }
+ auto myAvatar = DependencyManager::get()->getMyAvatar();
- auto myAvatar = DependencyManager::get()->getMyAvatar();
+ const QString& avatarUrl = myAvatar->getSkeletonModelURL().toString();
+ const QVariant& avatarScale = myAvatar->getAvatarScale();
- const QString& avatarUrl = myAvatar->getSkeletonModelURL().toString();
- const QVariant& avatarScale = myAvatar->getAvatarScale();
+ // If Avatar attachments ever change, this is where to update them, when saving remember to also append to AVATAR_BOOKMARK_VERSION
+ QVariantMap *bookmark = new QVariantMap;
+ bookmark->insert(ENTRY_VERSION, AVATAR_BOOKMARK_VERSION);
+ bookmark->insert(ENTRY_AVATAR_URL, avatarUrl);
+ bookmark->insert(ENTRY_AVATAR_SCALE, avatarScale);
+ bookmark->insert(ENTRY_AVATAR_ATTACHMENTS, myAvatar->getAttachmentsVariant());
+
+ Bookmarks::addBookmarkToFile(bookmarkName, *bookmark);
+ });
- // If Avatar attachments ever change, this is where to update them, when saving remember to also append to AVATAR_BOOKMARK_VERSION
- QVariantMap *bookmark = new QVariantMap;
- bookmark->insert(ENTRY_VERSION, AVATAR_BOOKMARK_VERSION);
- bookmark->insert(ENTRY_AVATAR_URL, avatarUrl);
- bookmark->insert(ENTRY_AVATAR_SCALE, avatarScale);
- bookmark->insert(ENTRY_AVATAR_ATTACHMENTS, myAvatar->getAttachmentsVariant());
-
- Bookmarks::addBookmarkToFile(bookmarkName, *bookmark);
}
void AvatarBookmarks::addBookmarkToMenu(Menu* menubar, const QString& name, const QVariant& bookmark) {
diff --git a/interface/src/Bookmarks.cpp b/interface/src/Bookmarks.cpp
index 0bd6b01128..f48b5e1f5b 100644
--- a/interface/src/Bookmarks.cpp
+++ b/interface/src/Bookmarks.cpp
@@ -58,20 +58,25 @@ void Bookmarks::addBookmarkToFile(const QString& bookmarkName, const QVariant& b
Menu* menubar = Menu::getInstance();
if (contains(bookmarkName)) {
auto offscreenUi = DependencyManager::get();
- auto duplicateBookmarkMessage = offscreenUi->createMessageBox(OffscreenUi::ICON_WARNING, "Duplicate Bookmark",
- "The bookmark name you entered already exists in your list.",
- QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
- duplicateBookmarkMessage->setProperty("informativeText", "Would you like to overwrite it?");
- auto result = offscreenUi->waitForMessageBoxResult(duplicateBookmarkMessage);
- if (result != QMessageBox::Yes) {
- return;
- }
- removeBookmarkFromMenu(menubar, bookmarkName);
- }
+ ModalDialogListener* dlg = OffscreenUi::asyncWarning("Duplicate Bookmark",
+ "The bookmark name you entered already exists in your list.",
+ QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
+ dlg->setProperty("informativeText", "Would you like to overwrite it?");
+ QObject::connect(dlg, &ModalDialogListener::response, this, [=] (QVariant answer) {
+ QObject::disconnect(dlg, &ModalDialogListener::response, this, nullptr);
- addBookmarkToMenu(menubar, bookmarkName, bookmark);
- insert(bookmarkName, bookmark); // Overwrites any item with the same bookmarkName.
- enableMenuItems(true);
+ if (QMessageBox::Yes == static_cast(answer.toInt())) {
+ removeBookmarkFromMenu(menubar, bookmarkName);
+ addBookmarkToMenu(menubar, bookmarkName, bookmark);
+ insert(bookmarkName, bookmark); // Overwrites any item with the same bookmarkName.
+ enableMenuItems(true);
+ }
+ });
+ } else {
+ addBookmarkToMenu(menubar, bookmarkName, bookmark);
+ insert(bookmarkName, bookmark); // Overwrites any item with the same bookmarkName.
+ enableMenuItems(true);
+ }
}
void Bookmarks::insert(const QString& name, const QVariant& bookmark) {
diff --git a/interface/src/LocationBookmarks.cpp b/interface/src/LocationBookmarks.cpp
index b234f8c07b..285f533a7f 100644
--- a/interface/src/LocationBookmarks.cpp
+++ b/interface/src/LocationBookmarks.cpp
@@ -74,20 +74,21 @@ void LocationBookmarks::teleportToBookmark() {
}
void LocationBookmarks::addBookmark() {
- bool ok = false;
- auto bookmarkName = OffscreenUi::getText(OffscreenUi::ICON_PLACEMARK, "Bookmark Location", "Name", QString(), &ok);
- if (!ok) {
- return;
- }
+ ModalDialogListener* dlg = OffscreenUi::getTextAsync(OffscreenUi::ICON_PLACEMARK, "Bookmark Location", "Name", QString());
- bookmarkName = bookmarkName.trimmed().replace(QRegExp("(\r\n|[\r\n\t\v ])+"), " ");
- if (bookmarkName.length() == 0) {
- return;
- }
+ connect(dlg, &ModalDialogListener::response, this, [=] (QVariant response) {
+ disconnect(dlg, &ModalDialogListener::response, this, nullptr);
+ auto bookmarkName = response.toString();
- auto addressManager = DependencyManager::get();
- QString bookmarkAddress = addressManager->currentAddress().toString();
- Bookmarks::addBookmarkToFile(bookmarkName, bookmarkAddress);
+ bookmarkName = bookmarkName.trimmed().replace(QRegExp("(\r\n|[\r\n\t\v ])+"), " ");
+ if (bookmarkName.length() == 0) {
+ return;
+ }
+
+ auto addressManager = DependencyManager::get();
+ QString bookmarkAddress = addressManager->currentAddress().toString();
+ Bookmarks::addBookmarkToFile(bookmarkName, bookmarkAddress);
+ });
}
void LocationBookmarks::addBookmarkToMenu(Menu* menubar, const QString& name, const QVariant& address) {
@@ -101,4 +102,4 @@ void LocationBookmarks::addBookmarkToMenu(Menu* menubar, const QString& name, co
menubar->addActionToQMenuAndActionHash(_bookmarksMenu, teleportAction, name, 0, QAction::NoRole);
Bookmarks::sortActions(menubar, _bookmarksMenu);
}
-}
\ No newline at end of file
+}
diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp
index 005d478411..9df22ab08e 100644
--- a/interface/src/Menu.cpp
+++ b/interface/src/Menu.cpp
@@ -367,6 +367,20 @@ Menu::Menu() {
QString("../../hifi/tablet/TabletGraphicsPreferences.qml"), "GraphicsPreferencesDialog");
});
+ // Developer > UI >>>
+ MenuWrapper* uiOptionsMenu = developerMenu->addMenu("UI");
+ action = addCheckableActionToQMenuAndActionHash(uiOptionsMenu, MenuOption::DesktopTabletToToolbar, 0,
+ qApp->getDesktopTabletBecomesToolbarSetting());
+ connect(action, &QAction::triggered, [action] {
+ qApp->setDesktopTabletBecomesToolbarSetting(action->isChecked());
+ });
+
+ action = addCheckableActionToQMenuAndActionHash(uiOptionsMenu, MenuOption::HMDTabletToToolbar, 0,
+ qApp->getHmdTabletBecomesToolbarSetting());
+ connect(action, &QAction::triggered, [action] {
+ qApp->setHmdTabletBecomesToolbarSetting(action->isChecked());
+ });
+
// Developer > Render >>>
MenuWrapper* renderOptionsMenu = developerMenu->addMenu("Render");
addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::WorldAxes);
diff --git a/interface/src/Menu.h b/interface/src/Menu.h
index d77c87a6fc..854f8d8c2b 100644
--- a/interface/src/Menu.h
+++ b/interface/src/Menu.h
@@ -200,6 +200,8 @@ namespace MenuOption {
const QString VisibleToFriends = "Friends";
const QString VisibleToNoOne = "No one";
const QString WorldAxes = "World Axes";
+ const QString DesktopTabletToToolbar = "Desktop Tablet Becomes Toolbar";
+ const QString HMDTabletToToolbar = "HMD Tablet Becomes Toolbar";
}
#endif // hifi_Menu_h
diff --git a/interface/src/ModelPackager.cpp b/interface/src/ModelPackager.cpp
index 44768db93c..5f4c7526e0 100644
--- a/interface/src/ModelPackager.cpp
+++ b/interface/src/ModelPackager.cpp
@@ -79,7 +79,7 @@ bool ModelPackager::loadModel() {
if (_modelFile.completeSuffix().contains("fst")) {
QFile fst(_modelFile.filePath());
if (!fst.open(QFile::ReadOnly | QFile::Text)) {
- OffscreenUi::warning(NULL,
+ OffscreenUi::asyncWarning(NULL,
QString("ModelPackager::loadModel()"),
QString("Could not open FST file %1").arg(_modelFile.filePath()),
QMessageBox::Ok);
@@ -98,7 +98,7 @@ bool ModelPackager::loadModel() {
// open the fbx file
QFile fbx(_fbxInfo.filePath());
if (!_fbxInfo.exists() || !_fbxInfo.isFile() || !fbx.open(QIODevice::ReadOnly)) {
- OffscreenUi::warning(NULL,
+ OffscreenUi::asyncWarning(NULL,
QString("ModelPackager::loadModel()"),
QString("Could not open FBX file %1").arg(_fbxInfo.filePath()),
QMessageBox::Ok);
@@ -408,7 +408,7 @@ bool ModelPackager::copyTextures(const QString& oldDir, const QDir& newDir) {
}
if (!errors.isEmpty()) {
- OffscreenUi::warning(nullptr, "ModelPackager::copyTextures()",
+ OffscreenUi::asyncWarning(nullptr, "ModelPackager::copyTextures()",
"Missing textures:" + errors);
qCDebug(interfaceapp) << "ModelPackager::copyTextures():" << errors;
return false;
diff --git a/interface/src/ModelPropertiesDialog.cpp b/interface/src/ModelPropertiesDialog.cpp
index d41a913c95..ae352974ae 100644
--- a/interface/src/ModelPropertiesDialog.cpp
+++ b/interface/src/ModelPropertiesDialog.cpp
@@ -201,7 +201,7 @@ void ModelPropertiesDialog::chooseTextureDirectory() {
return;
}
if (!directory.startsWith(_basePath)) {
- OffscreenUi::warning(NULL, "Invalid texture directory", "Texture directory must be child of base path.");
+ OffscreenUi::asyncWarning(NULL, "Invalid texture directory", "Texture directory must be child of base path.");
return;
}
_textureDirectory->setText(directory.length() == _basePath.length() ? "." : directory.mid(_basePath.length() + 1));
diff --git a/interface/src/assets/ATPAssetMigrator.cpp b/interface/src/assets/ATPAssetMigrator.cpp
index 667c2587b0..8de40865b7 100644
--- a/interface/src/assets/ATPAssetMigrator.cpp
+++ b/interface/src/assets/ATPAssetMigrator.cpp
@@ -42,117 +42,161 @@ static const QString COMPOUND_SHAPE_URL_KEY = "compoundShapeURL";
static const QString MESSAGE_BOX_TITLE = "ATP Asset Migration";
void ATPAssetMigrator::loadEntityServerFile() {
- auto filename = OffscreenUi::getOpenFileName(_dialogParent, tr("Select an entity-server content file to migrate"), QString(), tr("Entity-Server Content (*.gz)"));
-
- if (!filename.isEmpty()) {
- qCDebug(asset_migrator) << "Selected filename for ATP asset migration: " << filename;
-
- static const QString MIGRATION_CONFIRMATION_TEXT {
- "The ATP Asset Migration process will scan the selected entity-server file,\nupload discovered resources to the"\
- " current asset-server\nand then save a new entity-server file with the ATP URLs.\n\nAre you ready to"\
- " continue?\n\nMake sure you are connected to the right domain."
- };
-
- auto button = OffscreenUi::question(_dialogParent, MESSAGE_BOX_TITLE, MIGRATION_CONFIRMATION_TEXT,
- QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
-
- if (button == QMessageBox::No) {
- return;
- }
-
- // try to open the file at the given filename
- QFile modelsFile { filename };
-
- if (modelsFile.open(QIODevice::ReadOnly)) {
- QByteArray compressedJsonData = modelsFile.readAll();
- QByteArray jsonData;
-
- if (!gunzip(compressedJsonData, jsonData)) {
- OffscreenUi::warning(_dialogParent, "Error", "The file at" + filename + "was not in gzip format.");
- }
-
- QJsonDocument modelsJSON = QJsonDocument::fromJson(jsonData);
- _entitiesArray = modelsJSON.object()["Entities"].toArray();
-
- for (auto jsonValue : _entitiesArray) {
- QJsonObject entityObject = jsonValue.toObject();
- QString modelURLString = entityObject.value(MODEL_URL_KEY).toString();
- QString compoundURLString = entityObject.value(COMPOUND_SHAPE_URL_KEY).toString();
+ ModalDialogListener* dlg = OffscreenUi::getOpenFileNameAsync(_dialogParent, tr("Select an entity-server content file to migrate"),
+ QString(), tr("Entity-Server Content (*.gz)"));
- for (int i = 0; i < 2; ++i) {
- bool isModelURL = (i == 0);
- quint8 replacementType = i;
- auto migrationURLString = (isModelURL) ? modelURLString : compoundURLString;
+ connect(dlg, &ModalDialogListener::response, this, [=] (QVariant response) {
+ const QString& filename = response.toString();
+ disconnect(dlg, &ModalDialogListener::response, this, nullptr);
+ if (!filename.isEmpty()) {
+ qCDebug(asset_migrator) << "Selected filename for ATP asset migration: " << filename;
- if (!migrationURLString.isEmpty()) {
- QUrl migrationURL = QUrl(migrationURLString);
+ auto migrateResources = [=](QUrl migrationURL, QJsonValueRef jsonValue, bool isModelURL) {
+ auto request =
+ DependencyManager::get()->createResourceRequest(this, migrationURL);
- if (!_ignoredUrls.contains(migrationURL)
- && (migrationURL.scheme() == URL_SCHEME_HTTP || migrationURL.scheme() == URL_SCHEME_HTTPS
- || migrationURL.scheme() == URL_SCHEME_FILE || migrationURL.scheme() == URL_SCHEME_FTP)) {
+ if (request) {
+ qCDebug(asset_migrator) << "Requesting" << migrationURL << "for ATP asset migration";
- if (_pendingReplacements.contains(migrationURL)) {
- // we already have a request out for this asset, just store the QJsonValueRef
- // so we can do the hash replacement when the request comes back
- _pendingReplacements.insert(migrationURL, { jsonValue, replacementType });
- } else if (_uploadedAssets.contains(migrationURL)) {
- // we already have a hash for this asset
- // so just do the replacement immediately
- if (isModelURL) {
- entityObject[MODEL_URL_KEY] = _uploadedAssets.value(migrationURL).toString();
- } else {
- entityObject[COMPOUND_SHAPE_URL_KEY] = _uploadedAssets.value(migrationURL).toString();
- }
+ // add this combination of QUrl and QJsonValueRef to our multi hash so we can change the URL
+ // to an ATP one once ready
+ _pendingReplacements.insert(migrationURL, { jsonValue, (isModelURL ? 0 : 1)});
- jsonValue = entityObject;
- } else if (wantsToMigrateResource(migrationURL)) {
- auto request =
- DependencyManager::get()->createResourceRequest(this, migrationURL);
+ connect(request, &ResourceRequest::finished, this, [=]() {
+ if (request->getResult() == ResourceRequest::Success) {
+ migrateResource(request);
+ } else {
+ ++_errorCount;
+ _pendingReplacements.remove(migrationURL);
+ qWarning() << "Could not retrieve asset at" << migrationURL.toString();
- if (request) {
- qCDebug(asset_migrator) << "Requesting" << migrationURL << "for ATP asset migration";
+ checkIfFinished();
+ }
+ request->deleteLater();
+ });
- // add this combination of QUrl and QJsonValueRef to our multi hash so we can change the URL
- // to an ATP one once ready
- _pendingReplacements.insert(migrationURL, { jsonValue, (isModelURL ? 0 : 1)});
-
- connect(request, &ResourceRequest::finished, this, [=]() {
- if (request->getResult() == ResourceRequest::Success) {
- migrateResource(request);
- } else {
- ++_errorCount;
- _pendingReplacements.remove(migrationURL);
- qWarning() << "Could not retrieve asset at" << migrationURL.toString();
-
- checkIfFinished();
- }
- request->deleteLater();
- });
-
- request->send();
- } else {
- ++_errorCount;
- qWarning() << "Count not create request for asset at" << migrationURL.toString();
- }
-
- } else {
- _ignoredUrls.insert(migrationURL);
- }
- }
- }
+ request->send();
+ } else {
+ ++_errorCount;
+ qWarning() << "Count not create request for asset at" << migrationURL.toString();
}
- }
-
- _doneReading = true;
+ };
+ static const QString MIGRATION_CONFIRMATION_TEXT {
+ "The ATP Asset Migration process will scan the selected entity-server file,\nupload discovered resources to the"\
+ " current asset-server\nand then save a new entity-server file with the ATP URLs.\n\nAre you ready to"\
+ " continue?\n\nMake sure you are connected to the right domain."
+ };
+ ModalDialogListener* migrationConfirmDialog = OffscreenUi::asyncQuestion(_dialogParent, MESSAGE_BOX_TITLE, MIGRATION_CONFIRMATION_TEXT,
+ QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
+ QObject::connect(migrationConfirmDialog, &ModalDialogListener::response, this, [=] (QVariant answer) {
+ QObject::disconnect(migrationConfirmDialog, &ModalDialogListener::response, this, nullptr);
- checkIfFinished();
-
- } else {
- OffscreenUi::warning(_dialogParent, "Error",
- "There was a problem loading that entity-server file for ATP asset migration. Please try again");
+ if (QMessageBox::Yes == static_cast(answer.toInt())) {
+ // try to open the file at the given filename
+ QFile modelsFile { filename };
+
+ if (modelsFile.open(QIODevice::ReadOnly)) {
+ QByteArray compressedJsonData = modelsFile.readAll();
+ QByteArray jsonData;
+
+ if (!gunzip(compressedJsonData, jsonData)) {
+ OffscreenUi::asyncWarning(_dialogParent, "Error", "The file at" + filename + "was not in gzip format.");
+ }
+
+ QJsonDocument modelsJSON = QJsonDocument::fromJson(jsonData);
+ _entitiesArray = modelsJSON.object()["Entities"].toArray();
+
+ for (auto jsonValue : _entitiesArray) {
+ QJsonObject entityObject = jsonValue.toObject();
+ QString modelURLString = entityObject.value(MODEL_URL_KEY).toString();
+ QString compoundURLString = entityObject.value(COMPOUND_SHAPE_URL_KEY).toString();
+
+ for (int i = 0; i < 2; ++i) {
+ bool isModelURL = (i == 0);
+ quint8 replacementType = i;
+ auto migrationURLString = (isModelURL) ? modelURLString : compoundURLString;
+
+ if (!migrationURLString.isEmpty()) {
+ QUrl migrationURL = QUrl(migrationURLString);
+
+ if (!_ignoredUrls.contains(migrationURL)
+ && (migrationURL.scheme() == URL_SCHEME_HTTP || migrationURL.scheme() == URL_SCHEME_HTTPS
+ || migrationURL.scheme() == URL_SCHEME_FILE || migrationURL.scheme() == URL_SCHEME_FTP)) {
+
+ if (_pendingReplacements.contains(migrationURL)) {
+ // we already have a request out for this asset, just store the QJsonValueRef
+ // so we can do the hash replacement when the request comes back
+ _pendingReplacements.insert(migrationURL, { jsonValue, replacementType });
+ } else if (_uploadedAssets.contains(migrationURL)) {
+ // we already have a hash for this asset
+ // so just do the replacement immediately
+ if (isModelURL) {
+ entityObject[MODEL_URL_KEY] = _uploadedAssets.value(migrationURL).toString();
+ } else {
+ entityObject[COMPOUND_SHAPE_URL_KEY] = _uploadedAssets.value(migrationURL).toString();
+ }
+
+ jsonValue = entityObject;
+ } else {
+
+ static bool hasAskedForCompleteMigration { false };
+ static bool wantsCompleteMigration { false };
+
+ if (!hasAskedForCompleteMigration) {
+ // this is the first resource migration - ask the user if they just want to migrate everything
+ static const QString COMPLETE_MIGRATION_TEXT { "Do you want to migrate all assets found in this entity-server file?\n"\
+ "Select \"Yes\" to upload all discovered assets to the current asset-server immediately.\n"\
+ "Select \"No\" to be prompted for each discovered asset."
+ };
+ ModalDialogListener* migrationConfirmDialog1 = OffscreenUi::asyncQuestion(_dialogParent, MESSAGE_BOX_TITLE,
+ "Would you like to migrate the following resource?\n" + migrationURL.toString(),
+ QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
+
+ QObject::connect(migrationConfirmDialog1, &ModalDialogListener::response, this, [=] (QVariant answer) {
+ QObject::disconnect(migrationConfirmDialog1, &ModalDialogListener::response, this, nullptr);
+ if (static_cast(answer.toInt()) ==
+ QMessageBox::Yes) {
+ wantsCompleteMigration = true;
+ migrateResources(migrationURL, jsonValue, isModelURL);
+ } else {
+ ModalDialogListener* migrationConfirmDialog2 = OffscreenUi::asyncQuestion(_dialogParent, MESSAGE_BOX_TITLE, COMPLETE_MIGRATION_TEXT,
+ QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
+
+ QObject::connect(migrationConfirmDialog2, &ModalDialogListener::response, this, [=] (QVariant answer) {
+ QObject::disconnect(migrationConfirmDialog2, &ModalDialogListener::response, this, nullptr);
+ if (static_cast(answer.toInt()) ==
+ QMessageBox::Yes) {
+ migrateResources(migrationURL, jsonValue, isModelURL);
+ } else {
+ _ignoredUrls.insert(migrationURL);
+ }
+ });
+ }
+ });
+ hasAskedForCompleteMigration = true;
+ }
+ if (wantsCompleteMigration) {
+ migrateResources(migrationURL, jsonValue, isModelURL);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ _doneReading = true;
+
+ checkIfFinished();
+
+ } else {
+ OffscreenUi::asyncWarning(_dialogParent, "Error",
+ "There was a problem loading that entity-server file for ATP asset migration. Please try again");
+ }
+ }
+ });
}
- }
+ });
}
void ATPAssetMigrator::migrateResource(ResourceRequest* request) {
@@ -248,9 +292,6 @@ void ATPAssetMigrator::checkIfFinished() {
// are we out of pending replacements? if so it is time to save the entity-server file
if (_doneReading && _pendingReplacements.empty()) {
saveEntityServerFile();
-
- // reset after the attempted save, success or fail
- reset();
}
}
@@ -288,39 +329,43 @@ bool ATPAssetMigrator::wantsToMigrateResource(const QUrl& url) {
void ATPAssetMigrator::saveEntityServerFile() {
// show a dialog to ask the user where they want to save the file
- QString saveName = OffscreenUi::getSaveFileName(_dialogParent, "Save Migrated Entities File");
-
- QFile saveFile { saveName };
-
- if (saveFile.open(QIODevice::WriteOnly)) {
- QJsonObject rootObject;
- rootObject[ENTITIES_OBJECT_KEY] = _entitiesArray;
-
- QJsonDocument newDocument { rootObject };
- QByteArray jsonDataForFile;
-
- if (gzip(newDocument.toJson(), jsonDataForFile, -1)) {
-
- saveFile.write(jsonDataForFile);
- saveFile.close();
+ ModalDialogListener* dlg = OffscreenUi::getSaveFileNameAsync(_dialogParent, "Save Migrated Entities File");
+ connect(dlg, &ModalDialogListener::response, this, [=] (QVariant response) {
+ const QString& saveName = response.toString();
+ QFile saveFile { saveName };
- QString infoMessage = QString("Your new entities file has been saved at\n%1.").arg(saveName);
+ if (saveFile.open(QIODevice::WriteOnly)) {
+ QJsonObject rootObject;
+ rootObject[ENTITIES_OBJECT_KEY] = _entitiesArray;
- if (_errorCount > 0) {
- infoMessage += QString("\nThere were %1 models that could not be migrated.\n").arg(_errorCount);
- infoMessage += "Check the warnings in your log for details.\n";
- infoMessage += "You can re-attempt migration on those models\nby restarting this process with the newly saved file.";
+ QJsonDocument newDocument { rootObject };
+ QByteArray jsonDataForFile;
+
+ if (gzip(newDocument.toJson(), jsonDataForFile, -1)) {
+
+ saveFile.write(jsonDataForFile);
+ saveFile.close();
+
+ QString infoMessage = QString("Your new entities file has been saved at\n%1.").arg(saveName);
+
+ if (_errorCount > 0) {
+ infoMessage += QString("\nThere were %1 models that could not be migrated.\n").arg(_errorCount);
+ infoMessage += "Check the warnings in your log for details.\n";
+ infoMessage += "You can re-attempt migration on those models\nby restarting this process with the newly saved file.";
+ }
+
+ OffscreenUi::asyncInformation(_dialogParent, "Success", infoMessage);
+ } else {
+ OffscreenUi::asyncWarning(_dialogParent, "Error", "Could not gzip JSON data for new entities file.");
}
- OffscreenUi::information(_dialogParent, "Success", infoMessage);
} else {
- OffscreenUi::warning(_dialogParent, "Error", "Could not gzip JSON data for new entities file.");
+ OffscreenUi::asyncWarning(_dialogParent, "Error",
+ QString("Could not open file at %1 to write new entities file to.").arg(saveName));
}
-
- } else {
- OffscreenUi::warning(_dialogParent, "Error",
- QString("Could not open file at %1 to write new entities file to.").arg(saveName));
- }
+ // reset after the attempted save, success or fail
+ reset();
+ });
}
void ATPAssetMigrator::reset() {
diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp
index e508c972c6..19179d613d 100755
--- a/interface/src/avatar/MyAvatar.cpp
+++ b/interface/src/avatar/MyAvatar.cpp
@@ -3043,9 +3043,9 @@ glm::mat4 MyAvatar::getCenterEyeCalibrationMat() const {
if (rightEyeIndex >= 0 && leftEyeIndex >= 0) {
auto centerEyePos = (getAbsoluteDefaultJointTranslationInObjectFrame(rightEyeIndex) + getAbsoluteDefaultJointTranslationInObjectFrame(leftEyeIndex)) * 0.5f;
auto centerEyeRot = Quaternions::Y_180;
- return createMatFromQuatAndPos(centerEyeRot, centerEyePos);
+ return createMatFromQuatAndPos(centerEyeRot, centerEyePos / getSensorToWorldScale());
} else {
- return createMatFromQuatAndPos(DEFAULT_AVATAR_MIDDLE_EYE_ROT, DEFAULT_AVATAR_MIDDLE_EYE_POS);
+ return createMatFromQuatAndPos(DEFAULT_AVATAR_MIDDLE_EYE_ROT, DEFAULT_AVATAR_MIDDLE_EYE_POS / getSensorToWorldScale());
}
}
@@ -3055,9 +3055,9 @@ glm::mat4 MyAvatar::getHeadCalibrationMat() const {
if (headIndex >= 0) {
auto headPos = getAbsoluteDefaultJointTranslationInObjectFrame(headIndex);
auto headRot = getAbsoluteDefaultJointRotationInObjectFrame(headIndex);
- return createMatFromQuatAndPos(headRot, headPos);
+ return createMatFromQuatAndPos(headRot, headPos / getSensorToWorldScale());
} else {
- return createMatFromQuatAndPos(DEFAULT_AVATAR_HEAD_ROT, DEFAULT_AVATAR_HEAD_POS);
+ return createMatFromQuatAndPos(DEFAULT_AVATAR_HEAD_ROT, DEFAULT_AVATAR_HEAD_POS / getSensorToWorldScale());
}
}
@@ -3067,9 +3067,9 @@ glm::mat4 MyAvatar::getSpine2CalibrationMat() const {
if (spine2Index >= 0) {
auto spine2Pos = getAbsoluteDefaultJointTranslationInObjectFrame(spine2Index);
auto spine2Rot = getAbsoluteDefaultJointRotationInObjectFrame(spine2Index);
- return createMatFromQuatAndPos(spine2Rot, spine2Pos);
+ return createMatFromQuatAndPos(spine2Rot, spine2Pos / getSensorToWorldScale());
} else {
- return createMatFromQuatAndPos(DEFAULT_AVATAR_SPINE2_ROT, DEFAULT_AVATAR_SPINE2_POS);
+ return createMatFromQuatAndPos(DEFAULT_AVATAR_SPINE2_ROT, DEFAULT_AVATAR_SPINE2_POS / getSensorToWorldScale());
}
}
@@ -3079,9 +3079,9 @@ glm::mat4 MyAvatar::getHipsCalibrationMat() const {
if (hipsIndex >= 0) {
auto hipsPos = getAbsoluteDefaultJointTranslationInObjectFrame(hipsIndex);
auto hipsRot = getAbsoluteDefaultJointRotationInObjectFrame(hipsIndex);
- return createMatFromQuatAndPos(hipsRot, hipsPos);
+ return createMatFromQuatAndPos(hipsRot, hipsPos / getSensorToWorldScale());
} else {
- return createMatFromQuatAndPos(DEFAULT_AVATAR_HIPS_ROT, DEFAULT_AVATAR_HIPS_POS);
+ return createMatFromQuatAndPos(DEFAULT_AVATAR_HIPS_ROT, DEFAULT_AVATAR_HIPS_POS / getSensorToWorldScale());
}
}
@@ -3091,9 +3091,9 @@ glm::mat4 MyAvatar::getLeftFootCalibrationMat() const {
if (leftFootIndex >= 0) {
auto leftFootPos = getAbsoluteDefaultJointTranslationInObjectFrame(leftFootIndex);
auto leftFootRot = getAbsoluteDefaultJointRotationInObjectFrame(leftFootIndex);
- return createMatFromQuatAndPos(leftFootRot, leftFootPos);
+ return createMatFromQuatAndPos(leftFootRot, leftFootPos / getSensorToWorldScale());
} else {
- return createMatFromQuatAndPos(DEFAULT_AVATAR_LEFTFOOT_ROT, DEFAULT_AVATAR_LEFTFOOT_POS);
+ return createMatFromQuatAndPos(DEFAULT_AVATAR_LEFTFOOT_ROT, DEFAULT_AVATAR_LEFTFOOT_POS / getSensorToWorldScale());
}
}
@@ -3103,9 +3103,9 @@ glm::mat4 MyAvatar::getRightFootCalibrationMat() const {
if (rightFootIndex >= 0) {
auto rightFootPos = getAbsoluteDefaultJointTranslationInObjectFrame(rightFootIndex);
auto rightFootRot = getAbsoluteDefaultJointRotationInObjectFrame(rightFootIndex);
- return createMatFromQuatAndPos(rightFootRot, rightFootPos);
+ return createMatFromQuatAndPos(rightFootRot, rightFootPos / getSensorToWorldScale());
} else {
- return createMatFromQuatAndPos(DEFAULT_AVATAR_RIGHTFOOT_ROT, DEFAULT_AVATAR_RIGHTFOOT_POS);
+ return createMatFromQuatAndPos(DEFAULT_AVATAR_RIGHTFOOT_ROT, DEFAULT_AVATAR_RIGHTFOOT_POS / getSensorToWorldScale());
}
}
@@ -3115,9 +3115,9 @@ glm::mat4 MyAvatar::getRightArmCalibrationMat() const {
if (rightArmIndex >= 0) {
auto rightArmPos = getAbsoluteDefaultJointTranslationInObjectFrame(rightArmIndex);
auto rightArmRot = getAbsoluteDefaultJointRotationInObjectFrame(rightArmIndex);
- return createMatFromQuatAndPos(rightArmRot, rightArmPos);
+ return createMatFromQuatAndPos(rightArmRot, rightArmPos / getSensorToWorldScale());
} else {
- return createMatFromQuatAndPos(DEFAULT_AVATAR_RIGHTARM_ROT, DEFAULT_AVATAR_RIGHTARM_POS);
+ return createMatFromQuatAndPos(DEFAULT_AVATAR_RIGHTARM_ROT, DEFAULT_AVATAR_RIGHTARM_POS / getSensorToWorldScale());
}
}
@@ -3126,9 +3126,9 @@ glm::mat4 MyAvatar::getLeftArmCalibrationMat() const {
if (leftArmIndex >= 0) {
auto leftArmPos = getAbsoluteDefaultJointTranslationInObjectFrame(leftArmIndex);
auto leftArmRot = getAbsoluteDefaultJointRotationInObjectFrame(leftArmIndex);
- return createMatFromQuatAndPos(leftArmRot, leftArmPos);
+ return createMatFromQuatAndPos(leftArmRot, leftArmPos / getSensorToWorldScale());
} else {
- return createMatFromQuatAndPos(DEFAULT_AVATAR_LEFTARM_ROT, DEFAULT_AVATAR_LEFTARM_POS);
+ return createMatFromQuatAndPos(DEFAULT_AVATAR_LEFTARM_ROT, DEFAULT_AVATAR_LEFTARM_POS / getSensorToWorldScale());
}
}
@@ -3137,9 +3137,9 @@ glm::mat4 MyAvatar::getRightHandCalibrationMat() const {
if (rightHandIndex >= 0) {
auto rightHandPos = getAbsoluteDefaultJointTranslationInObjectFrame(rightHandIndex);
auto rightHandRot = getAbsoluteDefaultJointRotationInObjectFrame(rightHandIndex);
- return createMatFromQuatAndPos(rightHandRot, rightHandPos);
+ return createMatFromQuatAndPos(rightHandRot, rightHandPos / getSensorToWorldScale());
} else {
- return createMatFromQuatAndPos(DEFAULT_AVATAR_RIGHTHAND_ROT, DEFAULT_AVATAR_RIGHTHAND_POS);
+ return createMatFromQuatAndPos(DEFAULT_AVATAR_RIGHTHAND_ROT, DEFAULT_AVATAR_RIGHTHAND_POS / getSensorToWorldScale());
}
}
@@ -3148,9 +3148,9 @@ glm::mat4 MyAvatar::getLeftHandCalibrationMat() const {
if (leftHandIndex >= 0) {
auto leftHandPos = getAbsoluteDefaultJointTranslationInObjectFrame(leftHandIndex);
auto leftHandRot = getAbsoluteDefaultJointRotationInObjectFrame(leftHandIndex);
- return createMatFromQuatAndPos(leftHandRot, leftHandPos);
+ return createMatFromQuatAndPos(leftHandRot, leftHandPos / getSensorToWorldScale());
} else {
- return createMatFromQuatAndPos(DEFAULT_AVATAR_LEFTHAND_ROT, DEFAULT_AVATAR_LEFTHAND_POS);
+ return createMatFromQuatAndPos(DEFAULT_AVATAR_LEFTHAND_ROT, DEFAULT_AVATAR_LEFTHAND_POS / getSensorToWorldScale());
}
}
diff --git a/interface/src/raypick/LaserPointer.cpp b/interface/src/raypick/LaserPointer.cpp
index b696afa8e5..55ddd01123 100644
--- a/interface/src/raypick/LaserPointer.cpp
+++ b/interface/src/raypick/LaserPointer.cpp
@@ -92,8 +92,7 @@ void LaserPointer::updateRenderStateOverlay(const OverlayID& id, const QVariant&
}
}
-void LaserPointer::updateRenderState(const RenderState& renderState, const IntersectionType type, const float distance, const QUuid& objectID, const bool defaultState) {
- PickRay pickRay = qApp->getRayPickManager().getPickRay(_rayPickUID);
+void LaserPointer::updateRenderState(const RenderState& renderState, const IntersectionType type, const float distance, const QUuid& objectID, const PickRay& pickRay, const bool defaultState) {
if (!renderState.getStartID().isNull()) {
QVariantMap startProps;
startProps.insert("position", vec3toVariant(pickRay.origin));
@@ -185,12 +184,14 @@ void LaserPointer::disableRenderState(const RenderState& renderState) {
void LaserPointer::update() {
RayPickResult prevRayPickResult = DependencyManager::get()->getPrevRayPickResult(_rayPickUID);
- if (_renderingEnabled && !_currentRenderState.empty() && _renderStates.find(_currentRenderState) != _renderStates.end() && prevRayPickResult.type != IntersectionType::NONE) {
- updateRenderState(_renderStates[_currentRenderState], prevRayPickResult.type, prevRayPickResult.distance, prevRayPickResult.objectID, false);
+ if (_renderingEnabled && !_currentRenderState.empty() && _renderStates.find(_currentRenderState) != _renderStates.end() &&
+ (prevRayPickResult.type != IntersectionType::NONE || _laserLength > 0.0f || !_objectLockEnd.first.isNull())) {
+ float distance = _laserLength > 0.0f ? _laserLength : prevRayPickResult.distance;
+ updateRenderState(_renderStates[_currentRenderState], prevRayPickResult.type, distance, prevRayPickResult.objectID, prevRayPickResult.searchRay, false);
disableRenderState(_defaultRenderStates[_currentRenderState].second);
} else if (_renderingEnabled && !_currentRenderState.empty() && _defaultRenderStates.find(_currentRenderState) != _defaultRenderStates.end()) {
disableRenderState(_renderStates[_currentRenderState]);
- updateRenderState(_defaultRenderStates[_currentRenderState].second, IntersectionType::NONE, _defaultRenderStates[_currentRenderState].first, QUuid(), true);
+ updateRenderState(_defaultRenderStates[_currentRenderState].second, IntersectionType::NONE, _defaultRenderStates[_currentRenderState].first, QUuid(), prevRayPickResult.searchRay, true);
} else if (!_currentRenderState.empty()) {
disableRenderState(_renderStates[_currentRenderState]);
disableRenderState(_defaultRenderStates[_currentRenderState].second);
diff --git a/interface/src/raypick/LaserPointer.h b/interface/src/raypick/LaserPointer.h
index 23f023cf7a..5467a8233e 100644
--- a/interface/src/raypick/LaserPointer.h
+++ b/interface/src/raypick/LaserPointer.h
@@ -65,6 +65,7 @@ public:
void editRenderState(const std::string& state, const QVariant& startProps, const QVariant& pathProps, const QVariant& endProps);
void setPrecisionPicking(const bool precisionPicking) { DependencyManager::get()->setPrecisionPicking(_rayPickUID, precisionPicking); }
+ void setLaserLength(const float laserLength) { _laserLength = laserLength; }
void setIgnoreEntities(const QScriptValue& ignoreEntities) { DependencyManager::get()->setIgnoreEntities(_rayPickUID, ignoreEntities); }
void setIncludeEntities(const QScriptValue& includeEntities) { DependencyManager::get()->setIncludeEntities(_rayPickUID, includeEntities); }
void setIgnoreOverlays(const QScriptValue& ignoreOverlays) { DependencyManager::get()->setIgnoreOverlays(_rayPickUID, ignoreOverlays); }
@@ -78,6 +79,7 @@ public:
private:
bool _renderingEnabled;
+ float _laserLength { 0.0f };
std::string _currentRenderState { "" };
RenderStateMap _renderStates;
DefaultRenderStateMap _defaultRenderStates;
@@ -89,7 +91,7 @@ private:
QUuid _rayPickUID;
void updateRenderStateOverlay(const OverlayID& id, const QVariant& props);
- void updateRenderState(const RenderState& renderState, const IntersectionType type, const float distance, const QUuid& objectID, const bool defaultState);
+ void updateRenderState(const RenderState& renderState, const IntersectionType type, const float distance, const QUuid& objectID, const PickRay& pickRay, const bool defaultState);
void disableRenderState(const RenderState& renderState);
};
diff --git a/interface/src/raypick/LaserPointerManager.cpp b/interface/src/raypick/LaserPointerManager.cpp
index 1fd0fe9e88..b19ecc14f0 100644
--- a/interface/src/raypick/LaserPointerManager.cpp
+++ b/interface/src/raypick/LaserPointerManager.cpp
@@ -14,17 +14,19 @@ QUuid LaserPointerManager::createLaserPointer(const QVariant& rayProps, const La
const bool faceAvatar, const bool centerEndY, const bool lockEnd, const bool enabled) {
std::shared_ptr laserPointer = std::make_shared(rayProps, renderStates, defaultRenderStates, faceAvatar, centerEndY, lockEnd, enabled);
if (!laserPointer->getRayUID().isNull()) {
- QWriteLocker lock(&_addLock);
+ QWriteLocker containsLock(&_containsLock);
QUuid id = QUuid::createUuid();
- _laserPointersToAdd.push(std::pair>(id, laserPointer));
+ _laserPointers[id] = laserPointer;
+ _laserPointerLocks[id] = std::make_shared();
return id;
}
return QUuid();
}
void LaserPointerManager::removeLaserPointer(const QUuid uid) {
- QWriteLocker lock(&_removeLock);
- _laserPointersToRemove.push(uid);
+ QWriteLocker lock(&_containsLock);
+ _laserPointers.remove(uid);
+ _laserPointerLocks.remove(uid);
}
void LaserPointerManager::enableLaserPointer(const QUuid uid) {
@@ -69,32 +71,12 @@ const RayPickResult LaserPointerManager::getPrevRayPickResult(const QUuid uid) {
}
void LaserPointerManager::update() {
+ QReadLocker lock(&_containsLock);
for (QUuid& uid : _laserPointers.keys()) {
// This only needs to be a read lock because update won't change any of the properties that can be modified from scripts
QReadLocker laserLock(_laserPointerLocks[uid].get());
_laserPointers[uid]->update();
}
-
- QWriteLocker containsLock(&_containsLock);
- {
- QWriteLocker lock(&_addLock);
- while (!_laserPointersToAdd.empty()) {
- std::pair> laserPointerToAdd = _laserPointersToAdd.front();
- _laserPointersToAdd.pop();
- _laserPointers[laserPointerToAdd.first] = laserPointerToAdd.second;
- _laserPointerLocks[laserPointerToAdd.first] = std::make_shared();
- }
- }
-
- {
- QWriteLocker lock(&_removeLock);
- while (!_laserPointersToRemove.empty()) {
- QUuid uid = _laserPointersToRemove.front();
- _laserPointersToRemove.pop();
- _laserPointers.remove(uid);
- _laserPointerLocks.remove(uid);
- }
- }
}
void LaserPointerManager::setPrecisionPicking(QUuid uid, const bool precisionPicking) {
@@ -105,6 +87,14 @@ void LaserPointerManager::setPrecisionPicking(QUuid uid, const bool precisionPic
}
}
+void LaserPointerManager::setLaserLength(QUuid uid, const float laserLength) {
+ QReadLocker lock(&_containsLock);
+ if (_laserPointers.contains(uid)) {
+ QWriteLocker laserLock(_laserPointerLocks[uid].get());
+ _laserPointers[uid]->setLaserLength(laserLength);
+ }
+}
+
void LaserPointerManager::setIgnoreEntities(QUuid uid, const QScriptValue& ignoreEntities) {
QReadLocker lock(&_containsLock);
if (_laserPointers.contains(uid)) {
diff --git a/interface/src/raypick/LaserPointerManager.h b/interface/src/raypick/LaserPointerManager.h
index b573410fe7..6494bb7056 100644
--- a/interface/src/raypick/LaserPointerManager.h
+++ b/interface/src/raypick/LaserPointerManager.h
@@ -32,6 +32,7 @@ public:
const RayPickResult getPrevRayPickResult(const QUuid uid);
void setPrecisionPicking(QUuid uid, const bool precisionPicking);
+ void setLaserLength(QUuid uid, const float laserLength);
void setIgnoreEntities(QUuid uid, const QScriptValue& ignoreEntities);
void setIncludeEntities(QUuid uid, const QScriptValue& includeEntities);
void setIgnoreOverlays(QUuid uid, const QScriptValue& ignoreOverlays);
@@ -46,10 +47,6 @@ public:
private:
QHash> _laserPointers;
QHash> _laserPointerLocks;
- QReadWriteLock _addLock;
- std::queue>> _laserPointersToAdd;
- QReadWriteLock _removeLock;
- std::queue _laserPointersToRemove;
QReadWriteLock _containsLock;
};
diff --git a/interface/src/raypick/LaserPointerScriptingInterface.h b/interface/src/raypick/LaserPointerScriptingInterface.h
index d65eb335b3..2f6da87b5f 100644
--- a/interface/src/raypick/LaserPointerScriptingInterface.h
+++ b/interface/src/raypick/LaserPointerScriptingInterface.h
@@ -31,6 +31,7 @@ public slots:
Q_INVOKABLE RayPickResult getPrevRayPickResult(QUuid uid) { return qApp->getLaserPointerManager().getPrevRayPickResult(uid); }
Q_INVOKABLE void setPrecisionPicking(QUuid uid, const bool precisionPicking) { qApp->getLaserPointerManager().setPrecisionPicking(uid, precisionPicking); }
+ Q_INVOKABLE void setLaserLength(QUuid uid, const float laserLength) { qApp->getLaserPointerManager().setLaserLength(uid, laserLength); }
Q_INVOKABLE void setIgnoreEntities(QUuid uid, const QScriptValue& ignoreEntities) { qApp->getLaserPointerManager().setIgnoreEntities(uid, ignoreEntities); }
Q_INVOKABLE void setIncludeEntities(QUuid uid, const QScriptValue& includeEntities) { qApp->getLaserPointerManager().setIncludeEntities(uid, includeEntities); }
Q_INVOKABLE void setIgnoreOverlays(QUuid uid, const QScriptValue& ignoreOverlays) { qApp->getLaserPointerManager().setIgnoreOverlays(uid, ignoreOverlays); }
diff --git a/interface/src/raypick/RayPick.h b/interface/src/raypick/RayPick.h
index 04045b2116..0686a05718 100644
--- a/interface/src/raypick/RayPick.h
+++ b/interface/src/raypick/RayPick.h
@@ -70,6 +70,9 @@ public:
if (doesPickNonCollidable()) {
toReturn |= getBitMask(PICK_INCLUDE_NONCOLLIDABLE);
}
+ if (doesPickCourse()) {
+ toReturn |= getBitMask(PICK_COURSE);
+ }
return Flags(toReturn);
}
Flags getOverlayFlags() const {
@@ -80,6 +83,9 @@ public:
if (doesPickNonCollidable()) {
toReturn |= getBitMask(PICK_INCLUDE_NONCOLLIDABLE);
}
+ if (doesPickCourse()) {
+ toReturn |= getBitMask(PICK_COURSE);
+ }
return Flags(toReturn);
}
Flags getAvatarFlags() const { return Flags(getBitMask(PICK_AVATARS)); }
diff --git a/interface/src/raypick/RayPickManager.cpp b/interface/src/raypick/RayPickManager.cpp
index 1ec8efc331..bfc6e3fcb2 100644
--- a/interface/src/raypick/RayPickManager.cpp
+++ b/interface/src/raypick/RayPickManager.cpp
@@ -38,11 +38,12 @@ void RayPickManager::cacheResult(const bool intersects, const RayPickResult& res
res = resTemp;
}
} else {
- cache[ray][mask] = RayPickResult();
+ cache[ray][mask] = RayPickResult(res.searchRay);
}
}
void RayPickManager::update() {
+ QReadLocker lock(&_containsLock);
RayPickCache results;
for (auto& uid : _rayPicks.keys()) {
std::shared_ptr rayPick = _rayPicks[uid];
@@ -58,7 +59,7 @@ void RayPickManager::update() {
}
QPair rayKey = QPair(ray.origin, ray.direction);
- RayPickResult res;
+ RayPickResult res = RayPickResult(ray);
if (rayPick->getFilter().doesPickEntities()) {
RayToEntityIntersectionResult entityRes;
@@ -73,7 +74,7 @@ void RayPickManager::update() {
}
if (!fromCache) {
- cacheResult(entityRes.intersects, RayPickResult(IntersectionType::ENTITY, entityRes.entityID, entityRes.distance, entityRes.intersection, entityRes.surfaceNormal),
+ cacheResult(entityRes.intersects, RayPickResult(IntersectionType::ENTITY, entityRes.entityID, entityRes.distance, entityRes.intersection, ray, entityRes.surfaceNormal),
entityMask, res, rayKey, results);
}
}
@@ -91,7 +92,7 @@ void RayPickManager::update() {
}
if (!fromCache) {
- cacheResult(overlayRes.intersects, RayPickResult(IntersectionType::OVERLAY, overlayRes.overlayID, overlayRes.distance, overlayRes.intersection, overlayRes.surfaceNormal),
+ cacheResult(overlayRes.intersects, RayPickResult(IntersectionType::OVERLAY, overlayRes.overlayID, overlayRes.distance, overlayRes.intersection, ray, overlayRes.surfaceNormal),
overlayMask, res, rayKey, results);
}
}
@@ -100,7 +101,7 @@ void RayPickManager::update() {
RayPickFilter::Flags avatarMask = rayPick->getFilter().getAvatarFlags();
if (!checkAndCompareCachedResults(rayKey, results, res, avatarMask)) {
RayToAvatarIntersectionResult avatarRes = DependencyManager::get()->findRayIntersectionVector(ray, rayPick->getIncludeAvatars(), rayPick->getIgnoreAvatars());
- cacheResult(avatarRes.intersects, RayPickResult(IntersectionType::AVATAR, avatarRes.avatarID, avatarRes.distance, avatarRes.intersection), avatarMask, res, rayKey, results);
+ cacheResult(avatarRes.intersects, RayPickResult(IntersectionType::AVATAR, avatarRes.avatarID, avatarRes.distance, avatarRes.intersection, ray), avatarMask, res, rayKey, results);
}
}
@@ -109,7 +110,7 @@ void RayPickManager::update() {
RayPickFilter::Flags hudMask = rayPick->getFilter().getHUDFlags();
if (!checkAndCompareCachedResults(rayKey, results, res, hudMask)) {
glm::vec3 hudRes = DependencyManager::get()->calculateRayUICollisionPoint(ray.origin, ray.direction);
- cacheResult(true, RayPickResult(IntersectionType::HUD, 0, glm::distance(ray.origin, hudRes), hudRes), hudMask, res, rayKey, results);
+ cacheResult(true, RayPickResult(IntersectionType::HUD, 0, glm::distance(ray.origin, hudRes), hudRes, ray), hudMask, res, rayKey, results);
}
}
@@ -117,56 +118,39 @@ void RayPickManager::update() {
if (rayPick->getMaxDistance() == 0.0f || (rayPick->getMaxDistance() > 0.0f && res.distance < rayPick->getMaxDistance())) {
rayPick->setRayPickResult(res);
} else {
- rayPick->setRayPickResult(RayPickResult());
- }
- }
-
- QWriteLocker containsLock(&_containsLock);
- {
- QWriteLocker lock(&_addLock);
- while (!_rayPicksToAdd.empty()) {
- std::pair> rayPickToAdd = _rayPicksToAdd.front();
- _rayPicksToAdd.pop();
- _rayPicks[rayPickToAdd.first] = rayPickToAdd.second;
- _rayPickLocks[rayPickToAdd.first] = std::make_shared();
- }
- }
-
- {
- QWriteLocker lock(&_removeLock);
- while (!_rayPicksToRemove.empty()) {
- QUuid uid = _rayPicksToRemove.front();
- _rayPicksToRemove.pop();
- _rayPicks.remove(uid);
- _rayPickLocks.remove(uid);
+ rayPick->setRayPickResult(RayPickResult(ray));
}
}
}
QUuid RayPickManager::createRayPick(const std::string& jointName, const glm::vec3& posOffset, const glm::vec3& dirOffset, const RayPickFilter& filter, const float maxDistance, const bool enabled) {
- QWriteLocker lock(&_addLock);
+ QWriteLocker lock(&_containsLock);
QUuid id = QUuid::createUuid();
- _rayPicksToAdd.push(std::pair>(id, std::make_shared(jointName, posOffset, dirOffset, filter, maxDistance, enabled)));
+ _rayPicks[id] = std::make_shared(jointName, posOffset, dirOffset, filter, maxDistance, enabled);
+ _rayPickLocks[id] = std::make_shared();
return id;
}
QUuid RayPickManager::createRayPick(const RayPickFilter& filter, const float maxDistance, const bool enabled) {
- QWriteLocker lock(&_addLock);
+ QWriteLocker lock(&_containsLock);
QUuid id = QUuid::createUuid();
- _rayPicksToAdd.push(std::pair>(id, std::make_shared(filter, maxDistance, enabled)));
+ _rayPicks[id] = std::make_shared(filter, maxDistance, enabled);
+ _rayPickLocks[id] = std::make_shared();
return id;
}
QUuid RayPickManager::createRayPick(const glm::vec3& position, const glm::vec3& direction, const RayPickFilter& filter, const float maxDistance, const bool enabled) {
- QWriteLocker lock(&_addLock);
+ QWriteLocker lock(&_containsLock);
QUuid id = QUuid::createUuid();
- _rayPicksToAdd.push(std::pair>(id, std::make_shared(position, direction, filter, maxDistance, enabled)));
+ _rayPicks[id] = std::make_shared(position, direction, filter, maxDistance, enabled);
+ _rayPickLocks[id] = std::make_shared();
return id;
}
void RayPickManager::removeRayPick(const QUuid uid) {
- QWriteLocker lock(&_removeLock);
- _rayPicksToRemove.push(uid);
+ QWriteLocker lock(&_containsLock);
+ _rayPicks.remove(uid);
+ _rayPickLocks.remove(uid);
}
void RayPickManager::enableRayPick(const QUuid uid) {
@@ -185,18 +169,6 @@ void RayPickManager::disableRayPick(const QUuid uid) {
}
}
-const PickRay RayPickManager::getPickRay(const QUuid uid) {
- QReadLocker containsLock(&_containsLock);
- if (_rayPicks.contains(uid)) {
- bool valid;
- PickRay pickRay = _rayPicks[uid]->getPickRay(valid);
- if (valid) {
- return pickRay;
- }
- }
- return PickRay();
-}
-
const RayPickResult RayPickManager::getPrevRayPickResult(const QUuid uid) {
QReadLocker containsLock(&_containsLock);
if (_rayPicks.contains(uid)) {
diff --git a/interface/src/raypick/RayPickManager.h b/interface/src/raypick/RayPickManager.h
index f2b1ff4ae4..9717767f19 100644
--- a/interface/src/raypick/RayPickManager.h
+++ b/interface/src/raypick/RayPickManager.h
@@ -28,7 +28,6 @@ class RayPickManager {
public:
void update();
- const PickRay getPickRay(const QUuid uid);
QUuid createRayPick(const std::string& jointName, const glm::vec3& posOffset, const glm::vec3& dirOffset, const RayPickFilter& filter, const float maxDistance, const bool enabled);
QUuid createRayPick(const RayPickFilter& filter, const float maxDistance, const bool enabled);
@@ -49,10 +48,6 @@ public:
private:
QHash> _rayPicks;
QHash> _rayPickLocks;
- QReadWriteLock _addLock;
- std::queue>> _rayPicksToAdd;
- QReadWriteLock _removeLock;
- std::queue _rayPicksToRemove;
QReadWriteLock _containsLock;
typedef QHash, std::unordered_map> RayPickCache;
diff --git a/interface/src/scripting/WindowScriptingInterface.cpp b/interface/src/scripting/WindowScriptingInterface.cpp
index f63c128cf5..4b981207f1 100644
--- a/interface/src/scripting/WindowScriptingInterface.cpp
+++ b/interface/src/scripting/WindowScriptingInterface.cpp
@@ -59,7 +59,7 @@ WindowScriptingInterface::WindowScriptingInterface() {
QUrl url(urlString);
emit svoImportRequested(url.url());
} else {
- OffscreenUi::warning("Import SVO Error", "You need to be running edit.js to import entities.");
+ OffscreenUi::asyncWarning("Import SVO Error", "You need to be running edit.js to import entities.");
}
});
@@ -103,7 +103,7 @@ void WindowScriptingInterface::raiseMainWindow() {
/// \param const QString& message message to display
/// \return QScriptValue::UndefinedValue
void WindowScriptingInterface::alert(const QString& message) {
- OffscreenUi::warning("", message);
+ OffscreenUi::asyncWarning("", message);
}
/// Display a confirmation box with the options 'Yes' and 'No'
@@ -123,6 +123,17 @@ QScriptValue WindowScriptingInterface::prompt(const QString& message, const QStr
return ok ? QScriptValue(result) : QScriptValue::NullValue;
}
+/// Display a prompt with a text box
+/// \param const QString& message message to display
+/// \param const QString& defaultText default text in the text box
+void WindowScriptingInterface::promptAsync(const QString& message, const QString& defaultText) {
+ ModalDialogListener* dlg = OffscreenUi::getTextAsync(nullptr, "", message, QLineEdit::Normal, defaultText);
+ connect(dlg, &ModalDialogListener::response, this, [=] (QVariant result) {
+ disconnect(dlg, &ModalDialogListener::response, this, nullptr);
+ emit promptTextChanged(result.toString());
+ });
+}
+
CustomPromptResult WindowScriptingInterface::customPrompt(const QVariant& config) {
CustomPromptResult result;
bool ok = false;
@@ -191,8 +202,31 @@ QScriptValue WindowScriptingInterface::browseDir(const QString& title, const QSt
return result.isEmpty() ? QScriptValue::NullValue : QScriptValue(result);
}
-/// Display an open file dialog. If `directory` is an invalid file or directory the browser will start at the current
+/// Display a "browse to directory" dialog. If `directory` is an invalid file or directory the browser will start at the current
/// working directory.
+/// \param const QString& title title of the window
+/// \param const QString& directory directory to start the file browser at
+/// \param const QString& nameFilter filter to filter filenames by - see `QFileDialog`
+void WindowScriptingInterface::browseDirAsync(const QString& title, const QString& directory) {
+ ensureReticleVisible();
+ QString path = directory;
+ if (path.isEmpty()) {
+ path = getPreviousBrowseLocation();
+ }
+#ifndef Q_OS_WIN
+ path = fixupPathForMac(directory);
+#endif
+ ModalDialogListener* dlg = OffscreenUi::getExistingDirectoryAsync(nullptr, title, path);
+ connect(dlg, &ModalDialogListener::response, this, [=] (QVariant response) {
+ const QString& result = response.toString();
+ disconnect(dlg, &ModalDialogListener::response, this, nullptr);
+ if (!result.isEmpty()) {
+ setPreviousBrowseLocation(QFileInfo(result).absolutePath());
+ }
+ emit browseDirChanged(result);
+ });
+}
+
/// \param const QString& title title of the window
/// \param const QString& directory directory to start the file browser at
/// \param const QString& nameFilter filter to filter filenames by - see `QFileDialog`
@@ -213,6 +247,31 @@ QScriptValue WindowScriptingInterface::browse(const QString& title, const QStrin
return result.isEmpty() ? QScriptValue::NullValue : QScriptValue(result);
}
+/// Display an open file dialog. If `directory` is an invalid file or directory the browser will start at the current
+/// working directory.
+/// \param const QString& title title of the window
+/// \param const QString& directory directory to start the file browser at
+/// \param const QString& nameFilter filter to filter filenames by - see `QFileDialog`
+void WindowScriptingInterface::browseAsync(const QString& title, const QString& directory, const QString& nameFilter) {
+ ensureReticleVisible();
+ QString path = directory;
+ if (path.isEmpty()) {
+ path = getPreviousBrowseLocation();
+ }
+#ifndef Q_OS_WIN
+ path = fixupPathForMac(directory);
+#endif
+ ModalDialogListener* dlg = OffscreenUi::getOpenFileNameAsync(nullptr, title, path, nameFilter);
+ connect(dlg, &ModalDialogListener::response, this, [=] (QVariant response) {
+ const QString& result = response.toString();
+ disconnect(dlg, &ModalDialogListener::response, this, nullptr);
+ if (!result.isEmpty()) {
+ setPreviousBrowseLocation(QFileInfo(result).absolutePath());
+ }
+ emit openFileChanged(result);
+ });
+}
+
/// Display a save file dialog. If `directory` is an invalid file or directory the browser will start at the current
/// working directory.
/// \param const QString& title title of the window
@@ -235,7 +294,32 @@ QScriptValue WindowScriptingInterface::save(const QString& title, const QString&
return result.isEmpty() ? QScriptValue::NullValue : QScriptValue(result);
}
-/// Display a select asset dialog that lets the user select an asset from the Asset Server. If `directory` is an invalid
+/// Display a save file dialog. If `directory` is an invalid file or directory the browser will start at the current
+/// working directory.
+/// \param const QString& title title of the window
+/// \param const QString& directory directory to start the file browser at
+/// \param const QString& nameFilter filter to filter filenames by - see `QFileDialog`
+void WindowScriptingInterface::saveAsync(const QString& title, const QString& directory, const QString& nameFilter) {
+ ensureReticleVisible();
+ QString path = directory;
+ if (path.isEmpty()) {
+ path = getPreviousBrowseLocation();
+ }
+#ifndef Q_OS_WIN
+ path = fixupPathForMac(directory);
+#endif
+ ModalDialogListener* dlg = OffscreenUi::getSaveFileNameAsync(nullptr, title, path, nameFilter);
+ connect(dlg, &ModalDialogListener::response, this, [=] (QVariant response) {
+ const QString& result = response.toString();
+ disconnect(dlg, &ModalDialogListener::response, this, nullptr);
+ if (!result.isEmpty()) {
+ setPreviousBrowseLocation(QFileInfo(result).absolutePath());
+ }
+ emit saveFileChanged(result);
+ });
+}
+
+/// Display a select asset dialog that lets the user select an asset from the Asset Server. If `directory` is an invalid
/// directory the browser will start at the root directory.
/// \param const QString& title title of the window
/// \param const QString& directory directory to start the asset browser at
@@ -260,6 +344,35 @@ QScriptValue WindowScriptingInterface::browseAssets(const QString& title, const
return result.isEmpty() ? QScriptValue::NullValue : QScriptValue(result);
}
+/// Display a select asset dialog that lets the user select an asset from the Asset Server. If `directory` is an invalid
+/// directory the browser will start at the root directory.
+/// \param const QString& title title of the window
+/// \param const QString& directory directory to start the asset browser at
+/// \param const QString& nameFilter filter to filter asset names by - see `QFileDialog`
+void WindowScriptingInterface::browseAssetsAsync(const QString& title, const QString& directory, const QString& nameFilter) {
+ ensureReticleVisible();
+ QString path = directory;
+ if (path.isEmpty()) {
+ path = getPreviousBrowseAssetLocation();
+ }
+ if (path.left(1) != "/") {
+ path = "/" + path;
+ }
+ if (path.right(1) != "/") {
+ path = path + "/";
+ }
+
+ ModalDialogListener* dlg = OffscreenUi::getOpenAssetNameAsync(nullptr, title, path, nameFilter);
+ connect(dlg, &ModalDialogListener::response, this, [=] (QVariant response) {
+ const QString& result = response.toString();
+ disconnect(dlg, &ModalDialogListener::response, this, nullptr);
+ if (!result.isEmpty()) {
+ setPreviousBrowseAssetLocation(QFileInfo(result).absolutePath());
+ }
+ emit assetsDirChanged(result);
+ });
+}
+
void WindowScriptingInterface::showAssetServer(const QString& upload) {
QMetaObject::invokeMethod(qApp, "showAssetServerWidget", Qt::QueuedConnection, Q_ARG(QString, upload));
}
diff --git a/interface/src/scripting/WindowScriptingInterface.h b/interface/src/scripting/WindowScriptingInterface.h
index 4b5e2e81fc..0d58e6162d 100644
--- a/interface/src/scripting/WindowScriptingInterface.h
+++ b/interface/src/scripting/WindowScriptingInterface.h
@@ -51,12 +51,17 @@ public slots:
void raiseMainWindow();
void alert(const QString& message = "");
QScriptValue confirm(const QString& message = "");
- QScriptValue prompt(const QString& message = "", const QString& defaultText = "");
+ QScriptValue prompt(const QString& message, const QString& defaultText);
+ void promptAsync(const QString& message = "", const QString& defaultText = "");
CustomPromptResult customPrompt(const QVariant& config);
QScriptValue browseDir(const QString& title = "", const QString& directory = "");
+ void browseDirAsync(const QString& title = "", const QString& directory = "");
QScriptValue browse(const QString& title = "", const QString& directory = "", const QString& nameFilter = "");
+ void browseAsync(const QString& title = "", const QString& directory = "", const QString& nameFilter = "");
QScriptValue save(const QString& title = "", const QString& directory = "", const QString& nameFilter = "");
+ void saveAsync(const QString& title = "", const QString& directory = "", const QString& nameFilter = "");
QScriptValue browseAssets(const QString& title = "", const QString& directory = "", const QString& nameFilter = "");
+ void browseAssetsAsync(const QString& title = "", const QString& directory = "", const QString& nameFilter = "");
void showAssetServer(const QString& upload = "");
QString checkVersion();
void copyToClipboard(const QString& text);
@@ -89,6 +94,11 @@ signals:
void announcement(const QString& message);
void messageBoxClosed(int id, int button);
+ void browseDirChanged(QString browseDir);
+ void assetsDirChanged(QString assetsDir);
+ void saveFileChanged(QString filename);
+ void openFileChanged(QString filename);
+ void promptTextChanged(QString text);
// triggered when window size or position changes
void geometryChanged(QRect geometry);
diff --git a/interface/src/ui/AddressBarDialog.cpp b/interface/src/ui/AddressBarDialog.cpp
index 8aaaac1a57..d7b59ba912 100644
--- a/interface/src/ui/AddressBarDialog.cpp
+++ b/interface/src/ui/AddressBarDialog.cpp
@@ -73,11 +73,11 @@ void AddressBarDialog::loadForward() {
}
void AddressBarDialog::displayAddressOfflineMessage() {
- OffscreenUi::critical("", "That user or place is currently offline");
+ OffscreenUi::asyncCritical("", "That user or place is currently offline");
}
void AddressBarDialog::displayAddressNotFoundMessage() {
- OffscreenUi::critical("", "There is no address information for that user or place");
+ OffscreenUi::asyncCritical("", "There is no address information for that user or place");
}
void AddressBarDialog::observeShownChanged(bool visible) {
diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp
index 9cd00dfdf2..b3bd6fbd34 100644
--- a/interface/src/ui/PreferencesDialog.cpp
+++ b/interface/src/ui/PreferencesDialog.cpp
@@ -91,16 +91,6 @@ void setupPreferences() {
preference->setMax(500);
preferences->addPreference(preference);
}
- {
- auto getter = []()->bool { return qApp->getDesktopTabletBecomesToolbarSetting(); };
- auto setter = [](bool value) { qApp->setDesktopTabletBecomesToolbarSetting(value); };
- preferences->addPreference(new CheckPreference(UI_CATEGORY, "Desktop Tablet Becomes Toolbar", getter, setter));
- }
- {
- auto getter = []()->bool { return qApp->getHmdTabletBecomesToolbarSetting(); };
- auto setter = [](bool value) { qApp->setHmdTabletBecomesToolbarSetting(value); };
- preferences->addPreference(new CheckPreference(UI_CATEGORY, "HMD Tablet Becomes Toolbar", getter, setter));
- }
{
auto getter = []()->bool { return qApp->getPreferAvatarFingerOverStylus(); };
auto setter = [](bool value) { qApp->setPreferAvatarFingerOverStylus(value); };
diff --git a/interface/src/ui/overlays/Base3DOverlay.cpp b/interface/src/ui/overlays/Base3DOverlay.cpp
index 6f55260133..9afab80243 100644
--- a/interface/src/ui/overlays/Base3DOverlay.cpp
+++ b/interface/src/ui/overlays/Base3DOverlay.cpp
@@ -268,18 +268,17 @@ void Base3DOverlay::update(float duration) {
// In Base3DOverlay, if its location or bound changed, the renderTrasnformDirty flag is true.
// then the correct transform used for rendering is computed in the update transaction and assigned.
- // TODO: Fix the value to be computed in main thread now and passed by value to the render item.
- // This is the simplest fix for the web overlay of the tablet for now
if (_renderTransformDirty) {
- _renderTransformDirty = false;
auto itemID = getRenderItemID();
if (render::Item::isValidID(itemID)) {
+ _renderTransformDirty = false;
+ // Capture the render transform value in game loop before
+ auto latestTransform = evalRenderTransform();
render::ScenePointer scene = qApp->getMain3DScene();
render::Transaction transaction;
- transaction.updateItem(itemID, [](Overlay& data) {
+ transaction.updateItem(itemID, [latestTransform](Overlay& data) {
auto overlay3D = dynamic_cast(&data);
if (overlay3D) {
- auto latestTransform = overlay3D->evalRenderTransform();
overlay3D->setRenderTransform(latestTransform);
}
});
@@ -292,7 +291,7 @@ void Base3DOverlay::notifyRenderTransformChange() const {
_renderTransformDirty = true;
}
-Transform Base3DOverlay::evalRenderTransform() const {
+Transform Base3DOverlay::evalRenderTransform() {
return getTransform();
}
diff --git a/interface/src/ui/overlays/Base3DOverlay.h b/interface/src/ui/overlays/Base3DOverlay.h
index 55b55ed16f..93a973e60a 100644
--- a/interface/src/ui/overlays/Base3DOverlay.h
+++ b/interface/src/ui/overlays/Base3DOverlay.h
@@ -72,7 +72,7 @@ protected:
virtual void parentDeleted() override;
mutable Transform _renderTransform;
- virtual Transform evalRenderTransform() const;
+ virtual Transform evalRenderTransform();
virtual void setRenderTransform(const Transform& transform);
const Transform& getRenderTransform() const { return _renderTransform; }
diff --git a/interface/src/ui/overlays/Billboard3DOverlay.cpp b/interface/src/ui/overlays/Billboard3DOverlay.cpp
index f5668caa71..960f0de095 100644
--- a/interface/src/ui/overlays/Billboard3DOverlay.cpp
+++ b/interface/src/ui/overlays/Billboard3DOverlay.cpp
@@ -45,3 +45,14 @@ bool Billboard3DOverlay::applyTransformTo(Transform& transform, bool force) {
}
return transformChanged;
}
+
+Transform Billboard3DOverlay::evalRenderTransform() {
+ Transform transform = getTransform();
+ bool transformChanged = applyTransformTo(transform, true);
+ // If the transform is not modified, setting the transform to
+ // itself will cause drift over time due to floating point errors.
+ if (transformChanged) {
+ setTransform(transform);
+ }
+ return transform;
+}
\ No newline at end of file
diff --git a/interface/src/ui/overlays/Billboard3DOverlay.h b/interface/src/ui/overlays/Billboard3DOverlay.h
index d429537b5b..6b3aa40451 100644
--- a/interface/src/ui/overlays/Billboard3DOverlay.h
+++ b/interface/src/ui/overlays/Billboard3DOverlay.h
@@ -28,6 +28,8 @@ public:
protected:
virtual bool applyTransformTo(Transform& transform, bool force = false) override;
+
+ Transform evalRenderTransform() override;
};
#endif // hifi_Billboard3DOverlay_h
diff --git a/interface/src/ui/overlays/Circle3DOverlay.cpp b/interface/src/ui/overlays/Circle3DOverlay.cpp
index 57911c0786..4e51844d21 100644
--- a/interface/src/ui/overlays/Circle3DOverlay.cpp
+++ b/interface/src/ui/overlays/Circle3DOverlay.cpp
@@ -84,12 +84,7 @@ void Circle3DOverlay::render(RenderArgs* args) {
batch.setPipeline(args->_shapePipeline->pipeline);
}
- // FIXME: THe line width of _lineWidth is not supported anymore, we ll need a workaround
- // FIXME Start using the _renderTransform instead of calling for Transform from here, do the custom things needed in evalRenderTransform()
-
- auto transform = getTransform();
- transform.postScale(glm::vec3(getDimensions(), 1.0f));
- batch.setModelTransform(transform);
+ batch.setModelTransform(getRenderTransform());
// for our overlay, is solid means we draw a ring between the inner and outer radius of the circle, otherwise
// we just draw a line...
diff --git a/interface/src/ui/overlays/Cube3DOverlay.cpp b/interface/src/ui/overlays/Cube3DOverlay.cpp
index ca7355b86f..0ac9dba34b 100644
--- a/interface/src/ui/overlays/Cube3DOverlay.cpp
+++ b/interface/src/ui/overlays/Cube3DOverlay.cpp
@@ -53,18 +53,11 @@ void Cube3DOverlay::render(RenderArgs* args) {
const float MAX_COLOR = 255.0f;
glm::vec4 cubeColor(color.red / MAX_COLOR, color.green / MAX_COLOR, color.blue / MAX_COLOR, alpha);
- // TODO: handle registration point??
- // FIXME Start using the _renderTransform instead of calling for Transform from here, do the custom things needed in evalRenderTransform()
- glm::vec3 position = getPosition();
- glm::vec3 dimensions = getDimensions();
- glm::quat rotation = getRotation();
+
auto batch = args->_batch;
-
if (batch) {
- Transform transform;
- transform.setTranslation(position);
- transform.setRotation(rotation);
+ Transform transform = getRenderTransform();
auto geometryCache = DependencyManager::get();
auto shapePipeline = args->_shapePipeline;
if (!shapePipeline) {
@@ -72,12 +65,12 @@ void Cube3DOverlay::render(RenderArgs* args) {
}
if (_isSolid) {
- transform.setScale(dimensions);
batch->setModelTransform(transform);
geometryCache->renderSolidCubeInstance(args, *batch, cubeColor, shapePipeline);
} else {
geometryCache->bindSimpleProgram(*batch, false, false, false, true, true);
if (getIsDashedLine()) {
+ auto dimensions = transform.getScale();
transform.setScale(1.0f);
batch->setModelTransform(transform);
@@ -108,7 +101,6 @@ void Cube3DOverlay::render(RenderArgs* args) {
geometryCache->renderDashedLine(*batch, bottomRightFar, topRightFar, cubeColor, _geometryIds[11]);
} else {
- transform.setScale(dimensions);
batch->setModelTransform(transform);
geometryCache->renderWireCubeInstance(args, *batch, cubeColor, shapePipeline);
}
@@ -149,3 +141,16 @@ QVariant Cube3DOverlay::getProperty(const QString& property) {
return Volume3DOverlay::getProperty(property);
}
+
+Transform Cube3DOverlay::evalRenderTransform() {
+ // TODO: handle registration point??
+ glm::vec3 position = getPosition();
+ glm::vec3 dimensions = getDimensions();
+ glm::quat rotation = getRotation();
+
+ Transform transform;
+ transform.setScale(dimensions);
+ transform.setTranslation(position);
+ transform.setRotation(rotation);
+ return transform;
+}
diff --git a/interface/src/ui/overlays/Cube3DOverlay.h b/interface/src/ui/overlays/Cube3DOverlay.h
index 9289af4de5..e7b58ad911 100644
--- a/interface/src/ui/overlays/Cube3DOverlay.h
+++ b/interface/src/ui/overlays/Cube3DOverlay.h
@@ -36,6 +36,9 @@ public:
void setProperties(const QVariantMap& properties) override;
QVariant getProperty(const QString& property) override;
+protected:
+ Transform evalRenderTransform() override;
+
private:
float _borderSize;
// edges on a cube
diff --git a/interface/src/ui/overlays/Grid3DOverlay.cpp b/interface/src/ui/overlays/Grid3DOverlay.cpp
index 3172403731..ca275368cb 100644
--- a/interface/src/ui/overlays/Grid3DOverlay.cpp
+++ b/interface/src/ui/overlays/Grid3DOverlay.cpp
@@ -79,10 +79,7 @@ void Grid3DOverlay::render(RenderArgs* args) {
position += glm::vec3(cameraPosition.x, 0.0f, cameraPosition.z);
}
- // FIXME Start using the _renderTransform instead of calling for Transform from here, do the custom things needed in evalRenderTransform()
- Transform transform;
- transform.setRotation(getRotation());
- transform.setScale(glm::vec3(getDimensions(), 1.0f));
+ Transform transform = getRenderTransform();
transform.setTranslation(position);
batch->setModelTransform(transform);
const float MINOR_GRID_EDGE = 0.0025f;
@@ -146,3 +143,10 @@ void Grid3DOverlay::updateGrid() {
_minorGridRowDivisions = getDimensions().x / _minorGridEvery;
_minorGridColDivisions = getDimensions().y / _minorGridEvery;
}
+
+Transform Grid3DOverlay::evalRenderTransform() {
+ Transform transform;
+ transform.setRotation(getRotation());
+ transform.setScale(glm::vec3(getDimensions(), 1.0f));
+ return transform;
+}
diff --git a/interface/src/ui/overlays/Grid3DOverlay.h b/interface/src/ui/overlays/Grid3DOverlay.h
index 0d042af6ca..5a67b21e07 100644
--- a/interface/src/ui/overlays/Grid3DOverlay.h
+++ b/interface/src/ui/overlays/Grid3DOverlay.h
@@ -37,6 +37,9 @@ public:
// Grids are UI tools, and may not be intersected (pickable)
virtual bool findRayIntersection(const glm::vec3&, const glm::vec3&, float&, BoxFace&, glm::vec3&) override { return false; }
+protected:
+ Transform evalRenderTransform() override;
+
private:
void updateGrid();
diff --git a/interface/src/ui/overlays/Image3DOverlay.cpp b/interface/src/ui/overlays/Image3DOverlay.cpp
index c79d363811..998cc312eb 100644
--- a/interface/src/ui/overlays/Image3DOverlay.cpp
+++ b/interface/src/ui/overlays/Image3DOverlay.cpp
@@ -58,6 +58,7 @@ void Image3DOverlay::update(float deltatime) {
setTransform(transform);
}
#endif
+ Parent::update(deltatime);
}
void Image3DOverlay::render(RenderArgs* args) {
@@ -116,18 +117,8 @@ void Image3DOverlay::render(RenderArgs* args) {
const float MAX_COLOR = 255.0f;
xColor color = getColor();
float alpha = getAlpha();
-
- // FIXME Start using the _renderTransform instead of calling for Transform from here, do the custom things needed in evalRenderTransform()
- Transform transform = getTransform();
- bool transformChanged = applyTransformTo(transform, true);
- // If the transform is not modified, setting the transform to
- // itself will cause drift over time due to floating point errors.
- if (transformChanged) {
- setTransform(transform);
- }
- transform.postScale(glm::vec3(getDimensions(), 1.0f));
- batch->setModelTransform(transform);
+ batch->setModelTransform(getRenderTransform());
batch->setResourceTexture(0, _texture->getGPUTexture());
DependencyManager::get()->renderQuad(
@@ -249,3 +240,9 @@ bool Image3DOverlay::findRayIntersection(const glm::vec3& origin, const glm::vec
Image3DOverlay* Image3DOverlay::createClone() const {
return new Image3DOverlay(this);
}
+
+Transform Image3DOverlay::evalRenderTransform() {
+ auto transform = Parent::evalRenderTransform();
+ transform.postScale(glm::vec3(getDimensions(), 1.0f));
+ return transform;
+}
diff --git a/interface/src/ui/overlays/Image3DOverlay.h b/interface/src/ui/overlays/Image3DOverlay.h
index 4f813e7368..aa802a82a9 100644
--- a/interface/src/ui/overlays/Image3DOverlay.h
+++ b/interface/src/ui/overlays/Image3DOverlay.h
@@ -19,6 +19,7 @@
class Image3DOverlay : public Billboard3DOverlay {
Q_OBJECT
+ using Parent = Billboard3DOverlay;
public:
static QString const TYPE;
@@ -46,6 +47,9 @@ public:
virtual Image3DOverlay* createClone() const override;
+protected:
+ Transform evalRenderTransform() override;
+
private:
QString _url;
NetworkTexturePointer _texture;
diff --git a/interface/src/ui/overlays/Line3DOverlay.cpp b/interface/src/ui/overlays/Line3DOverlay.cpp
index 534261c839..87021cf852 100644
--- a/interface/src/ui/overlays/Line3DOverlay.cpp
+++ b/interface/src/ui/overlays/Line3DOverlay.cpp
@@ -132,10 +132,10 @@ void Line3DOverlay::render(RenderArgs* args) {
glm::vec4 colorv4(color.red / MAX_COLOR, color.green / MAX_COLOR, color.blue / MAX_COLOR, alpha);
auto batch = args->_batch;
if (batch) {
- // FIXME Start using the _renderTransform instead of calling for Transform and start and end from here, do the custom things needed in evalRenderTransform()
batch->setModelTransform(Transform());
- glm::vec3 start = getStart();
- glm::vec3 end = getEnd();
+ auto& renderTransform = getRenderTransform();
+ glm::vec3 start = renderTransform.getTranslation();
+ glm::vec3 end = renderTransform.transform(vec3(0.0, 0.0, -1.0));
auto geometryCache = DependencyManager::get();
if (getIsDashedLine()) {
@@ -268,3 +268,21 @@ QVariant Line3DOverlay::getProperty(const QString& property) {
Line3DOverlay* Line3DOverlay::createClone() const {
return new Line3DOverlay(this);
}
+
+Transform Line3DOverlay::evalRenderTransform() {
+ // Capture start and endin the renderTransform:
+ // start is the origin
+ // end is at the tip of the front axis aka -Z
+ Transform transform;
+ transform.setTranslation( getStart());
+ auto endPos = getEnd();
+
+ auto vec = endPos - transform.getTranslation();
+ auto scale = glm::length(vec);
+ auto dir = vec / scale;
+ auto orientation = glm::rotation(glm::vec3(0,0,-1), dir);
+ transform.setRotation(orientation);
+ transform.setScale(scale);
+
+ return transform;
+}
diff --git a/interface/src/ui/overlays/Line3DOverlay.h b/interface/src/ui/overlays/Line3DOverlay.h
index 9abc2f1a8d..bcb65b1f1e 100644
--- a/interface/src/ui/overlays/Line3DOverlay.h
+++ b/interface/src/ui/overlays/Line3DOverlay.h
@@ -15,6 +15,7 @@
class Line3DOverlay : public Base3DOverlay {
Q_OBJECT
+ using Parent = Base3DOverlay;
public:
static QString const TYPE;
@@ -56,6 +57,9 @@ public:
QUuid getEndParentID() const { return _endParentID; }
quint16 getEndJointIndex() const { return _endParentJointIndex; }
+protected:
+ Transform evalRenderTransform() override;
+
private:
QUuid _endParentID;
quint16 _endParentJointIndex { INVALID_JOINT_INDEX };
diff --git a/interface/src/ui/overlays/ModelOverlay.cpp b/interface/src/ui/overlays/ModelOverlay.cpp
index e2a7df7ae6..ca5ca54144 100644
--- a/interface/src/ui/overlays/ModelOverlay.cpp
+++ b/interface/src/ui/overlays/ModelOverlay.cpp
@@ -46,10 +46,7 @@ void ModelOverlay::update(float deltatime) {
if (_updateModel) {
_updateModel = false;
_model->setSnapModelToCenter(true);
- Transform transform = getTransform();
-#ifndef USE_SN_SCALE
- transform.setScale(1.0f); // disable inherited scale
-#endif
+ Transform transform = evalRenderTransform();
if (_scaleToFit) {
_model->setScaleToFit(true, transform.getScale() * getDimensions());
} else {
@@ -282,6 +279,12 @@ ModelOverlay* ModelOverlay::createClone() const {
return new ModelOverlay(this);
}
+Transform ModelOverlay::evalRenderTransform() {
+ Transform transform = getTransform();
+ transform.setScale(1.0f); // disable inherited scale
+ return transform;
+}
+
void ModelOverlay::locationChanged(bool tellPhysics) {
Base3DOverlay::locationChanged(tellPhysics);
diff --git a/interface/src/ui/overlays/ModelOverlay.h b/interface/src/ui/overlays/ModelOverlay.h
index 59548dfe62..8d8429b29e 100644
--- a/interface/src/ui/overlays/ModelOverlay.h
+++ b/interface/src/ui/overlays/ModelOverlay.h
@@ -46,6 +46,8 @@ public:
float getLoadPriority() const { return _loadPriority; }
protected:
+ Transform evalRenderTransform() override;
+
// helper to extract metadata from our Model's rigged joints
template using mapFunction = std::function