mirror of
https://github.com/JulianGro/overte.git
synced 2025-04-09 17:53:43 +02:00
Merge pull request #14803 from highfidelity/feature/quest
Case 20624: Final merge of Quest Interface application into master
This commit is contained in:
commit
4dbae787cb
51 changed files with 864 additions and 212 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -24,6 +24,7 @@ android/**/bin
|
|||
android/**/src/main/res/values/libs.xml
|
||||
android/**/src/main/assets
|
||||
android/**/gradle*
|
||||
*.class
|
||||
|
||||
# VSCode
|
||||
# List taken from Github Global Ignores master@435c4d92
|
||||
|
|
65
BUILD_QUEST.md
Normal file
65
BUILD_QUEST.md
Normal file
|
@ -0,0 +1,65 @@
|
|||
Please read the [general build guide](BUILD.md) for information on building other platform. Only Quest specific instructions are found in this file.
|
||||
|
||||
# Dependencies
|
||||
|
||||
Building is currently supported on OSX, Windows and Linux platforms, but developers intending to do work on the library dependencies are strongly urged to use 64 bit Linux as a build platform
|
||||
|
||||
You will need the following tools to build Android targets.
|
||||
|
||||
* [Android Studio](https://developer.android.com/studio/index.html)
|
||||
|
||||
### Android Studio
|
||||
|
||||
Download the Android Studio installer and run it. Once installed, at the welcome screen, click configure in the lower right corner and select SDK manager
|
||||
|
||||
From the SDK Platforms tab, select API levels 24 and 26.
|
||||
|
||||
From the SDK Tools tab select the following
|
||||
|
||||
* Android SDK Build-Tools
|
||||
* GPU Debugging Tools
|
||||
* CMake (even if you have a separate CMake installation)
|
||||
* LLDB
|
||||
* Android SDK Platform-Tools
|
||||
* Android SDK Tools
|
||||
* NDK (even if you have the NDK installed separately)
|
||||
|
||||
Make sure the NDK installed version is 18 (or higher)
|
||||
|
||||
# Environment
|
||||
|
||||
Setting up the environment for android builds requires some additional steps
|
||||
|
||||
#### Set up machine specific Gradle properties
|
||||
|
||||
Create a `gradle.properties` file in $HOME/.gradle. Edit the file to contain the following
|
||||
|
||||
HIFI_ANDROID_PRECOMPILED=<your_home_directory>/Android/hifi_externals
|
||||
HIFI_ANDROID_KEYSTORE=<key_store_directory>/<keystore_name>.jks
|
||||
HIFI_ANDROID_KEYSTORE_PASSWORD=<password>
|
||||
HIFI_ANDROID_KEY_ALIAS=<key_alias>
|
||||
HIFI_ANDROID_KEY_PASSWORD=<key_password>
|
||||
|
||||
Note, do not use `$HOME` for the path. It must be a fully qualified path name.
|
||||
|
||||
### Setup the repository
|
||||
|
||||
Clone the repository
|
||||
|
||||
`git clone https://github.com/highfidelity/hifi.git`
|
||||
|
||||
Enter the repository `android` directory
|
||||
|
||||
`cd hifi/android`
|
||||
|
||||
# Building & Running
|
||||
|
||||
* Open Android Studio
|
||||
* Choose _Open Existing Android Studio Project_
|
||||
* Navigate to the `hifi` repository and choose the `android` folder and select _OK_
|
||||
* Open Gradle.settings and comment out any projects not necessary
|
||||
* From _File_ menu select _Sync with File System_ to resync Gradle settings
|
||||
* From the _Build_ menu select _Make Project_
|
||||
* From
|
||||
* Once the build completes, from the _Run_ menu select _Run App_
|
||||
|
|
@ -100,6 +100,13 @@ if (ANDROID)
|
|||
add_definitions(-DCUSTOM_DISPLAY_PLUGINS)
|
||||
set(PLATFORM_PLUGIN_LIBRARIES oculusMobile oculusMobilePlugin)
|
||||
endif()
|
||||
|
||||
# Allow client code to use preprocessor macros to distinguish between quest and non-quest builds
|
||||
if (${HIFI_ANDROID_APP} STREQUAL "questInterface")
|
||||
add_definitions(-DANDROID_APP_QUEST_INTERFACE)
|
||||
elseif(${HIFI_ANDROID_APP} STREQUAL "interface")
|
||||
add_definitions(-DANDROID_APP_INTERFACE)
|
||||
endif()
|
||||
else ()
|
||||
set(PLATFORM_QT_COMPONENTS WebEngine Xml)
|
||||
endif ()
|
||||
|
|
|
@ -81,6 +81,7 @@ public class InterfaceActivity extends QtActivity implements WebViewFragment.OnW
|
|||
private boolean nativeEnterBackgroundCallEnqueued = false;
|
||||
private SlidingDrawer mWebSlidingDrawer;
|
||||
private boolean mStartInDomain;
|
||||
private boolean isLoading;
|
||||
// private GvrApi gvrApi;
|
||||
// Opaque native pointer to the Application C++ object.
|
||||
// This object is owned by the InterfaceActivity instance and passed to the native methods.
|
||||
|
@ -94,7 +95,7 @@ public class InterfaceActivity extends QtActivity implements WebViewFragment.OnW
|
|||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.isLoading = true;
|
||||
isLoading = true;
|
||||
Intent intent = getIntent();
|
||||
if (intent.hasExtra(DOMAIN_URL) && !TextUtils.isEmpty(intent.getStringExtra(DOMAIN_URL))) {
|
||||
intent.putExtra("applicationArguments", "--url " + intent.getStringExtra(DOMAIN_URL));
|
||||
|
@ -145,7 +146,7 @@ public class InterfaceActivity extends QtActivity implements WebViewFragment.OnW
|
|||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
if (super.isLoading) {
|
||||
if (isLoading) {
|
||||
nativeEnterBackgroundCallEnqueued = true;
|
||||
} else {
|
||||
nativeEnterBackground();
|
||||
|
@ -172,7 +173,6 @@ public class InterfaceActivity extends QtActivity implements WebViewFragment.OnW
|
|||
super.onResume();
|
||||
nativeEnterForeground();
|
||||
surfacesWorkaround();
|
||||
keepInterfaceRunning = false;
|
||||
registerReceiver(headsetStateReceiver, new IntentFilter(Intent.ACTION_HEADSET_PLUG));
|
||||
//gvrApi.resumeTracking();
|
||||
}
|
||||
|
@ -382,7 +382,7 @@ public class InterfaceActivity extends QtActivity implements WebViewFragment.OnW
|
|||
}
|
||||
|
||||
public void onAppLoadedComplete() {
|
||||
super.isLoading = false;
|
||||
isLoading = false;
|
||||
if (nativeEnterBackgroundCallEnqueued) {
|
||||
nativeEnterBackground();
|
||||
}
|
||||
|
@ -413,7 +413,6 @@ public class InterfaceActivity extends QtActivity implements WebViewFragment.OnW
|
|||
|
||||
@Override
|
||||
public void onExpand() {
|
||||
keepInterfaceRunning = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
set(TARGET_NAME questFramePlayer)
|
||||
setup_hifi_library(AndroidExtras)
|
||||
link_hifi_libraries(shared ktx shaders gpu gl oculusMobile ${PLATFORM_GL_BACKEND})
|
||||
target_include_directories(${TARGET_NAME} PRIVATE ${HIFI_ANDROID_PRECOMPILED}/ovr/VrApi/Include)
|
||||
|
||||
target_link_libraries(${TARGET_NAME} android log m)
|
||||
target_opengl()
|
||||
target_oculus_mobile()
|
||||
|
|
|
@ -19,24 +19,6 @@
|
|||
android:name="org.qtproject.qt5.android.bindings.QtApplication"
|
||||
tools:ignore="GoogleAppIndexingWarning,MissingApplicationIcon">
|
||||
<meta-data android:name="com.samsung.android.vr.application.mode" android:value="vr_only"/>
|
||||
<activity
|
||||
android:name=".QuestQtActivity"
|
||||
android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen"
|
||||
android:launchMode="singleTask"
|
||||
android:label="@string/app_name"
|
||||
android:screenOrientation="landscape"
|
||||
android:excludeFromRecents="false"
|
||||
android:alwaysRetainTaskState="true"
|
||||
android:configChanges="screenSize|screenLayout|orientation|keyboardHidden|keyboard|navigation|uiMode"
|
||||
>
|
||||
<!-- JNI nonsense -->
|
||||
<meta-data android:name="android.app.lib_name" android:value="questFramePlayer"/>
|
||||
<!-- Qt nonsense -->
|
||||
<meta-data android:name="android.app.qt_libs_resource_id" android:resource="@array/qt_libs"/>
|
||||
<meta-data android:name="android.app.bundled_in_lib_resource_id" android:resource="@array/bundled_in_lib"/>
|
||||
<meta-data android:name="android.app.bundled_in_assets_resource_id" android:resource="@array/bundled_in_assets"/>
|
||||
<meta-data android:name="android.app.load_local_libs" android:value="plugins/platforms/android/libqtforandroid.so:plugins/bearer/libqandroidbearer.so:lib/libQt5QuickParticles.so"/>
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen"
|
||||
|
@ -50,6 +32,13 @@
|
|||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
<!-- JNI nonsense -->
|
||||
<meta-data android:name="android.app.lib_name" android:value="questFramePlayer"/>
|
||||
<!-- Qt nonsense -->
|
||||
<meta-data android:name="android.app.qt_libs_resource_id" android:resource="@array/qt_libs"/>
|
||||
<meta-data android:name="android.app.bundled_in_lib_resource_id" android:resource="@array/bundled_in_lib"/>
|
||||
<meta-data android:name="android.app.bundled_in_assets_resource_id" android:resource="@array/bundled_in_assets"/>
|
||||
<meta-data android:name="android.app.load_local_libs" android:value="plugins/platforms/android/libqtforandroid.so:plugins/bearer/libqandroidbearer.so:lib/libQt5QuickParticles.so"/>
|
||||
</activity>
|
||||
</application>
|
||||
</manifest>
|
||||
|
|
30
android/apps/questFramePlayer/src/main/cpp/AndroidHelper.cpp
Normal file
30
android/apps/questFramePlayer/src/main/cpp/AndroidHelper.cpp
Normal file
|
@ -0,0 +1,30 @@
|
|||
//
|
||||
// Created by Bradley Austin Davis on 2019/02/15
|
||||
// Copyright 2013-2019 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
#include "AndroidHelper.h"
|
||||
|
||||
#include <QtCore/QDebug>
|
||||
#include <QtGui/QGuiApplication>
|
||||
|
||||
AndroidHelper::AndroidHelper() {
|
||||
}
|
||||
|
||||
AndroidHelper::~AndroidHelper() {
|
||||
}
|
||||
|
||||
void AndroidHelper::notifyLoadComplete() {
|
||||
emit qtAppLoadComplete();
|
||||
}
|
||||
|
||||
void AndroidHelper::notifyEnterForeground() {
|
||||
emit enterForeground();
|
||||
}
|
||||
|
||||
void AndroidHelper::notifyEnterBackground() {
|
||||
emit enterBackground();
|
||||
}
|
||||
|
43
android/apps/questFramePlayer/src/main/cpp/AndroidHelper.h
Normal file
43
android/apps/questFramePlayer/src/main/cpp/AndroidHelper.h
Normal file
|
@ -0,0 +1,43 @@
|
|||
//
|
||||
// Created by Bradley Austin Davis on 2019/02/15
|
||||
// Copyright 2013-2019 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#ifndef hifi_Android_Helper_h
|
||||
#define hifi_Android_Helper_h
|
||||
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QMap>
|
||||
#include <QtCore/QUrl>
|
||||
#include <QtCore/QEventLoop>
|
||||
|
||||
class AndroidHelper : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
AndroidHelper(AndroidHelper const&) = delete;
|
||||
void operator=(AndroidHelper const&) = delete;
|
||||
|
||||
static AndroidHelper& instance() {
|
||||
static AndroidHelper instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
void notifyLoadComplete();
|
||||
void notifyEnterForeground();
|
||||
void notifyEnterBackground();
|
||||
|
||||
|
||||
signals:
|
||||
void qtAppLoadComplete();
|
||||
void enterForeground();
|
||||
void enterBackground();
|
||||
|
||||
private:
|
||||
AndroidHelper();
|
||||
~AndroidHelper();
|
||||
};
|
||||
|
||||
#endif
|
|
@ -11,15 +11,11 @@
|
|||
#include <QtWidgets/QFileDialog>
|
||||
|
||||
PlayerWindow::PlayerWindow() {
|
||||
installEventFilter(this);
|
||||
setFlags(Qt::MSWindowsOwnDC | Qt::Window | Qt::Dialog | Qt::WindowMinMaxButtonsHint | Qt::WindowTitleHint);
|
||||
setFlags(Qt::Window);
|
||||
setSurfaceType(QSurface::OpenGLSurface);
|
||||
create();
|
||||
showFullScreen();
|
||||
// Ensure the window is visible and the GL context is valid
|
||||
QCoreApplication::processEvents();
|
||||
_renderThread.initialize(this);
|
||||
}
|
||||
|
||||
PlayerWindow::~PlayerWindow() {
|
||||
_renderThread.initialize();
|
||||
}
|
||||
|
|
|
@ -8,22 +8,13 @@
|
|||
|
||||
#pragma once
|
||||
#include <QtGui/QWindow>
|
||||
#include <QtCore/QSettings>
|
||||
|
||||
#include <gpu/Forward.h>
|
||||
#include "RenderThread.h"
|
||||
|
||||
// Create a simple OpenGL window that renders text in various ways
|
||||
class PlayerWindow : public QWindow {
|
||||
public:
|
||||
PlayerWindow();
|
||||
virtual ~PlayerWindow();
|
||||
|
||||
protected:
|
||||
//bool eventFilter(QObject* obj, QEvent* event) override;
|
||||
//void keyPressEvent(QKeyEvent* event) override;
|
||||
virtual ~PlayerWindow() {}
|
||||
|
||||
private:
|
||||
QSettings _settings;
|
||||
RenderThread _renderThread;
|
||||
};
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include <QtCore/QFileInfo>
|
||||
#include <QtGui/QWindow>
|
||||
#include <QtGui/QImageReader>
|
||||
#include <QtAndroidExtras/QAndroidJniObject>
|
||||
|
||||
#include <gl/QOpenGLContextWrapper.h>
|
||||
#include <gpu/FrameIO.h>
|
||||
|
@ -29,9 +30,7 @@
|
|||
#include <VrApi.h>
|
||||
#include <VrApi_Input.h>
|
||||
|
||||
static JNIEnv* _env { nullptr };
|
||||
static JavaVM* _vm { nullptr };
|
||||
static jobject _activity { nullptr };
|
||||
#include "AndroidHelper.h"
|
||||
|
||||
struct HandController{
|
||||
ovrInputTrackedRemoteCapabilities caps {};
|
||||
|
@ -48,21 +47,43 @@ struct HandController{
|
|||
};
|
||||
|
||||
std::vector<HandController> devices;
|
||||
QAndroidJniObject __interfaceActivity;
|
||||
|
||||
extern "C" {
|
||||
|
||||
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *, void *) {
|
||||
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void *) {
|
||||
__android_log_write(ANDROID_LOG_WARN, "QQQ", __FUNCTION__);
|
||||
return JNI_VERSION_1_6;
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_io_highfidelity_oculus_OculusMobileActivity_questNativeOnCreate(JNIEnv *env, jobject obj) {
|
||||
__android_log_print(ANDROID_LOG_INFO, "QQQ", __FUNCTION__);
|
||||
__interfaceActivity = QAndroidJniObject(obj);
|
||||
QObject::connect(&AndroidHelper::instance(), &AndroidHelper::qtAppLoadComplete, []() {
|
||||
__interfaceActivity.callMethod<void>("onAppLoadedComplete", "()V");
|
||||
QObject::disconnect(&AndroidHelper::instance(), &AndroidHelper::qtAppLoadComplete, nullptr, nullptr);
|
||||
});
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_io_highfidelity_frameplayer_QuestQtActivity_nativeOnCreate(JNIEnv* env, jobject obj) {
|
||||
env->GetJavaVM(&_vm);
|
||||
_activity = env->NewGlobalRef(obj);
|
||||
JNIEXPORT void
|
||||
Java_io_highfidelity_oculus_OculusMobileActivity_questOnAppAfterLoad(JNIEnv *env, jobject obj) {
|
||||
AndroidHelper::instance().moveToThread(qApp->thread());
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_io_highfidelity_oculus_OculusMobileActivity_questNativeOnPause(JNIEnv *env, jobject obj) {
|
||||
AndroidHelper::instance().notifyEnterBackground();
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_io_highfidelity_oculus_OculusMobileActivity_questNativeOnResume(JNIEnv *env, jobject obj) {
|
||||
AndroidHelper::instance().notifyEnterForeground();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
static const char* FRAME_FILE = "assets:/frames/20190121_1220.json";
|
||||
|
||||
static void textureLoader(const std::string& filename, const gpu::TexturePointer& texture, uint16_t layer) {
|
||||
|
@ -84,11 +105,10 @@ void RenderThread::move(const glm::vec3& v) {
|
|||
_correction = glm::inverse(glm::translate(mat4(), v)) * _correction;
|
||||
}
|
||||
|
||||
void RenderThread::initialize(QWindow* window) {
|
||||
void RenderThread::initialize() {
|
||||
std::unique_lock<std::mutex> lock(_frameLock);
|
||||
setObjectName("RenderThread");
|
||||
Parent::initialize();
|
||||
_window = window;
|
||||
_thread->setObjectName("RenderThread");
|
||||
}
|
||||
|
||||
|
@ -96,14 +116,7 @@ void RenderThread::setup() {
|
|||
// Wait until the context has been moved to this thread
|
||||
{ std::unique_lock<std::mutex> lock(_frameLock); }
|
||||
|
||||
|
||||
ovr::VrHandler::initVr();
|
||||
__android_log_write(ANDROID_LOG_WARN, "QQQ", "Launching oculus activity");
|
||||
_vm->AttachCurrentThread(&_env, nullptr);
|
||||
jclass cls = _env->GetObjectClass(_activity);
|
||||
jmethodID mid = _env->GetMethodID(cls, "launchOculusActivity", "()V");
|
||||
_env->CallVoidMethod(_activity, mid);
|
||||
__android_log_write(ANDROID_LOG_WARN, "QQQ", "Launching oculus activity done");
|
||||
ovr::VrHandler::setHandler(this);
|
||||
|
||||
makeCurrent();
|
||||
|
@ -169,7 +182,6 @@ void RenderThread::handleInput() {
|
|||
const auto &remote = controller.state;
|
||||
if (remote.Joystick.x != 0.0f || remote.Joystick.y != 0.0f) {
|
||||
glm::vec3 translation;
|
||||
float rotation = 0.0f;
|
||||
if (caps.ControllerCapabilities & ovrControllerCaps_LeftHand) {
|
||||
translation = glm::vec3{0.0f, -remote.Joystick.y, 0.0f};
|
||||
} else {
|
||||
|
|
|
@ -20,11 +20,9 @@
|
|||
class RenderThread : public GenericThread, ovr::VrHandler {
|
||||
using Parent = GenericThread;
|
||||
public:
|
||||
QWindow* _window{ nullptr };
|
||||
std::mutex _mutex;
|
||||
gpu::ContextPointer _gpuContext; // initialized during window creation
|
||||
std::shared_ptr<gpu::Backend> _backend;
|
||||
std::atomic<size_t> _presentCount{ 0 };
|
||||
std::mutex _frameLock;
|
||||
std::queue<gpu::FramePointer> _pendingFrames;
|
||||
gpu::FramePointer _activeFrame;
|
||||
|
@ -39,6 +37,6 @@ public:
|
|||
void handleInput();
|
||||
|
||||
void submitFrame(const gpu::FramePointer& frame);
|
||||
void initialize(QWindow* window);
|
||||
void initialize();
|
||||
void renderFrame();
|
||||
};
|
||||
|
|
|
@ -11,30 +11,33 @@
|
|||
#include <QtGui/QGuiApplication>
|
||||
#include <QtCore/QTimer>
|
||||
#include <QtCore/QFileInfo>
|
||||
#include <QtAndroidExtras/QAndroidJniObject>
|
||||
|
||||
#include <Trace.h>
|
||||
|
||||
#include "PlayerWindow.h"
|
||||
#include "AndroidHelper.h"
|
||||
|
||||
|
||||
void messageHandler(QtMsgType type, const QMessageLogContext& context, const QString& message) {
|
||||
if (!message.isEmpty()) {
|
||||
const char * local=message.toStdString().c_str();
|
||||
const char* local = message.toStdString().c_str();
|
||||
switch (type) {
|
||||
case QtDebugMsg:
|
||||
__android_log_write(ANDROID_LOG_DEBUG,"Interface",local);
|
||||
__android_log_write(ANDROID_LOG_DEBUG, "Interface", local);
|
||||
break;
|
||||
case QtInfoMsg:
|
||||
__android_log_write(ANDROID_LOG_INFO,"Interface",local);
|
||||
__android_log_write(ANDROID_LOG_INFO, "Interface", local);
|
||||
break;
|
||||
case QtWarningMsg:
|
||||
__android_log_write(ANDROID_LOG_WARN,"Interface",local);
|
||||
__android_log_write(ANDROID_LOG_WARN, "Interface", local);
|
||||
break;
|
||||
case QtCriticalMsg:
|
||||
__android_log_write(ANDROID_LOG_ERROR,"Interface",local);
|
||||
__android_log_write(ANDROID_LOG_ERROR, "Interface", local);
|
||||
break;
|
||||
case QtFatalMsg:
|
||||
default:
|
||||
__android_log_write(ANDROID_LOG_FATAL,"Interface",local);
|
||||
__android_log_write(ANDROID_LOG_FATAL, "Interface", local);
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
@ -46,11 +49,13 @@ int main(int argc, char** argv) {
|
|||
auto oldMessageHandler = qInstallMessageHandler(messageHandler);
|
||||
DependencyManager::set<tracing::Tracer>();
|
||||
PlayerWindow window;
|
||||
__android_log_write(ANDROID_LOG_FATAL,"QQQ","Exec");
|
||||
QTimer::singleShot(10, []{
|
||||
__android_log_write(ANDROID_LOG_WARN, "QQQ", "notifyLoadComplete");
|
||||
AndroidHelper::instance().notifyLoadComplete();
|
||||
});
|
||||
__android_log_write(ANDROID_LOG_WARN, "QQQ", "Exec");
|
||||
app.exec();
|
||||
__android_log_write(ANDROID_LOG_FATAL,"QQQ","Exec done");
|
||||
__android_log_write(ANDROID_LOG_WARN, "QQQ", "Exec done");
|
||||
qInstallMessageHandler(oldMessageHandler);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,53 +0,0 @@
|
|||
//
|
||||
// Created by Bradley Austin Davis on 2018/11/20
|
||||
// Copyright 2013-2018 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
|
||||
//
|
||||
package io.highfidelity.frameplayer;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
|
||||
import org.qtproject.qt5.android.bindings.QtActivity;
|
||||
|
||||
import io.highfidelity.oculus.OculusMobileActivity;
|
||||
|
||||
|
||||
public class QuestQtActivity extends QtActivity {
|
||||
private native void nativeOnCreate();
|
||||
private boolean launchedQuestMode = false;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
Log.w("QQQ_Qt", "QuestQtActivity::onCreate");
|
||||
super.onCreate(savedInstanceState);
|
||||
nativeOnCreate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
Log.w("QQQ_Qt", "QuestQtActivity::onDestroy");
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
public void launchOculusActivity() {
|
||||
Log.w("QQQ_Qt", "QuestQtActivity::launchOculusActivity");
|
||||
runOnUiThread(()->{
|
||||
keepInterfaceRunning = true;
|
||||
launchedQuestMode = true;
|
||||
moveTaskToBack(true);
|
||||
startActivity(new Intent(this, QuestRenderActivity.class));
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
if (launchedQuestMode) {
|
||||
moveTaskToBack(true);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,14 +1,6 @@
|
|||
package io.highfidelity.frameplayer;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
|
||||
import io.highfidelity.oculus.OculusMobileActivity;
|
||||
|
||||
public class QuestRenderActivity extends OculusMobileActivity {
|
||||
@Override
|
||||
public void onCreate(Bundle savedState) {
|
||||
super.onCreate(savedState);
|
||||
startActivity(new Intent(this, QuestQtActivity.class));
|
||||
}
|
||||
}
|
||||
|
|
16
android/apps/questInterface/CMakeLists.txt
Normal file
16
android/apps/questInterface/CMakeLists.txt
Normal file
|
@ -0,0 +1,16 @@
|
|||
set(TARGET_NAME questInterface)
|
||||
setup_hifi_library()
|
||||
link_hifi_libraries(
|
||||
shared task networking qml
|
||||
image fbx hfm render-utils physics entities octree
|
||||
oculusMobile oculusMobilePlugin
|
||||
gl gpu ${PLATFORM_GL_BACKEND}
|
||||
)
|
||||
target_opengl()
|
||||
target_bullet()
|
||||
target_oculus_mobile()
|
||||
|
||||
add_subdirectory("${CMAKE_SOURCE_DIR}/interface" "libraries/interface")
|
||||
include_directories("${CMAKE_SOURCE_DIR}/interface/src")
|
||||
add_subdirectory("${CMAKE_SOURCE_DIR}/plugins/hifiCodec" "libraries/hifiCodecPlugin")
|
||||
target_link_libraries(questInterface android log m interface)
|
149
android/apps/questInterface/build.gradle
Normal file
149
android/apps/questInterface/build.gradle
Normal file
|
@ -0,0 +1,149 @@
|
|||
import org.apache.tools.ant.taskdefs.condition.Os
|
||||
apply plugin: 'com.android.application'
|
||||
|
||||
task renameHifiACTaskDebug() {
|
||||
doLast {
|
||||
def sourceFile = new File("${appDir}/build/intermediates/cmake/debug/obj/arm64-v8a/","libhifiCodec.so")
|
||||
def destinationFile = new File("${appDir}/src/main/jniLibs/arm64-v8a", "libplugins_libhifiCodec.so")
|
||||
copy { from sourceFile; into destinationFile.parent; rename(sourceFile.name, destinationFile.name) }
|
||||
}
|
||||
}
|
||||
task renameHifiACTaskRelease(type: Copy) {
|
||||
doLast {
|
||||
def sourceFile = new File("${appDir}/build/intermediates/cmake/release/obj/arm64-v8a/","libhifiCodec.so")
|
||||
def destinationFile = new File("${appDir}/src/main/jniLibs/arm64-v8a", "libplugins_libhifiCodec.so")
|
||||
copy { from sourceFile; into destinationFile.parent; rename(sourceFile.name, destinationFile.name) }
|
||||
}
|
||||
}
|
||||
|
||||
android {
|
||||
compileSdkVersion 28
|
||||
|
||||
defaultConfig {
|
||||
applicationId "io.highfidelity.questInterface"
|
||||
minSdkVersion 24
|
||||
targetSdkVersion 28
|
||||
versionCode 1
|
||||
versionName appVersionName
|
||||
ndk { abiFilters 'arm64-v8a' }
|
||||
externalNativeBuild {
|
||||
cmake {
|
||||
arguments '-DHIFI_ANDROID=1',
|
||||
'-DHIFI_ANDROID_APP=questInterface',
|
||||
'-DANDROID_TOOLCHAIN=clang',
|
||||
'-DANDROID_STL=c++_shared',
|
||||
'-DCMAKE_VERBOSE_MAKEFILE=ON',
|
||||
'-DRELEASE_NUMBER=' + RELEASE_NUMBER,
|
||||
'-DRELEASE_TYPE=' + RELEASE_TYPE,
|
||||
'-DSTABLE_BUILD=' + STABLE_BUILD,
|
||||
'-DDISABLE_QML=OFF',
|
||||
'-DDISABLE_KTX_CACHE=OFF',
|
||||
'-DUSE_BREAKPAD=OFF'
|
||||
targets = ['questInterface']
|
||||
}
|
||||
}
|
||||
signingConfigs {
|
||||
release {
|
||||
storeFile project.hasProperty("HIFI_ANDROID_KEYSTORE") ? file(HIFI_ANDROID_KEYSTORE) : null
|
||||
storePassword project.hasProperty("HIFI_ANDROID_KEYSTORE_PASSWORD") ? HIFI_ANDROID_KEYSTORE_PASSWORD : ''
|
||||
keyAlias project.hasProperty("HIFI_ANDROID_KEY_ALIAS") ? HIFI_ANDROID_KEY_ALIAS : ''
|
||||
keyPassword project.hasProperty("HIFI_ANDROID_KEY_PASSWORD") ? HIFI_ANDROID_KEY_PASSWORD : ''
|
||||
v2SigningEnabled false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
debug {
|
||||
buildConfigField "String", "BACKTRACE_URL", "\"" + (System.getenv("CMAKE_BACKTRACE_URL") ? System.getenv("CMAKE_BACKTRACE_URL") : '') + "\""
|
||||
buildConfigField "String", "BACKTRACE_TOKEN", "\"" + (System.getenv("CMAKE_BACKTRACE_TOKEN") ? System.getenv("CMAKE_BACKTRACE_TOKEN") : '') + "\""
|
||||
buildConfigField "String", "OAUTH_CLIENT_ID", "\"" + (System.getenv("OAUTH_CLIENT_ID") ? System.getenv("OAUTH_CLIENT_ID") : '') + "\""
|
||||
buildConfigField "String", "OAUTH_CLIENT_SECRET", "\"" + (System.getenv("OAUTH_CLIENT_SECRET") ? System.getenv("OAUTH_CLIENT_SECRET") : '') + "\""
|
||||
buildConfigField "String", "OAUTH_REDIRECT_URI", "\"" + (System.getenv("OAUTH_REDIRECT_URI") ? System.getenv("OAUTH_REDIRECT_URI") : '') + "\""
|
||||
}
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
signingConfig signingConfigs.release
|
||||
buildConfigField "String", "BACKTRACE_URL", "\"" + (System.getenv("CMAKE_BACKTRACE_URL") ? System.getenv("CMAKE_BACKTRACE_URL") : '') + "\""
|
||||
buildConfigField "String", "BACKTRACE_TOKEN", "\"" + (System.getenv("CMAKE_BACKTRACE_TOKEN") ? System.getenv("CMAKE_BACKTRACE_TOKEN") : '') + "\""
|
||||
buildConfigField "String", "OAUTH_CLIENT_ID", "\"" + (System.getenv("OAUTH_CLIENT_ID") ? System.getenv("OAUTH_CLIENT_ID") : '') + "\""
|
||||
buildConfigField "String", "OAUTH_CLIENT_SECRET", "\"" + (System.getenv("OAUTH_CLIENT_SECRET") ? System.getenv("OAUTH_CLIENT_SECRET") : '') + "\""
|
||||
buildConfigField "String", "OAUTH_REDIRECT_URI", "\"" + (System.getenv("OAUTH_REDIRECT_URI") ? System.getenv("OAUTH_REDIRECT_URI") : '') + "\""
|
||||
}
|
||||
}
|
||||
|
||||
externalNativeBuild {
|
||||
cmake {
|
||||
path '../../../CMakeLists.txt'
|
||||
}
|
||||
}
|
||||
|
||||
applicationVariants.all { variant ->
|
||||
// Our asset contents depend on items produced in the CMake build
|
||||
// so our merge has to depend on the external native build
|
||||
variant.externalNativeBuildTasks.each { task ->
|
||||
variant.mergeResources.dependsOn(task)
|
||||
if (Os.isFamily(Os.FAMILY_UNIX)) {
|
||||
// FIXME
|
||||
def uploadDumpSymsTask = rootProject.getTasksByName("uploadBreakpadDumpSyms${variant.name.capitalize()}", false).first()
|
||||
def runDumpSymsTask = rootProject.getTasksByName("runBreakpadDumpSyms${variant.name.capitalize()}", false).first()
|
||||
def renameHifiACTask = rootProject.getTasksByName("renameHifiACTask${variant.name.capitalize()}", false).first()
|
||||
runDumpSymsTask.dependsOn(task)
|
||||
variant.assemble.dependsOn(uploadDumpSymsTask)
|
||||
variant.mergeResources.dependsOn(renameHifiACTask)
|
||||
}
|
||||
}
|
||||
|
||||
variant.mergeAssets.doLast {
|
||||
def assetList = new LinkedList<String>()
|
||||
def youngestLastModified = 0
|
||||
|
||||
// Copy the compiled resources generated by the external native build
|
||||
copy {
|
||||
from new File(projectDir, "../../../interface/compiledResources")
|
||||
into outputDir
|
||||
duplicatesStrategy DuplicatesStrategy.INCLUDE
|
||||
eachFile { details ->
|
||||
youngestLastModified = Math.max(youngestLastModified, details.lastModified)
|
||||
assetList.add(details.path)
|
||||
}
|
||||
}
|
||||
|
||||
// Copy the scripts directory
|
||||
copy {
|
||||
from new File(projectDir, "../../../scripts")
|
||||
into new File(outputDir, "scripts")
|
||||
duplicatesStrategy DuplicatesStrategy.INCLUDE
|
||||
eachFile { details->
|
||||
youngestLastModified = Math.max(youngestLastModified, details.lastModified)
|
||||
assetList.add("scripts/" + details.path)
|
||||
}
|
||||
}
|
||||
|
||||
// Write a list of files to be unpacked to the cache folder
|
||||
new File(outputDir, 'cache_assets.txt').withWriter { out ->
|
||||
out.println(Long.toString(youngestLastModified))
|
||||
assetList.each { file -> out.println(file) }
|
||||
}
|
||||
}
|
||||
|
||||
variant.outputs.all {
|
||||
if (RELEASE_NUMBER != '0') {
|
||||
outputFileName = "app_" + RELEASE_NUMBER + "_" + RELEASE_TYPE + ".apk"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation fileTree(include: ['*.jar'], dir: '../../libraries/qt/libs')
|
||||
implementation project(':oculus')
|
||||
implementation project(':qt')
|
||||
}
|
25
android/apps/questInterface/proguard-rules.pro
vendored
Normal file
25
android/apps/questInterface/proguard-rules.pro
vendored
Normal file
|
@ -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
|
49
android/apps/questInterface/src/main/AndroidManifest.xml
Normal file
49
android/apps/questInterface/src/main/AndroidManifest.xml
Normal file
|
@ -0,0 +1,49 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="io.highfidelity.questInterface"
|
||||
android:installLocation="auto">
|
||||
|
||||
<uses-feature android:glEsVersion="0x00030002" android:required="true" />
|
||||
<uses-permission android:name="android.permission.VIBRATE"/>
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
|
||||
<uses-permission android:name="android.permission.RECORD_AUDIO" />
|
||||
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
|
||||
<uses-feature android:name="android.hardware.sensor.accelerometer" android:required="true"/>
|
||||
<uses-feature android:name="android.hardware.sensor.gyroscope" android:required="true"/>
|
||||
<uses-feature android:name="android.software.vr.mode" android:required="true"/>
|
||||
<uses-feature android:name="android.hardware.vr.high_performance" android:required="true"/>
|
||||
|
||||
<application
|
||||
android:name="org.qtproject.qt5.android.bindings.QtApplication"
|
||||
android:label="@string/app_name"
|
||||
android:allowBackup="true">
|
||||
<meta-data android:name="com.samsung.android.vr.application.mode" android:value="vr_only"/>
|
||||
<activity
|
||||
android:name=".PermissionsChecker"
|
||||
android:launchMode="singleTask"
|
||||
android:screenOrientation="landscape"
|
||||
android:excludeFromRecents="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.INFO" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity
|
||||
android:configChanges="orientation|uiMode|screenLayout|screenSize|smallestScreenSize|locale|fontScale|keyboard|keyboardHidden|navigation"
|
||||
android:name=".InterfaceActivity"
|
||||
android:label="@string/app_name"
|
||||
android:launchMode="singleTask">
|
||||
<meta-data android:name="android.app.lib_name" android:value="questInterface"/>
|
||||
<meta-data android:name="android.app.qt_libs_resource_id" android:resource="@array/qt_libs"/>
|
||||
<meta-data android:name="android.app.bundled_in_lib_resource_id" android:resource="@array/bundled_in_lib"/>
|
||||
<meta-data android:name="android.app.bundled_in_assets_resource_id" android:resource="@array/bundled_in_assets"/>
|
||||
<meta-data android:name="android.app.load_local_libs" android:value="plugins/platforms/android/libqtforandroid.so:plugins/bearer/libqandroidbearer.so:lib/libQt5QuickParticles.so"/>
|
||||
<meta-data android:name="android.app.background_running" android:value="false"/>
|
||||
<meta-data android:name="android.app.auto_screen_scale_factor" android:value="false"/>
|
||||
<meta-data android:name="android.app.extract_android_style" android:value="full"/>
|
||||
</activity>
|
||||
</application>
|
||||
</manifest>
|
106
android/apps/questInterface/src/main/cpp/native.cpp
Normal file
106
android/apps/questInterface/src/main/cpp/native.cpp
Normal file
|
@ -0,0 +1,106 @@
|
|||
#include <functional>
|
||||
|
||||
#include <QtCore/QBuffer>
|
||||
#include <QtCore/QDebug>
|
||||
#include <QtCore/QDir>
|
||||
#include <QtCore/QFile>
|
||||
#include <QtCore/QThread>
|
||||
#include <QtCore/QStringList>
|
||||
#include <QtCore/QStandardPaths>
|
||||
#include <QtCore/QTextStream>
|
||||
#include <QtCore/QObject>
|
||||
|
||||
#include <QtAndroidExtras/QAndroidJniObject>
|
||||
#include <QtAndroidExtras/QtAndroid>
|
||||
#include <android/log.h>
|
||||
#include <android/asset_manager.h>
|
||||
#include <android/asset_manager_jni.h>
|
||||
|
||||
#include <shared/Storage.h>
|
||||
|
||||
#include <AddressManager.h>
|
||||
#include <AndroidHelper.h>
|
||||
#include <udt/PacketHeaders.h>
|
||||
|
||||
#include <OVR_Platform.h>
|
||||
#include <OVR_Functions_Voip.h>
|
||||
|
||||
void initOculusPlatform(JNIEnv* env, jobject obj) {
|
||||
static std::once_flag once;
|
||||
std::call_once(once, [&]{
|
||||
// static const char* appID = "2343652845669354";
|
||||
// if (ovr_PlatformInitializeAndroid(appID, obj, env) != ovrPlatformInitialize_Success) {
|
||||
// __android_log_write(ANDROID_LOG_WARN, "QQQ", "Failed to init platform SDK");
|
||||
// return;
|
||||
// }
|
||||
// ovr_Voip_SetSystemVoipSuppressed(true);
|
||||
});
|
||||
}
|
||||
|
||||
void getClassName(JNIEnv *env, jobject obj){
|
||||
jclass cls = env->GetObjectClass(obj);
|
||||
jmethodID mid = env->GetMethodID(cls,"getClass", "()Ljava/lang/Class;");
|
||||
jobject clsObj = env->CallObjectMethod(obj, mid);
|
||||
|
||||
cls= env->GetObjectClass(clsObj);
|
||||
|
||||
mid= env->GetMethodID(cls, "getName", "()Ljava/lang/String;");
|
||||
|
||||
jstring strObj = (jstring) env->CallObjectMethod(clsObj, mid);
|
||||
|
||||
const char* str = env->GetStringUTFChars(strObj, NULL);
|
||||
|
||||
__android_log_print(ANDROID_LOG_ERROR,__FUNCTION__, "Native Class call: %s",str);
|
||||
|
||||
env->ReleaseStringUTFChars(strObj, str);
|
||||
}
|
||||
|
||||
|
||||
extern "C" {
|
||||
JNIEXPORT void JNICALL
|
||||
Java_io_highfidelity_oculus_OculusMobileActivity_nativeInitOculusPlatform(JNIEnv *env, jobject obj){
|
||||
initOculusPlatform(env, obj);
|
||||
}
|
||||
QAndroidJniObject __interfaceActivity;
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_io_highfidelity_oculus_OculusMobileActivity_questNativeOnCreate(JNIEnv *env, jobject obj) {
|
||||
__android_log_print(ANDROID_LOG_INFO, "QQQ", __FUNCTION__);
|
||||
initOculusPlatform(env, obj);
|
||||
getClassName(env, obj);
|
||||
|
||||
__interfaceActivity = QAndroidJniObject(obj);
|
||||
|
||||
QObject::connect(&AndroidHelper::instance(), &AndroidHelper::qtAppLoadComplete, []() {
|
||||
__interfaceActivity.callMethod<void>("onAppLoadedComplete", "()V");
|
||||
|
||||
QObject::disconnect(&AndroidHelper::instance(), &AndroidHelper::qtAppLoadComplete,
|
||||
nullptr,
|
||||
nullptr);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
JNIEXPORT void Java_io_highfidelity_oculus_OculusMobileActivity_questOnAppAfterLoad(JNIEnv* env, jobject obj) {
|
||||
AndroidHelper::instance().moveToThread(qApp->thread());
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_io_highfidelity_oculus_OculusMobileActivity_questNativeOnPause(JNIEnv *env, jobject obj) {
|
||||
AndroidHelper::instance().notifyEnterBackground();
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_io_highfidelity_oculus_OculusMobileActivity_questNativeOnResume(JNIEnv *env, jobject obj) {
|
||||
AndroidHelper::instance().notifyEnterForeground();
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_io_highfidelity_questInterface_receiver_HeadsetStateReceiver_notifyHeadsetOn(JNIEnv *env,
|
||||
jobject instance,
|
||||
jboolean pluggedIn) {
|
||||
AndroidHelper::instance().notifyHeadsetOn(pluggedIn);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
package io.highfidelity.questInterface;
|
||||
|
||||
import android.os.Bundle;
|
||||
import io.highfidelity.oculus.OculusMobileActivity;
|
||||
import io.highfidelity.utils.HifiUtils;
|
||||
|
||||
public class InterfaceActivity extends OculusMobileActivity {
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
HifiUtils.upackAssets(getAssets(), getCacheDir().getAbsolutePath());
|
||||
super.onCreate(savedInstanceState);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
package io.highfidelity.questInterface;
|
||||
|
||||
import android.Manifest;
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.Bundle;
|
||||
|
||||
import io.highfidelity.oculus.OculusMobileActivity;
|
||||
import io.highfidelity.utils.HifiUtils;
|
||||
|
||||
public class PermissionsChecker extends Activity {
|
||||
private static final int REQUEST_PERMISSIONS = 20;
|
||||
private static final String TAG = PermissionsChecker.class.getName();
|
||||
private static final String[] REQUIRED_PERMISSIONS = new String[]{
|
||||
Manifest.permission.READ_EXTERNAL_STORAGE,
|
||||
Manifest.permission.WRITE_EXTERNAL_STORAGE,
|
||||
Manifest.permission.RECORD_AUDIO,
|
||||
Manifest.permission.CAMERA
|
||||
};
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
requestAppPermissions(REQUIRED_PERMISSIONS,REQUEST_PERMISSIONS);
|
||||
}
|
||||
|
||||
public void requestAppPermissions(final String[] requestedPermissions,
|
||||
final int requestCode) {
|
||||
int permissionCheck = PackageManager.PERMISSION_GRANTED;
|
||||
boolean shouldShowRequestPermissionRationale = false;
|
||||
for (String permission : requestedPermissions) {
|
||||
permissionCheck = permissionCheck + checkSelfPermission(permission);
|
||||
shouldShowRequestPermissionRationale = shouldShowRequestPermissionRationale || shouldShowRequestPermissionRationale(permission);
|
||||
}
|
||||
if (permissionCheck != PackageManager.PERMISSION_GRANTED) {
|
||||
System.out.println("Permission was not granted. Ask for permissions");
|
||||
if (shouldShowRequestPermissionRationale) {
|
||||
requestPermissions(requestedPermissions, requestCode);
|
||||
} else {
|
||||
requestPermissions(requestedPermissions, requestCode);
|
||||
}
|
||||
} else {
|
||||
System.out.println("Launching the other activity..");
|
||||
launchActivityWithPermissions();
|
||||
}
|
||||
}
|
||||
|
||||
private void launchActivityWithPermissions() {
|
||||
startActivity(new Intent(this, InterfaceActivity.class));
|
||||
finish();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
int permissionCheck = PackageManager.PERMISSION_GRANTED;
|
||||
for (int permission : grantResults) {
|
||||
permissionCheck = permissionCheck + permission;
|
||||
}
|
||||
if ((grantResults.length > 0) && permissionCheck == PackageManager.PERMISSION_GRANTED) {
|
||||
launchActivityWithPermissions();
|
||||
} else if (grantResults.length > 0) {
|
||||
System.out.println("User has deliberately denied Permissions. Launching anyways");
|
||||
launchActivityWithPermissions();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--suppress AndroidUnknownAttribute -->
|
||||
<vector xmlns:api24="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:viewportWidth="192"
|
||||
android:viewportHeight="192"
|
||||
android:width="192dp"
|
||||
android:height="192dp">
|
||||
<path
|
||||
android:pathData="M189.5 96.5A93.5 93.5 0 0 1 96 190 93.5 93.5 0 0 1 2.5 96.5 93.5 93.5 0 0 1 96 3 93.5 93.5 0 0 1 189.5 96.5Z"
|
||||
android:fillColor="#333333" />
|
||||
<path
|
||||
android:pathData="M96.2 173.1c-10.3 0 -20.4 -2.1 -29.8 -6 -9.2 -3.8 -17.3 -9.4 -24.3 -16.4 -7 -7 -12.6 -15.2 -16.4 -24.3 -4.1 -9.6 -6.2 -19.6 -6.2 -30 0 -10.3 2.1 -20.4 6 -29.8 3.8 -9.2 9.4 -17.3 16.4 -24.3 7 -7 15.2 -12.6 24.3 -16.4 9.5 -4 19.5 -6 29.8 -6 10.3 0 20.4 2.1 29.8 6 9.2 3.8 17.3 9.4 24.3 16.4 7 7 12.6 15.2 16.4 24.3 4 9.5 6 19.5 6 29.8 0 10.3 -2.1 20.4 -6 29.8 -3.8 9.2 -9.4 17.3 -16.4 24.3 -7 7 -15.2 12.6 -24.3 16.4 -9.2 4.1 -19.3 6.2 -29.6 6.2zm0 -145.3c-37.8 0 -68.6 30.8 -68.6 68.6 0 37.8 30.8 68.6 68.6 68.6 37.8 0 68.6 -30.8 68.6 -68.6 0 -37.8 -30.8 -68.6 -68.6 -68.6z"
|
||||
android:fillColor="#00b4f0" />
|
||||
<path
|
||||
android:pathData="M119.6 129l0 -53.8c3.4 -1.1 5.8 -4.3 5.8 -8 0 -4.6 -3.8 -8.4 -8.4 -8.4 -4.6 0 -8.4 3.8 -8.4 8.4 0 3.6 2.2 6.6 5.4 7.9l0 25L79 83.8 79 64c3.4 -1.1 5.8 -4.3 5.8 -8 0 -4.6 -3.8 -8.4 -8.4 -8.4 -4.6 0 -8.4 3.8 -8.4 8.4 0 3.6 2.2 6.6 5.4 7.9l0 54.1c-3.1 1.2 -5.4 4.3 -5.4 7.9 0 4.6 3.8 8.4 8.4 8.4 4.6 0 8.4 -3.8 8.4 -8.4 0 -3.7 -2.4 -6.9 -5.8 -8l0 -27.3 35 16.3 0 22.2c-3.1 1.2 -5.4 4.3 -5.4 7.9 0 4.6 3.8 8.4 8.4 8.4 4.6 0 8.4 -3.8 8.4 -8.4 0 -3.8 -2.4 -6.9 -5.8 -8z"
|
||||
android:fillColor="#00b4f0" />
|
||||
</vector>
|
|
@ -0,0 +1,3 @@
|
|||
<resources>
|
||||
<string name="app_name" translatable="false">Interface</string>
|
||||
</resources>
|
|
@ -42,6 +42,8 @@ ext {
|
|||
RELEASE_TYPE = project.hasProperty('RELEASE_TYPE') ? project.getProperty('RELEASE_TYPE') : 'DEV'
|
||||
STABLE_BUILD = project.hasProperty('STABLE_BUILD') ? project.getProperty('STABLE_BUILD') : '0'
|
||||
EXEC_SUFFIX = Os.isFamily(Os.FAMILY_WINDOWS) ? '.exe' : ''
|
||||
appVersionCode = Integer.valueOf(VERSION_CODE ?: 1)
|
||||
appVersionName = RELEASE_NUMBER ?: "1.0"
|
||||
}
|
||||
|
||||
def appDir = new File(projectDir, 'apps/interface')
|
||||
|
|
|
@ -1 +1,2 @@
|
|||
org.gradle.jvmargs=-Xms2g -Xmx4g
|
||||
android.debug.obsoleteApi=true
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#Sat Dec 01 08:32:47 PST 2018
|
||||
#Wed Dec 19 13:46:46 PST 2018
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.1-all.zip
|
||||
|
|
|
@ -15,3 +15,7 @@ android {
|
|||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation project(path: ':qt')
|
||||
}
|
||||
|
|
|
@ -7,62 +7,65 @@
|
|||
//
|
||||
package io.highfidelity.oculus;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.view.Surface;
|
||||
import android.view.SurfaceHolder;
|
||||
import android.view.SurfaceView;
|
||||
import android.view.WindowManager;
|
||||
|
||||
import org.qtproject.qt5.android.bindings.QtActivity;
|
||||
import io.highfidelity.utils.HifiUtils;
|
||||
|
||||
/**
|
||||
* Contains a native surface and forwards the activity lifecycle and surface lifecycle
|
||||
* events to the OculusMobileDisplayPlugin
|
||||
*/
|
||||
public class OculusMobileActivity extends Activity implements SurfaceHolder.Callback {
|
||||
public class OculusMobileActivity extends QtActivity implements SurfaceHolder.Callback {
|
||||
private static final String TAG = OculusMobileActivity.class.getSimpleName();
|
||||
static { System.loadLibrary("oculusMobile"); }
|
||||
|
||||
private native void nativeOnCreate();
|
||||
private native static void nativeOnResume();
|
||||
private native static void nativeOnPause();
|
||||
private native static void nativeOnDestroy();
|
||||
private native static void nativeOnSurfaceChanged(Surface s);
|
||||
|
||||
private native void questNativeOnCreate();
|
||||
private native void questNativeOnPause();
|
||||
private native void questNativeOnResume();
|
||||
private native void questOnAppAfterLoad();
|
||||
|
||||
|
||||
private SurfaceView mView;
|
||||
private SurfaceHolder mSurfaceHolder;
|
||||
|
||||
|
||||
public static void launch(Activity activity) {
|
||||
if (activity != null) {
|
||||
activity.runOnUiThread(()->{
|
||||
activity.startActivity(new Intent(activity, OculusMobileActivity.class));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
Log.w(TAG, "QQQ onCreate");
|
||||
super.onCreate(savedInstanceState);
|
||||
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
|
||||
|
||||
Log.w(TAG, "QQQ onCreate");
|
||||
// Create a native surface for VR rendering (Qt GL surfaces are not suitable
|
||||
// because of the lack of fine control over the surface callbacks)
|
||||
// Forward the create message to the JNI code
|
||||
mView = new SurfaceView(this);
|
||||
setContentView(mView);
|
||||
mView.getHolder().addCallback(this);
|
||||
|
||||
// Forward the create message to the JNI code
|
||||
nativeOnCreate();
|
||||
questNativeOnCreate();
|
||||
}
|
||||
public void onAppLoadedComplete() {
|
||||
Log.w(TAG, "QQQ Load Completed");
|
||||
runOnUiThread(() -> {
|
||||
setContentView(mView);
|
||||
questOnAppAfterLoad();
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
Log.w(TAG, "QQQ onDestroy");
|
||||
if (mSurfaceHolder != null) {
|
||||
nativeOnSurfaceChanged(null);
|
||||
}
|
||||
nativeOnDestroy();
|
||||
|
||||
nativeOnSurfaceChanged(null);
|
||||
|
||||
Log.w(TAG, "QQQ onDestroy -- SUPER onDestroy");
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
|
@ -70,19 +73,38 @@ public class OculusMobileActivity extends Activity implements SurfaceHolder.Call
|
|||
protected void onResume() {
|
||||
Log.w(TAG, "QQQ onResume");
|
||||
super.onResume();
|
||||
//Reconnect the global reference back to handler
|
||||
nativeOnCreate();
|
||||
|
||||
questNativeOnResume();
|
||||
nativeOnResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
Log.w(TAG, "QQQ onPause");
|
||||
nativeOnPause();
|
||||
super.onPause();
|
||||
|
||||
questNativeOnPause();
|
||||
nativeOnPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop(){
|
||||
super.onStop();
|
||||
Log.w(TAG, "QQQ Onstop called");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onRestart(){
|
||||
super.onRestart();
|
||||
Log.w(TAG, "QQQ onRestart called ****");
|
||||
questOnAppAfterLoad();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void surfaceCreated(SurfaceHolder holder) {
|
||||
Log.w(TAG, "QQQ surfaceCreated");
|
||||
Log.w(TAG, "QQQ surfaceCreated ************************************");
|
||||
nativeOnSurfaceChanged(holder.getSurface());
|
||||
mSurfaceHolder = holder;
|
||||
}
|
||||
|
@ -96,8 +118,9 @@ public class OculusMobileActivity extends Activity implements SurfaceHolder.Call
|
|||
|
||||
@Override
|
||||
public void surfaceDestroyed(SurfaceHolder holder) {
|
||||
Log.w(TAG, "QQQ surfaceDestroyed");
|
||||
Log.w(TAG, "QQQ surfaceDestroyed ***************************************************");
|
||||
nativeOnSurfaceChanged(null);
|
||||
mSurfaceHolder = null;
|
||||
|
||||
}
|
||||
}
|
|
@ -70,9 +70,6 @@ public class QtActivity extends Activity {
|
|||
public final String QT_ANDROID_DEFAULT_THEME = QT_ANDROID_THEMES[0]; // sets the default theme.
|
||||
private QtActivityLoader m_loader = new QtActivityLoader(this);
|
||||
|
||||
public boolean isLoading;
|
||||
public boolean keepInterfaceRunning;
|
||||
|
||||
public QtActivity() {
|
||||
}
|
||||
|
||||
|
@ -229,10 +226,13 @@ public class QtActivity extends Activity {
|
|||
//---------------------------------------------------------------------------
|
||||
|
||||
protected void onCreateHook(Bundle savedInstanceState) {
|
||||
|
||||
m_loader.APPLICATION_PARAMETERS = APPLICATION_PARAMETERS;
|
||||
m_loader.ENVIRONMENT_VARIABLES = ENVIRONMENT_VARIABLES;
|
||||
m_loader.QT_ANDROID_THEMES = QT_ANDROID_THEMES;
|
||||
m_loader.QT_ANDROID_DEFAULT_THEME = QT_ANDROID_DEFAULT_THEME;
|
||||
|
||||
|
||||
m_loader.onCreate(savedInstanceState);
|
||||
}
|
||||
|
||||
|
@ -364,7 +364,10 @@ public class QtActivity extends Activity {
|
|||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
QtApplication.invokeDelegate();
|
||||
|
||||
QtNative.terminateQt();
|
||||
QtNative.setActivity(null,null);
|
||||
System.exit(0);
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
|
@ -506,9 +509,9 @@ public class QtActivity extends Activity {
|
|||
super.onPause();
|
||||
// GC: this trick allow us to show a splash activity until Qt app finishes
|
||||
// loading
|
||||
if (!isLoading && !keepInterfaceRunning) {
|
||||
QtApplication.invokeDelegate();
|
||||
}
|
||||
//QtApplication.invokeDelegate();
|
||||
|
||||
//TODO(Amer): looking into why this messes up pause.
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
|
@ -647,11 +650,7 @@ public class QtActivity extends Activity {
|
|||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
if (!keepInterfaceRunning) {
|
||||
QtApplication.invokeDelegate();
|
||||
}
|
||||
QtNative.terminateQt();
|
||||
QtNative.setActivity(null,null);
|
||||
QtApplication.invokeDelegate();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
|
|
@ -12,15 +12,26 @@ project(':qt').projectDir = new File(settingsDir, 'libraries/qt')
|
|||
// Applications
|
||||
//
|
||||
|
||||
include ':interface'
|
||||
project(':interface').projectDir = new File(settingsDir, 'apps/interface')
|
||||
if (!getSettings().hasProperty("SUPPRESS_INTERFACE")) {
|
||||
include ':interface'
|
||||
project(':interface').projectDir = new File(settingsDir, 'apps/interface')
|
||||
}
|
||||
|
||||
if (!getSettings().hasProperty("SUPPRESS_QUEST_INTERFACE")) {
|
||||
include ':questInterface'
|
||||
project(':questInterface').projectDir = new File(settingsDir, 'apps/questInterface')
|
||||
}
|
||||
|
||||
//
|
||||
// Test projects
|
||||
//
|
||||
|
||||
include ':framePlayer'
|
||||
project(':framePlayer').projectDir = new File(settingsDir, 'apps/framePlayer')
|
||||
if (!getSettings().hasProperty("SUPPRESS_FRAME_PLAYER")) {
|
||||
include ':framePlayer'
|
||||
project(':framePlayer').projectDir = new File(settingsDir, 'apps/framePlayer')
|
||||
}
|
||||
|
||||
include ':questFramePlayer'
|
||||
project(':questFramePlayer').projectDir = new File(settingsDir, 'apps/questFramePlayer')
|
||||
if (!getSettings().hasProperty("SUPPRESS_QUEST_FRAME_PLAYER")) {
|
||||
include ':questFramePlayer'
|
||||
project(':questFramePlayer').projectDir = new File(settingsDir, 'apps/questFramePlayer')
|
||||
}
|
||||
|
|
|
@ -270,6 +270,16 @@ macro(AUTOSCRIBE_SHADER_LIBS)
|
|||
set(AUTOSCRIBE_SHADERGEN_COMMANDS_FILE ${CMAKE_CURRENT_BINARY_DIR}/shadergen.txt)
|
||||
file(WRITE ${AUTOSCRIBE_SHADERGEN_COMMANDS_FILE} "${AUTOSCRIBE_SHADERGEN_COMMANDS}")
|
||||
|
||||
if (HIFI_ANDROID)
|
||||
if (
|
||||
(${HIFI_ANDROID_APP} STREQUAL "questInterface") OR
|
||||
(${HIFI_ANDROID_APP} STREQUAL "questFramePlayer") OR
|
||||
(${HIFI_ANDROID_APP} STREQUAL "framePlayer")
|
||||
)
|
||||
set(EXTRA_SHADERGEN_ARGS --extensions EXT_clip_cull_distance)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# A custom python script which will generate all our shader artifacts
|
||||
add_custom_command(
|
||||
OUTPUT ${SCRIBED_SHADERS} ${SPIRV_SHADERS} ${REFLECTED_SHADERS}
|
||||
|
@ -279,6 +289,7 @@ macro(AUTOSCRIBE_SHADER_LIBS)
|
|||
--tools-dir ${VCPKG_TOOLS_DIR}
|
||||
--build-dir ${CMAKE_CURRENT_BINARY_DIR}
|
||||
--source-dir ${CMAKE_SOURCE_DIR}
|
||||
${EXTRA_SHADERGEN_ARGS}
|
||||
DEPENDS ${AUTOSCRIBE_SHADER_HEADERS} ${CMAKE_SOURCE_DIR}/tools/shadergen.py ${ALL_SCRIBE_SHADERS})
|
||||
|
||||
add_custom_target(shadergen DEPENDS ${SCRIBED_SHADERS} ${SPIRV_SHADERS} ${REFLECTED_SHADERS})
|
||||
|
|
|
@ -53,9 +53,9 @@ ANDROID_PACKAGES = {
|
|||
'includeLibs': ['libvrapi.so']
|
||||
},
|
||||
'oculusPlatform': {
|
||||
'file': 'OVRPlatformSDK_v1.32.0.zip',
|
||||
'versionId': 'jG9DB16zOGxSrmtZy4jcQnwO0TJUuaeL',
|
||||
'checksum': 'ab5b203b3a39a56ab148d68fff769e05',
|
||||
'file': 'OVRPlatformSDK_v1.34.0.zip',
|
||||
'versionId': 'vbRUkkyzUAXfTGSEtuiUr_7.Fm5h5BZk',
|
||||
'checksum': '16e4c5f39520f122bc49cb6d5bb88289',
|
||||
'sharedLibFolder': 'Android/libs/arm64-v8a',
|
||||
'includeLibs': ['libovrplatformloader.so']
|
||||
},
|
||||
|
|
|
@ -425,11 +425,12 @@ FocusScope {
|
|||
console.warn("Could not find top level window for " + item);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
if (typeof Controller === "undefined") {
|
||||
console.warn("Controller not yet available... can't center");
|
||||
return;
|
||||
}
|
||||
*/
|
||||
|
||||
var newRecommendedRectJS = (typeof Controller === "undefined") ? Qt.rect(0,0,0,0) : Controller.getRecommendedHUDRect();
|
||||
var newRecommendedRect = Qt.rect(newRecommendedRectJS.x, newRecommendedRectJS.y,
|
||||
|
@ -455,15 +456,17 @@ FocusScope {
|
|||
console.warn("Could not find top level window for " + item);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
if (typeof Controller === "undefined") {
|
||||
console.warn("Controller not yet available... can't reposition targetWindow:" + targetWindow);
|
||||
return;
|
||||
}
|
||||
*/
|
||||
|
||||
var oldRecommendedRect = recommendedRect;
|
||||
var oldRecommendedDimmensions = { x: oldRecommendedRect.width, y: oldRecommendedRect.height };
|
||||
var newRecommendedRect = Controller.getRecommendedHUDRect();
|
||||
var newRecommendedRect = { width: 1280, height: 720, x: 0, y: 0 };
|
||||
if (typeof Controller !== "undefined") newRecommendedRect = Controller.getRecommendedHUDRect();
|
||||
var newRecommendedDimmensions = { x: newRecommendedRect.width, y: newRecommendedRect.height };
|
||||
repositionWindow(targetWindow, false, oldRecommendedRect, oldRecommendedDimmensions, newRecommendedRect, newRecommendedDimmensions);
|
||||
}
|
||||
|
@ -480,7 +483,8 @@ FocusScope {
|
|||
return;
|
||||
}
|
||||
|
||||
var recommended = Controller.getRecommendedHUDRect();
|
||||
var recommended = { width: 1280, height: 720, x: 0, y: 0 };
|
||||
if (typeof Controller !== "undefined") recommended = Controller.getRecommendedHUDRect();
|
||||
var maxX = recommended.x + recommended.width;
|
||||
var maxY = recommended.y + recommended.height;
|
||||
var newPosition = Qt.vector2d(targetWindow.x, targetWindow.y);
|
||||
|
|
|
@ -18,8 +18,8 @@ OriginalDesktop.Desktop {
|
|||
hoverEnabled: true
|
||||
propagateComposedEvents: true
|
||||
scrollGestureEnabled: false // we don't need/want these
|
||||
onEntered: ApplicationCompositor.reticleOverDesktop = true
|
||||
onExited: ApplicationCompositor.reticleOverDesktop = false
|
||||
onEntered: if (typeof ApplicationCompositor !== "undefined") ApplicationCompositor.reticleOverDesktop = true
|
||||
onExited: if (typeof ApplicationCompositor !== "undefined") ApplicationCompositor.reticleOverDesktop = false
|
||||
acceptedButtons: Qt.NoButton
|
||||
}
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
|
||||
#include "Application.h"
|
||||
|
||||
#include <chrono>
|
||||
|
@ -37,7 +38,6 @@
|
|||
|
||||
#include <QtNetwork/QLocalSocket>
|
||||
#include <QtNetwork/QLocalServer>
|
||||
|
||||
#include <QtQml/QQmlContext>
|
||||
#include <QtQml/QQmlEngine>
|
||||
#include <QtQuick/QQuickWindow>
|
||||
|
@ -51,6 +51,7 @@
|
|||
#include <QProcessEnvironment>
|
||||
#include <QTemporaryDir>
|
||||
|
||||
|
||||
#include <gl/QOpenGLContextWrapper.h>
|
||||
#include <gl/GLWindow.h>
|
||||
#include <gl/GLHelpers.h>
|
||||
|
@ -191,6 +192,9 @@
|
|||
#include "scripting/WalletScriptingInterface.h"
|
||||
#include "scripting/TTSScriptingInterface.h"
|
||||
#include "scripting/KeyboardScriptingInterface.h"
|
||||
|
||||
|
||||
|
||||
#if defined(Q_OS_MAC) || defined(Q_OS_WIN)
|
||||
#include "SpeechRecognizer.h"
|
||||
#endif
|
||||
|
@ -239,6 +243,7 @@
|
|||
#include "webbrowser/WebBrowserSuggestionsEngine.h"
|
||||
#include <DesktopPreviewProvider.h>
|
||||
|
||||
|
||||
#include "AboutUtil.h"
|
||||
|
||||
#if defined(Q_OS_WIN)
|
||||
|
@ -1745,7 +1750,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
|||
});
|
||||
_applicationStateDevice->setInputVariant(STATE_PLATFORM_ANDROID, []() -> float {
|
||||
#if defined(Q_OS_ANDROID)
|
||||
return 1;
|
||||
return 1 ;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
|
@ -1848,6 +1853,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
|||
|
||||
this->installEventFilter(this);
|
||||
|
||||
|
||||
|
||||
#ifdef HAVE_DDE
|
||||
auto ddeTracker = DependencyManager::get<DdeFaceTracker>();
|
||||
ddeTracker->init();
|
||||
|
@ -3085,7 +3092,7 @@ void Application::initializeUi() {
|
|||
}
|
||||
if (TouchscreenVirtualPadDevice::NAME == inputPlugin->getName()) {
|
||||
_touchscreenVirtualPadDevice = std::dynamic_pointer_cast<TouchscreenVirtualPadDevice>(inputPlugin);
|
||||
#if defined(Q_OS_ANDROID)
|
||||
#if defined(ANDROID_APP_INTERFACE)
|
||||
auto& virtualPadManager = VirtualPad::Manager::instance();
|
||||
connect(&virtualPadManager, &VirtualPad::Manager::hapticFeedbackRequested,
|
||||
this, [](int duration) {
|
||||
|
@ -3617,10 +3624,14 @@ void Application::handleSandboxStatus(QNetworkReply* reply) {
|
|||
}
|
||||
|
||||
// Get controller availability
|
||||
#ifdef ANDROID_APP_QUEST_INTERFACE
|
||||
bool hasHandControllers = true;
|
||||
#else
|
||||
bool hasHandControllers = false;
|
||||
if (PluginUtils::isViveControllerAvailable() || PluginUtils::isOculusTouchControllerAvailable()) {
|
||||
hasHandControllers = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Check HMD use (may be technically available without being in use)
|
||||
bool hasHMD = PluginUtils::isHMDAvailable();
|
||||
|
@ -8237,6 +8248,7 @@ void Application::loadDomainConnectionDialog() {
|
|||
}
|
||||
|
||||
void Application::toggleLogDialog() {
|
||||
#ifndef ANDROID_APP_QUEST_INTERFACE
|
||||
if (getLoginDialogPoppedUp()) {
|
||||
return;
|
||||
}
|
||||
|
@ -8260,6 +8272,7 @@ void Application::toggleLogDialog() {
|
|||
} else {
|
||||
_logDialog->show();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void Application::recreateLogWindow(int keepOnTop) {
|
||||
|
@ -9125,17 +9138,23 @@ void Application::beforeEnterBackground() {
|
|||
void Application::enterBackground() {
|
||||
QMetaObject::invokeMethod(DependencyManager::get<AudioClient>().data(),
|
||||
"stop", Qt::BlockingQueuedConnection);
|
||||
// Quest only supports one plugin which can't be deactivated currently
|
||||
#if !defined(ANDROID_APP_QUEST_INTERFACE)
|
||||
if (getActiveDisplayPlugin()->isActive()) {
|
||||
getActiveDisplayPlugin()->deactivate();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void Application::enterForeground() {
|
||||
QMetaObject::invokeMethod(DependencyManager::get<AudioClient>().data(),
|
||||
"start", Qt::BlockingQueuedConnection);
|
||||
// Quest only supports one plugin which can't be deactivated currently
|
||||
#if !defined(ANDROID_APP_QUEST_INTERFACE)
|
||||
if (!getActiveDisplayPlugin() || getActiveDisplayPlugin()->isActive() || !getActiveDisplayPlugin()->activate()) {
|
||||
qWarning() << "Could not re-activate display plugin";
|
||||
}
|
||||
#endif
|
||||
auto nodeList = DependencyManager::get<NodeList>();
|
||||
nodeList->setSendDomainServerCheckInEnabled(true);
|
||||
}
|
||||
|
|
|
@ -388,10 +388,23 @@ ShaderPointer Deserializer::readShader(const json& node) {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
static std::map<std::string, uint32_t> shadersIdsByName;
|
||||
if (shadersIdsByName.empty()) {
|
||||
for (const auto id : shader::allShaders()) {
|
||||
const auto& shaderSource = shader::Source::get(id);
|
||||
shadersIdsByName[shaderSource.name] = id;
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME support procedural shaders
|
||||
Shader::Type type = node[keys::type];
|
||||
std::string name = node[keys::name];
|
||||
uint32_t id = node[keys::id];
|
||||
// Using the serialized ID is bad, because it's generated at
|
||||
// cmake time, and can change across platforms or when
|
||||
// shaders are added or removed
|
||||
// uint32_t id = node[keys::id];
|
||||
|
||||
uint32_t id = shadersIdsByName[name];
|
||||
ShaderPointer result;
|
||||
switch (type) {
|
||||
//case Shader::Type::GEOMETRY:
|
||||
|
|
|
@ -167,7 +167,7 @@ TransformObject getTransformObject() {
|
|||
vec4 eyeClipEdge[2]= vec4[2](vec4(-1,0,0,1), vec4(1,0,0,1));
|
||||
vec2 eyeOffsetScale = vec2(-0.5, +0.5);
|
||||
uint eyeIndex = uint(_stereoSide);
|
||||
#ifndef GPU_GLES
|
||||
#if !defined(GPU_GLES) || (defined(HAVE_EXT_clip_cull_distance) && !defined(VULKAN))
|
||||
gl_ClipDistance[0] = dot(<$clipPos$>, eyeClipEdge[eyeIndex]);
|
||||
#endif
|
||||
float newClipPosX = <$clipPos$>.x * 0.5 + eyeOffsetScale[eyeIndex] * <$clipPos$>.w;
|
||||
|
|
|
@ -315,10 +315,6 @@ JNIEXPORT void JNICALL Java_io_highfidelity_oculus_OculusMobileActivity_nativeOn
|
|||
SURFACE.onCreate(env, obj);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_io_highfidelity_oculus_OculusMobileActivity_nativeOnDestroy(JNIEnv*, jclass) {
|
||||
__android_log_write(ANDROID_LOG_WARN, "QQQ_JNI", __FUNCTION__);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_io_highfidelity_oculus_OculusMobileActivity_nativeOnResume(JNIEnv*, jclass) {
|
||||
__android_log_write(ANDROID_LOG_WARN, "QQQ_JNI", __FUNCTION__);
|
||||
SURFACE.setResumed(true);
|
||||
|
|
7
libraries/render-utils/src/parabola_forward.slv
Normal file
7
libraries/render-utils/src/parabola_forward.slv
Normal file
|
@ -0,0 +1,7 @@
|
|||
layout(location=0) in vec4 _color;
|
||||
|
||||
layout(location=0) out vec4 _fragColor0;
|
||||
|
||||
void main(void) {
|
||||
_fragColor0 = _color;
|
||||
}
|
|
@ -1,6 +1,3 @@
|
|||
#version 310 es
|
||||
#define GPU_GLES
|
||||
#define GPU_GLES_310
|
||||
#define BITFIELD highp int
|
||||
#define LAYOUT(X) layout(X)
|
||||
#define LAYOUT_STD140(X) layout(std140, X)
|
||||
|
@ -9,6 +6,9 @@
|
|||
#define gl_VertexID gl_VertexIndex
|
||||
#endif
|
||||
#extension GL_EXT_texture_buffer : enable
|
||||
#if defined(HAVE_EXT_clip_cull_distance) && !defined(VULKAN)
|
||||
#extension GL_EXT_clip_cull_distance : enable
|
||||
#endif
|
||||
precision highp float;
|
||||
precision highp samplerBuffer;
|
||||
precision highp sampler2DShadow;
|
||||
|
|
3
libraries/shaders/headers/310es/version.glsl
Normal file
3
libraries/shaders/headers/310es/version.glsl
Normal file
|
@ -0,0 +1,3 @@
|
|||
#version 310 es
|
||||
#define GPU_GLES
|
||||
#define GPU_GLES_310
|
|
@ -1,5 +1,3 @@
|
|||
#version 410 core
|
||||
#define GPU_GL410
|
||||
#define BITFIELD int
|
||||
#if defined(VULKAN)
|
||||
#extension GL_ARB_shading_language_420pack : require
|
||||
|
|
2
libraries/shaders/headers/410/version.glsl
Normal file
2
libraries/shaders/headers/410/version.glsl
Normal file
|
@ -0,0 +1,2 @@
|
|||
#version 410 core
|
||||
#define GPU_GL410
|
|
@ -1,5 +1,3 @@
|
|||
#version 450 core
|
||||
#define GPU_GL450
|
||||
#define GPU_SSBO_TRANSFORM_OBJECT
|
||||
#define BITFIELD int
|
||||
#define LAYOUT(X) layout(X)
|
||||
|
|
2
libraries/shaders/headers/450/version.glsl
Normal file
2
libraries/shaders/headers/450/version.glsl
Normal file
|
@ -0,0 +1,2 @@
|
|||
#version 450 core
|
||||
#define GPU_GL450
|
|
@ -224,7 +224,7 @@ String Source::getSource(Dialect dialect, Variant variant) const {
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef Q_OS_ANDROID
|
||||
#if defined(Q_OS_ANDROID) || defined(USE_GLES)
|
||||
// SPIRV cross injects "#extension GL_OES_texture_buffer : require" into the GLSL shaders,
|
||||
// which breaks android rendering
|
||||
return variantSource.scribe;
|
||||
|
|
|
@ -24,7 +24,7 @@ QmlFragmentClass::QmlFragmentClass(bool restricted, QString id) : QmlWindowClass
|
|||
|
||||
// Method called by Qt scripts to create a new bottom menu bar in Android
|
||||
QScriptValue QmlFragmentClass::internal_constructor(QScriptContext* context, QScriptEngine* engine, bool restricted) {
|
||||
|
||||
#ifndef DISABLE_QML
|
||||
std::lock_guard<std::mutex> guard(_mutex);
|
||||
auto qml = context->argument(0).toVariant().toMap().value("qml");
|
||||
if (qml.isValid()) {
|
||||
|
@ -53,6 +53,9 @@ QScriptValue QmlFragmentClass::internal_constructor(QScriptContext* context, QSc
|
|||
QScriptValue scriptObject = engine->newQObject(retVal);
|
||||
_fragments[qml.toString()] = scriptObject;
|
||||
return scriptObject;
|
||||
#else
|
||||
return QScriptValue();
|
||||
#endif
|
||||
}
|
||||
|
||||
void QmlFragmentClass::close() {
|
||||
|
@ -61,6 +64,7 @@ void QmlFragmentClass::close() {
|
|||
}
|
||||
|
||||
QObject* QmlFragmentClass::addButton(const QVariant& properties) {
|
||||
#ifndef DISABLE_QML
|
||||
QVariant resultVar;
|
||||
Qt::ConnectionType connectionType = Qt::AutoConnection;
|
||||
|
||||
|
@ -79,8 +83,10 @@ QObject* QmlFragmentClass::addButton(const QVariant& properties) {
|
|||
qWarning() << "QmlFragmentClass addButton result not a QObject";
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return qmlButton;
|
||||
#else
|
||||
return nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
void QmlFragmentClass::removeButton(QObject* button) {
|
||||
|
|
|
@ -98,6 +98,7 @@ QmlWindowClass::QmlWindowClass(bool restricted) : _restricted(restricted) {
|
|||
* @property {boolean} visible
|
||||
*/
|
||||
void QmlWindowClass::initQml(QVariantMap properties) {
|
||||
#ifndef DISABLE_QML
|
||||
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
||||
_source = properties[SOURCE_PROPERTY].toString();
|
||||
|
||||
|
@ -150,6 +151,7 @@ void QmlWindowClass::initQml(QVariantMap properties) {
|
|||
|
||||
Q_ASSERT(_qmlWindow);
|
||||
Q_ASSERT(dynamic_cast<const QQuickItem*>(_qmlWindow.data()));
|
||||
#endif
|
||||
}
|
||||
|
||||
void QmlWindowClass::qmlToScript(const QVariant& message) {
|
||||
|
|
|
@ -58,6 +58,9 @@ logging.setLoggerClass(TrackableLogger)
|
|||
logger = logging.getLogger('prebuild')
|
||||
|
||||
def headSha():
|
||||
if shutil.which('git') is None:
|
||||
logger.warn("Unable to find git executable, can't caclulate commit ID")
|
||||
return '0xDEADBEEF'
|
||||
repo_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
git = subprocess.Popen(
|
||||
'git rev-parse --short HEAD',
|
||||
|
@ -67,7 +70,7 @@ def headSha():
|
|||
stdout, _ = git.communicate()
|
||||
sha = stdout.split('\n')[0]
|
||||
if not sha:
|
||||
raise RuntimeError("couldn't find git sha")
|
||||
raise RuntimeError("couldn't find git sha for repository {}".format(repo_dir))
|
||||
return sha
|
||||
|
||||
@contextmanager
|
||||
|
|
|
@ -49,11 +49,36 @@ def getCommonScribeArgs(scribefile, includeLibs):
|
|||
scribeArgs.append(scribefile)
|
||||
return scribeArgs
|
||||
|
||||
def getDialectAndVariantHeaders(dialect, variant):
|
||||
extensionsHeaderMutex = Lock()
|
||||
|
||||
def getExtensionsHeader(dialect, variant, extensions):
|
||||
extensionHeader = '{}/extensions_{}_{}.glsl'.format(args.build_dir, dialect, variant)
|
||||
global extensionsHeaderMutex
|
||||
extensionsHeaderMutex.acquire()
|
||||
if not os.path.exists(extensionHeader):
|
||||
extensionsDefines = []
|
||||
for extension in extensions:
|
||||
extensionsDefines.append('#define HAVE_{}'.format(extension))
|
||||
# make sure we end with a line feed
|
||||
extensionsDefines.append("\r\n")
|
||||
with open(extensionHeader, "w") as f:
|
||||
f.write('\r\n'.join(extensionsDefines))
|
||||
extensionsHeaderMutex.release()
|
||||
return extensionHeader
|
||||
|
||||
|
||||
def getDialectAndVariantHeaders(dialect, variant, extensions=None):
|
||||
result = []
|
||||
headerPath = args.source_dir + '/libraries/shaders/headers/'
|
||||
variantHeader = headerPath + ('stereo.glsl' if (variant == 'stereo') else 'mono.glsl')
|
||||
versionHeader = headerPath + dialect + '/version.glsl'
|
||||
result.append(versionHeader)
|
||||
if extensions is not None:
|
||||
result.append(getExtensionsHeader(dialect, variant, extensions))
|
||||
dialectHeader = headerPath + dialect + '/header.glsl'
|
||||
return [dialectHeader, variantHeader]
|
||||
result.append(dialectHeader)
|
||||
variantHeader = headerPath + ('stereo.glsl' if (variant == 'stereo') else 'mono.glsl')
|
||||
result.append(variantHeader)
|
||||
return result
|
||||
|
||||
class ScribeDependenciesCache:
|
||||
cache = {}
|
||||
|
@ -170,7 +195,7 @@ def processCommand(line):
|
|||
|
||||
scribeDepCache.gen(scribeFile, libs, dialect, variant)
|
||||
scribeArgs = getCommonScribeArgs(scribeFile, libs)
|
||||
for header in getDialectAndVariantHeaders(dialect, variant):
|
||||
for header in getDialectAndVariantHeaders(dialect, variant, args.extensions):
|
||||
scribeArgs.extend(['-H', header])
|
||||
scribeArgs.extend(['-o', unoptGlslFile])
|
||||
executeSubprocess(scribeArgs)
|
||||
|
@ -218,6 +243,7 @@ def main():
|
|||
|
||||
|
||||
parser = ArgumentParser(description='Generate shader artifacts.')
|
||||
parser.add_argument('--extensions', type=str, nargs='*', help='Available extensions for the shaders')
|
||||
parser.add_argument('--commands', type=argparse.FileType('r'), help='list of commands to execute')
|
||||
parser.add_argument('--tools-dir', type=str, help='location of the host compatible binaries')
|
||||
parser.add_argument('--build-dir', type=str, help='The build directory base path')
|
||||
|
@ -230,8 +256,8 @@ args = None
|
|||
if len(sys.argv) == 1:
|
||||
# for debugging
|
||||
sourceDir = expanduser('~/git/hifi')
|
||||
toolsDir = os.path.join(expanduser('~/git/vcpkg'), 'installed', 'x64-windows', 'tools')
|
||||
buildPath = sourceDir + '/build'
|
||||
toolsDir = 'd:/hifi/vcpkg/android/fd82f0a8/installed/x64-windows/tools'
|
||||
buildPath = sourceDir + '/build_android'
|
||||
commandsPath = buildPath + '/libraries/shaders/shadergen.txt'
|
||||
shaderDir = buildPath + '/libraries/shaders'
|
||||
testArgs = '--commands {} --tools-dir {} --build-dir {} --source-dir {}'.format(
|
||||
|
@ -239,6 +265,7 @@ if len(sys.argv) == 1:
|
|||
).split()
|
||||
testArgs.append('--debug')
|
||||
testArgs.append('--force')
|
||||
testArgs.extend('--extensions EXT_clip_cull_distance'.split())
|
||||
#testArgs.append('--dry-run')
|
||||
args = parser.parse_args(testArgs)
|
||||
else:
|
||||
|
|
Loading…
Reference in a new issue