Merge remote-tracking branch 'hifi/master' into android_friends_main

This commit is contained in:
Cristian Luis Duarte 2018-07-30 19:01:41 -03:00
commit a572af1df2
717 changed files with 36528 additions and 13600 deletions

View file

@ -39,7 +39,7 @@ Go to `Control Panel > System > Advanced System Settings > Environment Variables
### Step 6. Installing OpenSSL via vcpkg
* In the vcpkg directory, install the 64 bit OpenSSL package with the command `vcpkg install openssl:x64-windows`
* In the vcpkg directory, install the 64 bit OpenSSL package with the command `.\vcpkg install openssl:x64-windows`
* Once the build completes you should have a file `ssl.h` in `${VCPKG_ROOT}/installed/x64-windows/include/openssl`
### Step 7. Running CMake to Generate Build Files

View file

@ -21,6 +21,7 @@ To produce an executable installer on Windows, the following are required:
- [NSISpcre Plug-in for Nullsoft](http://nsis.sourceforge.net/NSISpcre_plug-in) - 1.0
- [nsisSlideshow Plug-in for Nullsoft](http://nsis.sourceforge.net/NsisSlideshow_plug-in) - 1.7
- [Nsisunz plug-in for Nullsoft](http://nsis.sourceforge.net/Nsisunz_plug-in)
- [ApplicationID plug-in for Nullsoft](http://nsis.sourceforge.net/ApplicationID_plug-in) - 1.0
Run the `package` target to create an executable installer using the Nullsoft Scriptable Install System.

View file

@ -1,8 +1,8 @@
High Fidelity (hifi) is an early-stage technology lab experimenting with Virtual Worlds and VR.
In this repository you'll find the source to many of the components in our
alpha-stage virtual world. The project embraces distributed development
and if you'd like to help, we'll pay you -- find out more at [Worklist.net](https://worklist.net).
This repository contains the source to many of the components in our
alpha-stage virtual world. The project embraces distributed development.
If you'd like to help, we'll pay you -- find out more at [Worklist.net](https://worklist.net).
If you find a small bug and have a fix, pull requests are welcome. If you'd
like to get paid for your work, make sure you report the bug via a job on
[Worklist.net](https://worklist.net).
@ -32,9 +32,10 @@ Running Interface
When you launch interface, you will automatically connect to our default domain: "root.highfidelity.io".
If you don't see anything, make sure your preferences are pointing to
root.highfidelity.io (set your domain via Cmnd+D/Cntrl+D), if you still have no luck it's possible our servers are
simply down; if you're experiencing a major bug, let us know by adding an issue to this repository.
Make sure to include details about your computer and how to reproduce the bug.
root.highfidelity.io (set your domain via Cmnd+D/Cntrl+D). If you still have no luck,
it's possible our servers are down. If you're experiencing a major bug, let us know by
adding an issue to this repository. Include details about your computer and how to
reproduce the bug in your issue.
To move around in-world, use the arrow keys (and Shift + up/down to fly up or
down) or W A S D, and E or C to fly up/down. All of the other possible options
@ -48,7 +49,8 @@ you to run the full stack of the virtual world.
In order to set up your own virtual world, you need to set up and run your own
local "domain".
The domain-server gives a number different types of assignments to the assignment-client for different features: audio, avatars, voxels, particles, meta-voxels and models.
The domain-server gives a number different types of assignments to the assignment-client
for different features: audio, avatars, voxels, particles, meta-voxels and models.
Follow the instructions in the [build guide](BUILD.md) to build the various components.
@ -56,7 +58,8 @@ From the domain-server build directory, launch a domain-server.
./domain-server
Then, run an assignment-client. The assignment-client uses localhost as its assignment-server and talks to it on port 40102 (the default domain-server port).
Then, run an assignment-client. The assignment-client uses localhost as its assignment-server
and talks to it on port 40102 (the default domain-server port).
In a new Terminal window, run:
@ -64,13 +67,20 @@ In a new Terminal window, run:
Any target can be terminated with Ctrl-C (SIGINT) in the associated Terminal window.
This assignment-client will grab one assignment from the domain-server. You can tell the assignment-client what type you want it to be with the `-t` option. You can also run an assignment-client that forks off *n* assignment-clients with the `-n` option. The `-min` and `-max` options allow you to set a range of required assignment-clients, this allows you to have flexibility in the number of assignment-clients that are running. See `--help` for more options.
This assignment-client will grab one assignment from the domain-server. You can tell the
assignment-client what type you want it to be with the `-t` option. You can also run an
assignment-client that forks off *n* assignment-clients with the `-n` option. The `-min`
and `-max` options allow you to set a range of required assignment-clients. This allows
you to have flexibility in the number of assignment-clients that are running.
See `--help` for more options.
./assignment-client --min 6 --max 20
To test things out you'll want to run the Interface client.
To test things out, you'll need to run the Interface client.
To access your local domain in Interface, open your Preferences -- on OS X this is available in the Interface menu, on Linux you'll find it in the File menu. Enter "localhost" in the "Domain server" field.
To access your local domain in Interface, open your Preferences. On OS X, this is available
in the Interface menu. On Linux, you'll find it in the File menu. Enter "localhost" in the
"Domain server" field.
If everything worked you should see that you are connected to at least one server.
If everything worked, you should see that you are connected to at least one server.
Nice work!

View file

@ -1,15 +1,20 @@
import org.apache.tools.ant.taskdefs.condition.Os
apply plugin: 'com.android.application'
android {
compileSdkVersion 26
//buildToolsVersion '27.0.3'
def appVersionCode = Integer.valueOf(VERSION_CODE ?: 1)
def appVersionName = RELEASE_NUMBER ?: "1.0"
defaultConfig {
applicationId "io.highfidelity.hifiinterface"
minSdkVersion 24
targetSdkVersion 26
versionCode 1
versionName "1.0"
versionCode appVersionCode
versionName appVersionName
ndk { abiFilters 'arm64-v8a' }
externalNativeBuild {
cmake {
@ -24,7 +29,8 @@ android {
'-DRELEASE_TYPE=' + RELEASE_TYPE,
'-DSTABLE_BUILD=' + STABLE_BUILD,
'-DDISABLE_QML=OFF',
'-DDISABLE_KTX_CACHE=OFF'
'-DDISABLE_KTX_CACHE=OFF',
'-DUSE_BREAKPAD=' + (System.getenv("CMAKE_BACKTRACE_URL") && System.getenv("CMAKE_BACKTRACE_TOKEN") ? 'ON' : 'OFF');
}
}
signingConfigs {
@ -43,6 +49,10 @@ android {
}
buildTypes {
debug {
buildConfigField "String", "BACKTRACE_URL", "\"" + (System.getenv("CMAKE_BACKTRACE_URL") ? System.getenv("CMAKE_BACKTRACE_URL") : '') + "\""
buildConfigField "String", "BACKTRACE_TOKEN", "\"" + (System.getenv("CMAKE_BACKTRACE_TOKEN") ? System.getenv("CMAKE_BACKTRACE_TOKEN") : '') + "\""
}
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
@ -50,6 +60,8 @@ android {
project.hasProperty("HIFI_ANDROID_KEYSTORE_PASSWORD") &&
project.hasProperty("HIFI_ANDROID_KEY_ALIAS") &&
project.hasProperty("HIFI_ANDROID_KEY_PASSWORD")? signingConfigs.release : null
buildConfigField "String", "BACKTRACE_URL", "\"" + (System.getenv("CMAKE_BACKTRACE_URL") ? System.getenv("CMAKE_BACKTRACE_URL") : '') + "\""
buildConfigField "String", "BACKTRACE_TOKEN", "\"" + (System.getenv("CMAKE_BACKTRACE_TOKEN") ? System.getenv("CMAKE_BACKTRACE_TOKEN") : '') + "\""
}
}
@ -64,6 +76,12 @@ android {
// so our merge has to depend on the external native build
variant.externalNativeBuildTasks.each { task ->
variant.mergeResources.dependsOn(task)
if (Os.isFamily(Os.FAMILY_UNIX)) {
def uploadDumpSymsTask = rootProject.getTasksByName("uploadBreakpadDumpSyms${variant.name.capitalize()}", false).first()
def runDumpSymsTask = rootProject.getTasksByName("runBreakpadDumpSyms${variant.name.capitalize()}", false).first()
runDumpSymsTask.dependsOn(task)
variant.assemble.dependsOn(uploadDumpSymsTask)
}
}
variant.mergeAssets.doLast {

View file

@ -22,13 +22,15 @@
android:icon="@drawable/ic_launcher"
android:launchMode="singleTop"
android:roundIcon="@drawable/ic_launcher">
<activity android:name="io.highfidelity.hifiinterface.PermissionChecker">
<activity android:name="io.highfidelity.hifiinterface.PermissionChecker"
android:theme="@style/Theme.AppCompat.Translucent.NoActionBar.Launcher">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name="io.highfidelity.hifiinterface.WebViewActivity"
android:configChanges="orientation|screenSize"
android:theme="@android:style/Theme.Material.Light.NoActionBar"/>
<!-- We don't want to show this on Daydream yet (we need to fix the turn-around problem on this screen)
<activity android:name="io.highfidelity.hifiinterface.GvrLoaderActivity">
@ -67,6 +69,12 @@
android:name=".SplashActivity"
android:screenOrientation="portrait"
android:theme="@style/Theme.AppCompat.Translucent.NoActionBar" />
<service
android:name=".BreakpadUploaderService"
android:enabled="true"
android:exported="false"
android:process=":breakpad_uploader"/>
</application>
<uses-feature android:name="android.software.vr.mode" android:required="true"/>

View file

@ -153,10 +153,43 @@ JNIEXPORT void Java_io_highfidelity_hifiinterface_InterfaceActivity_nativeOnCrea
unpackAndroidAssets();
qInstallMessageHandler(oldMessageHandler);
QObject::connect(&AndroidHelper::instance(), &AndroidHelper::androidActivityRequested, [](const QString& a, const bool backToScene) {
JavaVM* jvm;
env->GetJavaVM(&jvm);
QObject::connect(&AndroidHelper::instance(), &AndroidHelper::androidActivityRequested, [jvm](const QString& a, const bool backToScene, QList<QString> args) {
JNIEnv* myNewEnv;
JavaVMAttachArgs jvmArgs;
jvmArgs.version = JNI_VERSION_1_6; // choose your JNI version
jvmArgs.name = NULL; // you might want to give the java thread a name
jvmArgs.group = NULL; // you might want to assign the java thread to a ThreadGroup
int attachedHere = 0; // know if detaching at the end is necessary
jint res = jvm->GetEnv((void**)&myNewEnv, JNI_VERSION_1_6); // checks if current env needs attaching or it is already attached
if (JNI_OK != res) {
qDebug() << "[JCRASH] GetEnv env not attached yet, attaching now..";
res = jvm->AttachCurrentThread(reinterpret_cast<JNIEnv **>(&myNewEnv), &jvmArgs);
if (JNI_OK != res) {
qDebug() << "[JCRASH] Failed to AttachCurrentThread, ErrorCode = " << res;
return;
} else {
attachedHere = 1;
}
}
QAndroidJniObject string = QAndroidJniObject::fromString(a);
jboolean jBackToScene = (jboolean) backToScene;
__interfaceActivity.callMethod<void>("openAndroidActivity", "(Ljava/lang/String;Z)V", string.object<jstring>(), jBackToScene);
jclass hashMapClass = myNewEnv->FindClass("java/util/HashMap");
jmethodID mapClassConstructor = myNewEnv->GetMethodID(hashMapClass, "<init>", "()V");
jobject hashmap = myNewEnv->NewObject(hashMapClass, mapClassConstructor);
jmethodID mapClassPut = myNewEnv->GetMethodID(hashMapClass, "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
for (const QString& arg: args) {
QAndroidJniObject jArg = QAndroidJniObject::fromString(arg);
myNewEnv->CallObjectMethod(hashmap, mapClassPut, QAndroidJniObject::fromString("url").object<jstring>(), jArg.object<jstring>());
}
__interfaceActivity.callMethod<void>("openAndroidActivity", "(Ljava/lang/String;ZLjava/util/HashMap;)V", string.object<jstring>(), jBackToScene, hashmap);
if (attachedHere) {
jvm->DetachCurrentThread();
}
});
QObject::connect(&AndroidHelper::instance(), &AndroidHelper::hapticFeedbackRequested, [](int duration) {
@ -228,7 +261,7 @@ Java_io_highfidelity_hifiinterface_fragment_LoginFragment_nativeLogin(JNIEnv *en
env->ReleaseStringUTFChars(username_, c_username);
env->ReleaseStringUTFChars(password_, c_password);
auto accountManager = AndroidHelper::instance().getAccountManager();
auto accountManager = DependencyManager::get<AccountManager>();
__loginCompletedListener = QAndroidJniObject(instance);
__usernameChangedListener = QAndroidJniObject(usernameChangedListener);
@ -281,21 +314,26 @@ Java_io_highfidelity_hifiinterface_SplashActivity_registerLoadCompleteListener(J
}
JNIEXPORT jboolean JNICALL
Java_io_highfidelity_hifiinterface_MainActivity_nativeIsLoggedIn(JNIEnv *env, jobject instance) {
return AndroidHelper::instance().getAccountManager()->isLoggedIn();
return DependencyManager::get<AccountManager>()->isLoggedIn();
}
JNIEXPORT void JNICALL
Java_io_highfidelity_hifiinterface_MainActivity_nativeLogout(JNIEnv *env, jobject instance) {
AndroidHelper::instance().getAccountManager()->logout();
DependencyManager::get<AccountManager>()->logout();
}
JNIEXPORT jstring JNICALL
Java_io_highfidelity_hifiinterface_MainActivity_nativeGetDisplayName(JNIEnv *env,
jobject instance) {
QString username = AndroidHelper::instance().getAccountManager()->getAccountInfo().getUsername();
QString username = DependencyManager::get<AccountManager>()->getAccountInfo().getUsername();
return env->NewStringUTF(username.toLatin1().data());
}
JNIEXPORT void JNICALL
Java_io_highfidelity_hifiinterface_InterfaceActivity_nativeBeforeEnterBackground(JNIEnv *env, jobject obj) {
AndroidHelper::instance().notifyBeforeEnterBackground();
}
JNIEXPORT void JNICALL
Java_io_highfidelity_hifiinterface_InterfaceActivity_nativeEnterBackground(JNIEnv *env, jobject obj) {
AndroidHelper::instance().notifyEnterBackground();
@ -306,4 +344,10 @@ Java_io_highfidelity_hifiinterface_InterfaceActivity_nativeEnterForeground(JNIEn
AndroidHelper::instance().notifyEnterForeground();
}
JNIEXPORT void Java_io_highfidelity_hifiinterface_WebViewActivity_nativeProcessURL(JNIEnv* env, jobject obj, jstring url_str) {
const char *nativeString = env->GetStringUTFChars(url_str, 0);
AndroidHelper::instance().processURL(QString::fromUtf8(nativeString));
}
}

View file

@ -0,0 +1,173 @@
package io.highfidelity.hifiinterface;
import android.app.Service;
import android.content.Intent;
import android.os.FileObserver;
import android.os.IBinder;
import android.support.annotation.Nullable;
import android.util.Log;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.Timer;
import java.util.TimerTask;
import javax.net.ssl.HttpsURLConnection;
public class BreakpadUploaderService extends Service {
private static final String ANNOTATIONS_JSON = "annotations.json";
private static final String TAG = "Interface";
public static final String EXT_DMP = "dmp";
private static final long DUMP_DELAY = 5000;
private FileObserver fileObserver;
public BreakpadUploaderService() {
super();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
URL baseUrl;
baseUrl = getUrl();
if (baseUrl == null) {
stopSelf();
return START_NOT_STICKY;
}
new Thread(() -> {
File[] matchingFiles = getFilesByExtension(getObbDir(), EXT_DMP);
for (File file : matchingFiles) {
uploadDumpAndDelete(file, baseUrl);
}
}).start();
fileObserver = new FileObserver(getObbDir().getPath()) {
@Override
public void onEvent(int event, String path) {
if (path == null) {
return;
}
if (FileObserver.CREATE == event && EXT_DMP.equals(getExtension(path))) {
URL baseUrl = getUrl();
if (baseUrl != null) {
new Timer().schedule(new TimerTask() {
@Override
public void run() {
uploadDumpAndDelete(new File(getObbDir(), path), baseUrl);
}
}, DUMP_DELAY);
}
}
}
};
fileObserver.startWatching();
return START_STICKY;
}
private URL getUrl() {
String parameters = getAnnotationsAsUrlEncodedParameters();
try {
return new URL(BuildConfig.BACKTRACE_URL+ "/post?format=minidump&token=" + BuildConfig.BACKTRACE_TOKEN + (parameters.isEmpty() ? "" : ("&" + parameters)));
} catch (MalformedURLException e) {
Log.e(TAG, "Could not initialize Breakpad URL", e);
}
return null;
}
private void uploadDumpAndDelete(File file, URL url) {
int size = (int) file.length();
byte[] bytes = new byte[size];
try {
BufferedInputStream buf = new BufferedInputStream(new FileInputStream(file));
buf.read(bytes, 0, bytes.length);
buf.close();
HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection();
urlConnection.setRequestMethod("POST");
urlConnection.setDoOutput(true);
urlConnection.setChunkedStreamingMode(0);
OutputStream ostream = urlConnection.getOutputStream();
OutputStream out = new BufferedOutputStream(ostream);
out.write(bytes, 0, size);
InputStream in = new BufferedInputStream(urlConnection.getInputStream());
in.read();
if (urlConnection.getResponseCode() == 200) {
file.delete();
}
urlConnection.disconnect();
} catch (IOException e) {
Log.e(TAG, "Error uploading file " + file.getAbsolutePath(), e);
}
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
private File[] getFilesByExtension(File dir, final String extension) {
return dir.listFiles(pathName -> getExtension(pathName.getName()).equals(extension));
}
private String getExtension(String fileName) {
String extension = "";
int i = fileName.lastIndexOf('.');
int p = Math.max(fileName.lastIndexOf('/'), fileName.lastIndexOf('\\'));
if (i > p) {
extension = fileName.substring(i+1);
}
return extension;
}
public String getAnnotationsAsUrlEncodedParameters() {
String parameters = "";
File annotationsFile = new File(getObbDir(), ANNOTATIONS_JSON);
if (annotationsFile.exists()) {
JsonParser parser = new JsonParser();
try {
JsonObject json = (JsonObject) parser.parse(new FileReader(annotationsFile));
for (String k: json.keySet()) {
if (!json.get(k).getAsString().isEmpty()) {
String key = k.contains("/") ? k.substring(k.indexOf("/") + 1) : k;
if (!parameters.isEmpty()) {
parameters += "&";
}
parameters += URLEncoder.encode(key, "UTF-8") + "=" + URLEncoder.encode(json.get(k).getAsString(), "UTF-8");
}
}
} catch (FileNotFoundException e) {
Log.e(TAG, "Error reading annotations file", e);
} catch (UnsupportedEncodingException e) {
Log.e(TAG, "Error reading annotations file", e);
}
}
return parameters;
}
}

View file

@ -11,44 +11,55 @@
package io.highfidelity.hifiinterface;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.res.AssetManager;
import android.content.res.Configuration;
import android.graphics.Point;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Vibrator;
import android.view.HapticFeedbackConstants;
import android.view.WindowManager;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.WindowManager;
import android.widget.FrameLayout;
import android.widget.SlidingDrawer;
import org.qtproject.qt5.android.QtLayout;
import org.qtproject.qt5.android.QtSurface;
import org.qtproject.qt5.android.bindings.QtActivity;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import io.highfidelity.hifiinterface.fragment.WebViewFragment;
/*import com.google.vr.cardboard.DisplaySynchronizer;
import com.google.vr.cardboard.DisplayUtils;
import com.google.vr.ndk.base.GvrApi;*/
import android.graphics.Point;
import android.content.res.Configuration;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.view.View;
import android.widget.FrameLayout;
import java.lang.reflect.Field;
public class InterfaceActivity extends QtActivity {
public class InterfaceActivity extends QtActivity implements WebViewFragment.OnWebViewInteractionListener {
public static final String DOMAIN_URL = "url";
private static final String TAG = "Interface";
private static final int WEB_DRAWER_RIGHT_MARGIN = 262;
private static final int WEB_DRAWER_BOTTOM_MARGIN = 150;
private static final int NORMAL_DPI = 160;
private Vibrator mVibrator;
//public static native void handleHifiURL(String hifiURLString);
private native long nativeOnCreate(InterfaceActivity instance, AssetManager assetManager);
private native void nativeOnDestroy();
private native void nativeGotoUrl(String url);
private native void nativeBeforeEnterBackground();
private native void nativeEnterBackground();
private native void nativeEnterForeground();
private native long nativeOnExitVr();
@ -56,6 +67,9 @@ public class InterfaceActivity extends QtActivity {
private AssetManager assetManager;
private static boolean inVrMode;
private boolean nativeEnterBackgroundCallEnqueued = false;
private SlidingDrawer webSlidingDrawer;
// private GvrApi gvrApi;
// Opaque native pointer to the Application C++ object.
// This object is owned by the InterfaceActivity instance and passed to the native methods.
@ -116,18 +130,42 @@ public class InterfaceActivity extends QtActivity {
});
startActivity(new Intent(this, SplashActivity.class));
mVibrator = (Vibrator) this.getSystemService(VIBRATOR_SERVICE);
FrameLayout mainLayout = findViewById(android.R.id.content);
LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
webSlidingDrawer = (SlidingDrawer) inflater.inflate(R.layout.web_drawer, mainLayout, false);
QtLayout qtLayout = (QtLayout) mainLayout.getChildAt(0);
QtLayout.LayoutParams layoutParams = new QtLayout.LayoutParams(webSlidingDrawer.getLayoutParams());
webSlidingDrawer.setOnDrawerCloseListener(() -> {
WebViewFragment webViewFragment = (WebViewFragment) getFragmentManager().findFragmentByTag("webViewFragment");
webViewFragment.close();
});
int widthPx = Math.max(size.x, size.y);
int heightPx = Math.min(size.x, size.y);
layoutParams.x = (int) (widthPx - WEB_DRAWER_RIGHT_MARGIN * getResources().getDisplayMetrics().xdpi / NORMAL_DPI);
layoutParams.y = (int) (heightPx - WEB_DRAWER_BOTTOM_MARGIN * getResources().getDisplayMetrics().ydpi / NORMAL_DPI);
layoutParams.resolveLayoutDirection(View.LAYOUT_DIRECTION_RTL);
qtLayout.addView(webSlidingDrawer, layoutParams);
webSlidingDrawer.setVisibility(View.GONE);
}
@Override
protected void onPause() {
super.onPause();
nativeEnterBackground();
if (super.isLoading) {
nativeEnterBackgroundCallEnqueued = true;
} else {
nativeEnterBackground();
}
//gvrApi.pauseTracking();
}
@Override
protected void onStart() {
super.onStart();
nativeEnterBackgroundCallEnqueued = false;
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
}
@ -142,6 +180,7 @@ public class InterfaceActivity extends QtActivity {
super.onResume();
nativeEnterForeground();
surfacesWorkaround();
keepInterfaceRunning = false;
//gvrApi.resumeTracking();
}
@ -173,9 +212,16 @@ public class InterfaceActivity extends QtActivity {
FrameLayout fl = findViewById(android.R.id.content);
if (fl.getChildCount() > 0) {
QtLayout qtLayout = (QtLayout) fl.getChildAt(0);
if (qtLayout.getChildCount() > 1) {
QtSurface s1 = (QtSurface) qtLayout.getChildAt(0);
QtSurface s2 = (QtSurface) qtLayout.getChildAt(1);
List<QtSurface> surfaces = new ArrayList<>();
for (int i = 0; i < qtLayout.getChildCount(); i++) {
Object ch = qtLayout.getChildAt(i);
if (ch instanceof QtSurface) {
surfaces.add((QtSurface) ch);
}
}
if (surfaces.size() > 1) {
QtSurface s1 = surfaces.get(0);
QtSurface s2 = surfaces.get(1);
Integer subLayer1 = 0;
Integer subLayer2 = 0;
try {
@ -232,21 +278,46 @@ public class InterfaceActivity extends QtActivity {
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
if (intent.hasExtra(DOMAIN_URL)) {
webSlidingDrawer.setVisibility(View.GONE);
nativeGotoUrl(intent.getStringExtra(DOMAIN_URL));
}
}
public void openAndroidActivity(String activityName, boolean backToScene) {
openAndroidActivity(activityName, backToScene, null);
}
public void openAndroidActivity(String activityName, boolean backToScene, HashMap args) {
switch (activityName) {
case "Home":
case "Privacy Policy":
case "Login": {
nativeBeforeEnterBackground();
Intent intent = new Intent(this, MainActivity.class);
intent.putExtra(MainActivity.EXTRA_FRAGMENT, activityName);
intent.putExtra(MainActivity.EXTRA_BACK_TO_SCENE, backToScene);
startActivity(intent);
break;
}
case "WebView":
runOnUiThread(() -> {
webSlidingDrawer.setVisibility(View.VISIBLE);
if (!webSlidingDrawer.isOpened()) {
webSlidingDrawer.animateOpen();
}
if (args != null && args.containsKey(WebViewActivity.WEB_VIEW_ACTIVITY_EXTRA_URL)) {
WebViewFragment webViewFragment = (WebViewFragment) getFragmentManager().findFragmentByTag("webViewFragment");
webViewFragment.loadUrl((String) args.get(WebViewActivity.WEB_VIEW_ACTIVITY_EXTRA_URL), true);
webViewFragment.setToolbarVisible(true);
webViewFragment.setCloseAction(() -> {
if (webSlidingDrawer.isOpened()) {
webSlidingDrawer.animateClose();
}
webSlidingDrawer.setVisibility(View.GONE);
});
}
});
break;
default: {
Log.w(TAG, "Could not open activity by name " + activityName);
break;
@ -256,6 +327,9 @@ public class InterfaceActivity extends QtActivity {
public void onAppLoadedComplete() {
super.isLoading = false;
if (nativeEnterBackgroundCallEnqueued) {
nativeEnterBackground();
}
}
public void performHapticFeedback(int duration) {
@ -268,4 +342,18 @@ public class InterfaceActivity extends QtActivity {
public void onBackPressed() {
openAndroidActivity("Home", false);
}
@Override
public void processURL(String url) { }
@Override
public void onWebLoaded(String url, WebViewFragment.SafenessLevel safenessLevel) { }
@Override
public void onTitleReceived(String title) { }
@Override
public void onExpand() {
keepInterfaceRunning = true;
}
}

View file

@ -1,13 +1,14 @@
package io.highfidelity.hifiinterface;
import android.Manifest;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.app.Activity;
import android.content.DialogInterface;
import android.app.AlertDialog;
import android.util.Log;
import android.view.View;
import org.json.JSONException;
import org.json.JSONObject;
@ -24,20 +25,31 @@ public class PermissionChecker extends Activity {
private static final int REQUEST_PERMISSIONS = 20;
private static final boolean CHOOSE_AVATAR_ON_STARTUP = false;
private static final String TAG = "Interface";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent myIntent = new Intent(this, BreakpadUploaderService.class);
startService(myIntent);
if (CHOOSE_AVATAR_ON_STARTUP) {
showMenu();
}
this.requestAppPermissions(new
String[]{
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.RECORD_AUDIO,
Manifest.permission.CAMERA}
,2,REQUEST_PERMISSIONS);
File obbDir = getObbDir();
if (!obbDir.exists()) {
if (obbDir.mkdirs()) {
Log.d(TAG, "Obb dir created");
}
}
requestAppPermissions(new
String[]{
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.RECORD_AUDIO,
Manifest.permission.CAMERA}
,2,REQUEST_PERMISSIONS);
}
@ -125,5 +137,12 @@ public class PermissionChecker extends Activity {
}
}
@Override
protected void onResume() {
super.onResume();
View decorView = getWindow().getDecorView();
// Hide the status bar.
int uiOptions = View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
decorView.setSystemUiVisibility(uiOptions);
}
}

View file

@ -8,93 +8,64 @@
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
//package hifiinterface.highfidelity.io.mybrowserapplication;
package io.highfidelity.hifiinterface;
import android.app.ActionBar;
import android.app.Activity;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
import android.net.http.SslError;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.webkit.SslErrorHandler;
import android.webkit.WebChromeClient;
import android.webkit.WebResourceError;
import android.webkit.WebResourceRequest;
import android.webkit.WebResourceResponse;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.ProgressBar;
import android.widget.Toast;
import android.widget.Toolbar;
import android.os.Looper;
import java.lang.Thread;
import java.lang.Runnable;
import java.net.MalformedURLException;
import java.net.URL;
public class WebViewActivity extends Activity {
import io.highfidelity.hifiinterface.fragment.WebViewFragment;
public class WebViewActivity extends Activity implements WebViewFragment.OnWebViewInteractionListener {
public static final String WEB_VIEW_ACTIVITY_EXTRA_URL = "url";
private static final String FRAGMENT_TAG = "WebViewActivity_WebFragment";
private native void nativeProcessURL(String url);
private WebView myWebView;
private ProgressBar mProgressBar;
private ActionBar mActionBar;
private String mUrl;
enum SafenessLevel {
NOT_ANALYZED_YET(""),
NOT_SECURE(""),
SECURE("\uD83D\uDD12 "),
BAD_SECURE("\uD83D\uDD13 ");
String icon;
SafenessLevel(String icon) {
this.icon = icon;
}
}
private SafenessLevel safenessLevel = SafenessLevel.NOT_ANALYZED_YET;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_web_view);
setActionBar((Toolbar) findViewById(R.id.toolbar_actionbar));
setActionBar(findViewById(R.id.toolbar_actionbar));
mActionBar = getActionBar();
mActionBar.setDisplayHomeAsUpEnabled(true);
mProgressBar = (ProgressBar) findViewById(R.id.toolbarProgressBar);
loadWebViewFragment(getIntent().getStringExtra(WEB_VIEW_ACTIVITY_EXTRA_URL));
}
mUrl = getIntent().getStringExtra(WEB_VIEW_ACTIVITY_EXTRA_URL);
myWebView = (WebView) findViewById(R.id.web_view);
myWebView.setWebViewClient(new HiFiWebViewClient());
myWebView.setWebChromeClient(new HiFiWebChromeClient());
WebSettings webSettings = myWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
webSettings.setBuiltInZoomControls(true);
webSettings.setDisplayZoomControls(false);
myWebView.loadUrl(mUrl);
private void loadWebViewFragment(String url) {
WebViewFragment fragment = WebViewFragment.newInstance();
Bundle bundle = new Bundle();
bundle.putString(WebViewFragment.URL, url);
bundle.putBoolean(WebViewFragment.TOOLBAR_VISIBLE, false);
fragment.setArguments(bundle);
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction ft = fragmentManager.beginTransaction();
ft.replace(R.id.content_frame, fragment, FRAGMENT_TAG);
ft.commit();
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
// Check if the key event was the Back button and if there's history
if ((keyCode == KeyEvent.KEYCODE_BACK) && myWebView.canGoBack()) {
myWebView.goBack();
WebViewFragment fragment = (WebViewFragment) getFragmentManager().findFragmentByTag(FRAGMENT_TAG);
if (fragment != null && fragment.onKeyDown(keyCode)) {
return true;
}
// If it wasn't the Back key or there's no web page history, bubble up to the default
@ -102,15 +73,6 @@ public class WebViewActivity extends Activity {
return super.onKeyDown(keyCode, event);
}
private void showSubtitleWithUrl(String url) {
try {
mActionBar.setSubtitle(safenessLevel.icon + new URL(url.toString()).getHost());
} catch (MalformedURLException e) {
Toast.makeText(WebViewActivity.this, "Error loading page: " + "bad url", Toast.LENGTH_LONG).show();
Log.e("openUrl", "bad url");
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
@ -119,7 +81,7 @@ public class WebViewActivity extends Activity {
}
private String intentUrlOrWebUrl() {
return myWebView==null || myWebView.getUrl()==null?mUrl:myWebView.getUrl();
return ((WebViewFragment) getFragmentManager().findFragmentById(R.id.content_frame)).intentUrlOrWebUrl();
}
@Override
@ -145,98 +107,28 @@ public class WebViewActivity extends Activity {
return super.onOptionsItemSelected(item);
}
class HiFiWebViewClient extends WebViewClient {
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
mProgressBar.setVisibility(View.GONE);
if (safenessLevel!=SafenessLevel.BAD_SECURE) {
if (url.startsWith("https:")) {
safenessLevel=SafenessLevel.SECURE;
} else {
safenessLevel=SafenessLevel.NOT_SECURE;
}
}
showSubtitleWithUrl(url);
}
@Override
public void processURL(String url) {
nativeProcessURL(url);
}
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
super.onPageStarted(view, url, favicon);
safenessLevel = SafenessLevel.NOT_ANALYZED_YET;
mProgressBar.setVisibility(View.VISIBLE);
mProgressBar.setProgress(0);
showSubtitleWithUrl(url);
}
@Override
public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {
Toast.makeText(WebViewActivity.this, "Error loading page: " + error.getDescription(), Toast.LENGTH_LONG).show();
if (ERROR_FAILED_SSL_HANDSHAKE == error.getErrorCode()) {
safenessLevel = SafenessLevel.BAD_SECURE;
}
}
@Override
public void onReceivedHttpError(WebView view, WebResourceRequest request, WebResourceResponse errorResponse) {
Toast.makeText(WebViewActivity.this, "Network Error loading page: " + errorResponse.getReasonPhrase(), Toast.LENGTH_LONG).show();
}
@Override
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
super.onReceivedSslError(view, handler, error);
Toast.makeText(WebViewActivity.this, "SSL error loading page: " + error.toString(), Toast.LENGTH_LONG).show();
safenessLevel = SafenessLevel.BAD_SECURE;
}
private boolean isFst(WebResourceRequest request) {
return isFst(request.getUrl().toString());
}
private boolean isFst(String url) {
return url.endsWith(".fst");
}
@Override
public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
// managing avatar selections
if (isFst(request)) {
final String url = request.getUrl().toString();
new Thread(new Runnable() {
public void run() {
nativeProcessURL(url);
}
}).start(); // Avoid deadlock in Qt dialog
WebViewActivity.this.finish();
return true;
}
return super.shouldOverrideUrlLoading(view, request);
}
@Override
public void onLoadResource(WebView view, String url) {
if (isFst(url)) {
// processed separately
} else {
super.onLoadResource(view, url);
}
@Override
public void onWebLoaded(String url, WebViewFragment.SafenessLevel safenessLevel) {
try {
mActionBar.setSubtitle(safenessLevel.icon + new URL(url.toString()).getHost());
} catch (MalformedURLException e) {
Toast.makeText(WebViewActivity.this, "Error loading page: " + "bad url", Toast.LENGTH_LONG).show();
Log.e("openUrl", "bad url");
}
}
class HiFiWebChromeClient extends WebChromeClient {
@Override
public void onProgressChanged(WebView view, int newProgress) {
super.onProgressChanged(view, newProgress);
mProgressBar.setProgress(newProgress);
}
@Override
public void onReceivedTitle(WebView view, String title) {
super.onReceivedTitle(view, title);
mActionBar.setTitle(title);
}
@Override
public void onTitleReceived(String title) {
mActionBar.setTitle(title);
}
@Override
public void onExpand() { }
}

View file

@ -4,6 +4,7 @@ import android.app.Fragment;
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.text.Editable;
@ -32,6 +33,7 @@ public class HomeFragment extends Fragment {
private OnHomeInteractionListener mListener;
private SwipeRefreshLayout mSwipeRefreshLayout;
public native String nativeGetLastLocation();
@ -57,12 +59,14 @@ public class HomeFragment extends Fragment {
View rootView = inflater.inflate(R.layout.fragment_home, container, false);
searchNoResultsView = rootView.findViewById(R.id.searchNoResultsView);
mSwipeRefreshLayout = rootView.findViewById(R.id.swipeRefreshLayout);
mDomainsView = rootView.findViewById(R.id.rvDomains);
int numberOfColumns = 1;
GridLayoutManager gridLayoutMgr = new GridLayoutManager(getContext(), numberOfColumns);
mDomainsView.setLayoutManager(gridLayoutMgr);
mDomainAdapter = new DomainAdapter(getContext(), HifiUtils.getInstance().protocolVersionSignature(), nativeGetLastLocation());
mSwipeRefreshLayout.setRefreshing(true);
mDomainAdapter.setClickListener((view, position, domain) -> {
new Handler(getActivity().getMainLooper()).postDelayed(() -> {
if (mListener != null) {
@ -76,12 +80,14 @@ public class HomeFragment extends Fragment {
searchNoResultsView.setText(R.string.search_no_results);
searchNoResultsView.setVisibility(View.VISIBLE);
mDomainsView.setVisibility(View.GONE);
mSwipeRefreshLayout.setRefreshing(false);
}
@Override
public void onNonEmptyAdapter() {
searchNoResultsView.setVisibility(View.GONE);
mDomainsView.setVisibility(View.VISIBLE);
mSwipeRefreshLayout.setRefreshing(false);
}
@Override
@ -104,7 +110,7 @@ public class HomeFragment extends Fragment {
@Override
public void afterTextChanged(Editable editable) {
mDomainAdapter.loadDomains(editable.toString());
mDomainAdapter.loadDomains(editable.toString(), false);
if (editable.length() > 0) {
mSearchIconView.setVisibility(View.GONE);
mClearSearch.setVisibility(View.VISIBLE);
@ -130,6 +136,13 @@ public class HomeFragment extends Fragment {
mClearSearch.setOnClickListener(view -> onSearchClear(view));
mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
mDomainAdapter.loadDomains(mSearchView.getText().toString(), true);
}
});
getActivity().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
return rootView;

View file

@ -0,0 +1,343 @@
package io.highfidelity.hifiinterface.fragment;
import android.app.Fragment;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.net.http.SslError;
import android.os.Bundle;
import android.os.Handler;
import android.view.GestureDetector;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AlphaAnimation;
import android.webkit.SslErrorHandler;
import android.webkit.WebChromeClient;
import android.webkit.WebResourceError;
import android.webkit.WebResourceRequest;
import android.webkit.WebResourceResponse;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.ProgressBar;
import android.widget.Toast;
import io.highfidelity.hifiinterface.R;
import io.highfidelity.hifiinterface.WebViewActivity;
public class WebViewFragment extends Fragment implements GestureDetector.OnGestureListener {
public static final String URL = "url";
public static final String TOOLBAR_VISIBLE = "toolbar_visible";
private static final long DELAY_HIDE_TOOLBAR_MILLIS = 3000;
private static final long FADE_OUT_DURATION = 2000;
private WebView myWebView;
private GestureDetector gestureDetector;
private View mToolbar;
private ProgressBar mProgressBar;
private String mUrl;
private boolean mToolbarVisible;
private OnWebViewInteractionListener mListener;
private Runnable mCloseAction;
private Handler mHandler;
private Runnable mHideToolbar = new Runnable() {
@Override
public void run() {
if (mToolbar != null) {
AlphaAnimation anim = new AlphaAnimation(1.0f, 0.0f);
anim.setDuration(FADE_OUT_DURATION);
anim.setFillAfter(true);
mToolbar.startAnimation(anim);
}
}
};
public boolean onKeyDown(int keyCode) {
// Check if the key event was the Back button and if there's history
if ((keyCode == KeyEvent.KEYCODE_BACK) && myWebView.canGoBack()) {
myWebView.goBack();
return true;
}
return false;
}
public String intentUrlOrWebUrl() {
return myWebView == null || myWebView.getUrl() == null ? mUrl : myWebView.getUrl();
}
public void loadUrl(String url, boolean showToolbar) {
mUrl = url;
mToolbarVisible = showToolbar;
loadUrl(myWebView, url);
}
private void loadUrl(WebView webView, String url) {
webView.setVisibility(View.GONE);
webView.getSettings().setLoadWithOverviewMode(true);
webView.getSettings().setUseWideViewPort(true);
webView.loadUrl(url);
mToolbar.setVisibility(mToolbarVisible ? View.VISIBLE : View.GONE);
mToolbar.clearAnimation();
if (mToolbarVisible) {
mHandler.postDelayed(mHideToolbar, DELAY_HIDE_TOOLBAR_MILLIS);
}
}
public void setToolbarVisible(boolean visible) {
mToolbar.setVisibility(visible ? View.VISIBLE : View.GONE);
}
public void setCloseAction(Runnable closeAction) {
this.mCloseAction = closeAction;
}
@Override
public boolean onDown(MotionEvent motionEvent) {
mHandler.removeCallbacks(mHideToolbar);
if (mToolbarVisible) {
mToolbar.setVisibility(mToolbarVisible ? View.VISIBLE : View.GONE);
mToolbar.clearAnimation();
mHandler.postDelayed(mHideToolbar, DELAY_HIDE_TOOLBAR_MILLIS);
}
return false;
}
@Override
public void onShowPress(MotionEvent motionEvent) {
}
@Override
public boolean onSingleTapUp(MotionEvent motionEvent) {
return false;
}
@Override
public boolean onScroll(MotionEvent motionEvent, MotionEvent motionEvent1, float v, float v1) {
return false;
}
@Override
public void onLongPress(MotionEvent motionEvent) {
}
@Override
public boolean onFling(MotionEvent motionEvent, MotionEvent motionEvent1, float v, float v1) {
return false;
}
public void close() {
myWebView.loadUrl("about:blank");
if (mCloseAction != null) {
mCloseAction.run();
}
}
public enum SafenessLevel {
NOT_ANALYZED_YET(""),
NOT_SECURE(""),
SECURE("\uD83D\uDD12 "),
BAD_SECURE("\uD83D\uDD13 ");
public String icon;
SafenessLevel(String icon) {
this.icon = icon;
}
}
private SafenessLevel safenessLevel = SafenessLevel.NOT_ANALYZED_YET;
public WebViewFragment() {
// Required empty public constructor
}
public static WebViewFragment newInstance() {
WebViewFragment fragment = new WebViewFragment();
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mUrl = getArguments().getString(URL);
mToolbarVisible = getArguments().getBoolean(TOOLBAR_VISIBLE);
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_web_view, container, false);
mProgressBar = rootView.findViewById(R.id.toolbarProgressBar);
myWebView = rootView.findViewById(R.id.web_view);
mHandler = new Handler();
gestureDetector = new GestureDetector(this);
gestureDetector.setOnDoubleTapListener(new GestureDetector.OnDoubleTapListener() {
@Override
public boolean onSingleTapConfirmed(MotionEvent motionEvent) {
return false;
}
@Override
public boolean onDoubleTap(MotionEvent motionEvent) {
expand();
return false;
}
@Override
public boolean onDoubleTapEvent(MotionEvent motionEvent) {
return false;
}
});
myWebView.setOnTouchListener((v, event) -> gestureDetector.onTouchEvent(event));
myWebView.setWebViewClient(new HiFiWebViewClient());
myWebView.setWebChromeClient(new HiFiWebChromeClient());
WebSettings webSettings = myWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
webSettings.setBuiltInZoomControls(true);
webSettings.setDisplayZoomControls(false);
mToolbar = rootView.findViewById(R.id.toolbar);
mToolbar.findViewById(R.id.viewFullScreen).setOnClickListener(view -> {
expand();
});
mToolbar.findViewById(R.id.close).setOnClickListener(view -> {
close();
});
if (mUrl != null) {
loadUrl(myWebView, mUrl);
}
return rootView;
}
private void expand() {
if (mListener != null) {
mListener.onExpand();
}
Intent intent = new Intent(getActivity(), WebViewActivity.class);
intent.putExtra(WebViewActivity.WEB_VIEW_ACTIVITY_EXTRA_URL, intentUrlOrWebUrl());
getActivity().startActivity(intent);
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof OnWebViewInteractionListener) {
mListener = (OnWebViewInteractionListener) context;
} else {
throw new RuntimeException(context.toString()
+ " must implement OnWebViewInteractionListener");
}
}
@Override
public void onDetach() {
super.onDetach();
mListener = null;
}
public interface OnWebViewInteractionListener {
void processURL(String url);
void onWebLoaded(String url, SafenessLevel safenessLevel);
void onTitleReceived(String title);
void onExpand();
}
class HiFiWebViewClient extends WebViewClient {
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
mProgressBar.setVisibility(View.GONE);
if (safenessLevel!= SafenessLevel.BAD_SECURE) {
if (url.startsWith("https:")) {
safenessLevel = SafenessLevel.SECURE;
} else {
safenessLevel = SafenessLevel.NOT_SECURE;
}
}
if (mListener != null) {
myWebView.setVisibility(View.VISIBLE);
mListener.onWebLoaded(url, safenessLevel);
}
}
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
super.onPageStarted(view, url, favicon);
safenessLevel = SafenessLevel.NOT_ANALYZED_YET;
mProgressBar.setVisibility(View.VISIBLE);
mProgressBar.setProgress(0);
if (mListener != null) {
myWebView.setVisibility(View.VISIBLE);
mListener.onWebLoaded(url, safenessLevel);
}
}
@Override
public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {
Toast.makeText(getActivity(), "Error loading page: " + error.getDescription(), Toast.LENGTH_LONG).show();
if (ERROR_FAILED_SSL_HANDSHAKE == error.getErrorCode()) {
safenessLevel = SafenessLevel.BAD_SECURE;
}
}
@Override
public void onReceivedHttpError(WebView view, WebResourceRequest request, WebResourceResponse errorResponse) {
Toast.makeText(getActivity(), "Network Error loading page: " + errorResponse.getReasonPhrase(), Toast.LENGTH_LONG).show();
}
@Override
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
super.onReceivedSslError(view, handler, error);
Toast.makeText(getActivity(), "SSL error loading page: " + error.toString(), Toast.LENGTH_LONG).show();
safenessLevel = SafenessLevel.BAD_SECURE;
}
private boolean isFst(WebResourceRequest request) {
return isFst(request.getUrl().toString());
}
private boolean isFst(String url) {
return url.contains(".fst");
}
@Override
public void onLoadResource(WebView view, String url) {
if (isFst(url)) {
// processed separately
} else {
super.onLoadResource(view, url);
}
}
}
class HiFiWebChromeClient extends WebChromeClient {
@Override
public void onProgressChanged(WebView view, int newProgress) {
super.onProgressChanged(view, newProgress);
mProgressBar.setProgress(newProgress);
}
@Override
public void onReceivedTitle(WebView view, String title) {
super.onReceivedTitle(view, title);
if (mListener != null) {
mListener.onTitleReceived(title);
}
}
}
}

View file

@ -10,7 +10,7 @@ import io.highfidelity.hifiinterface.view.DomainAdapter;
public interface DomainProvider {
void retrieve(String filterText, DomainCallback domainCallback);
void retrieve(String filterText, DomainCallback domainCallback, boolean forceRefresh);
interface DomainCallback {
void retrieveOk(List<DomainAdapter.Domain> domain);

View file

@ -49,8 +49,8 @@ public class UserStoryDomainProvider implements DomainProvider {
}
@Override
public synchronized void retrieve(String filterText, DomainCallback domainCallback) {
if (!startedToGetFromAPI) {
public synchronized void retrieve(String filterText, DomainCallback domainCallback, boolean forceRefresh) {
if (!startedToGetFromAPI || forceRefresh) {
startedToGetFromAPI = true;
fillDestinations(filterText, domainCallback);
} else {
@ -72,6 +72,7 @@ public class UserStoryDomainProvider implements DomainProvider {
allStories.clear();
getUserStoryPage(1, allStories, null,
ex -> {
suggestions.clear();
allStories.forEach(userStory -> {
if (taggedStoriesIds.contains(userStory.id)) {
userStory.tagFound = true;

View file

@ -42,14 +42,14 @@ public class DomainAdapter extends RecyclerView.Adapter<DomainAdapter.ViewHolder
mProtocol = protocol;
mLastLocation = lastLocation;
domainProvider = new UserStoryDomainProvider(mProtocol);
loadDomains("");
loadDomains("", true);
}
public void setListener(AdapterListener adapterListener) {
mAdapterListener = adapterListener;
}
public void loadDomains(String filterText) {
public void loadDomains(String filterText, boolean forceRefresh) {
domainProvider.retrieve(filterText, new DomainProvider.DomainCallback() {
@Override
public void retrieveOk(List<Domain> domain) {
@ -76,7 +76,7 @@ public class DomainAdapter extends RecyclerView.Adapter<DomainAdapter.ViewHolder
Log.e("DOMAINS", message, e);
if (mAdapterListener != null) mAdapterListener.onError(e, message);
}
});
}, forceRefresh);
}
private void overrideDefaultThumbnails(List<Domain> domain) {

View file

@ -60,6 +60,8 @@ import android.view.View;
import android.view.WindowManager.LayoutParams;
import android.view.accessibility.AccessibilityEvent;
import org.qtproject.qt5.android.QtNative;
@SuppressWarnings("unused")
public class QtActivity extends Activity {
public String APPLICATION_PARAMETERS = null;
@ -69,6 +71,7 @@ public class QtActivity extends Activity {
private QtActivityLoader m_loader = new QtActivityLoader(this);
public boolean isLoading;
public boolean keepInterfaceRunning;
public QtActivity() {
}
@ -102,7 +105,7 @@ public class QtActivity extends Activity {
}
public boolean super_dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
return super_dispatchPopulateAccessibilityEvent(event);
return super.dispatchPopulateAccessibilityEvent(event);
}
//---------------------------------------------------------------------------
@ -361,7 +364,25 @@ public class QtActivity extends Activity {
@Override
protected void onDestroy() {
super.onDestroy();
QtApplication.invokeDelegate();
/*
cduarte https://highfidelity.manuscript.com/f/cases/16712/App-freezes-on-opening-randomly
After Qt upgrade to 5.11 we had a black screen crash after closing the application with
the hardware button "Back" and trying to start the app again. It could only be fixed after
totally closing the app swiping it in the list of running apps.
This problem did not happen with the previous Qt version.
After analysing changes we came up with this case and change:
https://codereview.qt-project.org/#/c/218882/
In summary they've moved libs loading to the same thread as main() and as a matter of correctness
in the onDestroy method in QtActivityDelegate, they exit that thread with `QtNative.m_qtThread.exit();`
That exit call is the main reason of this problem.
In this fix we just replace the `QtApplication.invokeDelegate();` call that may end using the
entire onDestroy method including that thread exit line for other three lines that purposely
terminate qt (borrowed from QtActivityDelegate::onDestroy as well).
*/
QtNative.terminateQt();
QtNative.setActivity(null, null);
System.exit(0);
}
//---------------------------------------------------------------------------
@ -503,7 +524,7 @@ public class QtActivity extends Activity {
super.onPause();
// GC: this trick allow us to show a splash activity until Qt app finishes
// loading
if (!isLoading) {
if (!isLoading && !keepInterfaceRunning) {
QtApplication.invokeDelegate();
}
}
@ -644,7 +665,9 @@ public class QtActivity extends Activity {
@Override
protected void onStop() {
super.onStop();
QtApplication.invokeDelegate();
if (!keepInterfaceRunning) {
QtApplication.invokeDelegate();
}
}
//---------------------------------------------------------------------------

View file

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<vector
xmlns:android="http://schemas.android.com/apk/res/android"
android:name="vector"
android:width="173dp"
android:height="173dp"
android:viewportWidth="173"
android:viewportHeight="173">
<path
android:name="path"
android:pathData="M 86.5 173 C 134.273 173 173 134.273 173 86.5 C 173 38.727 134.273 0 86.5 0 C 38.727 0 0 38.727 0 86.5 C 0 134.273 38.727 173 86.5 173 Z"
android:fillColor="#181818"
android:fillAlpha="0.6"
android:strokeWidth="1"/>
<path
android:name="path_1"
android:pathData="M 53.3 53.3 L 119.7 119.7 M 53.3 119.7 L 119.7 53.3"
android:fillColor="#000"
android:fillAlpha="0.6"
android:strokeColor="#ffffff"
android:strokeWidth="13.5424"
android:strokeLineCap="round"/>
</vector>

View file

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<vector
xmlns:android="http://schemas.android.com/apk/res/android"
android:name="vector"
android:width="173dp"
android:height="173dp"
android:viewportWidth="173"
android:viewportHeight="173">
<path
android:name="path"
android:pathData="M 86.5 173 C 134.273 173 173 134.273 173 86.5 C 173 38.727 134.273 0 86.5 0 C 38.727 0 0 38.727 0 86.5 C 0 134.273 38.727 173 86.5 173 Z"
android:fillColor="#181818"
android:fillAlpha="0.6"
android:strokeWidth="1"/>
<path
android:name="path_2"
android:pathData="M 52.4 52.4 C 52.4 58.4 52.3 63.7 52.4 69 C 52.5 71.8 51.5 72.7 48.7 72.7 C 37.6 72.4 39.7 74.1 39.6 63.6 C 39.5 56.9 39.7 50.1 39.5 43.4 C 39.4 40.4 40.5 39.5 43.4 39.6 C 51.8 39.7 60.2 39.7 68.7 39.6 C 71.6 39.6 72.7 40.4 72.6 43.4 C 72.3 54.2 73.9 52.2 63.8 52.4 L 52.4 52.4 Z M 120.6 52.4 C 114.8 52.4 109.5 52.3 104.2 52.5 C 101.3 52.6 100.2 51.6 100.3 48.7 C 100.6 38 99 39.9 109.1 39.7 C 116 39.6 122.9 39.8 129.7 39.6 C 132.5 39.5 133.4 40.5 133.4 43.3 C 133.3 52 133.3 60.7 133.4 69.4 C 133.4 71.7 132.7 72.8 130.3 72.7 C 118.4 72.5 120.9 74.1 120.6 63.7 L 120.6 52.4 Z M 52.4 120.6 C 58.4 120.6 63.7 120.7 69 120.6 C 71.7 120.5 72.8 121.4 72.7 124.2 C 72.4 135.4 74 133.2 63.7 133.4 C 56.8 133.5 49.9 133.3 43.1 133.5 C 40.6 133.5 39.6 132.7 39.6 130.1 C 39.7 121.4 39.7 112.7 39.6 104 C 39.6 101.6 40.2 100.4 42.9 100.4 C 54.5 100.6 52.2 99 52.4 109.5 C 52.5 113 52.4 116.4 52.4 120.6 Z M 120.6 120.6 C 120.6 114.6 120.7 109.4 120.6 104.2 C 120.5 101.3 121.4 100.2 124.4 100.2 C 135.2 100.5 133.3 98.9 133.4 109 C 133.5 115.9 133.3 122.8 133.5 129.6 C 133.6 132.3 132.7 133.3 129.9 133.3 C 121.2 133.2 112.5 133.2 103.8 133.3 C 101.2 133.3 100.4 132.3 100.4 129.8 C 100.6 118.5 99.1 120.7 109.3 120.5 C 112.9 120.6 116.5 120.6 120.6 120.6 Z"
android:fillColor="#ffffff"
android:strokeWidth="1"/>
</vector>

View file

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" android:opacity="opaque">
<item android:drawable="@android:color/black"/>
<item android:drawable="@drawable/hifi_logo_splash"
android:gravity="center_horizontal"
android:top="225dp"
android:height="242dp"
android:width="242dp">
</item>
</layer-list>

View file

@ -7,9 +7,17 @@
android:layout_height="match_parent"
android:background="@android:color/black">
<ImageView
android:id="@+id/hifi_logo"
android:layout_width="242dp"
android:layout_height="242dp"
android:src="@drawable/hifi_logo_splash"
android:layout_centerHorizontal="true"
android:layout_marginTop="225dp"/>
<ProgressBar
style="@style/Widget.AppCompat.ProgressBar"
android:theme="@style/HifiCircularProgress"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/hifi_logo"
android:layout_centerHorizontal="true"/>
</RelativeLayout>

View file

@ -1,8 +1,9 @@
<?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:layout_width="match_parent"
android:layout_height="match_parent">
<Toolbar
android:id="@+id/toolbar_actionbar"
android:layout_width="match_parent"
@ -16,19 +17,9 @@
android:contentInsetStartWithNavigation="0dp"
android:title="">
</Toolbar>
<WebView
android:id="@+id/web_view"
<FrameLayout
android:id="@+id/content_frame"
android:layout_below="@id/toolbar_actionbar"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<ProgressBar
android:id="@+id/toolbarProgressBar"
android:layout_below="@id/toolbar_actionbar"
style="?android:attr/progressBarStyleHorizontal"
android:visibility="gone"
android:layout_width="match_parent"
android:layout_height="3dp"
android:indeterminate="false"
android:padding="0dp" />
android:layout_height="match_parent" />
</RelativeLayout>

View file

@ -63,13 +63,18 @@
android:visibility="gone"
/>
<android.support.v7.widget.RecyclerView
android:id="@+id/rvDomains"
<android.support.v4.widget.SwipeRefreshLayout
android:id="@+id/swipeRefreshLayout"
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:layout_height="0dp">
<android.support.v7.widget.RecyclerView
android:id="@+id/rvDomains"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</android.support.v4.widget.SwipeRefreshLayout>
</android.support.constraint.ConstraintLayout>

View file

@ -0,0 +1,42 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto">
<WebView
android:id="@+id/web_view"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<android.support.constraint.ConstraintLayout
android:id="@+id/toolbar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_alignParentRight="true"
android:layout_marginTop="6dp"
android:layout_marginRight="5dp"
android:visibility="gone">
<ImageView
android:id="@+id/viewFullScreen"
android:layout_width="31dp"
android:layout_height="31dp"
android:src="@drawable/ic_expand" />
<ImageView
android:id="@+id/close"
android:layout_width="31dp"
android:layout_height="31dp"
app:layout_constraintLeft_toRightOf="@id/viewFullScreen"
android:layout_marginLeft="5dp"
android:src="@drawable/ic_close" />
</android.support.constraint.ConstraintLayout>
<ProgressBar
android:id="@+id/toolbarProgressBar"
android:layout_below="@id/toolbar_actionbar"
style="?android:attr/progressBarStyleHorizontal"
android:visibility="gone"
android:layout_width="match_parent"
android:layout_height="3dp"
android:indeterminate="false"
android:padding="0dp" />
</RelativeLayout>

View file

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<SlidingDrawer android:id="@+id/drawer"
android:layout_width="218dp"
android:layout_height="125dp"
android:layout_gravity="bottom|right"
android:layout_marginBottom="11dp"
android:layout_marginRight="11dp"
android:handle="@+id/handle"
android:content="@+id/content"
xmlns:android="http://schemas.android.com/apk/res/android">
<ImageView
android:id="@id/handle"
android:layout_width="0dp"
android:layout_height="0dp"/>
<fragment
android:id="@id/content"
android:name="io.highfidelity.hifiinterface.fragment.WebViewFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:tag="webViewFragment"
/>
</SlidingDrawer>

View file

@ -17,4 +17,5 @@
<color name="colorLoginError">#FF7171</color>
<color name="black_060">#99000000</color>
<color name="statusbar_color">#292929</color>
<color name="hifiLogoColor">#23B2E7</color>
</resources>

View file

@ -19,6 +19,9 @@
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
</style>
<style name="Theme.AppCompat.Translucent.NoActionBar.Launcher" parent="Theme.AppCompat.Translucent.NoActionBar">
<item name="android:windowBackground">@drawable/launch_screen</item>
</style>
<style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" />
@ -62,4 +65,7 @@
<item name="android:background">@color/white_opaque</item>
</style>
<style name="HifiCircularProgress" parent="Theme.AppCompat.Light">
<item name="colorAccent">@color/hifiLogoColor</item>
</style>
</resources>

View file

@ -21,6 +21,7 @@ buildscript {
plugins {
id 'de.undercouch.download' version '3.3.0'
id "cz.malohlava" version "1.0.3"
id "io.github.http-builder-ng.http-plugin" version "0.1.1"
}
allprojects {
@ -36,6 +37,7 @@ task clean(type: Delete) {
ext {
RELEASE_NUMBER = project.hasProperty('RELEASE_NUMBER') ? project.getProperty('RELEASE_NUMBER') : '0'
VERSION_CODE = project.hasProperty('VERSION_CODE') ? project.getProperty('VERSION_CODE') : '0'
RELEASE_TYPE = project.hasProperty('RELEASE_TYPE') ? project.getProperty('RELEASE_TYPE') : 'DEV'
STABLE_BUILD = project.hasProperty('STABLE_BUILD') ? project.getProperty('STABLE_BUILD') : '0'
EXEC_SUFFIX = Os.isFamily(Os.FAMILY_WINDOWS) ? '.exe' : ''
@ -67,18 +69,19 @@ def baseFolder = new File(HIFI_ANDROID_PRECOMPILED)
def appDir = new File(projectDir, 'app')
def jniFolder = new File(appDir, 'src/main/jniLibs/arm64-v8a')
def baseUrl = 'https://hifi-public.s3.amazonaws.com/dependencies/android/'
def breakpadDumpSymsDir = new File("${appDir}/build/tmp/breakpadDumpSyms")
def qtFile='qt-5.9.3_linux_armv8-libcpp_openssl.tgz'
def qtChecksum='04599670ccca84bd2b15f6915568eb2d'
def qtVersionId='8QbCma4ryEPgBYn_8kgYgB10IvNx9I1W'
def qtFile='qt-5.11.1_linux_armv8-libcpp_openssl.tgz'
def qtChecksum='f312c47cd8b8dbca824c32af4eec5e66'
def qtVersionId='nyCGcb91S4QbYeJhUkawO5x1lrLdSNB_'
if (Os.isFamily(Os.FAMILY_MAC)) {
qtFile = 'qt-5.9.3_osx_armv8-libcpp_openssl.tgz'
qtChecksum='4b02de9d67d6bfb202355a808d2d9c59'
qtVersionId='2gfgoYCggJGyXxKiazaPGsMs1Gn9j4og'
qtFile = 'qt-5.11.1_osx_armv8-libcpp_openssl.tgz'
qtChecksum='a0c8b394aec5b0fcd46714ca3a53278a'
qtVersionId='QNa.lwNJaPc0eGuIL.xZ8ebeTuLL7rh8'
} else if (Os.isFamily(Os.FAMILY_WINDOWS)) {
qtFile = 'qt-5.9.3_win_armv8-libcpp_openssl.tgz'
qtChecksum='c3e25db64002d0f43cf565e0ef708911'
qtVersionId='xKIteC6HO0xrmcWeMmhQcmKyPEsnUrcZ'
qtFile = 'qt-5.11.1_win_armv8-libcpp_openssl.tgz'
qtChecksum='d80aed4233ce9e222aae8376e7a94bf9'
qtVersionId='iDVXu0i3WEXRFIxQCtzcJ2XuKrE8RIqB'
}
def packages = [
@ -149,6 +152,13 @@ def packages = [
file: 'etc2comp-patched-armv8-libcpp.tgz',
versionId: 'bHhGECRAQR1vkpshBcK6ByNc1BQIM8gU',
checksum: '14b02795d774457a33bbc60e00a786bc'
],
breakpad: [
file: 'breakpad.tgz',
versionId: '8VrYXz7oyc.QBxNia0BVJOUBvrFO61jI',
checksum: 'ddcb23df336b08017042ba4786db1d9e',
sharedLibFolder: 'lib',
includeLibs: ['libbreakpad_client.a']
]
]
@ -367,6 +377,7 @@ task verifyPolyvox(type: Verify) { def p = packages['polyvox']; src new File(bas
task verifyTBB(type: Verify) { def p = packages['tbb']; src new File(baseFolder, p['file']); checksum p['checksum'] }
task verifyHifiAC(type: Verify) { def p = packages['hifiAC']; src new File(baseFolder, p['file']); checksum p['checksum'] }
task verifyEtc2Comp(type: Verify) { def p = packages['etc2comp']; src new File(baseFolder, p['file']); checksum p['checksum'] }
task verifyBreakpad(type: Verify) { def p = packages['breakpad']; src new File(baseFolder, p['file']); checksum p['checksum'] }
task verifyDependencyDownloads(dependsOn: downloadDependencies) { }
verifyDependencyDownloads.dependsOn verifyQt
@ -378,6 +389,7 @@ verifyDependencyDownloads.dependsOn verifyPolyvox
verifyDependencyDownloads.dependsOn verifyTBB
verifyDependencyDownloads.dependsOn verifyHifiAC
verifyDependencyDownloads.dependsOn verifyEtc2Comp
verifyDependencyDownloads.dependsOn verifyBreakpad
task extractDependencies(dependsOn: verifyDependencyDownloads) {
doLast {
@ -540,7 +552,93 @@ task cleanDependencies(type: Delete) {
delete 'app/src/main/res/values/libs.xml'
}
def runBreakpadDumpSyms = { buildType ->
gradle.startParameter.showStacktrace = ShowStacktrace.ALWAYS
def objDir = new File("${appDir}/build/intermediates/cmake/${buildType}/obj/arm64-v8a")
def stripDebugSymbol = "${appDir}/build/intermediates/transforms/stripDebugSymbol/${buildType}/0/lib/arm64-v8a/"
def outputDir = new File(breakpadDumpSymsDir, buildType)
if (!outputDir.exists()) {
outputDir.mkdirs()
}
objDir.eachFileRecurse (FileType.FILES) { file ->
if (file.name.endsWith('.so')) {
def output = file.name + ".sym"
def cmdArgs = [
file.toString(),
stripDebugSymbol
]
def result = exec {
workingDir HIFI_ANDROID_PRECOMPILED + '/breakpad/bin'
commandLine './dump_syms'
args cmdArgs
ignoreExitValue true
standardOutput = new BufferedOutputStream(new FileOutputStream(new File(outputDir, output)))
}
}
}
}
task runBreakpadDumpSymsDebug() {
doLast {
runBreakpadDumpSyms("debug");
}
}
task runBreakpadDumpSymsRelease() {
doLast {
runBreakpadDumpSyms("release");
}
}
task zipDumpSymsDebug(type: Zip, dependsOn: runBreakpadDumpSymsDebug) {
from (new File(breakpadDumpSymsDir, "debug").absolutePath)
archiveName "symbols-${RELEASE_NUMBER}-debug.zip"
destinationDir(new File("${appDir}/build/tmp/"))
}
task zipDumpSymsRelease(type: Zip, dependsOn: runBreakpadDumpSymsRelease) {
from (new File(breakpadDumpSymsDir, "release").absolutePath)
archiveName "symbols-${RELEASE_NUMBER}-release.zip"
destinationDir(new File("${appDir}/build/tmp/"))
}
task uploadBreakpadDumpSymsDebug(type:io.github.httpbuilderng.http.HttpTask, dependsOn: zipDumpSymsDebug) {
onlyIf {
System.getenv("CMAKE_BACKTRACE_URL") && System.getenv("CMAKE_BACKTRACE_SYMBOLS_TOKEN")
}
config {
request.uri = System.getenv("CMAKE_BACKTRACE_URL")
}
post {
request.uri.path = '/post'
request.uri.query = [format: 'symbols', token: System.getenv("CMAKE_BACKTRACE_SYMBOLS_TOKEN")]
request.body = new File("${appDir}/build/tmp/", "symbols-${RELEASE_NUMBER}-debug.zip").bytes
request.contentType = 'application/octet-stream'
response.success {
println ("${appDir}/build/tmp/symbols-${RELEASE_NUMBER}-debug.zip uploaded")
}
}
}
task uploadBreakpadDumpSymsRelease(type:io.github.httpbuilderng.http.HttpTask, dependsOn: zipDumpSymsRelease) {
onlyIf {
System.getenv("CMAKE_BACKTRACE_URL") && System.getenv("CMAKE_BACKTRACE_SYMBOLS_TOKEN")
}
config {
request.uri = System.getenv("CMAKE_BACKTRACE_URL")
}
post {
request.uri.path = '/post'
request.uri.query = [format: 'symbols', token: System.getenv("CMAKE_BACKTRACE_SYMBOLS_TOKEN")]
request.body = new File("${appDir}/build/tmp/", "symbols-${RELEASE_NUMBER}-release.zip").bytes
request.contentType = 'application/octet-stream'
response.success {
println ("${appDir}/build/tmp/symbols-${RELEASE_NUMBER}-release.zip uploaded")
}
}
}
// FIXME this code is prototyping the desired functionality for doing build time binary dependency resolution.
// See the comment on the qtBundle task above
@ -615,4 +713,4 @@ task testElf (dependsOn: 'externalNativeBuildDebug') {
}
}
}
*/
*/

View file

@ -50,6 +50,7 @@
#include "entities/AssignmentParentFinder.h"
#include "RecordingScriptingInterface.h"
#include "AbstractAudioInterface.h"
#include "AgentScriptingInterface.h"
static const int RECEIVED_AUDIO_STREAM_CAPACITY_FRAMES = 10;
@ -64,6 +65,7 @@ Agent::Agent(ReceivedMessage& message) :
DependencyManager::get<EntityScriptingInterface>()->setPacketSender(&_entityEditSender);
DependencyManager::set<ResourceManager>();
DependencyManager::set<PluginManager>();
DependencyManager::registerInheritance<SpatialParentFinder, AssignmentParentFinder>();
@ -343,8 +345,6 @@ void Agent::scriptRequestFinished() {
void Agent::executeScript() {
_scriptEngine = scriptEngineFactory(ScriptEngine::AGENT_SCRIPT, _scriptContents, _payload);
DependencyManager::get<RecordingScriptingInterface>()->setScriptEngine(_scriptEngine);
// setup an Avatar for the script to use
auto scriptedAvatar = DependencyManager::get<ScriptableAvatar>();
@ -451,7 +451,7 @@ void Agent::executeScript() {
packetReceiver.registerListener(PacketType::AvatarIdentity, avatarHashMap.data(), "processAvatarIdentityPacket");
// register ourselves to the script engine
_scriptEngine->registerGlobalObject("Agent", this);
_scriptEngine->registerGlobalObject("Agent", new AgentScriptingInterface(this));
_scriptEngine->registerGlobalObject("SoundCache", DependencyManager::get<SoundCache>().data());
_scriptEngine->registerGlobalObject("AnimationCache", DependencyManager::get<AnimationCache>().data());
@ -833,6 +833,8 @@ void Agent::aboutToFinish() {
DependencyManager::get<ResourceManager>()->cleanup();
DependencyManager::destroy<PluginManager>();
// cleanup the AudioInjectorManager (and any still running injectors)
DependencyManager::destroy<AudioInjectorManager>();

View file

@ -33,19 +33,6 @@
#include "entities/EntityTreeHeadlessViewer.h"
#include "avatars/ScriptableAvatar.h"
/**jsdoc
* @namespace Agent
*
* @hifi-assignment-client
*
* @property {boolean} isAvatar
* @property {boolean} isPlayingAvatarSound <em>Read-only.</em>
* @property {boolean} isListeningToAudioStream
* @property {boolean} isNoiseGateEnabled
* @property {number} lastReceivedAudioLoudness <em>Read-only.</em>
* @property {Uuid} sessionUUID <em>Read-only.</em>
*/
class Agent : public ThreadedAssignment {
Q_OBJECT
@ -73,28 +60,11 @@ public:
virtual void aboutToFinish() override;
public slots:
/**jsdoc
* @function Agent.run
* @deprecated This function is being removed from the API.
*/
void run() override;
/**jsdoc
* @function Agent.playAvatarSound
* @param {object} avatarSound
*/
void playAvatarSound(SharedSoundPointer avatarSound);
/**jsdoc
* @function Agent.setIsAvatar
* @param {boolean} isAvatar
*/
void setIsAvatar(bool isAvatar);
/**jsdoc
* @function Agent.isAvatar
* @returns {boolean}
*/
void setIsAvatar(bool isAvatar);
bool isAvatar() const { return _isAvatar; }
private slots:

View file

@ -0,0 +1,17 @@
//
// AgentScriptingInterface.cpp
// assignment-client/src
//
// Created by Thijs Wenker on 7/23/18.
// Copyright 2018 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include "AgentScriptingInterface.h"
AgentScriptingInterface::AgentScriptingInterface(Agent* agent) :
QObject(agent),
_agent(agent)
{ }

View file

@ -0,0 +1,80 @@
//
// AgentScriptingInterface.h
// assignment-client/src
//
// Created by Thijs Wenker on 7/23/18.
// Copyright 2018 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#pragma once
#ifndef hifi_AgentScriptingInterface_h
#define hifi_AgentScriptingInterface_h
#include <QObject>
#include "Agent.h"
/**jsdoc
* @namespace Agent
*
* @hifi-assignment-client
*
* @property {boolean} isAvatar
* @property {boolean} isPlayingAvatarSound <em>Read-only.</em>
* @property {boolean} isListeningToAudioStream
* @property {boolean} isNoiseGateEnabled
* @property {number} lastReceivedAudioLoudness <em>Read-only.</em>
* @property {Uuid} sessionUUID <em>Read-only.</em>
*/
class AgentScriptingInterface : public QObject {
Q_OBJECT
Q_PROPERTY(bool isAvatar READ isAvatar WRITE setIsAvatar)
Q_PROPERTY(bool isPlayingAvatarSound READ isPlayingAvatarSound)
Q_PROPERTY(bool isListeningToAudioStream READ isListeningToAudioStream WRITE setIsListeningToAudioStream)
Q_PROPERTY(bool isNoiseGateEnabled READ isNoiseGateEnabled WRITE setIsNoiseGateEnabled)
Q_PROPERTY(float lastReceivedAudioLoudness READ getLastReceivedAudioLoudness)
Q_PROPERTY(QUuid sessionUUID READ getSessionUUID)
public:
AgentScriptingInterface(Agent* agent);
bool isPlayingAvatarSound() const { return _agent->isPlayingAvatarSound(); }
bool isListeningToAudioStream() const { return _agent->isListeningToAudioStream(); }
void setIsListeningToAudioStream(bool isListeningToAudioStream) const { _agent->setIsListeningToAudioStream(isListeningToAudioStream); }
bool isNoiseGateEnabled() const { return _agent->isNoiseGateEnabled(); }
void setIsNoiseGateEnabled(bool isNoiseGateEnabled) const { _agent->setIsNoiseGateEnabled(isNoiseGateEnabled); }
float getLastReceivedAudioLoudness() const { return _agent->getLastReceivedAudioLoudness(); }
QUuid getSessionUUID() const { return _agent->getSessionUUID(); }
public slots:
/**jsdoc
* @function Agent.setIsAvatar
* @param {boolean} isAvatar
*/
void setIsAvatar(bool isAvatar) const { _agent->setIsAvatar(isAvatar); }
/**jsdoc
* @function Agent.isAvatar
* @returns {boolean}
*/
bool isAvatar() const { return _agent->isAvatar(); }
/**jsdoc
* @function Agent.playAvatarSound
* @param {object} avatarSound
*/
void playAvatarSound(SharedSoundPointer avatarSound) const { _agent->playAvatarSound(avatarSound); }
private:
Agent* _agent;
};
#endif // hifi_AgentScriptingInterface_h

View file

@ -23,6 +23,7 @@
#include <QtCore/QFile>
#include <QtCore/QFileInfo>
#include <QtCore/QJsonDocument>
#include <QtCore/QSaveFile>
#include <QtCore/QString>
#include <QtGui/QImageReader>
#include <QtCore/QVector>
@ -291,18 +292,6 @@ AssetServer::AssetServer(ReceivedMessage& message) :
_bakingTaskPool(this),
_filesizeLimit(AssetUtils::MAX_UPLOAD_SIZE)
{
// store the current state of image compression so we can reset it when this assignment is complete
_wasColorTextureCompressionEnabled = image::isColorTexturesCompressionEnabled();
_wasGrayscaleTextureCompressionEnabled = image::isGrayscaleTexturesCompressionEnabled();
_wasNormalTextureCompressionEnabled = image::isNormalTexturesCompressionEnabled();
_wasCubeTextureCompressionEnabled = image::isCubeTexturesCompressionEnabled();
// enable compression in image library
image::setColorTexturesCompressionEnabled(true);
image::setGrayscaleTexturesCompressionEnabled(true);
image::setNormalTexturesCompressionEnabled(true);
image::setCubeTexturesCompressionEnabled(true);
BAKEABLE_TEXTURE_EXTENSIONS = image::getSupportedFormats();
qDebug() << "Supported baking texture formats:" << BAKEABLE_MODEL_EXTENSIONS;
@ -354,12 +343,6 @@ void AssetServer::aboutToFinish() {
while (_pendingBakes.size() > 0) {
QCoreApplication::processEvents();
}
// re-set defaults in image library
image::setColorTexturesCompressionEnabled(_wasCubeTextureCompressionEnabled);
image::setGrayscaleTexturesCompressionEnabled(_wasGrayscaleTextureCompressionEnabled);
image::setNormalTexturesCompressionEnabled(_wasNormalTextureCompressionEnabled);
image::setCubeTexturesCompressionEnabled(_wasCubeTextureCompressionEnabled);
}
void AssetServer::run() {
@ -1060,7 +1043,7 @@ bool AssetServer::loadMappingsFromFile() {
bool AssetServer::writeMappingsToFile() {
auto mapFilePath = _resourcesDirectory.absoluteFilePath(MAP_FILE_NAME);
QFile mapFile { mapFilePath };
QSaveFile mapFile { mapFilePath };
if (mapFile.open(QIODevice::WriteOnly)) {
QJsonObject root;
@ -1071,8 +1054,12 @@ bool AssetServer::writeMappingsToFile() {
QJsonDocument jsonDocument { root };
if (mapFile.write(jsonDocument.toJson()) != -1) {
qCDebug(asset_server) << "Wrote JSON mappings to file at" << mapFilePath;
return true;
if (mapFile.commit()) {
qCDebug(asset_server) << "Wrote JSON mappings to file at" << mapFilePath;
return true;
} else {
qCWarning(asset_server) << "Failed to commit JSON mappings to file at" << mapFilePath;
}
} else {
qCWarning(asset_server) << "Failed to write JSON mappings to file at" << mapFilePath;
}

View file

@ -167,11 +167,6 @@ private:
using RequestQueue = QVector<QPair<QSharedPointer<ReceivedMessage>, SharedNodePointer>>;
RequestQueue _queuedRequests;
bool _wasColorTextureCompressionEnabled { false };
bool _wasGrayscaleTextureCompressionEnabled { false };
bool _wasNormalTextureCompressionEnabled { false };
bool _wasCubeTextureCompressionEnabled { false };
uint64_t _filesizeLimit;
};

View file

@ -65,7 +65,8 @@ AudioMixer::AudioMixer(ReceivedMessage& message) :
// hash the available codecs (on the mixer)
_availableCodecs.clear(); // Make sure struct is clean
auto codecPlugins = PluginManager::getInstance()->getCodecPlugins();
auto pluginManager = DependencyManager::set<PluginManager>();
auto codecPlugins = pluginManager->getCodecPlugins();
std::for_each(codecPlugins.cbegin(), codecPlugins.cend(),
[&](const CodecPluginPointer& codec) {
_availableCodecs[codec->getName()] = codec;
@ -106,6 +107,10 @@ AudioMixer::AudioMixer(ReceivedMessage& message) :
connect(nodeList.data(), &NodeList::nodeKilled, this, &AudioMixer::handleNodeKilled);
}
void AudioMixer::aboutToFinish() {
DependencyManager::destroy<PluginManager>();
}
void AudioMixer::queueAudioPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer node) {
if (message->getType() == PacketType::SilentAudioFrame) {
_numSilentPackets++;

View file

@ -58,6 +58,9 @@ public:
to.getPublicSocket() != from.getPublicSocket() &&
to.getLocalSocket() != from.getLocalSocket();
}
virtual void aboutToFinish() override;
public slots:
void run() override;
void sendStatsPacket() override;

View file

@ -53,6 +53,7 @@ AvatarMixer::AvatarMixer(ReceivedMessage& message) :
packetReceiver.registerListener(PacketType::NodeIgnoreRequest, this, "handleNodeIgnoreRequestPacket");
packetReceiver.registerListener(PacketType::RadiusIgnoreRequest, this, "handleRadiusIgnoreRequestPacket");
packetReceiver.registerListener(PacketType::RequestsDomainListData, this, "handleRequestsDomainListDataPacket");
packetReceiver.registerListener(PacketType::AvatarIdentityRequest, this, "handleAvatarIdentityRequestPacket");
packetReceiver.registerListenerForTypes({
PacketType::ReplicatedAvatarIdentity,
@ -602,6 +603,31 @@ void AvatarMixer::handleAvatarIdentityPacket(QSharedPointer<ReceivedMessage> mes
_handleAvatarIdentityPacketElapsedTime += (end - start);
}
void AvatarMixer::handleAvatarIdentityRequestPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer senderNode) {
if (message->getSize() < NUM_BYTES_RFC4122_UUID) {
qCDebug(avatars) << "Malformed AvatarIdentityRequest received from" << message->getSenderSockAddr().toString();
return;
}
QUuid avatarID(QUuid::fromRfc4122(message->getMessage()) );
if (!avatarID.isNull()) {
auto nodeList = DependencyManager::get<NodeList>();
auto node = nodeList->nodeWithUUID(avatarID);
if (node) {
QMutexLocker lock(&node->getMutex());
AvatarMixerClientData* avatarClientData = dynamic_cast<AvatarMixerClientData*>(node->getLinkedData());
if (avatarClientData) {
const AvatarData& avatarData = avatarClientData->getAvatar();
QByteArray serializedAvatar = avatarData.identityByteArray();
auto identityPackets = NLPacketList::create(PacketType::AvatarIdentity, QByteArray(), true, true);
identityPackets->write(serializedAvatar);
nodeList->sendPacketList(std::move(identityPackets), *senderNode);
++_sumIdentityPackets;
}
}
}
}
void AvatarMixer::handleKillAvatarPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer node) {
auto start = usecTimestampNow();
handleAvatarKilled(node);

View file

@ -54,6 +54,7 @@ private slots:
void handleRequestsDomainListDataPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer senderNode);
void handleReplicatedPacket(QSharedPointer<ReceivedMessage> message);
void handleReplicatedBulkAvatarPacket(QSharedPointer<ReceivedMessage> message);
void handleAvatarIdentityRequestPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer senderNode);
void domainSettingsRequestComplete();
void handlePacketVersionMismatch(PacketType type, const HifiSockAddr& senderSockAddr, const QUuid& senderUUID);
void start();

View file

@ -396,21 +396,26 @@ void AvatarMixerSlave::broadcastAvatarDataToAgent(const SharedNodePointer& node)
quint64 end = usecTimestampNow();
_stats.toByteArrayElapsedTime += (end - start);
static const int MAX_ALLOWED_AVATAR_DATA = (1400 - NUM_BYTES_RFC4122_UUID);
if (bytes.size() > MAX_ALLOWED_AVATAR_DATA) {
qCWarning(avatars) << "otherAvatar.toByteArray() resulted in very large buffer:" << bytes.size() << "... attempt to drop facial data";
auto maxAvatarDataBytes = avatarPacketList->getMaxSegmentSize() - NUM_BYTES_RFC4122_UUID;
if (bytes.size() > maxAvatarDataBytes) {
qCWarning(avatars) << "otherAvatar.toByteArray() for" << otherNode->getUUID()
<< "resulted in very large buffer of" << bytes.size() << "bytes - dropping facial data";
dropFaceTracking = true; // first try dropping the facial data
bytes = otherAvatar->toByteArray(detail, lastEncodeForOther, lastSentJointsForOther,
hasFlagsOut, dropFaceTracking, distanceAdjust, viewerPosition, &lastSentJointsForOther);
if (bytes.size() > MAX_ALLOWED_AVATAR_DATA) {
qCWarning(avatars) << "otherAvatar.toByteArray() without facial data resulted in very large buffer:" << bytes.size() << "... reduce to MinimumData";
if (bytes.size() > maxAvatarDataBytes) {
qCWarning(avatars) << "otherAvatar.toByteArray() for" << otherNode->getUUID()
<< "without facial data resulted in very large buffer of" << bytes.size()
<< "bytes - reducing to MinimumData";
bytes = otherAvatar->toByteArray(AvatarData::MinimumData, lastEncodeForOther, lastSentJointsForOther,
hasFlagsOut, dropFaceTracking, distanceAdjust, viewerPosition, &lastSentJointsForOther);
if (bytes.size() > MAX_ALLOWED_AVATAR_DATA) {
qCWarning(avatars) << "otherAvatar.toByteArray() MinimumData resulted in very large buffer:" << bytes.size() << "... FAIL!!";
if (bytes.size() > maxAvatarDataBytes) {
qCWarning(avatars) << "otherAvatar.toByteArray() for" << otherNode->getUUID()
<< "MinimumData resulted in very large buffer of" << bytes.size()
<< "bytes - refusing to send avatar";
includeThisAvatar = false;
}
}

View file

@ -504,6 +504,11 @@ void EntityServer::startDynamicDomainVerification() {
QString thisDomainID = DependencyManager::get<AddressManager>()->getDomainID().remove(QRegExp("\\{|\\}"));
if (jsonObject["domain_id"].toString() != thisDomainID) {
EntityItemPointer entity = tree->findEntityByEntityItemID(entityID);
if (!entity) {
qCDebug(entities) << "Entity undergoing dynamic domain verification is no longer available:" << entityID;
networkReply->deleteLater();
return;
}
if (entity->getAge() > (_MAXIMUM_DYNAMIC_DOMAIN_VERIFICATION_TIMER_MS/MSECS_PER_SECOND)) {
qCDebug(entities) << "Entity's cert's domain ID" << jsonObject["domain_id"].toString()
<< "doesn't match the current Domain ID" << thisDomainID << "; deleting entity" << entityID;
@ -517,11 +522,8 @@ void EntityServer::startDynamicDomainVerification() {
qCDebug(entities) << "Entity passed dynamic domain verification:" << entityID;
}
} else {
qCDebug(entities) << "Call to" << networkReply->url() << "failed with error" << networkReply->error() << "; deleting entity" << entityID
qCDebug(entities) << "Call to" << networkReply->url() << "failed with error" << networkReply->error() << "; NOT deleting entity" << entityID
<< "More info:" << jsonObject;
tree->withWriteLock([&] {
tree->deleteEntity(entityID, true);
});
}
networkReply->deleteLater();

View file

@ -17,6 +17,9 @@ EntityTreeHeadlessViewer::EntityTreeHeadlessViewer()
}
EntityTreeHeadlessViewer::~EntityTreeHeadlessViewer() {
if (_simulation) {
_simulation->setEntityTree(nullptr); // Break shared_ptr cycle.
}
}
void EntityTreeHeadlessViewer::init() {

View file

@ -231,18 +231,19 @@ void OctreeServer::trackProcessWaitTime(float time) {
OctreeServer::OctreeServer(ReceivedMessage& message) :
ThreadedAssignment(message),
_argc(0),
_argv(NULL),
_parsedArgV(NULL),
_argv(nullptr),
_parsedArgV(nullptr),
_httpManager(nullptr),
_statusPort(0),
_packetsPerClientPerInterval(10),
_packetsTotalPerInterval(DEFAULT_PACKETS_PER_INTERVAL),
_tree(NULL),
_tree(nullptr),
_wantPersist(true),
_debugSending(false),
_debugReceiving(false),
_verboseDebug(false),
_octreeInboundPacketProcessor(NULL),
_persistThread(NULL),
_octreeInboundPacketProcessor(nullptr),
_persistManager(nullptr),
_started(time(0)),
_startedUSecs(usecTimestampNow())
{
@ -265,11 +266,8 @@ OctreeServer::~OctreeServer() {
_octreeInboundPacketProcessor->deleteLater();
}
if (_persistThread) {
_persistThread->terminating();
_persistThread->terminate();
_persistThread->deleteLater();
}
qDebug() << "Waiting for persist thread to come down";
_persistThread.wait();
// cleanup our tree here...
qDebug() << qPrintable(_safeServerName) << "server START cleaning up octree... [" << this << "]";
@ -1052,19 +1050,13 @@ void OctreeServer::readConfiguration() {
_persistAsFileType = "json.gz";
_persistInterval = OctreePersistThread::DEFAULT_PERSIST_INTERVAL;
readOptionInt(QString("persistInterval"), settingsSectionObject, _persistInterval);
qDebug() << "persistInterval=" << _persistInterval;
bool noBackup;
readOptionBool(QString("NoBackup"), settingsSectionObject, noBackup);
_wantBackup = !noBackup;
qDebug() << "wantBackup=" << _wantBackup;
if (!readOptionString("backupDirectoryPath", settingsSectionObject, _backupDirectoryPath)) {
_backupDirectoryPath = "";
int result { -1 };
readOptionInt(QString("persistInterval"), settingsSectionObject, result);
if (result != -1) {
_persistInterval = std::chrono::milliseconds(result);
}
qDebug() << "backupDirectoryPath=" << _backupDirectoryPath;
qDebug() << "persistInterval=" << _persistInterval.count();
readOptionBool(QString("persistFileDownload"), settingsSectionObject, _persistFileDownload);
qDebug() << "persistFileDownload=" << _persistFileDownload;
@ -1128,111 +1120,14 @@ void OctreeServer::run() {
}
void OctreeServer::domainSettingsRequestComplete() {
if (_state != OctreeServerState::WaitingForDomainSettings) {
qCWarning(octree_server) << "Received domain settings after they have already been received";
return;
}
auto& packetReceiver = DependencyManager::get<NodeList>()->getPacketReceiver();
packetReceiver.registerListener(getMyQueryMessageType(), this, "handleOctreeQueryPacket");
packetReceiver.registerListener(PacketType::OctreeDataNack, this, "handleOctreeDataNackPacket");
packetReceiver.registerListener(PacketType::OctreeDataFileReply, this, "handleOctreeDataFileReply");
packetReceiver.registerListener(getMyQueryMessageType(), this, "handleOctreeQueryPacket");
qDebug(octree_server) << "Received domain settings";
readConfiguration();
_state = OctreeServerState::WaitingForOctreeDataNegotation;
auto nodeList = DependencyManager::get<NodeList>();
const DomainHandler& domainHandler = nodeList->getDomainHandler();
auto packet = NLPacket::create(PacketType::OctreeDataFileRequest, -1, true, false);
OctreeUtils::RawOctreeData data;
qCDebug(octree_server) << "Reading octree data from" << _persistAbsoluteFilePath;
if (data.readOctreeDataInfoFromFile(_persistAbsoluteFilePath)) {
qCDebug(octree_server) << "Current octree data: ID(" << data.id << ") DataVersion(" << data.version << ")";
packet->writePrimitive(true);
auto id = data.id.toRfc4122();
packet->write(id);
packet->writePrimitive(data.version);
} else {
qCWarning(octree_server) << "No octree data found";
packet->writePrimitive(false);
}
qCDebug(octree_server) << "Sending request for octree data to DS";
nodeList->sendPacket(std::move(packet), domainHandler.getSockAddr());
}
void OctreeServer::handleOctreeDataFileReply(QSharedPointer<ReceivedMessage> message) {
if (_state != OctreeServerState::WaitingForOctreeDataNegotation) {
qCWarning(octree_server) << "Server received ocree data file reply but is not currently negotiating.";
return;
}
bool includesNewData;
message->readPrimitive(&includesNewData);
QByteArray replaceData;
if (includesNewData) {
replaceData = message->readAll();
qDebug() << "Got reply to octree data file request, new data sent";
} else {
qDebug() << "Got reply to octree data file request, current entity data is sufficient";
OctreeUtils::RawEntityData data;
qCDebug(octree_server) << "Reading octree data from" << _persistAbsoluteFilePath;
if (data.readOctreeDataInfoFromFile(_persistAbsoluteFilePath)) {
if (data.id.isNull()) {
qCDebug(octree_server) << "Current octree data has a null id, updating";
data.resetIdAndVersion();
QFile file(_persistAbsoluteFilePath);
if (file.open(QIODevice::WriteOnly)) {
auto entityData = data.toGzippedByteArray();
file.write(entityData);
file.close();
} else {
qCDebug(octree_server) << "Failed to update octree data";
}
}
}
}
_state = OctreeServerState::Running;
beginRunning(replaceData);
}
void OctreeServer::beginRunning(QByteArray replaceData) {
if (_state != OctreeServerState::Running) {
qCWarning(octree_server) << "Server is not running";
return;
}
auto nodeList = DependencyManager::get<NodeList>();
// we need to ask the DS about agents so we can ping/reply with them
nodeList->addSetOfNodeTypesToNodeInterestSet({ NodeType::Agent, NodeType::EntityScriptServer });
beforeRun(); // after payload has been processed
connect(nodeList.data(), SIGNAL(nodeAdded(SharedNodePointer)), SLOT(nodeAdded(SharedNodePointer)));
connect(nodeList.data(), SIGNAL(nodeKilled(SharedNodePointer)), SLOT(nodeKilled(SharedNodePointer)));
#ifndef WIN32
setvbuf(stdout, NULL, _IOLBF, 0);
#endif
nodeList->linkedDataCreateCallback = [this](Node* node) {
auto queryNodeData = createOctreeQueryNode();
queryNodeData->init();
node->setLinkedData(std::move(queryNodeData));
};
srand((unsigned)time(0));
// if we want Persistence, set up the local file and persist thread
if (_wantPersist) {
static const QString ENTITY_PERSIST_EXTENSION = ".json.gz";
@ -1288,40 +1183,40 @@ void OctreeServer::beginRunning(QByteArray replaceData) {
}
auto persistFileDirectory = QFileInfo(_persistAbsoluteFilePath).absolutePath();
if (_backupDirectoryPath.isEmpty()) {
// Use the persist file's directory to store backups
_backupDirectoryPath = persistFileDirectory;
} else {
// The backup directory has been set.
// If relative, make it relative to the entities directory in the application data directory
// If absolute, no resolution is necessary
QDir backupDirectory { _backupDirectoryPath };
QString absoluteBackupDirectory;
if (backupDirectory.isRelative()) {
absoluteBackupDirectory = QDir(PathUtils::getAppDataFilePath("entities/")).absoluteFilePath(_backupDirectoryPath);
absoluteBackupDirectory = QDir(absoluteBackupDirectory).absolutePath();
} else {
absoluteBackupDirectory = backupDirectory.absolutePath();
}
backupDirectory = QDir(absoluteBackupDirectory);
if (!backupDirectory.exists()) {
if (backupDirectory.mkpath(".")) {
qDebug() << "Created backup directory";
} else {
qDebug() << "ERROR creating backup directory, using persist file directory";
_backupDirectoryPath = persistFileDirectory;
}
} else {
_backupDirectoryPath = absoluteBackupDirectory;
}
}
qDebug() << "Backups will be stored in: " << _backupDirectoryPath;
// now set up PersistThread
_persistThread = new OctreePersistThread(_tree, _persistAbsoluteFilePath, _backupDirectoryPath, _persistInterval,
_wantBackup, _settings, _debugTimestampNow, _persistAsFileType, replaceData);
_persistThread->initialize(true);
_persistManager = new OctreePersistThread(_tree, _persistAbsoluteFilePath, _persistInterval, _debugTimestampNow,
_persistAsFileType);
_persistManager->moveToThread(&_persistThread);
connect(&_persistThread, &QThread::finished, _persistManager, &QObject::deleteLater);
connect(&_persistThread, &QThread::started, _persistManager, &OctreePersistThread::start);
connect(_persistManager, &OctreePersistThread::loadCompleted, this, [this]() {
beginRunning();
});
_persistThread.start();
} else {
beginRunning();
}
}
void OctreeServer::beginRunning() {
auto nodeList = DependencyManager::get<NodeList>();
// we need to ask the DS about agents so we can ping/reply with them
nodeList->addSetOfNodeTypesToNodeInterestSet({ NodeType::Agent, NodeType::EntityScriptServer });
beforeRun(); // after payload has been processed
connect(nodeList.data(), &NodeList::nodeAdded, this, &OctreeServer::nodeAdded);
connect(nodeList.data(), &NodeList::nodeKilled, this, &OctreeServer::nodeKilled);
nodeList->linkedDataCreateCallback = [this](Node* node) {
auto queryNodeData = createOctreeQueryNode();
queryNodeData->init();
node->setLinkedData(std::move(queryNodeData));
};
srand((unsigned)time(0));
// set up our OctreeServerPacketProcessor
_octreeInboundPacketProcessor = new OctreeInboundPacketProcessor(this);
@ -1384,7 +1279,7 @@ void OctreeServer::aboutToFinish() {
qDebug() << qPrintable(_safeServerName) << "inform Octree Inbound Packet Processor that we are shutting down...";
// we're going down - set the NodeList linkedDataCallback to NULL so we do not create any more OctreeQueryNode objects.
// we're going down - set the NodeList linkedDataCallback to nullptr so we do not create any more OctreeQueryNode objects.
// This ensures that we don't get any more newly connecting nodes
DependencyManager::get<NodeList>()->linkedDataCreateCallback = nullptr;
@ -1402,9 +1297,8 @@ void OctreeServer::aboutToFinish() {
// which waits on the thread to be done before returning
_sendThreads.clear(); // Cleans up all the send threads.
if (_persistThread) {
_persistThread->aboutToFinish();
_persistThread->terminating();
if (_persistManager) {
_persistThread.quit();
}
qDebug() << qPrintable(_safeServerName) << "server ENDING about to finish...";

View file

@ -33,12 +33,6 @@ Q_DECLARE_LOGGING_CATEGORY(octree_server)
const int DEFAULT_PACKETS_PER_INTERVAL = 2000; // some 120,000 packets per second total
enum class OctreeServerState {
WaitingForDomainSettings,
WaitingForOctreeDataNegotation,
Running
};
/// Handles assignments of type OctreeServer - sending octrees to various clients.
class OctreeServer : public ThreadedAssignment, public HTTPRequestHandler {
Q_OBJECT
@ -46,8 +40,6 @@ public:
OctreeServer(ReceivedMessage& message);
~OctreeServer();
OctreeServerState _state { OctreeServerState::WaitingForDomainSettings };
/// allows setting of run arguments
void setArguments(int argc, char** argv);
@ -68,12 +60,12 @@ public:
static void clientConnected() { _clientCount++; }
static void clientDisconnected() { _clientCount--; }
bool isInitialLoadComplete() const { return (_persistThread) ? _persistThread->isInitialLoadComplete() : true; }
bool isPersistEnabled() const { return (_persistThread) ? true : false; }
quint64 getLoadElapsedTime() const { return (_persistThread) ? _persistThread->getLoadElapsedTime() : 0; }
QString getPersistFilename() const { return (_persistThread) ? _persistThread->getPersistFilename() : ""; }
QString getPersistFileMimeType() const { return (_persistThread) ? _persistThread->getPersistFileMimeType() : "text/plain"; }
QByteArray getPersistFileContents() const { return (_persistThread) ? _persistThread->getPersistFileContents() : QByteArray(); }
bool isInitialLoadComplete() const { return (_persistManager) ? _persistManager->isInitialLoadComplete() : true; }
bool isPersistEnabled() const { return (_persistManager) ? true : false; }
quint64 getLoadElapsedTime() const { return (_persistManager) ? _persistManager->getLoadElapsedTime() : 0; }
QString getPersistFilename() const { return (_persistManager) ? _persistManager->getPersistFilename() : ""; }
QString getPersistFileMimeType() const { return (_persistManager) ? _persistManager->getPersistFileMimeType() : "text/plain"; }
QByteArray getPersistFileContents() const { return (_persistManager) ? _persistManager->getPersistFileContents() : QByteArray(); }
// Subclasses must implement these methods
virtual std::unique_ptr<OctreeQueryNode> createOctreeQueryNode() = 0;
@ -149,7 +141,6 @@ private slots:
void domainSettingsRequestComplete();
void handleOctreeQueryPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer senderNode);
void handleOctreeDataNackPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer senderNode);
void handleOctreeDataFileReply(QSharedPointer<ReceivedMessage> message);
void removeSendThread();
protected:
@ -171,7 +162,7 @@ protected:
QString getConfiguration();
QString getStatusLink();
void beginRunning(QByteArray replaceData);
void beginRunning();
UniqueSendThread createSendThread(const SharedNodePointer& node);
virtual UniqueSendThread newSendThread(const SharedNodePointer& node) = 0;
@ -190,7 +181,6 @@ protected:
QString _persistFilePath;
QString _persistAbsoluteFilePath;
QString _persistAsFileType;
QString _backupDirectoryPath;
int _packetsPerClientPerInterval;
int _packetsTotalPerInterval;
OctreePointer _tree; // this IS a reaveraging tree
@ -200,13 +190,11 @@ protected:
bool _debugTimestampNow;
bool _verboseDebug;
OctreeInboundPacketProcessor* _octreeInboundPacketProcessor;
OctreePersistThread* _persistThread;
OctreePersistThread* _persistManager;
QThread _persistThread;
int _persistInterval;
bool _wantBackup;
std::chrono::milliseconds _persistInterval;
bool _persistFileDownload;
QString _backupExtensionFormat;
int _backupInterval;
int _maxBackupVersions;
time_t _started;

View file

@ -58,6 +58,7 @@ EntityScriptServer::EntityScriptServer(ReceivedMessage& message) : ThreadedAssig
DependencyManager::get<EntityScriptingInterface>()->setPacketSender(&_entityEditSender);
DependencyManager::set<ResourceManager>();
DependencyManager::set<PluginManager>();
DependencyManager::registerInheritance<SpatialParentFinder, AssignmentParentFinder>();
@ -68,9 +69,6 @@ EntityScriptServer::EntityScriptServer(ReceivedMessage& message) : ThreadedAssig
DependencyManager::set<AudioInjectorManager>();
DependencyManager::set<ScriptCache>();
DependencyManager::set<ScriptEngines>(ScriptEngine::ENTITY_SERVER_SCRIPT);
DependencyManager::set<EntityScriptServerServices>();
// Needed to ensure the creation of the DebugDraw instance on the main thread
@ -253,6 +251,9 @@ void EntityScriptServer::handleEntityScriptCallMethodPacket(QSharedPointer<Recei
void EntityScriptServer::run() {
DependencyManager::set<ScriptEngines>(ScriptEngine::ENTITY_SERVER_SCRIPT);
DependencyManager::set<EntityScriptServerServices>();
// make sure we request our script once the agent connects to the domain
auto nodeList = DependencyManager::get<NodeList>();
@ -570,8 +571,12 @@ void EntityScriptServer::aboutToFinish() {
entityScriptingInterface->setPacketSender(nullptr);
}
DependencyManager::destroy<AssignmentParentFinder>();
DependencyManager::get<ResourceManager>()->cleanup();
DependencyManager::destroy<PluginManager>();
// cleanup the AudioInjectorManager (and any still running injectors)
DependencyManager::destroy<AudioInjectorManager>();
DependencyManager::destroy<ScriptEngines>();

View file

@ -66,6 +66,13 @@ elseif ((NOT MSVC12) AND (NOT MSVC14))
endif()
endif ()
if (CMAKE_GENERATOR STREQUAL "Xcode")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g")
set(CMAKE_XCODE_ATTRIBUTE_GCC_GENERATE_DEBUGGING_SYMBOLS[variant=Release] "YES")
set(CMAKE_XCODE_ATTRIBUTE_DEBUG_INFORMATION_FORMAT[variant=Release] "dwarf-with-dsym")
set(CMAKE_XCODE_ATTRIBUTE_DEPLOYMENT_POSTPROCESSING[variant=Release] "YES")
endif()
if (APPLE)
set(CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LANGUAGE_STANDARD "c++11")
set(CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LIBRARY "libc++")

View file

@ -3,7 +3,7 @@ set(EXTERNAL_NAME GifCreator)
include(ExternalProject)
ExternalProject_Add(
${EXTERNAL_NAME}
URL https://hifi-public.s3.amazonaws.com/dependencies/GifCreator.zip
URL https://public.highfidelity.com/dependencies/GifCreator.zip
URL_MD5 8ac8ef5196f47c658dce784df5ecdb70
CONFIGURE_COMMAND ""
BUILD_COMMAND ""

View file

@ -17,7 +17,7 @@ if (WIN32)
ExternalProject_Add(
${EXTERNAL_NAME}
URL http://hifi-public.s3.amazonaws.com/dependencies/ovr_sdk_win_1.26.0_public.zip
URL https://public.highfidelity.com/dependencies/ovr_sdk_win_1.26.0_public.zip
URL_MD5 06804ff9727b910dcd04a37c800053b5
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR>
PATCH_COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_SOURCE_DIR}/LibOVRCMakeLists.txt" <SOURCE_DIR>/CMakeLists.txt
@ -38,7 +38,7 @@ elseif(APPLE)
ExternalProject_Add(
${EXTERNAL_NAME}
URL http://static.oculus.com/sdk-downloads/ovr_sdk_macos_0.5.0.1.tar.gz
URL https://public.highfidelity.com/dependencies/ovr_sdk_macos_0.5.0.1.tar.gz
URL_MD5 0a0785a04fb285f64f62267388344ad6
CONFIGURE_COMMAND ""
BUILD_COMMAND ""

View file

@ -9,7 +9,7 @@ if (WIN32)
ExternalProject_Add(
${EXTERNAL_NAME}
URL http://hifi-public.s3.amazonaws.com/dependencies/OVRPlatformSDK_v1.10.0.zip
URL https://public.highfidelity.com/dependencies/OVRPlatformSDK_v1.10.0.zip
URL_MD5 e6c8264af16d904e6506acd5172fa0a9
CONFIGURE_COMMAND ""
BUILD_COMMAND ""

View file

@ -5,7 +5,7 @@ include(ExternalProject)
ExternalProject_Add(
${EXTERNAL_NAME}
#URL https://github.com/boostorg/config/archive/boost-1.58.0.zip
URL http://hifi-public.s3.amazonaws.com/dependencies/config-boost-1.58.0.zip
URL https://public.highfidelity.com/dependencies/config-boost-1.58.0.zip
URL_MD5 42fa673bae2b7645a22736445e80eb8d
CONFIGURE_COMMAND ""
BUILD_COMMAND ""

View file

@ -17,7 +17,7 @@ include(ExternalProject)
if (WIN32)
ExternalProject_Add(
${EXTERNAL_NAME}
URL http://hifi-public.s3.amazonaws.com/dependencies/bullet-2.88.tgz
URL https://public.highfidelity.com/dependencies/bullet-2.88.tgz
URL_MD5 0a6876607ebe83e227427215f15946fd
CMAKE_ARGS ${PLATFORM_CMAKE_ARGS} -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR> -DBUILD_EXTRAS=0 -DINSTALL_LIBS=1 -DBUILD_BULLET3=0 -DBUILD_OPENGL3_DEMOS=0 -DBUILD_BULLET2_DEMOS=0 -DBUILD_UNIT_TESTS=0 -DUSE_GLUT=0 -DUSE_DX11=0
LOG_DOWNLOAD 1
@ -28,7 +28,7 @@ if (WIN32)
else ()
ExternalProject_Add(
${EXTERNAL_NAME}
URL http://hifi-public.s3.amazonaws.com/dependencies/bullet-2.88.tgz
URL https://public.highfidelity.com/dependencies/bullet-2.88.tgz
URL_MD5 0a6876607ebe83e227427215f15946fd
CMAKE_ARGS ${PLATFORM_CMAKE_ARGS} -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR> -DBUILD_EXTRAS=0 -DINSTALL_LIBS=1 -DBUILD_BULLET3=0 -DBUILD_OPENGL3_DEMOS=0 -DBUILD_BULLET2_DEMOS=0 -DBUILD_UNIT_TESTS=0 -DUSE_GLUT=0
LOG_DOWNLOAD 1

View file

@ -6,7 +6,7 @@ string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER)
if (WIN32)
ExternalProject_Add(
${EXTERNAL_NAME}
URL http://public.highfidelity.com/dependencies/crashpad_062317.1.zip
URL https://public.highfidelity.com/dependencies/crashpad_062317.1.zip
URL_MD5 9c84b77f5f23daf939da1371825ed2b1
CONFIGURE_COMMAND ""
BUILD_COMMAND ""
@ -16,19 +16,46 @@ if (WIN32)
ExternalProject_Get_Property(${EXTERNAL_NAME} SOURCE_DIR)
set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${SOURCE_DIR}/include CACHE PATH "List of Crashpad include directories")
set(BIN_RELEASE_PATH "${SOURCE_DIR}/out/Release_x64")
set(BIN_EXT ".exe")
set(LIB_RELEASE_PATH "${SOURCE_DIR}/out/Release_x64/lib_MD")
set(LIB_DEBUG_PATH "${SOURCE_DIR}/out/Debug_x64/lib_MD")
set(LIB_PREFIX "")
set(LIB_EXT "lib")
elseif (APPLE)
ExternalProject_Add(
${EXTERNAL_NAME}
URL https://public.highfidelity.com/dependencies/crashpad_mac_070318.zip
URL_MD5 ba1501dc163591ac2d1be74946967e2a
CONFIGURE_COMMAND ""
BUILD_COMMAND ""
INSTALL_COMMAND ""
LOG_DOWNLOAD 1
)
set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${SOURCE_DIR}/out/Release_x64/lib_MD/${LIB_PREFIX}crashpad_client.${LIB_EXT} CACHE FILEPATH "Path to Crashpad release library")
set(${EXTERNAL_NAME_UPPER}_BASE_LIBRARY_RELEASE ${SOURCE_DIR}/out/Release_x64/lib_MD/${LIB_PREFIX}base.${LIB_EXT} CACHE FILEPATH "Path to Crashpad base release library")
set(${EXTERNAL_NAME_UPPER}_UTIL_LIBRARY_RELEASE ${SOURCE_DIR}/out/Release_x64/lib_MD/${LIB_PREFIX}crashpad_util.${LIB_EXT} CACHE FILEPATH "Path to Crashpad util release library")
ExternalProject_Get_Property(${EXTERNAL_NAME} SOURCE_DIR)
set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG ${SOURCE_DIR}/out/Debug_x64/lib_MD/${LIB_PREFIX}crashpad_client.${LIB_EXT} CACHE FILEPATH "Path to Crashpad debug library")
set(${EXTERNAL_NAME_UPPER}_BASE_LIBRARY_DEBUG ${SOURCE_DIR}/out/Debug_x64/lib_MD/${LIB_PREFIX}base.${LIB_EXT} CACHE FILEPATH "Path to Crashpad base debug library")
set(${EXTERNAL_NAME_UPPER}_UTIL_LIBRARY_DEBUG ${SOURCE_DIR}/out/Debug_x64/lib_MD/${LIB_PREFIX}crashpad_util.${LIB_EXT} CACHE FILEPATH "Path to Crashpad util debug library")
set(BIN_RELEASE_PATH "${SOURCE_DIR}/out/Release")
set(BIN_EXT "")
set(LIB_RELEASE_PATH "${SOURCE_DIR}/out/Release/lib")
set(LIB_DEBUG_PATH "${SOURCE_DIR}/out/Debug/lib")
set(LIB_PREFIX "lib")
set(LIB_EXT "a")
endif ()
set(CRASHPAD_HANDLER_EXE_PATH ${SOURCE_DIR}/out/Release_x64/crashpad_handler.exe CACHE FILEPATH "Path to the Crashpad handler executable")
if (WIN32 OR APPLE)
set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${SOURCE_DIR}/include CACHE PATH "List of Crashpad include directories")
set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${LIB_RELEASE_PATH}/${LIB_PREFIX}crashpad_client.${LIB_EXT} CACHE FILEPATH "Path to Crashpad release library")
set(${EXTERNAL_NAME_UPPER}_BASE_LIBRARY_RELEASE ${LIB_RELEASE_PATH}/${LIB_PREFIX}base.${LIB_EXT} CACHE FILEPATH "Path to Crashpad base release library")
set(${EXTERNAL_NAME_UPPER}_UTIL_LIBRARY_RELEASE ${LIB_RELEASE_PATH}/${LIB_PREFIX}crashpad_util.${LIB_EXT} CACHE FILEPATH "Path to Crashpad util release library")
set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG ${LIB_DEBUG_PATH}/${LIB_PREFIX}crashpad_client.${LIB_EXT} CACHE FILEPATH "Path to Crashpad debug library")
set(${EXTERNAL_NAME_UPPER}_BASE_LIBRARY_DEBUG ${LIB_DEBUG_PATH}/${LIB_PREFIX}base.${LIB_EXT} CACHE FILEPATH "Path to Crashpad base debug library")
set(${EXTERNAL_NAME_UPPER}_UTIL_LIBRARY_DEBUG ${LIB_DEBUG_PATH}/${LIB_PREFIX}crashpad_util.${LIB_EXT} CACHE FILEPATH "Path to Crashpad util debug library")
set(CRASHPAD_HANDLER_EXE_PATH ${BIN_RELEASE_PATH}/crashpad_handler${BIN_EXT} CACHE FILEPATH "Path to the Crashpad handler binary")
endif ()
# Hide this external target (for ide users)

View file

@ -11,7 +11,7 @@ endif ()
include(ExternalProject)
ExternalProject_Add(
${EXTERNAL_NAME}
URL http://hifi-public.s3.amazonaws.com/dependencies/draco-1.1.0.zip
URL https://public.highfidelity.com/dependencies/draco-1.1.0.zip
URL_MD5 208f8b04c91d5f1c73d731a3ea37c5bb
CONFIGURE_COMMAND CMAKE_ARGS ${ANDROID_CMAKE_ARGS} -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR>-$<CONFIG> ${EXTRA_CMAKE_FLAGS}
LOG_DOWNLOAD 1

View file

@ -15,7 +15,7 @@ include(ExternalProject)
# that would override CMAKE_CXX_FLAGS
ExternalProject_Add(
${EXTERNAL_NAME}
URL https://hifi-public.s3.amazonaws.com/dependencies/etc2comp-patched.zip
URL https://public.highfidelity.com/dependencies/etc2comp-patched.zip
URL_MD5 4c96153eb179acbe619e3d99d3330595
CMAKE_ARGS ${ANDROID_CMAKE_ARGS} ${EXTRA_CMAKE_FLAGS}
BINARY_DIR ${EXTERNAL_PROJECT_PREFIX}/build
@ -33,23 +33,26 @@ ExternalProject_Get_Property(${EXTERNAL_NAME} INSTALL_DIR)
string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER)
if (WIN32)
set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG ${INSTALL_DIR}/build/EtcLib/Debug/EtcLib.lib CACHE FILEPATH "Path to Etc2Comp debug library")
if (WIN32 OR APPLE)
if (WIN32)
set(_LIB_FILE "EtcLib.lib")
else ()
set(_LIB_FILE "libEtcLib.a")
endif ()
set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG ${INSTALL_DIR}/build/EtcLib/Debug/${_LIB_FILE} CACHE FILEPATH "Path to Etc2Comp debug library")
# use generator expression to ensure the correct library is found when building different configurations in VS
set(_LIB_FOLDER "$<$<CONFIG:RelWithDebInfo>:build/EtcLib/RelWithDebInfo>")
set(_LIB_FOLDER "${_LIB_FOLDER}$<$<CONFIG:MinSizeRel>:build/EtcLib/MinSizeRel>")
set(_LIB_FOLDER "${_LIB_FOLDER}$<$<OR:$<CONFIG:Release>,$<CONFIG:Debug>>:build/EtcLib/Release>")
set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${INSTALL_DIR}/${_LIB_FOLDER}/EtcLib.lib CACHE FILEPATH "Path to Etc2Comp release library")
elseif (APPLE)
set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG ${INSTALL_DIR}/build/EtcLib/Debug/libEtcLib.a CACHE FILEPATH "Path to EtcLib debug library")
set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${INSTALL_DIR}/build/EtcLib/Release/libEtcLib.a CACHE FILEPATH "Path to EtcLib release library")
set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${INSTALL_DIR}/${_LIB_FOLDER}/${_LIB_FILE} CACHE FILEPATH "Path to Etc2Comp release library")
else ()
set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG "" CACHE FILEPATH "Path to EtcLib debug library")
set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${INSTALL_DIR}/build/EtcLib/libEtcLib.a CACHE FILEPATH "Path to EtcLib release library")
endif ()
set(ETC_INCLUDE_DIR ${SOURCE_DIR}/EtcLib/Etc CACHE FILEPATH "Path to Etc2Comp/Etc include directory")
set(ETCCODEC_INCLUDE_DIR ${SOURCE_DIR}/EtcLib/EtcCodec CACHE FILEPATH "Path to Etc2Comp/EtcCodec include directory")
# ETC2COMP_INCLUDE_DIRS will be set later by FindEtc2Comp
# ETC2COMP_INCLUDE_DIRS will be set later by FindEtc2Comp

View file

@ -5,7 +5,7 @@ include(SelectLibraryConfigurations)
ExternalProject_Add(
${EXTERNAL_NAME}
URL https://hifi-public.s3.amazonaws.com/austin/glad/glad32es.zip
URL https://public.highfidelity.com/dependencies/glad/glad32es.zip
URL_MD5 6a641d8c49dee4c895fa59315f5682a6
CONFIGURE_COMMAND CMAKE_ARGS -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR> -DCMAKE_POSITION_INDEPENDENT_CODE=ON
LOG_DOWNLOAD 1

View file

@ -5,7 +5,7 @@ include(SelectLibraryConfigurations)
ExternalProject_Add(
${EXTERNAL_NAME}
URL https://hifi-public.s3.amazonaws.com/austin/glad/glad41.zip
URL https://public.highfidelity.com/dependencies/glad/glad41.zip
URL_MD5 1324eeec33abe91e67d19ae551ba624d
CONFIGURE_COMMAND CMAKE_ARGS -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR> -DCMAKE_POSITION_INDEPENDENT_CODE=ON
LOG_DOWNLOAD 1

View file

@ -5,7 +5,7 @@ include(SelectLibraryConfigurations)
ExternalProject_Add(
${EXTERNAL_NAME}
URL https://hifi-public.s3.amazonaws.com/austin/glad/glad45.zip
URL https://public.highfidelity.com/dependencies/glad/glad45.zip
URL_MD5 cfb19b3cb5b2f8f1d1669fb3150e5f05
CONFIGURE_COMMAND CMAKE_ARGS -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR> -DCMAKE_POSITION_INDEPENDENT_CODE=ON
LOG_DOWNLOAD 1

View file

@ -3,7 +3,7 @@ set(EXTERNAL_NAME gli)
include(ExternalProject)
ExternalProject_Add(
${EXTERNAL_NAME}
URL https://hifi-public.s3.amazonaws.com/dependencies/gli-0.8.1.0.zip
URL https://public.highfidelity.com/dependencies/gli-0.8.1.0.zip
URL_MD5 00c990f59c12bbf367956ef399d6f798
BINARY_DIR ${EXTERNAL_PROJECT_PREFIX}/build
CONFIGURE_COMMAND ""

View file

@ -3,7 +3,7 @@ set(EXTERNAL_NAME glm)
include(ExternalProject)
ExternalProject_Add(
${EXTERNAL_NAME}
URL https://hifi-public.s3.amazonaws.com/dependencies/glm-0.9.8.5-patched.zip
URL https://public.highfidelity.com/dependencies/glm-0.9.8.5-patched.zip
URL_MD5 7d39ecc1cea275427534c3cfd6dd63f0
BINARY_DIR ${EXTERNAL_PROJECT_PREFIX}/build
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR> ${EXTERNAL_ARGS}

View file

@ -6,16 +6,16 @@ set(EXTERNAL_NAME hifiAudioCodec)
string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER)
if (WIN32)
set(DOWNLOAD_URL http://s3.amazonaws.com/hifi-public/dependencies/codecSDK-win-2.0.zip)
set(DOWNLOAD_URL https://public.highfidelity.com/dependencies/codecSDK-win-2.0.zip)
set(DOWNLOAD_MD5 9199d4dbd6b16bed736b235efe980e67)
elseif (APPLE)
set(DOWNLOAD_URL http://s3.amazonaws.com/hifi-public/dependencies/codecSDK-mac-2.0.zip)
set(DOWNLOAD_URL https://public.highfidelity.com/dependencies/codecSDK-mac-2.0.zip)
set(DOWNLOAD_MD5 21649881e7d5dc94f922179be96f76ba)
elseif (ANDROID)
set(DOWNLOAD_URL http://s3.amazonaws.com/hifi-public/dependencies/codecSDK-android-2.0.zip)
set(DOWNLOAD_URL https://public.highfidelity.com/dependencies/codecSDK-android-2.0.zip)
set(DOWNLOAD_MD5 aef2a852600d498d58aa586668191683)
elseif (UNIX)
set(DOWNLOAD_URL http://s3.amazonaws.com/hifi-public/dependencies/codecSDK-linux-2.0.zip)
set(DOWNLOAD_URL https://public.highfidelity.com/dependencies/codecSDK-linux-2.0.zip)
set(DOWNLOAD_MD5 67fb7755f9bcafb98a9fceea53bc7481)
else()
return()

View file

@ -4,7 +4,7 @@ set(EXTERNAL_NAME neuron)
string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER)
set(NEURON_URL "https://s3.amazonaws.com/hifi-public/dependencies/neuron_datareader_b.12.2.zip")
set(NEURON_URL "https://public.highfidelity.com/dependencies/neuron_datareader_b.12.2.zip")
set(NEURON_URL_MD5 "84273ad2200bf86a9279d1f412a822ca")
ExternalProject_Add(${EXTERNAL_NAME}

View file

@ -8,7 +8,7 @@ string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER)
if (WIN32)
ExternalProject_Add(
${EXTERNAL_NAME}
URL http://s3.amazonaws.com/hifi-public/dependencies/nvtt-win-2.1.0.hifi.zip
URL https://public.highfidelity.com/dependencies/nvtt-win-2.1.0.hifi.zip
URL_MD5 10da01cf601f88f6dc12a6bc13c89136
CONFIGURE_COMMAND ""
BUILD_COMMAND ""
@ -29,7 +29,7 @@ else ()
ExternalProject_Add(
${EXTERNAL_NAME}
URL http://hifi-public.s3.amazonaws.com/dependencies/nvidia-texture-tools-2.1.0.hifi-83462e4.zip
URL https://public.highfidelity.com/dependencies/nvidia-texture-tools-2.1.0.hifi-83462e4.zip
URL_MD5 602776e08515b54bfa1b8dc455003f0f
CONFIGURE_COMMAND CMAKE_ARGS ${ANDROID_CMAKE_ARGS} -DNVTT_SHARED=1 -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR> -DCMAKE_POSITION_INDEPENDENT_CODE=ON
LOG_DOWNLOAD 1

View file

@ -7,7 +7,7 @@ string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER)
ExternalProject_Add(
${EXTERNAL_NAME}
URL https://github.com/ValveSoftware/openvr/archive/v1.0.6.zip
URL https://public.highfidelity.com/dependencies/openvr-1.0.6.zip
URL_MD5 f6892cd3a3078f505d03b4297f5a1951
CONFIGURE_COMMAND ""
BUILD_COMMAND ""

View file

@ -3,7 +3,7 @@ set(EXTERNAL_NAME polyvox)
include(ExternalProject)
ExternalProject_Add(
${EXTERNAL_NAME}
URL http://hifi-public.s3.amazonaws.com/dependencies/polyvox-master-2015-7-15.zip
URL https://public.highfidelity.com/dependencies/polyvox-master-2015-7-15.zip
URL_MD5 9ec6323b87e849ae36e562ae1c7494a9
CMAKE_ARGS -DENABLE_EXAMPLES=OFF -DENABLE_BINDINGS=OFF -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR>
BINARY_DIR ${EXTERNAL_PROJECT_PREFIX}/build

View file

@ -13,7 +13,7 @@ endif ()
ExternalProject_Add(
${EXTERNAL_NAME}
URL https://hifi-public.s3.amazonaws.com/dependencies/quazip-0.7.3.zip
URL https://public.highfidelity.com/dependencies/quazip-0.7.3.zip
URL_MD5 ed03754d39b9da1775771819b8001d45
BINARY_DIR ${EXTERNAL_PROJECT_PREFIX}/build
CMAKE_ARGS ${QUAZIP_CMAKE_ARGS}

View file

@ -7,7 +7,7 @@ string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER)
if (WIN32)
ExternalProject_Add(
${EXTERNAL_NAME}
URL http://hifi-public.s3.amazonaws.com/dependencies/SDL2-devel-2.0.3-VC.zip
URL https://public.highfidelity.com/dependencies/SDL2-devel-2.0.3-VC.zip
URL_MD5 30a333bcbe94bc5016e8799c73e86233
CONFIGURE_COMMAND ""
BUILD_COMMAND ""
@ -18,7 +18,8 @@ elseif (APPLE)
ExternalProject_Add(
${EXTERNAL_NAME}
URL http://hifi-public.s3.amazonaws.com/dependencies/SDL2-2.0.3.zip
URL https://public.highfidelity.com/dependencies/SDL2-2.0.3.zip
URL_MD5 55f1eae5142d20db11c844d8d4d6deed
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR> -DVIDEO_OPENGL=OFF
BINARY_DIR ${EXTERNAL_PROJECT_PREFIX}/build
LOG_DOWNLOAD 1
@ -49,7 +50,7 @@ else ()
ExternalProject_Add(
${EXTERNAL_NAME}
URL http://www.libsdl.org/release/SDL2-2.0.3.tar.gz
URL https://public.highfidelity.com/dependencies/SDL2-2.0.3.tar.gz
URL_MD5 fe6c61d2e9df9ef570e7e80c6e822537
CMAKE_ARGS ${ANDROID_CMAKE_ARGS} -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR>
LOG_DOWNLOAD 1

View file

@ -4,8 +4,8 @@ set(EXTERNAL_NAME serverless-content)
ExternalProject_Add(
${EXTERNAL_NAME}
URL http://cdn.highfidelity.com/content-sets/serverless-tutorial-RC68.zip
URL_MD5 a068f74d4045e257cfa7926fe6e38ad5
URL http://cdn.highfidelity.com/content-sets/serverless-tutorial-RC69.zip
URL_MD5 e2467b08de069da7e22ec8e032435592
CONFIGURE_COMMAND ""
BUILD_COMMAND ""
INSTALL_COMMAND ""

View file

@ -4,15 +4,15 @@ set(EXTERNAL_NAME sixense)
string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER)
#set(SIXENSE_URL "http://hifi-public.s3.amazonaws.com/dependencies/SixenseSDK_062612.zip")
#set(SIXENSE_URL "https://public.highfidelity.com/dependencies/SixenseSDK_062612.zip")
#set(SIXENSE_URL_MD5 "10cc8dc470d2ac1244a88cf04bc549cc")
#set(SIXENSE_NEW_LAYOUT 0)
set(SIXENSE_URL "http://hifi-public.s3.amazonaws.com/dependencies/SixenseSDK_071615.zip")
set(SIXENSE_URL "https://public.highfidelity.com/dependencies/SixenseSDK_071615.zip")
set(SIXENSE_URL_MD5 "752a3901f334124e9cffc2ba4136ef7d")
set(SIXENSE_NEW_LAYOUT 1)
#set(SIXENSE_URL "http://hifi-public.s3.amazonaws.com/dependencies/SixenseSDK_102215.zip")
#set(SIXENSE_URL "https://public.highfidelity.com/dependencies/SixenseSDK_102215.zip")
#set(SIXENSE_URL_MD5 "93c3a6795cce777a0f472b09532935f1")
#set(SIXENSE_NEW_LAYOUT 1)

View file

@ -4,7 +4,7 @@ set(EXTERNAL_NAME steamworks)
string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER)
set(STEAMWORKS_URL "https://s3.amazonaws.com/hifi-public/dependencies/steamworks_sdk_137.zip")
set(STEAMWORKS_URL "https://public.highfidelity.com/dependencies/steamworks_sdk_137.zip")
set(STEAMWORKS_URL_MD5 "95ba9d0e3ddc04f8a8be17d2da806cbb")
ExternalProject_Add(

View file

@ -3,13 +3,13 @@ set(EXTERNAL_NAME tbb)
include(ExternalProject)
if (WIN32)
set(DOWNLOAD_URL http://hifi-public.s3.amazonaws.com/dependencies/tbb2017_20170604oss_win_slim.zip)
set(DOWNLOAD_URL https://public.highfidelity.com/dependencies/tbb2017_20170604oss_win_slim.zip)
set(DOWNLOAD_MD5 065934458e3db88397f3d10e7eea536c)
elseif (APPLE)
set(DOWNLOAD_URL http://s3.amazonaws.com/hifi-public/dependencies/tbb2017_20170604oss_mac_slim.tar.gz)
set(DOWNLOAD_URL https://public.highfidelity.com/dependencies/tbb2017_20170604oss_mac_slim.tar.gz)
set(DOWNLOAD_MD5 62bde626b396f8e1a85c6a8ded1d8105)
else ()
set(DOWNLOAD_URL http://hifi-public.s3.amazonaws.com/dependencies/tbb2017_20170604oss_lin_slim.tar.gz)
set(DOWNLOAD_URL https://public.highfidelity.com/dependencies/tbb2017_20170604oss_lin_slim.tar.gz)
set(DOWNLOAD_MD5 2a5c721f40fa3503ffc12c18dd00011c)
endif ()

View file

@ -7,7 +7,7 @@ endif ()
include(ExternalProject)
ExternalProject_Add(
${EXTERNAL_NAME}
URL http://hifi-public.s3.amazonaws.com/dependencies/v-hacd-master.zip
URL https://public.highfidelity.com/dependencies/v-hacd-master.zip
URL_MD5 3bfc94f8dd3dfbfe8f4dc088f4820b3e
CMAKE_ARGS ${ANDROID_CMAKE_ARGS} -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR>
BINARY_DIR ${EXTERNAL_PROJECT_PREFIX}/build

View file

@ -6,7 +6,7 @@ if (WIN32)
include(ExternalProject)
ExternalProject_Add(
${EXTERNAL_NAME}
URL http://hifi-public.s3.amazonaws.com/dependencies/qtaudio_wasapi10.zip
URL https://public.highfidelity.com/dependencies/qtaudio_wasapi10.zip
URL_MD5 4f40e49715a420fb67b45b9cee19052c
CONFIGURE_COMMAND ""
BUILD_COMMAND ""

View file

@ -5,7 +5,8 @@ include(ExternalProject)
ExternalProject_Add(
${EXTERNAL_NAME}
URL http://hifi-public.s3.amazonaws.com/dependencies/zlib128.zip
URL https://public.highfidelity.com/dependencies/zlib128.zip
URL_MD5 126f8676442ffbd97884eb4d6f32afb4
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR>
BINARY_DIR ${EXTERNAL_PROJECT_PREFIX}/build
LOG_DOWNLOAD 1

View file

@ -23,7 +23,7 @@ macro(add_crashpad)
set(CMAKE_BACKTRACE_TOKEN $ENV{CMAKE_BACKTRACE_TOKEN})
endif()
if (WIN32 AND USE_CRASHPAD)
if ((WIN32 OR APPLE) AND USE_CRASHPAD)
get_property(CRASHPAD_CHECKED GLOBAL PROPERTY CHECKED_FOR_CRASHPAD_ONCE)
if (NOT CRASHPAD_CHECKED)
@ -42,6 +42,10 @@ macro(add_crashpad)
if (WIN32)
set_target_properties(${TARGET_NAME} PROPERTIES LINK_FLAGS "/ignore:4099")
elseif (APPLE)
find_library(Security Security)
target_link_libraries(${TARGET_NAME} ${Security})
target_link_libraries(${TARGET_NAME} "-lbsm")
endif()
add_custom_command(

View file

@ -22,7 +22,7 @@ macro(optional_win_executable_signing)
# setup a post build command to sign the executable
add_custom_command(
TARGET ${TARGET_NAME} POST_BUILD
COMMAND ${SIGNTOOL_EXECUTABLE} sign /fd sha256 /f %HF_PFX_FILE% /p %HF_PFX_PASSPHRASE% /tr http://tsa.starfieldtech.com /td SHA256 ${EXECUTABLE_PATH}
COMMAND ${SIGNTOOL_EXECUTABLE} sign /fd sha256 /f %HF_PFX_FILE% /p %HF_PFX_PASSPHRASE% /tr http://sha256timestamp.ws.symantec.com/sha256/timestamp /td SHA256 ${EXECUTABLE_PATH}
)
else ()
message(FATAL_ERROR "HF_PFX_PASSPHRASE must be set for executables to be signed.")

View file

@ -18,6 +18,7 @@ macro(SET_PACKAGING_PARAMETERS)
set(BUILD_GLOBAL_SERVICES "DEVELOPMENT")
set(USE_STABLE_GLOBAL_SERVICES 0)
set(BUILD_NUMBER 0)
set(APP_USER_MODEL_ID "com.highfidelity.sandbox-dev")
set_from_env(RELEASE_TYPE RELEASE_TYPE "DEV")
set_from_env(RELEASE_NUMBER RELEASE_NUMBER "")
@ -89,13 +90,13 @@ macro(SET_PACKAGING_PARAMETERS)
# for the second parent of HEAD (not HEAD) since that is the
# SHA of the commit merged to master for the build
if (PR_BUILD)
set(_GIT_LOG_FORMAT "%p")
set(_GIT_LOG_FORMAT "%p %h")
else ()
set(_GIT_LOG_FORMAT "%h")
endif ()
execute_process(
COMMAND git log -1 --format=${_GIT_LOG_FORMAT}
COMMAND git log -1 --abbrev=7 --format=${_GIT_LOG_FORMAT}
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_VARIABLE _GIT_LOG_OUTPUT
ERROR_VARIABLE _GIT_LOG_ERROR
@ -172,6 +173,7 @@ macro(SET_PACKAGING_PARAMETERS)
if (PRODUCTION_BUILD)
set(INTERFACE_SHORTCUT_NAME "High Fidelity Interface")
set(CONSOLE_SHORTCUT_NAME "Sandbox")
set(APP_USER_MODEL_ID "com.highfidelity.sandbox")
else ()
set(INTERFACE_SHORTCUT_NAME "High Fidelity Interface - ${BUILD_VERSION_NO_SHA}")
set(CONSOLE_SHORTCUT_NAME "Sandbox - ${BUILD_VERSION_NO_SHA}")

View file

@ -0,0 +1,22 @@
#
# Copyright 2018 High Fidelity, Inc.
# Created by Gabriel Calero & Cristian Duarte on 2018/03/13
#
# Distributed under the Apache License, Version 2.0.
# See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
#
macro(TARGET_BREAKPAD)
if (ANDROID)
set(INSTALL_DIR ${HIFI_ANDROID_PRECOMPILED}/breakpad)
set(BREAKPAD_INCLUDE_DIRS "${INSTALL_DIR}/include" CACHE TYPE INTERNAL)
set(LIB_DIR ${INSTALL_DIR}/lib)
list(APPEND BREAKPAD_LIBRARIES ${LIB_DIR}/libbreakpad_client.a)
target_include_directories(${TARGET_NAME} SYSTEM PRIVATE ${BREAKPAD_INCLUDE_DIRS})
if (USE_BREAKPAD)
add_definitions(-DHAS_BREAKPAD)
endif()
endif()
target_link_libraries(${TARGET_NAME} ${BREAKPAD_LIBRARIES})
endmacro()

View file

@ -49,3 +49,4 @@ set(ADD_REMOVE_ICON_PATH "@ADD_REMOVE_ICON_PATH@")
set(SERVER_COMPONENT_CONDITIONAL "@SERVER_COMPONENT_CONDITIONAL@")
set(CLIENT_COMPONENT_CONDITIONAL "@CLIENT_COMPONENT_CONDITIONAL@")
set(INSTALLER_TYPE "@INSTALLER_TYPE@")
set(APP_USER_MODEL_ID "@APP_USER_MODEL_ID@")

View file

@ -130,7 +130,7 @@
; The Inner invocation has written an uninstaller binary for us.
; We need to sign it if it's a production or PR build.
!if @PRODUCTION_BUILD@ == 1
!system '"@SIGNTOOL_EXECUTABLE@" sign /fd sha256 /f %HF_PFX_FILE% /p %HF_PFX_PASSPHRASE% /tr http://tsa.starfieldtech.com /td SHA256 $%TEMP%\@UNINSTALLER_NAME@' = 0
!system '"@SIGNTOOL_EXECUTABLE@" sign /fd sha256 /f %HF_PFX_FILE% /p %HF_PFX_PASSPHRASE% /tr http://sha256timestamp.ws.symantec.com/sha256/timestamp /td SHA256 $%TEMP%\@UNINSTALLER_NAME@' = 0
!endif
; Good. Now we can carry on writing the real installer.
@ -905,6 +905,8 @@ Function HandlePostInstallOptions
${If} $DesktopServerState == ${BST_CHECKED}
CreateShortCut "$DESKTOP\@CONSOLE_HF_SHORTCUT_NAME@.lnk" "$INSTDIR\@CONSOLE_INSTALL_SUBDIR@\@CONSOLE_WIN_EXEC_NAME@"
!insertmacro WriteInstallOption @CONSOLE_DESKTOP_SHORTCUT_REG_KEY@ YES
; Set appUserModelId
ApplicationID::Set "$DESKTOP\@CONSOLE_HF_SHORTCUT_NAME@.lnk" "@APP_USER_MODEL_ID@"
${Else}
!insertmacro WriteInstallOption @CONSOLE_DESKTOP_SHORTCUT_REG_KEY@ NO
${EndIf}
@ -1162,6 +1164,8 @@ Section "-Core installation"
${If} @SERVER_COMPONENT_CONDITIONAL@
CreateShortCut "$SMPROGRAMS\$STARTMENU_FOLDER\@CONSOLE_SHORTCUT_NAME@.lnk" \
"$INSTDIR\@CONSOLE_INSTALL_SUBDIR@\@CONSOLE_WIN_EXEC_NAME@"
; Set appUserModelId
ApplicationID::Set "$SMPROGRAMS\$STARTMENU_FOLDER\@CONSOLE_SHORTCUT_NAME@.lnk" "@APP_USER_MODEL_ID@"
${EndIf}
CreateShortCut "$SMPROGRAMS\$STARTMENU_FOLDER\Uninstall.lnk" "$INSTDIR\@UNINSTALLER_NAME@"

View file

@ -1,5 +1,8 @@
{
"releaseType": "@RELEASE_TYPE@",
"buildNumber": "@BUILD_NUMBER@",
"stableBuild": "@STABLE_BUILD@",
"buildIdentifier": "@BUILD_VERSION@",
"organization": "@BUILD_ORGANIZATION@"
"organization": "@BUILD_ORGANIZATION@",
"appUserModelId": "@APP_USER_MODEL_ID@"
}

View file

@ -1223,7 +1223,7 @@
"name": "max_avatar_height",
"type": "double",
"label": "Maximum Avatar Height (meters)",
"help": "Limits the scale of avatars in your domain. Cannot be greater than 1755.",
"help": "Limits the height of avatars in your domain. Cannot be greater than 1755.",
"placeholder": 5.2,
"default": 5.2
},

View file

@ -58,7 +58,11 @@ $(document).ready(function(){
}
Settings.handlePostSettings = function(formJSON) {
if (!verifyAvatarHeights()) {
return false;
}
// check if we've set the basic http password
if (formJSON["security"]) {
@ -207,7 +211,7 @@ $(document).ready(function(){
swal({
title: '',
type: 'error',
text: "There was a problem retreiving domain information from High Fidelity API.",
text: "There was a problem retrieving domain information from High Fidelity API.",
confirmButtonText: 'Try again',
showCancelButton: true,
closeOnConfirm: false
@ -288,7 +292,7 @@ $(document).ready(function(){
swal({
title: 'Create new domain ID',
type: 'input',
text: 'Enter a label this machine.</br></br>This will help you identify which domain ID belongs to which machine.</br></br>',
text: 'Enter a label for this machine.</br></br>This will help you identify which domain ID belongs to which machine.</br></br>',
showCancelButton: true,
confirmButtonText: "Create",
closeOnConfirm: false,
@ -669,7 +673,7 @@ $(document).ready(function(){
var spinner = createDomainSpinner();
$('#' + Settings.PLACES_TABLE_ID).after($(spinner));
var errorEl = createDomainLoadingError("There was an error retreiving your places.");
var errorEl = createDomainLoadingError("There was an error retrieving your places.");
$("#" + Settings.PLACES_TABLE_ID).after(errorEl);
// do we have a domain ID?
@ -1091,4 +1095,43 @@ $(document).ready(function(){
$('#settings_backup .panel-body').html(html);
}
function verifyAvatarHeights() {
var errorString = '';
var minAllowedHeight = 0.009;
var maxAllowedHeight = 1755;
var alertCss = { backgroundColor: '#ffa0a0' };
var minHeightElement = $('input[name="avatars.min_avatar_height"]');
var maxHeightElement = $('input[name="avatars.max_avatar_height"]');
var minHeight = Number(minHeightElement.val());
var maxHeight = Number(maxHeightElement.val());
if (maxHeight < minHeight) {
errorString = 'Maximum avatar height must not be less than minimum avatar height<br>';
minHeightElement.css(alertCss);
maxHeightElement.css(alertCss);
};
if (minHeight < minAllowedHeight) {
errorString += 'Minimum avatar height must not be less than ' + minAllowedHeight + '<br>';
minHeightElement.css(alertCss);
}
if (maxHeight > maxAllowedHeight) {
errorString += 'Maximum avatar height must not be greater than ' + maxAllowedHeight + '<br>';
maxHeightElement.css(alertCss);
}
if (errorString.length > 0) {
swal({
type: 'error',
title: '',
text: errorString,
html: true
});
return false;
} else {
return true;
}
}
});

View file

@ -412,7 +412,7 @@ SharedNodePointer DomainGatekeeper::processAgentConnectRequest(const NodeConnect
} else if (verifyUserSignature(username, usernameSignature, nodeConnection.senderSockAddr)) {
// they sent us a username and the signature verifies it
getGroupMemberships(username);
verifiedUsername = username;
verifiedUsername = username.toLower();
} else {
// they sent us a username, but it didn't check out
requestUserPublicKey(username);
@ -660,9 +660,8 @@ void DomainGatekeeper::requestUserPublicKey(const QString& username, bool isOpti
// even if we have a public key for them right now, request a new one in case it has just changed
JSONCallbackParameters callbackParams;
callbackParams.jsonCallbackReceiver = this;
callbackParams.callbackReceiver = this;
callbackParams.jsonCallbackMethod = "publicKeyJSONCallback";
callbackParams.errorCallbackReceiver = this;
callbackParams.errorCallbackMethod = "publicKeyJSONErrorCallback";
@ -675,19 +674,19 @@ void DomainGatekeeper::requestUserPublicKey(const QString& username, bool isOpti
QNetworkAccessManager::GetOperation, callbackParams);
}
QString extractUsernameFromPublicKeyRequest(QNetworkReply& requestReply) {
QString extractUsernameFromPublicKeyRequest(QNetworkReply* requestReply) {
// extract the username from the request url
QString username;
const QString PUBLIC_KEY_URL_REGEX_STRING = "api\\/v1\\/users\\/([A-Za-z0-9_\\.]+)\\/public_key";
QRegExp usernameRegex(PUBLIC_KEY_URL_REGEX_STRING);
if (usernameRegex.indexIn(requestReply.url().toString()) != -1) {
if (usernameRegex.indexIn(requestReply->url().toString()) != -1) {
username = usernameRegex.cap(1);
}
return username.toLower();
}
void DomainGatekeeper::publicKeyJSONCallback(QNetworkReply& requestReply) {
QJsonObject jsonObject = QJsonDocument::fromJson(requestReply.readAll()).object();
void DomainGatekeeper::publicKeyJSONCallback(QNetworkReply* requestReply) {
QJsonObject jsonObject = QJsonDocument::fromJson(requestReply->readAll()).object();
QString username = extractUsernameFromPublicKeyRequest(requestReply);
bool isOptimisticKey = _inFlightPublicKeyRequests.take(username);
@ -707,8 +706,8 @@ void DomainGatekeeper::publicKeyJSONCallback(QNetworkReply& requestReply) {
}
}
void DomainGatekeeper::publicKeyJSONErrorCallback(QNetworkReply& requestReply) {
qDebug() << "publicKey api call failed:" << requestReply.error();
void DomainGatekeeper::publicKeyJSONErrorCallback(QNetworkReply* requestReply) {
qDebug() << "publicKey api call failed:" << requestReply->error();
QString username = extractUsernameFromPublicKeyRequest(requestReply);
_inFlightPublicKeyRequests.remove(username);
}
@ -893,9 +892,8 @@ void DomainGatekeeper::getGroupMemberships(const QString& username) {
JSONCallbackParameters callbackParams;
callbackParams.jsonCallbackReceiver = this;
callbackParams.callbackReceiver = this;
callbackParams.jsonCallbackMethod = "getIsGroupMemberJSONCallback";
callbackParams.errorCallbackReceiver = this;
callbackParams.errorCallbackMethod = "getIsGroupMemberErrorCallback";
const QString GET_IS_GROUP_MEMBER_PATH = "api/v1/groups/members/%2";
@ -906,18 +904,18 @@ void DomainGatekeeper::getGroupMemberships(const QString& username) {
}
QString extractUsernameFromGroupMembershipsReply(QNetworkReply& requestReply) {
QString extractUsernameFromGroupMembershipsReply(QNetworkReply* requestReply) {
// extract the username from the request url
QString username;
const QString GROUP_MEMBERSHIPS_URL_REGEX_STRING = "api\\/v1\\/groups\\/members\\/([A-Za-z0-9_\\.]+)";
QRegExp usernameRegex(GROUP_MEMBERSHIPS_URL_REGEX_STRING);
if (usernameRegex.indexIn(requestReply.url().toString()) != -1) {
if (usernameRegex.indexIn(requestReply->url().toString()) != -1) {
username = usernameRegex.cap(1);
}
return username.toLower();
}
void DomainGatekeeper::getIsGroupMemberJSONCallback(QNetworkReply& requestReply) {
void DomainGatekeeper::getIsGroupMemberJSONCallback(QNetworkReply* requestReply) {
// {
// "data":{
// "username":"sethalves",
@ -934,7 +932,7 @@ void DomainGatekeeper::getIsGroupMemberJSONCallback(QNetworkReply& requestReply)
// "status":"success"
// }
QJsonObject jsonObject = QJsonDocument::fromJson(requestReply.readAll()).object();
QJsonObject jsonObject = QJsonDocument::fromJson(requestReply->readAll()).object();
if (jsonObject["status"].toString() == "success") {
QJsonObject data = jsonObject["data"].toObject();
QJsonObject groups = data["groups"].toObject();
@ -953,16 +951,15 @@ void DomainGatekeeper::getIsGroupMemberJSONCallback(QNetworkReply& requestReply)
_inFlightGroupMembershipsRequests.remove(extractUsernameFromGroupMembershipsReply(requestReply));
}
void DomainGatekeeper::getIsGroupMemberErrorCallback(QNetworkReply& requestReply) {
qDebug() << "getIsGroupMember api call failed:" << requestReply.error();
void DomainGatekeeper::getIsGroupMemberErrorCallback(QNetworkReply* requestReply) {
qDebug() << "getIsGroupMember api call failed:" << requestReply->error();
_inFlightGroupMembershipsRequests.remove(extractUsernameFromGroupMembershipsReply(requestReply));
}
void DomainGatekeeper::getDomainOwnerFriendsList() {
JSONCallbackParameters callbackParams;
callbackParams.jsonCallbackReceiver = this;
callbackParams.callbackReceiver = this;
callbackParams.jsonCallbackMethod = "getDomainOwnerFriendsListJSONCallback";
callbackParams.errorCallbackReceiver = this;
callbackParams.errorCallbackMethod = "getDomainOwnerFriendsListErrorCallback";
const QString GET_FRIENDS_LIST_PATH = "api/v1/user/friends";
@ -974,7 +971,7 @@ void DomainGatekeeper::getDomainOwnerFriendsList() {
}
void DomainGatekeeper::getDomainOwnerFriendsListJSONCallback(QNetworkReply& requestReply) {
void DomainGatekeeper::getDomainOwnerFriendsListJSONCallback(QNetworkReply* requestReply) {
// {
// status: "success",
// data: {
@ -991,20 +988,20 @@ void DomainGatekeeper::getDomainOwnerFriendsListJSONCallback(QNetworkReply& requ
// ]
// }
// }
QJsonObject jsonObject = QJsonDocument::fromJson(requestReply.readAll()).object();
QJsonObject jsonObject = QJsonDocument::fromJson(requestReply->readAll()).object();
if (jsonObject["status"].toString() == "success") {
_domainOwnerFriends.clear();
QJsonArray friends = jsonObject["data"].toObject()["friends"].toArray();
for (int i = 0; i < friends.size(); i++) {
_domainOwnerFriends += friends.at(i).toString();
_domainOwnerFriends += friends.at(i).toString().toLower();
}
} else {
qDebug() << "getDomainOwnerFriendsList api call returned:" << QJsonDocument(jsonObject).toJson(QJsonDocument::Compact);
}
}
void DomainGatekeeper::getDomainOwnerFriendsListErrorCallback(QNetworkReply& requestReply) {
qDebug() << "getDomainOwnerFriendsList api call failed:" << requestReply.error();
void DomainGatekeeper::getDomainOwnerFriendsListErrorCallback(QNetworkReply* requestReply) {
qDebug() << "getDomainOwnerFriendsList api call failed:" << requestReply->error();
}
void DomainGatekeeper::refreshGroupsCache() {

View file

@ -51,14 +51,14 @@ public slots:
void processICEPingReplyPacket(QSharedPointer<ReceivedMessage> message);
void processICEPeerInformationPacket(QSharedPointer<ReceivedMessage> message);
void publicKeyJSONCallback(QNetworkReply& requestReply);
void publicKeyJSONErrorCallback(QNetworkReply& requestReply);
void publicKeyJSONCallback(QNetworkReply* requestReply);
void publicKeyJSONErrorCallback(QNetworkReply* requestReply);
void getIsGroupMemberJSONCallback(QNetworkReply& requestReply);
void getIsGroupMemberErrorCallback(QNetworkReply& requestReply);
void getIsGroupMemberJSONCallback(QNetworkReply* requestReply);
void getIsGroupMemberErrorCallback(QNetworkReply* requestReply);
void getDomainOwnerFriendsListJSONCallback(QNetworkReply& requestReply);
void getDomainOwnerFriendsListErrorCallback(QNetworkReply& requestReply);
void getDomainOwnerFriendsListJSONCallback(QNetworkReply* requestReply);
void getDomainOwnerFriendsListErrorCallback(QNetworkReply* requestReply);
void refreshGroupsCache();

View file

@ -514,13 +514,13 @@ void DomainServer::getTemporaryName(bool force) {
// request a temporary name from the metaverse
auto accountManager = DependencyManager::get<AccountManager>();
JSONCallbackParameters callbackParameters { this, "handleTempDomainSuccess", this, "handleTempDomainError" };
JSONCallbackParameters callbackParameters { this, "handleTempDomainSuccess", "handleTempDomainError" };
accountManager->sendRequest("/api/v1/domains/temporary", AccountManagerAuth::None,
QNetworkAccessManager::PostOperation, callbackParameters);
}
void DomainServer::handleTempDomainSuccess(QNetworkReply& requestReply) {
QJsonObject jsonObject = QJsonDocument::fromJson(requestReply.readAll()).object();
void DomainServer::handleTempDomainSuccess(QNetworkReply* requestReply) {
QJsonObject jsonObject = QJsonDocument::fromJson(requestReply->readAll()).object();
// grab the information for the new domain
static const QString DATA_KEY = "data";
@ -565,7 +565,7 @@ void DomainServer::handleTempDomainSuccess(QNetworkReply& requestReply) {
}
}
void DomainServer::handleTempDomainError(QNetworkReply& requestReply) {
void DomainServer::handleTempDomainError(QNetworkReply* requestReply) {
qWarning() << "A temporary name was requested but there was an error creating one. Please try again via domain-server relaunch"
<< "or from the domain-server settings.";
}
@ -1345,7 +1345,7 @@ void DomainServer::sendPendingTransactionsToServer() {
JSONCallbackParameters transactionCallbackParams;
transactionCallbackParams.jsonCallbackReceiver = this;
transactionCallbackParams.callbackReceiver = this;
transactionCallbackParams.jsonCallbackMethod = "transactionJSONCallback";
while (i != _pendingAssignmentCredits.end()) {
@ -1449,11 +1449,11 @@ void DomainServer::sendHeartbeatToMetaverse(const QString& networkAddress) {
DependencyManager::get<AccountManager>()->sendRequest(DOMAIN_UPDATE.arg(uuidStringWithoutCurlyBraces(getID())),
AccountManagerAuth::Optional,
QNetworkAccessManager::PutOperation,
JSONCallbackParameters(nullptr, QString(), this, "handleMetaverseHeartbeatError"),
JSONCallbackParameters(this, QString(), "handleMetaverseHeartbeatError"),
domainUpdateJSON.toUtf8());
}
void DomainServer::handleMetaverseHeartbeatError(QNetworkReply& requestReply) {
void DomainServer::handleMetaverseHeartbeatError(QNetworkReply* requestReply) {
if (!_metaverseHeartbeatTimer) {
// avoid rehandling errors from the same issue
return;
@ -1462,13 +1462,13 @@ void DomainServer::handleMetaverseHeartbeatError(QNetworkReply& requestReply) {
// only attempt to grab a new temporary name if we're already a temporary domain server
if (_type == MetaverseTemporaryDomain) {
// check if we need to force a new temporary domain name
switch (requestReply.error()) {
switch (requestReply->error()) {
// if we have a temporary domain with a bad token, we get a 401
case QNetworkReply::NetworkError::AuthenticationRequiredError: {
static const QString DATA_KEY = "data";
static const QString TOKEN_KEY = "api_key";
QJsonObject jsonObject = QJsonDocument::fromJson(requestReply.readAll()).object();
QJsonObject jsonObject = QJsonDocument::fromJson(requestReply->readAll()).object();
auto tokenFailure = jsonObject[DATA_KEY].toObject()[TOKEN_KEY];
if (!tokenFailure.isNull()) {
@ -1531,9 +1531,8 @@ void DomainServer::sendICEServerAddressToMetaverseAPI() {
// make sure we hear about failure so we can retry
JSONCallbackParameters callbackParameters;
callbackParameters.errorCallbackReceiver = this;
callbackParameters.callbackReceiver = this;
callbackParameters.errorCallbackMethod = "handleFailedICEServerAddressUpdate";
callbackParameters.jsonCallbackReceiver = this;
callbackParameters.jsonCallbackMethod = "handleSuccessfulICEServerAddressUpdate";
static bool printedIceServerMessage = false;
@ -1552,7 +1551,7 @@ void DomainServer::sendICEServerAddressToMetaverseAPI() {
domainUpdateJSON.toUtf8());
}
void DomainServer::handleSuccessfulICEServerAddressUpdate(QNetworkReply& requestReply) {
void DomainServer::handleSuccessfulICEServerAddressUpdate(QNetworkReply* requestReply) {
_sendICEServerAddressToMetaverseAPIInProgress = false;
if (_sendICEServerAddressToMetaverseAPIRedo) {
qDebug() << "ice-server address updated with metaverse, but has since changed. redoing update...";
@ -1563,7 +1562,7 @@ void DomainServer::handleSuccessfulICEServerAddressUpdate(QNetworkReply& request
}
}
void DomainServer::handleFailedICEServerAddressUpdate(QNetworkReply& requestReply) {
void DomainServer::handleFailedICEServerAddressUpdate(QNetworkReply* requestReply) {
_sendICEServerAddressToMetaverseAPIInProgress = false;
if (_sendICEServerAddressToMetaverseAPIRedo) {
// if we have new data, retry right away, even though the previous attempt didn't go well.
@ -1573,7 +1572,7 @@ void DomainServer::handleFailedICEServerAddressUpdate(QNetworkReply& requestRepl
const int ICE_SERVER_UPDATE_RETRY_MS = 2 * 1000;
qWarning() << "Failed to update ice-server address with High Fidelity Metaverse - error was"
<< requestReply.errorString();
<< requestReply->errorString();
qWarning() << "\tRe-attempting in" << ICE_SERVER_UPDATE_RETRY_MS / 1000 << "seconds";
QTimer::singleShot(ICE_SERVER_UPDATE_RETRY_MS, this, SLOT(sendICEServerAddressToMetaverseAPI()));
@ -1917,14 +1916,16 @@ bool DomainServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url
// don't handle if we don't have a matching node
if (!matchingNode) {
return false;
connection->respond(HTTPConnection::StatusCode404, "Resource not found.");
return true;
}
auto nodeData = static_cast<DomainServerNodeData*>(matchingNode->getLinkedData());
// don't handle if we don't have node data for this node
if (!nodeData) {
return false;
connection->respond(HTTPConnection::StatusCode404, "Resource not found.");
return true;
}
SharedAssignmentPointer matchingAssignment = _allAssignments.value(nodeData->getAssignmentUUID());
@ -1945,7 +1946,8 @@ bool DomainServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url
}
// request not handled
return false;
connection->respond(HTTPConnection::StatusCode404, "Resource not found.");
return true;
}
// check if this is a request for our domain ID

View file

@ -108,10 +108,10 @@ private slots:
void sendHeartbeatToIceServer();
void handleConnectedNode(SharedNodePointer newNode);
void handleTempDomainSuccess(QNetworkReply& requestReply);
void handleTempDomainError(QNetworkReply& requestReply);
void handleTempDomainSuccess(QNetworkReply* requestReply);
void handleTempDomainError(QNetworkReply* requestReply);
void handleMetaverseHeartbeatError(QNetworkReply& requestReply);
void handleMetaverseHeartbeatError(QNetworkReply* requestReply);
void queuedQuit(QString quitMessage, int exitCode);
@ -121,8 +121,8 @@ private slots:
void handleICEHostInfo(const QHostInfo& hostInfo);
void sendICEServerAddressToMetaverseAPI();
void handleSuccessfulICEServerAddressUpdate(QNetworkReply& requestReply);
void handleFailedICEServerAddressUpdate(QNetworkReply& requestReply);
void handleSuccessfulICEServerAddressUpdate(QNetworkReply* requestReply);
void handleFailedICEServerAddressUpdate(QNetworkReply* requestReply);
void updateReplicatedNodes();
void updateDownstreamNodes();

View file

@ -1815,9 +1815,8 @@ void DomainServerSettingsManager::apiRefreshGroupInformation() {
void DomainServerSettingsManager::apiGetGroupID(const QString& groupName) {
JSONCallbackParameters callbackParams;
callbackParams.jsonCallbackReceiver = this;
callbackParams.callbackReceiver = this;
callbackParams.jsonCallbackMethod = "apiGetGroupIDJSONCallback";
callbackParams.errorCallbackReceiver = this;
callbackParams.errorCallbackMethod = "apiGetGroupIDErrorCallback";
const QString GET_GROUP_ID_PATH = "api/v1/groups/names/%1";
@ -1826,7 +1825,7 @@ void DomainServerSettingsManager::apiGetGroupID(const QString& groupName) {
QNetworkAccessManager::GetOperation, callbackParams);
}
void DomainServerSettingsManager::apiGetGroupIDJSONCallback(QNetworkReply& requestReply) {
void DomainServerSettingsManager::apiGetGroupIDJSONCallback(QNetworkReply* requestReply) {
// {
// "data":{
// "groups":[{
@ -1857,7 +1856,7 @@ void DomainServerSettingsManager::apiGetGroupIDJSONCallback(QNetworkReply& reque
// },
// "status":"success"
// }
QJsonObject jsonObject = QJsonDocument::fromJson(requestReply.readAll()).object();
QJsonObject jsonObject = QJsonDocument::fromJson(requestReply->readAll()).object();
if (jsonObject["status"].toString() == "success") {
QJsonArray groups = jsonObject["data"].toObject()["groups"].toArray();
for (int i = 0; i < groups.size(); i++) {
@ -1876,15 +1875,14 @@ void DomainServerSettingsManager::apiGetGroupIDJSONCallback(QNetworkReply& reque
}
}
void DomainServerSettingsManager::apiGetGroupIDErrorCallback(QNetworkReply& requestReply) {
qDebug() << "******************** getGroupID api call failed:" << requestReply.error();
void DomainServerSettingsManager::apiGetGroupIDErrorCallback(QNetworkReply* requestReply) {
qDebug() << "******************** getGroupID api call failed:" << requestReply->error();
}
void DomainServerSettingsManager::apiGetGroupRanks(const QUuid& groupID) {
JSONCallbackParameters callbackParams;
callbackParams.jsonCallbackReceiver = this;
callbackParams.callbackReceiver = this;
callbackParams.jsonCallbackMethod = "apiGetGroupRanksJSONCallback";
callbackParams.errorCallbackReceiver = this;
callbackParams.errorCallbackMethod = "apiGetGroupRanksErrorCallback";
const QString GET_GROUP_RANKS_PATH = "api/v1/groups/%1/ranks";
@ -1893,7 +1891,7 @@ void DomainServerSettingsManager::apiGetGroupRanks(const QUuid& groupID) {
QNetworkAccessManager::GetOperation, callbackParams);
}
void DomainServerSettingsManager::apiGetGroupRanksJSONCallback(QNetworkReply& requestReply) {
void DomainServerSettingsManager::apiGetGroupRanksJSONCallback(QNetworkReply* requestReply) {
// {
// "data":{
// "groups":{
@ -1926,7 +1924,7 @@ void DomainServerSettingsManager::apiGetGroupRanksJSONCallback(QNetworkReply& re
// }
bool changed = false;
QJsonObject jsonObject = QJsonDocument::fromJson(requestReply.readAll()).object();
QJsonObject jsonObject = QJsonDocument::fromJson(requestReply->readAll()).object();
if (jsonObject["status"].toString() == "success") {
QJsonObject groups = jsonObject["data"].toObject()["groups"].toObject();
@ -1972,8 +1970,8 @@ void DomainServerSettingsManager::apiGetGroupRanksJSONCallback(QNetworkReply& re
}
}
void DomainServerSettingsManager::apiGetGroupRanksErrorCallback(QNetworkReply& requestReply) {
qDebug() << "******************** getGroupRanks api call failed:" << requestReply.error();
void DomainServerSettingsManager::apiGetGroupRanksErrorCallback(QNetworkReply* requestReply) {
qDebug() << "******************** getGroupRanks api call failed:" << requestReply->error();
}
void DomainServerSettingsManager::recordGroupMembership(const QString& name, const QUuid groupID, QUuid rankID) {

View file

@ -133,10 +133,10 @@ signals:
void settingsUpdated();
public slots:
void apiGetGroupIDJSONCallback(QNetworkReply& requestReply);
void apiGetGroupIDErrorCallback(QNetworkReply& requestReply);
void apiGetGroupRanksJSONCallback(QNetworkReply& requestReply);
void apiGetGroupRanksErrorCallback(QNetworkReply& requestReply);
void apiGetGroupIDJSONCallback(QNetworkReply* requestReply);
void apiGetGroupIDErrorCallback(QNetworkReply* requestReply);
void apiGetGroupRanksJSONCallback(QNetworkReply* requestReply);
void apiGetGroupRanksErrorCallback(QNetworkReply* requestReply);
private slots:
void processSettingsRequestPacket(QSharedPointer<ReceivedMessage> message);

View file

@ -206,14 +206,13 @@ endif()
# link required hifi libraries
link_hifi_libraries(
shared task octree ktx gpu gl procedural graphics graphics-scripting render
shared workload task octree ktx gpu gl procedural graphics graphics-scripting render
pointers
recording fbx networking model-networking entities avatars trackers
audio audio-client animation script-engine physics
render-utils entities-renderer avatars-renderer ui qml auto-updater midi
controllers plugins image trackers
ui-plugins display-plugins input-plugins
workload
${PLATFORM_GL_BACKEND}
)
@ -226,6 +225,7 @@ target_openssl()
target_bullet()
target_opengl()
add_crashpad()
target_breakpad()
# perform standard include and linking for found externals
foreach(EXTERNAL ${OPTIONAL_EXTERNALS})

View file

@ -566,7 +566,7 @@
},
{
"id": "idleToWalkFwd",
"interpTarget": 3,
"interpTarget": 10,
"interpDuration": 3,
"transitions": [
{ "var": "idleToWalkFwdOnDone", "state": "walkFwd" },
@ -603,8 +603,8 @@
},
{
"id": "walkBwd",
"interpTarget": 6,
"interpDuration": 6,
"interpTarget": 8,
"interpDuration": 2,
"transitions": [
{ "var": "isNotMoving", "state": "idle" },
{ "var": "isMovingForward", "state": "walkFwd" },
@ -621,8 +621,8 @@
},
{
"id": "strafeRight",
"interpTarget": 6,
"interpDuration": 6,
"interpTarget": 20,
"interpDuration": 1,
"transitions": [
{ "var": "isNotMoving", "state": "idle" },
{ "var": "isMovingForward", "state": "walkFwd" },
@ -639,8 +639,8 @@
},
{
"id": "strafeLeft",
"interpTarget": 6,
"interpDuration": 6,
"interpTarget": 20,
"interpDuration": 1,
"transitions": [
{ "var": "isNotMoving", "state": "idle" },
{ "var": "isMovingForward", "state": "walkFwd" },

View file

@ -0,0 +1,777 @@
{
"Anime boy": {
"attachments": [
],
"avatarEntites": [
{
"properties": {
"acceleration": {
"x": 0,
"y": 0,
"z": 0
},
"actionData": "",
"age": 6.915350914001465,
"ageAsText": "0 hours 0 minutes 6 seconds",
"angularDamping": 0.39346998929977417,
"angularVelocity": {
"x": 0,
"y": 0,
"z": 0
},
"animation": {
"allowTranslation": true,
"currentFrame": 0,
"firstFrame": 0,
"fps": 30,
"hold": false,
"lastFrame": 100000,
"loop": true,
"running": false,
"url": ""
},
"boundingBox": {
"brn": {
"x": -0.10961885005235672,
"y": -0.19444090127944946,
"z": -0.15760529041290283
},
"center": {
"x": 2.6226043701171875e-06,
"y": -0.13999652862548828,
"z": -0.04999971389770508
},
"dimensions": {
"x": 0.21924294531345367,
"y": 0.10888873785734177,
"z": 0.2152111530303955
},
"tfl": {
"x": 0.10962409526109695,
"y": -0.0855521634221077,
"z": 0.057605862617492676
}
},
"canCastShadow": true,
"certificateID": "",
"clientOnly": true,
"cloneAvatarEntity": false,
"cloneDynamic": false,
"cloneLifetime": 300,
"cloneLimit": 0,
"cloneOriginID": "{00000000-0000-0000-0000-000000000000}",
"cloneable": false,
"collidesWith": "",
"collisionMask": 0,
"collisionSoundURL": "",
"collisionless": false,
"collisionsWillMove": false,
"compoundShapeURL": "",
"created": "2018-06-06T17:27:53Z",
"damping": 0.39346998929977417,
"density": 1000,
"description": "",
"dimensions": {
"x": 0.21924294531345367,
"y": 0.07768379896879196,
"z": 0.2055898904800415
},
"dynamic": false,
"editionNumber": 15,
"entityInstanceNumber": 0,
"friction": 0.5,
"gravity": {
"x": 0,
"y": 0,
"z": 0
},
"href": "",
"id": "{5d20c775-a0d7-4163-b158-4e0a784a4625}",
"ignoreForCollisions": false,
"itemArtist": "jyoum",
"itemCategories": "Wearables",
"itemDescription": "Wear these, and others will respect your authoritah.",
"itemLicense": "",
"itemName": "Aviators",
"jointRotations": [
],
"jointRotationsSet": [
],
"jointTranslations": [
],
"jointTranslationsSet": [
],
"lastEdited": 1528306178314655,
"lastEditedBy": "{439a2669-4626-487f-9dcf-2d15e77c69a2}",
"lifetime": -1,
"limitedRun": 4294967295,
"localPosition": {
"x": 2.6226043701171875e-06,
"y": -0.13999652862548828,
"z": -0.04999971389770508
},
"localRotation": {
"w": 0.9969173073768616,
"x": -0.07845909893512726,
"y": 0,
"z": 0
},
"locked": false,
"marketplaceID": "40d879ec-93f0-4b4a-8c58-dd6349bdb058",
"modelURL": "http://mpassets.highfidelity.com/40d879ec-93f0-4b4a-8c58-dd6349bdb058-v1/Aviator.fbx",
"name": "",
"naturalDimensions": {
"x": 0.1660931408405304,
"y": 0.05885136127471924,
"z": 0.15574991703033447
},
"naturalPosition": {
"x": 0,
"y": 1.6633577346801758,
"z": 0.048884183168411255
},
"originalTextures": "{\n \"aviator:Eyewear2F\": \"http://mpassets.highfidelity.com/40d879ec-93f0-4b4a-8c58-dd6349bdb058-v1/Aviator.fbx/Aviator.fbm/aviator_Eyewear_Diffuse.png\",\n \"aviator:Eyewear2F1\": \"http://mpassets.highfidelity.com/40d879ec-93f0-4b4a-8c58-dd6349bdb058-v1/Aviator.fbx/Aviator.fbm/aviator_Eyewear_Specular.png\"\n}\n",
"owningAvatarID": "{439a2669-4626-487f-9dcf-2d15e77c69a2}",
"parentID": "{439a2669-4626-487f-9dcf-2d15e77c69a2}",
"parentJointIndex": 66,
"position": {
"x": 2.6226043701171875e-06,
"y": -0.13999652862548828,
"z": -0.04999971389770508
},
"queryAACube": {
"scale": 0.9313028454780579,
"x": -1.4091639518737793,
"y": -10.133878707885742,
"z": 1.9983724355697632
},
"registrationPoint": {
"x": 0.5,
"y": 0.5,
"z": 0.5
},
"relayParentJoints": false,
"renderInfo": {
"drawCalls": 1,
"hasTransparent": false,
"texturesCount": 2,
"texturesSize": 1310720,
"verticesCount": 982
},
"restitution": 0.5,
"rotation": {
"w": 0.9969173073768616,
"x": -0.07845909893512726,
"y": 0,
"z": 0
},
"script": "",
"scriptTimestamp": 0,
"serverScripts": "",
"shapeType": "box",
"staticCertificateVersion": 0,
"textures": "",
"type": "Model",
"userData": "{\"Attachment\":{\"action\":\"attach\",\"joint\":\"HeadTop_End\",\"attached\":false,\"options\":{\"translation\":{\"x\":0,\"y\":0,\"z\":0},\"scale\":1}},\"grabbableKey\":{\"cloneable\":false,\"grabbable\":true}}",
"velocity": {
"x": 0,
"y": 0,
"z": 0
},
"visible": true
}
}
],
"avatarScale": 1,
"avatarUrl": "http://mpassets.highfidelity.com/46e0fd52-3cff-462f-ba97-927338d88295-v1/AnimeBoy2.fst",
"version": 3
},
"Anime girl": {
"attachments": [
],
"avatarEntites": [
{
"properties": {
"acceleration": {
"x": 0,
"y": 0,
"z": 0
},
"actionData": "",
"age": 19.66267967224121,
"ageAsText": "0 hours 0 minutes 19 seconds",
"angularDamping": 0.39346998929977417,
"angularVelocity": {
"x": 0,
"y": 0,
"z": 0
},
"animation": {
"allowTranslation": true,
"currentFrame": 0,
"firstFrame": 0,
"fps": 30,
"hold": false,
"lastFrame": 100000,
"loop": true,
"running": false,
"url": ""
},
"boundingBox": {
"brn": {
"x": -0.10536206513643265,
"y": -0.16647332906723022,
"z": -0.12632352113723755
},
"center": {
"x": 0,
"y": -0.12999999523162842,
"z": -0.030000001192092896
},
"dimensions": {
"x": 0.2107241302728653,
"y": 0.07294666767120361,
"z": 0.1926470398902893
},
"tfl": {
"x": 0.10536206513643265,
"y": -0.09352666139602661,
"z": 0.06632351875305176
}
},
"canCastShadow": true,
"certificateID": "",
"clientOnly": true,
"cloneAvatarEntity": false,
"cloneDynamic": false,
"cloneLifetime": 300,
"cloneLimit": 0,
"cloneOriginID": "{00000000-0000-0000-0000-000000000000}",
"cloneable": false,
"collidesWith": "",
"collisionMask": 0,
"collisionSoundURL": "",
"collisionless": false,
"collisionsWillMove": false,
"compoundShapeURL": "",
"created": "2018-06-05T00:10:37Z",
"damping": 0.39346998929977417,
"density": 1000,
"description": "",
"dimensions": {
"x": 0.2107241302728653,
"y": 0.07294666767120361,
"z": 0.1926470398902893
},
"dynamic": false,
"editionNumber": 5,
"entityInstanceNumber": 0,
"friction": 0.5,
"gravity": {
"x": 0,
"y": 0,
"z": 0
},
"href": "",
"id": "{1586b83a-2af7-4532-9bfb-82fe3f5d5ce9}",
"ignoreForCollisions": false,
"itemArtist": "moam_00",
"itemCategories": "Wearables",
"itemDescription": "Perfect for side-glancin'.",
"itemLicense": "",
"itemName": "Blacker Fem Glasses",
"jointRotations": [
],
"jointRotationsSet": [
],
"jointTranslations": [
],
"jointTranslationsSet": [
],
"lastEdited": 1528157470041658,
"lastEditedBy": "{425df1a8-289b-42fc-819c-c3b2a12d7165}",
"lifetime": -1,
"limitedRun": 4294967295,
"localPosition": {
"x": 0,
"y": -0.12999999523162842,
"z": -0.029999999329447746
},
"localRotation": {
"w": 1,
"x": -2.2351741790771484e-08,
"y": 3.4924596548080444e-10,
"z": 3.725290298461914e-09
},
"locked": false,
"marketplaceID": "06781d12-9139-48f4-ac2a-417dde090981",
"modelURL": "http://mpassets.highfidelity.com/06781d12-9139-48f4-ac2a-417dde090981-v1/FemGlasses03.fbx",
"name": "Female Glasses 3 by Mario Andrade",
"naturalDimensions": {
"x": 0.16209548711776733,
"y": 0.05611282214522362,
"z": 0.14819003641605377
},
"naturalPosition": {
"x": 0,
"y": -7.636845111846924e-08,
"z": 0
},
"originalTextures": "{\n \"file49\": \"http://mpassets.highfidelity.com/06781d12-9139-48f4-ac2a-417dde090981-v1/FemGlasses03.fbx/FemGlasses03.fbm/FemGlasses03Mat_Mixed_AO.jpg\",\n \"file81\": \"http://mpassets.highfidelity.com/06781d12-9139-48f4-ac2a-417dde090981-v1/FemGlasses03.fbx/FemGlasses03.fbm/FemGlasses03Mat_Metallic.jpg\",\n \"file84\": \"http://mpassets.highfidelity.com/06781d12-9139-48f4-ac2a-417dde090981-v1/FemGlasses03.fbx/FemGlasses03.fbm/FemGlasses03Mat_Roughness.jpg\",\n \"file86\": \"http://mpassets.highfidelity.com/06781d12-9139-48f4-ac2a-417dde090981-v1/FemGlasses03.fbx/FemGlasses03.fbm/FemGlasses03Mat_Base_Color.jpg\",\n \"file87\": \"http://mpassets.highfidelity.com/06781d12-9139-48f4-ac2a-417dde090981-v1/FemGlasses03.fbx/FemGlasses03.fbm/FemGlasses03Mat_Normal_DirectX.jpg\"\n}\n",
"owningAvatarID": "{1277f725-fbb4-478b-ae79-1241fd90e508}",
"parentID": "{1277f725-fbb4-478b-ae79-1241fd90e508}",
"parentJointIndex": 66,
"position": {
"x": 0,
"y": -0.12999999523162842,
"z": -0.029999999329447746
},
"queryAACube": {
"scale": 0.8840523958206177,
"x": -2.6587564945220947,
"y": -10.162277221679688,
"z": -0.9548344016075134
},
"registrationPoint": {
"x": 0.5,
"y": 0.5,
"z": 0.5
},
"relayParentJoints": false,
"renderInfo": {
"drawCalls": 1,
"hasTransparent": false,
"texturesCount": 5,
"texturesSize": 0,
"verticesCount": 1156
},
"restitution": 0.5,
"rotation": {
"w": 1,
"x": -2.2351741790771484e-08,
"y": 3.4924596548080444e-10,
"z": 3.725290298461914e-09
},
"script": "",
"scriptTimestamp": 0,
"serverScripts": "",
"shapeType": "box",
"staticCertificateVersion": 0,
"textures": "",
"type": "Model",
"userData": "{\"Attachment\":{\"action\":\"attach\",\"joint\":\"HeadTop_End\",\"attached\":false,\"options\":{\"translation\":{\"x\":0,\"y\":0,\"z\":0},\"scale\":1}},\"grabbableKey\":{\"cloneable\":false,\"grabbable\":true}}",
"velocity": {
"x": 0,
"y": 0,
"z": 0
},
"visible": true
}
}
],
"avatarScale": 1,
"avatarUrl": "http://mpassets.highfidelity.com/0dce3426-55c8-4641-8dd5-d76eb575b64a-v1/Anime_F_Outfit.fst",
"version": 3
},
"Last Legends: Male": {
"attachments": [
],
"avatarEntites": [
{
"properties": {
"acceleration": {
"x": 0,
"y": 0,
"z": 0
},
"actionData": "",
"age": 14.011327743530273,
"ageAsText": "0 hours 0 minutes 14 seconds",
"angularDamping": 0.39346998929977417,
"angularVelocity": {
"x": 0,
"y": 0,
"z": 0
},
"animation": {
"allowTranslation": true,
"currentFrame": 0,
"firstFrame": 0,
"fps": 30,
"hold": false,
"lastFrame": 100000,
"loop": true,
"running": false,
"url": ""
},
"boundingBox": {
"brn": {
"x": -0.20154684782028198,
"y": 0.03644842654466629,
"z": -0.2641940414905548
},
"center": {
"x": -0.030000001192092896,
"y": 0.12999820709228516,
"z": -0.07000023126602173
},
"dimensions": {
"x": 0.3430936932563782,
"y": 0.18709957599639893,
"z": 0.38838762044906616
},
"tfl": {
"x": 0.1415468454360962,
"y": 0.22354799509048462,
"z": 0.12419357895851135
}
},
"canCastShadow": true,
"certificateID": "",
"clientOnly": true,
"cloneAvatarEntity": false,
"cloneDynamic": false,
"cloneLifetime": 300,
"cloneLimit": 0,
"cloneOriginID": "{00000000-0000-0000-0000-000000000000}",
"cloneable": false,
"collidesWith": "",
"collisionMask": 0,
"collisionSoundURL": "",
"collisionless": false,
"collisionsWillMove": false,
"compoundShapeURL": "",
"created": "2018-06-06T17:25:42Z",
"damping": 0.39346998929977417,
"density": 1000,
"description": "",
"dimensions": {
"x": 0.33466479182243347,
"y": 0.16981728374958038,
"z": 0.38838762044906616
},
"dynamic": false,
"editionNumber": 19,
"entityInstanceNumber": 0,
"friction": 0.5,
"gravity": {
"x": 0,
"y": 0,
"z": 0
},
"href": "",
"id": "{6b0a2b08-e8e3-4d43-95cc-dfc4f7a4b0c9}",
"ignoreForCollisions": false,
"itemArtist": "jyoum",
"itemCategories": "Wearables",
"itemDescription": "A stylish and classic piece of headwear for your avatar.",
"itemLicense": "",
"itemName": "Fedora",
"jointRotations": [
],
"jointRotationsSet": [
],
"jointTranslations": [
],
"jointTranslationsSet": [
],
"lastEdited": 1528306032827319,
"lastEditedBy": "{4c770def-4abb-40c6-91a1-88da5247b2db}",
"lifetime": -1,
"limitedRun": 4294967295,
"localPosition": {
"x": -0.030000008642673492,
"y": 0.12999820709228516,
"z": -0.07000023126602173
},
"localRotation": {
"w": 0.9996573328971863,
"x": 0,
"y": 0,
"z": 0.026176949962973595
},
"locked": false,
"marketplaceID": "11c4208d-15d7-4449-9758-a08da6dbd3dc",
"modelURL": "http://mpassets.highfidelity.com/11c4208d-15d7-4449-9758-a08da6dbd3dc-v1/Fedora.fbx",
"name": "",
"naturalDimensions": {
"x": 0.2765824794769287,
"y": 0.14034485816955566,
"z": 0.320981502532959
},
"naturalPosition": {
"x": 0.000143393874168396,
"y": 1.7460365295410156,
"z": 0.022502630949020386
},
"originalTextures": "{\n \"file5\": \"http://mpassets.highfidelity.com/11c4208d-15d7-4449-9758-a08da6dbd3dc-v1/Fedora.fbx/Texture/Fedora_Hat1_Base_Color.png\",\n \"file7\": \"http://mpassets.highfidelity.com/11c4208d-15d7-4449-9758-a08da6dbd3dc-v1/Fedora.fbx/Texture/Fedora_Hat1_Roughness.png\"\n}\n",
"owningAvatarID": "{4c770def-4abb-40c6-91a1-88da5247b2db}",
"parentID": "{4c770def-4abb-40c6-91a1-88da5247b2db}",
"parentJointIndex": 64,
"position": {
"x": -0.030000008642673492,
"y": 0.12999820709228516,
"z": -0.07000023126602173
},
"queryAACube": {
"scale": 1.6202316284179688,
"x": -0.5601736903190613,
"y": -10.668098449707031,
"z": -0.8933582305908203
},
"registrationPoint": {
"x": 0.5,
"y": 0.5,
"z": 0.5
},
"relayParentJoints": false,
"renderInfo": {
"drawCalls": 1,
"hasTransparent": false,
"texturesCount": 2,
"texturesSize": 327680,
"verticesCount": 719
},
"restitution": 0.5,
"rotation": {
"w": 0.9996573328971863,
"x": 0,
"y": 0,
"z": 0.026176949962973595
},
"script": "",
"scriptTimestamp": 0,
"serverScripts": "",
"shapeType": "box",
"staticCertificateVersion": 0,
"textures": "",
"type": "Model",
"userData": "{\"Attachment\":{\"action\":\"attach\",\"joint\":\"HeadTop_End\",\"attached\":false,\"options\":{\"translation\":{\"x\":0,\"y\":0,\"z\":0},\"scale\":1}},\"grabbableKey\":{\"cloneable\":false,\"grabbable\":true}}",
"velocity": {
"x": 0,
"y": 0,
"z": 0
},
"visible": true
}
},
{
"properties": {
"acceleration": {
"x": 0,
"y": 0,
"z": 0
},
"actionData": "",
"age": 14.011027336120605,
"ageAsText": "0 hours 0 minutes 14 seconds",
"angularDamping": 0.39346998929977417,
"angularVelocity": {
"x": 0,
"y": 0,
"z": 0
},
"animation": {
"allowTranslation": true,
"currentFrame": 0,
"firstFrame": 0,
"fps": 30,
"hold": false,
"lastFrame": 100000,
"loop": true,
"running": false,
"url": ""
},
"boundingBox": {
"brn": {
"x": -0.04381517320871353,
"y": 0.20789726078510284,
"z": -0.0394962802529335
},
"center": {
"x": -1.9073486328125e-06,
"y": 0.2300434112548828,
"z": 1.2159347534179688e-05
},
"dimensions": {
"x": 0.08762653172016144,
"y": 0.04429228603839874,
"z": 0.07901687920093536
},
"tfl": {
"x": 0.043811358511447906,
"y": 0.2521895468235016,
"z": 0.03952059894800186
}
},
"canCastShadow": true,
"certificateID": "",
"clientOnly": true,
"cloneAvatarEntity": false,
"cloneDynamic": false,
"cloneLifetime": 300,
"cloneLimit": 0,
"cloneOriginID": "{00000000-0000-0000-0000-000000000000}",
"cloneable": false,
"collidesWith": "",
"collisionMask": 0,
"collisionSoundURL": "",
"collisionless": false,
"collisionsWillMove": false,
"compoundShapeURL": "",
"created": "2018-06-06T17:25:42Z",
"damping": 0.39346998929977417,
"density": 1000,
"description": "",
"dimensions": {
"x": 0.03022606298327446,
"y": 0.06644226610660553,
"z": 0.07229919731616974
},
"dynamic": false,
"editionNumber": 58,
"entityInstanceNumber": 0,
"friction": 0.5,
"gravity": {
"x": 0,
"y": 0,
"z": 0
},
"href": "",
"id": "{d018c6ea-b2f4-441e-85e1-d17373ae6f34}",
"ignoreForCollisions": false,
"itemArtist": "jyoum",
"itemCategories": "Wearables",
"itemDescription": "A cool scifi watch for your avatar!",
"itemLicense": "",
"itemName": "Scifi Watch",
"jointRotations": [
],
"jointRotationsSet": [
],
"jointTranslations": [
],
"jointTranslationsSet": [
],
"lastEdited": 1528306032505220,
"lastEditedBy": "{b46f9c9e-4cd3-4964-96d6-cf3954abb908}",
"lifetime": -1,
"limitedRun": 4294967295,
"localPosition": {
"x": -1.9073486328125e-06,
"y": 0.2300434112548828,
"z": 1.2159347534179688e-05
},
"localRotation": {
"w": 0.5910987257957458,
"x": -0.48726412653923035,
"y": -0.4088631868362427,
"z": 0.49599069356918335
},
"locked": false,
"marketplaceID": "0685794d-fddb-4bad-a608-6d7789ceda90",
"modelURL": "http://mpassets.highfidelity.com/0685794d-fddb-4bad-a608-6d7789ceda90-v1/ScifiWatch.fbx",
"name": "Scifi Watch by Jimi",
"naturalDimensions": {
"x": 0.023250818252563477,
"y": 0.0511094331741333,
"z": 0.055614765733480453
},
"naturalPosition": {
"x": 0.6493338942527771,
"y": 1.4500460624694824,
"z": -0.06031447649002075
},
"originalTextures": "{\n \"file4\": \"http://mpassets.highfidelity.com/0685794d-fddb-4bad-a608-6d7789ceda90-v1/ScifiWatch.fbx/ScifiWatch/texture/lambert1_Base_Color.png\",\n \"file5\": \"http://mpassets.highfidelity.com/0685794d-fddb-4bad-a608-6d7789ceda90-v1/ScifiWatch.fbx/ScifiWatch/texture/lambert1_Normal_OpenGL.png\",\n \"file6\": \"http://mpassets.highfidelity.com/0685794d-fddb-4bad-a608-6d7789ceda90-v1/ScifiWatch.fbx/ScifiWatch/texture/lambert1_Metallic.png\",\n \"file7\": \"http://mpassets.highfidelity.com/0685794d-fddb-4bad-a608-6d7789ceda90-v1/ScifiWatch.fbx/ScifiWatch/texture/lambert1_Roughness.png\",\n \"file8\": \"http://mpassets.highfidelity.com/0685794d-fddb-4bad-a608-6d7789ceda90-v1/ScifiWatch.fbx/ScifiWatch/texture/lambert1_Emissive.png\"\n}\n",
"owningAvatarID": "{4c770def-4abb-40c6-91a1-88da5247b2db}",
"parentID": "{4c770def-4abb-40c6-91a1-88da5247b2db}",
"parentJointIndex": 16,
"position": {
"x": -1.9073486328125e-06,
"y": 0.2300434112548828,
"z": 1.2159347534179688e-05
},
"queryAACube": {
"scale": 0.3082179129123688,
"x": -0.19203892350196838,
"y": -10.429610252380371,
"z": -0.4076632857322693
},
"registrationPoint": {
"x": 0.5,
"y": 0.5,
"z": 0.5
},
"relayParentJoints": false,
"renderInfo": {
"drawCalls": 1,
"hasTransparent": false,
"texturesCount": 5,
"texturesSize": 786432,
"verticesCount": 273
},
"restitution": 0.5,
"rotation": {
"w": 0.5910987257957458,
"x": -0.48726412653923035,
"y": -0.4088631868362427,
"z": 0.49599069356918335
},
"script": "",
"scriptTimestamp": 0,
"serverScripts": "",
"shapeType": "box",
"staticCertificateVersion": 0,
"textures": "",
"type": "Model",
"userData": "{\"Attachment\":{\"action\":\"attach\",\"joint\":\"[LR]ForeArm\",\"attached\":false,\"options\":{\"translation\":{\"x\":0,\"y\":0,\"z\":0},\"scale\":1}},\"grabbableKey\":{\"cloneable\":false,\"grabbable\":true}}",
"velocity": {
"x": 0,
"y": 0,
"z": 0
},
"visible": true
}
}
],
"avatarScale": 1,
"avatarUrl": "http://mpassets.highfidelity.com/28569047-6f1a-4100-af67-8054ec397cc3-v1/LLMale2.fst",
"version": 3
},
"Last legends Female": {
"attachments": [
],
"avatarEntites": [
],
"avatarScale": 1,
"avatarUrl": "http://mpassets.highfidelity.com/8d823be5-6197-4418-b984-eb94160ed956-v1/LLFemale_Clothes.fst",
"version": 3
},
"Matthew": {
"attachments": [
],
"avatarEntites": [
],
"avatarScale": 1,
"avatarUrl": "http://mpassets.highfidelity.com/b652081b-a199-425e-ae5c-7815721bdc09-v1/matthew.fst",
"version": 3
},
"Priscilla": {
"attachments": [
],
"avatarEntites": [
],
"avatarScale": 1,
"avatarUrl": "http://mpassets.highfidelity.com/e7565f93-8bc5-47c2-b6eb-b3b31d4a1339-v1/priscilla.fst",
"version": 3
},
"Woody": {
"attachments": [
],
"avatarEntites": [
],
"avatarScale": 1,
"avatarUrl": "http://mpassets.highfidelity.com/ad348528-de38-420c-82bb-054cb22163f5-v1/mannequin.fst",
"version": 3
}
}

View file

@ -1,11 +1,10 @@
{
"name": "Keyboard/Mouse to Actions",
"channels": [
{ "from": "Keyboard.A", "when": "Keyboard.RightMouseButton", "to": "Actions.LATERAL_LEFT" },
{ "from": "Keyboard.D", "when": "Keyboard.RightMouseButton", "to": "Actions.LATERAL_RIGHT" },
{ "from": "Keyboard.E", "to": "Actions.LATERAL_RIGHT" },
{ "from": "Keyboard.Q", "to": "Actions.LATERAL_LEFT" },
{ "from": "Keyboard.A", "when": ["Keyboard.RightMouseButton", "!Keyboard.Control"], "to": "Actions.LATERAL_LEFT" },
{ "from": "Keyboard.D", "when": ["Keyboard.RightMouseButton", "!Keyboard.Control"], "to": "Actions.LATERAL_RIGHT" },
{ "from": "Keyboard.E", "when": "!Keyboard.Control", "to": "Actions.LATERAL_RIGHT" },
{ "from": "Keyboard.Q", "when": "!Keyboard.Control", "to": "Actions.LATERAL_LEFT" },
{ "comment" : "Mouse turn need to be small continuous increments",
"from": { "makeAxis" : [
@ -87,21 +86,41 @@
},
{ "from": { "makeAxis" : [
["Keyboard.A", "Keyboard.TouchpadLeft"],
["Keyboard.D", "Keyboard.TouchpadRight"]
["Keyboard.A"],
["Keyboard.D"]
]
},
"when": ["Application.CameraFirstPerson", "!Keyboard.Control"],
"to": "Actions.Yaw"
},
{ "from": { "makeAxis" : [
["Keyboard.A"],
["Keyboard.D"]
]
},
"when": ["Application.CameraThirdPerson", "!Keyboard.Control"],
"to": "Actions.Yaw"
},
{ "from": { "makeAxis" : [
["Keyboard.TouchpadLeft"],
["Keyboard.TouchpadRight"]
]
},
"when": "Application.CameraFirstPerson",
"to": "Actions.Yaw"
},
{ "from": { "makeAxis" : [
["Keyboard.A", "Keyboard.TouchpadLeft"],
["Keyboard.D", "Keyboard.TouchpadRight"]
["Keyboard.TouchpadLeft"],
["Keyboard.TouchpadRight"]
]
},
"when": "Application.CameraThirdPerson",
"to": "Actions.Yaw"
},
{ "from": { "makeAxis" : ["Keyboard.MouseMoveLeft", "Keyboard.MouseMoveRight"] },
"when": "Keyboard.RightMouseButton",
"to": "Actions.Yaw",

Binary file not shown.

View file

@ -35,8 +35,6 @@
<glyph glyph-name="diclosure-expand" unicode="&#66;" d="M239 187c-3 0-6 1-8 3-5 5-5 12 0 17l42 42-43 44c-5 4-5 12 0 17 4 4 12 4 17 0l60-61-60-59c-2-2-5-3-8-3z"/>
<glyph glyph-name="reload-small" unicode="&#97;" d="M334 253c-9 0-18-7-18-16-3-27-25-47-52-47-29 0-52 24-52 52 0 11 2 27 14 38 6 5 14 9 24 12-5-7-4-16 2-22 3-3 8-4 12-4 5 0 9 1 13 5l28 28c1 2 3 4 3 7 3 6 1 13-3 18l-29 29c-3 3-7 5-12 5-5 0-9-2-12-5-4-3-5-8-5-12 0-5 1-9 5-13l0 0c-20-3-37-11-50-23-16-16-25-38-25-63 0-47 39-86 86-86 45 0 82 33 87 78 1 9-6 18-16 19z"/>
<glyph glyph-name="close-small" unicode="&#67;" d="M291 259l43 44c8 7 8 19 0 27-7 7-19 7-26 0l-44-44-44 44c-7 7-19 7-26 0-8-8-8-20 0-27l43-44-43-43c-8-8-8-20 0-27 7-7 19-7 26 0l44 44 44-44c7-7 19-7 26 0 8 8 8 19 0 27z"/>
<glyph glyph-name="backward" unicode="&#69;" d="M292 349c-5 3-12 3-18-1l-94-71c-4-3-7-8-7-13 0-5 2-10 6-14l95-80c3-2 7-4 11-4 2 0 5 1 7 2 6 3 10 9 10 15l0 151c0 6-4 12-10 15"/>
<glyph glyph-name="reload" unicode="&#70;" d="M365 261c-9 1-17-5-18-15-4-45-43-80-89-80-49 0-89 40-89 89 0 19 4 45 25 65 16 15 39 23 68 25l-15-16c-6-6-6-17 0-24 4-3 8-4 12-4 4 0 9 1 12 5l43 44c2 2 3 4 4 6 2 6 1 13-4 18l-44 44c-6 6-17 6-23 0-7-7-7-17 0-24l15-15c-38-2-69-14-91-35-23-21-36-53-36-88 0-68 55-123 123-123 64 0 116 47 122 110 1 9-5 18-15 18"/>
<glyph glyph-name="minimize" unicode="&#73;" d="M154 282l198 0c10 0 18-8 18-18 0-10-8-18-18-18l-198 0c-10 0-18 8-18 18 0 10 8 18 18 18"/>
<glyph glyph-name="maximize" unicode="&#74;" d="M157 244l77 0 0-75c0-9 8-17 17-17 9 0 17 8 17 17l0 75 75 0c10 0 17 8 17 17 0 10-7 18-17 18l-75 0 0 76c0 10-8 17-17 17-9 0-17-7-17-17l0-76-77 0c-10 0-17-8-17-18 0-9 8-17 17-17z"/>
<glyph glyph-name="maximize-inverted" unicode="&#75;" d="M251 434c-96 0-173-78-173-173 0-96 77-173 173-173 95 0 173 77 173 173 0 95-78 173-173 173z m93-190l-77 0 0-76c0-10-7-17-16-17-9 0-16 7-16 17l0 76-77 0c-10 0-17 8-17 17 0 9 7 17 17 17l77 0 0 76c0 9 7 17 16 17 9 0 16-8 16-17l0-76 77 0c9 0 17-8 17-17 0-9-8-17-17-17z"/>
@ -48,7 +46,6 @@
<glyph glyph-name="script-new" unicode="&#81;" d="M298 80l-145 0c-30 0-55 15-72 43-12 20-16 40-16 41l-3 16 267 0 0-12c0-1 1-15 9-29 10-18 26-27 49-27 13 0 22 4 29 12 16 18 16 54 14 66l0 1 0 206-269 0c-7 0-13 6-13 13 0 7 6 13 13 13l295 0 0-230c1-8 5-57-21-86-12-14-28-21-48-21-41 0-62 23-72 41-5 10-8 19-10 28l-210 0c2-7 5-12 8-18 13-20 29-30 50-30l145 0c7 0 13-7 13-14 0-7-6-13-13-13z m95 260l-180 0c-7 0-14 6-14 14 0 8 7 14 14 14l180 0c7 0 14-6 14-14 0-8-7-14-14-14z m0-59l-135 0c-8 0-14 7-14 15 0 7 6 14 14 14l135 0c7 0 14-7 14-14 0-8-7-15-14-15z m0-58l-180 0c-7 0-14 7-14 14 0 8 7 15 14 15l180 0c7 0 14-7 14-15 0-7-7-14-14-14z m-250 90l0 53c0 9-7 16-16 16-9 0-16-7-16-16l0-53-54 0c-9 0-16-8-16-17 0-9 8-17 16-17l54 0 0-53c0-9 7-16 16-16 9 0 16 8 16 17l0 52 54 0c9 0 16 8 16 17 0 9-8 16-17 16z"/>
<glyph glyph-name="hifi-forum" unicode="&#50;" d="M265 410c-83 0-150-68-150-150 0-24 6-47 16-67l-27-79 80 20c23-16 51-25 81-25 83 0 150 68 150 150 0 83-67 151-150 151z m38-248c-9 0-17 7-17 17 0 7 4 14 12 16l0 46-74 33 0-56c7-2 12-8 12-16 0-10-7-18-17-18-10 0-19 8-19 18 0 7 6 13 10 16l0 111c-4 2-10 9-10 16 0 10 9 17 19 17 9 0 17-7 17-17 0-8-5-14-12-16l0-41 74-33 0 51c-8 3-12 9-12 16 0 10 7 18 17 18 10 0 17-8 17-18 0-7-5-14-12-16l0-110c7-3 12-9 12-17 0-10-7-17-17-17z"/>
<glyph glyph-name="hifi-logo-small" unicode="&#83;" d="M374 374c-32 32-74 49-119 49-46 0-88-17-120-49-32-32-49-74-49-119 0-45 17-87 49-118 32-32 74-49 119-49 45 0 88 17 119 49 32 32 49 73 49 118 1 45-17 87-48 119z m-17-221c-28-28-65-43-103-43-39 0-75 15-103 43-27 27-42 64-42 102 0 39 15 75 42 103 28 28 64 43 103 43 38 0 75-15 103-43 27-28 42-64 42-103 0-39-15-76-42-102z m-145 47c-5 0-9 3-9 6l0 126c0 3 4 7 9 7 6 0 10-4 10-7l0-125c0-4-4-7-10-7z m0 118c-5 0-10 2-14 6-7 7-7 20 0 27 5 5 9 6 14 6 6 0 11-2 14-6 4-4 5-8 5-14 0-5-2-10-5-13-4-4-8-6-14-6z m0-144c-5 0-10 2-14 5-4 5-5 9-5 14 0 6 2 11 5 14 5 4 9 5 14 5 6 0 11-2 14-5 4-4 5-8 5-14 0-5-2-10-5-14-4-3-8-5-14-5z m85 2c-6 0-10 3-10 7l0 121c0 4 4 7 10 7 5 0 9-3 9-7l0-121c0-5-4-7-9-7z m0 120c-6 0-11 2-14 5-8 8-8 20 0 28 4 4 8 5 14 5 5 0 10-2 14-5 4-4 5-9 5-14 0-5-2-11-5-14-4-3-9-5-14-5z m0-144c-6 0-11 2-14 5-8 7-8 20 0 28 4 4 8 5 14 5 5 0 10-2 14-5 4-5 5-9 5-14 0-5-2-11-5-14-4-3-9-5-14-5z m1 73l-85 40 1 18 86-40z"/>
<glyph glyph-name="avatar-1" unicode="&#84;" d="M293 71c-1 0-1 0-1 0-14-1-14-1-16 12-6 43-11 86-16 128-1 2-1 4-1 6-3 0-6 0-9 0-2-10-3-20-4-31-4-36-8-72-12-109-1-7-2-8-9-8-2 0-5 0-7 0 0 74 1 181 1 254-1-1-33 0-44 1-15 0-62 1-79 1-8 0-14 3-18 10-1 2-2 4-4 7 8 0 15 0 22 1 35 1 99 8 100 12 14 11 23 10 36 10 15 0 31 0 46-1 11 0 24 3 37-10 20-10 81-10 123-11 0 0 1 0 1 0-4-12-12-17-25-17-29-1-77-3-127-1 2-73 4-181 6-254z m-32 371c16-6 14-20 13-32 0-5-1-10-1-14-2-11-10-18-20-18-11 0-19 8-20 18-1 6-1 13-2 20-1 7 3 13 11 15 10 3 10 3 19 11z"/>
<glyph glyph-name="placemark" unicode="&#85;" d="M134 98c31-32 73-49 119-49l1 0c45 0 86 16 117 47 31 30 48 71 48 114 1 46-16 88-46 120-9 9-20 17-31 24-3-7-6-15-10-22 5-4 11-8 16-13 15-14 28-32 33-46l1-1c0-1 0-2-1-3l-1 0c-12-7-25-10-38-12-2-1-4-1-7-2l-1 0c0 0-1 0-2 1 0 0-1 1-1 1l0 1c-3 15-6 31-12 46l-7-15c4-11 6-21 8-32l0-1c0-1 0-1 0-2-1-1-1-1-2-1l-1 0-55-3-4 0c0 0-1 0-1 0-1 1-1 2-1 2l0 74c-5 9-8 17-11 26 0-1 0-1 0-1l-1 0 0-97c0 0 0-1 0-2 0-1-1-2-2-2l-1 0c0 0-1 0-1 0l-51 3c-1 0-2 0-2 1-1 1-1 2 0 2l0 1c5 27 13 58 35 83 6 6 12 13 20 16 0 0 1 0 1 0-3 7-6 15-9 22-37-4-71-20-99-47-30-30-47-70-48-113-1-46 16-88 47-120z m198 72c0 4 1 7 1 10l0 0c0 7 1 14 1 21 0 9 0 18 0 27 0 3 0 6 0 9l0 1c-1 1-1 6 5 7 11 3 23 5 34 8l1 0c3 1 7 2 11 2l1 1c1 0 3-1 3-2l0-1c0-1 1-1 1-2 1-3 1-5 2-8 3-14 4-27 3-40-2-12-8-21-18-25-8-3-17-5-25-8-3 0-7-1-10-2-1-1-3-1-4-1-1 0-1 0-2 0l-1-1c0 0 0 0 0 0-1 0-2 1-2 1-1 1-1 1-1 2z m2-17c12 4 23 7 35 10l14 4c1 0 2 0 2-1 1 0 1-2 1-2l-1-2c-7-18-17-34-30-47-13-13-28-24-46-31l-2-1c0 0-1 0-1 0-1 0-1 0-2 0 0 1-1 2-1 3l1 1c0 1 0 1 0 1 0 1 0 2 1 3 6 9 15 24 22 55 1 3 2 6 7 7z m-78 83c0 1 1 3 2 3l3 0 41 2 13 1c0 0 1 0 1 0l1 0c0 0 0-1 1-1l1 0c1 0 2-1 2-3 0-1 0-3 0-5 0-2 0-4 0-6l0-5c1-7 1-15 0-22l0-4c0-5 0-11-1-17 0-1 0-3 0-5 0-1 0-3 0-4 0-2-1-7-7-8-10 0-20-1-30-2l-2 0c-3-1-8-1-12-1-5-1-7-1-8-1-1 0-1 0-2 0l-2 1c-1 1-1 2-1 3l0 74z m0-92c0 1 1 3 2 3l3 0 51 3c1 0 2 0 2-1 1 0 1-1 1-2l0-1c0 0 0-1 0-1 0 0 0 0-1-1 0 0 0-1 0-1l0-1c0-1-1-3-1-4-1-2-2-5-3-7l-1-3c-3-9-7-18-11-27-4-8-9-14-14-19-5-6-13-9-23-10l-3 0c-1 0-1 0-2 1 0 0 0 1 0 2l0 69z m-52-59c-1-1-1-2-2-2 0 0-1 1-1 1l-2 1c-27 6-64 40-78 79l-1 1c0 1 0 2 1 3 1 1 2 1 3 1l13-4c12-4 24-7 36-11 3-1 6-2 7-7 5-24 12-42 23-57l1-2c1-1 1-3 0-3z m40-10c0-1-1-1-1-2-1 0-2 0-2 0 0 0-1 0-1 0-1 0-14 4-20 11-15 19-23 41-29 61 0 0 0 0 0 1l0 1c0 1 0 1 1 2 0 1 1 1 2 1l1 0 29-2 17-1c2-1 3-2 3-3l0-69z m-21 165l18-2c2 0 3-1 3-2l0-75c0-1-1-2-1-2-1-1-2-1-2-1 0 0 0 0-1 0 0 0-14 2-21 2-8 1-17 2-26 3-4 0-6 4-6 7-2 18-3 35-3 47 0 5-1 22-1 22 0 1 1 2 1 2 1 1 1 1 2 1z m-98 32l1 1c12 31 42 59 76 71l3 1c1 0 2 0 3-1 0-1 0-2 0-3l-2-3c-18-25-25-53-31-79l0-1c0-1 0-2-1-2 0 0-1-1-1-1-1 0-1 0-1 0l-1 1c-5 1-11 3-17 4-8 2-18 4-27 8l0 1c-2 0-2 2-2 3z m-8-18l1 1c0 1 1 2 3 2l49-13c1 0 2-1 2-3l2-71c0-1 0-2-1-2-1-1-1-1-2-1 0 0 0 0 0 0l-1 0c-1 0-2 1-3 1l0 0c-2 0-4 1-7 1-16 4-29 9-39 17-6 4-9 8-9 15-1 19 1 37 5 53z m178 42c-8 16-14 31-21 46-8 17-17 35-24 52-14 31 3 65 36 71 28 5 56-16 59-44 0-9-1-18-5-26-14-32-29-64-44-97 0 0-1-1-1-2z m27 117c0 15-12 28-27 28-15 0-27-12-28-27 0-16 13-28 28-28 15 0 27 12 27 27z"/>
<glyph glyph-name="box" unicode="&#86;" d="M318 74l126 89 15-22-126-88z m-137 101l0-99 27 0 0 96z m145-125c-1 0-1 0-2 0l-262 26c-7 1-12 7-12 13l0 263c0 4 1 7 4 10 3 2 7 4 10 3l263-26c7 0 12-6 12-13l0-262c0-4-2-8-4-10-3-3-6-4-9-4z m-250 51l236-23 0 236-236 23z m377 326l-263 26c-3 1-7-1-10-3-3-3-4-6-4-10l0-21c3 2 7 3 11 3 0 0 0 0 1 0 3 2 7 4 11 4 2 0 3 0 5-1l234-23 0-236c0-7-3-10-10-14 1-2 1-5 1-7 1-2 0-3 0-5l21-2c1 0 1 0 2 0 3 0 6 1 8 4 3 2 5 6 5 10l0 262c0 7-5 13-12 13z m-397-64l125 88 16-22-126-88z m262-26l126 88 15-22-126-88z m-256-123l2 27 263-26-3-26z m146 37l0 91-27 0 0-88c9-1 18-2 27-3z"/>
<glyph glyph-name="community" unicode="&#48;" d="M50 175c-4 0-8 2-11 6-4 6-2 14 4 18l24 16 69 48 89-64c6-4 7-13 3-19-5-6-13-7-19-3l-74 53-53-37-24-16c-3-1-5-2-8-2z m130-10l-44 32-47-32-22-14 0-63 135 0 0 60z m120 10c-4 0-9 2-11 6-4 6-3 14 3 18l25 16 68 48 89-64c6-4 7-13 3-19-4-6-13-7-19-3l-73 53-54-37-24-16c-2-1-5-2-7-2z m129-10l-46 32-45-32-22-14 0-63 135 0 0 60z m-256 202c-4 0-9 2-11 5-4 7-3 15 4 19l24 16 68 48 89-65c6-4 7-12 3-18-4-6-12-7-18-3l-74 53-53-37-25-16c-2-2-5-2-7-2z m129-11l-46 32-45-31-22-15 0-62 135 0 0 60z"/>
@ -103,7 +100,6 @@
<glyph glyph-name="lock" unicode="&#57350;" d="M389 233l0 62c0 68-55 124-123 124-69 0-124-56-124-124l0-62c-24-4-44-26-44-52l0-74c0-29 24-52 52-52l230 0c29 0 53 23 53 52l0 74c0 26-18 48-44 52z m-123 129c37 0 67-30 67-67l0-61-135 0 0 61c0 37 31 67 68 67z"/>
<glyph glyph-name="visible" unicode="&#57351;" d="M258 116c-55 0-106 17-147 51-31 25-47 51-47 52-4 7-4 16 1 23 2 4 66 98 195 96 133-3 192-93 195-97 4-6 4-15 0-22 0-1-15-27-46-53-29-23-79-50-151-50 0 0 0 0 0 0z m-148 113c7-7 17-18 30-29 34-27 73-40 118-40 0 0 0 0 0 0 47 0 88 13 122 40 13 10 23 21 29 29-7 7-16 16-30 26-34 25-74 38-119 38-81 2-130-42-150-64z m-27 1z m227-4c0-25-21-46-47-46-26 0-47 21-47 46 0 26 21 47 47 47 26 0 47-21 47-47z"/>
<glyph glyph-name="model" unicode="&#57352;" d="M494 395c-2 5-8 8-13 7l-90-16 45 72c3 5 2 11-1 15-4 4-10 5-15 3l-213-98c-15 5-72 27-111 43 0 0-1 0-1 0 0 0 0 0 0 0 0 0-1 0-1 1 0 0-1 0-1 0 0 0-1 0-1 0 0 0 0 0 0 0-1 0-1 0-2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0-1 0-1 0 0 0 0 0 0-1-1 0-1 0-2 0 0 0 0 0 0 0 0 0-1 0-1 0 0 0 0-1 0-1-1 0-2 0-3-1 0 0 0 0 0 0 0-1-1-1-1-1 0 0 0 0 0 0 0 0 0-1 0-1-1 0-1 0-1 0 0 0 0 0 0-1 0 0 0 0-1-1l-27-52-33-40c-3-4-3-10 0-15 2-3 6-5 10-5 1 0 2 0 4 1l50 17 40 2-26-51c-3-4-2-9 1-13 1-1 26-30 52-58 15-17 28-30 38-40 6-6 11-11 15-14l-16-61-46-18c-6-3-9-10-6-16 2-5 6-8 11-8 1 0 3 1 4 1l45 18 17-15c2-3 5-4 8-4 4 0 7 2 9 5 5 5 4 12-1 17l-17 15 16 61 76-90c2-2 6-4 9-4 1 0 2 0 3 0l85 23c5 2 8 6 9 11 0 5-2 9-7 12l-136 72 45 91 178 123c5 3 6 9 4 15z m-200-117l-122 55 41 21 181 83z m-148 73l-24 33c16-6 39-15 54-21z m-59-6l-9 13 15 29 27-38 2-2z m36-77l23 44c18-45 35-91 47-121-19 20-45 49-70 77z m194-194l-57 68 105-55z m-94 101c-5 14-42 104-30 77 0-2-21 49-28 66l121-59-48-95z m108 120l43 63 70 16z"/>
<glyph glyph-name="forward" unicode="&#68;" d="M330 278l-95 70c-5 4-12 5-18 2-5-3-9-9-9-16l0-150c0-7 4-13 10-16 2-1 5-2 7-2 4 0 8 2 11 5l95 79c4 4 6 9 6 14-1 5-3 10-7 14"/>
<glyph glyph-name="avatar-2" unicode="&#57353;" d="M256 88c-93 0-169 75-169 168 0 93 76 169 169 169 93 0 169-76 169-169 0-93-76-168-169-168z m0 316c-81 0-148-66-148-148 0-81 67-147 148-147 81 0 148 66 148 147 0 82-67 148-148 148z m97-90l-1 1c-3 3-7 4-10 4-1 0-61-9-86-9-1 0-1 0-2 0-25 0-87 10-87 10-5 0-10-2-13-6l-1-2c-2-3-2-7-1-10 1-4 3-6 6-8 12-5 49-20 60-22 2 0 5 0 6-7 1-8-3-46-7-65-5-17-13-40-13-41-2-6 1-13 7-15l8-3c3-1 6-1 9 1 3 1 5 4 6 7l21 65 20-67c1-3 3-6 6-7 2-1 4-1 5-1 2 0 3 0 5 0l7 3c5 2 8 8 7 14 0 0-6 24-11 44-3 12-4 30-5 45 0 9-1 16-2 22 0 1 0 4 5 5 0 0 1 0 2 0l55 22c4 2 6 5 7 9 1 4 0 8-3 11z m-68 37c0-16-13-29-29-29-16 0-29 13-29 29 0 16 13 29 29 29 16 0 29-13 29-29z"/>
<glyph glyph-name="arrow-dn" unicode="&#53;" d="M258 219l-43 55 86 0z"/>
<glyph glyph-name="arrow-up" unicode="&#54;" d="M258 283l43-55-86 0z"/>
@ -154,4 +150,8 @@
<glyph glyph-name="uninstall" unicode="&#57395;" d="M83 227c-7 0-13-6-13-13l0-78c0-19 16-35 35-35l297 0c19 0 35 16 35 35l0 78c0 7-6 13-13 13-7 0-13-6-13-13l0-78c0-5-4-9-9-9l-297 0c-5 0-9 4-9 9l0 78c0 7-6 13-13 13z m191 47l50 50c5 5 5 14 0 19-5 5-13 5-19 0l-50-50-50 50c-5 5-13 5-19 0-5-5-5-14 0-19l50-50-50-50c-5-5-5-14 0-19 5-5 14-5 19 0l50 50 50-50c5-5 14-5 19 0 5 5 5 14 0 19z"/>
<glyph glyph-name="install" unicode="&#57391;" d="M83 227c-7 0-13-6-13-13l0-78c0-19 16-35 35-35l297 0c19 0 35 16 35 35l0 78c0 7-6 13-13 13-7 0-13-6-13-13l0-78c0-5-4-9-9-9l-297 0c-5 0-9 4-9 9l0 78c0 7-6 13-13 13z m170 171l0-155-33 27c-6 5-14 5-19-1-4-5-4-14 2-18l54-48c3-2 5-3 8-3 3 0 7 1 9 3l54 48c5 4 6 13 1 18-4 5-13 6-18 1l-32-27 0 154c0 8-6 13-13 13-7 0-13-5-13-12z"/>
<glyph glyph-name="ellipsis-vertical" unicode="&#57396;" d="M276 178c0-14-11-24-24-24-14 0-25 10-25 24 0 13 11 24 25 24 13 0 24-11 24-24z m0 78c0-14-11-24-24-24-14 0-25 10-25 24 0 13 11 24 25 24 13 0 24-11 24-24z m0 78c0-14-11-24-24-24-14 0-25 10-25 24 0 13 11 24 25 24 13 0 24-11 24-24z"/>
<glyph glyph-name="backward" unicode="&#69;" d="M292 349c-5 3-12 3-18-1l-94-71c-4-3-7-8-7-13 0-5 2-10 6-14l95-80c3-2 7-4 11-4 2 0 5 1 7 2 6 3 10 9 10 15l0 151c0 6-4 12-10 15"/>
<glyph glyph-name="40-reload" unicode="&#70;" d="M365 261c-9 1-17-5-18-15-4-45-43-80-89-80-49 0-89 40-89 89 0 19 4 45 25 65 16 15 39 23 68 25l-15-16c-6-6-6-17 0-24 4-3 8-4 12-4 4 0 9 1 12 5l43 44c2 2 3 4 4 6 2 6 1 13-4 18l-44 44c-6 6-17 6-23 0-7-7-7-17 0-24l15-15c-38-2-69-14-91-35-23-21-36-53-36-88 0-68 55-123 123-123 64 0 116 47 122 110 1 9-5 18-15 18"/>
<glyph glyph-name="forward" unicode="&#68;" d="M330 278l-95 70c-5 4-12 5-18 2-5-3-9-9-9-16l0-150c0-7 4-13 10-16 2-1 5-2 7-2 4 0 8 2 11 5l95 79c4 4 6 9 6 14-1 5-3 10-7 14"/>
<glyph glyph-name="avatar-1" unicode="&#84;" d="M396 344l-2 2c-4 4-9 5-15 5-1 0-88-13-124-14-1 0-2 0-3 0-37 0-126 15-127 15-7 1-14-2-18-8l-2-4c-3-4-3-9-2-14 2-5 5-9 10-11 16-7 69-22 85-29 3-1 10-4 10-14 1-11-4-67-10-93-7-26-18-60-19-60-3-9 2-19 11-22l11-4c4-2 9-1 13 1 5 2 8 6 9 10l31 94 28-96c2-5 5-9 9-11 3-1 5-2 8-2 2 0 4 0 7 1l10 4c8 3 12 12 10 20 0 1-8 36-16 65-4 17-6 43-7 64-1 13-1 21-3 30 0 1 2 11 10 14 10 4 81 29 80 28 6 2 10 7 11 13 1 6-1 12-5 16z m-98 54c0-24-19-43-43-43-24 0-43 19-43 43 0 23 19 42 43 42 24 0 43-19 43-42z"/>
</font></defs></svg>

Before

Width:  |  Height:  |  Size: 83 KiB

After

Width:  |  Height:  |  Size: 83 KiB

View file

@ -127,14 +127,6 @@
<div class="icon icon-close-small"></div>
<input type="text" readonly="readonly" value="close-small">
</li>
<li>
<div class="icon icon-backward"></div>
<input type="text" readonly="readonly" value="backward">
</li>
<li>
<div class="icon icon-reload"></div>
<input type="text" readonly="readonly" value="reload">
</li>
<li>
<div class="icon icon-minimize"></div>
<input type="text" readonly="readonly" value="minimize">
@ -179,10 +171,6 @@
<div class="icon icon-hifi-logo-small"></div>
<input type="text" readonly="readonly" value="hifi-logo-small">
</li>
<li>
<div class="icon icon-avatar-1"></div>
<input type="text" readonly="readonly" value="avatar-1">
</li>
<li>
<div class="icon icon-placemark"></div>
<input type="text" readonly="readonly" value="placemark">
@ -399,10 +387,6 @@
<div class="icon icon-model"></div>
<input type="text" readonly="readonly" value="model">
</li>
<li>
<div class="icon icon-forward"></div>
<input type="text" readonly="readonly" value="forward">
</li>
<li>
<div class="icon icon-avatar-2"></div>
<input type="text" readonly="readonly" value="avatar-2">
@ -603,6 +587,22 @@
<div class="icon icon-ellipsis-vertical"></div>
<input type="text" readonly="readonly" value="ellipsis-vertical">
</li>
<li>
<div class="icon icon-backward"></div>
<input type="text" readonly="readonly" value="backward">
</li>
<li>
<div class="icon icon-40-reload"></div>
<input type="text" readonly="readonly" value="40-reload">
</li>
<li>
<div class="icon icon-forward"></div>
<input type="text" readonly="readonly" value="forward">
</li>
<li>
<div class="icon icon-avatar-1"></div>
<input type="text" readonly="readonly" value="avatar-1">
</li>
</ul>
<h2>Character mapping</h2>
<ul class="glyphs character-mapping">
@ -718,14 +718,6 @@
<div data-icon="C" class="icon"></div>
<input type="text" readonly="readonly" value="C">
</li>
<li>
<div data-icon="E" class="icon"></div>
<input type="text" readonly="readonly" value="E">
</li>
<li>
<div data-icon="F" class="icon"></div>
<input type="text" readonly="readonly" value="F">
</li>
<li>
<div data-icon="I" class="icon"></div>
<input type="text" readonly="readonly" value="I">
@ -770,10 +762,6 @@
<div data-icon="S" class="icon"></div>
<input type="text" readonly="readonly" value="S">
</li>
<li>
<div data-icon="T" class="icon"></div>
<input type="text" readonly="readonly" value="T">
</li>
<li>
<div data-icon="U" class="icon"></div>
<input type="text" readonly="readonly" value="U">
@ -990,10 +978,6 @@
<div data-icon="&#xe008;" class="icon"></div>
<input type="text" readonly="readonly" value="&amp;#xe008;">
</li>
<li>
<div data-icon="D" class="icon"></div>
<input type="text" readonly="readonly" value="D">
</li>
<li>
<div data-icon="&#xe009;" class="icon"></div>
<input type="text" readonly="readonly" value="&amp;#xe009;">
@ -1194,6 +1178,22 @@
<div data-icon="&#xe034;" class="icon"></div>
<input type="text" readonly="readonly" value="&amp;#xe034;">
</li>
<li>
<div data-icon="E" class="icon"></div>
<input type="text" readonly="readonly" value="E">
</li>
<li>
<div data-icon="F" class="icon"></div>
<input type="text" readonly="readonly" value="F">
</li>
<li>
<div data-icon="D" class="icon"></div>
<input type="text" readonly="readonly" value="D">
</li>
<li>
<div data-icon="T" class="icon"></div>
<input type="text" readonly="readonly" value="T">
</li>
</ul>
</div>
<script>(function() {

View file

@ -122,12 +122,6 @@
.icon-close-small:before {
content: "\43";
}
.icon-backward:before {
content: "\45";
}
.icon-reload:before {
content: "\46";
}
.icon-minimize:before {
content: "\49";
}
@ -161,9 +155,6 @@
.icon-hifi-logo-small:before {
content: "\53";
}
.icon-avatar-1:before {
content: "\54";
}
.icon-placemark:before {
content: "\55";
}
@ -326,9 +317,6 @@
.icon-model:before {
content: "\e008";
}
.icon-forward:before {
content: "\44";
}
.icon-avatar-2:before {
content: "\e009";
}
@ -479,3 +467,15 @@
.icon-ellipsis-vertical:before {
content: "\e034";
}
.icon-backward:before {
content: "\45";
}
.icon-40-reload:before {
content: "\46";
}
.icon-forward:before {
content: "\44";
}
.icon-avatar-1:before {
content: "\54";
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 298 KiB

After

Width:  |  Height:  |  Size: 91 KiB

Some files were not shown because too many files have changed in this diff Show more