mirror of
https://github.com/JulianGro/overte.git
synced 2025-04-29 23:23:11 +02:00
Merge branch 'master' into 21863
This commit is contained in:
commit
b74f42dc23
492 changed files with 4657 additions and 2573 deletions
CMakeLists.txt
android/app
build.gradle
src/main
AndroidManifest.xml
assets
cpp
java
io/highfidelity/hifiinterface
GotoActivity.javaHifiUtils.javaHomeActivity.javaInterfaceActivity.javaLoginActivity.javaPermissionChecker.java
QtPreloader
SplashActivity.javaprovider
view
org/qtproject/qt5/android/bindings
res
assignment-client/src
AssignmentClient.cppAssignmentClientMonitor.cppAssignmentDynamic.cppAssignmentFactory.cpp
audio
avatars
AvatarMixer.cppAvatarMixerClientData.cppAvatarMixerSlave.cppAvatarMixerSlave.hAvatarMixerSlavePool.cppScriptableAvatar.cpp
entities
messages
octree
cmake/macros
domain-server/src
gvr-interface/src
interface
resources
html
qml
LoginDialog
dialogs/assetDialog
hifi
shaders
src
AndroidHelper.cppAndroidHelper.hApplication.cppApplication.hApplication_render.cppAvatarBookmarks.cppBookmarks.cppDiscoverabilityManager.cppDiscoverabilityManager.hGLCanvas.cppInterfaceDynamicFactory.cppInterfaceParentFinder.cppLODManager.cppLocationBookmarks.cppLocationBookmarks.hMenu.cppMenu.hModelPackager.cppModelPackager.hModelPropertiesDialog.cppModelSelector.cppSecondaryCamera.cppSecondaryCamera.hSpeechRecognizer.cppSpeechRecognizer.mmUIUtil.cpp
audio
avatar
commerce
|
@ -180,6 +180,7 @@ add_subdirectory(tools)
|
|||
|
||||
if (BUILD_TESTS)
|
||||
add_subdirectory(tests)
|
||||
add_subdirectory(tests-manual)
|
||||
endif()
|
||||
|
||||
if (BUILD_INSTALLER)
|
||||
|
|
|
@ -104,6 +104,11 @@ dependencies {
|
|||
implementation 'com.android.support:design:26.1.0'
|
||||
implementation 'com.android.support:appcompat-v7:26.1.0'
|
||||
compile 'com.android.support:recyclerview-v7:26.1.0'
|
||||
compile 'com.android.support:cardview-v7:26.1.0'
|
||||
|
||||
compile 'com.squareup.retrofit2:retrofit:2.4.0'
|
||||
compile 'com.squareup.retrofit2:converter-gson:2.4.0'
|
||||
implementation 'com.squareup.picasso:picasso:2.71828'
|
||||
|
||||
implementation fileTree(include: ['*.jar'], dir: 'libs')
|
||||
}
|
||||
|
|
|
@ -42,18 +42,18 @@
|
|||
android:name=".HomeActivity"
|
||||
android:label="@string/home"
|
||||
android:screenOrientation="portrait"
|
||||
android:theme="@style/AppTheme.NoActionBar">
|
||||
android:theme="@style/Theme.AppCompat.Translucent.NoActionBar">
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".GotoActivity"
|
||||
android:label="@string/go_to"
|
||||
android:theme="@style/AppTheme">
|
||||
</activity>
|
||||
android:theme="@style/AppTheme" />
|
||||
<activity android:name=".LoginActivity"
|
||||
android:theme="@style/AppTheme"/>
|
||||
<activity
|
||||
android:configChanges="orientation|uiMode|screenLayout|screenSize|smallestScreenSize|locale|fontScale|keyboard|keyboardHidden|navigation"
|
||||
android:name=".InterfaceActivity"
|
||||
android:label="@string/app_name"
|
||||
android:screenOrientation="landscape"
|
||||
android:launchMode="singleTop"
|
||||
>
|
||||
|
||||
|
@ -75,6 +75,11 @@
|
|||
<meta-data
|
||||
android:name="preloaded_fonts"
|
||||
android:resource="@array/preloaded_fonts" />
|
||||
|
||||
<activity
|
||||
android:name=".SplashActivity"
|
||||
android:screenOrientation="portrait"
|
||||
android:theme="@style/Theme.AppCompat.Translucent.NoActionBar" />
|
||||
</application>
|
||||
|
||||
<uses-feature android:name="android.software.vr.mode" android:required="true"/>
|
||||
|
|
|
@ -1,24 +0,0 @@
|
|||
{
|
||||
"hifi_domains" : [
|
||||
{
|
||||
"name": "Your last location",
|
||||
"url": "",
|
||||
"thumbnail": ""
|
||||
},
|
||||
{
|
||||
"name": "dev-mobile-master",
|
||||
"url": "hifi://dev-mobile-master",
|
||||
"thumbnail": ""
|
||||
},
|
||||
{
|
||||
"name": "dev-mobile",
|
||||
"url": "hifi://dev-mobile",
|
||||
"thumbnail": ""
|
||||
},
|
||||
{
|
||||
"name": "dev-welcome",
|
||||
"url": "hifi://dev-welcome",
|
||||
"thumbnail": ""
|
||||
}
|
||||
]
|
||||
}
|
|
@ -21,8 +21,11 @@
|
|||
|
||||
#include <AddressManager.h>
|
||||
#include "AndroidHelper.h"
|
||||
#include <udt/PacketHeaders.h>
|
||||
|
||||
QAndroidJniObject __activity;
|
||||
QAndroidJniObject __interfaceActivity;
|
||||
QAndroidJniObject __loginActivity;
|
||||
QAndroidJniObject __loadCompleteListener;
|
||||
|
||||
void tempMessageHandler(QtMsgType type, const QMessageLogContext& context, const QString& message) {
|
||||
if (!message.isEmpty()) {
|
||||
|
@ -142,16 +145,16 @@ void unpackAndroidAssets() {
|
|||
extern "C" {
|
||||
|
||||
JNIEXPORT void Java_io_highfidelity_hifiinterface_InterfaceActivity_nativeOnCreate(JNIEnv* env, jobject obj, jobject instance, jobject asset_mgr) {
|
||||
qDebug() << "nativeOnCreate On thread " << QThread::currentThreadId();
|
||||
g_assetManager = AAssetManager_fromJava(env, asset_mgr);
|
||||
__activity = QAndroidJniObject(instance);
|
||||
qRegisterMetaType<QAndroidJniObject>("QAndroidJniObject");
|
||||
__interfaceActivity = QAndroidJniObject(instance);
|
||||
auto oldMessageHandler = qInstallMessageHandler(tempMessageHandler);
|
||||
unpackAndroidAssets();
|
||||
qInstallMessageHandler(oldMessageHandler);
|
||||
|
||||
QObject::connect(&AndroidHelper::instance(), &AndroidHelper::androidActivityRequested, [](const QString& a) {
|
||||
QAndroidJniObject string = QAndroidJniObject::fromString(a);
|
||||
__activity.callMethod<void>("openAndroidActivity", "(Ljava/lang/String;)V", string.object<jstring>());
|
||||
__interfaceActivity.callMethod<void>("openAndroidActivity", "(Ljava/lang/String;)V", string.object<jstring>());
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -167,15 +170,12 @@ JNIEXPORT void Java_io_highfidelity_hifiinterface_InterfaceActivity_nativeGotoUr
|
|||
}
|
||||
|
||||
JNIEXPORT void Java_io_highfidelity_hifiinterface_InterfaceActivity_nativeOnPause(JNIEnv* env, jobject obj) {
|
||||
qDebug() << "nativeOnPause";
|
||||
}
|
||||
|
||||
JNIEXPORT void Java_io_highfidelity_hifiinterface_InterfaceActivity_nativeOnResume(JNIEnv* env, jobject obj) {
|
||||
qDebug() << "nativeOnResume";
|
||||
}
|
||||
|
||||
JNIEXPORT void Java_io_highfidelity_hifiinterface_InterfaceActivity_nativeOnExitVr(JNIEnv* env, jobject obj) {
|
||||
qDebug() << "nativeOnCreate On thread " << QThread::currentThreadId();
|
||||
}
|
||||
|
||||
JNIEXPORT void Java_io_highfidelity_hifiinterface_InterfaceActivity_nativeGoBackFromAndroidActivity(JNIEnv *env, jobject instance) {
|
||||
|
@ -204,4 +204,68 @@ JNIEXPORT jstring JNICALL Java_io_highfidelity_hifiinterface_HifiUtils_getCurren
|
|||
return env->NewStringUTF(str.toLatin1().data());
|
||||
}
|
||||
|
||||
JNIEXPORT jstring JNICALL Java_io_highfidelity_hifiinterface_HifiUtils_protocolVersionSignature(JNIEnv *env, jobject instance) {
|
||||
return env->NewStringUTF(protocolVersionsSignatureBase64().toLatin1().data());
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_io_highfidelity_hifiinterface_LoginActivity_nativeLogin(JNIEnv *env, jobject instance,
|
||||
jstring username_, jstring password_) {
|
||||
const char *c_username = env->GetStringUTFChars(username_, 0);
|
||||
const char *c_password = env->GetStringUTFChars(password_, 0);
|
||||
QString username = QString(c_username);
|
||||
QString password = QString(c_password);
|
||||
env->ReleaseStringUTFChars(username_, c_username);
|
||||
env->ReleaseStringUTFChars(password_, c_password);
|
||||
|
||||
auto accountManager = AndroidHelper::instance().getAccountManager();
|
||||
|
||||
__loginActivity = QAndroidJniObject(instance);
|
||||
|
||||
QObject::connect(accountManager.data(), &AccountManager::loginComplete, [](const QUrl& authURL) {
|
||||
jboolean jSuccess = (jboolean) true;
|
||||
__loginActivity.callMethod<void>("handleLoginCompleted", "(Z)V", jSuccess);
|
||||
});
|
||||
|
||||
QObject::connect(accountManager.data(), &AccountManager::loginFailed, []() {
|
||||
jboolean jSuccess = (jboolean) false;
|
||||
__loginActivity.callMethod<void>("handleLoginCompleted", "(Z)V", jSuccess);
|
||||
});
|
||||
|
||||
QMetaObject::invokeMethod(accountManager.data(), "requestAccessToken", Q_ARG(const QString&, username), Q_ARG(const QString&, password));
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_io_highfidelity_hifiinterface_SplashActivity_registerLoadCompleteListener(JNIEnv *env,
|
||||
jobject instance) {
|
||||
|
||||
__loadCompleteListener = QAndroidJniObject(instance);
|
||||
|
||||
QObject::connect(&AndroidHelper::instance(), &AndroidHelper::qtAppLoadComplete, []() {
|
||||
|
||||
__loadCompleteListener.callMethod<void>("onAppLoadedComplete", "()V");
|
||||
__interfaceActivity.callMethod<void>("onAppLoadedComplete", "()V");
|
||||
|
||||
QObject::disconnect(&AndroidHelper::instance(), &AndroidHelper::qtAppLoadComplete, nullptr,
|
||||
nullptr);
|
||||
});
|
||||
|
||||
}
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_io_highfidelity_hifiinterface_HomeActivity_nativeIsLoggedIn(JNIEnv *env, jobject instance) {
|
||||
return AndroidHelper::instance().getAccountManager()->isLoggedIn();
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_io_highfidelity_hifiinterface_HomeActivity_nativeLogout(JNIEnv *env, jobject instance) {
|
||||
AndroidHelper::instance().getAccountManager()->logout();
|
||||
}
|
||||
|
||||
JNIEXPORT jstring JNICALL
|
||||
Java_io_highfidelity_hifiinterface_HomeActivity_nativeGetDisplayName(JNIEnv *env,
|
||||
jobject instance) {
|
||||
QString username = AndroidHelper::instance().getAccountManager()->getAccountInfo().getUsername();
|
||||
return env->NewStringUTF(username.toLatin1().data());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -9,12 +9,8 @@ import android.support.v7.widget.Toolbar;
|
|||
import android.view.KeyEvent;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
import android.widget.EditText;
|
||||
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
|
||||
public class GotoActivity extends AppCompatActivity {
|
||||
|
||||
public static final String PARAM_DOMAIN_URL = "domain_url";
|
||||
|
@ -61,15 +57,7 @@ public class GotoActivity extends AppCompatActivity {
|
|||
private void actionGo() {
|
||||
String urlString = mUrlEditText.getText().toString();
|
||||
if (!urlString.trim().isEmpty()) {
|
||||
URI uri;
|
||||
try {
|
||||
uri = new URI(urlString);
|
||||
} catch (URISyntaxException e) {
|
||||
return;
|
||||
}
|
||||
if (uri.getScheme() == null || uri.getScheme().isEmpty()) {
|
||||
urlString = "hifi://" + urlString;
|
||||
}
|
||||
urlString = HifiUtils.getInstance().sanitizeHifiUrl(urlString);
|
||||
|
||||
Intent intent = new Intent();
|
||||
intent.putExtra(GotoActivity.PARAM_DOMAIN_URL, urlString);
|
||||
|
|
|
@ -1,11 +1,16 @@
|
|||
package io.highfidelity.hifiinterface;
|
||||
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
|
||||
/**
|
||||
* Created by Gabriel Calero & Cristian Duarte on 4/13/18.
|
||||
*/
|
||||
|
||||
public class HifiUtils {
|
||||
|
||||
public static final String BASE_URL = "https://metaverse.highfidelity.com";
|
||||
|
||||
private static HifiUtils instance;
|
||||
|
||||
private HifiUtils() {
|
||||
|
@ -18,6 +23,40 @@ public class HifiUtils {
|
|||
return instance;
|
||||
}
|
||||
|
||||
public String sanitizeHifiUrl(String urlString) {
|
||||
urlString = urlString.trim();
|
||||
if (!urlString.isEmpty()) {
|
||||
URI uri;
|
||||
try {
|
||||
uri = new URI(urlString);
|
||||
} catch (URISyntaxException e) {
|
||||
return urlString;
|
||||
}
|
||||
if (uri.getScheme() == null || uri.getScheme().isEmpty()) {
|
||||
urlString = "hifi://" + urlString;
|
||||
}
|
||||
}
|
||||
return urlString;
|
||||
}
|
||||
|
||||
public String absoluteHifiAssetUrl(String urlString) {
|
||||
urlString = urlString.trim();
|
||||
if (!urlString.isEmpty()) {
|
||||
URI uri;
|
||||
try {
|
||||
uri = new URI(urlString);
|
||||
} catch (URISyntaxException e) {
|
||||
return urlString;
|
||||
}
|
||||
if (uri.getScheme() == null || uri.getScheme().isEmpty()) {
|
||||
urlString = BASE_URL + urlString;
|
||||
}
|
||||
}
|
||||
return urlString;
|
||||
}
|
||||
|
||||
public native String getCurrentAddress();
|
||||
|
||||
public native String protocolVersionSignature();
|
||||
|
||||
}
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
package io.highfidelity.hifiinterface;
|
||||
|
||||
import android.app.ProgressDialog;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Color;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.design.widget.NavigationView;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.support.v4.view.GravityCompat;
|
||||
import android.support.v4.widget.DrawerLayout;
|
||||
import android.support.v7.app.ActionBar;
|
||||
|
@ -14,30 +13,43 @@ import android.support.v7.app.AppCompatActivity;
|
|||
import android.support.v7.widget.GridLayoutManager;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
import android.text.Editable;
|
||||
import android.text.TextWatcher;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.SearchView;
|
||||
import android.widget.TabHost;
|
||||
import android.widget.TabWidget;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.EditText;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import io.highfidelity.hifiinterface.QtPreloader.QtPreloader;
|
||||
import org.qtproject.qt5.android.bindings.QtActivity;
|
||||
|
||||
import io.highfidelity.hifiinterface.view.DomainAdapter;
|
||||
|
||||
public class HomeActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener {
|
||||
|
||||
public native boolean nativeIsLoggedIn();
|
||||
public native void nativeLogout();
|
||||
public native String nativeGetDisplayName();
|
||||
|
||||
/**
|
||||
* Set this intent extra param to NOT start a new InterfaceActivity after a domain is selected"
|
||||
*/
|
||||
public static final String PARAM_NOT_START_INTERFACE_ACTIVITY = "not_start_interface_activity";
|
||||
//public static final String PARAM_NOT_START_INTERFACE_ACTIVITY = "not_start_interface_activity";
|
||||
|
||||
public static final int ENTER_DOMAIN_URL = 1;
|
||||
|
||||
private DomainAdapter domainAdapter;
|
||||
private DomainAdapter mDomainAdapter;
|
||||
private DrawerLayout mDrawerLayout;
|
||||
private ProgressDialog mDialog;
|
||||
private NavigationView mNavigationView;
|
||||
private RecyclerView mDomainsView;
|
||||
private TextView searchNoResultsView;
|
||||
private ImageView mSearchIconView;
|
||||
private ImageView mClearSearch;
|
||||
private EditText mSearchView;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
|
@ -56,114 +68,111 @@ public class HomeActivity extends AppCompatActivity implements NavigationView.On
|
|||
mNavigationView = (NavigationView) findViewById(R.id.nav_view);
|
||||
mNavigationView.setNavigationItemSelectedListener(this);
|
||||
|
||||
TabHost tabs = (TabHost)findViewById(R.id.tabhost);
|
||||
tabs.setup();
|
||||
searchNoResultsView = findViewById(R.id.searchNoResultsView);
|
||||
|
||||
TabHost.TabSpec spec=tabs.newTabSpec("featured");
|
||||
spec.setContent(R.id.featured);
|
||||
spec.setIndicator(getString(R.string.featured));
|
||||
tabs.addTab(spec);
|
||||
|
||||
spec = tabs.newTabSpec("popular");
|
||||
spec.setContent(R.id.popular);
|
||||
spec.setIndicator(getString(R.string.popular));
|
||||
tabs.addTab(spec);
|
||||
|
||||
spec = tabs.newTabSpec("bookmarks");
|
||||
spec.setContent(R.id.bookmarks);
|
||||
spec.setIndicator(getString(R.string.bookmarks));
|
||||
tabs.addTab(spec);
|
||||
|
||||
tabs.setCurrentTab(0);
|
||||
|
||||
TabWidget tabwidget=tabs.getTabWidget();
|
||||
for(int i=0; i<tabwidget.getChildCount(); i++){
|
||||
TextView tv=(TextView) tabwidget.getChildAt(i).findViewById(android.R.id.title);
|
||||
tv.setTextAppearance(R.style.TabText);
|
||||
}
|
||||
|
||||
|
||||
RecyclerView domainsView = findViewById(R.id.rvDomains);
|
||||
mDomainsView = findViewById(R.id.rvDomains);
|
||||
int numberOfColumns = 1;
|
||||
GridLayoutManager gridLayoutMgr = new GridLayoutManager(this, numberOfColumns);
|
||||
domainsView.setLayoutManager(gridLayoutMgr);
|
||||
domainAdapter = new DomainAdapter(this);
|
||||
domainAdapter.setClickListener(new DomainAdapter.ItemClickListener() {
|
||||
mDomainsView.setLayoutManager(gridLayoutMgr);
|
||||
mDomainAdapter = new DomainAdapter(this, HifiUtils.getInstance().protocolVersionSignature());
|
||||
mDomainAdapter.setClickListener(new DomainAdapter.ItemClickListener() {
|
||||
|
||||
@Override
|
||||
public void onItemClick(View view, int position, DomainAdapter.Domain domain) {
|
||||
gotoDomain(domain.url);
|
||||
new Handler(getMainLooper()).postDelayed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
gotoDomain(domain.url);
|
||||
}
|
||||
}, 400); // a delay so the ripple effect can be seen
|
||||
}
|
||||
});
|
||||
domainsView.setAdapter(domainAdapter);
|
||||
mDomainAdapter.setListener(new DomainAdapter.AdapterListener() {
|
||||
@Override
|
||||
public void onEmptyAdapter() {
|
||||
searchNoResultsView.setText(R.string.search_no_results);
|
||||
searchNoResultsView.setVisibility(View.VISIBLE);
|
||||
mDomainsView.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
SearchView searchView = findViewById(R.id.searchView);
|
||||
int searchPlateId = searchView.getContext().getResources().getIdentifier("android:id/search_plate", null, null);
|
||||
View searchPlate = searchView.findViewById(searchPlateId);
|
||||
if (searchPlate != null) {
|
||||
searchPlate.setBackgroundColor (Color.TRANSPARENT);
|
||||
int searchTextId = searchPlate.getContext ().getResources ().getIdentifier ("android:id/search_src_text", null, null);
|
||||
TextView searchTextView = searchView.findViewById(searchTextId);
|
||||
searchTextView.setTextAppearance(R.style.SearchText);
|
||||
@Override
|
||||
public void onNonEmptyAdapter() {
|
||||
searchNoResultsView.setVisibility(View.GONE);
|
||||
mDomainsView.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(Exception e, String message) {
|
||||
|
||||
}
|
||||
});
|
||||
mDomainsView.setAdapter(mDomainAdapter);
|
||||
|
||||
mSearchView = findViewById(R.id.searchView);
|
||||
mSearchIconView = findViewById(R.id.search_mag_icon);
|
||||
mClearSearch = findViewById(R.id.search_clear);
|
||||
|
||||
mSearchView.addTextChangedListener(new TextWatcher() {
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {}
|
||||
|
||||
@Override
|
||||
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {}
|
||||
|
||||
@Override
|
||||
public void afterTextChanged(Editable editable) {
|
||||
mDomainAdapter.loadDomains(editable.toString());
|
||||
if (editable.length() > 0) {
|
||||
mSearchIconView.setVisibility(View.GONE);
|
||||
mClearSearch.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
mSearchIconView.setVisibility(View.VISIBLE);
|
||||
mClearSearch.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
});
|
||||
mSearchView.setOnKeyListener((view, i, keyEvent) -> {
|
||||
if (i == KeyEvent.KEYCODE_ENTER) {
|
||||
String urlString = mSearchView.getText().toString();
|
||||
if (!urlString.trim().isEmpty()) {
|
||||
urlString = HifiUtils.getInstance().sanitizeHifiUrl(urlString);
|
||||
}
|
||||
gotoDomain(urlString);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
|
||||
|
||||
updateLoginMenu();
|
||||
|
||||
Window window = getWindow();
|
||||
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
|
||||
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
|
||||
window.setStatusBarColor(ContextCompat.getColor(this, R.color.statusbar_color));
|
||||
}
|
||||
|
||||
private void updateLoginMenu() {
|
||||
TextView loginOption = findViewById(R.id.login);
|
||||
TextView logoutOption = findViewById(R.id.logout);
|
||||
if (nativeIsLoggedIn()) {
|
||||
loginOption.setVisibility(View.GONE);
|
||||
logoutOption.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
loginOption.setVisibility(View.VISIBLE);
|
||||
logoutOption.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
if (getIntent() == null ||
|
||||
!getIntent().hasExtra(PARAM_NOT_START_INTERFACE_ACTIVITY) ||
|
||||
!getIntent().getBooleanExtra(PARAM_NOT_START_INTERFACE_ACTIVITY, false)) {
|
||||
preloadQt();
|
||||
showActivityIndicator();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void gotoDomain(String domainUrl) {
|
||||
Intent intent = new Intent(HomeActivity.this, InterfaceActivity.class);
|
||||
intent.putExtra(InterfaceActivity.DOMAIN_URL, domainUrl);
|
||||
HomeActivity.this.finish();
|
||||
if (getIntent() != null &&
|
||||
getIntent().hasExtra(PARAM_NOT_START_INTERFACE_ACTIVITY) &&
|
||||
getIntent().getBooleanExtra(PARAM_NOT_START_INTERFACE_ACTIVITY, false)) {
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
|
||||
}
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
|
||||
startActivity(intent);
|
||||
}
|
||||
|
||||
private void showActivityIndicator() {
|
||||
if (mDialog == null) {
|
||||
mDialog = new ProgressDialog(this);
|
||||
}
|
||||
mDialog.setMessage("Please wait...");
|
||||
mDialog.setCancelable(false);
|
||||
mDialog.show();
|
||||
}
|
||||
|
||||
private void cancelActivityIndicator() {
|
||||
if (mDialog != null) {
|
||||
mDialog.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
private AsyncTask preloadTask;
|
||||
|
||||
private void preloadQt() {
|
||||
if (preloadTask == null) {
|
||||
preloadTask = new AsyncTask() {
|
||||
@Override
|
||||
protected Object doInBackground(Object[] objects) {
|
||||
new QtPreloader(HomeActivity.this).initQt();
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
cancelActivityIndicator();
|
||||
}
|
||||
});
|
||||
return null;
|
||||
}
|
||||
};
|
||||
preloadTask.execute();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
// Inflate the menu; this adds items to the action bar if it is present.
|
||||
|
@ -188,7 +197,6 @@ public class HomeActivity extends AppCompatActivity implements NavigationView.On
|
|||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
cancelActivityIndicator();
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
|
@ -199,8 +207,6 @@ public class HomeActivity extends AppCompatActivity implements NavigationView.On
|
|||
Intent i = new Intent(this, GotoActivity.class);
|
||||
startActivityForResult(i, ENTER_DOMAIN_URL);
|
||||
return true;
|
||||
case R.id.action_settings:
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -213,8 +219,27 @@ public class HomeActivity extends AppCompatActivity implements NavigationView.On
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
updateLoginMenu();
|
||||
}
|
||||
|
||||
public void onLoginClicked(View view) {
|
||||
Intent intent = new Intent(this, LoginActivity.class);
|
||||
startActivity(intent);
|
||||
}
|
||||
|
||||
public void onLogoutClicked(View view) {
|
||||
nativeLogout();
|
||||
updateLoginMenu();
|
||||
}
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
finishAffinity();
|
||||
}
|
||||
|
||||
public void onSearchClear(View view) {
|
||||
mSearchView.setText("");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,8 +36,6 @@ public class InterfaceActivity extends QtActivity {
|
|||
|
||||
//public static native void handleHifiURL(String hifiURLString);
|
||||
private native long nativeOnCreate(InterfaceActivity instance, AssetManager assetManager);
|
||||
//private native void nativeOnPause();
|
||||
//private native void nativeOnResume();
|
||||
private native void nativeOnDestroy();
|
||||
private native void nativeGotoUrl(String url);
|
||||
private native void nativeGoBackFromAndroidActivity();
|
||||
|
@ -63,6 +61,7 @@ public class InterfaceActivity extends QtActivity {
|
|||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.isLoading = true;
|
||||
Intent intent = getIntent();
|
||||
if (intent.hasExtra(DOMAIN_URL) && !intent.getStringExtra(DOMAIN_URL).isEmpty()) {
|
||||
intent.putExtra("applicationArguments", "--url " + intent.getStringExtra(DOMAIN_URL));
|
||||
|
@ -112,31 +111,33 @@ public class InterfaceActivity extends QtActivity {
|
|||
}
|
||||
}
|
||||
});
|
||||
startActivity(new Intent(this, SplashActivity.class));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
//nativeOnPause();
|
||||
nativeEnterBackground();
|
||||
//gvrApi.pauseTracking();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
nativeEnterForeground();
|
||||
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
nativeEnterBackground();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
//nativeOnResume();
|
||||
nativeEnterForeground();
|
||||
//gvrApi.resumeTracking();
|
||||
}
|
||||
|
||||
|
@ -201,7 +202,6 @@ public class InterfaceActivity extends QtActivity {
|
|||
switch (activityName) {
|
||||
case "Home": {
|
||||
Intent intent = new Intent(this, HomeActivity.class);
|
||||
intent.putExtra(HomeActivity.PARAM_NOT_START_INTERFACE_ACTIVITY, true);
|
||||
startActivity(intent);
|
||||
break;
|
||||
}
|
||||
|
@ -212,6 +212,10 @@ public class InterfaceActivity extends QtActivity {
|
|||
}
|
||||
}
|
||||
|
||||
public void onAppLoadedComplete() {
|
||||
super.isLoading = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
openAndroidActivity("Home");
|
||||
|
|
|
@ -0,0 +1,106 @@
|
|||
package io.highfidelity.hifiinterface;
|
||||
|
||||
import android.app.ProgressDialog;
|
||||
import android.support.annotation.MainThread;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.View;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
public class LoginActivity extends AppCompatActivity {
|
||||
|
||||
public native void nativeLogin(String username, String password);
|
||||
|
||||
private EditText mUsername;
|
||||
private EditText mPassword;
|
||||
private TextView mError;
|
||||
private Button mLoginButton;
|
||||
|
||||
private ProgressDialog mDialog;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_login);
|
||||
|
||||
mUsername = findViewById(R.id.username);
|
||||
mPassword = findViewById(R.id.password);
|
||||
mError = findViewById(R.id.error);
|
||||
mLoginButton = findViewById(R.id.loginButton);
|
||||
|
||||
mPassword.setOnEditorActionListener(
|
||||
new TextView.OnEditorActionListener() {
|
||||
@Override
|
||||
public boolean onEditorAction(TextView textView, int actionId, KeyEvent keyEvent) {
|
||||
if (actionId == EditorInfo.IME_ACTION_DONE) {
|
||||
mLoginButton.performClick();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
cancelActivityIndicator();
|
||||
}
|
||||
|
||||
public void login(View view) {
|
||||
String username = mUsername.getText().toString();
|
||||
String password = mPassword.getText().toString();
|
||||
if (username.isEmpty() || password.isEmpty()) {
|
||||
showError(getString(R.string.login_username_or_password_incorrect));
|
||||
} else {
|
||||
mLoginButton.setEnabled(false);
|
||||
hideError();
|
||||
showActivityIndicator();
|
||||
nativeLogin(username, password);
|
||||
}
|
||||
}
|
||||
|
||||
private void showActivityIndicator() {
|
||||
if (mDialog == null) {
|
||||
mDialog = new ProgressDialog(this);
|
||||
}
|
||||
mDialog.setMessage(getString(R.string.logging_in));
|
||||
mDialog.setCancelable(false);
|
||||
mDialog.show();
|
||||
}
|
||||
|
||||
private void cancelActivityIndicator() {
|
||||
if (mDialog != null) {
|
||||
mDialog.cancel();
|
||||
}
|
||||
}
|
||||
private void showError(String error) {
|
||||
mError.setText(error);
|
||||
mError.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
private void hideError() {
|
||||
mError.setText("");
|
||||
mError.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
|
||||
public void handleLoginCompleted(boolean success) {
|
||||
runOnUiThread(() -> {
|
||||
mLoginButton.setEnabled(true);
|
||||
cancelActivityIndicator();
|
||||
if (success) {
|
||||
finish();
|
||||
} else {
|
||||
showError(getString(R.string.login_username_or_password_incorrect));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
|
@ -63,8 +63,7 @@ public class PermissionChecker extends Activity {
|
|||
}
|
||||
|
||||
private void launchActivityWithPermissions(){
|
||||
finish();
|
||||
Intent i = new Intent(this, HomeActivity.class);
|
||||
Intent i = new Intent(this, InterfaceActivity.class);
|
||||
startActivity(i);
|
||||
finish();
|
||||
}
|
||||
|
|
|
@ -1,315 +0,0 @@
|
|||
package io.highfidelity.hifiinterface.QtPreloader;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.pm.ComponentInfo;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.res.AssetManager;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
|
||||
import org.qtproject.qt5.android.bindings.QtApplication;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import dalvik.system.DexClassLoader;
|
||||
|
||||
/**
|
||||
* Created by Gabriel Calero & Cristian Duarte on 3/22/18.
|
||||
*/
|
||||
|
||||
public class QtPreloader {
|
||||
|
||||
public String ENVIRONMENT_VARIABLES = "QT_USE_ANDROID_NATIVE_DIALOGS=1";
|
||||
private ComponentInfo m_contextInfo;
|
||||
private String[] m_qtLibs = null; // required qt libs
|
||||
private Context m_context;
|
||||
|
||||
private static final String DEX_PATH_KEY = "dex.path";
|
||||
private static final String LIB_PATH_KEY = "lib.path";
|
||||
private static final String NATIVE_LIBRARIES_KEY = "native.libraries";
|
||||
private static final String ENVIRONMENT_VARIABLES_KEY = "environment.variables";
|
||||
private static final String BUNDLED_LIBRARIES_KEY = "bundled.libraries";
|
||||
private static final String BUNDLED_IN_LIB_RESOURCE_ID_KEY = "android.app.bundled_in_lib_resource_id";
|
||||
private static final String BUNDLED_IN_ASSETS_RESOURCE_ID_KEY = "android.app.bundled_in_assets_resource_id";
|
||||
private static final String MAIN_LIBRARY_KEY = "main.library";
|
||||
|
||||
private static final int BUFFER_SIZE = 1024;
|
||||
|
||||
public QtPreloader(Context context) {
|
||||
m_context = context;
|
||||
}
|
||||
|
||||
public void initQt() {
|
||||
|
||||
try {
|
||||
m_contextInfo = m_context.getPackageManager().getActivityInfo(new ComponentName("io.highfidelity.hifiinterface", "io.highfidelity.hifiinterface.InterfaceActivity"),
|
||||
PackageManager.GET_META_DATA);
|
||||
|
||||
if (m_contextInfo.metaData.containsKey("android.app.qt_libs_resource_id")) {
|
||||
int resourceId = m_contextInfo.metaData.getInt("android.app.qt_libs_resource_id");
|
||||
m_qtLibs = m_context.getResources().getStringArray(resourceId);
|
||||
}
|
||||
ArrayList<String> libraryList = new ArrayList<>();
|
||||
String localPrefix = m_context.getApplicationInfo().dataDir + "/";
|
||||
String pluginsPrefix = localPrefix + "qt-reserved-files/";
|
||||
cleanOldCacheIfNecessary(localPrefix, pluginsPrefix);
|
||||
extractBundledPluginsAndImports(pluginsPrefix);
|
||||
|
||||
for (String lib : m_qtLibs) {
|
||||
libraryList.add(localPrefix + "lib/lib" + lib + ".so");
|
||||
}
|
||||
|
||||
if (m_contextInfo.metaData.containsKey("android.app.load_local_libs")) {
|
||||
String[] extraLibs = m_contextInfo.metaData.getString("android.app.load_local_libs").split(":");
|
||||
for (String lib : extraLibs) {
|
||||
if (lib.length() > 0) {
|
||||
if (lib.startsWith("lib/")) {
|
||||
libraryList.add(localPrefix + lib);
|
||||
} else {
|
||||
libraryList.add(pluginsPrefix + lib);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Bundle loaderParams = new Bundle();
|
||||
loaderParams.putString(DEX_PATH_KEY, new String());
|
||||
|
||||
loaderParams.putStringArrayList(NATIVE_LIBRARIES_KEY, libraryList);
|
||||
|
||||
loaderParams.putString(ENVIRONMENT_VARIABLES_KEY, ENVIRONMENT_VARIABLES
|
||||
+ "\tQML2_IMPORT_PATH=" + pluginsPrefix + "/qml"
|
||||
+ "\tQML_IMPORT_PATH=" + pluginsPrefix + "/imports"
|
||||
+ "\tQT_PLUGIN_PATH=" + pluginsPrefix + "/plugins");
|
||||
|
||||
|
||||
// add all bundled Qt libs to loader params
|
||||
ArrayList<String> libs = new ArrayList<>();
|
||||
|
||||
String libName = m_contextInfo.metaData.getString("android.app.lib_name");
|
||||
loaderParams.putString(MAIN_LIBRARY_KEY, libName); //main library contains main() function
|
||||
loaderParams.putStringArrayList(BUNDLED_LIBRARIES_KEY, libs);
|
||||
|
||||
// load and start QtLoader class
|
||||
DexClassLoader classLoader = new DexClassLoader(loaderParams.getString(DEX_PATH_KEY), // .jar/.apk files
|
||||
m_context.getDir("outdex", Context.MODE_PRIVATE).getAbsolutePath(), // directory where optimized DEX files should be written.
|
||||
loaderParams.containsKey(LIB_PATH_KEY) ? loaderParams.getString(LIB_PATH_KEY) : null, // libs folder (if exists)
|
||||
m_context.getClassLoader()); // parent loader
|
||||
|
||||
Class<?> loaderClass = classLoader.loadClass(loaderClassName()); // load QtLoader class
|
||||
Object qtLoader = loaderClass.newInstance(); // create an instance
|
||||
Method prepareAppMethod = qtLoader.getClass().getMethod("loadApplication",
|
||||
contextClassName(),
|
||||
ClassLoader.class,
|
||||
Bundle.class);
|
||||
prepareAppMethod.invoke(qtLoader, m_context, classLoader, loaderParams);
|
||||
|
||||
// now load the application library so it's accessible from this class loader
|
||||
if (libName != null) {
|
||||
System.loadLibrary(libName);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.e(QtApplication.QtTAG, "Error pre-loading HiFi Qt app", e);
|
||||
}
|
||||
}
|
||||
|
||||
protected String loaderClassName() {
|
||||
return "org.qtproject.qt5.android.QtActivityDelegate";
|
||||
}
|
||||
|
||||
protected Class<?> contextClassName() {
|
||||
return android.app.Activity.class;
|
||||
}
|
||||
|
||||
|
||||
private void deleteRecursively(File directory) {
|
||||
File[] files = directory.listFiles();
|
||||
if (files != null) {
|
||||
for (File file : files) {
|
||||
if (file.isDirectory()) {
|
||||
deleteRecursively(file);
|
||||
} else {
|
||||
file.delete();
|
||||
}
|
||||
}
|
||||
|
||||
directory.delete();
|
||||
}
|
||||
}
|
||||
|
||||
private void cleanOldCacheIfNecessary(String oldLocalPrefix, String localPrefix) {
|
||||
File newCache = new File(localPrefix);
|
||||
if (!newCache.exists()) {
|
||||
{
|
||||
File oldPluginsCache = new File(oldLocalPrefix + "plugins/");
|
||||
if (oldPluginsCache.exists() && oldPluginsCache.isDirectory()) {
|
||||
deleteRecursively(oldPluginsCache);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
File oldImportsCache = new File(oldLocalPrefix + "imports/");
|
||||
if (oldImportsCache.exists() && oldImportsCache.isDirectory()) {
|
||||
deleteRecursively(oldImportsCache);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
File oldQmlCache = new File(oldLocalPrefix + "qml/");
|
||||
if (oldQmlCache.exists() && oldQmlCache.isDirectory()) {
|
||||
deleteRecursively(oldQmlCache);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static private void copyFile(InputStream inputStream, OutputStream outputStream)
|
||||
throws IOException {
|
||||
byte[] buffer = new byte[BUFFER_SIZE];
|
||||
|
||||
int count;
|
||||
while ((count = inputStream.read(buffer)) > 0) {
|
||||
outputStream.write(buffer, 0, count);
|
||||
}
|
||||
}
|
||||
|
||||
private void copyAsset(String source, String destination)
|
||||
throws IOException {
|
||||
// Already exists, we don't have to do anything
|
||||
File destinationFile = new File(destination);
|
||||
if (destinationFile.exists()) {
|
||||
return;
|
||||
}
|
||||
|
||||
File parentDirectory = destinationFile.getParentFile();
|
||||
if (!parentDirectory.exists()) {
|
||||
parentDirectory.mkdirs();
|
||||
}
|
||||
|
||||
destinationFile.createNewFile();
|
||||
|
||||
AssetManager assetsManager = m_context.getAssets();
|
||||
InputStream inputStream = assetsManager.open(source);
|
||||
OutputStream outputStream = new FileOutputStream(destinationFile);
|
||||
copyFile(inputStream, outputStream);
|
||||
|
||||
inputStream.close();
|
||||
outputStream.close();
|
||||
}
|
||||
|
||||
private static void createBundledBinary(String source, String destination)
|
||||
throws IOException {
|
||||
// Already exists, we don't have to do anything
|
||||
File destinationFile = new File(destination);
|
||||
if (destinationFile.exists()) {
|
||||
return;
|
||||
}
|
||||
|
||||
File parentDirectory = destinationFile.getParentFile();
|
||||
if (!parentDirectory.exists()) {
|
||||
parentDirectory.mkdirs();
|
||||
}
|
||||
|
||||
destinationFile.createNewFile();
|
||||
|
||||
InputStream inputStream = new FileInputStream(source);
|
||||
OutputStream outputStream = new FileOutputStream(destinationFile);
|
||||
copyFile(inputStream, outputStream);
|
||||
|
||||
inputStream.close();
|
||||
outputStream.close();
|
||||
}
|
||||
|
||||
private boolean cleanCacheIfNecessary(String pluginsPrefix, long packageVersion) {
|
||||
File versionFile = new File(pluginsPrefix + "cache.version");
|
||||
|
||||
long cacheVersion = 0;
|
||||
if (versionFile.exists() && versionFile.canRead()) {
|
||||
try {
|
||||
DataInputStream inputStream = new DataInputStream(new FileInputStream(versionFile));
|
||||
cacheVersion = inputStream.readLong();
|
||||
inputStream.close();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (cacheVersion != packageVersion) {
|
||||
deleteRecursively(new File(pluginsPrefix));
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private void extractBundledPluginsAndImports(String pluginsPrefix) throws IOException {
|
||||
String libsDir = m_context.getApplicationInfo().nativeLibraryDir + "/";
|
||||
long packageVersion = -1;
|
||||
try {
|
||||
PackageInfo packageInfo = m_context.getPackageManager().getPackageInfo(m_context.getPackageName(), 0);
|
||||
packageVersion = packageInfo.lastUpdateTime;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
|
||||
if (!cleanCacheIfNecessary(pluginsPrefix, packageVersion)) {
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
File versionFile = new File(pluginsPrefix + "cache.version");
|
||||
|
||||
File parentDirectory = versionFile.getParentFile();
|
||||
if (!parentDirectory.exists()) {
|
||||
parentDirectory.mkdirs();
|
||||
}
|
||||
|
||||
versionFile.createNewFile();
|
||||
|
||||
DataOutputStream outputStream = new DataOutputStream(new FileOutputStream(versionFile));
|
||||
outputStream.writeLong(packageVersion);
|
||||
outputStream.close();
|
||||
}
|
||||
|
||||
{
|
||||
String key = BUNDLED_IN_LIB_RESOURCE_ID_KEY;
|
||||
if (m_contextInfo.metaData.containsKey(key)) {
|
||||
String[] list = m_context.getResources().getStringArray(m_contextInfo.metaData.getInt(key));
|
||||
|
||||
for (String bundledImportBinary : list) {
|
||||
String[] split = bundledImportBinary.split(":");
|
||||
String sourceFileName = libsDir + split[0];
|
||||
String destinationFileName = pluginsPrefix + split[1];
|
||||
createBundledBinary(sourceFileName, destinationFileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
String key = BUNDLED_IN_ASSETS_RESOURCE_ID_KEY;
|
||||
if (m_contextInfo.metaData.containsKey(key)) {
|
||||
String[] list = m_context.getResources().getStringArray(m_contextInfo.metaData.getInt(key));
|
||||
|
||||
for (String fileName : list) {
|
||||
String[] split = fileName.split(":");
|
||||
String sourceFileName = split[0];
|
||||
String destinationFileName = pluginsPrefix + split[1];
|
||||
copyAsset(sourceFileName, destinationFileName);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
package io.highfidelity.hifiinterface;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
|
||||
public class SplashActivity extends Activity {
|
||||
|
||||
private native void registerLoadCompleteListener();
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_splash);
|
||||
registerLoadCompleteListener();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
}
|
||||
|
||||
public void onAppLoadedComplete() {
|
||||
startActivity(new Intent(this, HomeActivity.class)); // + 2 sec
|
||||
SplashActivity.this.finish();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
package io.highfidelity.hifiinterface.provider;
|
||||
|
||||
/**
|
||||
* Created by cduarte on 4/18/18.
|
||||
*/
|
||||
|
||||
public interface Callback<T> {
|
||||
public void callback(T t);
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
package io.highfidelity.hifiinterface.provider;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import io.highfidelity.hifiinterface.view.DomainAdapter;
|
||||
|
||||
/**
|
||||
* Created by cduarte on 4/17/18.
|
||||
*/
|
||||
|
||||
public interface DomainProvider {
|
||||
|
||||
void retrieve(String filterText, DomainCallback domainCallback);
|
||||
|
||||
interface DomainCallback {
|
||||
void retrieveOk(List<DomainAdapter.Domain> domain);
|
||||
void retrieveError(Exception e, String message);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,235 @@
|
|||
package io.highfidelity.hifiinterface.provider;
|
||||
|
||||
import android.util.Log;
|
||||
import android.util.MutableInt;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import io.highfidelity.hifiinterface.HifiUtils;
|
||||
import io.highfidelity.hifiinterface.view.DomainAdapter;
|
||||
import retrofit2.Call;
|
||||
import retrofit2.Response;
|
||||
import retrofit2.Retrofit;
|
||||
import retrofit2.converter.gson.GsonConverterFactory;
|
||||
import retrofit2.http.GET;
|
||||
import retrofit2.http.Query;
|
||||
|
||||
/**
|
||||
* Created by cduarte on 4/17/18.
|
||||
*/
|
||||
|
||||
public class UserStoryDomainProvider implements DomainProvider {
|
||||
|
||||
public static final String BASE_URL = "https://metaverse.highfidelity.com/";
|
||||
|
||||
private static final String INCLUDE_ACTIONS_FOR_PLACES = "concurrency";
|
||||
private static final String INCLUDE_ACTIONS_FOR_FULL_SEARCH = "concurrency,announcements,snapshot";
|
||||
private static final int MAX_PAGES_TO_GET = 10;
|
||||
|
||||
private String mProtocol;
|
||||
private Retrofit mRetrofit;
|
||||
private UserStoryDomainProviderService mUserStoryDomainProviderService;
|
||||
|
||||
private boolean startedToGetFromAPI = false;
|
||||
private List<UserStory> allStories; // All retrieved stories from the API
|
||||
private List<DomainAdapter.Domain> suggestions; // Filtered places to show
|
||||
|
||||
public UserStoryDomainProvider(String protocol) {
|
||||
mRetrofit = new Retrofit.Builder()
|
||||
.baseUrl(BASE_URL)
|
||||
.addConverterFactory(GsonConverterFactory.create())
|
||||
.build();
|
||||
mUserStoryDomainProviderService = mRetrofit.create(UserStoryDomainProviderService.class);
|
||||
mProtocol = protocol;
|
||||
allStories = new ArrayList<>();
|
||||
suggestions = new ArrayList<>();
|
||||
}
|
||||
|
||||
private void fillDestinations(String filterText, DomainCallback domainCallback) {
|
||||
StoriesFilter filter = new StoriesFilter(filterText);
|
||||
final MutableInt counter = new MutableInt(0);
|
||||
allStories.clear();
|
||||
getUserStoryPage(1,
|
||||
e -> {
|
||||
allStories.subList(counter.value, allStories.size()).forEach(userStory -> {
|
||||
filter.filterOrAdd(userStory);
|
||||
});
|
||||
if (domainCallback != null) {
|
||||
domainCallback.retrieveOk(suggestions); //ended
|
||||
}
|
||||
},
|
||||
a -> {
|
||||
allStories.forEach(userStory -> {
|
||||
counter.value++;
|
||||
filter.filterOrAdd(userStory);
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
private void handleError(String url, Throwable t, Callback<Exception> restOfPagesCallback) {
|
||||
restOfPagesCallback.callback(new Exception("Error accessing url [" + url + "]", t));
|
||||
}
|
||||
|
||||
private void getUserStoryPage(int pageNumber, Callback<Exception> restOfPagesCallback, Callback<Void> firstPageCallback) {
|
||||
Call<UserStories> userStories = mUserStoryDomainProviderService.getUserStories(
|
||||
INCLUDE_ACTIONS_FOR_PLACES,
|
||||
"open",
|
||||
true,
|
||||
mProtocol,
|
||||
pageNumber);
|
||||
Log.d("API-USER-STORY-DOMAINS", "Protocol [" + mProtocol + "] include_actions [" + INCLUDE_ACTIONS_FOR_PLACES + "]");
|
||||
userStories.enqueue(new retrofit2.Callback<UserStories>() {
|
||||
@Override
|
||||
public void onResponse(Call<UserStories> call, Response<UserStories> response) {
|
||||
UserStories data = response.body();
|
||||
allStories.addAll(data.user_stories);
|
||||
if (data.current_page < data.total_pages && data.current_page <= MAX_PAGES_TO_GET) {
|
||||
if (pageNumber == 1 && firstPageCallback != null) {
|
||||
firstPageCallback.callback(null);
|
||||
}
|
||||
getUserStoryPage(pageNumber + 1, restOfPagesCallback, null);
|
||||
return;
|
||||
}
|
||||
restOfPagesCallback.callback(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Call<UserStories> call, Throwable t) {
|
||||
handleError(call.request().url().toString(), t, restOfPagesCallback);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private class StoriesFilter {
|
||||
String[] mWords = new String[]{};
|
||||
public StoriesFilter(String filterText) {
|
||||
mWords = filterText.toUpperCase().split("\\s+");
|
||||
}
|
||||
|
||||
private boolean matches(UserStory story) {
|
||||
if (mWords.length <= 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for (String word : mWords) {
|
||||
if (!story.searchText().contains(word)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void addToSuggestions(UserStory story) {
|
||||
suggestions.add(story.toDomain());
|
||||
}
|
||||
|
||||
public void filterOrAdd(UserStory story) {
|
||||
if (matches(story)) {
|
||||
addToSuggestions(story);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void filterChoicesByText(String filterText, DomainCallback domainCallback) {
|
||||
suggestions.clear();
|
||||
StoriesFilter storiesFilter = new StoriesFilter(filterText);
|
||||
allStories.forEach(story -> {
|
||||
storiesFilter.filterOrAdd(story);
|
||||
});
|
||||
domainCallback.retrieveOk(suggestions);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void retrieve(String filterText, DomainCallback domainCallback) {
|
||||
if (!startedToGetFromAPI) {
|
||||
startedToGetFromAPI = true;
|
||||
fillDestinations(filterText, domainCallback);
|
||||
} else {
|
||||
filterChoicesByText(filterText, domainCallback);
|
||||
}
|
||||
}
|
||||
|
||||
public void retrieveNot(DomainCallback domainCallback) {
|
||||
// TODO Call multiple pages
|
||||
Call<UserStories> userStories = mUserStoryDomainProviderService.getUserStories(
|
||||
INCLUDE_ACTIONS_FOR_PLACES,
|
||||
"open",
|
||||
true,
|
||||
mProtocol,
|
||||
1);
|
||||
|
||||
Log.d("API-USER-STORY-DOMAINS", "Protocol [" + mProtocol + "] include_actions [" + INCLUDE_ACTIONS_FOR_PLACES + "]");
|
||||
userStories.enqueue(new retrofit2.Callback<UserStories>() {
|
||||
|
||||
@Override
|
||||
public void onResponse(Call<UserStories> call, Response<UserStories> response) {
|
||||
UserStories userStories = response.body();
|
||||
if (userStories == null) {
|
||||
domainCallback.retrieveOk(new ArrayList<>(0));
|
||||
}
|
||||
List<DomainAdapter.Domain> domains = new ArrayList<>(userStories.total_entries);
|
||||
userStories.user_stories.forEach(userStory -> {
|
||||
domains.add(userStory.toDomain());
|
||||
});
|
||||
domainCallback.retrieveOk(domains);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Call<UserStories> call, Throwable t) {
|
||||
domainCallback.retrieveError(new Exception(t), t.getMessage());
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
public interface UserStoryDomainProviderService {
|
||||
@GET("api/v1/user_stories")
|
||||
Call<UserStories> getUserStories(@Query("include_actions") String includeActions,
|
||||
@Query("restriction") String restriction,
|
||||
@Query("require_online") boolean requireOnline,
|
||||
@Query("protocol") String protocol,
|
||||
@Query("page") int pageNumber);
|
||||
}
|
||||
|
||||
class UserStory {
|
||||
public UserStory() {}
|
||||
String place_name;
|
||||
String path;
|
||||
String thumbnail_url;
|
||||
String place_id;
|
||||
String domain_id;
|
||||
private String searchText;
|
||||
|
||||
// New fields? tags, description
|
||||
|
||||
String searchText() {
|
||||
if (searchText == null) {
|
||||
searchText = place_name == null? "" : place_name.toUpperCase();
|
||||
}
|
||||
return searchText;
|
||||
}
|
||||
DomainAdapter.Domain toDomain() {
|
||||
// TODO Proper url creation (it can or can't have hifi
|
||||
// TODO Or use host value from api?
|
||||
String absoluteThumbnailUrl = HifiUtils.getInstance().absoluteHifiAssetUrl(thumbnail_url);
|
||||
DomainAdapter.Domain domain = new DomainAdapter.Domain(
|
||||
place_name,
|
||||
HifiUtils.getInstance().sanitizeHifiUrl(place_name) + "/" + path,
|
||||
absoluteThumbnailUrl
|
||||
);
|
||||
return domain;
|
||||
}
|
||||
}
|
||||
|
||||
class UserStories {
|
||||
String status;
|
||||
int current_page;
|
||||
int total_pages;
|
||||
int total_entries;
|
||||
List<UserStory> user_stories;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
package io.highfidelity.hifiinterface.view;
|
||||
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
|
@ -9,6 +10,8 @@ import android.view.ViewGroup;
|
|||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.squareup.picasso.Picasso;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
@ -19,69 +22,59 @@ import java.util.ArrayList;
|
|||
import java.util.List;
|
||||
|
||||
import io.highfidelity.hifiinterface.R;
|
||||
import io.highfidelity.hifiinterface.provider.DomainProvider;
|
||||
import io.highfidelity.hifiinterface.provider.UserStoryDomainProvider;
|
||||
|
||||
/**
|
||||
* Created by Gabriel Calero & Cristian Duarte on 3/20/18.
|
||||
*/
|
||||
public class DomainAdapter extends RecyclerView.Adapter<DomainAdapter.ViewHolder> {
|
||||
|
||||
private static final java.lang.String DOMAINS_FILE = "hifi_domains.json";
|
||||
private static final String TAG = "HiFi Interface";
|
||||
private Context mContext;
|
||||
private LayoutInflater mInflater;
|
||||
private ItemClickListener mClickListener;
|
||||
|
||||
public class Domain {
|
||||
public String name;
|
||||
public String url;
|
||||
public String thumbnail;
|
||||
Domain(String name, String url, String thumbnail) {
|
||||
this.name = name;
|
||||
this.thumbnail = thumbnail;
|
||||
this.url = url;
|
||||
}
|
||||
}
|
||||
private String mProtocol;
|
||||
private UserStoryDomainProvider domainProvider;
|
||||
private AdapterListener mAdapterListener;
|
||||
|
||||
// references to our domains
|
||||
private Domain[] mDomains = {};
|
||||
|
||||
public DomainAdapter(Context c) {
|
||||
public DomainAdapter(Context c, String protocol) {
|
||||
mContext = c;
|
||||
this.mInflater = LayoutInflater.from(mContext);
|
||||
loadDomains();
|
||||
mProtocol = protocol;
|
||||
domainProvider = new UserStoryDomainProvider(mProtocol);
|
||||
loadDomains("");
|
||||
}
|
||||
|
||||
private void loadDomains() {
|
||||
try {
|
||||
JSONObject json = new JSONObject(loadJSONFromAsset());
|
||||
JSONArray hifiDomains = json.getJSONArray("hifi_domains");
|
||||
List<Domain> domains = new ArrayList<>();
|
||||
for (int i = 0; i < hifiDomains.length(); i++) {
|
||||
JSONObject jDomain = hifiDomains.getJSONObject(i);
|
||||
public void setListener(AdapterListener adapterListener) {
|
||||
mAdapterListener = adapterListener;
|
||||
}
|
||||
|
||||
String domainName = jDomain.getString("name");
|
||||
String domainUrl = jDomain.getString("url");
|
||||
String domainThumb = jDomain.getString("thumbnail");
|
||||
|
||||
domains.add(new Domain(domainName, domainUrl, domainThumb));
|
||||
public void loadDomains(String filterText) {
|
||||
domainProvider.retrieve(filterText, new DomainProvider.DomainCallback() {
|
||||
@Override
|
||||
public void retrieveOk(List<Domain> domain) {
|
||||
mDomains = new Domain[domain.size()];
|
||||
mDomains = domain.toArray(mDomains);
|
||||
notifyDataSetChanged();
|
||||
if (mAdapterListener != null) {
|
||||
if (mDomains.length == 0) {
|
||||
mAdapterListener.onEmptyAdapter();
|
||||
} else {
|
||||
mAdapterListener.onNonEmptyAdapter();
|
||||
}
|
||||
}
|
||||
}
|
||||
mDomains = domains.toArray(mDomains);
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, "Error loading domains from local file", e);
|
||||
} catch (JSONException e) {
|
||||
Log.e(TAG, "Error loading domains from local file", e);
|
||||
}
|
||||
}
|
||||
|
||||
public String loadJSONFromAsset() throws IOException {
|
||||
String json = null;
|
||||
InputStream is = mContext.getAssets().open(DOMAINS_FILE);
|
||||
int size = is.available();
|
||||
byte[] buffer = new byte[size];
|
||||
is.read(buffer);
|
||||
is.close();
|
||||
json = new String(buffer, "UTF-8");
|
||||
return json;
|
||||
@Override
|
||||
public void retrieveError(Exception e, String message) {
|
||||
Log.e("DOMAINS", message, e);
|
||||
if (mAdapterListener != null) mAdapterListener.onError(e, message);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -94,7 +87,10 @@ public class DomainAdapter extends RecyclerView.Adapter<DomainAdapter.ViewHolder
|
|||
public void onBindViewHolder(ViewHolder holder, int position) {
|
||||
// TODO
|
||||
//holder.thumbnail.setImageResource(mDomains[position].thumbnail);
|
||||
holder.mDomainName.setText(mDomains[position].name);
|
||||
Domain domain = mDomains[position];
|
||||
holder.mDomainName.setText(domain.name);
|
||||
Uri uri = Uri.parse(domain.thumbnail);
|
||||
Picasso.get().load(uri).into(holder.mThumbnail);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -128,4 +124,21 @@ public class DomainAdapter extends RecyclerView.Adapter<DomainAdapter.ViewHolder
|
|||
public interface ItemClickListener {
|
||||
void onItemClick(View view, int position, Domain domain);
|
||||
}
|
||||
|
||||
public static class Domain {
|
||||
public String name;
|
||||
public String url;
|
||||
public String thumbnail;
|
||||
public Domain(String name, String url, String thumbnail) {
|
||||
this.name = name;
|
||||
this.thumbnail = thumbnail;
|
||||
this.url = url;
|
||||
}
|
||||
}
|
||||
|
||||
public interface AdapterListener {
|
||||
void onEmptyAdapter();
|
||||
void onNonEmptyAdapter();
|
||||
void onError(Exception e, String message);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -68,6 +68,8 @@ 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 QtActivity() {
|
||||
}
|
||||
|
||||
|
@ -499,7 +501,11 @@ public class QtActivity extends Activity {
|
|||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
QtApplication.invokeDelegate();
|
||||
// GC: this trick allow us to show a splash activity until Qt app finishes
|
||||
// loading
|
||||
if (!isLoading) {
|
||||
QtApplication.invokeDelegate();
|
||||
}
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
|
@ -640,6 +646,7 @@ public class QtActivity extends Activity {
|
|||
super.onStop();
|
||||
QtApplication.invokeDelegate();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:top="1dp" android:left="12dp" android:bottom="6dp" android:right="12dp">
|
||||
<shape android:shape="rectangle">
|
||||
<solid android:color="@color/backgroundDark" />
|
||||
<corners android:radius="4dp"/>
|
||||
</shape>
|
||||
</item>
|
||||
|
||||
</layer-list>
|
50
android/app/src/main/res/drawable/hifi_header.xml
Normal file
50
android/app/src/main/res/drawable/hifi_header.xml
Normal file
|
@ -0,0 +1,50 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="350dp"
|
||||
android:height="100dp"
|
||||
android:viewportWidth="350"
|
||||
android:viewportHeight="100">
|
||||
|
||||
<path
|
||||
android:fillColor="#00B4F0"
|
||||
android:pathData="M132.646,40.971 L132.646,62.955 L127.959,62.955 L127.959,53.361 L120.222,53.361 L120.222,62.955 L115.535,62.955 L115.535,40.971 L120.222,40.971 L120.222,49.453 L127.959,49.453 L127.959,40.971 L132.646,40.971 Z" />
|
||||
<path
|
||||
android:fillColor="#00B4F0"
|
||||
android:pathData="M140.959,62.955 L136.271,62.955 L136.271,40.971 L140.959,40.971 L140.959,62.955 Z" />
|
||||
<path
|
||||
android:fillColor="#00B4F0"
|
||||
android:pathData="M154.488,44.479 C153.383,44.479,152.454,44.568,151.658,44.79 C150.906,45.012,150.287,45.367,149.801,45.856 C149.315,46.345,149.006,47.055,148.784,47.899 C148.563,48.743,148.474,49.809,148.474,51.053 L148.474,53.051 C148.474,54.383,148.563,55.449,148.74,56.293 C148.917,57.137,149.226,57.803,149.668,58.247 C150.066,58.736,150.641,59.047,151.305,59.225 C151.968,59.403,152.808,59.492,153.781,59.492 C154.047,59.492,154.356,59.492,154.665,59.448 C154.976,59.448,155.284,59.403,155.638,59.358 L155.638,53.408 L152.898,53.408 L153.339,49.765 L160.06,49.765 L160.06,62.29 C159.22,62.601,158.16,62.823,156.876,63.001 C155.638,63.179,154.312,63.267,152.985,63.267 C151.305,63.267,149.89,63.045,148.741,62.646 C147.548,62.247,146.619,61.625,145.867,60.782 C145.116,59.937,144.585,58.916,144.231,57.628 C143.877,56.385,143.745,54.874,143.745,53.188 L143.745,50.921 C143.745,49.367,143.922,47.99,144.231,46.702 C144.585,45.414,145.16,44.348,145.956,43.46 C146.751,42.572,147.812,41.861,149.095,41.373 C150.377,40.884,152.013,40.618,153.958,40.618 C155.02,40.618,156.081,40.706,157.097,40.884 C158.115,41.062,158.954,41.284,159.618,41.506 L158.866,45.059 C158.291,44.881,157.628,44.748,156.921,44.615 C156.212,44.523,155.416,44.479,154.488,44.479 Z" />
|
||||
<path
|
||||
android:fillColor="#00B4F0"
|
||||
android:pathData="M181.104,40.971 L181.104,62.955 L176.417,62.955 L176.417,53.361 L168.724,53.361 L168.724,62.955 L164.037,62.955 L164.037,40.971 L168.724,40.971 L168.724,49.453 L176.461,49.453 L176.461,40.971 L181.104,40.971 Z" />
|
||||
<path
|
||||
android:fillColor="#00B4F0"
|
||||
android:pathData="M206.084,40.971 L205.555,44.79 L197.375,44.79 L197.375,49.365 L204.936,49.365 L204.405,53.183 L197.377,53.183 L197.377,62.954 L192.689,62.954 L192.689,40.971 L206.084,40.971 Z" />
|
||||
<path
|
||||
android:fillColor="#00B4F0"
|
||||
android:pathData="M213.688,62.955 L209.001,62.955 L209.001,40.971 L213.688,40.971 L213.688,62.955 Z" />
|
||||
<path
|
||||
android:fillColor="#00B4F0"
|
||||
android:pathData="M217.447,40.971 L224.609,40.971 C226.465,40.971,228.013,41.237,229.252,41.726 C230.491,42.215,231.463,42.925,232.215,43.769 C232.966,44.657,233.452,45.679,233.762,46.922 C234.073,48.166,234.203,49.498,234.203,50.92 L234.203,53.007 C234.203,54.473,234.071,55.805,233.762,57.049 C233.452,58.292,232.922,59.315,232.215,60.202 C231.463,61.09,230.49,61.756,229.252,62.245 C228.014,62.732,226.467,63,224.609,63 L217.491,63 L217.491,40.971 L217.447,40.971 L217.447,40.971 Z M222.09,59.137 L224.123,59.137 C225.008,59.137,225.76,59.047,226.467,58.825 C227.13,58.603,227.705,58.248,228.147,57.76 C228.589,57.272,228.899,56.606,229.121,55.805 C229.342,55.006,229.431,53.985,229.431,52.742 L229.431,51.098 C229.431,49.854,229.342,48.832,229.121,48.034 C228.899,47.235,228.591,46.569,228.147,46.08 C227.707,45.591,227.174,45.236,226.467,45.059 C225.803,44.881,225.008,44.748,224.123,44.748 L222.09,44.748 L222.09,59.137 Z" />
|
||||
<path
|
||||
android:fillColor="#00B4F0"
|
||||
android:pathData="M250.871,40.971 L250.385,44.657 L241.942,44.657 L241.942,49.453 L249.899,49.453 L249.459,53.141 L241.985,53.141 L241.985,59.315 L250.918,59.315 L250.43,63 L237.254,63 L237.254,40.971 L250.871,40.971 Z" />
|
||||
<path
|
||||
android:fillColor="#00B4F0"
|
||||
android:pathData="M258.609,40.971 L258.609,59.137 L267.496,59.137 L266.965,62.955 L253.922,62.955 L253.922,40.971 L258.609,40.971 Z" />
|
||||
<path
|
||||
android:fillColor="#00B4F0"
|
||||
android:pathData="M275.232,62.955 L270.544,62.955 L270.544,40.971 L275.232,40.971 L275.232,62.955 Z" />
|
||||
<path
|
||||
android:fillColor="#00B4F0"
|
||||
android:pathData="M295.482,40.971 L294.952,44.79 L289.027,44.79 L289.027,62.955 L284.339,62.955 L284.339,44.79 L277.884,44.79 L278.415,40.971 L295.482,40.971 Z" />
|
||||
<path
|
||||
android:fillColor="#00B4F0"
|
||||
android:pathData="M306.58,49.543 L311.134,40.971 L315.953,40.971 L308.791,53.363 L308.791,62.956 L304.103,62.956 L304.103,53.363 L297.03,40.971 L302.159,40.971 L306.58,49.543 Z" />
|
||||
<path
|
||||
android:fillColor="#00B4F0"
|
||||
android:pathData="M68.848,83.209 C64.427,83.209,60.094,82.32,56.07,80.633 C52.135,78.989,48.642,76.591,45.636,73.571 C42.63,70.551,40.242,66.999,38.606,63.091 C36.837,58.96,35.953,54.653,35.953,50.166 C35.953,45.725,36.837,41.372,38.517,37.33 C40.153,33.377,42.54,29.869,45.547,26.848 C48.553,23.828,52.09,21.43,55.981,19.786 C60.049,18.054,64.337,17.21,68.758,17.21 C73.179,17.21,77.513,18.098,81.536,19.786 C85.471,21.429,88.964,23.828,91.97,26.848 C94.977,29.869,97.365,33.422,98.999,37.33 C100.724,41.416,101.563,45.725,101.563,50.166 C101.563,54.606,100.681,58.959,99,63.001 C97.365,66.954,94.978,70.462,91.971,73.483 C88.965,76.503,85.428,78.901,81.537,80.544 C77.602,82.32,73.269,83.209,68.848,83.209 Z M68.848,20.584 C52.621,20.584,39.402,33.864,39.402,50.164 C39.402,66.465,52.621,79.744,68.848,79.744 S98.293,66.465,98.293,50.164 C98.293,33.864,85.074,20.584,68.848,20.584 Z" />
|
||||
<path
|
||||
android:fillColor="#00B4F0"
|
||||
android:pathData="M78.884,64.199 L78.884,41.014 C80.343,40.525,81.36,39.149,81.36,37.55 C81.36,35.551,79.725,33.908,77.735,33.908 C75.745,33.908,74.11,35.552,74.11,37.55 C74.11,39.105,75.038,40.393,76.409,40.97 L76.409,51.762 L61.376,44.745 L61.376,36.217 C62.835,35.729,63.852,34.352,63.852,32.753 C63.852,30.754,62.216,29.111,60.227,29.111 C58.238,29.111,56.602,30.755,56.602,32.753 C56.602,34.308,57.531,35.596,58.901,36.173 L58.901,59.491 C57.574,60.023,56.602,61.355,56.602,62.911 C56.602,64.91,58.238,66.553,60.227,66.553 C62.216,66.553,63.852,64.91,63.852,62.911 C63.852,61.312,62.835,59.935,61.376,59.447 L61.376,47.676 L76.409,54.694 L76.409,64.244 C75.083,64.775,74.11,66.109,74.11,67.663 C74.11,69.662,75.745,71.305,77.735,71.305 C79.725,71.305,81.36,69.662,81.36,67.663 C81.359,66.02,80.343,64.688,78.884,64.199 Z" />
|
||||
</vector>
|
12
android/app/src/main/res/drawable/ic_clear.xml
Normal file
12
android/app/src/main/res/drawable/ic_clear.xml
Normal file
|
@ -0,0 +1,12 @@
|
|||
<vector android:height="24dp" android:viewportHeight="15.0"
|
||||
android:viewportWidth="15.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="#404040" android:pathData="M7.5,7.5m-7.5,0a7.5,7.5 0,1 1,15 0a7.5,7.5 0,1 1,-15 0"/>
|
||||
<path android:fillColor="#00000000"
|
||||
android:pathData="M4.683,4.583L10,10.27"
|
||||
android:strokeColor="#E3E3E3" android:strokeLineCap="round"
|
||||
android:strokeLineJoin="bevel" android:strokeWidth="1"/>
|
||||
<path android:fillColor="#00000000"
|
||||
android:pathData="M10,4.73L4.683,10.417"
|
||||
android:strokeColor="#E3E3E3" android:strokeLineCap="round"
|
||||
android:strokeLineJoin="bevel" android:strokeWidth="1"/>
|
||||
</vector>
|
4
android/app/src/main/res/drawable/ic_search.xml
Normal file
4
android/app/src/main/res/drawable/ic_search.xml
Normal file
|
@ -0,0 +1,4 @@
|
|||
<vector android:height="24dp" android:viewportHeight="18.0"
|
||||
android:viewportWidth="18.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="#F2F2F2" android:fillType="evenOdd" android:pathData="M12.5,11L11.7,11L11.4,10.7C12.4,9.6 13,8.1 13,6.5C13,2.9 10.1,0 6.5,0C2.9,0 0,2.9 0,6.5C0,10.1 2.9,13 6.5,13C8.1,13 9.6,12.4 10.7,11.4L11,11.7L11,12.5L16,17.5L17.5,16L12.5,11ZM6.5,11C4,11 2,9 2,6.5C2,4 4,2 6.5,2C9,2 11,4 11,6.5C11,9 9,11 6.5,11Z"/>
|
||||
</vector>
|
24
android/app/src/main/res/drawable/rounded_button.xml
Normal file
24
android/app/src/main/res/drawable/rounded_button.xml
Normal file
|
@ -0,0 +1,24 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
|
||||
<item android:state_pressed="true" >
|
||||
<shape android:shape="rectangle" >
|
||||
<corners android:radius="4dip" />
|
||||
<stroke android:width="1dip" android:color="@color/colorButton1" />
|
||||
<solid android:color="@color/colorButton1"/>
|
||||
</shape>
|
||||
</item>
|
||||
<item android:state_focused="true">
|
||||
<shape android:shape="rectangle" >
|
||||
<corners android:radius="4dip" />
|
||||
<stroke android:width="1dip" android:color="@color/colorButton1" />
|
||||
<solid android:color="@color/colorButton1"/>
|
||||
</shape>
|
||||
</item>
|
||||
<item>
|
||||
<shape android:shape="rectangle" >
|
||||
<corners android:radius="4dip" />
|
||||
<stroke android:width="1dip" android:color="@color/colorButton1" />
|
||||
<solid android:color="@color/colorButton1"/>
|
||||
</shape>
|
||||
</item>
|
||||
</selector>
|
7
android/app/src/main/res/drawable/rounded_edit.xml
Normal file
7
android/app/src/main/res/drawable/rounded_edit.xml
Normal file
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle" android:padding="9dp">
|
||||
<corners android:radius="4dip" />
|
||||
<stroke android:width="1dip" android:color="@android:color/black" />
|
||||
<solid android:color="@color/backgroundEditText"/>
|
||||
</shape>
|
|
@ -18,8 +18,9 @@
|
|||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
android:background="?attr/colorPrimary"
|
||||
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" />
|
||||
android:background="@color/colorPrimaryDark"
|
||||
android:elevation="4dp"
|
||||
/>
|
||||
|
||||
<include layout="@layout/content_home" />
|
||||
|
||||
|
@ -32,7 +33,31 @@
|
|||
android:layout_height="match_parent"
|
||||
android:layout_gravity="start"
|
||||
android:fitsSystemWindows="true"
|
||||
android:background="@color/colorPrimaryDark"
|
||||
app:menu="@menu/menu_home"
|
||||
/>
|
||||
>
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom"
|
||||
android:clickable="true"
|
||||
android:orientation="vertical"
|
||||
android:padding="@dimen/activity_horizontal_margin">
|
||||
<TextView
|
||||
android:id="@+id/login"
|
||||
android:text="@string/login"
|
||||
android:onClick="onLoginClicked"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="@color/menuOption" />
|
||||
<TextView
|
||||
android:id="@+id/logout"
|
||||
android:text="@string/logout"
|
||||
android:onClick="onLogoutClicked"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="@color/menuOption" />
|
||||
</LinearLayout>
|
||||
</android.support.design.widget.NavigationView>
|
||||
|
||||
</android.support.v4.widget.DrawerLayout>
|
||||
|
|
106
android/app/src/main/res/layout/activity_login.xml
Normal file
106
android/app/src/main/res/layout/activity_login.xml
Normal file
|
@ -0,0 +1,106 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/backgroundLight"
|
||||
tools:context="io.highfidelity.hifiinterface.LoginActivity">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/imageView3"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:srcCompat="@drawable/hifi_header"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintBottom_toTopOf="@id/username"
|
||||
android:layout_marginBottom="75dp"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/error"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:fontFamily="@font/raleway"
|
||||
android:textColor="@color/colorLoginError"
|
||||
android:textSize="12sp"
|
||||
app:layout_constraintBottom_toTopOf="@id/username"
|
||||
app:layout_constraintLeft_toLeftOf="@id/username"
|
||||
android:visibility="invisible"/>
|
||||
|
||||
<EditText
|
||||
android:id="@+id/username"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="@dimen/activity_horizontal_margin"
|
||||
android:layout_marginRight="@dimen/activity_horizontal_margin"
|
||||
android:background="@drawable/rounded_edit"
|
||||
android:padding="9dp"
|
||||
android:paddingRight="12dp"
|
||||
android:ems="10"
|
||||
android:fontFamily="@font/raleway"
|
||||
android:inputType="textEmailAddress"
|
||||
android:textStyle="italic"
|
||||
android:textColor="@color/editTextColor"
|
||||
android:textColorHint="@color/editTextColor"
|
||||
android:gravity="right"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
android:hint="@string/username_or_email" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/password"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="@dimen/activity_horizontal_margin"
|
||||
android:layout_marginRight="@dimen/activity_horizontal_margin"
|
||||
android:background="@drawable/rounded_edit"
|
||||
android:padding="9dp"
|
||||
android:paddingRight="12dp"
|
||||
android:ems="10"
|
||||
android:fontFamily="@font/raleway"
|
||||
android:inputType="textPassword"
|
||||
android:textStyle="italic"
|
||||
android:textColor="@color/editTextColor"
|
||||
android:textColorHint="@color/editTextColor"
|
||||
android:gravity="right"
|
||||
android:layout_marginTop="14dp"
|
||||
app:layout_constraintTop_toBottomOf="@id/username"
|
||||
android:hint="@string/password"
|
||||
android:imeOptions="actionDone"/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/loginButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/rounded_button"
|
||||
android:textColor="@color/white_opaque"
|
||||
android:text="@string/login"
|
||||
app:layout_constraintRight_toRightOf="@id/username"
|
||||
app:layout_constraintTop_toBottomOf="@id/password"
|
||||
android:paddingRight="30dp"
|
||||
android:paddingLeft="30dp"
|
||||
android:paddingTop="4dp"
|
||||
android:paddingBottom="4dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:onClick="login"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="@dimen/activity_horizontal_margin"
|
||||
android:fontFamily="@font/raleway_semibold"
|
||||
android:text="@string/forgot_password"
|
||||
android:textStyle="italic"
|
||||
android:padding="10dp"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/loginButton"
|
||||
android:textColor="@color/colorButton1"/>
|
||||
|
||||
|
||||
|
||||
|
||||
</android.support.constraint.ConstraintLayout>
|
12
android/app/src/main/res/layout/activity_splash.xml
Normal file
12
android/app/src/main/res/layout/activity_splash.xml
Normal file
|
@ -0,0 +1,12 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/root_activity_splash"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/backgroundLight">
|
||||
|
||||
<!-- TODO -->
|
||||
|
||||
</RelativeLayout>
|
|
@ -2,75 +2,75 @@
|
|||
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/contentHomeRoot"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior"
|
||||
android:background="@color/colorPrimary"
|
||||
tools:context="io.highfidelity.hifiinterface.HomeActivity"
|
||||
tools:showIn="@layout/activity_home">
|
||||
|
||||
<TabHost
|
||||
android:id="@+id/tabhost"
|
||||
<EditText
|
||||
android:id="@+id/searchView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginBottom="8dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
android:layout_height="@dimen/searchEditHeight"
|
||||
app:layout_constraintTop_toTopOf="@id/contentHomeRoot"
|
||||
android:background="@drawable/search_bg"
|
||||
android:layout_marginTop="@dimen/searchEditAdditionalMarginTop"
|
||||
android:gravity="center_vertical|end"
|
||||
android:paddingStart="@dimen/searchEditPaddingStart"
|
||||
android:paddingEnd="@dimen/searchEditPaddingEnd"
|
||||
android:fontFamily="@font/raleway"
|
||||
android:hint="@string/search_hint"
|
||||
android:textSize="@dimen/searchEditTextSize"
|
||||
android:inputType="textUri"
|
||||
android:imeOptions="actionGo"
|
||||
/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/search_mag_icon"
|
||||
android:layout_width="@dimen/searchEditMagIconWidth"
|
||||
android:layout_height="@dimen/searchEditMagIconHeight"
|
||||
app:layout_constraintEnd_toEndOf="@id/searchView"
|
||||
app:layout_constraintTop_toTopOf="@id/searchView"
|
||||
app:layout_constraintBottom_toBottomOf="@id/searchView"
|
||||
android:layout_marginEnd="@dimen/searchEditMagMarginEnd"
|
||||
android:src="@drawable/ic_search"
|
||||
/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/search_clear"
|
||||
android:layout_width="@dimen/searchEditClearIconWidth"
|
||||
android:layout_height="@dimen/searchEditClearIconHeight"
|
||||
app:layout_constraintEnd_toEndOf="@id/searchView"
|
||||
app:layout_constraintTop_toTopOf="@id/searchView"
|
||||
app:layout_constraintBottom_toBottomOf="@id/searchView"
|
||||
android:layout_marginEnd="@dimen/searchEditClearMarginEnd"
|
||||
android:visibility="gone"
|
||||
android:src="@drawable/ic_clear"
|
||||
android:onClick="onSearchClear"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/searchNoResultsView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
style="@style/SearchText"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent">
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/searchView"
|
||||
android:layout_marginTop="32dp"
|
||||
android:text="@string/search_no_results"
|
||||
android:visibility="gone"
|
||||
/>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TabWidget
|
||||
android:id="@android:id/tabs"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@color/backgroundDark"/>
|
||||
|
||||
<SearchView
|
||||
android:id="@+id/searchView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="42dp"
|
||||
android:background="@drawable/search_bg"
|
||||
android:gravity="right"
|
||||
android:layout_gravity="right"
|
||||
|
||||
/>
|
||||
<FrameLayout
|
||||
android:id="@android:id/tabcontent"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/featured"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
<android.support.v7.widget.RecyclerView
|
||||
android:id="@+id/rvDomains"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/popular"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/bookmarks"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
</LinearLayout>
|
||||
</FrameLayout>
|
||||
</LinearLayout>
|
||||
</TabHost>
|
||||
<android.support.v7.widget.RecyclerView
|
||||
android:id="@+id/rvDomains"
|
||||
app:layout_constraintTop_toBottomOf="@id/searchView"
|
||||
app:layout_constraintBottom_toBottomOf="@id/contentHomeRoot"
|
||||
app:layout_constraintStart_toStartOf="@id/contentHomeRoot"
|
||||
app:layout_constraintEnd_toEndOf="@id/contentHomeRoot"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp" />
|
||||
|
||||
</android.support.constraint.ConstraintLayout>
|
||||
|
|
|
@ -1,74 +1,44 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="113dp"
|
||||
android:paddingLeft="14dp"
|
||||
android:paddingRight="14dp"
|
||||
android:paddingTop="4dp"
|
||||
android:paddingBottom="4dp"
|
||||
android:background="@drawable/domain_bg">
|
||||
<ImageView
|
||||
android:id="@+id/domainThumbnail"
|
||||
android:layout_height="@dimen/domainItemHeight"
|
||||
android:layout_marginStart="@dimen/domainMarginStart"
|
||||
android:layout_marginEnd="@dimen/domainMarginEnd"
|
||||
android:layout_marginTop="@dimen/domainMarginTop"
|
||||
android:layout_marginBottom="@dimen/domainMarginBottom"
|
||||
android:foreground="@drawable/rippleable"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:elevation="0dp"
|
||||
app:cardElevation="0dp"
|
||||
app:cardCornerRadius="@dimen/item_corner_radius">
|
||||
|
||||
<android.support.constraint.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:srcCompat="@android:drawable/ic_menu_gallery" />
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/domainName"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="14dp"
|
||||
android:layout_marginLeft="10dp"
|
||||
android:fontFamily="@font/raleway_semibold"
|
||||
android:text=""
|
||||
android:textSize="21sp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintLeft_toLeftOf="parent" />
|
||||
<ImageView
|
||||
android:id="@+id/domainThumbnail"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:scaleType="centerCrop"
|
||||
app:srcCompat="@android:drawable/ic_menu_gallery" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/amountOfPeople"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="7dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:fontFamily="@font/raleway"
|
||||
android:text="10"
|
||||
android:textSize="16sp"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
<TextView
|
||||
android:id="@+id/domainName"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/domainNameHeight"
|
||||
android:fontFamily="@font/raleway_semibold"
|
||||
android:paddingStart="10dp"
|
||||
android:paddingEnd="10dp"
|
||||
android:gravity="center_vertical"
|
||||
android:text=""
|
||||
android:textSize="21sp"
|
||||
android:textColor="@color/white_opaque"
|
||||
android:background="@color/black_060"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintLeft_toLeftOf="parent" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/imageView2"
|
||||
android:layout_width="12dp"
|
||||
android:layout_height="13dp"
|
||||
android:layout_marginLeft="4dp"
|
||||
android:layout_marginBottom="3dp"
|
||||
app:srcCompat="@drawable/ic_person"
|
||||
app:layout_constraintBottom_toBottomOf="@id/amountOfPeople"
|
||||
app:layout_constraintLeft_toRightOf="@id/amountOfPeople"/>
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/imageButtonBookmark"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/ic_bookmark"
|
||||
android:tint="@color/colorPrimary"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
android:padding="1dp"
|
||||
android:layout_marginRight="10dp"
|
||||
android:layout_marginTop="12dp"/>
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/imageViewShare"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="9dp"
|
||||
app:layout_constraintTop_toBottomOf="@id/imageButtonBookmark"
|
||||
app:layout_constraintLeft_toLeftOf="@id/imageButtonBookmark"
|
||||
app:layout_constraintRight_toRightOf="@id/imageButtonBookmark"
|
||||
android:background="@drawable/ic_share"
|
||||
/>
|
||||
</android.support.constraint.ConstraintLayout>
|
||||
</android.support.constraint.ConstraintLayout>
|
||||
</android.support.v7.widget.CardView>
|
|
@ -1,13 +1,20 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="white_opaque">#ffffff</color>
|
||||
<color name="colorPrimary">#272727</color>
|
||||
<color name="colorPrimaryDark">#000000</color>
|
||||
<color name="colorPrimary">@color/backgroundLight</color>
|
||||
<color name="colorPrimaryDark">@color/backgroundDark</color>
|
||||
<color name="colorAccent">#54D7FD</color>
|
||||
<color name="backgroundEditText">#E3E3E3</color>
|
||||
<color name="editTextColor">#575757</color>
|
||||
<color name="tabs">#1EB5EC</color>
|
||||
<color name="colorButton1">#00B4EF</color>
|
||||
<color name="backgroundDark">#333333</color>
|
||||
<color name="backgroundLight">#4F4F4F</color>
|
||||
<color name="backgroundSearch">#33999999</color>
|
||||
<color name="editText">#212121</color>
|
||||
<color name="editTextHint">#9e9e9e</color>
|
||||
<color name="menuOption">#F2F2F2</color>
|
||||
<color name="colorLoginError">#FF7171</color>
|
||||
<color name="black_060">#99000000</color>
|
||||
<color name="statusbar_color">#292929</color>
|
||||
</resources>
|
||||
|
|
|
@ -11,4 +11,26 @@
|
|||
<dimen name="text_size_subtitle_material_toolbar">12dp</dimen>
|
||||
<dimen name="button_horizontal_margin">12dp</dimen>
|
||||
<dimen name="edit_text_padding">8dp</dimen>
|
||||
<dimen name="item_corner_radius">4dp</dimen>
|
||||
|
||||
<!-- Search (domains) screen dimensions -->
|
||||
<dimen name="searchEditHeight">47.5dp</dimen>
|
||||
<dimen name="searchEditAdditionalMarginTop">11dp</dimen>
|
||||
<dimen name="searchEditPaddingStart">24dp</dimen>
|
||||
<dimen name="searchEditPaddingEnd">51dp</dimen>
|
||||
<dimen name="searchEditTextSize">19sp</dimen>
|
||||
<dimen name="searchEditMagIconWidth">16dp</dimen>
|
||||
<dimen name="searchEditMagIconHeight">16dp</dimen>
|
||||
<dimen name="searchEditMagMarginEnd">22dp</dimen>
|
||||
<dimen name="searchEditClearIconWidth">16dp</dimen>
|
||||
<dimen name="searchEditClearIconHeight">16dp</dimen>
|
||||
<dimen name="searchEditClearMarginEnd">22dp</dimen>
|
||||
|
||||
<dimen name="domainItemHeight">163dp</dimen>
|
||||
<dimen name="domainMarginStart">14dp</dimen>
|
||||
<dimen name="domainMarginEnd">14dp</dimen>
|
||||
<dimen name="domainMarginTop">2dp</dimen>
|
||||
<dimen name="domainMarginBottom">6dp</dimen>
|
||||
<dimen name="domainNameHeight">64dp</dimen>
|
||||
|
||||
</resources>
|
|
@ -13,5 +13,14 @@
|
|||
<string name="action_goto">Go To</string>
|
||||
<string name="goto_url_hint">Type a domain url</string>
|
||||
<string name="go">Go</string>
|
||||
|
||||
<string name="username_or_email">Username or email</string>
|
||||
<string name="password">Password</string>
|
||||
<string name="login">Login</string>
|
||||
<string name="logout">Logout</string>
|
||||
<string name="forgot_password">Forgot password?</string>
|
||||
<string name="login_username_or_password_incorrect">Username or password incorrect.</string>
|
||||
<string name="logging_in">Logging into High Fidelity</string>
|
||||
<string name="search_hint"><i>Search for a place by name</i>\u00A0</string>
|
||||
<string name="search_loading">Loading places…</string>
|
||||
<string name="search_no_results">No places exist with that name</string>
|
||||
</resources>
|
||||
|
|
|
@ -7,7 +7,14 @@
|
|||
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
|
||||
<item name="colorAccent">@color/colorAccent</item>
|
||||
</style>
|
||||
|
||||
<style name="Theme.AppCompat.Translucent.NoActionBar" parent="Theme.AppCompat.NoActionBar">
|
||||
<item name="android:windowNoTitle">true</item>
|
||||
<item name="android:windowBackground">@android:color/transparent</item>
|
||||
<item name="android:colorBackgroundCacheHint">@null</item>
|
||||
<item name="android:windowIsTranslucent">true</item>
|
||||
<item name="android:windowAnimationStyle">@android:style/Animation</item>
|
||||
<item name="android:windowActionBar">false</item>
|
||||
</style>
|
||||
<style name="AppTheme.NoActionBar">
|
||||
<item name="windowActionBar">false</item>
|
||||
<item name="windowNoTitle">true</item>
|
||||
|
@ -35,7 +42,7 @@
|
|||
|
||||
<style name="SearchText">
|
||||
<item name="android:fontFamily">@font/raleway_light_italic</item>
|
||||
<item name="android:textSize">15sp</item>
|
||||
<item name="android:textSize">19sp</item>
|
||||
</style>
|
||||
|
||||
<!-- Overriding text size so it's not so big in portrait -->
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "AssignmentClient.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <QProcess>
|
||||
|
@ -32,16 +34,14 @@
|
|||
#include <SoundCache.h>
|
||||
#include <ResourceScriptingInterface.h>
|
||||
#include <UserActivityLoggerScriptingInterface.h>
|
||||
|
||||
#include "AssignmentFactory.h"
|
||||
#include "AssignmentDynamicFactory.h"
|
||||
|
||||
#include "AssignmentClient.h"
|
||||
#include "AssignmentClientLogging.h"
|
||||
#include "avatars/ScriptableAvatar.h"
|
||||
#include <Trace.h>
|
||||
#include <StatTracker.h>
|
||||
|
||||
#include "AssignmentClientLogging.h"
|
||||
#include "AssignmentDynamicFactory.h"
|
||||
#include "AssignmentFactory.h"
|
||||
#include "avatars/ScriptableAvatar.h"
|
||||
|
||||
const QString ASSIGNMENT_CLIENT_TARGET_NAME = "assignment-client";
|
||||
const long long ASSIGNMENT_REQUEST_INTERVAL_MSECS = 1 * 1000;
|
||||
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "AssignmentClientMonitor.h"
|
||||
|
||||
#include <memory>
|
||||
#include <signal.h>
|
||||
|
||||
|
@ -19,7 +21,6 @@
|
|||
#include <LogHandler.h>
|
||||
#include <udt/PacketHeaders.h>
|
||||
|
||||
#include "AssignmentClientMonitor.h"
|
||||
#include "AssignmentClientApp.h"
|
||||
#include "AssignmentClientChildData.h"
|
||||
#include "SharedUtil.h"
|
||||
|
|
|
@ -9,10 +9,10 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "EntitySimulation.h"
|
||||
|
||||
#include "AssignmentDynamic.h"
|
||||
|
||||
#include "EntitySimulation.h"
|
||||
|
||||
AssignmentDynamic::AssignmentDynamic(EntityDynamicType type, const QUuid& id, EntityItemPointer ownerEntity) :
|
||||
EntityDynamicInterface(type, id),
|
||||
_data(QByteArray()),
|
||||
|
|
|
@ -9,11 +9,12 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "AssignmentFactory.h"
|
||||
|
||||
#include <udt/PacketHeaders.h>
|
||||
|
||||
#include "Agent.h"
|
||||
#include "assets/AssetServer.h"
|
||||
#include "AssignmentFactory.h"
|
||||
#include "audio/AudioMixer.h"
|
||||
#include "avatars/AvatarMixer.h"
|
||||
#include "entities/EntityServer.h"
|
||||
|
|
|
@ -9,11 +9,11 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "AudioMixerSlavePool.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <algorithm>
|
||||
|
||||
#include "AudioMixerSlavePool.h"
|
||||
|
||||
void AudioMixerSlaveThread::run() {
|
||||
while (true) {
|
||||
wait();
|
||||
|
|
|
@ -9,10 +9,11 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "AvatarAudioStream.h"
|
||||
|
||||
#include <udt/PacketHeaders.h>
|
||||
|
||||
#include "AudioLogging.h"
|
||||
#include "AvatarAudioStream.h"
|
||||
|
||||
AvatarAudioStream::AvatarAudioStream(bool isStereo, int numStaticJitterFrames) :
|
||||
PositionalAudioStream(PositionalAudioStream::Microphone, isStereo, numStaticJitterFrames) {}
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "AvatarMixer.h"
|
||||
|
||||
#include <cfloat>
|
||||
#include <chrono>
|
||||
#include <memory>
|
||||
|
@ -31,8 +33,6 @@
|
|||
#include <UUID.h>
|
||||
#include <TryLocker.h>
|
||||
|
||||
#include "AvatarMixer.h"
|
||||
|
||||
const QString AVATAR_MIXER_LOGGING_NAME = "avatar-mixer";
|
||||
|
||||
// FIXME - what we'd actually like to do is send to users at ~50% of their present rate down to 30hz. Assume 90 for now.
|
||||
|
|
|
@ -9,13 +9,13 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "AvatarMixerClientData.h"
|
||||
|
||||
#include <udt/PacketHeaders.h>
|
||||
|
||||
#include <DependencyManager.h>
|
||||
#include <NodeList.h>
|
||||
|
||||
#include "AvatarMixerClientData.h"
|
||||
|
||||
AvatarMixerClientData::AvatarMixerClientData(const QUuid& nodeID) :
|
||||
NodeData(nodeID)
|
||||
{
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "AvatarMixerSlave.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <random>
|
||||
|
||||
|
@ -28,10 +30,8 @@
|
|||
#include <StDev.h>
|
||||
#include <UUID.h>
|
||||
|
||||
|
||||
#include "AvatarMixer.h"
|
||||
#include "AvatarMixerClientData.h"
|
||||
#include "AvatarMixerSlave.h"
|
||||
|
||||
void AvatarMixerSlave::configure(ConstIter begin, ConstIter end) {
|
||||
_begin = begin;
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
#ifndef hifi_AvatarMixerSlave_h
|
||||
#define hifi_AvatarMixerSlave_h
|
||||
|
||||
#include <NodeList.h>
|
||||
|
||||
class AvatarMixerClientData;
|
||||
|
||||
class AvatarMixerSlaveStats {
|
||||
|
|
|
@ -9,11 +9,11 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "AvatarMixerSlavePool.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <algorithm>
|
||||
|
||||
#include "AvatarMixerSlavePool.h"
|
||||
|
||||
void AvatarMixerSlaveThread::run() {
|
||||
while (true) {
|
||||
wait();
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "ScriptableAvatar.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QThread>
|
||||
#include <glm/gtx/transform.hpp>
|
||||
|
@ -16,7 +18,6 @@
|
|||
#include <shared/QtHelpers.h>
|
||||
#include <GLMHelpers.h>
|
||||
#include <AnimUtil.h>
|
||||
#include "ScriptableAvatar.h"
|
||||
|
||||
|
||||
QByteArray ScriptableAvatar::toByteArrayStateful(AvatarDataDetail dataDetail, bool dropFaceTracking) {
|
||||
|
|
|
@ -9,21 +9,23 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "EntityServer.h"
|
||||
|
||||
#include <QtCore/QEventLoop>
|
||||
#include <QTimer>
|
||||
#include <QJsonArray>
|
||||
#include <QJsonDocument>
|
||||
|
||||
#include <EntityTree.h>
|
||||
#include <SimpleEntitySimulation.h>
|
||||
#include <ResourceCache.h>
|
||||
#include <ScriptCache.h>
|
||||
#include <EntityEditFilters.h>
|
||||
#include <NetworkingConstants.h>
|
||||
#include <QJsonArray>
|
||||
#include <QJsonDocument>
|
||||
#include <AddressManager.h>
|
||||
|
||||
#include "AssignmentParentFinder.h"
|
||||
#include "EntityNodeData.h"
|
||||
#include "EntityServer.h"
|
||||
#include "EntityServerConsts.h"
|
||||
#include "EntityTreeSendThread.h"
|
||||
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "MessagesMixer.h"
|
||||
|
||||
#include <QtCore/QCoreApplication>
|
||||
#include <QtCore/QJsonObject>
|
||||
#include <QBuffer>
|
||||
|
@ -16,7 +18,6 @@
|
|||
#include <MessagesClient.h>
|
||||
#include <NodeList.h>
|
||||
#include <udt/PacketHeaders.h>
|
||||
#include "MessagesMixer.h"
|
||||
|
||||
const QString MESSAGES_MIXER_LOGGING_NAME = "messages-mixer";
|
||||
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "OctreeInboundPacketProcessor.h"
|
||||
|
||||
#include <limits>
|
||||
|
||||
#include <NumericalConstants.h>
|
||||
|
@ -17,7 +19,6 @@
|
|||
|
||||
#include "OctreeServer.h"
|
||||
#include "OctreeServerConsts.h"
|
||||
#include "OctreeInboundPacketProcessor.h"
|
||||
|
||||
static QUuid DEFAULT_NODE_ID_REF;
|
||||
const quint64 TOO_LONG_SINCE_LAST_NACK = 1 * USECS_PER_SECOND;
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "OctreeSendThread.h"
|
||||
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
|
||||
|
@ -17,7 +19,6 @@
|
|||
#include <udt/PacketHeaders.h>
|
||||
#include <PerfStat.h>
|
||||
|
||||
#include "OctreeSendThread.h"
|
||||
#include "OctreeServer.h"
|
||||
#include "OctreeServerConsts.h"
|
||||
#include "OctreeLogging.h"
|
||||
|
|
|
@ -124,15 +124,14 @@ macro(SETUP_HIFI_TESTCASE)
|
|||
# This target will also build + run the other test targets using ctest when built.
|
||||
|
||||
add_custom_target(${TEST_TARGET}
|
||||
COMMAND ctest .
|
||||
SOURCES ${TEST_PROJ_SRC_FILES} # display source files under the testcase target
|
||||
DEPENDS ${${TEST_PROJ_NAME}_TARGETS})
|
||||
|
||||
set_target_properties(${TEST_TARGET} PROPERTIES
|
||||
FOLDER "Tests"
|
||||
EXCLUDE_FROM_DEFAULT_BUILD TRUE
|
||||
EXCLUDE_FROM_ALL TRUE)
|
||||
|
||||
set_target_properties(${TEST_TARGET} PROPERTIES FOLDER "Tests")
|
||||
|
||||
list (APPEND ALL_TEST_TARGETS ${TEST_TARGET})
|
||||
set(ALL_TEST_TARGETS "${ALL_TEST_TARGETS}" PARENT_SCOPE)
|
||||
else ()
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "DomainServerNodeData.h"
|
||||
|
||||
#include <QtCore/QDataStream>
|
||||
#include <QtCore/QJsonArray>
|
||||
#include <QtCore/QJsonDocument>
|
||||
|
@ -17,8 +19,6 @@
|
|||
|
||||
#include <udt/PacketHeaders.h>
|
||||
|
||||
#include "DomainServerNodeData.h"
|
||||
|
||||
DomainServerNodeData::StringPairHash DomainServerNodeData::_overrideHash;
|
||||
|
||||
DomainServerNodeData::DomainServerNodeData() {
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include <QtCore/QElapsedTimer>
|
||||
#include <QtCore/QHash>
|
||||
#include <QtCore/QUuid>
|
||||
#include <QtCore/QJsonObject>
|
||||
|
||||
#include <HifiSockAddr.h>
|
||||
#include <NLPacket.h>
|
||||
|
|
|
@ -9,13 +9,13 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "DomainServerWebSessionData.h"
|
||||
|
||||
#include <QtCore/QDataStream>
|
||||
#include <QtCore/QDebug>
|
||||
#include <QtCore/QJsonArray>
|
||||
#include <QtCore/QJsonObject>
|
||||
|
||||
#include "DomainServerWebSessionData.h"
|
||||
|
||||
DomainServerWebSessionData::DomainServerWebSessionData() :
|
||||
_username(),
|
||||
_roles()
|
||||
|
|
|
@ -9,14 +9,14 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "Client.h"
|
||||
|
||||
#include <AccountManager.h>
|
||||
#include <AddressManager.h>
|
||||
#include <HifiSockAddr.h>
|
||||
#include <NodeList.h>
|
||||
#include <PacketHeaders.h>
|
||||
|
||||
#include "Client.h"
|
||||
|
||||
Client::Client(QObject* parent) :
|
||||
QObject(parent)
|
||||
{
|
||||
|
@ -70,4 +70,4 @@ void Client::processDatagrams() {
|
|||
processVerifiedPacket(senderSockAddr, incomingPacket);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "GVRInterface.h"
|
||||
|
||||
#ifdef ANDROID
|
||||
|
||||
#include <jni.h>
|
||||
|
@ -32,8 +34,6 @@
|
|||
#include "GVRMainWindow.h"
|
||||
#include "RenderingClient.h"
|
||||
|
||||
#include "GVRInterface.h"
|
||||
|
||||
static QString launchURLString = QString();
|
||||
|
||||
#ifdef ANDROID
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "GVRMainWindow.h"
|
||||
|
||||
#include <QtGui/QKeyEvent>
|
||||
#include <QtWidgets/QApplication>
|
||||
#include <QtWidgets/QInputDialog>
|
||||
|
@ -37,8 +39,6 @@ const float LIBOVR_LONG_PRESS_DURATION = 0.75f;
|
|||
#include "LoginDialog.h"
|
||||
#include "RenderingClient.h"
|
||||
|
||||
#include "GVRMainWindow.h"
|
||||
|
||||
|
||||
|
||||
GVRMainWindow::GVRMainWindow(QWidget* parent) :
|
||||
|
|
|
@ -9,14 +9,14 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "LoginDialog.h"
|
||||
|
||||
#include <QtWidgets/QDialogButtonBox>
|
||||
#include <QtWidgets/QGridLayout>
|
||||
#include <QtWidgets/QLabel>
|
||||
#include <QtWidgets/QLineEdit>
|
||||
#include <QtWidgets/QPushButton>
|
||||
|
||||
#include "LoginDialog.h"
|
||||
|
||||
LoginDialog::LoginDialog(QWidget* parent) :
|
||||
QDialog(parent)
|
||||
{
|
||||
|
@ -66,4 +66,4 @@ void LoginDialog::setupGUI() {
|
|||
void LoginDialog::loginButtonClicked() {
|
||||
emit credentialsEntered(_usernameLineEdit->text(), _passwordLineEdit->text());
|
||||
close();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "RenderingClient.h"
|
||||
|
||||
#include <QtCore/QThread>
|
||||
#include <QtWidgets/QInputDialog>
|
||||
|
||||
|
@ -17,8 +19,6 @@
|
|||
#include <AvatarHashMap.h>
|
||||
#include <NodeList.h>
|
||||
|
||||
#include "RenderingClient.h"
|
||||
|
||||
RenderingClient* RenderingClient::_instance = NULL;
|
||||
|
||||
RenderingClient::RenderingClient(QObject *parent, const QString& launchURLString) :
|
||||
|
|
|
@ -7,6 +7,9 @@
|
|||
//
|
||||
// Sends messages over the EventBridge when text input is required.
|
||||
//
|
||||
|
||||
/* global document, window, console, setTimeout, setInterval, EventBridge */
|
||||
|
||||
(function () {
|
||||
var POLL_FREQUENCY = 500; // ms
|
||||
var MAX_WARNINGS = 3;
|
||||
|
@ -37,22 +40,24 @@
|
|||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function shouldSetNumeric() {
|
||||
return document.activeElement.type === "number";
|
||||
};
|
||||
}
|
||||
|
||||
function scheduleBringToView(timeout) {
|
||||
|
||||
var timer = setTimeout(function () {
|
||||
clearTimeout(timer);
|
||||
|
||||
setTimeout(function () {
|
||||
// If the element is not visible because the keyboard has been raised over the top of it, scroll it up into view.
|
||||
// If the element is not visible because the keyboard raising has moved it off screen, scroll it down into view.
|
||||
var elementRect = document.activeElement.getBoundingClientRect();
|
||||
var absoluteElementTop = elementRect.top + window.scrollY;
|
||||
var middle = absoluteElementTop - (window.innerHeight / 2);
|
||||
|
||||
window.scrollTo(0, middle);
|
||||
var VISUAL_MARGIN = 3;
|
||||
var delta = elementRect.y + elementRect.height + VISUAL_MARGIN - window.innerHeight;
|
||||
if (delta > 0) {
|
||||
window.scrollBy(0, delta);
|
||||
} else if (elementRect.y < VISUAL_MARGIN) {
|
||||
window.scrollBy(0, elementRect.y - VISUAL_MARGIN);
|
||||
}
|
||||
}, timeout);
|
||||
}
|
||||
|
||||
|
@ -62,11 +67,13 @@
|
|||
var passwordField = shouldSetPasswordField();
|
||||
|
||||
if (isWindowFocused &&
|
||||
(keyboardRaised !== window.isKeyboardRaised || numericKeyboard !== window.isNumericKeyboard || passwordField !== window.isPasswordField)) {
|
||||
(keyboardRaised !== window.isKeyboardRaised || numericKeyboard !== window.isNumericKeyboard
|
||||
|| passwordField !== window.isPasswordField)) {
|
||||
|
||||
if (typeof EventBridge !== "undefined" && EventBridge !== null) {
|
||||
EventBridge.emitWebEvent(
|
||||
keyboardRaised ? ("_RAISE_KEYBOARD" + (numericKeyboard ? "_NUMERIC" : "") + (passwordField ? "_PASSWORD" : "")) : "_LOWER_KEYBOARD"
|
||||
keyboardRaised ? ("_RAISE_KEYBOARD" + (numericKeyboard ? "_NUMERIC" : "")
|
||||
+ (passwordField ? "_PASSWORD" : "")) : "_LOWER_KEYBOARD"
|
||||
);
|
||||
} else {
|
||||
if (numWarnings < MAX_WARNINGS) {
|
||||
|
@ -77,7 +84,7 @@
|
|||
|
||||
if (!window.isKeyboardRaised) {
|
||||
scheduleBringToView(250); // Allow time for keyboard to be raised in QML.
|
||||
// 2DO: should it be rather done from 'client area height changed' event?
|
||||
// 2DO: should it be rather done from 'client area height changed' event?
|
||||
}
|
||||
|
||||
window.isKeyboardRaised = keyboardRaised;
|
||||
|
|
|
@ -84,11 +84,9 @@ Item {
|
|||
height: undefined // invalidate so that the image's size sets the height
|
||||
focus: true
|
||||
|
||||
style: OriginalStyles.ButtonStyle {
|
||||
background: Image {
|
||||
id: buttonImage
|
||||
source: "../../images/steam-sign-in.png"
|
||||
}
|
||||
background: Image {
|
||||
id: buttonImage
|
||||
source: "../../images/steam-sign-in.png"
|
||||
}
|
||||
onClicked: signInBody.login()
|
||||
}
|
||||
|
|
|
@ -20,15 +20,10 @@ import "../fileDialog"
|
|||
Item {
|
||||
// Set from OffscreenUi::assetDialog()
|
||||
property alias dir: assetTableModel.folder
|
||||
property alias filter: selectionType.filtersString // FIXME: Currently only supports simple filters, "*.xxx".
|
||||
property int options // Not used.
|
||||
property alias filter: selectionType.filtersString
|
||||
property int options
|
||||
|
||||
property bool selectDirectory: false
|
||||
|
||||
// Not implemented.
|
||||
//property bool saveDialog: false;
|
||||
//property bool multiSelect: false;
|
||||
|
||||
property bool singleClickNavigate: false
|
||||
|
||||
HifiConstants { id: hifi }
|
||||
|
@ -85,7 +80,6 @@ Item {
|
|||
size: 28
|
||||
width: height
|
||||
enabled: destination !== ""
|
||||
//onClicked: d.navigateHome();
|
||||
onClicked: assetTableModel.folder = destination;
|
||||
}
|
||||
}
|
||||
|
@ -228,7 +222,9 @@ Item {
|
|||
|
||||
function onGetAllMappings(error, map) {
|
||||
var mappings,
|
||||
fileTypeFilter,
|
||||
fileTypeFilters = [],
|
||||
filterListStart,
|
||||
filterListEnd,
|
||||
index,
|
||||
path,
|
||||
fileName,
|
||||
|
@ -249,7 +245,16 @@ Item {
|
|||
|
||||
if (error === "") {
|
||||
mappings = Object.keys(map);
|
||||
fileTypeFilter = filter.replace("*", "").toLowerCase();
|
||||
filter = filter.replace(/\s/g, '');
|
||||
filterListStart = filter.indexOf("(");
|
||||
filterListEnd = filter.indexOf(")");
|
||||
if (filterListStart !== -1 && filterListEnd !== -1) {
|
||||
var FIRST_EXTENSION_OFFSET = 2;
|
||||
fileTypeFilters = filter.substring(filterListStart + FIRST_EXTENSION_OFFSET
|
||||
, filterListEnd).toLowerCase().split("*");
|
||||
} else if (filter !== "") {
|
||||
fileTypeFilters[0] = filter.replace("*", "").toLowerCase();
|
||||
}
|
||||
|
||||
for (i = 0, length = mappings.length; i < length; i++) {
|
||||
index = mappings[i].lastIndexOf("/");
|
||||
|
@ -260,7 +265,24 @@ Item {
|
|||
fileIsDir = false;
|
||||
isValid = false;
|
||||
|
||||
if (fileType.toLowerCase() === fileTypeFilter) {
|
||||
if (fileTypeFilters.length > 1) {
|
||||
if (fileTypeFilters.indexOf(fileType.toLowerCase()) !== -1) {
|
||||
if (path === folder) {
|
||||
isValid = !selectDirectory;
|
||||
} else if (path.length > folder.length) {
|
||||
subDirectory = path.slice(folder.length);
|
||||
index = subDirectory.indexOf("/");
|
||||
if (index === subDirectory.lastIndexOf("/")) {
|
||||
fileName = subDirectory.slice(0, index);
|
||||
if (subDirectories.indexOf(fileName) === -1) {
|
||||
fileIsDir = true;
|
||||
isValid = true;
|
||||
subDirectories.push(fileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (fileType.toLowerCase() === fileTypeFilters[0] || fileTypeFilters.length === 0) {
|
||||
if (path === folder) {
|
||||
isValid = !selectDirectory;
|
||||
} else if (path.length > folder.length) {
|
||||
|
|
|
@ -787,7 +787,7 @@ Rectangle {
|
|||
}
|
||||
lightboxPopup.button2text = "CONFIRM";
|
||||
lightboxPopup.button2method = function() {
|
||||
Commerce.replaceContentSet(root.itemHref);
|
||||
Commerce.replaceContentSet(root.itemHref, root.certificateId);
|
||||
lightboxPopup.visible = false;
|
||||
rezzedNotifContainer.visible = true;
|
||||
rezzedNotifContainerTimer.start();
|
||||
|
|
|
@ -49,6 +49,7 @@ Item {
|
|||
property string upgradeTitle;
|
||||
property bool updateAvailable: root.upgradeUrl !== "" && !root.isShowingMyItems;
|
||||
property bool isShowingMyItems;
|
||||
property bool valid;
|
||||
|
||||
property string originalStatusText;
|
||||
property string originalStatusColor;
|
||||
|
@ -239,6 +240,7 @@ Item {
|
|||
width: 62;
|
||||
|
||||
onLoaded: {
|
||||
item.enabled = root.valid;
|
||||
item.buttonGlyphText = hifi.glyphs.gift;
|
||||
item.buttonText = "Gift";
|
||||
item.buttonClicked = function() {
|
||||
|
@ -463,7 +465,7 @@ Item {
|
|||
|
||||
Item {
|
||||
id: statusContainer;
|
||||
visible: root.purchaseStatus === "pending" || root.purchaseStatus === "invalidated" || root.numberSold > -1;
|
||||
visible: root.purchaseStatus === "pending" || !root.valid || root.numberSold > -1;
|
||||
anchors.left: itemName.left;
|
||||
anchors.right: itemName.right;
|
||||
anchors.top: itemName.bottom;
|
||||
|
@ -480,7 +482,7 @@ Item {
|
|||
text: {
|
||||
if (root.purchaseStatus === "pending") {
|
||||
"PENDING..."
|
||||
} else if (root.purchaseStatus === "invalidated") {
|
||||
} else if (!root.valid) {
|
||||
"INVALIDATED"
|
||||
} else if (root.numberSold > -1) {
|
||||
("Sales: " + root.numberSold + "/" + (root.limitedRun === -1 ? "\u221e" : root.limitedRun))
|
||||
|
@ -492,7 +494,7 @@ Item {
|
|||
color: {
|
||||
if (root.purchaseStatus === "pending") {
|
||||
hifi.colors.blueAccent
|
||||
} else if (root.purchaseStatus === "invalidated") {
|
||||
} else if (!root.valid) {
|
||||
hifi.colors.redAccent
|
||||
} else {
|
||||
hifi.colors.baseGray
|
||||
|
@ -506,7 +508,7 @@ Item {
|
|||
text: {
|
||||
if (root.purchaseStatus === "pending") {
|
||||
hifi.glyphs.question
|
||||
} else if (root.purchaseStatus === "invalidated") {
|
||||
} else if (!root.valid) {
|
||||
hifi.glyphs.question
|
||||
} else {
|
||||
""
|
||||
|
@ -523,7 +525,7 @@ Item {
|
|||
color: {
|
||||
if (root.purchaseStatus === "pending") {
|
||||
hifi.colors.blueAccent
|
||||
} else if (root.purchaseStatus === "invalidated") {
|
||||
} else if (!root.valid) {
|
||||
hifi.colors.redAccent
|
||||
} else {
|
||||
hifi.colors.baseGray
|
||||
|
@ -538,7 +540,7 @@ Item {
|
|||
onClicked: {
|
||||
if (root.purchaseStatus === "pending") {
|
||||
sendToPurchases({method: 'showPendingLightbox'});
|
||||
} else if (root.purchaseStatus === "invalidated") {
|
||||
} else if (!root.valid) {
|
||||
sendToPurchases({method: 'showInvalidatedLightbox'});
|
||||
}
|
||||
}
|
||||
|
@ -546,7 +548,7 @@ Item {
|
|||
if (root.purchaseStatus === "pending") {
|
||||
statusText.color = hifi.colors.blueHighlight;
|
||||
statusIcon.color = hifi.colors.blueHighlight;
|
||||
} else if (root.purchaseStatus === "invalidated") {
|
||||
} else if (!root.valid) {
|
||||
statusText.color = hifi.colors.redAccent;
|
||||
statusIcon.color = hifi.colors.redAccent;
|
||||
}
|
||||
|
@ -555,7 +557,7 @@ Item {
|
|||
if (root.purchaseStatus === "pending") {
|
||||
statusText.color = hifi.colors.blueAccent;
|
||||
statusIcon.color = hifi.colors.blueAccent;
|
||||
} else if (root.purchaseStatus === "invalidated") {
|
||||
} else if (!root.valid) {
|
||||
statusText.color = hifi.colors.redHighlight;
|
||||
statusIcon.color = hifi.colors.redHighlight;
|
||||
}
|
||||
|
@ -645,8 +647,8 @@ Item {
|
|||
width: 160;
|
||||
height: 40;
|
||||
enabled: root.hasPermissionToRezThis &&
|
||||
root.purchaseStatus !== "invalidated" &&
|
||||
MyAvatar.skeletonModelURL !== root.itemHref;
|
||||
MyAvatar.skeletonModelURL !== root.itemHref &&
|
||||
root.valid;
|
||||
|
||||
onHoveredChanged: {
|
||||
if (hovered) {
|
||||
|
|
|
@ -616,6 +616,7 @@ Rectangle {
|
|||
upgradeTitle: model.upgrade_title;
|
||||
itemType: model.itemType;
|
||||
isShowingMyItems: root.isShowingMyItems;
|
||||
valid: model.valid;
|
||||
anchors.topMargin: 10;
|
||||
anchors.bottomMargin: 10;
|
||||
|
||||
|
@ -995,10 +996,6 @@ Rectangle {
|
|||
|
||||
for (var i = 0; i < purchasesModel.count; i++) {
|
||||
if (purchasesModel.get(i).title.toLowerCase().indexOf(filterBar.text.toLowerCase()) !== -1) {
|
||||
if (!purchasesModel.get(i).valid) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (purchasesModel.get(i).status !== "confirmed" && !root.isShowingMyItems) {
|
||||
tempPurchasesModel.insert(0, purchasesModel.get(i));
|
||||
} else if ((root.isShowingMyItems && purchasesModel.get(i).edition_number === "0") ||
|
||||
|
@ -1055,10 +1052,6 @@ Rectangle {
|
|||
var currentId;
|
||||
for (var i = 0; i < tempPurchasesModel.count; i++) {
|
||||
currentId = tempPurchasesModel.get(i).id;
|
||||
|
||||
if (!purchasesModel.get(i).valid) {
|
||||
continue;
|
||||
}
|
||||
filteredPurchasesModel.append(tempPurchasesModel.get(i));
|
||||
filteredPurchasesModel.setProperty(i, 'cardBackVisible', false);
|
||||
filteredPurchasesModel.setProperty(i, 'isInstalled', ((root.installedApps).indexOf(currentId) > -1));
|
||||
|
|
|
@ -172,7 +172,7 @@ StackView {
|
|||
source: InputConfiguration.configurationLayout(box.currentText);
|
||||
onLoaded: {
|
||||
if (loader.item.hasOwnProperty("pluginName")) {
|
||||
if (box.currentText === "Vive") {
|
||||
if (box.currentText === "HTC Vive") {
|
||||
loader.item.pluginName = "OpenVR";
|
||||
} else {
|
||||
loader.item.pluginName = box.currentText;
|
||||
|
|
47
interface/resources/shaders/splashSkybox.frag
Normal file
47
interface/resources/shaders/splashSkybox.frag
Normal file
|
@ -0,0 +1,47 @@
|
|||
const vec3 COLOR = vec3(0x00, 0xD8, 0x02) / vec3(0xFF);
|
||||
const float CUTOFF = 0.65;
|
||||
const float NOISE_MULT = 8.0;
|
||||
const float NOISE_POWER = 1.0;
|
||||
|
||||
float noise4D(vec4 p) {
|
||||
return fract(sin(dot(p ,vec4(12.9898,78.233,126.7235, 593.2241))) * 43758.5453);
|
||||
}
|
||||
|
||||
float worley4D(vec4 p) {
|
||||
float r = 3.0;
|
||||
vec4 f = floor(p);
|
||||
vec4 x = fract(p);
|
||||
for(int i = -1; i<=1; i++)
|
||||
{
|
||||
for(int j = -1; j<=1; j++)
|
||||
{
|
||||
for(int k = -1; k<=1; k++)
|
||||
{
|
||||
for (int l = -1; l <= 1; l++) {
|
||||
vec4 q = vec4(float(i),float(j),float(k), float(l));
|
||||
vec4 v = q + vec4(noise4D((q+f)*1.11), noise4D((q+f)*1.14), noise4D((q+f)*1.17), noise4D((q+f)*1.20)) - x;
|
||||
float d = dot(v, v);
|
||||
r = min(r, d);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return sqrt(r);
|
||||
}
|
||||
|
||||
|
||||
vec3 mainColor(vec3 direction) {
|
||||
float n = worley4D(vec4(direction * NOISE_MULT, iGlobalTime / 3.0));
|
||||
n = 1.0 - n;
|
||||
n = pow(n, NOISE_POWER);
|
||||
if (n < CUTOFF) {
|
||||
return vec3(0.0);
|
||||
}
|
||||
|
||||
n = (n - CUTOFF) / (1.0 - CUTOFF);
|
||||
return COLOR * (1.0 - n);
|
||||
}
|
||||
|
||||
vec3 getSkyboxColor() {
|
||||
return mainColor(normalize(_normal));
|
||||
}
|
|
@ -10,11 +10,42 @@
|
|||
//
|
||||
#include "AndroidHelper.h"
|
||||
#include <QDebug>
|
||||
#include <AccountManager.h>
|
||||
|
||||
AndroidHelper::AndroidHelper() {
|
||||
}
|
||||
|
||||
AndroidHelper::~AndroidHelper() {
|
||||
workerThread.quit();
|
||||
workerThread.wait();
|
||||
}
|
||||
|
||||
void AndroidHelper::init() {
|
||||
workerThread.start();
|
||||
_accountManager = QSharedPointer<AccountManager>(new AccountManager, &QObject::deleteLater);
|
||||
_accountManager->setIsAgent(true);
|
||||
_accountManager->setAuthURL(NetworkingConstants::METAVERSE_SERVER_URL());
|
||||
_accountManager->setSessionID(DependencyManager::get<AccountManager>()->getSessionID());
|
||||
connect(_accountManager.data(), &AccountManager::loginComplete, [](const QUrl& authURL) {
|
||||
DependencyManager::get<AccountManager>()->setAccountInfo(AndroidHelper::instance().getAccountManager()->getAccountInfo());
|
||||
DependencyManager::get<AccountManager>()->setAuthURL(authURL);
|
||||
});
|
||||
|
||||
connect(_accountManager.data(), &AccountManager::logoutComplete, [] () {
|
||||
DependencyManager::get<AccountManager>()->logout();
|
||||
});
|
||||
_accountManager->moveToThread(&workerThread);
|
||||
}
|
||||
|
||||
void AndroidHelper::requestActivity(const QString &activityName) {
|
||||
emit androidActivityRequested(activityName);
|
||||
}
|
||||
|
||||
void AndroidHelper::notifyLoadComplete() {
|
||||
emit qtAppLoadComplete();
|
||||
}
|
||||
|
||||
void AndroidHelper::goBackFromAndroidActivity() {
|
||||
emit backFromAndroidActivity();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -13,6 +13,8 @@
|
|||
#define hifi_Android_Helper_h
|
||||
|
||||
#include <QObject>
|
||||
#include <QThread>
|
||||
#include <AccountManager.h>
|
||||
|
||||
class AndroidHelper : public QObject {
|
||||
Q_OBJECT
|
||||
|
@ -21,17 +23,24 @@ public:
|
|||
static AndroidHelper instance;
|
||||
return instance;
|
||||
}
|
||||
void init();
|
||||
void requestActivity(const QString &activityName);
|
||||
void notifyLoadComplete();
|
||||
void goBackFromAndroidActivity();
|
||||
QSharedPointer<AccountManager> getAccountManager() { return _accountManager; }
|
||||
|
||||
AndroidHelper(AndroidHelper const&) = delete;
|
||||
void operator=(AndroidHelper const&) = delete;
|
||||
signals:
|
||||
void androidActivityRequested(const QString &activityName);
|
||||
void backFromAndroidActivity();
|
||||
void qtAppLoadComplete();
|
||||
|
||||
private:
|
||||
AndroidHelper() {}
|
||||
AndroidHelper();
|
||||
~AndroidHelper();
|
||||
QSharedPointer<AccountManager> _accountManager;
|
||||
QThread workerThread;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -144,16 +144,7 @@
|
|||
#include <trackers/EyeTracker.h>
|
||||
#include <avatars-renderer/ScriptAvatar.h>
|
||||
#include <RenderableEntityItem.h>
|
||||
|
||||
#include <AnimationLogging.h>
|
||||
#include <AvatarLogging.h>
|
||||
#include <ScriptEngineLogging.h>
|
||||
#include <ModelFormatLogging.h>
|
||||
#include <controllers/Logging.h>
|
||||
#include <NetworkLogging.h>
|
||||
#include <shared/StorageLogging.h>
|
||||
#include <ScriptEngineLogging.h>
|
||||
#include <ui/Logging.h>
|
||||
#include <procedural/ProceduralSkybox.h>
|
||||
|
||||
#include "AudioClient.h"
|
||||
#include "audio/AudioScope.h"
|
||||
|
@ -385,7 +376,7 @@ Setting::Handle<int> maxOctreePacketsPerSecond("maxOctreePPS", DEFAULT_MAX_OCTRE
|
|||
static const QString MARKETPLACE_CDN_HOSTNAME = "mpassets.highfidelity.com";
|
||||
static const int INTERVAL_TO_CHECK_HMD_WORN_STATUS = 500; // milliseconds
|
||||
static const QString DESKTOP_DISPLAY_PLUGIN_NAME = "Desktop";
|
||||
|
||||
static const QString ACTIVE_DISPLAY_PLUGIN_SETTING_NAME = "activeDisplayPlugin";
|
||||
static const QString SYSTEM_TABLET = "com.highfidelity.interface.tablet.system";
|
||||
|
||||
const std::vector<std::pair<QString, Application::AcceptURLMethod>> Application::_acceptedExtensions {
|
||||
|
@ -743,6 +734,11 @@ extern DisplayPluginList getDisplayPlugins();
|
|||
extern InputPluginList getInputPlugins();
|
||||
extern void saveInputPluginSettings(const InputPluginList& plugins);
|
||||
|
||||
// Parameters used for running tests from teh command line
|
||||
const QString TEST_SCRIPT_COMMAND{ "--testScript" };
|
||||
const QString TEST_QUIT_WHEN_FINISHED_OPTION{ "quitWhenFinished" };
|
||||
const QString TEST_RESULTS_LOCATION_COMMAND{ "--testResultsLocation" };
|
||||
|
||||
bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) {
|
||||
const char** constArgv = const_cast<const char**>(argv);
|
||||
|
||||
|
@ -777,7 +773,22 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) {
|
|||
|
||||
static const auto SUPPRESS_SETTINGS_RESET = "--suppress-settings-reset";
|
||||
bool suppressPrompt = cmdOptionExists(argc, const_cast<const char**>(argv), SUPPRESS_SETTINGS_RESET);
|
||||
bool previousSessionCrashed = CrashHandler::checkForResetSettings(runningMarkerExisted, suppressPrompt);
|
||||
|
||||
// Ignore any previous crashes if running from command line with a test script.
|
||||
bool inTestMode { false };
|
||||
for (int i = 0; i < argc; ++i) {
|
||||
QString parameter(argv[i]);
|
||||
if (parameter == TEST_SCRIPT_COMMAND) {
|
||||
inTestMode = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool previousSessionCrashed { false };
|
||||
if (!inTestMode) {
|
||||
previousSessionCrashed = CrashHandler::checkForResetSettings(runningMarkerExisted, suppressPrompt);
|
||||
}
|
||||
|
||||
// get dir to use for cache
|
||||
static const auto CACHE_SWITCH = "--cache";
|
||||
QString cacheDir = getCmdOption(argc, const_cast<const char**>(argv), CACHE_SWITCH);
|
||||
|
@ -840,7 +851,11 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) {
|
|||
DependencyManager::set<Cursor::Manager>();
|
||||
DependencyManager::set<VirtualPad::Manager>();
|
||||
DependencyManager::set<DesktopPreviewProvider>();
|
||||
#if defined(Q_OS_ANDROID)
|
||||
DependencyManager::set<AccountManager>(); // use the default user agent getter
|
||||
#else
|
||||
DependencyManager::set<AccountManager>(std::bind(&Application::getUserAgent, qApp));
|
||||
#endif
|
||||
DependencyManager::set<StatTracker>();
|
||||
DependencyManager::set<ScriptEngines>(ScriptEngine::CLIENT_SCRIPT);
|
||||
DependencyManager::set<ScriptInitializerMixin, NativeScriptInitializers>();
|
||||
|
@ -996,14 +1011,34 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
|||
setProperty(hifi::properties::STEAM, (steamClient && steamClient->isRunning()));
|
||||
setProperty(hifi::properties::CRASHED, _previousSessionCrashed);
|
||||
{
|
||||
const QString TEST_SCRIPT = "--testScript";
|
||||
const QStringList args = arguments();
|
||||
|
||||
for (int i = 0; i < args.size() - 1; ++i) {
|
||||
if (args.at(i) == TEST_SCRIPT) {
|
||||
if (args.at(i) == TEST_SCRIPT_COMMAND && (i + 1) < args.size()) {
|
||||
QString testScriptPath = args.at(i + 1);
|
||||
if (QFileInfo(testScriptPath).exists()) {
|
||||
|
||||
// If the URL scheme is http(s) or ftp, then use as is, else - treat it as a local file
|
||||
// This is done so as not break previous command line scripts
|
||||
if (testScriptPath.left(URL_SCHEME_HTTP.length()) == URL_SCHEME_HTTP ||
|
||||
testScriptPath.left(URL_SCHEME_FTP.length()) == URL_SCHEME_FTP) {
|
||||
|
||||
setProperty(hifi::properties::TEST, QUrl::fromUserInput(testScriptPath));
|
||||
} else if (QFileInfo(testScriptPath).exists()) {
|
||||
setProperty(hifi::properties::TEST, QUrl::fromLocalFile(testScriptPath));
|
||||
}
|
||||
|
||||
// quite when finished parameter must directly follow the test script
|
||||
if ((i + 2) < args.size() && args.at(i + 2) == TEST_QUIT_WHEN_FINISHED_OPTION) {
|
||||
quitWhenFinished = true;
|
||||
}
|
||||
} else if (args.at(i) == TEST_RESULTS_LOCATION_COMMAND) {
|
||||
// Set test snapshot location only if it is a writeable directory
|
||||
QString path(args.at(i + 1));
|
||||
|
||||
QFileInfo fileInfo(path);
|
||||
if (fileInfo.isDir() && fileInfo.isWritable()) {
|
||||
TestScriptingInterface::getInstance()->setTestResultsLocation(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1322,10 +1357,14 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
|||
QCoreApplication::processEvents();
|
||||
_glWidget->createContext();
|
||||
|
||||
// Create the main thread context, the GPU backend, and the display plugins
|
||||
// Create the main thread context, the GPU backend
|
||||
initializeGL();
|
||||
DependencyManager::get<TextureCache>()->setGPUContext(_gpuContext);
|
||||
qCDebug(interfaceapp, "Initialized Display.");
|
||||
qCDebug(interfaceapp, "Initialized GL");
|
||||
|
||||
// Initialize the display plugin architecture
|
||||
initializeDisplayPlugins();
|
||||
qCDebug(interfaceapp, "Initialized Display");
|
||||
|
||||
// Create the rendering engine. This can be slow on some machines due to lots of
|
||||
// GPU pipeline creation.
|
||||
initializeRenderEngine();
|
||||
|
@ -1335,8 +1374,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
|||
// Needs to happen AFTER the render engine initialization to access its configuration
|
||||
initializeUi();
|
||||
|
||||
updateVerboseLogging();
|
||||
|
||||
init();
|
||||
qCDebug(interfaceapp, "init() complete.");
|
||||
|
||||
|
@ -1676,6 +1713,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
|||
|
||||
loadSettings();
|
||||
|
||||
updateVerboseLogging();
|
||||
|
||||
// Now that we've loaded the menu and thus switched to the previous display plugin
|
||||
// we can unlock the desktop repositioning code, since all the positions will be
|
||||
// relative to the desktop size for this plugin
|
||||
|
@ -2128,14 +2167,24 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
|||
return entityServerNode && !isPhysicsEnabled();
|
||||
});
|
||||
|
||||
_snapshotSound = DependencyManager::get<SoundCache>()->getSound(PathUtils::resourcesUrl("sounds/snap.wav"));
|
||||
_snapshotSound = DependencyManager::get<SoundCache>()->getSound(PathUtils::resourcesUrl("sounds/snapshot/snap.wav"));
|
||||
|
||||
QVariant testProperty = property(hifi::properties::TEST);
|
||||
qDebug() << testProperty;
|
||||
if (testProperty.isValid()) {
|
||||
auto scriptEngines = DependencyManager::get<ScriptEngines>();
|
||||
const auto testScript = property(hifi::properties::TEST).toUrl();
|
||||
scriptEngines->loadScript(testScript, false);
|
||||
|
||||
// Set last parameter to exit interface when the test script finishes, if so requested
|
||||
scriptEngines->loadScript(testScript, false, false, false, false, quitWhenFinished);
|
||||
|
||||
// This is done so we don't get a "connection time-out" message when we haven't passed in a URL.
|
||||
if (arguments().contains("--url")) {
|
||||
auto reply = SandboxUtils::getStatus();
|
||||
connect(reply, &QNetworkReply::finished, this, [=] {
|
||||
handleSandboxStatus(reply);
|
||||
});
|
||||
}
|
||||
} else {
|
||||
PROFILE_RANGE(render, "GetSandboxStatus");
|
||||
auto reply = SandboxUtils::getStatus();
|
||||
|
@ -2207,46 +2256,27 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
|||
_pendingRenderEvent = false;
|
||||
|
||||
qCDebug(interfaceapp) << "Metaverse session ID is" << uuidStringWithoutCurlyBraces(accountManager->getSessionID());
|
||||
|
||||
#if defined(Q_OS_ANDROID)
|
||||
AndroidHelper::instance().init();
|
||||
AndroidHelper::instance().notifyLoadComplete();
|
||||
#endif
|
||||
}
|
||||
|
||||
void Application::updateVerboseLogging() {
|
||||
bool enable = Menu::getInstance()->isOptionChecked(MenuOption::VerboseLogging);
|
||||
auto menu = Menu::getInstance();
|
||||
if (!menu) {
|
||||
return;
|
||||
}
|
||||
bool enable = menu->isOptionChecked(MenuOption::VerboseLogging);
|
||||
|
||||
const_cast<QLoggingCategory*>(&animation())->setEnabled(QtDebugMsg, enable);
|
||||
const_cast<QLoggingCategory*>(&animation())->setEnabled(QtInfoMsg, enable);
|
||||
|
||||
const_cast<QLoggingCategory*>(&avatars())->setEnabled(QtDebugMsg, enable);
|
||||
const_cast<QLoggingCategory*>(&avatars())->setEnabled(QtInfoMsg, enable);
|
||||
|
||||
const_cast<QLoggingCategory*>(&scriptengine())->setEnabled(QtDebugMsg, enable);
|
||||
const_cast<QLoggingCategory*>(&scriptengine())->setEnabled(QtInfoMsg, enable);
|
||||
|
||||
const_cast<QLoggingCategory*>(&modelformat())->setEnabled(QtDebugMsg, enable);
|
||||
const_cast<QLoggingCategory*>(&modelformat())->setEnabled(QtInfoMsg, enable);
|
||||
|
||||
const_cast<QLoggingCategory*>(&controllers())->setEnabled(QtDebugMsg, enable);
|
||||
const_cast<QLoggingCategory*>(&controllers())->setEnabled(QtInfoMsg, enable);
|
||||
|
||||
const_cast<QLoggingCategory*>(&resourceLog())->setEnabled(QtDebugMsg, enable);
|
||||
const_cast<QLoggingCategory*>(&resourceLog())->setEnabled(QtInfoMsg, enable);
|
||||
|
||||
const_cast<QLoggingCategory*>(&networking())->setEnabled(QtDebugMsg, enable);
|
||||
const_cast<QLoggingCategory*>(&networking())->setEnabled(QtInfoMsg, enable);
|
||||
|
||||
const_cast<QLoggingCategory*>(&asset_client())->setEnabled(QtDebugMsg, enable);
|
||||
const_cast<QLoggingCategory*>(&asset_client())->setEnabled(QtInfoMsg, enable);
|
||||
|
||||
const_cast<QLoggingCategory*>(&messages_client())->setEnabled(QtDebugMsg, enable);
|
||||
const_cast<QLoggingCategory*>(&messages_client())->setEnabled(QtInfoMsg, enable);
|
||||
|
||||
const_cast<QLoggingCategory*>(&storagelogging())->setEnabled(QtDebugMsg, enable);
|
||||
const_cast<QLoggingCategory*>(&storagelogging())->setEnabled(QtInfoMsg, enable);
|
||||
|
||||
const_cast<QLoggingCategory*>(&uiLogging())->setEnabled(QtDebugMsg, enable);
|
||||
const_cast<QLoggingCategory*>(&uiLogging())->setEnabled(QtInfoMsg, enable);
|
||||
|
||||
const_cast<QLoggingCategory*>(&glLogging())->setEnabled(QtDebugMsg, enable);
|
||||
const_cast<QLoggingCategory*>(&glLogging())->setEnabled(QtInfoMsg, enable);
|
||||
QString rules =
|
||||
"hifi.*.debug=%1\n"
|
||||
"hifi.*.info=%1\n"
|
||||
"hifi.audio-stream.debug=false\n"
|
||||
"hifi.audio-stream.info=false";
|
||||
rules = rules.arg(enable ? "true" : "false");
|
||||
QLoggingCategory::setFilterRules(rules);
|
||||
}
|
||||
|
||||
void Application::domainConnectionRefused(const QString& reasonMessage, int reasonCodeInt, const QString& extraInfo) {
|
||||
|
@ -2359,6 +2389,10 @@ void Application::onAboutToQuit() {
|
|||
}
|
||||
}
|
||||
|
||||
// The active display plugin needs to be loaded before the menu system is active,
|
||||
// so its persisted explicitly here
|
||||
Setting::Handle<QString>{ ACTIVE_DISPLAY_PLUGIN_SETTING_NAME }.set(getActiveDisplayPlugin()->getName());
|
||||
|
||||
getActiveDisplayPlugin()->deactivate();
|
||||
if (_autoSwitchDisplayModeSupportedHMDPlugin
|
||||
&& _autoSwitchDisplayModeSupportedHMDPlugin->isSessionActive()) {
|
||||
|
@ -2598,10 +2632,84 @@ void Application::initializeGL() {
|
|||
_glWidget->makeCurrent();
|
||||
_gpuContext = std::make_shared<gpu::Context>();
|
||||
|
||||
DependencyManager::get<TextureCache>()->setGPUContext(_gpuContext);
|
||||
|
||||
// Restore the default main thread context
|
||||
_offscreenContext->makeCurrent();
|
||||
}
|
||||
|
||||
updateDisplayMode();
|
||||
static const QString SPLASH_SKYBOX{ "{\"ProceduralEntity\":{ \"version\":2, \"shaderUrl\":\"qrc:///shaders/splashSkybox.frag\" } }" };
|
||||
|
||||
void Application::initializeDisplayPlugins() {
|
||||
auto displayPlugins = PluginManager::getInstance()->getDisplayPlugins();
|
||||
Setting::Handle<QString> activeDisplayPluginSetting{ ACTIVE_DISPLAY_PLUGIN_SETTING_NAME, displayPlugins.at(0)->getName() };
|
||||
auto lastActiveDisplayPluginName = activeDisplayPluginSetting.get();
|
||||
|
||||
auto defaultDisplayPlugin = displayPlugins.at(0);
|
||||
// Once time initialization code
|
||||
DisplayPluginPointer targetDisplayPlugin;
|
||||
foreach(auto displayPlugin, displayPlugins) {
|
||||
displayPlugin->setContext(_gpuContext);
|
||||
if (displayPlugin->getName() == lastActiveDisplayPluginName) {
|
||||
targetDisplayPlugin = displayPlugin;
|
||||
}
|
||||
QObject::connect(displayPlugin.get(), &DisplayPlugin::recommendedFramebufferSizeChanged,
|
||||
[this](const QSize& size) { resizeGL(); });
|
||||
QObject::connect(displayPlugin.get(), &DisplayPlugin::resetSensorsRequested, this, &Application::requestReset);
|
||||
}
|
||||
|
||||
// The default display plugin needs to be activated first, otherwise the display plugin thread
|
||||
// may be launched by an external plugin, which is bad
|
||||
setDisplayPlugin(defaultDisplayPlugin);
|
||||
|
||||
// Now set the desired plugin if it's not the same as the default plugin
|
||||
if (targetDisplayPlugin != defaultDisplayPlugin) {
|
||||
setDisplayPlugin(targetDisplayPlugin);
|
||||
}
|
||||
|
||||
// Submit a default frame to render until the engine starts up
|
||||
updateRenderArgs(0.0f);
|
||||
|
||||
_offscreenContext->makeCurrent();
|
||||
|
||||
#define ENABLE_SPLASH_FRAME 0
|
||||
#if ENABLE_SPLASH_FRAME
|
||||
{
|
||||
QMutexLocker viewLocker(&_renderArgsMutex);
|
||||
|
||||
if (_appRenderArgs._isStereo) {
|
||||
_gpuContext->enableStereo(true);
|
||||
_gpuContext->setStereoProjections(_appRenderArgs._eyeProjections);
|
||||
_gpuContext->setStereoViews(_appRenderArgs._eyeOffsets);
|
||||
}
|
||||
|
||||
// Frame resources
|
||||
auto framebufferCache = DependencyManager::get<FramebufferCache>();
|
||||
gpu::FramebufferPointer finalFramebuffer = framebufferCache->getFramebuffer();
|
||||
std::shared_ptr<ProceduralSkybox> procedural = std::make_shared<ProceduralSkybox>();
|
||||
procedural->parse(SPLASH_SKYBOX);
|
||||
|
||||
_gpuContext->beginFrame(_appRenderArgs._view, _appRenderArgs._headPose);
|
||||
gpu::doInBatch("splashFrame", _gpuContext, [&](gpu::Batch& batch) {
|
||||
batch.resetStages();
|
||||
batch.enableStereo(false);
|
||||
batch.setFramebuffer(finalFramebuffer);
|
||||
batch.clearColorFramebuffer(gpu::Framebuffer::BUFFER_COLOR0, { 0, 0, 0, 1 });
|
||||
batch.enableSkybox(true);
|
||||
batch.enableStereo(_appRenderArgs._isStereo);
|
||||
batch.setViewportTransform({ 0, 0, finalFramebuffer->getSize() });
|
||||
procedural->render(batch, _appRenderArgs._renderArgs.getViewFrustum());
|
||||
});
|
||||
auto frame = _gpuContext->endFrame();
|
||||
frame->frameIndex = 0;
|
||||
frame->framebuffer = finalFramebuffer;
|
||||
frame->pose = _appRenderArgs._headPose;
|
||||
frame->framebufferRecycler = [framebufferCache, procedural](const gpu::FramebufferPointer& framebuffer) {
|
||||
framebufferCache->releaseFramebuffer(framebuffer);
|
||||
};
|
||||
_displayPlugin->submitFrame(frame);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void Application::initializeRenderEngine() {
|
||||
|
@ -2625,6 +2733,7 @@ void Application::initializeRenderEngine() {
|
|||
}
|
||||
|
||||
extern void setupPreferences();
|
||||
static void addDisplayPluginToMenu(const DisplayPluginPointer& displayPlugin, bool active);
|
||||
|
||||
void Application::initializeUi() {
|
||||
// Build a shared canvas / context for the Chromium processes
|
||||
|
@ -2766,10 +2875,25 @@ void Application::initializeUi() {
|
|||
offscreenSurfaceCache->reserve(TabletScriptingInterface::QML, 1);
|
||||
offscreenSurfaceCache->reserve(Web3DOverlay::QML, 2);
|
||||
|
||||
// Now that the menu is instantiated, ensure the display plugin menu is properly updated
|
||||
updateDisplayMode();
|
||||
flushMenuUpdates();
|
||||
|
||||
// Now that the menu is instantiated, ensure the display plugin menu is properly updated
|
||||
{
|
||||
auto displayPlugins = PluginManager::getInstance()->getDisplayPlugins();
|
||||
// first sort the plugins into groupings: standard, advanced, developer
|
||||
std::stable_sort(displayPlugins.begin(), displayPlugins.end(),
|
||||
[](const DisplayPluginPointer& a, const DisplayPluginPointer& b)->bool { return a->getGrouping() < b->getGrouping(); });
|
||||
|
||||
// concatenate the groupings into a single list in the order: standard, advanced, developer
|
||||
for(const auto& displayPlugin : displayPlugins) {
|
||||
addDisplayPluginToMenu(displayPlugin, _displayPlugin == displayPlugin);
|
||||
}
|
||||
|
||||
// after all plugins have been added to the menu, add a separator to the menu
|
||||
auto parent = getPrimaryMenu()->getMenu(MenuOption::OutputMenu);
|
||||
parent->addSeparator();
|
||||
}
|
||||
|
||||
// The display plugins are created before the menu now, so we need to do this here to hide the menu bar
|
||||
// now that it exists
|
||||
if (_window && _window->isFullScreen()) {
|
||||
|
@ -2920,7 +3044,7 @@ void Application::updateCamera(RenderArgs& renderArgs, float deltaTime) {
|
|||
_thirdPersonHMDCameraBoomValid = false;
|
||||
|
||||
_myCamera.setOrientation(myAvatar->getHead()->getOrientation());
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::CenterPlayerInView)) {
|
||||
if (isOptionChecked(MenuOption::CenterPlayerInView)) {
|
||||
_myCamera.setPosition(myAvatar->getDefaultEyePosition()
|
||||
+ _myCamera.getOrientation() * boomOffset);
|
||||
}
|
||||
|
@ -3175,7 +3299,6 @@ void Application::handleSandboxStatus(QNetworkReply* reply) {
|
|||
qCDebug(interfaceapp) << "First run... going to" << qPrintable(addressLookupString.isEmpty() ? QString("default location") : addressLookupString);
|
||||
DependencyManager::get<AddressManager>()->loadSettings(addressLookupString);
|
||||
#else
|
||||
showHelp();
|
||||
DependencyManager::get<AddressManager>()->goToEntry();
|
||||
sentTo = SENT_TO_ENTRY;
|
||||
#endif
|
||||
|
@ -3634,7 +3757,7 @@ void Application::keyPressEvent(QKeyEvent* event) {
|
|||
} else {
|
||||
showCursor(Cursor::Icon::DEFAULT);
|
||||
}
|
||||
} else {
|
||||
} else if (!event->isAutoRepeat()){
|
||||
resetSensors(true);
|
||||
}
|
||||
break;
|
||||
|
@ -5723,6 +5846,32 @@ void Application::update(float deltaTime) {
|
|||
}
|
||||
|
||||
|
||||
updateRenderArgs(deltaTime);
|
||||
|
||||
// HACK
|
||||
// load the view frustum
|
||||
// FIXME: This preDisplayRender call is temporary until we create a separate render::scene for the mirror rendering.
|
||||
// Then we can move this logic into the Avatar::simulate call.
|
||||
myAvatar->preDisplaySide(&_appRenderArgs._renderArgs);
|
||||
|
||||
|
||||
{
|
||||
PerformanceTimer perfTimer("limitless");
|
||||
AnimDebugDraw::getInstance().update();
|
||||
}
|
||||
|
||||
{
|
||||
PerformanceTimer perfTimer("limitless");
|
||||
DependencyManager::get<LimitlessVoiceRecognitionScriptingInterface>()->update();
|
||||
}
|
||||
|
||||
{ // Game loop is done, mark the end of the frame for the scene transactions and the render loop to take over
|
||||
PerformanceTimer perfTimer("enqueueFrame");
|
||||
getMain3DScene()->enqueueFrame();
|
||||
}
|
||||
}
|
||||
|
||||
void Application::updateRenderArgs(float deltaTime) {
|
||||
editRenderArgs([this, deltaTime](AppRenderArgs& appRenderArgs) {
|
||||
PerformanceTimer perfTimer("editRenderArgs");
|
||||
appRenderArgs._headPose = getHMDSensorPose();
|
||||
|
@ -5746,9 +5895,9 @@ void Application::update(float deltaTime) {
|
|||
QMutexLocker viewLocker(&_viewMutex);
|
||||
// adjust near clip plane to account for sensor scaling.
|
||||
auto adjustedProjection = glm::perspective(glm::radians(_fieldOfView.get()),
|
||||
getActiveDisplayPlugin()->getRecommendedAspectRatio(),
|
||||
DEFAULT_NEAR_CLIP * sensorToWorldScale,
|
||||
DEFAULT_FAR_CLIP);
|
||||
getActiveDisplayPlugin()->getRecommendedAspectRatio(),
|
||||
DEFAULT_NEAR_CLIP * sensorToWorldScale,
|
||||
DEFAULT_FAR_CLIP);
|
||||
_viewFrustum.setProjection(adjustedProjection);
|
||||
_viewFrustum.calculate();
|
||||
}
|
||||
|
@ -5764,8 +5913,14 @@ void Application::update(float deltaTime) {
|
|||
}
|
||||
{
|
||||
PROFILE_RANGE(render, "/resizeGL");
|
||||
PerformanceWarning::setSuppressShortTimings(Menu::getInstance()->isOptionChecked(MenuOption::SuppressShortTimings));
|
||||
bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
|
||||
bool showWarnings = false;
|
||||
bool suppressShortTimings = false;
|
||||
auto menu = Menu::getInstance();
|
||||
if (menu) {
|
||||
suppressShortTimings = menu->isOptionChecked(MenuOption::SuppressShortTimings);
|
||||
showWarnings = menu->isOptionChecked(MenuOption::PipelineWarnings);
|
||||
}
|
||||
PerformanceWarning::setSuppressShortTimings(suppressShortTimings);
|
||||
PerformanceWarning warn(showWarnings, "Application::paintGL()");
|
||||
resizeGL();
|
||||
}
|
||||
|
@ -5821,12 +5976,6 @@ void Application::update(float deltaTime) {
|
|||
}
|
||||
}
|
||||
|
||||
// HACK
|
||||
// load the view frustum
|
||||
// FIXME: This preDisplayRender call is temporary until we create a separate render::scene for the mirror rendering.
|
||||
// Then we can move this logic into the Avatar::simulate call.
|
||||
myAvatar->preDisplaySide(&appRenderArgs._renderArgs);
|
||||
|
||||
{
|
||||
QMutexLocker viewLocker(&_viewMutex);
|
||||
_myCamera.loadViewFrustum(_displayViewFrustum);
|
||||
|
@ -5838,21 +5987,6 @@ void Application::update(float deltaTime) {
|
|||
appRenderArgs._renderArgs.setViewFrustum(_displayViewFrustum);
|
||||
}
|
||||
});
|
||||
|
||||
{
|
||||
PerformanceTimer perfTimer("limitless");
|
||||
AnimDebugDraw::getInstance().update();
|
||||
}
|
||||
|
||||
{
|
||||
PerformanceTimer perfTimer("limitless");
|
||||
DependencyManager::get<LimitlessVoiceRecognitionScriptingInterface>()->update();
|
||||
}
|
||||
|
||||
{ // Game loop is done, mark the end of the frame for the scene transactions and the render loop to take over
|
||||
PerformanceTimer perfTimer("enqueueFrame");
|
||||
getMain3DScene()->enqueueFrame();
|
||||
}
|
||||
}
|
||||
|
||||
void Application::queryAvatars() {
|
||||
|
@ -7466,7 +7600,9 @@ void Application::loadAvatarBrowser() const {
|
|||
void Application::takeSnapshot(bool notify, bool includeAnimated, float aspectRatio, const QString& filename) {
|
||||
postLambdaEvent([notify, includeAnimated, aspectRatio, filename, this] {
|
||||
// Get a screenshot and save it
|
||||
QString path = Snapshot::saveSnapshot(getActiveDisplayPlugin()->getScreenshot(aspectRatio), filename);
|
||||
QString path = Snapshot::saveSnapshot(getActiveDisplayPlugin()->getScreenshot(aspectRatio), filename,
|
||||
TestScriptingInterface::getInstance()->getTestResultsLocation());
|
||||
|
||||
// If we're not doing an animated snapshot as well...
|
||||
if (!includeAnimated) {
|
||||
// Tell the dependency manager that the capture of the still snapshot has taken place.
|
||||
|
@ -7480,7 +7616,9 @@ void Application::takeSnapshot(bool notify, bool includeAnimated, float aspectRa
|
|||
|
||||
void Application::takeSecondaryCameraSnapshot(const QString& filename) {
|
||||
postLambdaEvent([filename, this] {
|
||||
QString snapshotPath = Snapshot::saveSnapshot(getActiveDisplayPlugin()->getSecondaryCameraScreenshot(), filename);
|
||||
QString snapshotPath = Snapshot::saveSnapshot(getActiveDisplayPlugin()->getSecondaryCameraScreenshot(), filename,
|
||||
TestScriptingInterface::getInstance()->getTestResultsLocation());
|
||||
|
||||
emit DependencyManager::get<WindowScriptingInterface>()->stillSnapshotTaken(snapshotPath, true);
|
||||
});
|
||||
}
|
||||
|
@ -7493,15 +7631,19 @@ void Application::shareSnapshot(const QString& path, const QUrl& href) {
|
|||
}
|
||||
|
||||
float Application::getRenderResolutionScale() const {
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::RenderResolutionOne)) {
|
||||
auto menu = Menu::getInstance();
|
||||
if (!menu) {
|
||||
return 1.0f;
|
||||
} else if (Menu::getInstance()->isOptionChecked(MenuOption::RenderResolutionTwoThird)) {
|
||||
}
|
||||
if (menu->isOptionChecked(MenuOption::RenderResolutionOne)) {
|
||||
return 1.0f;
|
||||
} else if (menu->isOptionChecked(MenuOption::RenderResolutionTwoThird)) {
|
||||
return 0.666f;
|
||||
} else if (Menu::getInstance()->isOptionChecked(MenuOption::RenderResolutionHalf)) {
|
||||
} else if (menu->isOptionChecked(MenuOption::RenderResolutionHalf)) {
|
||||
return 0.5f;
|
||||
} else if (Menu::getInstance()->isOptionChecked(MenuOption::RenderResolutionThird)) {
|
||||
} else if (menu->isOptionChecked(MenuOption::RenderResolutionThird)) {
|
||||
return 0.333f;
|
||||
} else if (Menu::getInstance()->isOptionChecked(MenuOption::RenderResolutionQuarter)) {
|
||||
} else if (menu->isOptionChecked(MenuOption::RenderResolutionQuarter)) {
|
||||
return 0.25f;
|
||||
} else {
|
||||
return 1.0f;
|
||||
|
@ -7725,7 +7867,7 @@ DisplayPluginPointer Application::getActiveDisplayPlugin() const {
|
|||
|
||||
static const char* EXCLUSION_GROUP_KEY = "exclusionGroup";
|
||||
|
||||
static void addDisplayPluginToMenu(DisplayPluginPointer displayPlugin, bool active = false) {
|
||||
static void addDisplayPluginToMenu(const DisplayPluginPointer& displayPlugin, bool active) {
|
||||
auto menu = Menu::getInstance();
|
||||
QString name = displayPlugin->getName();
|
||||
auto grouping = displayPlugin->getGrouping();
|
||||
|
@ -7770,65 +7912,12 @@ void Application::updateDisplayMode() {
|
|||
qFatal("Attempted to switch display plugins from a non-main thread");
|
||||
}
|
||||
|
||||
auto displayPlugins = PluginManager::getInstance()->getDisplayPlugins();
|
||||
|
||||
// Once time initialization code
|
||||
static std::once_flag once;
|
||||
std::call_once(once, [&] {
|
||||
foreach(auto displayPlugin, displayPlugins) {
|
||||
displayPlugin->setContext(_gpuContext);
|
||||
QObject::connect(displayPlugin.get(), &DisplayPlugin::recommendedFramebufferSizeChanged,
|
||||
[this](const QSize& size) { resizeGL(); });
|
||||
QObject::connect(displayPlugin.get(), &DisplayPlugin::resetSensorsRequested, this, &Application::requestReset);
|
||||
}
|
||||
});
|
||||
|
||||
// Once time initialization code that depends on the UI being available
|
||||
auto menu = Menu::getInstance();
|
||||
if (menu) {
|
||||
static std::once_flag onceUi;
|
||||
std::call_once(onceUi, [&] {
|
||||
bool first = true;
|
||||
|
||||
// first sort the plugins into groupings: standard, advanced, developer
|
||||
DisplayPluginList standard;
|
||||
DisplayPluginList advanced;
|
||||
DisplayPluginList developer;
|
||||
foreach(auto displayPlugin, displayPlugins) {
|
||||
displayPlugin->setContext(_gpuContext);
|
||||
auto grouping = displayPlugin->getGrouping();
|
||||
switch (grouping) {
|
||||
case Plugin::ADVANCED:
|
||||
advanced.push_back(displayPlugin);
|
||||
break;
|
||||
case Plugin::DEVELOPER:
|
||||
developer.push_back(displayPlugin);
|
||||
break;
|
||||
default:
|
||||
standard.push_back(displayPlugin);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// concatenate the groupings into a single list in the order: standard, advanced, developer
|
||||
standard.insert(std::end(standard), std::begin(advanced), std::end(advanced));
|
||||
standard.insert(std::end(standard), std::begin(developer), std::end(developer));
|
||||
|
||||
foreach(auto displayPlugin, standard) {
|
||||
addDisplayPluginToMenu(displayPlugin, first);
|
||||
first = false;
|
||||
}
|
||||
|
||||
// after all plugins have been added to the menu, add a separator to the menu
|
||||
auto parent = menu->getMenu(MenuOption::OutputMenu);
|
||||
parent->addSeparator();
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
auto displayPlugins = getDisplayPlugins();
|
||||
|
||||
// Default to the first item on the list, in case none of the menu items match
|
||||
DisplayPluginPointer newDisplayPlugin = displayPlugins.at(0);
|
||||
auto menu = getPrimaryMenu();
|
||||
if (menu) {
|
||||
foreach(DisplayPluginPointer displayPlugin, PluginManager::getInstance()->getDisplayPlugins()) {
|
||||
QString name = displayPlugin->getName();
|
||||
|
@ -7852,6 +7941,14 @@ void Application::updateDisplayMode() {
|
|||
}
|
||||
|
||||
void Application::setDisplayPlugin(DisplayPluginPointer newDisplayPlugin) {
|
||||
if (newDisplayPlugin == _displayPlugin) {
|
||||
return;
|
||||
}
|
||||
|
||||
// FIXME don't have the application directly set the state of the UI,
|
||||
// instead emit a signal that the display plugin is changing and let
|
||||
// the desktop lock itself. Reduces coupling between the UI and display
|
||||
// plugins
|
||||
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
||||
auto desktop = offscreenUi->getDesktop();
|
||||
auto menu = Menu::getInstance();
|
||||
|
@ -7862,8 +7959,8 @@ void Application::setDisplayPlugin(DisplayPluginPointer newDisplayPlugin) {
|
|||
bool wasRepositionLocked = false;
|
||||
if (desktop) {
|
||||
// Tell the desktop to no reposition (which requires plugin info), until we have set the new plugin, below.
|
||||
wasRepositionLocked = offscreenUi->getDesktop()->property("repositionLocked").toBool();
|
||||
offscreenUi->getDesktop()->setProperty("repositionLocked", true);
|
||||
wasRepositionLocked = desktop->property("repositionLocked").toBool();
|
||||
desktop->setProperty("repositionLocked", true);
|
||||
}
|
||||
|
||||
if (_displayPlugin) {
|
||||
|
@ -8174,17 +8271,17 @@ void Application::openAndroidActivity(const QString& activityName) {
|
|||
void Application::enterBackground() {
|
||||
QMetaObject::invokeMethod(DependencyManager::get<AudioClient>().data(),
|
||||
"stop", Qt::BlockingQueuedConnection);
|
||||
//GC: commenting it out until we fix it
|
||||
//getActiveDisplayPlugin()->deactivate();
|
||||
if (getActiveDisplayPlugin()->isActive()) {
|
||||
getActiveDisplayPlugin()->deactivate();
|
||||
}
|
||||
}
|
||||
|
||||
void Application::enterForeground() {
|
||||
QMetaObject::invokeMethod(DependencyManager::get<AudioClient>().data(),
|
||||
"start", Qt::BlockingQueuedConnection);
|
||||
//GC: commenting it out until we fix it
|
||||
/*if (!getActiveDisplayPlugin() || !getActiveDisplayPlugin()->activate()) {
|
||||
if (!getActiveDisplayPlugin() || getActiveDisplayPlugin()->isActive() || !getActiveDisplayPlugin()->activate()) {
|
||||
qWarning() << "Could not re-activate display plugin";
|
||||
}*/
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -148,6 +148,7 @@ public:
|
|||
Q_INVOKABLE QString getUserAgent();
|
||||
|
||||
void initializeGL();
|
||||
void initializeDisplayPlugins();
|
||||
void initializeRenderEngine();
|
||||
void initializeUi();
|
||||
|
||||
|
@ -418,7 +419,6 @@ public slots:
|
|||
void updateVerboseLogging();
|
||||
Q_INVOKABLE void openAndroidActivity(const QString& activityName);
|
||||
|
||||
|
||||
private slots:
|
||||
void onDesktopRootItemCreated(QQuickItem* qmlContext);
|
||||
void onDesktopRootContextCreated(QQmlContext* qmlContext);
|
||||
|
@ -671,6 +671,7 @@ private:
|
|||
|
||||
using RenderArgsEditor = std::function <void (AppRenderArgs&)>;
|
||||
void editRenderArgs(RenderArgsEditor editor);
|
||||
void updateRenderArgs(float deltaTime);
|
||||
|
||||
|
||||
Overlays _overlays;
|
||||
|
@ -750,5 +751,7 @@ private:
|
|||
|
||||
std::atomic<bool> _pendingIdleEvent { true };
|
||||
std::atomic<bool> _pendingRenderEvent { true };
|
||||
|
||||
bool quitWhenFinished { false };
|
||||
};
|
||||
#endif // hifi_Application_h
|
||||
|
|
|
@ -13,8 +13,9 @@
|
|||
|
||||
#include <display-plugins/CompositorHelper.h>
|
||||
#include <FramebufferCache.h>
|
||||
#include "ui/Stats.h"
|
||||
#include <plugins/PluginManager.h>
|
||||
#include <SceneScriptingInterface.h>
|
||||
#include "ui/Stats.h"
|
||||
#include "Util.h"
|
||||
|
||||
|
||||
|
@ -233,3 +234,4 @@ void Application::runRenderFrame(RenderArgs* renderArgs) {
|
|||
_renderEngine->run();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "AvatarBookmarks.h"
|
||||
|
||||
#include <QAction>
|
||||
#include <QInputDialog>
|
||||
#include <QMessageBox>
|
||||
|
@ -27,7 +29,6 @@
|
|||
|
||||
#include "MainWindow.h"
|
||||
#include "Menu.h"
|
||||
#include "AvatarBookmarks.h"
|
||||
#include "InterfaceLogging.h"
|
||||
|
||||
#include "QVariantGLM.h"
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "Bookmarks.h"
|
||||
|
||||
#include <QAction>
|
||||
#include <QDebug>
|
||||
#include <QInputDialog>
|
||||
|
@ -22,8 +24,6 @@
|
|||
#include "Menu.h"
|
||||
#include "InterfaceLogging.h"
|
||||
|
||||
#include "Bookmarks.h"
|
||||
|
||||
Bookmarks::Bookmarks() :
|
||||
_isMenuSorted(false)
|
||||
{
|
||||
|
|
|
@ -9,7 +9,10 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "DiscoverabilityManager.h"
|
||||
|
||||
#include <QtCore/QJsonDocument>
|
||||
#include <QThread>
|
||||
|
||||
#include <AccountManager.h>
|
||||
#include <AddressManager.h>
|
||||
|
@ -21,11 +24,8 @@
|
|||
#include <UUID.h>
|
||||
|
||||
#include "Crashpad.h"
|
||||
#include "DiscoverabilityManager.h"
|
||||
#include "Menu.h"
|
||||
|
||||
#include <QThread>
|
||||
|
||||
const Discoverability::Mode DEFAULT_DISCOVERABILITY_MODE = Discoverability::Connections;
|
||||
|
||||
DiscoverabilityManager::DiscoverabilityManager() :
|
||||
|
|
|
@ -12,9 +12,13 @@
|
|||
#ifndef hifi_DiscoverabilityManager_h
|
||||
#define hifi_DiscoverabilityManager_h
|
||||
|
||||
#include <QJsonObject>
|
||||
|
||||
#include <DependencyManager.h>
|
||||
#include <SettingHandle.h>
|
||||
|
||||
class QNetworkReply;
|
||||
|
||||
namespace Discoverability {
|
||||
enum Mode {
|
||||
None,
|
||||
|
|
|
@ -9,10 +9,10 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
// FIXME ordering of headers
|
||||
#include "Application.h"
|
||||
#include "GLCanvas.h"
|
||||
|
||||
#include "Application.h"
|
||||
|
||||
bool GLCanvas::event(QEvent* event) {
|
||||
if (QEvent::Paint == event->type() && qApp->isAboutToQuit()) {
|
||||
return true;
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
|
||||
#include "InterfaceDynamicFactory.h"
|
||||
|
||||
#include <avatar/AvatarActionHold.h>
|
||||
#include <avatar/AvatarActionFarGrab.h>
|
||||
|
@ -22,9 +22,6 @@
|
|||
#include <ObjectConstraintConeTwist.h>
|
||||
#include <LogHandler.h>
|
||||
|
||||
#include "InterfaceDynamicFactory.h"
|
||||
|
||||
|
||||
EntityDynamicPointer interfaceDynamicFactory(EntityDynamicType type, const QUuid& id, EntityItemPointer ownerEntity) {
|
||||
switch (type) {
|
||||
case DYNAMIC_TYPE_NONE:
|
||||
|
|
|
@ -9,13 +9,13 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "InterfaceParentFinder.h"
|
||||
|
||||
#include <Application.h>
|
||||
#include <AvatarData.h>
|
||||
#include <avatar/AvatarManager.h>
|
||||
#include <EntityTree.h>
|
||||
#include <EntityTreeRenderer.h>
|
||||
#include <avatar/AvatarManager.h>
|
||||
#include <AvatarData.h>
|
||||
|
||||
#include "InterfaceParentFinder.h"
|
||||
|
||||
SpatiallyNestableWeakPointer InterfaceParentFinder::find(QUuid parentID, bool& success, SpatialParentTree* entityTree) const {
|
||||
SpatiallyNestableWeakPointer parent;
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "LODManager.h"
|
||||
|
||||
#include <SettingHandle.h>
|
||||
#include <OctreeUtils.h>
|
||||
#include <Util.h>
|
||||
|
@ -17,8 +19,6 @@
|
|||
#include "ui/DialogsManager.h"
|
||||
#include "InterfaceLogging.h"
|
||||
|
||||
#include "LODManager.h"
|
||||
|
||||
|
||||
Setting::Handle<float> desktopLODDecreaseFPS("desktopLODDecreaseFPS", DEFAULT_DESKTOP_LOD_DOWN_FPS);
|
||||
Setting::Handle<float> hmdLODDecreaseFPS("hmdLODDecreaseFPS", DEFAULT_HMD_LOD_DOWN_FPS);
|
||||
|
@ -70,7 +70,7 @@ void LODManager::autoAdjustLOD(float realTimeDelta) {
|
|||
// Note: we MUST clamp the blend to 1.0 for stability
|
||||
float blend = (realTimeDelta < LOD_ADJUST_RUNNING_AVG_TIMESCALE) ? realTimeDelta / LOD_ADJUST_RUNNING_AVG_TIMESCALE : 1.0f;
|
||||
_avgRenderTime = (1.0f - blend) * _avgRenderTime + blend * maxRenderTime; // msec
|
||||
if (!_automaticLODAdjust) {
|
||||
if (!_automaticLODAdjust || _avgRenderTime == 0.0f) {
|
||||
// early exit
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -9,21 +9,16 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "LocationBookmarks.h"
|
||||
|
||||
#include <QAction>
|
||||
#include <QInputDialog>
|
||||
#include <QMessageBox>
|
||||
#include <QStandardPaths>
|
||||
|
||||
#include <AddressManager.h>
|
||||
#include <Application.h>
|
||||
#include <OffscreenUi.h>
|
||||
|
||||
#include "MainWindow.h"
|
||||
#include "Menu.h"
|
||||
|
||||
#include "LocationBookmarks.h"
|
||||
#include <QtQuick/QQuickWindow>
|
||||
|
||||
const QString LocationBookmarks::HOME_BOOKMARK = "Home";
|
||||
|
||||
LocationBookmarks::LocationBookmarks() {
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#define hifi_LocationBookmarks_h
|
||||
|
||||
#include <DependencyManager.h>
|
||||
|
||||
#include "Bookmarks.h"
|
||||
|
||||
class LocationBookmarks : public Bookmarks, public Dependency {
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "Menu.h"
|
||||
|
||||
#include <QFileDialog>
|
||||
#include <QMenuBar>
|
||||
#include <QShortcut>
|
||||
|
@ -52,8 +54,6 @@
|
|||
#include "SpeechRecognizer.h"
|
||||
#endif
|
||||
|
||||
#include "Menu.h"
|
||||
|
||||
extern bool DEV_DECIMATE_TEXTURES;
|
||||
|
||||
Menu* Menu::getInstance() {
|
||||
|
|
|
@ -193,7 +193,6 @@ namespace MenuOption {
|
|||
const QString ShowOtherLookAtVectors = "Show Other Eye Vectors";
|
||||
const QString EnableLookAtSnapping = "Enable LookAt Snapping";
|
||||
const QString ShowRealtimeEntityStats = "Show Realtime Entity Stats";
|
||||
const QString StandingHMDSensorMode = "Standing HMD Sensor Mode";
|
||||
const QString SimulateEyeTracking = "Simulate";
|
||||
const QString SMIEyeTracking = "SMI Eye Tracking";
|
||||
const QString SparseTextureManagement = "Enable Sparse Texture Management";
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "ModelPackager.h"
|
||||
|
||||
#include <QFile>
|
||||
#include <QFileDialog>
|
||||
#include <QMessageBox>
|
||||
|
@ -21,8 +23,6 @@
|
|||
#include "ModelPropertiesDialog.h"
|
||||
#include "InterfaceLogging.h"
|
||||
|
||||
#include "ModelPackager.h"
|
||||
|
||||
static const int MAX_TEXTURE_SIZE = 1024;
|
||||
|
||||
void copyDirectoryContent(QDir& from, QDir& to) {
|
||||
|
|
|
@ -12,11 +12,15 @@
|
|||
#ifndef hifi_ModelPackager_h
|
||||
#define hifi_ModelPackager_h
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <QFileInfo>
|
||||
#include <QVariantHash>
|
||||
|
||||
#include "ui/ModelsBrowser.h"
|
||||
|
||||
class FBXGeometry;
|
||||
|
||||
class ModelPackager : public QObject {
|
||||
public:
|
||||
static bool package();
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "ModelPropertiesDialog.h"
|
||||
|
||||
#include <QCheckBox>
|
||||
#include <QComboBox>
|
||||
#include <QDialogButtonBox>
|
||||
|
@ -23,8 +25,6 @@
|
|||
#include <GLMHelpers.h>
|
||||
#include <OffscreenUi.h>
|
||||
|
||||
#include "ModelPropertiesDialog.h"
|
||||
|
||||
|
||||
ModelPropertiesDialog::ModelPropertiesDialog(FSTReader::ModelType modelType, const QVariantHash& originalMapping,
|
||||
const QString& basePath, const FBXGeometry& geometry) :
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "ModelSelector.h"
|
||||
|
||||
#include <QDialogButtonBox>
|
||||
#include <QComboBox>
|
||||
#include <QFileDialog>
|
||||
|
@ -16,8 +18,6 @@
|
|||
#include <QPushButton>
|
||||
#include <QStandardPaths>
|
||||
|
||||
#include "ModelSelector.h"
|
||||
|
||||
static const QString AVATAR_HEAD_AND_BODY_STRING = "Avatar Body with Head";
|
||||
static const QString AVATAR_ATTACHEMENT_STRING = "Avatar Attachment";
|
||||
static const QString ENTITY_MODEL_STRING = "Entity Model";
|
||||
|
@ -82,4 +82,4 @@ void ModelSelector::browse() {
|
|||
_browseButton->setText(fileInfo.fileName());
|
||||
lastModelBrowseLocation.set(fileInfo.path());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,13 +9,16 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "Application.h"
|
||||
#include "SecondaryCamera.h"
|
||||
#include <TextureCache.h>
|
||||
#include <gpu/Context.h>
|
||||
#include <EntityScriptingInterface.h>
|
||||
|
||||
#include <glm/gtx/transform.hpp>
|
||||
|
||||
#include <EntityScriptingInterface.h>
|
||||
#include <gpu/Context.h>
|
||||
#include <TextureCache.h>
|
||||
|
||||
#include "Application.h"
|
||||
|
||||
using RenderArgsPointer = std::shared_ptr<RenderArgs>;
|
||||
|
||||
void MainRenderTask::build(JobModel& task, const render::Varying& inputs, render::Varying& outputs, render::CullFunctor cullFunctor, bool isDeferred) {
|
||||
|
@ -213,4 +216,4 @@ void SecondaryCameraRenderTask::build(JobModel& task, const render::Varying& inp
|
|||
task.addJob<RenderDeferredTask>("RenderDeferredTask", items);
|
||||
}
|
||||
task.addJob<EndSecondaryCameraFrame>("EndSecondaryCamera", cachedArg);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
#include <render/RenderFetchCullSortTask.h>
|
||||
#include <RenderDeferredTask.h>
|
||||
#include <RenderForwardTask.h>
|
||||
#include <TextureCache.h>
|
||||
#include <ViewFrustum.h>
|
||||
|
||||
class MainRenderTask {
|
||||
public:
|
||||
|
|
|
@ -9,11 +9,12 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "SpeechRecognizer.h"
|
||||
|
||||
#include <QtGlobal>
|
||||
#include <QDebug>
|
||||
|
||||
#include "InterfaceLogging.h"
|
||||
#include "SpeechRecognizer.h"
|
||||
|
||||
#if defined(Q_OS_WIN)
|
||||
|
||||
|
|
|
@ -16,10 +16,10 @@
|
|||
#import <AppKit/NSSpeechRecognizer.h>
|
||||
#import <AppKit/NSWorkspace.h>
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
#include "SpeechRecognizer.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
@interface SpeechRecognizerDelegate : NSObject <NSSpeechRecognizerDelegate> {
|
||||
SpeechRecognizer* _listener;
|
||||
}
|
||||
|
|
|
@ -9,11 +9,11 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "UIUtil.h"
|
||||
|
||||
#include <QStyle>
|
||||
#include <QStyleOptionTitleBar>
|
||||
|
||||
#include "UIUtil.h"
|
||||
|
||||
int UIUtil::getWindowTitleBarHeight(const QWidget* window) {
|
||||
QStyleOptionTitleBar options;
|
||||
options.titleBarState = 1;
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "AudioScope.h"
|
||||
|
||||
#include <qvector2d.h>
|
||||
#include <limits>
|
||||
|
||||
|
@ -19,8 +21,6 @@
|
|||
#include <gpu/Context.h>
|
||||
#include <GLMHelpers.h>
|
||||
|
||||
#include "AudioScope.h"
|
||||
|
||||
static const unsigned int DEFAULT_FRAMES_PER_SCOPE = 5;
|
||||
static const unsigned int MULTIPLIER_SCOPE_HEIGHT = 20;
|
||||
static const unsigned int SCOPE_HEIGHT = 2 * 15 * MULTIPLIER_SCOPE_HEIGHT;
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "AvatarManager.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <QScriptEngine>
|
||||
|
@ -38,7 +40,6 @@
|
|||
#include <shared/ConicalViewFrustum.h>
|
||||
|
||||
#include "Application.h"
|
||||
#include "AvatarManager.h"
|
||||
#include "InterfaceLogging.h"
|
||||
#include "Menu.h"
|
||||
#include "MyAvatar.h"
|
||||
|
|
|
@ -21,6 +21,17 @@ AvatarMotionState::AvatarMotionState(AvatarSharedPointer avatar, const btCollisi
|
|||
_type = MOTIONSTATE_TYPE_AVATAR;
|
||||
}
|
||||
|
||||
void AvatarMotionState::handleEasyChanges(uint32_t& flags) {
|
||||
ObjectMotionState::handleEasyChanges(flags);
|
||||
if (flags & Simulation::DIRTY_PHYSICS_ACTIVATION && !_body->isActive()) {
|
||||
_body->activate();
|
||||
}
|
||||
}
|
||||
|
||||
bool AvatarMotionState::handleHardAndEasyChanges(uint32_t& flags, PhysicsEngine* engine) {
|
||||
return ObjectMotionState::handleHardAndEasyChanges(flags, engine);
|
||||
}
|
||||
|
||||
AvatarMotionState::~AvatarMotionState() {
|
||||
assert(_avatar);
|
||||
_avatar = nullptr;
|
||||
|
@ -46,6 +57,9 @@ PhysicsMotionType AvatarMotionState::computePhysicsMotionType() const {
|
|||
const btCollisionShape* AvatarMotionState::computeNewShape() {
|
||||
ShapeInfo shapeInfo;
|
||||
std::static_pointer_cast<Avatar>(_avatar)->computeShapeInfo(shapeInfo);
|
||||
glm::vec3 halfExtents = shapeInfo.getHalfExtents();
|
||||
halfExtents.y = 0.0f;
|
||||
_diameter = 2.0f * glm::length(halfExtents);
|
||||
return getShapeManager()->getShape(shapeInfo);
|
||||
}
|
||||
|
||||
|
@ -60,25 +74,31 @@ void AvatarMotionState::getWorldTransform(btTransform& worldTrans) const {
|
|||
worldTrans.setRotation(glmToBullet(getObjectRotation()));
|
||||
if (_body) {
|
||||
_body->setLinearVelocity(glmToBullet(getObjectLinearVelocity()));
|
||||
_body->setAngularVelocity(glmToBullet(getObjectLinearVelocity()));
|
||||
_body->setAngularVelocity(glmToBullet(getObjectAngularVelocity()));
|
||||
}
|
||||
}
|
||||
|
||||
// virtual
|
||||
void AvatarMotionState::setWorldTransform(const btTransform& worldTrans) {
|
||||
// HACK: The PhysicsEngine does not actually move OTHER avatars -- instead it slaves their local RigidBody to the transform
|
||||
// as specified by a remote simulation. However, to give the remote simulation time to respond to our own objects we tie
|
||||
// the other avatar's body to its true position with a simple spring. This is a HACK that will have to be improved later.
|
||||
const float SPRING_TIMESCALE = 0.5f;
|
||||
float tau = PHYSICS_ENGINE_FIXED_SUBSTEP / SPRING_TIMESCALE;
|
||||
btVector3 currentPosition = worldTrans.getOrigin();
|
||||
btVector3 targetPosition = glmToBullet(getObjectPosition());
|
||||
btTransform newTransform;
|
||||
newTransform.setOrigin((1.0f - tau) * currentPosition + tau * targetPosition);
|
||||
newTransform.setRotation(glmToBullet(getObjectRotation()));
|
||||
_body->setWorldTransform(newTransform);
|
||||
_body->setLinearVelocity(glmToBullet(getObjectLinearVelocity()));
|
||||
_body->setAngularVelocity(glmToBullet(getObjectLinearVelocity()));
|
||||
btVector3 offsetToTarget = glmToBullet(getObjectPosition()) - currentPosition;
|
||||
float distance = offsetToTarget.length();
|
||||
if ((1.0f - tau) * distance > _diameter) {
|
||||
// the avatar body is far from its target --> slam position
|
||||
btTransform newTransform;
|
||||
newTransform.setOrigin(currentPosition + offsetToTarget);
|
||||
newTransform.setRotation(glmToBullet(getObjectRotation()));
|
||||
_body->setWorldTransform(newTransform);
|
||||
_body->setLinearVelocity(glmToBullet(getObjectLinearVelocity()));
|
||||
_body->setAngularVelocity(glmToBullet(getObjectAngularVelocity()));
|
||||
} else {
|
||||
// the avatar body is near its target --> slam velocity
|
||||
btVector3 velocity = glmToBullet(getObjectLinearVelocity()) + (1.0f / SPRING_TIMESCALE) * offsetToTarget;
|
||||
_body->setLinearVelocity(velocity);
|
||||
_body->setAngularVelocity(glmToBullet(getObjectAngularVelocity()));
|
||||
}
|
||||
}
|
||||
|
||||
// These pure virtual methods must be implemented for each MotionState type
|
||||
|
@ -145,3 +165,8 @@ void AvatarMotionState::computeCollisionGroupAndMask(int16_t& group, int16_t& ma
|
|||
mask = Physics::getDefaultCollisionMask(group);
|
||||
}
|
||||
|
||||
// virtual
|
||||
float AvatarMotionState::getMass() const {
|
||||
return std::static_pointer_cast<Avatar>(_avatar)->computeMass();
|
||||
}
|
||||
|
||||
|
|
|
@ -23,6 +23,9 @@ class AvatarMotionState : public ObjectMotionState {
|
|||
public:
|
||||
AvatarMotionState(AvatarSharedPointer avatar, const btCollisionShape* shape);
|
||||
|
||||
virtual void handleEasyChanges(uint32_t& flags) override;
|
||||
virtual bool handleHardAndEasyChanges(uint32_t& flags, PhysicsEngine* engine) override;
|
||||
|
||||
virtual PhysicsMotionType getMotionType() const override { return _motionType; }
|
||||
|
||||
virtual uint32_t getIncomingDirtyFlags() override;
|
||||
|
@ -64,6 +67,8 @@ public:
|
|||
|
||||
virtual void computeCollisionGroupAndMask(int16_t& group, int16_t& mask) const override;
|
||||
|
||||
virtual float getMass() const override;
|
||||
|
||||
friend class AvatarManager;
|
||||
friend class Avatar;
|
||||
|
||||
|
@ -76,6 +81,7 @@ protected:
|
|||
virtual const btCollisionShape* computeNewShape() override;
|
||||
|
||||
AvatarSharedPointer _avatar;
|
||||
float _diameter { 0.0f };
|
||||
|
||||
uint32_t _dirtyFlags;
|
||||
};
|
||||
|
|
|
@ -2039,7 +2039,7 @@ void MyAvatar::postUpdate(float deltaTime, const render::ScenePointer& scene) {
|
|||
}
|
||||
}
|
||||
|
||||
void MyAvatar::preDisplaySide(RenderArgs* renderArgs) {
|
||||
void MyAvatar::preDisplaySide(const RenderArgs* renderArgs) {
|
||||
|
||||
// toggle using the cauterizedBones depending on where the camera is and the rendering pass type.
|
||||
const bool shouldDrawHead = shouldRenderHead(renderArgs);
|
||||
|
|
|
@ -272,7 +272,7 @@ public:
|
|||
|
||||
void update(float deltaTime);
|
||||
virtual void postUpdate(float deltaTime, const render::ScenePointer& scene) override;
|
||||
void preDisplaySide(RenderArgs* renderArgs);
|
||||
void preDisplaySide(const RenderArgs* renderArgs);
|
||||
|
||||
const glm::mat4& getHMDSensorMatrix() const { return _hmdSensorMatrix; }
|
||||
const glm::vec3& getHMDSensorPosition() const { return _hmdSensorPosition; }
|
||||
|
|
|
@ -9,16 +9,19 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "Ledger.h"
|
||||
|
||||
#include <QJsonObject>
|
||||
#include <QJsonArray>
|
||||
#include <QTimeZone>
|
||||
#include <QJsonDocument>
|
||||
#include "Wallet.h"
|
||||
#include "Ledger.h"
|
||||
#include "CommerceLogging.h"
|
||||
|
||||
#include <NetworkingConstants.h>
|
||||
#include <AddressManager.h>
|
||||
|
||||
#include "Wallet.h"
|
||||
#include "CommerceLogging.h"
|
||||
|
||||
// inventory answers {status: 'success', data: {assets: [{id: "guid", title: "name", preview: "url"}....]}}
|
||||
// balance answers {status: 'success', data: {balance: integer}}
|
||||
// buy and receive_at answer {status: 'success'}
|
||||
|
|
|
@ -9,22 +9,7 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "CommerceLogging.h"
|
||||
#include "Ledger.h"
|
||||
#include "Wallet.h"
|
||||
#include "Application.h"
|
||||
#include "ui/SecurityImageProvider.h"
|
||||
#include "scripting/HMDScriptingInterface.h"
|
||||
#include <ui/TabletScriptingInterface.h>
|
||||
|
||||
#include <PathUtils.h>
|
||||
#include <OffscreenUi.h>
|
||||
#include <AccountManager.h>
|
||||
|
||||
#include <QFile>
|
||||
#include <QCryptographicHash>
|
||||
#include <QQmlContext>
|
||||
#include <QBuffer>
|
||||
|
||||
#include <openssl/ssl.h>
|
||||
#include <openssl/err.h>
|
||||
|
@ -33,7 +18,6 @@
|
|||
#include <openssl/evp.h>
|
||||
#include <openssl/aes.h>
|
||||
#include <openssl/ecdsa.h>
|
||||
|
||||
// I know, right? But per https://www.openssl.org/docs/faq.html
|
||||
// this avoids OPENSSL_Uplink(00007FF847238000,08): no OPENSSL_Applink
|
||||
// at runtime.
|
||||
|
@ -41,6 +25,22 @@
|
|||
#include <openssl/applink.c>
|
||||
#endif
|
||||
|
||||
#include <QFile>
|
||||
#include <QCryptographicHash>
|
||||
#include <QQmlContext>
|
||||
#include <QBuffer>
|
||||
|
||||
#include <PathUtils.h>
|
||||
#include <OffscreenUi.h>
|
||||
#include <AccountManager.h>
|
||||
#include <ui/TabletScriptingInterface.h>
|
||||
|
||||
#include "Application.h"
|
||||
#include "CommerceLogging.h"
|
||||
#include "Ledger.h"
|
||||
#include "ui/SecurityImageProvider.h"
|
||||
#include "scripting/HMDScriptingInterface.h"
|
||||
|
||||
static const char* KEY_FILE = "hifikey";
|
||||
static const char* INSTRUCTIONS_FILE = "backup_instructions.html";
|
||||
static const char* IMAGE_HEADER = "-----BEGIN SECURITY IMAGE-----\n";
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue